Sonntag, 31. Mai 2015

STM32 ADC - some weird behaviours

For the Voltage-Ampere-Meter based upon my tiny STM32F030P4 boards I needed to measure different sources - two external sources and the supply voltage. Now from the datasheet, the samples on the net and in the Standard Peripheral Lib, all you need to do is to configure the channels you want to measure and that's it. But as soon as I wanted to measure more than one source, I got weird results. Research on the net gave no good hints where to look for the error.


The 12 bit ADC from ST knows some different ways to work: single shot measurement or continous mode, one channel or more channels. As soon as more than one channel is configured, it seems the ADC goes into the scanning mode where it measures each channel by subsequent ADC-Start commands. So if you want to measure your supply voltage in the beginning and later on something on Pin A0, every second call for an ADC conversion will measure Vcc instead of Pin A0. At least that would explain the results delivered in my tests.

To do it right, you need to DeInit the ADC after the measurement and for a new measurement completely re-initialize it. This leads to reliable and reasonable results. So here are some code snippets to show how I solved that for me.

 int read_vbat(void) {  
      uint32_t temp = 0;  
      adc_init(ADC_Channel_0, ADC_SampleTime_28_5Cycles);  
      // throw away first result like on AVR? first value seems wrong.  
      ADC_StartOfConversion(ADC1);  
      while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);  
      for (uint8_t i = 0; i<8; i++) { // resampling  
           ADC_StartOfConversion(ADC1);  
           while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);  
           temp += ADC_GetConversionValue(ADC1);  
      }  
      ADC_Cmd(ADC1, DISABLE);  
      return ( (temp>>3) );  
 }  
 int read_shunt(void) {  
      uint32_t temp = 0;  
      adc_init(ADC_Channel_1, ADC_SampleTime_28_5Cycles);  
      // throw away first result like on AVR? first value seems wrong.  
      ADC_StartOfConversion(ADC1);  
      while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);  
      for (uint8_t i = 0; i<8; i++) { // resampling  
           ADC_StartOfConversion(ADC1);  
           while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);  
           temp += ADC_GetConversionValue(ADC1);  
      }  
      ADC_Cmd(ADC1, DISABLE);  
      return ( (temp>>3) );  
 }  
 void read_Vdda(void) {  
      // Get Vdda  
      adc_init(ADC_Channel_17, ADC_SampleTime_28_5Cycles);  
      ADC_VrefintCmd(ENABLE);  
      ADC_StartOfConversion(ADC1);  
      while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);  
      int temp=0;  
      for (uint8_t i = 0; i<8; i++) { // resampling  
           ADC_StartOfConversion(ADC1);  
           while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);  
           temp += ADC_GetConversionValue(ADC1);  
      }  
      Vdda=(temp>>3)*3300/(VREFINT_CAL); // VREFINT_CAL/VRefInt=3300/Vdda -> Vdda=3300*Vref/VREFINT_CAL  
      ADC_VrefintCmd(DISABLE);  
      ADC_Cmd(ADC1, DISABLE);  
 }  
 void adc_init(int channel, int sample_time) {  
      ADC_InitTypeDef ADC_InitStructure;  
      ADC_DeInit(ADC1); // clean up  
      ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;  
      ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; // on demand  
      ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_TRGO;  
      ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;  
      ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; // 12 bit right aligned  
      ADC_InitStructure.ADC_ScanDirection = ADC_ScanDirection_Upward;  
      ADC_Init(ADC1, &ADC_InitStructure);  
      // ADC calibration; but not used as returned value ends nowhere now...  
      ADC_GetCalibrationFactor(ADC1);  
      ADC_ChannelConfig(ADC1, channel, sample_time);  
      ADC_Cmd(ADC1, ENABLE);  
      ADC_DiscModeCmd(ADC1, ENABLE);  
 }  

It seems necessary to split every channel reading into separate functions. Another solution would be to always read through all configured channels and update their values. For oversampling, that would mean quite some overhead if you don't need all those channels at that time.

Other observations: Although the STM32 ADCs have an internal voltage reference and even store their values measured at the factory at 30°C and 3.3V - you can only use that for calibrating. You can measure the actual VRefInt value and calculate your supply voltage based upon that. Which is in case of STM32F030P4 always your ADC reference voltage; this TSSOP20 µC lacks a Aref Pin. The address is different for different STM32 µC families - for STM32F030P4, you can read the factory calibration data like this:

   const uint16_t *p = (uint16_t *)0x1FFFF7BA; // 2 Byte at this address is VRefInt @3.3V/30°C  
   VREFINT_CAL = *p; // read the value at pointer address  

Before converting a channel with my desired signals I always call the function to read Vdda as well as the supply voltage may be unstable. This way, the results will get even more stable. Finally I can use the STM32 ADC - before finding out these weird behaviours it delivered mostly garbage. Now it's nearly a 12bit presision instrument ;)

TP4056 Charger plotted with STM32 ADC.

This is how a proper measurement cycle looks like in the end. Way better than with AVR / Arduino 10 bit ADC. 

Samstag, 30. Mai 2015

Beware of fake/cloned TP4056 LiIon charger ICs

When playing around with my DIY Volt-Ampere-meter for inspecting chargers I stumbled upon a serious issue with my clone/fake TP4056 LiIon charging ICs.

Fake TP4056 IC.

While in a first test without measurement equipment attached a battery came out with 4.175V, upon closer observation with a shunt-based current meter the voltage climbed up to over 4.4V. I remembered that in my first fast test I used a protected battery which obviously cut off the cell before overcharging it.

So I decided to plot the graph of the charging curve of this IC. Upon plugging in the charger the voltage immediately jumps up to over 4.4V. This is not yet the real voltage which I can measure directly on the battery, but still is weird.

At the end I unplugged the charger, you can see the cell voltage drop to acceptable ranges. Just out of curiosity I plugged it in again to see if the IC just needs a little time or help to properly end the charging cycle. But it didn't help.

Although I can measure zero current on the high side shunt, the voltmeter on the USB plug shows more than 500 mA flowing at 3,5W.


Original TP4056 on a commercial PCB.

To double check if the TP4056 is incompatible with measurements via shunt I took a commercial PCB from eBay with the original TP4056 IC with the correct logo and charged the same battery after discharging it ~380mAh. So this was a controlled experiment.

The graph looks way better!












Charging curve of the original TP4056.


The voltage rises up to 4.3V during charging, but the original TP4056 decreases the current sufficiently to not overstress the battery.
A proper charge end adds to the positive image of this IC.

It works like expected!




The only difference between the commercial layout and my DIY PCB is the optional R400 resistor at the Vcc connection. According to the datasheet, this is optional, so I didn't populate it. I added a 0R47 and restarted measurements.

Adding a R47 to the Vcc input of the fake TP4056.

It helps the huge jump of the cell voltage at the beginning of the charge cycle. An hour later, I measured the cell directly with a multimeter and immediately unplugged the charger. As can be seen in the graph, the cell has been charged to 4.4V already, although the measurement via shunt shows no current flow anymore.



Thus be warned. The fake TP4056 chips without the original logo resembling a "F" are potentially dangerous. Please check at least one charge cycle with your IC to verify it works correctly (and don't use a protected battery for that as it would protect the cell and hide the error.)
I am not the only one observing weird behaviour of cloned TP4056s - after researching a little on the issue I found other reports as well.

Update 09.07.2015: I received another batch of cloned TP4056 - the seller advertised with the original photo, but delivered ICs marked with "4056E". I built a PCB with it.


At first, the charger started off with 1.3A charging current. I stopped manually at 4.20V. When I checked, the charge current program resistor wasn't properly connected and delivered 4 MOhms instead of 1.2kOhm.
I resoldered it and it was 1.2kOhm afterwards. I restarted charging with the corrected PCB ...











To my surprise, the 4056E works correctly! It starts off with good 1A current. The current dropped slowly from the start and the charge termination is also correct at 100mA. (The glitches stem from notebook movements which  loosened the GND/- connection a little for a few ms.)

So not all clone TP4056 ICs are bad, some work correctly. The ones with a chip marking "TP4056" without that "F"-resembling logo are flawed, the original ones and the 4056E version are ok.

Donnerstag, 28. Mai 2015

Soshine T2 - measurements

The Soshine T2 serves me well for some months now already. As I built a low side shunt voltage and current logger, I wanted to take a closer look at the charger again.

Here's a photo of the battery dummy to feed the charger output to the shunt+opamp PCB, measurements are done with ATmega328 10Bit ADC (Arduino Nano in this case).

Some chargers have problems when there is additional resistance between the battery and ground, even if it's only 0.03 Ohms. But from the results I got, the Soshine T2 seems to work properly even with this data logger in place.
















The Soshine T2 shows some remarkable behaviour: It charges for roundabout 14 seconds, then switches off for 3 seconds - this seems to be a mechanism to measure battery voltage without load. This leads to a prolongued charging cycle, though.

Update 13.07.2015: Soshine T2 LiIon charging plot
The charger constantly drops the current over the whole charge cycle, so it delivers no real Constant Current phase. This is not the recommended charging scheme for LiIons, but no real problem as it only leads to a longer charge cycle.
What I deem problematic is that the charger doesn't really end the charging cycle even when it shows "FULL" on the display. After the charging ends, with different equipment I can see small current spikes. The voltage didn't rise anymore even when I left the battery in place for more than half an hour, even contrary, the voltage dropped as the cell discharged a few mV after charge end as usual. These spikes seem just to be very short and without real energy to detect if a battery is inserted.




So for rare occasions / not everyday usage the Soshine T2 is useable, but users should remember to take out the batteries after charging ends with a "FULL" display. It is not the best charger, but still ok. Especially considering that it can handle not only LiIon and LiFePos, but also NiMHs batteries (which is what I use it for).

Update 13.07.2015: Soshine T2 NiMH charging plot
Update 13.07.2015: With my improved Shunt and ADC setup (replaced the first plot of a charging curve), I can see that the current spikes at the end don't deliver measurable real current. Those seem to be for detecting an inserted battery; so all-in-all no bad feelings here. The charger seems to work correctly. The battery had exactly 4.200V when the charge ended, dropping a few mA (5-10) after that - the usual fast self discharge shortly after ending a charge cycle.

Also the NiMH charging is working correctly as you can see in the NiMH charge cycle plot to the left. The -dV charge termination detection can be clearly seen - and that there is some trickle charging, contrary to what happens in the LiIon charge program.

Another charging graph with even improved measurement and setup:
It's better visible that the charge current drops continuously - and when "switching to constant voltage" mode, a small increase in current occurs shortly before charging ends. To get an idea what this charging behaviour means in practice: Charging ~2500mAh into the battery took nearly 5 hours. Better chargers with real 1A current do this in 3 1/2 to 4 hours.

Sonntag, 10. Mai 2015

DIY LiIon-Charger

There are plenty of readily built chargers for LiIon batteries available on the market, and many are even quite cheap. But they all are usually limited to a form factor like 18650 cells, special for certain LiPo batteries like for quadcopters, mobile phones or digital cameras. Also, you never really know what you get technically, and sometimes it's not even worth being called a charger.

DIY battery holder with TP4057 DIY charger.
For example, I ordered a chinese wall-plug-charger with sliding connectors so I could charge all kind of flat batteries. One problem though, this charger showed "ready" when the battery had 4.4V - the limit is 4.2V +/- 0.05V, so correct result should have been 4.15-4.25V. Other chargers behave like LiIons are NiMH/NiCd batteries and don't stop charging, but continue to trickle-charge with a few mA; unfortunately the one I bought as universal charger with changeable cradles is one of these. LiIons have very little self discharge, so this will overcharge and damage the battery. Other chargers like the Trustfire TR-001 and TR-002 have electrical problems and also don't work properly with many produced lots; it's like playing the lottery to get a good charger.

"Damage the battery" doesn't sound as bad as it possibly is. Cheap NiCd/NiMH can blow up and leave an ugly mess with the acidic electrolyte. LiIons not only can produce fire and a hydrogen explosion, they also contain Lithium which is one of the most reactive alcaline metals which burns by itself. Destabilizing such a battery with a cheap or simply broken-by-design charger is something you certainly want to avoid. Just remember the Boeing Dreamliner LiIon issues.







TP4056 IC on the eBay/Aliexpress PCBs - original.
This was the reason I was looking around for alternatives. The first thing I stumbled upon a few years ago were TP4056 boards which received quite good feedback. They are small, extremely cheap (less than a buck per board on Aliexpress) and reliable.

These boards use the original TP4056 charger IC (datasheet). There seem to be a few knock-offs or clones around, which nearly all seem not to work well like the original ICs (WARNING!). But this shows that you always need to check at least one charge cycle to verify that your charger is working correctly.









I ordered a few handful of these chips for about 2 Euros including shipping and today finally built my own PCB with it. It is a bit smaller than those boards from eBay/Aliexpress.
Size comparison: DIY board vs. eBay PCB.

On the picture you can see that it is possible to save some space. But it was a challenge to get that on a perfboard without shorts and solder bridges. The LEDs are in the usual colours - red and green, instead of blue (charging) and red (ready/stand by) on the properly manufactured boards.

Finally it worked correctly. Using my improvised battery holder I had a decent CC CV charging cycle with very little thermal throttling. During the constant current phase, close to 1A current were flowing. The battery came out with 4.175V, the charger completely stopped charging the battery. So the IC works like wanted and expected. This was only a random result though, see the newer article about fake and clone TP4056 ICs.













Close-up view of the DIY TP4056 PCB.
Knock-off TP4056 - the logo is missing.


















I also ordered a few different ICs which I wanted to test for building my own (universal) chargers .
The LTC4054 DIY PCB.

There is a small SOT-23-5 chip available called LTC4054 (datasheet). It is dirt cheap on Aliexpress, I got 50 pieces for less than 3 Euros. That again includes shipping fees. It can charge with up to 800mA.

At least in theory. At that rate the IC gets quite hot and thus runs into thermal throttling. This not only prolongs the charging cycle, it also leads to a premature end of the CV phase. My batteries had only around 4.15V after charging with this IC.

The LTC4054 only supports one status LED. With a capacitor for the battery connection, without a battery attached it shows a dimmed light with bright pulses at a frequency depending on the capacitance. During charge, it shines bright; when finished, it is in the dimmed state again - without flashing.

It is reliable and doing a good job, but it is hard to cool down due to its small footprint. I like it anyways. Not charging a LiIon battery to the full 4.20V is putting less stress on the cell, leading to a longer life span.

Another charging IC I recently found is the TP4057 (datasheet). The datasheet is only available in chinese, but Google Translate delivers a sufficient translation.
A TP4057 DIY charger board.

The SOT-23-6 IC is also hard to put on a perfboard. But it works fine after all.

The TP4057 delivers up to 500mA charge current. As the other ICs I tested, it properly stops the charging cycle at the end. The final cell voltage was exactly within the datasheet specs of 4.20V +/- 1% with the batteries having 4.158V after the charge cycle.

The TP4057 also has a very good reputation and as noticeable special feature a reverse-battery protection. It got used on some Miller ML-102 versions, where two of the ICs were used in parallel for increasing the charge current up to 1A. The LEDs are connected to only one of the ICs then, which is why those ML-102 versions continue charging a bit longer even when their green LED lights up already.


With these ICs it is quite easy and fun to build your own LiIon charger. The result is a reliable charger which does a proper job without overcharging or trickling the battery. For very little money as well!