ATMEGA C routine for an algorithm Q..

Thread Starter

toffee_pie

Joined Oct 31, 2009
235
hi guys,

I have code here I am running on an ATmega 328p, I want to perform some math/data activity on it, for a power related project.

what I am interested in knowing is mainly, if any number crunching code makes any difference to power consumption?

I am using ca 23.5mA of current with the program listed here, I have a LED to light up once a result is known. I tried other routines but the current did not fluctuate much, if at all.

what I want to do is basically have a routine return some value, and gradually reduce the voltage into the 328p until garbage is returned, or no result.

is this possible?



Rich (BB code):
void maths(){



signed char alpha, beta, gamma;

signed int prod;
signed int sum;
signed char result;


prod = (int) alpha * beta;

sum = (( signed char) (prod>>8)) + gamma;

if (sum>127)

result =127;

else if (sum < -128)

result = -128;

else

result = (signed char) sum;

    int a = 1;
    int b = 2;
    int c = 0;
    int d,e;
    int i;

    for(i =0; i < 10 ; i++){
    
        a = b  * c;
        d*= e; 

        c = (a+b);
        d = (a+c);
        e = (a+d);
        c = (a+b) * d * result;


    _delay_ms(1000);
    //PORTB = 0b00000010; // led on PB5

        }


}
 

zxsa

Joined Jun 11, 2010
31
The current won't change much by just running different instructions. A little bit, yes, but it should not be that significant.

Where you will see a change in the current, is when you activate/deactivate different peripheral units (like the UART, SPI, Timers, ADC, etc).

The AVR has a feature built in called brown-out detection. When enabled, this module will detect when the supply voltage drops to a low level and will then place the AVR into reset. This is exactly to prevent garbage results.

So, to do your test, make sure that brown out is disabled (it's one of the fuse settings).

Also, you need to look at the clock settings. Although I can't be 100% of the device you're using, all the mega's that I've worked with requires stable 5V in order to use the maximum 16MHz clock. At this high clock, you will see the AVR performing badly at fairly high voltages (above 4.0V even).

It is likely that you might not see any garbage, but that the clock simply stops. So you probably want to keep an oscilloscope watching the clock signal at the same time.
 

sage.radachowsky

Joined May 11, 2010
241
I once saw an MSP430 run as low as 1.4V or so... I forget exactly what voltage but it was far below the 1.8V published as spec. It was even blinking a red LED, and it probably could have run even lower but wasn't able to blink the LED. I powered it off a supercap, and then just let the supercap get lower and lower and watched the LED.

Sage
 

Thread Starter

toffee_pie

Joined Oct 31, 2009
235
thanks for the feedback guys,

what I am mainly getting to is this.

If there is some operation or operand running @ lets say 3.5volts, and it works dandy, no problems.

what if the voltage was reduced to 2.9 volts, and ding a ling,, it also worked satisfactory and as expected.

that's what i want to prove, there would have been a saving of 600mV in the above example, both voltage levels are acceptable, but its obviously preferred to have as low a voltage as possible.

does this make sense? i want to plot some vcc vs current charts on excel to describe this but not sure how i should approach it.

as it stands i have a programmable buck converter whose voltage i can dynamically change, and this feeds a 328p as my load.

regards.
 

zxsa

Joined Jun 11, 2010
31
Like I said previously, it won't be an instruction that is "a bridge too far", it would be activating another peripheral. All instructions are run inside the core which will draw more or less the same current regardless of instruction.

You probably would not need to plot voltage vs current. Just run your program at various voltage levels and see if it runs reliably (reliably means test it 100 times at the same voltage and you would want it to run correctly each and every time).

You could also measure the current that your buck converter supplies as an indication of the average current consumption at the various voltage levels.

Something else that I would like to point out, is that this measurement is, in a way, futile. You may measure one microcontroller to be able to run 600mV below the specified voltage. A second one may even run 2V below specification! But the other 98 out of 100 will fail to run reliably below the specified voltage.

There is usually a fairly good reason why a manufacturer specifies certain data. If you design for operation outside of this specification, you're taking a gamble.

It's generally considered good practise to design 20% above specification. For example, the specification may say that an IO-pin recognises 2.0V as a logic high - I would design so that the signal on the pin is 2.4V.

Of course this is not always possible. As I said before, some of the AVRs requires 5V in order to run at 16MHz. But they also have an absolute max voltage of 5.5V or 6.0V. Adding 20% on top of 5V will place me right at the abs max rating which is much worse than trying to run it at exactly 5.0V.
 

Thread Starter

toffee_pie

Joined Oct 31, 2009
235
thanks for the update,

What about the pre scaling of the crystal, would this be a useful exercise, it would be some type of dynamic voltage frequency scaling i guess.

vary the voltage and use pre scalers and see the current and power changes.,?
 

Papabravo

Joined Feb 24, 2006
21,225
The crystal oscillator pins do have some flexibility to choose different types and frequency ranges. I'm not sure what you mean by "prescaling" the crystal. Crystal oscillators can be "pulled" a little bit by changing the capacitive load but this technique does not apply over a wide range.

If you want to do this type of experiment get a signal generator and configure the ATmega part for external clock. Connect the output square wave to XTAL1 and leave XTAL2 open. Now you can vary the clock to your hearts content. One thing to check is any hint that there is a minimum clock frequency. If there is not then the design is probably static (opposite of dynamic) and you can stop and restart the clock without losing the contents of the registers. There were several processors of the late '70s that were famous for being able to do this. Of course there were others where this would be catastrophic to the internal data integrity.
 
what I am interested in knowing is mainly, if any number crunching code makes any difference to power consumption?
If that is really what you want to know, then I would suggest that you stay on one input voltage and measure the input current. I suggest that you should run two versions of code -- one that endlessly does the math you want to test, and the other that does something else like an endless loop as in "while(1) {NOP; NOP; NOP; NOP; NOP; NOP;}" (lots of no operations). You may also try other codes.

I would *not* try to do this by having any delay in which the core is sleeping, as I think you have with "__delay_ms(...);" because that would really make the difference a lot smaller between the two codes. Already, I doubt that there will be a measurable difference.

My offhand guess is that there is very little difference in power consumption by a microcontroller whether it's branching, testing, or multiplying. Maybe there would be a *little* more if you're using a special 32-bit multiply repeatedly or some other section that is not the normal width of the processor, since it will be flipping gates that are not normally in use.

In terms of power consumption, you may notice in the data sheets that the main factors are:
  • voltage of power supply
  • speed of processor
  • peripherals that are active
  • duty cycle (% of time awake)
  • power loss on I/O pins for various reasons

In general, if you want to reduce the power consumption to the minimum, then run the processor at a slower speed, like 1 MHz, sleep all the time except when you *must* be awake. Write your code so that you do the minimum number of wakeups, including interrupts, and do all your processing in the same wakeup period, run at the lowest safe voltage (which is the one spec'd in the data sheet as minimum), and tie all your unused pins to 0 or Vdd and set as inputs, or else set them as outputs... and watch for leakage through internal pull-up resistors and make sure all analog inputs are set as input so they won't try to be Schmitt triggered. Also, use the oscillator that uses lowest power -- the internal RC if you don't need true timekeeping, or a 32,768 watch crystal if you do need real time clock.
 

Thread Starter

toffee_pie

Joined Oct 31, 2009
235
hi guys

this is worse than i expected.. :mad:

I ran this code,

current on my DMM was ca 4.4mA,

I had a bank of 6 led's on port d giving about 9/10 mA which was normal.

then i blanked out the function below and programmed the atmega with that, basically a blank box..

and ditto, also got back 4.4mA.. :eek::eek:


Rich (BB code):
/int x,y,z;


//signed char alpha, beta, gamma;

//signed int prod;
//signed int sum;
//signed char result;


//prod = (int) alpha * beta;

//sum = (( signed char) (prod>>8)) + gamma;

//if (sum>127)

//result =127;

//else if (sum < -128)

//result = -128;

//else

//result = (signed char) sum;


//x = (result * prod/sum) * y/2;

//z = sum + x;
 

zxsa

Joined Jun 11, 2010
31
I can't say that this was unexpected to the rest of us :)

Using a multimeter for this measurement is not the best idea. Better would be to use an oscilloscope. Consider using the attached circuit to do the measurement (I'm including an LTspice schematic which you can simulate to see how it works).



 

Attachments

Thread Starter

toffee_pie

Joined Oct 31, 2009
235
Last edited:

zxsa

Joined Jun 11, 2010
31
The x10 is because of the 10ohm resistor
x40 is the gain of the INA138 opamp (the gain is selected by the 200k resistor to ground).

You should use 1% accuracy resistors for both the 10 ohm and 200k ohm. Otherwise just measure the gain by drawing a known current and measuring the output voltage.

This INA138 device is a specialised opamp - specialised for high-side current measurement applications. As long as your buck regulator is pretty stable, and you have an oscilloscope with sufficient resolution, you should be able to see what your current is doing.

The link in your post is the correct device. It is a fairly small surface mount device, but if you put your mind to it, you can solder thin wires to each pin. I've had one of my junior engineers doing that and it worked perfectly.
 

Thread Starter

toffee_pie

Joined Oct 31, 2009
235
The x10 is because of the 10ohm resistor
x40 is the gain of the INA138 opamp (the gain is selected by the 200k resistor to ground).

You should use 1% accuracy resistors for both the 10 ohm and 200k ohm. Otherwise just measure the gain by drawing a known current and measuring the output voltage.

This INA138 device is a specialised opamp - specialised for high-side current measurement applications. As long as your buck regulator is pretty stable, and you have an oscilloscope with sufficient resolution, you should be able to see what your current is doing.

The link in your post is the correct device. It is a fairly small surface mount device, but if you put your mind to it, you can solder thin wires to each pin. I've had one of my junior engineers doing that and it worked perfectly.

nice one, i have a lp3907 buck converter put onto a pcb i made so i should manage.

will smd or wire wound resistors make a difference for this? bearing in mind all my components on the breadboard are wirewound.
the buck converter and its pcb has all smd parts. very small footprints.
 

Thread Starter

toffee_pie

Joined Oct 31, 2009
235
I think i got a winner here...!

this routine uses a tasty 10.7mA, can anyone verify this on another atmega device for me?

I have tried a lot of maths algorithms and this is so far the most power hungry..


/* this program merges 2 arrays, the first has 2 elements and the second
array has 3. I have initialised the arrays with values so that you can run
the code and see the output. This can of course be generalised to arrays
of any size which are read from a file or from the keyboard.
*/

int i=0,j=0,k=0;
int a[M] = {2,3}, b[N]={4,5,6}, c[M+N];

while (i<M && j<N)
if( a < b[j] )
c[k++] = a[i++];
else
c[k++] = b[j++];

while( i<M )
c[k++] = a[i++];
while ( j<N )
c[k++]=b[j++];

for (i=0;i<N+M;i++)
printf("%d\n", c);
 
What is your testing procedure?

Do you run the routines in an endless loop, or are you scoping the current consumption through the blip of time it takes to execute once?

Does the "printf" in the second routine use the UART, i.e. sending data to the serial port?

I'm interested in your results. I am wondering if RAM access (read / write) uses more power than using the registers.
 
I'm posting the circuit proposed by ZXSA in a graphic format so it's easier for others to read.

My concern is that its output voltage is going to ripple with the amount of current, for example at 10 mA it will lower 100 mV.
 

Attachments

zxsa

Joined Jun 11, 2010
31
@toffee_pie: the increase in the current MAY be due to the printf statement. printf may be using the serial port to output characters. If this is the case, then your routine has now enabled an extra peripheral inside the AVR which is why more current is being used.

@Sage: Yes, the voltage to the AVR circuit will fall. But provided that toffee_pie has placed decoupling caps on the AVR's power pins (as required by the datasheet), the voltage should stay stable - although at a slightly lower voltage.

One solution to this problem would be to take the regulator's feedback voltage from between the 10 ohm resistor and AVR circuit. The regulator will then attempt to keep that voltage at 5V (or which ever setting is being used).
 

Thread Starter

toffee_pie

Joined Oct 31, 2009
235
I will post back later re: printf//

I notice the minimum vcc for the 138 is 2.7 volts,

what i could do i suppose is use buck 2 output from 3.5volts to 2.7 volts and see how load (data) activity on the atmega gets on for the varying input...?
 
Top