Interrupt causing reboot

Hi all,

I have a board and code that operate as expected most of the time. It monitors the temperature of hot and cold taps. It uses two signal relays to set the polarity then opens/closes two solenoid valves in order to allow flow for two minutes during temperature sample.

The unit is activated by a radio that grounds interruptPin (2), by high state to bc547 + minature relay. It normally runs off an alkaline pack but result is the same with a bench supply and 5A.

When the unit fails, it fails in the same way if there is a switch between pin 2 and gnd so I don't think the circuit is the fault. The unit can work reliably for days without fail.

The unit should receive activation command, via interrupt to gnd, and run through a 4 minute sequence. When it fails, the interrupt pin is connected to ground and causes the atmega328P-U to reboot instead, then go back to sleep. I fitted an external watchdog circuit to reboot the unit once a day but the failure can continue over a power cycle.

Can anyone see a fault with my code or circuit that may explain this behaviour? Interrupt intermittently causing atmega328 to reboot, rather than continue from the point in the code where it went to sleep.

Many thanks,
Ben

Flush_UART.ino (7.02 KB)

  1. You haven't posted your code in a way that most people can see- check out point #7 here.
  2. You're missing the 0.1uF decoupling capacitors for the VCC and AVCC lines.
  3. It appears that 'RELAY_INT' is a relay that is being driven directly from one of the pins of the ATMega328. It probably draws too much current for that, and it also doesn't have a required back-EMF diode.

Thanks for reply,

  1. this is my code:
#include <math.h>
#include <avr/sleep.h>
#define interruptPin 2 

float vout = 0.0;
float vin = 0.0;
float RV1 = 100000.0; // resistance of R1 (100K)
float RV2 = 10000.0; // resistance of R2 (10K)
int value = 0;

int ThermistorPin = 0;
int Vo;
float R1 = 10000;
float logR2, R2, T, HT, CT;
float c1 = 1.009249522e-03, c2 = 2.378405444e-04, c3 = 2.019202697e-07;

int identifier = 88;

double thePower, tempC = 0, tempP = 0;
int count = 0;
char buffer1[30], buffer2[30];
 
int volt = 99;
int Irms = 999;                                     
int index;
char inchar;
String temp = "";
char pos[80];
 
byte start_with = 0;
byte end_with = 0;
byte CRC = 0;
int b;
float a,y=0;
 
String incomingByte = "";
unsigned int stringLength;
int started = 0;


int l1 = 0;
int l2Pin = 3;
int lPin = 2;
int s1Pin = 13;               
int s2Pin = 12;  
int s3Pin = 11;               
int s4Pin = 10;           
int rbPin = 9;
int pPin = 8;  
int lrPin = 5; 
int lgPin = 6; 
int lbPin = 7;
byte SENSE = 6;

int valve = 0;

void(* resetFunc) (void) = 0;//declare reset function at address 0

void Going_To_Sleep(){
    //Serial.println("Standby");
    delay(1000);
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);      // setting sleep mode (full sleep)
    noInterrupts ();                          // make sure no interrupt before sleep
    sleep_enable();                           // enable sleep mode

    EIFR = bit (INTF0);                       // clear flag for interrupt 0
    
    attachInterrupt(0, wakeUp, FALLING);      // attach an interrupt to pin d2
    delay(1000);                              // wait a second to allow the led to be turned off before going to sleep
    interrupts ();                            // interrupts allowed now, next instruction WILL be executed
    sleep_cpu();                              // activate sleep mode
    sleep_disable();                          // disable sleep mode (next line of code executed after the interrupt)
}

void wakeUp(){
  detachInterrupt(0); //Removes the interrupt from pin 2;
}

void takeRead(){
  Vo = analogRead(ThermistorPin);
  R2 = R1 / (1023.0 / (float)Vo - 1.0);
  logR2 = log(R2);
  T = (1.0 / (c1 + c2*logR2 + c3*logR2*logR2*logR2));
  T = T - 273.15;
}
 
void setup() {
  pinMode(lPin, OUTPUT);
  pinMode(s1Pin, OUTPUT);
  pinMode(s2Pin, OUTPUT);
  pinMode(s3Pin, OUTPUT);
  pinMode(s4Pin, OUTPUT);
  pinMode(rbPin, OUTPUT);
  pinMode(pPin, OUTPUT);
  pinMode(lbPin, OUTPUT);
  pinMode(lgPin, OUTPUT);
  pinMode(lrPin, OUTPUT);
  digitalWrite(lPin, LOW);
  digitalWrite(s1Pin, LOW);
  digitalWrite(s2Pin, LOW);
  digitalWrite(s3Pin, LOW);
  digitalWrite(s4Pin, LOW);
  digitalWrite(pPin, LOW);
  digitalWrite(rbPin, LOW);
  digitalWrite(lbPin, HIGH);
  digitalWrite(lgPin, HIGH);
  digitalWrite(lrPin, HIGH);
  pinMode(interruptPin,INPUT_PULLUP);  

  Serial.begin(115200);
  delay(1000);
  for (int i=0; i < 3; i++){               
    digitalWrite(lgPin, LOW);
    delay(800);
    digitalWrite(lgPin, HIGH);
    delay(400);
  }
  
  digitalWrite(s1Pin, LOW);                 // config solenoid 1 closed
  digitalWrite(s2Pin, HIGH);
  digitalWrite(s3Pin, LOW);                 // config solenoid 2 closed
  digitalWrite(s4Pin, HIGH);
  delay(10);
  digitalWrite(s1Pin, LOW);
  digitalWrite(s2Pin, LOW);
  digitalWrite(s3Pin, LOW);
  digitalWrite(s4Pin, LOW);

  delay(10); 
  digitalWrite(pPin, HIGH);                 // power solenoid
  delay(50);              
  digitalWrite(pPin, LOW);
}
 
void loop() { 

    Going_To_Sleep();
                                              // *HOT* //
    valve = 1;
    digitalWrite(s1Pin, HIGH);                // config solenoid
    digitalWrite(s2Pin, LOW);
    delay(10);
    digitalWrite(s1Pin, LOW);
    digitalWrite(s2Pin, LOW); 
    
    delay(10);   
    digitalWrite(pPin, HIGH);                 // power solenoid
    delay(50);              
    digitalWrite(pPin, LOW);
 
    for (int i=0; i < 92; i++){               // 46 blinks = 1 minute     
      digitalWrite(lrPin, LOW);
      delay(1200);
      digitalWrite(lrPin, HIGH);
      digitalWrite(lgPin, LOW);
      delay(100);
      digitalWrite(lgPin, HIGH);
    }
    
    takeRead();
    HT = T;
    //Serial.print(" T "); 
    //Serial.println("52.7");
 
    digitalWrite(s1Pin, LOW);                 // config solenoid
    digitalWrite(s2Pin, HIGH);
    delay(10);
    digitalWrite(s1Pin, LOW);
    digitalWrite(s2Pin, LOW);
 
    delay(10); 
    digitalWrite(pPin, HIGH);                 // power solenoid
    delay(50);              
    digitalWrite(pPin, LOW);
 
    digitalWrite(lPin, LOW);
   
    for (int i=0; i < 10; i++){               // led fush 1 complete
      
      digitalWrite(lrPin, LOW);
      delay(300);
      digitalWrite(lrPin, HIGH);
      delay(100);
    }

    delay(1000);
                                              // *COLD* //
    valve = 0;
    digitalWrite(s3Pin, HIGH);                // config solenoid
    digitalWrite(s4Pin, LOW);
    delay(10);
    digitalWrite(s3Pin, LOW);
    digitalWrite(s4Pin, LOW); 
    
    delay(10);   
    digitalWrite(pPin, HIGH);                 // power solenoid
    delay(50);              
    digitalWrite(pPin, LOW);
 
    for (int i=0; i < 96; i++){               
      digitalWrite(lbPin, LOW);
      delay(1200);
      digitalWrite(lbPin, HIGH);
      digitalWrite(lgPin, LOW);
      delay(100);
      digitalWrite(lgPin, HIGH);
    }                         

    takeRead();  
    CT = T;
    //Serial.print(" T "); 
    //Serial.println("17.8");
 
    digitalWrite(s3Pin, LOW);                 // config solenoid
    digitalWrite(s4Pin, HIGH);
    delay(10);
    digitalWrite(s3Pin, LOW);
    digitalWrite(s4Pin, LOW);
 
    delay(10); 
    digitalWrite(pPin, HIGH);                 // power solenoid
    delay(50);              
    digitalWrite(pPin, LOW);
 
    digitalWrite(lPin, LOW);
   
    for (int i=0; i < 10; i++){               // led fush 2 complete      
      digitalWrite(lbPin, LOW);
      delay(300);
      digitalWrite(lbPin, HIGH);
      delay(100);
    }
   
    for (int i=0; i < 30; i++){               // led fush sequence complete
      digitalWrite(lgPin, LOW);
      delay(80);
      digitalWrite(lgPin, HIGH);
      delay(80);
    }

    value = analogRead(1);
    vout = (value * 5.18) / 1024.0; // see text
    vin = vout / (RV2/(RV1+RV2)); 
    if (vin<0.09) {
      vin=0.0;                                // ignore undesired reading
    } 
    //Serial.print("EXTPW ");
    //Serial.print(vin);
    //Serial.println("V");

    Serial.print(HT);
    Serial.print(",");
    Serial.print(CT);
    Serial.print(",");
    Serial.println(vin);
    
    delay(800);   

    Serial.flush();
    Serial.end();
    digitalWrite(rbPin, HIGH);                // power cycle tag
    delay(5000);                     
    digitalWrite(rbPin, LOW);
    Serial.begin(115200);
    delay(1000);
    resetFunc();                              // call reset
}
  1. As VCC and AVCC are connected, I've added a 0.1uf cap between VCC and GND.

  2. Omron G6K uses 21.1mA at 5V. I have added a 1N4007 flyback diode across relay.

There seems to be two relays in that circuit. So each one needs a diode. It is rather difficult to follow circuit. It would be easier if the relay contacts were drawn conventionally and the wiring not all over the place.

hackysack:
Thanks for reply,
2. As VCC and AVCC are connected, I've added a 0.1uf cap between VCC and GND.

You should have a capacitor for each VCC and AVCC pin.

hackysack:
3. Omron G6K uses 21.1mA at 5V. I have added a 1N4007 flyback diode across relay.

That looks like a good choice for a relay. Now that you've added a diode, what happens?

Grumpy_Mike:
It is rather difficult to follow circuit. It would be easier if the relay contacts were drawn conventionally and the wiring not all over the place.

OP, this is excellent advice. Some rearranging of the components would make this much easier to understand.

Thanks. Ok, will add another capacitor. Two of the relays are latched and used to invert the polarity that is supplied to the solenoid valves (open/close). So no standard +'ve/-'ve.

  1. Should I be adding flyback diodes to BOTH power/gnd pins, for these two latching relays? Would they still work ok?

  2. Is the 1N4007 acceptable for these flyback diodes?

  3. Why are there no 0.1uf caps on the ArduinoToBreadboard guide?

Not working yet, relays are not fused. I will replace the relays in case though.

New circuit attached. I have not been able to sort the flyback diodes for the latching relays, as they switch by inverting the supply polarity, rather than switching from pulses in one polarity.

I have been reading about hbridges and TVS diodes but some of it is beyond me.

Is there a simpler way to do this? Protect the relays from spikes without putting the flyback diode across the supply pins?

Maybe something like attachment 2..

Thanks for advice.

2.jpg

Can you tell us please the part number of your latching relay.

G6SU-2-DC5 (Omron). Thanks

en-g6s-1128313.pdf (1.82 MB)

You can't drive those coils directly from an Arduino pin because they take 40mA, which is the point where damage starts to occur to the Arduino's pins.

This part of the circuit puts a short on the power supply every time the relay is triggered. This will look like a reboot because as soon as the short happens the power is removed then the power is restored and the processor boots up again.

short.png

short.png