Atmega328p not returning for power nap

Go To Last Post
15 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi all.

 

I have been asked to create a tracker that reports its GPS coordinates every 12 hours.

The interface with the GPS unit were surprisingly easy.

The interface with the GPRS module for posting data to a Web page was ... harder, but not too bad.

 

But for the problem:

The unit is designed to live off of 3 penlight batteries, and I was hoping for at least 6 months worth of data.

So I will need to shut down everything I won't be needing and sing the CPU to sleep during the 12 hours of waiting.

The idea was to start the 16 bit timer and have it track the time. Running the CPU on 1MHz (8 MHz internal Chrystal, with the 8 divider) and a 1024 prescaler, the Interrupt triggers every 67.7 (?) second

 

Please have a look at my following code. I have posted the following functions;
void timer1_init(void);                         // To init the Timer that will keep track of time and that will wake the CPU from slumber

ISR(TIMER1_OVF_vect)                       // Interrupt handler. To track overflows and to initiate the wake-up of the CPU
void timer1_CPUwakeup(void);             // Function to carefully bring the CPU back from slumber
void timer1_CPUsleep(void);                // To lead the CPU into light slumber

 

Plan of attack is to:

* Run the "timer1_init()" at startup, and then run straight into the GPS DATA retrieval.

* Entering the GPS retrieval will set a variable "workschedule" that will tell the timer to not trigger sleep

* When the job is done, then run the "timer1_CPUsleep()" to lead the CPU into slumber and wait for next time to do some work.

* When the timer has counted enough overflows, it will run the "timer1_CPUwakeup()" to wake up the CPU and continue the counting.

 

Now - I can see that the system does the job the first time. And I can see that it completes the "timer1_CPUsleep()". However, it never recovers from the sleep.

I've been searching the Internet for about a day, but no good leads on how to bring it out from the slumber.

Any pointers would be greatly appreciated.

The only IO that is needed is PC0, PC1, PC2 and USART. Everything else is disposable.

 

Also - I have been looking for a place to buy the "uCurrent" designed and produced by the EEVblog genious.
It does not seem to be available anywhere. Is there some replacement you could recommend for me?

 

Kind regards,

Geir Moen

 

 

---------------------- CODE -------------------
 

void timer1_init(){                                    // initialize timer, interrupt and variable

  TCCR1B |= (1 << CS10) | (1 << CS12);  // set up timer with prescaler = 1024

  TCNT1 = 0;                                            // initialize counter

  TIMSK1 |= (1 << TOIE1);                       // enable overflow interrupt

  sei();                                                     // enable global interrupts

  int1_overflow = 0;                                  // Clear out variable for Interrupt overflow

  workschedule = 1;                                  // Start up by flagging active work

}

 

ISR(TIMER1_OVF_vect){                                          // TIMER1 overflow interrupt service routine. *** triggers every 67,72486772486772 sec. Not sure why ***

  int1_overflow++;                                                  // Keep a track of number of overflows

  if(int1_overflow ==  637){timer1_CPUwakeup();}   // Trigger work ethic after 12 hours of sleep

  if(int1_overflow == 1275){timer1_CPUwakeup();}  // Trigger work ethic after 24 hours of sleep

  if(int1_overflow == 1912){timer1_CPUwakeup();}  // Trigger work ethic after 36 hours of sleep

  if(int1_overflow == 2549){timer1_CPUwakeup();}  // Trigger work ethic after 48 hours of sleep

  if(int1_overflow == 3186){timer1_CPUwakeup();}  // Trigger work ethic after 60 hours of sleep

  if(int1_overflow == 3827){timer1_CPUwakeup();}  // Trigger work ethic after 72 hours of sleep

  if(int1_overflow == 4464){timer1_CPUwakeup();}  // Trigger work ethic after 84 hours of sleep

  if(int1_overflow == 5103){timer1_CPUwakeup();}  // Trigger work ethic after 96 hours of sleep

  if(int1_overflow == 5742){timer1_CPUwakeup();}  // Trigger work ethic after 108 hours of sleep

  if(int1_overflow == 6381){timer1_CPUwakeup();}  // Trigger work ethic after 120 hours of sleep

  if(int1_overflow == 6381){int1_overflow = 0;}       // Reset trigger if 120 hours has passed

  if(workschedule == 0){

    set_sleep_mode(SLEEP_MODE_IDLE);

    sleep_mode();

  }

}

 

void timer1_CPUsleep(void){

  cli();

  workschedule = 0;

  DIDR0 = 0xFF;                                        // Disable binary buffer for PORTC (analogue pins);

  DIDR1 |= 3;                                            // Disable digital input buffer on Analog comparator pins

  ACSR &= -(1<<ADIE);                             // Disable Analog comparator interrupt

  ACSR |= -(1<<ADC);                               // Disable Analog comparator

  ADCSRA &= -(1<<ADEN);                        // Disable unused peripherals

  power_adc_disable();                               // Disable Analog / digital converter

  power_spi_disable();                                // Disable SPI communication

  power_twi_disable();                                // Disable Two wire communication

  power_usart0_disable();                           // Disable Serial communication

  power_timer0_disable();                           // Disable 8 bit timer TIMER0

  power_timer2_disable();                           // Disable 8 bit timer TIMER2

  sei();                                                       // Re-enable Interrupt (TIMER1 is the only one running)

  set_sleep_mode(SLEEP_MODE_IDLE);        // Prepare for SLEEP mode

  sleep_mode();                                          // Enter SLEEP mode

}

 

void timer1_CPUwakeup(void){

  cli();                                                        // Disable Interrupt so that it doesn't trigger uncontrolled

  workschedule = 1;                                    // Flag system for Work

  DIDR0 = 0x00;                                         // Re-enable binary buffer for PORTC (analogue pins);

  power_usart0_enable();                            // Re-enable Serial interface

  sei();                                                       // Re-enable Interrupt

}

 

This topic has a solution.
Last Edited: Tue. Feb 27, 2018 - 12:40 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

When sleeping in an ISR, the next interrupt is not generated.
That is, the CPU will not wake up.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 That's true. When an interrupt occurs, global interrupt bit is cleared, same as you'd call cli() and no interrupt will happen until current one is handled. To enable nested interrupts, I-bit has to be set, eg by calling sei() within ISR. But this is not the case here, your task does not require nested interrupts.

 In general:

 -keep your ISR short, just toggle flags or increment counters;

 -reset overflow counter every 12 hours;

 -don't mess with I-flag.

 In order to prolong your battery life you consider a deeper sleep mode (eg power-save) and don't forget to turn off your GPS and cellular modules. Use the lowest UART baudrate to keep CPU speed low when awaken.

 


Qoitech AB, The Home of Otii Arc, an SMU for every developer

Check out Otii solution at www.qoitech.com

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanx a lot.

I feel terrible asking the Interrupt to run the CLI command. Effectively asking it to commit suicide.

Code has been updated, and the system seems to run as intended.

 

Two questions remain though ...

1) Is there anything else I can do to bring the power consumption even lower?

    I have only been able to work with the original "SLEEP_MODE_IDLE". No other status will return from sleep.

    Tested statuses are SLEEP_MODE_PWR_SAVE, SLEEP_MODE_PWR_DOWN and SLEEP_MODE_STANDBY

    The GPS unit, the GPRS unit and the Admin interface is powered via a P-channel MOSFET connected to PC0, PC1 and PC2 respectfully.

    The UART baudrate has been set to 9600. That is pretty low and it is the default for GPS unit. The GPRS module is autodetect.

2) I would feel a lot better if I was able to measure the actual power consumption on my board.

    Other web pages suggests buying the "uCurrent Gold" from the EEVblog genious - http://www.eevblog.com/product/u...

    However, it is all out of stock everywhere I look. Do you guys know of any other product I may search for?

 

 

Thank you so much so far.

Kind regards,

Geir Moen

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Geir_Moen wrote:

Also - I have been looking for a place to buy the "uCurrent" designed and produced by the EEVblog genious.
It does not seem to be available anywhere. Is there some replacement you could recommend for me?

 

I bought mine last year from a company here in the UK called Simon's Electronics but their website seems to be broken.

 

It might be worth an email to...

 

simon@simonselectronics.co.uk

 

...which was on my paypal receipt.

 

 

There is also the Atmel Power Debugger but it is a lot more expensive.

 

 

 

"This forum helps those that help themselves."

"How have you proved that your chip is running at xxMHz?" - Me

"If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand." - Heater's ex-boss

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

A couple of things, don't sleep in the ISR() has already been covered.  As for sleep modes, idle is not a low power mode, but a good place to start learning about sleep modes.

For low power, you will need either an external wake up source (RT clock chip works) or use T2 with an external clock chip, 32KHz, and a low power sleep mode.

Care must also be taken on external circuits elements in addition to the mpu itself, i.e.  if measuring external voltages via the ADC, care must be taken with choosing voltage divider resistors

or power lost in the divider will swamp the power used by the mpu. 

Good luck with your project and come back an let us know when you complete it (and lessons learned along the way)....

 

Jim

 

Mission: Improving the readiness of hams world wide : flinthillsradioinc.com

Interests: Ham Radio, Solar power, futures & currency trading - whats yours?

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

1) Sleep modes differ in available clocks and peripherals, hence in wakeup sources. For periodic wakeups from power-save mode Timer2 should be used. Read Power Management and Timer2 sections of datasheet.

2) uCurrent is great, but you still need a multimeter. Not sure if you need Gold though. 324 in power-save would consume tens of uA, no?

 In general minimisation of energy consumption requires systematic approach. It starts with HW design and SW optimnisation. When your schematics are shining and algorithm is perfectly clear, proper choice of sleep mode, unused peripherals etc will be obvious.

 Pay more attention to your programming skills. Check numerous interrupt-driven LED blinking examples, this is more or less the same architecture as your app.

 

 HTH

 

PS Just curious... What is it that moves so slow that it needs location once in 12 hours?

 


Qoitech AB, The Home of Otii Arc, an SMU for every developer

 

Check out Otii solution at www.qoitech.com

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi guys.

Sorry about the slow response.

I switched from TIMER1 to Watchdog, and the "set_sleep_mode (SLEEP_MODE_PWR_DOWN);" works just fine now.

Assuming PWR_DOWN stops normal timers, but leaves WatchDog running...

 

I am using the internal crystal and the 8 x divider. Hoping this will meet the Atmel / Microchip criteria
-------- snippet from datasheet (page 2) ---------
Power Consumption at 1MHz, 1.8V, 25°C

– Active Mode: 0.2mA

– Power-down Mode: 0.1μA

– Power-save Mode: 0.75μA (Including 32kHz RTC)
-------------- end snippet --------------

My circuit will never reach 1.8 volt though.

It is designed to run off of 3 x penlight battery.

When it runs down to 1.8 volt, then it will die when I fire up a Buck converter to deliver 5 Volt, 2 Ampere to the GPRS module

And using another buck converter to produce 1.8 Volt will consume more power than the processor running on 4.5 volt.

 

 

Circuit board has finally been designed and I am waiting for them to be created and shipped back.

One big task left now - to teach myself AutoCad or SolidWorks well enough to create a box for this tracker.

 

Thanx again for your time and knowledge.

I should be able to carry on now.

 

 

Best regards,

Geir Moen

 

 

Yabusame wrote:
PS Just curious... What is it that moves so slow that it needs location once in 12 hours?

This will track large shipments over huge distances.

They don't need to know where it is right now. Only how far it's come and that it is heading in the right direction.

Existing trackers typically report every 24 hours to save battery.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Geir_Moen wrote:
Assuming PWR_DOWN stops normal timers, but leaves WatchDog running...

What does the datasheet say?

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Geir_Moen wrote:

Hi guys.

Sorry about the slow response.

I switched from TIMER1 to Watchdog, and the "set_sleep_mode (SLEEP_MODE_PWR_DOWN);" works just fine now.

Assuming PWR_DOWN stops normal timers, but leaves WatchDog running...

 

I am using the internal crystal and the 8 x divider. Hoping this will meet the Atmel / Microchip criteria
-------- snippet from datasheet (page 2) ---------
Power Consumption at 1MHz, 1.8V, 25°C

– Active Mode: 0.2mA

– Power-down Mode: 0.1μA

– Power-save Mode: 0.75μA (Including 32kHz RTC)
-------------- end snippet --------------

My circuit will never reach 1.8 volt though.

It is designed to run off of 3 x penlight battery.

When it runs down to 1.8 volt, then it will die when I fire up a Buck converter to deliver 5 Volt, 2 Ampere to the GPRS module

And using another buck converter to produce 1.8 Volt will consume more power than the processor running on 4.5 volt.

 

 

 I just thought about two power lines, one with buck converter for high power peripherals, which is turned on and off by the MCU and an LDO to provide 1.8-3.3 V to the MCU itself. But it may make not much sense to have an MCU running if it can not determine and report its position, right?

 Do you monitor battery charge level? How much energy does navigation consume? Are there any more MTC-suitable modems available, like LTE Cat-M/0?

 

Geir_Moen wrote:

 

I should be able to carry on now.

 

 

 Heh... Sure. But if you think that it's over now, well... Abandon thy hope. Start planning version 0.1

 

Geir_Moen wrote:

 

This will track large shipments over huge distances.

They don't need to know where it is right now. Only how far it's come and that it is heading in the right direction.

Existing trackers typically report every 24 hours to save battery.

 

 

 Hmm... Do they really use satellite navigation for that? Does it work inside warehouses and metal containers? Could connect to vehicle's tracker and get at fix from it. Or use intial navigation instead. Or maybe report going in and out warehose gate.

 Nevermind. It suddenly dropped from +3 to -5 outside, just dreaming.

 


Qoitech AB, The Home of Otii Arc, an SMU for every developer

Check out Otii solution at www.qoitech.com

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

theusch wrote:

Geir_Moen wrote:
Assuming PWR_DOWN stops normal timers, but leaves WatchDog running...

What does the datasheet say?

 

 That's exactly what it says, no?

 It'd be interesting to compare this solution to having T2 running in power-save or extended standby. If clocked by something really slow, < 16 kHz, then T2's overflow period will be longer than WDT's 8 sec.

 


Qoitech AB, The Home of Otii Arc, an SMU for every developer

Check out Otii solution at www.qoitech.com

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Also - I have been looking for a place to buy the "uCurrent" designed and produced by the EEVblog genious.
It does not seem to be available anywhere. Is there some replacement you could recommend for me?

 

I would have a look at the Otii for tracking the power consumption. If you don't need to go down into single nanoamps it works great.

 

What GNSS module are you using ?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

theusch wrote:
What does the datasheet say?

The way I read this is that only physical pins for INT0, INT1, TWI ID and WatchDog will be able to wake up from "PWR_DOWN". TIMER1 will not be able to wake it up. This is exactly my experience as well.

But it also shows me that I may disable BOD in the PWR_DOWN mode. I will add this to my power saving procedure. Again, than you so much!

 

Yabusame wrote:
I just thought about two power lines, one with buck converter for high power peripherals, which is turned on and off by the MCU and an LDO to provide 1.8-3.3 V to the MCU itself.

The best LDO I have found consumes 1uA on idle. I'm expecting to save power by connecting the MCU directly to the batteries. Brand new batteries should not exceed 4.8volt, and that is well within the ATmega328's power limit.

 

Yabusame wrote:
Are there any more MTC-suitable modems available, like LTE Cat-M/0?

This is a good idea! I was not aware of this kind of modems. I am currently using a fully functioning modem - "Goouuu Tech Mini IOT-GA6 GPRS GSM Module" - http://www.greenelectronicstore....

... strange. This is the module, but Ebay specs are 5volt power and 3.3volt comm. This is what I use, and it works fine...

 

I will look into the IoT modems you are suggesting.

Transfer speed is not an issue for me.

I will send 72-75 bytes, and receive a ~1K bytes XML file in response.

 

Thanx a lot

 

 

Best regards,

Geir Moen

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Geir_Moen wrote:
The way I read this is that only physical pins for INT0, INT1, TWI ID and WatchDog will be able to wake up from "PWR_DOWN". TIMER1 will not be able to wake it up. This is exactly my experience as well.

Exactly.  No need to assume anything.

 

BTW, add "pin change" to your list.  Note that is [nearly?] every I/O pin on the micro.  INT0/INT1 is quite limited (IMO) for power-down wakeup given that it is only low-level, and the trigger is persistent.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Geir_Moen wrote:
This is the module, but Ebay specs are 5volt power and 3.3volt comm. This is what I use, and it works fine...

 

add a 1k resistor between 328 TXD pin to gps modules RXD pin just to be safe, although it may work for a while like it is......

3.3v input from module will be ok for the 328's RXD pin.

 

 

Jim

 

Mission: Improving the readiness of hams world wide : flinthillsradioinc.com

Interests: Ham Radio, Solar power, futures & currency trading - whats yours?