📜 ⬆️ ⬇️

Manage generator or fight against ADC in STM32F030

I somehow did not develop historically with the STM32F030 family, 5 years ago I tried to work with them and for a long time was surprised at the clumsiness of the work of most of the periphery, and then scored on them. And the other day I still had to return to this series, it was necessary to measure for minimal money the constant voltage on the lead battery (or assembly up to 4 pieces in series) from 8 to 60V with an accuracy of no less than ± 0.1 V with a small polling frequency.

Solving the problem "in the forehead" allowed me to accurately measure the voltage only when the input value of the ADC is greater than 1.5 ... 1.6 V, that is, only in the second half of the range, which meant 30 ... 60 V instead of the required 8 for me .. .60B. The main problem was in the range of 0 ... 1.6 V, it looked as if my voltage divider was “floating” or the reference voltage for the ADC (V ref ) was extremely unstable.

It was necessary to quickly solve the problem, albeit not in the most elegant way, but at least without obvious crutches. To do this, it was necessary to first study the problem and understand where the "legs grow", and then eliminate this problem. If it does not work out, then at least somehow get around it in order to finally get a working device and send it to the customer.
')


The essence of the task


Generally, I’m not trying to get involved in such a small thing for a long time, but then a relative came to me, and a good person who also works in a subject close to me — collects some SES somewhere in the suburbs. I didn’t want to refuse, and at that moment this task seemed to me “a couple of hours of iron + a couple of hours of code”. The project in Altium Designer really took me a couple of hours, but the fight against the ADC ate the whole evening, so I decided to share the information so that others would not waste time.

The device itself is extremely simple, the algorithm works as follows:


Everything! Example: there is one battery for 12V and it is powered by an inverter. If the voltage falls below the "lower threshold", the default is 10.2V, then turn on the generator. If the voltage on the battery has grown to "the lower threshold + hysteresis", then turn off. By default, the hysteresis is set to 2V and is needed so that the gasoline generator is not cut down as soon as the battery slightly charges to 10.3V. From constant on / off, the generator will simply die. Well, just in case protection: if the voltage on the battery is higher than 14.4V, then the generator does not exactly turn on.

The algorithm is simple and clear, in addition it was necessary to make a small menu so that you can change three variables: “lower threshold”, “hysteresis”, “upper threshold”. Nothing complicated, but the devil is in the details.

Initially, the company where the relative works, used a Chinese device with similar functionality. Of the minor drawbacks - it was impossible to change the hysteresis, for powering needed an additional source of 5V and measurement of up to 30V, that is, for 1 or 2 batteries. Of the big drawbacks - the Chinese device sometimes hung up and rebooted at the time of starting the gasoline generator, which was controlled. The last "feature" just became the reason for trying to abandon the Chinese solution.

From me they wanted to eliminate all these disadvantages and that the price of the device was like that of the Chinese, that is, $ 10. “Devil's trifle” in this case was that they wanted to buy from me a ready-made device for $ 10 in batches of only 20-30 pieces, although it is stable and quite often. That is, I had to make the device much better in a small series and much cheaper than the Chinese, I also need to make money in the future. Yeah, I, too, was funny in the first 10 minutes, but by the time I realized this situation, I already said “YES”, that is, beyond the Volga, there was no land for me ...

Iron problem solving


As I wrote above, the main problem is the unstable operation of the device during generator start-up. As a result, a Chinese device with an aliexpress was purchased for testing and research. The main reason for the demolition of the head was not in the generator, but in the relay :)) At the time of switching over the power supply, a 3.3V bus passed a pulse with an amplitude of about 25V, which seemed to hint ... Also, interference went to the signal circuits. In the Chinese scheme to deal with such a problem were diodes LL4148, which type blocked the way to interference. It turned out to be enough for the device to work normally on the table, but not in the conditions of a heap of external additional noise such as a generator and other equipment. In order to permanently get rid of the above, I decided to apply galvanic isolation through the “optocoupler + dc / dc” connection, which made it possible to completely eliminate the electrical contact and the path of interference between the control winding of the relay and the rest of the circuit.



An alternative to this solution was the use of protective TVS diodes together with the common-mode choke, as well as the complication of the filter on the power supply. But why such a collective farm? Putting dc / dc is easier, but in practice it turned out to be even cheaper - the Chinese Mornsun B0505S-1WR2 module cost me $ 0.4, while the cost of one common-mode choke for a small batch is about $ 0.32.

As a result, after such a solution and prototype testing, the device began to work as a Kalashnikov assault rifle and the problems with the restart were gone. In general, I am a little surprised that the relay + sensitive generator still forced stm to reboot, Chinese developers basically did everything well: 10 kOhm + 0.1 ÎĽF to reset blocking capacitors for power, ferrite beads, everything was there, but it still turned out few.

The second minus of the “Chinese” was the need for additional power, apparently saving on dc / dc. I solved the problem in the forehead - I took power from the input signal, right from one connector. To do this, you just had to put dc / dc, which digests at least 4 * 14.4V, that is 57.6V. My choice fell on the LMR16010PDDAR. First, it is Texas and that says it all. Secondly, the Asian comrades offered me this chip very cheaply.

The previous item comprehensively decided the third minus - the ability to connect up to 4 batteries in series. DC / DC easily digests 60V, begins to try to burn only at 72 ... 73V, so the maximum 57.6V is definitely not scary for it. The voltage divider doesn’t care how much the input is, so everything was decided with minimal effort.

You can see how all this is implemented in the diagram here - PDF . The scheme is quite large, so the picture did not fill. By the way, in pdf-ke you can also see the dimensions with the printed circuit board, but there is nothing supernatural.

As a result, components for 10 devices were ordered for the first test batch, and after assembly it turned out like this:



It was not without incident - when I created a component for the dc / dc module I confused 1 and 2 legs in some places, I had to tinker a bit. Although on subsequent boards I did it more carefully, so that no one noticed, and the board in the photo remained in my quality of debugging, just in case or for software modifications, if the customer comes up with something during testing.

Fight with ADC accuracy


We now turn to the main part of the article. As I wrote at the beginning of the article - the F030 ADC was inaccurate, that is, up to a voltage of 30 ... 32V at the device input, the readings floated with a deviation of up to 15 ... 20%, and then the error smoothly disappeared. One thing pleased me - at first glance, the deviations had some sort of regularity, which means it was not a random error and can be traced and tried to be corrected.

Let's get a little more detail about the error ... after the conversion is complete, the ADC sends the raw data to the DR register, which contains a value from 0 to 4095 (2 12 ). To recalculate this value in the voltage you need to multiply it by the quantization step. In my case, the voltage at the VDDA pin, from which the ADC takes support, was 3.3072V and, accordingly, the step is 3.3072V / 4096 = 0.000807V, I rounded it to 0.0008. To get the voltage at the input of the device, the resulting voltage must be multiplied by the voltage divider coefficient, in my case the resistor in the upper arm is 100 kΩ and in the lower arm is 4.7 kΩ, which is given by the divider 22.2765. Based on this, the voltage at the input of the device, that is, the voltage of the battery, is found using the formula:

float voltageReference = 0.0008; float voltageDivider = 22.2765; adcVoltageResult = (float)adcData * voltageReference * voltageDivider; 

It turns out that after reading the data ADC1-> DR , they are reduced to the type float and simply multiplied by the coefficients, which are constants, and we get the result in the usual volts. In practice, it turned out that everything is very bad with accuracy.

Recalling Hanlon's razor, I began to look for a place where I made a mistake. At first, I checked the voltage on the VDDA leg, I thought that it somehow floated and depends on the input voltage, for example, the LDO is faulty. Armed with a benchtop multimeter, I monitored the voltage on the VDDA and changed the input voltage from 8 to 60V, while the voltage on the leg of the VDDA was dead at 3.3072V, only the next 2 characters floated, which is very good for a linear operator for 10 cents.

The next place of potential error was the voltage divider. Although it seemed to me strange that the resistors from Bourns by ± 0.1% float so that the data has an error of up to 20% and this error is non-linear. Carried out the same experiment: a multimeter measured the voltage after the divider, and the input voltage changed in steps of 0.5V and as a result, the divider coefficient was also tightly fixed at 22.2768.

At this point, the beginning to become interesting. There remained one component in which I could doubt - this is an operational amplifier LMV611MFX. This OU is included as a voltage follower. The voltage BEFORE and AFTER it was the same up to 4 decimal places. Strange ... According to the datasheet, it is not bad and it is all the same TI, he doubted, but decided to check, because This particular OS has never been used. Just in case, my favorite and tested in a heap of projects OPA320, which I have in coils, soldered in its place and it showed the same result.

There remained the last component - MK, namely its ADC. Over the years, the use of STM, I used to trust their products, the more I take only the originals, so I thought the last thing at MK. The first thing I thought I forgot to do the calibration or did wrong. Got into the reference manual, they demanded not only cutting the ADC by writing zero to the ADEN bit, but also setting 1 to the ADDIS bit and 0 to the DMAEN bit. The last 2 steps were not taken, I usually cut down the ADC and everything works well, eventually corrected a piece of code with calibration:

  /* disable ADC */ if (ADC1->CR & ADC_CR_ADEN) { ADC1->CR |= ADC_CR_ADDIS; while (ADC1->CR & ADC_CR_ADEN) {} } /* calibrate ADC */ ADC1->CR |= ADC_CR_ADCAL; while(ADC1->CR & ADC_CR_ADCAL) {} /* reset configuration */ ADC1->CFGR2 = 0; /* enable device */ ADC1->CR = ADC_CR_ADEN; while(!(ADC1->ISR & ADC_ISR_ADRDY)); 

Unfortunately it did not help and decided to conduct the following experiment ... The coefficients have already been checked and they are 100% correct, so I will apply voltage from the laboratory power supply to the input, change it and output the raw ADC measurement results to the seven-segment indicator, and then compare it with what should there to be with what really measured. As a result, I obtained the following results:



As you can see the theoretical graph has excellent linearity, since not tied to the gland. The graph based on real data is also almost linear with minimal deviations. In fact, a graph with real data can be combined with a theoretical graph by parallel transfer to a certain constant. If you speak the language of electronics - the ADC has an offset!

According to the data on the basis of which the graphs were built, I found out that the ADC has an offset at different points of 71 ... 73 steps. This was the problem, and the “nonlinearity” seemed to me because the shift to 71 steps at 10V is about 14%, and at 30V it is already 4%. That is, if we plot the deviations in%, the dependence will have an exponential form, but such a graph is not interesting.

It was decided that in order to refine the results, try to enter into the formula another variable that will shift my values ​​upwards and have the following form:

 uint16_t offsetVoltage = 72; float voltageReference = 0.0008; float voltageDivider = 22.2765; adcVoltageResult = ((float)(adcData+offsetVoltage))*voltageReference*voltageDivider; 

After these simple manipulations, my device began to accurately measure the voltage and the data stopped floating. Until that moment, it was lying at 72 * 0.0008V * 22.2768 = 1.28V , which in the case of monitoring one battery is very critical. Of course, a lead battery does not explode like Li-ion, but it still quickly fails, especially if it is not constantly discharged to 10.2V, but to 8.92V.

Here is such a small story about a small piece of iron. I hope someone this material will be useful, or at least it will be just interesting to read. Be careful with all these ADCs and other filth :))

UPD. olartamonov very diligently asked not to fool the people and use the calibration code from the reference manual - he made the change with pleasure. Unfortunately, in my case this did not change the situation and the displacement did not disappear anywhere. Probably a problem in the chip itself. on instructions from the State Department threw counterfeit products

Competition


PCBway comrades have a competition among technical projects , anyone can take part. The rules are simple. Printed circuit boards for your project will do for free. And the most important prizes! These are a few green notes with American gentlemen on your paypal + virtual currency to which you can order printed circuit boards + honor and respect + the opportunity to get a job offer somewhere outside the CIS :)) I especially recommend students to participate, the technical level is not too high Although there are very strong projects from the experience of past competitions, so a “strong” DIY-box can easily get into winners!

Source: https://habr.com/ru/post/448202/


All Articles