Sensing in Attiny85 driven buck converter? - Page 1
Forum section: electronics / projects

author: Artlav
author_rank: Frequent Contributor
timestamp: September 03, 2014, 11:07:15 pm
content: I'm trying to make a battery charger buck converter, driven by attiny85.Based on the AVR458 reference design by Atmel.However, i can't quite get it to work.The problem is in current sensing, and to some degree, voltage too.Schematic:Layout:I'm using 1.1V reference voltage instead of 2.5V, everything else is about the same as in AVR458.The voltage sensing is running read_volt_amp in a loop.It senses the voltage directly, and current differentially with x20 gain.Code:void read_volt_amp(void){volatile uint32_t res;if(half==0){ADCSRA|=(1<<ADIF);ADCSRA|=(1<<ADSC);while((ADCSRA&(1<<ADIF))==0){}ADCSRA|=(1<<ADIF);res=ADCW;//res=res*484UL;//res=res/100UL;//res=res*175UL;//res=res/100UL;cur_amp=(cur_amp+res)/2UL;half=1;ADMUX=(1<<REFS1)|(1<<MUX1)|(1<<MUX0);}else{ADCSRA|=(1<<ADIF);ADCSRA|=(1<<ADSC);while((ADCSRA&(1<<ADIF))==0){}ADCSRA|=(1<<ADIF);res=ADCW;res=res*115UL;res=res/10UL;cur_volt=(cur_volt+res)/2UL;half=0;ADMUX=(1<<REFS1)|(1<<MUX2)|(1<<MUX1)|(1<<MUX0);}}void setup_adc(void){ADMUX=(1<<REFS1);ADCSRA=(1<<ADEN)|(1<<ADPS1)|(1<<ADPS0);}There is no control as of now, the PWM is fixed so there is a constant current (150mA) going through a test load, a 9V LED.Problem is, the current read by the ADC can:-A, vary within +-10-B, is higher or lower than what is expected (consistent, but non-linear).The higher the ADC prescaler, the weirder the current read-out is.Without the half-half reading (that is, reading all in one go), the current reads 0, always.If you remove voltage reading, it does read, but reads the same weird value.If you read the current once, on a signal instead of a loop, then it gives the correct value.Voltage reads correct all the time, with a bit of a noise on it (that fits the ripple actually seen).I don't get it.Is it some noise in the circuitry?Is it software issue?Being based on a reference design, i expected it to just work.

author: georges80
author_rank: Frequent Contributor
timestamp: September 04, 2014, 01:02:43 am
content: You should set and wait on ADSC for the conversion.ADCSRA |= _BV(ADSC); // start A/D conversionwhile (ADCSRA & _BV(ADSC)) // wait for A/D conversion to complete;Software control of a buck driver will never be as good as a dedicated switcher IC. I created a tiny based LED driver (software buck) many years ago - it worked ok if voltage was stable etc. Otherwise there was flicker. A software control loop has fixed PWM step sizes (8 bit PWM) and also takes time to respond to transients.It's a neat project to play with, but I eventually moved to dedicated switcher IC's that were then controlled (current driver and/or PWM) by the tiny.From experience working in semiconductor companies, NEVER assume that an application note is 'correct'... They are generally created by app engineers working for the marketing dept... Treat them more as 'conceptual designs' that you likely need to refine.cheers,george.

author: hlokk
author_rank: Contributor
timestamp: September 04, 2014, 02:21:56 am
content: I haven't gone through the circuit in any detail, but if you're using a different reference voltage, its not quite clear where you've set that in your code.http://arduino.cc/en/Reference/AnalogReferenceAlso, as the arduino at least (and presuming the attiny), make sure your voltages are referenced to ground. If you're measuring across the LED and the series resistor is below that then measuring the LED or resistor may short the resistor out? (Cant remember which way it goes). It may be obvious from your circuit diagram and code that you have this sorted though (didn't get a chance to fully go over)

author: Artlav
author_rank: Frequent Contributor
timestamp: September 04, 2014, 05:31:32 am
content: Quote from: georges80 on September 04, 2014, 01:02:43 amTried to wait for ADSC to go low - works the same as with waiting for ADIF to go high.Quote from: georges80 on September 04, 2014, 01:02:43 amSure, but it's an interesting idea to explore.And for loads that does not vary much, like a battery being charged, it might work just fine.Quote from: georges80 on September 04, 2014, 01:02:43 amWell, it does not make it less strange that the ADC fails to work like that.Quote from: hlokk on September 04, 2014, 02:21:56 amUm, ADMUX=(1<<REFS1); ?I'm not using Arduino libs or their derivatives, just attiny85.

author: hlokk
author_rank: Contributor
timestamp: September 04, 2014, 06:35:10 am
content: Quote from: Artlav on September 04, 2014, 05:31:32 amThe arduino was just a link to show how its done on the arduino only, but seems you've set the reference to the inbuilt one. AFAIK the inbuilt ref isn't super precise, so might make sense to use an external reference if you need a lot of accuracy (but otherwise it should work).I followed the path of your sense resistor, and at 150mA it'll drop 15mA. For a 9v supply you then volt divide it by 100k/10k which gives you two voltages for 818.18mV (ADC2/PB4) high side and 816.82mV (ADC3/PB3) for the low side, then feed this into the MCU via a 4.7k resistor. Assuming a perfectly high impedance in the chip, you'll get those two values read by the Attiny85's ADC, which for 10 bit will give values of 762 and 760 so only 2 counts difference. Effectively you're taking a 15mV differential, then dividing that difference by around 10 meaning the ADC needs to differentiate between a mV or two to determine the current.The Voltage reading should be ok as its placed well in the ADC range (and ref'd to ground). If the Attiny85 doesn't have a perfectly high impedance (I'm guessing its on the order of 10-100M? then the 4.7k will act as a voltage divider, but you may not mind the accuracy/precision loss)The reason for getting weird results when not sampling at the same time (half and half) as you say is that the current may be fluctuating a little (expected with a switchmode supply as there will always be output ripple, even if minor). So if the low side of the current resistor fluctuates a few mV then your current calculation readings will be garbage due to the precision of the ADC.Seems like you'll need to use an amplifier or similar to get a different voltage for the current prior to feeding it into the ADC?I tried following the code, but you haven't commented it at all (). Its unclear what types "res", "cur_volt" and "cur_amp" are. Are these declared as unsigned longs as per the "UL"?

author: Artlav
author_rank: Frequent Contributor
timestamp: September 04, 2014, 08:10:34 am
content: Quote from: hlokk on September 04, 2014, 06:35:10 amAttiny85 have a differential input mode with a gain of 20, which should produce a value of about 25.In other words, about 6mA resolution.But i'm getting 50 or 80, or 0, or garbage, depending on prescaler, whether voltage was read before, etc.Quote from: hlokk on September 04, 2014, 06:35:10 amVoltage is read single-ended, relative to the ground.The current is read differentially, between the two pins.So timing or fluctuations shouldn't affect it.If it was voltage reading sagging one end, then i should have seen an increase in current reading when it was read before the current, since voltage is read on the load side.It would dip the lower half.But i get 0 in that case.

author: T3sl4co1l
author_rank: Super Contributor
timestamp: September 04, 2014, 08:26:27 am
content: http://www.atmel.com/Images/Atmel-2586-AVR-8-bit-Microcontroller-ATtiny25-ATtiny45-ATtiny85_Datasheet.pdfRead page 168. You've just measured the performance of the ADC. Actually, you probably found better than typical, because they only guarantee +/-20 LSBs on that measurement, at a 5 times lower clock rate!On the plus side, the x20 amplifier's bandwidth is so low that you're nearly guaranteed to have consistent samples.On the minus side, according to the diagram, switching the mux will switch what the amplifier sees, so you need to wait until its output settles.Did anyone ever mention before how awful ATmega series analog peripherals are?Not that you can expect much from the circuit to begin with -- 30 LSBs (< 5 bits) isn't much of a signal for current when you're dealing with 10 bit acquisitions, let alone the seriously euphemistic expectations of 32 bit variables.Tim

author: hlokk
author_rank: Contributor
timestamp: September 04, 2014, 08:29:37 am
content: Quote from: Artlav on September 04, 2014, 08:10:34 amIf your voltage is fluctuation, you take a reading, then wait some amount of time, then take another reading then subtract one value from the other then you'll get readings all over the shop (unless the noise/ripple is much less than your resolution).Perhaps its an issue with a register being overwritten, or a integer value creeping into a double calculation or vice versa (e.g. if you need floating point precision).I think your best bet at troubleshooting is to disconnect the sense lines and put in a potentiometer rigged up to a low voltage supply and then adjust it to get say 1mV difference between the differential inputs on your Attiny85 and see if you get the same issues? If running all linear, stable parts confirmed with a multimeter and it works then you know the switching circuit is likely the problem not the MCU or your code.

author: Artlav
author_rank: Frequent Contributor
timestamp: September 04, 2014, 08:59:07 am
content: Quote from: hlokk on September 04, 2014, 08:29:37 amExcept that's not what i do.Attiny85 have a hardware differential ADC input.Sampling the difference, not two one after another.Quote from: T3sl4co1l on September 04, 2014, 08:26:27 amSo, basically the conclusion is that the AVR458 reference design is garbage, and i should put a proper current sense amplifier chip in there instead of trying to use attiny's ADC directly?Quote from: T3sl4co1l on September 04, 2014, 08:26:27 amI had suspicions like that.But never actually had to take one to it's limits.

author: T3sl4co1l
author_rank: Super Contributor
timestamp: September 04, 2014, 09:40:08 am
content: Quote from: Artlav on September 04, 2014, 08:59:07 amThat would be one thing. Another would be to get rid of it altogether.Even if you get full dynamic range (zero to VCC = 0-1023 counts, and so on), you're still limited by the sample rate, which always requires that you need a massive inductor so that the analog bandwidth is slow enough not to run away between samples. In other words, if the load suddenly goes open or shorted, for example, what's the soonest you can do anything about it? In most practical cases, that's going to take maybe 3-6 samples worth of time, and no less than 2 (one for the sample, one for the PWM output to actually change).The best possible case would be using it as a pulse width modulator and nothing else. If you run SPI at full speed, you can get passable bandwidth from an external (8-12 bit) ADC. Or you could use a different type of ADC, or external logic, to generate parallel data, and read that at high bandwidth through digital input ports (you'll need a few more pins, of course). But by then, you might as well use a comparator to generate the PWM in a dumb manner, and now you don't have to worry about the outboard ADC, and boot time (10s of us to 10s of ms depending on POR and clock settings!), let alone possible software crashes (not that such a simple program should be able to crash, but if it happens, well... there you go).If you need to implement a more complicated function, like a battery monitor or solar charger or artificial sunrise lights or whatever, you're always better off implementing the basic stuff in basic hardware (analog), and wrapping a digital control around that (ADCs/DACs). You can get away with internal converters in this case, because the bandwidth will probably be low -- how often does the battery voltage / current setpoint need to be updated? Probably a few times a second, whereas the inductor's current can be monitored in real time by analog circuits with MHz+ bandwidth -- something an MCU shouldn't be required to handle.Ed: and then, you can use lower bandwidth op-amps for things like current sense -- common mode range is a tricky thing, even for purpose-made current sense devices. Most don't look very good over 100kHz, right where all the switching ripple is. A slow monitor doesn't need to worry about that, and it can all be filtered clean.QuoteWell, an 'optimal' circuit (and program), designed fully around the limitations of the chip, could still do a lot better than what's here. But that would still be many times inferior to a proper controller chip.Tim

author: eneuro
author_rank: Super Contributor
timestamp: September 04, 2014, 06:40:26 pm
content: Quote from: T3sl4co1l on September 04, 2014, 09:40:08 amDo we realy need Mhz bandwidth for battery charging?I use ATTiny85 with TL431I voltage reference and Hall current sensor & simply voltage divider @ 250Khz ADC clock, where ADC mesurement takes about 13 clocks, so without any reference voltage changing I can sample current and voltage close to 10000 times per second and in the time when ADC conversion takes place do needed corrections and calculations at 16Mhz internal oscilatorIt is only battery charger and more important is have temperature stable voltage reference I think, so I've choosen industrial version of TL431I while this charger will be used in winter too to keep in full charge lead acid car battery at 13.5V voltage and it looks like even in desulfator mode (without any inductor) this voltage at 10kHz PWM is stable as expected while TL431I is used as AVref on ATTiny PB0 pin

author: T3sl4co1l
author_rank: Super Contributor
timestamp: September 04, 2014, 07:49:57 pm
content: Well, the internal control loop usually has ~MHz bandwidth, which is normal for analog error amps. The minimum will be on par with the switching frequency (give or take a pole-zero pair, the controller usually has a dominant pole not too many times the switching frequency). Doing it significantly lower than the switching frequency will give you... problems.An external loop can be as slow as needed, which for a battery, can be in the millihertz.Is that not what I said?....Aren't we just agreeing?I would ask you this: how does your battery charger / desulfator respond to a short circuit? Would you care to demonstrate for us? If not... well...As well, 10kHz is ridiculously low for a switching application -- almost in the domain of iron cored chokes -- it's painful to the ears, and bulky to build. Suppose you wanted to build a smaller one with otherwise the same design, would you be able to? How would it respond to transients or shorts?Tim

author: eneuro
author_rank: Super Contributor
timestamp: September 04, 2014, 08:22:14 pm
content: Quote from: T3sl4co1l on September 04, 2014, 07:49:57 pmMCU in this charger is powered from charged battery voltage, so mains 230VAC interrupts does not affect its program flow without storing anything in EEPROM.There are 2 fuses- 1st small at 230VAC transformer mains and 2nd 15A on its secondary-while two IRFZ44N with 18mRDSON each in pararell and thick 5mm copper tracks should win in the case of shortcircuit on transformer secondary while those mosfets are rated close to 50A (ID)This 2nd fuse may be burned if reverse polarity attched to car battery, but if someone doesn't care about it is better one will have to change this fuse and think about it next timeQuote from: T3sl4co1l on September 04, 2014, 07:49:57 pmIt depends on inductor used and desired output ripple.Some guys use even 100Hz desulfators, other 1kHz with 5% PWMBTW: In desulfator mode inductor is shorted and 20Vmax 10kHz pulses "keep alive" old battery when needed under steady safe 13.5V .

author: T3sl4co1l
author_rank: Super Contributor
timestamp: September 04, 2014, 09:32:06 pm
content: Quote from: eneuro on September 04, 2014, 08:22:14 pmNon sequitur? I mean shorted output. The beefy ampy sparky end.If it's supplied by the battery, then how quickly does it shut down? Does it shut down at all gracefully -- i.e., do transistors get shorted out, or are they turned off within microseconds?QuoteA noble effort, but only useful for protecting the wiring -- transistors die in 10 us, fuses blow in 10 000 us.QuoteWhy would the transformer go short circuit? The transformer is one of the most reliable parts of your circuit (and the last thing to be afraid of, besides possible surges from the line side).Beefy transistors are no guarantee of safe operation, in fact the higher current capacity can make things worse, for themselves and for everything around.A 50A transistor means short circuit currents of at least 50A, if it's accidentally left on during a fault condition. That's 500W at 10V, which will blow silicon sooner than the fuse will open.QuoteOuch, reverse polarity car battery, that's probably orders of magnitude worse than my challenge, a mere short circuit. And you said the fuse is on the transformer secondary, not the output terminals, correct? So it won't do anything -- cold cranking current directly into the output transistors / diodes, yikes!QuoteThat sounds all kinds of nasty...Tim

author: eneuro
author_rank: Super Contributor
timestamp: September 04, 2014, 10:14:23 pm
content: Quote from: T3sl4co1l on September 04, 2014, 09:32:06 pmIt is supplied from battery but the same it charges and a few lines of code when disconnected will shutdown PWM while even MCu will have VCC above BOD terminals voltage will drop to 0V (below 7V required to switch PWM ON ) when someone will try to put together output terminals taken from the batteryQuoteQuote from: T3sl4co1l on September 04, 2014, 09:32:06 pmOutput terminals are.. on transformer secondary tooEven without fuse on terminals outputs, those short output wires would got hot first and.... disapearedThis "reference" design works more than 2 years without any problems and nothing burned so far.I had to take look into its schematics concept and forgot that mosfet internal diodes will block reverse connected battery, so the most difficult (and expensive) silicons to repair are quite safe anyway