atMega328P reboots itself continuously

Hi all,

For my project I'm facing an issue. The atMega328P reboots itself continuously(so it can't run it's code).

I have

  • NRF24L01 set up as transmitter (with 10uF capacitor on Vcc / ground)
  • 2x AA 2500mAh rechargeable batteries (Panasonic Eneloop) (2,4-2,5V in total)
  • 1x atMega328p (8MHz
  • 1x LED (which is used as power indicator, if you turn on the device it will be ON for 2 seconds and then turn OFF)

Technical details
Power consumption in standby: 0.02mA
Power consumption on transmitting: 7mA
How much used: daily base around 20 times for a couple of seconds.

With this details, I did assume my setup could run for at least a year

So currently I'm testing this project, it did run for around 2 weeks fine. After that the power indicator started blinking like it was continuously booting..Resetting gave the same results. When measuring the voltage, it was still 2.4V.
However, giving the batteries a bit of charge and putting them back in, seemed to fix it. But how can this happen?

Currently I'm performing the same test, but using 2x alkaline (1,5V). Not sure if it will fix the problem, since it runs for around a week now.

Is there something wrong in my code?

The receiver is DC powered, so I think only the transmitter code will do;

/* 
 === file: THE BULB SoLooTion SYSTEM
 === version: V7.0
 === last update: 22-07-20

 === notes: transmitterCode

 === www.thebulb.nl

*/

 
#include <LowPower.h>
#include <avr/sleep.h>
#include <avr/power.h>
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <RF24Network.h>

RF24 radio(9, 10); // CE, CSN

//enable this package if it's the ladies version

struct package
{
  int id=1;                   //id for ladies (1,2,3,4,5) id for gents (6,7,8,9,10) ; choose a desired ID
  byte toiletStatus = 2;      //2 = occupied ladies, 5 = occupied gents   
  char dataToSend ='1';        //auto-increment txNum
};

//enable this package if it's the gents version
/*
struct package
{
  int id=6;                   //id for ladies (1,2,3,4,5) id for gents (6,7,8,9,10); choose a desired ID
  byte toiletStatus = 5;      //2 = occupied ladies, 5 = occupied gents   
  char dataToSend ='1';       //auto-increment txNum
};
*/

char dataToSend = '1';

typedef struct package Package;
Package data;

byte addresses[][6] = {"0"};

const byte ledPin = 8; //debug only
const byte interrupt_pin = 2;   

unsigned long interval = 1000;

volatile byte state = LOW;

void wake(){
  // cancel sleep as a precaution
  sleep_disable();
  // precautionary while we do other stuff
  detachInterrupt (0);        // gents
  detachInterrupt (1);         // ladies
}  // end of wake

void setup() {
  Serial.begin(9600); //temp 
  pinMode(ledPin, OUTPUT); 
  pinMode(interrupt_pin, INPUT);

  for (int i = 0; i < 20; i++) {
  if(i != 2)//just because the button is hooked up to digital pin 2
  pinMode(i, OUTPUT);
    }

   clock_prescale_set(clock_div_256);

  //Disable ADC - don't forget to flip back after waking up if using ADC in your application ADCSRA |= (1 << 7);
  ADCSRA &= ~(1 << 7);

  //ENABLE SLEEP - this enables the sleep mode
  SMCR |= (1 << 2); //power down mode
  SMCR |= 1;//enable sleep
  
  //DISABLE BOD
  MCUCR |= (3 << 5); //set both BODS and BODSE at the same time
  MCUCR = (MCUCR & ~(1 << 5)) | (1 << 6); //then set the BODS bit and clear the BODSE bit at the same time

  //SET CLOCK PROCESSOR
  CLKPR = 0x80;
  CLKPR = 0x01;
  
  radio.begin();
  radio.openWritingPipe( addresses[0]);
  radio.setRetries(3, 5);
  radio.setChannel(115); 
  radio.setPALevel(RF24_PA_MAX);
  radio.setDataRate( RF24_250KBPS ) ; 
  radio.stopListening();

  //boot light indicator
  digitalWrite(ledPin, HIGH);
  delay (2000);
  digitalWrite(ledPin, LOW);  
}

void loop() {

  ADCSRA = 0;
  
  // the interrupt must be attached each loop
  attachInterrupt(digitalPinToInterrupt(interrupt_pin),interrupt_routine,RISING);
  LowPower.powerDown(SLEEP_FOREVER,ADC_OFF,BOD_OFF); // sleep until interrupt
  detachInterrupt(digitalPinToInterrupt(interrupt_pin)); // remove interrupt
  
  // the usual wake routine that turns on the LED
  if (state==HIGH){
    send();
    delay(250);
  }
  
  if (state==HIGH){
    state = LOW;
    digitalWrite(ledPin,LOW);
    attachInterrupt(digitalPinToInterrupt(interrupt_pin),interrupt_routine,RISING);
    delay(interval);
  }
}

void interrupt_routine(){
  state = HIGH;
}

void send(){ 

  radio.write(&data, sizeof(data)); 

  Serial.print("\n");  
  Serial.print("\nID:");
  Serial.print(data.id);
  Serial.print("\nToilet status:");
  Serial.print(data.toiletStatus);
  Serial.print("\nUnique number:");
  Serial.print(data.dataToSend);

    data.id = data.id;

    data.toiletStatus = data.toiletStatus;
    
    data.dataToSend = dataToSend +=1;
      if (dataToSend >= '6'){
        dataToSend = '0';
    }
  delay(100);

}

Here is the schematic, be aware!! I'M NOT USING AN ADAFRUIT PIR OR SIMILAR.
Instead I use the best PIR that exists in my opinion; the Panasonic EKMB series.
In my setup I use the EKMB12... range which consumes ultra-low power.

Oh and sorry, I forgot to draw one component. I use a 10uF capacitor on Vin and GND of the NRF24L01

  • 2x AA 2500mAh rechargeable batteries (Panasonic Eneloop) (2,4-2,5V in total)

With this details, I did assume my setup could run for at least a year

Assuming you mean NiMh, they self discharge in a lot less than a year, maybe good for a month.

I've not checked the minimum operating voltage for an atMega328p but are you sure they will work on 2V4, or less when the batteries start to discharge?

To find out why it restarts put serial prints in parts of the code to indicate where it's getting to.

Hi PerryBebbington,

Thank you for your reply.
I will add some more serial prints.

The minimum operating voltage for the atmega is 1.9v, same as for the NRF24L01

The batteries have a low self discharge, they should work for quite some time.

OK.
I don't know why it restarts. If there is something in the code I leave that for someone else.

Are you using breadboard? I am thinking maybe when the transmitter is on it draws too much current through a dodgy breadboard connection and the voltage drops.

The 328P can only run at 4MHz if the voltage is 1.9V. It's a bit difficult to judge from the datasheet what it can do at 2.4V; it's somewhere between 4MHz and 10MHz.

How do you measure the batteries? Not sure if it applies to your type of batteries but 'empty' batteries usually measure the specified voltage but collapse under load.

Hi,
Can you please post a circuit diagram and include your batteries and where you have them connected to the MEGA.

I hope the 5V pin and not Vin.
Vin is for power supplies 7V to 12V and connects to a linear 5V regulator.

Thanks.. Tom... :slight_smile:

@TomGeorge

Where do you get Mega from?

A couple of things that look peculiar but probably won't be the cause your restart problems.

This look silly

    data.id = data.id;

    data.toiletStatus = data.toiletStatus;

and should not

 // precautionary while we do other stuff
  detachInterrupt (0);        // gents
  detachInterrupt (1);         // ladies

use digitalPinToInterrupt() rather than the magic numbers 0 and 1 !

sterretje:
@TomGeorge

Where do you get Mega from?

Brain fade, not taken my meds, to much blood in the coffee stream,
But the question is still valid until we see a schematic.
Tom... :slight_smile:

darthvader072:
Hi PerryBebbington,

Thank you for your reply.
I will add some more serial prints.

The minimum operating voltage for the atmega is 1.9v, same as for the NRF24L01

The minimum operating voltage depends on the fuse settings for the BOD, which is for
standard arduino board settings 2.7V normally

The batteries have a low self discharge, they should work for quite some time.

They would be hybrid NiMH then?

The Speed Grade chart in the datasheet shows 2.4V to be the minimum for running at 8 MHz.
Below that, all bets are off.
8 MHz is 2/3 of the way between 4 and 10 MHz, and 2.4V is 2/3 of the way between 1.8 and 2.7V.

  • 2x AA 2500mAh rechargeable batteries (Panasonic Eneloop)

The batteries have a low self discharge, they should work for quite some time.

Those are new to me, very interested to know how well they perform in the real world, rather than taking Panasonic's word for it.
Panasonic Eneloop

PerryBebbington:
Those are new to me, very interested to know how well they perform in the real world, rather than taking Panasonic's word for it.
Panasonic Eneloop

You can ask Pentax camera users :wink: Eneloops have for a looooong time been the advised battery for e.g. de Pentax K100D (which saw the light in 2006 or so).

Hi,
Are there any bypass capacitors in the circuit?
Have you built this on a custom PCB?

If so can you post some CAD images of the PCB please?

Tom... :slight_smile:

Hi all,

Thanks for the many replies, did not see that coming.

TomGeorge:

It's a custom PCB, prototype cardboard PCB (so not fabricated or anything else), since this is the prototype.
I've attached schematic in original post!

Be aware, I'm not using the Adafruit PIR.

CrossRoads:

I'm aware of the MHz and relation to Voltage, I do believe I should be good since my atMega's run on 8MHz

I'm still testing daily, waiting till it happens again, hopefully I can share a vid then
I recently discovered the 26650 battery which perhaps is the best for what I want. Rather I'll stick with 2xAA

sterretje:
The 328P can only run at 4MHz if the voltage is 1.9V. It's a bit difficult to judge from the datasheet what it can do at 2.4V; it's somewhere between 4MHz and 10MHz.

How do you measure the batteries? Not sure if it applies to your type of batteries but 'empty' batteries usually measure the specified voltage but collapse under load.

I do use an regular multimeter, measure the voltage coming into the atMega, and 2nd measurement on the Vin and GND of the NRF24L01.

And that is measured while the system is not sleeping?

sterretje:
And that is measured while the system is not sleeping?

Not sure actually, BUT since I'm holding the device in my hands (it's like the size of a small wallet) the PIR is probably activated. I'm expecting a power failure at the beginning of next week, so I'll measure when the device is sleeping and when active

I believe MarkT is right. As the batteries discharge, and particularly when transmitting, you're bumping up against the brown-out detector. The BOD trigger voltage is part of the fuse settings, and by default that's set at 2.7V on Arduinos. If you're using a bare 328P chip, then I don't know how those come from the factory, but if you've burned a bootloader to it, that would include the default Arduino fuse settings.