attiny84 freezing

hi there

I have a attiny84 on a PCB that I have had made but every now and then it seems to just freeze midway through the loop. This may only happen once every four ,five weeks. Any ideas which may be causing this?
The power feed comes in through a 1000UF cap into L7805ABV volt regulator out through 33UF cap then into 0.1 UF cap
All inputs are optically isolated.
All outputs go into a ULN2803A transistor which in turn powers coils of relays .
This unit is inside a metre square panel which is full of 3 phase kit which in turn could be noisy.
On the other hand there's other printed circuits in there working fine.

While you seem to be considering all the sources of hardware-based errors, what about a software error?
Can you post your code?

Hi, have you got the attiny and it circuitry shielded, or in a metal case?
Do you have a 0.1uF cap across the power supply pins of the attiny itself? (soldered right at the IC pins)
It sounds like you have not got enough bypassing, the optos are certainly a good idea.
A pic of your project and a circuit diagram would be great, even a pic of a hand drawn circuit.

Hope we can help....Tom..... :slight_smile:

You don't mention the reset pin.
Put a 10kohm resistor from the reset pin to +5V. What you see is maybe autoresetting

While you seem to be considering all the sources of hardware-based errors, what about a software error?
Can you post your code?

I know it cant be code issues as it was heavily tested before putting into service and I have 60 of these out there now working for approx 6-12 months all seem to be fine apart from these odd few

Hi, have you got the attiny and it circuitry shielded, or in a metal case?
Do you have a 0.1uF cap across the power supply pins of the attiny itself? (soldered right at the IC pins)
It sounds like you have not got enough bypassing, the optos are certainly a good idea.
A pic of your project and a circuit diagram would be great, even a pic of a hand drawn circuit.

Yes I do have a 0.1 UF very close to the attiny
I will get some pics up very soon
All cables into the board are screened and earthed

You don't mention the reset pin.
Put a 10kohm resistor from the reset pin to +5V. What you see is maybe autoresetting

no I don't have anything attached to reset pin this may be my problem I will give it a try

thanks for all your help

hi there I said I would post a pic and here we go

but I'm still having issues with it freezing so doe's any one have other suggesting?
only doing it about every 3-4 weeks

HI, thanks for your replies to our questions, do you test/measure the 1000uF caps before you fit them. It could be a low batch of caps, I'd be using a 2200uF for a 1A supply, to help load spikes from the relays.
Only a suggestion, as you say it is not consistent, just consistently intermittent.

Tom...... :slight_smile:

hi there no I don't text them but when I'm next at site I will and we will see what we have
thanks again
Joe

Just out of curiosity... are you using functions like millis()? since they could have a loop around issue?

hi there I have test the caps and they seem fine
here is the code

---------------------------------------------
Set heater1 to match HeatIn1.
 
 If HeatIn1 is low and reverse is high:
 delay 30sec 
 write heater1R high 
 delay 10sec 
 write heater1R low 
 delay 30sec
 Wait for HeatIn1 to come on
 
 Set heater2 to match HeatIn2.
 
 If HeatIn2 is low and reverse is high:
 delay 30sec 
 write heater2R high 
 delay 10sec 
 write heater2R low 
 delay 30sec
 Wait for HeatIn1 to come on
 
 if HeatIn1 or HeatIn2 are high:

 delay 5sec
 write pump high (Start pump)
 
 if HeatIn1 and HeatIn2 have been low for a full 30 minutes:

 write pump low (Stop pump)
 
 If overload 1 or 2 are high 
 write LED high 
 */

//         ***  INPUT'S  ***
const int HeatIn1   =  7;    // input from PC 1
const int HeatIn2   =  8;    // input from PC 2
const int overload1 =  9;    // overload cut out 1
const int overload2 = 10;    // overload cut out 2
const int reverse   =  6;   // reverse swich for heat's

//          *** OUTPUT'S  ***
const int valve     =  11;    // valve in pooler room       // not being used
const int LED       =  5;    // lock out led
const int pump      =  4;    //  pump in pooler room
const int heater1   =  3;    // heater 1 output forwch 
const int heater1R  =  2;    // heater 1 output revus
const int heater2   =  1;    // heater 2 output forwch 
const int heater2R  =  0;    // heater 2 output revus



void setup()
{
  //        ***  OUTPUT'S  ***
  pinMode(valve   ,    OUTPUT);
  pinMode(LED     ,    OUTPUT);
  pinMode(pump    ,    OUTPUT);
  pinMode(heater1 ,    OUTPUT);
  pinMode(heater1R,    OUTPUT);
  pinMode(heater2 ,    OUTPUT);
  pinMode(heater2R,    OUTPUT);


  //        ***  INPUT'S  ***
  pinMode(HeatIn1,     INPUT);
  pinMode(HeatIn2,     INPUT);
  pinMode(reverse,     INPUT);
  pinMode(overload1,   INPUT);
  pinMode(overload2,   INPUT);

}
enum LoopOneStates {
  Heating, NotHeating, ReverseMode, ReverseModeOn,  ReverseModeOff, WaitingToHeat};

enum LoopTwoStates {
  EitherHot, OpenValve, StartPump, NeitherHot,  CloseValveStopPump};

void loop() {
  unsigned long currentTime = millis();
  
  //  LoopOne for Heater 1
if (digitalRead(overload1)) {
  static enum LoopOneStates state1 = Heating;
  static unsigned long state1EntryTime = 0;
  switch (state1) {
  case Heating:
    digitalWrite(heater1, HIGH);
    if (!digitalRead(HeatIn1))
      state1 = NotHeating;
    break;

  case NotHeating: 
    digitalWrite(heater1, LOW);
    if (digitalRead(reverse)) {
      state1 = ReverseMode;
      state1EntryTime = currentTime;
    }
    if (digitalRead(HeatIn1))
      state1 = Heating;
    break;

  case ReverseMode:
    if (currentTime - state1EntryTime > 30000) {
      digitalWrite(heater1R, HIGH);
      state1 = ReverseModeOn;
      state1EntryTime = currentTime;
    }
    break;

  case ReverseModeOn:
    if (currentTime - state1EntryTime > 10000) {
      digitalWrite(heater1R, LOW);
      state1 = ReverseModeOff;
      state1EntryTime = currentTime;
    }
    break;

  case ReverseModeOff:
    if (currentTime - state1EntryTime > 30000) {
      state1 = WaitingToHeat;
    }
    break;

  case WaitingToHeat:
    if (digitalRead(HeatIn1)) {
      state1 = Heating;
    }
    break;
  }
}
else {
  digitalWrite(heater1,  LOW);
  digitalWrite(heater1R, LOW);
}


  //  LoopOne for Heater 2
  if (digitalRead(overload2)) {
  static enum LoopOneStates state2 = Heating;
  static unsigned long state2EntryTime = 0;
  switch (state2) {
  case Heating:
    digitalWrite(heater2, HIGH);
    if (!digitalRead(HeatIn2))
      state2 = NotHeating;
    break;

  case NotHeating: 
    digitalWrite(heater2, LOW);
    if (digitalRead(reverse)) {
      state2 = ReverseMode;
      state2EntryTime = currentTime;
    }
    if (digitalRead(HeatIn2))
      state2 = Heating;
    break;

  case ReverseMode:
    if (currentTime - state2EntryTime > 30000) {
      digitalWrite(heater2R, HIGH);
      state2 = ReverseModeOn;
      state2EntryTime = currentTime;
    }
    break;

  case ReverseModeOn:
    if (currentTime - state2EntryTime > 10000) {
      digitalWrite(heater2R, LOW);
      state2 = ReverseModeOff;
      state2EntryTime = currentTime;
    }
    break;

  case ReverseModeOff:
    if (currentTime - state2EntryTime > 30000) {
      state2 = WaitingToHeat;
    }
    break;

  case WaitingToHeat:
    if (digitalRead(HeatIn2)) {
      state2 = Heating;
    }
    break;

  }
  }
else {
  digitalWrite(heater2,  LOW);
  digitalWrite(heater2R, LOW);
}

  //                                                        **loop two**
  //  LoopOne for Heater 1
  static enum LoopTwoStates state3 = EitherHot;
  static unsigned long state3EntryTime = 0;
  switch (state3) {
  case EitherHot:
    if (digitalRead(HeatIn1) || digitalRead(HeatIn2)) {
      state3 = OpenValve;
      state3EntryTime = currentTime;
    }
    break;

  case OpenValve:
    digitalWrite(valve, HIGH);
    // Fifteen seconds later, starty the pump
    if (currentTime - state3EntryTime > 5000) {
      state3 = StartPump;
      state3EntryTime = currentTime;
    }
    break;

  case StartPump:
    digitalWrite(pump, HIGH);
    state3 = NeitherHot;
    state3EntryTime = currentTime;
    break;

  case NeitherHot:
    // Wait for a full 30 minutes with neither heat indicators on
    if (digitalRead(HeatIn1) || digitalRead(HeatIn2)) {
      // Reset the timer if either heater is on
      state3EntryTime = currentTime;
    }
    if (currentTime - state3EntryTime > 1000UL*60UL*30UL) {
      state3 = CloseValveStopPump;
    }
    break;

  case CloseValveStopPump:
    digitalWrite(valve,       LOW);
    digitalWrite(pump,        LOW);
    state3 = EitherHot;
    break;
  }
  //     Lock out LED
  if (!digitalRead(overload1) || !digitalRead(overload2)) {
     digitalWrite(LED,     HIGH); 
  }
     else {
     digitalWrite(LED,     LOW);    
  } 
}

Hi, can you post a copy either CAD or picture of hand drawn circuit diagram, jpg, png or pdf, thank you.

Tom....... :slight_smile:

Joes:
I have a attiny84 on a PCB that I have had made but every now and then it seems to just freeze midway through the loop. This may only happen once every four ,five weeks. Any ideas which may be causing this?

millis() wraps around to 0 every 49 days...

If you really can't find the problem it then this is what the watchdog timer is for - reset the chip if it locks up.

my money is on the 3 phase you have near the unit, i made a unit which has 2 328's measuring 3phase and boy did the 328's play up they froze / locked up just like yours are i tryed opto isolators made no change still froze, i tryed removing the gnd fill on my board made no difference i nearly went insane tyring out how to cure it, eventually i had to remove the board from the 3 phase altogether, and had a sensor on the end of a screened 2 core cable which worked.

it looks like yopu have many antenna's that go into your unit as well ie wires that will also pick up noise as well you could try to use screened cable for both 3 phase and your wires you could also try to putting your unit in a metal box, and maby use external pull up r's stronger like 5 to 10k think the internal r's are like 30/40k ish, can you move your unit and associated wires away from the 3 phase?

(to prove it is the 3 phase put the 3 phase wires right next to your unit (better still put wires on top of the 328) and try to make some noise like switching on/off the 3 phase im sure its the 3 phase)

a long shot, maby its a duff 328 or regulator, my money is on the 3 phase good luck

hi there thanks for all your feedback
yes I would agree it is the 3 phase what is playing me up, still having issues so I am all out of ideas?

I have look into the watchdog timer but just seem to reset like every 10s so I don't no if I have dun something wrong?

//         ***  INPUT'S  ***
const int HeatIn1   =  7;    // input from PC 1
const int HeatIn2   =  8;    // input from PC 2
const int overload1 =  9;    // overload cut out 1
const int overload2 = 10;    // overload cut out 2
const int reverse   =  6;   // reverse swich for heat's

//          *** OUTPUT'S  ***
const int valve     =  11;    // valve in pooler room       // not being used
const int LED       =  5;    // lock out led
const int pump      =  4;    //  pump in pooler room
const int heater1   =  3;    // heater 1 output forwch 
const int heater1R  =  2;    // heater 1 output revus
const int heater2   =  1;    // heater 2 output forwch 
const int heater2R  =  0;    // heater 2 output revus


#include <avr/wdt.h>

unsigned long resetTime = 0;
#define TIMEOUTPERIOD 10000             // You can make this time as long as you want,
                                       // it's not limited to 8 seconds like the normal
                                       // watchdog
#define doggieTickle() resetTime = millis();  // This macro will reset the timer
void(* resetFunc) (void) = 0; //declare reset function @ address 0

void watchdogSetup()
{
cli();  // disable all interrupts
wdt_reset(); // reset the WDT timer
MCUSR &= ~(1<<WDRF);  // because the data sheet said to
/*
WDTCSR configuration:
WDIE = 1 :Interrupt Enable
WDE = 1  :Reset Enable - I won't be using this on the 2560
WDP3 = 0 :For 1000ms Time-out
WDP2 = 1 :bit pattern is 
WDP1 = 1 :0110  change this for a different
WDP0 = 0 :timeout period.
*/
// Enter Watchdog Configuration mode:
WDTCSR = (1<<WDCE) | (1<<WDE);
// Set Watchdog settings: interrupte enable, 0110 for timer
WDTCSR = (1<<WDIE) | (0<<WDP3) | (1<<WDP2) | (1<<WDP1) | (0<<WDP0);
sei();
}


ISR(WDT_vect) // Watchdog timer interrupt.
{ 
  if(millis() - resetTime > TIMEOUTPERIOD){
  doggieTickle();                                          // take these lines out
  resetFunc();     // This will call location zero and cause a reboot.
  }
}


void setup()
{
  watchdogSetup();
  //        ***  OUTPUT'S  ***
  pinMode(valve   ,    OUTPUT);
  pinMode(LED     ,    OUTPUT);
  pinMode(pump    ,    OUTPUT);
  pinMode(heater1 ,    OUTPUT);
  pinMode(heater1R,    OUTPUT);
  pinMode(heater2 ,    OUTPUT);
  pinMode(heater2R,    OUTPUT);


  //        ***  INPUT'S  ***
  pinMode(HeatIn1,     INPUT);
  pinMode(HeatIn2,     INPUT);
  pinMode(reverse,     INPUT);
  pinMode(overload1,   INPUT);
  pinMode(overload2,   INPUT);

}

int firstTime = true;

enum LoopOneStates {
  Heating, NotHeating, ReverseMode, ReverseModeOn,  ReverseModeOff, WaitingToHeat};

enum LoopTwoStates {
  EitherHot, OpenValve, StartPump, NeitherHot,  CloseValveStopPump};

void loop() {
    if (firstTime){
    firstTime = false;
  }
  if(millis() - resetTime > 2000){
    doggieTickle();  // if you uncomment this line, it will keep resetting the timer.
  }
  
  
  unsigned long currentTime = millis();
  
  //  LoopOne for Heater 1
if (digitalRead(overload1)) {
  static enum LoopOneStates state1 = Heating;
  static unsigned long state1EntryTime = 0;
  switch (state1) {
  case Heating:
    digitalWrite(heater1, HIGH);
    if (!digitalRead(HeatIn1))
      state1 = NotHeating;
    break;

  case NotHeating: 
    digitalWrite(heater1, LOW);
    if (digitalRead(reverse)) {
      state1 = ReverseMode;
      state1EntryTime = currentTime;
    }
    if (digitalRead(HeatIn1))
      state1 = Heating;
    break;

  case ReverseMode:
    if (currentTime - state1EntryTime > 30000) {
      digitalWrite(heater1R, HIGH);
      state1 = ReverseModeOn;
      state1EntryTime = currentTime;
    }
    break;

  case ReverseModeOn:
    if (currentTime - state1EntryTime > 10000) {
      digitalWrite(heater1R, LOW);
      state1 = ReverseModeOff;
      state1EntryTime = currentTime;
    }
    break;

  case ReverseModeOff:
    if (currentTime - state1EntryTime > 30000) {
      state1 = WaitingToHeat;
    }
    break;

  case WaitingToHeat:
    if (digitalRead(HeatIn1)) {
      state1 = Heating;
    }
    break;
  }
}
else {
  digitalWrite(heater1,  LOW);
  digitalWrite(heater1R, LOW);
}


  //  LoopOne for Heater 2
  if (digitalRead(overload2)) {
  static enum LoopOneStates state2 = Heating;
  static unsigned long state2EntryTime = 0;
  switch (state2) {
  case Heating:
    digitalWrite(heater2, HIGH);
    if (!digitalRead(HeatIn2))
      state2 = NotHeating;
    break;

  case NotHeating: 
    digitalWrite(heater2, LOW);
    if (digitalRead(reverse)) {
      state2 = ReverseMode;
      state2EntryTime = currentTime;
    }
    if (digitalRead(HeatIn2))
      state2 = Heating;
    break;

  case ReverseMode:
    if (currentTime - state2EntryTime > 30000) {
      digitalWrite(heater2R, HIGH);
      state2 = ReverseModeOn;
      state2EntryTime = currentTime;
    }
    break;

  case ReverseModeOn:
    if (currentTime - state2EntryTime > 10000) {
      digitalWrite(heater2R, LOW);
      state2 = ReverseModeOff;
      state2EntryTime = currentTime;
    }
    break;

  case ReverseModeOff:
    if (currentTime - state2EntryTime > 30000) {
      state2 = WaitingToHeat;
    }
    break;

  case WaitingToHeat:
    if (digitalRead(HeatIn2)) {
      state2 = Heating;
    }
    break;

  }
  }
else {
  digitalWrite(heater2,  LOW);
  digitalWrite(heater2R, LOW);
}

  //                                                        **loop two**
  //  LoopOne for Heater 1
  static enum LoopTwoStates state3 = EitherHot;
  static unsigned long state3EntryTime = 0;
  switch (state3) {
  case EitherHot:
    if (digitalRead(HeatIn1) || digitalRead(HeatIn2)) {
      state3 = OpenValve;
      state3EntryTime = currentTime;
    }
    break;

  case OpenValve:
    digitalWrite(valve, HIGH);
    // Fifteen seconds later, starty the pump
    if (currentTime - state3EntryTime > 5000) {
      state3 = StartPump;
      state3EntryTime = currentTime;
    }
    break;

  case StartPump:
    digitalWrite(pump, HIGH);
    state3 = NeitherHot;
    state3EntryTime = currentTime;
    break;

  case NeitherHot:
    // Wait for a full 30 minutes with neither heat indicators on
    if (digitalRead(HeatIn1) || digitalRead(HeatIn2)) {
      // Reset the timer if either heater is on
      state3EntryTime = currentTime;
    }
    if (currentTime - state3EntryTime > 1000UL*60UL*30UL) {
      state3 = CloseValveStopPump;
    }
    break;

  case CloseValveStopPump:
    digitalWrite(valve,       LOW);
    digitalWrite(pump,        LOW);
    state3 = EitherHot;
    break;
  }
  //     Lock out LED
  if (!digitalRead(overload1) || !digitalRead(overload2)) {
     digitalWrite(LED,     HIGH); 
  }
     else {
     digitalWrite(LED,     LOW);    
  } 
}