System resets itself

Hi guys newbie here,

Wrote this code yesterday for an ultrasonic rangefinder, but the system just resets itself after “Ready!” is displayed on my LCD. It should continue onto the rangefinder code, but never does.

Im using the ATMEGA from the Uno in a circuit i put together, see below.

Never coded anything before, so i’m kinda stumped as to why it doesn’t work.

Code is a little bit of a mess, cleanup advice would be appreciated (just make it simple advice!)

Cheers

Bushwookie

#include <EEPROMex.h>
#include <EEPROMVar.h>
#include <LiquidCrystal.h>
#define LCD_RS 8                    // Register select
#define LCD_EN 9                    // Enable
#define LCD_D4 10                   // Data bits
#define LCD_D5 11                   // Data bits
#define LCD_D6 12                   // Data bits
#define LCD_D7 13                   // Data bits
#define seriesresistor 10000        // Value of resistor in series with thermistor
#define temperaturepin A0           // Analog pin of input
#define readyswitch A1              // Analog pin of ready/cal switch
#define tempcalswitch A3            // Analog pin of temp cal switch
#define rangecalswitch A2           // Analog pin of rangecal switch
#define alarmmuteswitch A0          // Analog pin of alarm mute switch
#define bcoefficient 3570           // B coeff of the thermistor
#define thermistornominal 10000     // Nominal temp of thermistor

LiquidCrystal lcd(5, 4, 3, 2, 1, 0);// initialize the library with the numbers of the interface pins
int TXSIGNAL = 8;                   // Name pin 8 as TX_SIGNAL
int RXSIGNAL = 6;                   // Select the input pin for the Piezo reciever
int constrast = 7;                  // Grounding pin for LCD contrast
int RXSIGNALVALUE = 0;              // variable to store the value coming from the sensor

float counter = 47.0;               // Var for counter
float measuredtime = 0.01;          // Analog read from rx sensor
float speedofsound = 343.3;         // Speed of sound floating variable
float offset = 102.1;               // Distance from sensor to max fill (in mm)
float litres = 0.001;               // Litres remaining float for lcd
float tempreading = 0.01;           // Analog read from temp sensor
float tempgradient = 0.61;          // Temp coefficient
float tempintercept = 331.4;        // Y intercept of temp

int calmode = 0;                    // Variable to store cal switch state
int rangecalmode = 0;               // Variable to store rangecal switch state
int tempcalmode = 0;                // Variable to store tempcal switch state
int address = 0;                    // EEPROM Address

void setup() {
  pinMode(7, OUTPUT);               // Ground for LCD contrast 
  digitalWrite(7, HIGH);
  lcd.begin(16, 2);                 // set up the LCD's number of columns and rows: 
  lcd.print("Initializing.");       // warm up for caps.
  delay(1000);
  digitalWrite(7, LOW);
  delay(1000);
  lcd.print("."); 
  address= 0;
  offset = EEPROM.readFloat(address);
  delay(1000);  
  lcd.print("."); 
  address = 100;
  tempreading = EEPROM.readFloat(address);
  delay(500);
  lcd.clear();
  calmode = analogRead(readyswitch);
  rangecalmode = analogRead(rangecalswitch);
  tempcalmode = analogRead(tempcalswitch);
  pinMode(8, OUTPUT);               // Initialise TXON pin for output
  pinMode(6, INPUT);                // Initialise RXIN pin for input

  if (calmode > 600)                // Calibration mode
  {
    lcd.clear();
    lcd.print("Ready!");
    delay(2500);
  }
      else if (rangecalmode > 600)  // zero the sensor
  {
        lcd.clear();
        lcd.print("Range Cal Mode");
        delay(2500);
        lcd.clear();
        lcd.print("Ensure sensor is");
        lcd.setCursor(0, 1);
        lcd.print("fully screwed in");
        delay(5000);
        lcd.clear();
        lcd.print("Range reading");
        lcd.setCursor(0, 1);
        lcd.print("in progress");
        delay(5000);
        float measuredtime, mm;
        digitalWrite(TXSIGNAL, LOW);
        delayMicroseconds(10);
        digitalWrite(TXSIGNAL, HIGH);    
        delayMicroseconds(23);            
        digitalWrite(TXSIGNAL, LOW);     
        measuredtime = pulseIn(RXSIGNAL, HIGH);
        mm = microsecondsToMillimeters(measuredtime);
        offset = mm / 2;
        address = 0;
        EEPROM.writeFloat(address, offset);
        delay(10);
        offset = EEPROM.readFloat(address);
        lcd.clear();
        lcd.print("Offset is now");
        lcd.setCursor(0, 1);
        lcd.print("calibrated to");
        delay(5000);
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print(offset);
        lcd.print(" mm");
        delay(2000);
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("Reset switches");
        lcd.setCursor(0, 1);
        lcd.print("then restart.");
        delay(9999999);              // Long delay until reset, basically hangs
        lcd.clear();
  }
        else if (tempcalmode > 600)
  {
              lcd.clear();
              lcd.print("Temp Cal Mode");
              delay(2500);
              lcd.clear();
              lcd.print("Ensure sensor is");
              lcd.setCursor(0, 1);
              lcd.print("inside chamber");
              delay(15000);
              lcd.clear();
              lcd.setCursor(0, 0);
              lcd.print("Temp reading");
              lcd.setCursor(0, 1);
              lcd.print("in progress.");
              delay(2000);
              tempreading = analogRead(temperaturepin);
              lcd.print(".");
              tempreading = (1023 / tempreading) - 1;
              delay(2000);
              lcd.print(".");
              delay(2000);
              lcd.clear(); 
              tempreading = seriesresistor / tempreading;
              lcd.print("Temp is now");
              lcd.setCursor(0, 1);
              lcd.print("calibrated to");
              delay(5000);
              float steinhart;
              steinhart = tempreading / thermistornominal;     // (R/Ro)
              steinhart = log(steinhart);                      // ln(R/Ro)
              steinhart /= bcoefficient;                       // 1/B * ln(R/Ro)
              steinhart += 1.0 / (thermistornominal + 273.15); // + (1/To)
              steinhart = 1.0 / steinhart;                     // Invert
              steinhart -= 273.15;                             // convert to C
              speedofsound = tempgradient * steinhart;
              speedofsound = speedofsound + tempintercept;
              address = 100;
              EEPROM.writeFloat(address, speedofsound);
              delay(100);
              speedofsound = EEPROM.readFloat(address);
              tempreading = steinhart;
              lcd.clear();
              lcd.print(steinhart);
              lcd.print(" *C");
              delay(2500);
              lcd.clear();
              lcd.setCursor(0, 0);
              lcd.print("Reset switches");
              lcd.setCursor(0, 1);
              lcd.print("and restart unit");
              delay(9999999);              // Long delay until reset, basically hangs
              lcd.clear();
              
              
  }
}


void loop() {

  float mm;
  digitalWrite(TXSIGNAL, LOW);
  delayMicroseconds(10);
  digitalWrite(TXSIGNAL, HIGH);    // Turn on TXON for 50uS
  delayMicroseconds(23);            // wait for a 25uS - accounted for code delay
  digitalWrite(TXSIGNAL, LOW);     // Turn off TXON
  measuredtime = pulseIn(RXSIGNAL, HIGH);
  mm = microsecondsToMillimeters(measuredtime);
  //compensate for code time delay
  mm = mm - offset;
  litres = mm / 13;
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print(litres);
  lcd.print(" Litres");
  delay(100); 
}

long microsecondsToMillimeters(long microseconds){
  // The speed of sound is defined by variable Speedofsound
  // Then half the distance travelled.
  return microseconds / speedofsound / 2;
}

Anything that now looks like this lcd.print("Range Cal Mode"); should look like this lcd.print(F("Range Cal Mode"));

As to the reset - have you got an adequate power supply and decoupling?

Im using the ATMEGA from the Uno in a circuit i put together, see below.

That is a boost regulator and is quite an advanced thing to try and make for even a professional engineer. You don’t just throw one of those together.
I would suggest replacing that with a 5V supply for the time being. If that works OK then you have trouble with that circuit which can oscillate and be very unstable if it is not made correctly.

Thanks, I will add the “f’s” to my code

AWOL:
As to the reset - have you got an adequate power supply and decoupling?

theoretically, i think so. I am using the texas instruments TPS61202 synchronous boost converter, running off 2x AA cells.

See figure1, page 7.

Grumpy_Mike:
That is a boost regulator and is quite an advanced thing to try and make for even a professional engineer. You don’t just throw one of those together.
I would suggest replacing that with a 5V supply for the time being. If that works OK then you have trouble with that circuit which can oscillate and be very unstable if it is not made correctly.

I know its tiny. I am using components identical to those shown on the datasheet, on a custom made PCB (see below).

I am using components identical to those shown on the datasheet, on a custom made PCB

I have had to manage many professional electronic engineers and I have never met one yet that has managed to design a switch more power supply first time. It takes a lot more than you have done. Even specialist power supply engineers fail. What about the ground plane?

So have you put a scope on it to look at the output stability?

Grumpy_Mike: I have had to manage many professional electronic engineers and I have never met one yet that has managed to design a switch more power supply first time. It takes a lot more than you have done. Even specialist power supply engineers fail. What about the ground plane?

So have you put a scope on it to look at the output stability?

Thats great, im a second year apprentice though, still learning :)

No ground plane, only bought single sided boards, as we had to etch by hand.

No scope check yet, i left the office late but will be back in the morning - its the first thing to do on my list. Im gonna find myself a really nice one and do some probing.

What kind of thing would i be missing on the psu? several projects i researched plus the datasheet all run identical configurations...

What kind of thing would i be missing on the psu?

A good layout.

The Layout is critical to a switch mode supply working connections have to be short and the current carrying and feedback tracks have to be short. The data sheet normally has recommended layouts, that should be your start position.

Never seen anyone attempt one on a single sided board.

Grumpy_Mike: A good layout.

Damn... well its definitely too late in the project to make another board, since deadline day is tomorrow :)

Seems wierd that the board will power for 20 seconds or so and then reset after a time though - i would have thought if it was not getting power to begin with, i would never see anything on the LCD.

What does the word "Unstable" mean?

However it is only a suggestion, as I said try powering it with a proper supply to see if that "fixes" it.

Your code looks a bit flakey, if the comments reflect your thinking. For example:-

delayMicroseconds(23);            // wait for a 25uS - accounted for code delay

What is "code delay" and why do you have to "account" for it and anyway why would a delay do this?

Grumpy_Mike: What does the word "Unstable" mean? However it is only a suggestion, as I said try powering it with a proper supply to see if that "fixes" it.

Good idea :)

Grumpy_Mike: What is "code delay" and why do you have to "account" for it and anyway why would a delay do this?

So, I have to account for the length of time it takes to run through the lines of code, so that I get an accurate timing.

I tested out the pulsewidth of a 50kHz square wave i made using digitalwrite low and then high for 10uS each.

The pulsewidth was actually around 11uS high and 13uS low, when both should be 10uS. To counteract, i would send the high pulse to be 9us, and the low to be 7us - for instance.

Since my rangefinder needs to be highly accurate, i am attempting to account for what i believe to be a delay in code execution, by shortening my pulse length by a few uS.

The lengths are untested as of yet, i was hoping to get it powered today, but still waiting.

hope that makes sense

So the comment should not have been

// accounted for code delay

but rather
// additional delay to control the timing between pulses.

I tested out the pulsewidth of a 50kHz square wave i made using digitalwrite low and then high for 10uS each.

Common ultrasound devices are usually around 40kHz.

Grumpy_Mike: So the comment should not have beenbut rather // additional delay to control the timing between pulses.

it made sense to me :)

AWOL: Common ultrasound devices are usually around 40kHz.

true, this was only for an experiment. 50kHz means a 20uS time period, and therefore 10uS per half-wave - easy to judge on an oscilloscope

How do you know it resets? If it does I know what it should do, but I am asking you.

How long ( estimate ) it takes for you to see "Ready" after power-up ? And how long before "it resets" AKA "Ready" goes away? Asking because you said "power up 20 seconds" and it just does not add up.

BTW if you just need +5V you should power up with "hard" source > 5V directly and forget the "booster". Read up on Uno hardware , especially on power supply input and current capacity on its +5V output.

Vaclav: How do you know it resets? If it does I know what it should do, but I am asking you.

How long ( estimate ) it takes for you to see "Ready" after power-up ? And how long before "it resets" AKA "Ready" goes away? Asking because you said "power up 20 seconds" and it just does not add up.

BTW if you just need +5V you should power up with "hard" source > 5V directly and forget the "booster". Read up on Uno hardware , especially on power supply input and current capacity on its +5V output.

20 seconds was an overestimation, its more like 6 seconds.

After "Ready!" the code should execute the digitalwrite(TXSIGNAL, LOW) inside the void loop.

The LCD should display a value in litres on the screen, but instead goes back to "initializing".

Edit- I have tested the code further, and have discovered that it fails when executing the line

  digitalWrite(TXSIGNAL, HIGH);    // Turn on TXON for 50uS

Finding a hard source right as we speak!

it made sense to me :slight_smile:

If you were less slip shot in your use of language maybe you would be less slip shot in your writing of code.

have tested the code further, and have discovered that it fails when executing the line…

digitalWrite(TXSIGNAL, HIGH ) ; // Turn on TXON for 50uS

There is nothing in the schematic that shows what that is connected to.
Try just a sketch with initializing that pi as an output then setting it high. Does it still reset? The unseen part of your circuit could be shorting something out.

Other totally useless lines are:-

 delay(9999999);              // Long delay until reset, basically hangs
lcd.clear();

Just use:-

while(1);

And it will do the same thing. However as a code technique it is pants. And how on earth is the lcd.clear() call ever going to be made? It is not so what is the point of including it.

Irregadless how others think your code is illogical I would suggest to break it down to KNOWN flow. After all it is programmable software and it it does not work you need to take it apart ( as you are already doing) until you find the cause of the error.

void setup() {
  pinMode(7, OUTPUT);               // Ground for LCD contrast 
  digitalWrite(7, HIGH);
  lcd.begin(16, 2);                 // set up the LCD's number of columns and rows: 
  lcd.print("Initializing.");       // warm up for caps. prints Initializing.
  delay(1000);
  digitalWrite(7, LOW);
  delay(1000);
  lcd.print(".");                   prints Initializing.. (two dots after 2 seconds )
  address= 0;
  offset = EEPROM.readFloat(address);
  delay(1000);  
  lcd.print(".");             prints Initializing... 3 dots after another second 
  address = 100;
  tempreading = EEPROM.readFloat(address);
  delay(500);
  lcd.clear();                clears lcd fof Initialiozing after 3.5 seconds 
  calmode = analogRead(readyswitch);
  rangecalmode = analogRead(rangecalswitch);
  tempcalmode = analogRead(tempcalswitch);
  pinMode(8, OUTPUT);               // Initialise TXON pin for output
  pinMode(6, INPUT);                // Initialise RXIN pin for input

// debuhg step 1 
// simulate calmode 
calmode = 601;


// debug step 2 
// simulate rangecalmode and run test similar to while(1) ... in debug step 1 
// rnagemode = 601; 


// debug step 3 
// simulate .... same as above

  if (calmode > 600)                // Calibration mode
  {
    lcd.clear();
    lcd.print("Ready!");
    delay(5000);          // does it stay up for 5 seconds? 
    lcd.clear();
    delay(5000);         // still no reset ? 

   // debug step 1 
   while(1){
  // lcd.clear(); 
   Serial.print ( "debug step 1");
   delay(2000);

   lcd.clear();
    lcd.print("Ready!");
    delay(2000);
  }

   // does it resets now AKA prints "initializing" ?

    delay(2500);
  }
      else if (rangecalmode > 600)  // zero the sensor
  {
        lcd.clear();
        lcd.print("Range Cal Mode");
        delay(2500);
        lcd.clear();
        lcd.print("Ensure sensor is");
        lcd.setCursor(0, 1);
        lcd.print("fully screwed in");
        delay(5000);
        lcd.clear();
        lcd.print("Range reading");
        lcd.setCursor(0, 1);
        lcd.print("in progress");
        delay(5000);
        float measuredtime, mm;
        digitalWrite(TXSIGNAL, LOW);
        delayMicroseconds(10);
        digitalWrite(TXSIGNAL, HIGH);    
        delayMicroseconds(23);            
        digitalWrite(TXSIGNAL, LOW);     
        measuredtime = pulseIn(RXSIGNAL, HIGH);
        mm = microsecondsToMillimeters(measuredtime);
        offset = mm / 2;
        address = 0;
        EEPROM.writeFloat(address, offset);
        delay(10);
        offset = EEPROM.readFloat(address);
        lcd.clear();
        lcd.print("Offset is now");
        lcd.setCursor(0, 1);
        lcd.print("calibrated to");
        delay(5000);
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print(offset);
        lcd.print(" mm");
        delay(2000);
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("Reset switches");
        lcd.setCursor(0, 1);
        lcd.print("then restart.");
        delay(9999999);              // Long delay until reset, basically hangs
        lcd.clear();
  }
        else if (tempcalmode > 600)
  {
              lcd.clear();
              lcd.print("Temp Cal Mode");
              delay(2500);
              lcd.clear();
              lcd.print("Ensure sensor is");
              lcd.setCursor(0, 1);
              lcd.print("inside chamber");
              delay(15000);
              lcd.clear();
              lcd.setCursor(0, 0);
              lcd.print("Temp reading");
              lcd.setCursor(0, 1);
              lcd.print("in progress.");
              delay(2000);
              tempreading = analogRead(temperaturepin);
              lcd.print(".");
              tempreading = (1023 / tempreading) - 1;
              delay(2000);
              lcd.print(".");
              delay(2000);
              lcd.clear(); 
              tempreading = seriesresistor / tempreading;
              lcd.print("Temp is now");
              lcd.setCursor(0, 1);
              lcd.print("calibrated to");
              delay(5000);
              float steinhart;
              steinhart = tempreading / thermistornominal;     // (R/Ro)
              steinhart = log(steinhart);                      // ln(R/Ro)
              steinhart /= bcoefficient;                       // 1/B * ln(R/Ro)
              steinhart += 1.0 / (thermistornominal + 273.15); // + (1/To)
              steinhart = 1.0 / steinhart;                     // Invert
              steinhart -= 273.15;                             // convert to C
              speedofsound = tempgradient * steinhart;
              speedofsound = speedofsound + tempintercept;
              address = 100;
              EEPROM.writeFloat(address, speedofsound);
              delay(100);
              speedofsound = EEPROM.readFloat(address);
              tempreading = steinhart;
              lcd.clear();
              lcd.print(steinhart);
              lcd.print(" *C");
              delay(2500);
              lcd.clear();
              lcd.setCursor(0, 0);
              lcd.print("Reset switches");
              lcd.setCursor(0, 1);
              lcd.print("and restart unit");
              delay(9999999);              // Long delay until reset, basically hangs
              lcd.clear();
              
              
  }
}

Moderator edit: CODE TAGS, DAMMIT.

until you find the cause of the error.

The error is not in the software, it is in the hardware.

Vaclav: Irregadless ........

Odd word, I thought it was a bushisim until I looked it up. But it turns out it is a miss spelled wrong usage word that has been around a long time. http://en.wikipedia.org/wiki/Irregardless

Irregardless is not a proper word.

Anyway, my advice would be to try running your program on an actual arduino.

You have too many competing possible sources of failure ( dodgy power supply, dodgy program, dodgy wiring, dodgy sensor ) to be able to debug your system effectively.

Your program looks spectacularly long and complicated. Try deleting 75% of it and getting one piece of functionality working at a time.

Wow, GrumpyMike you sure are grumpy today :stuck_out_tongue:

I saw the word “irregardless” and thought of the TV show American Dad when Stan says it and Steve laughs at him and tells him that word is “a logical absurdity”
0:20 Clip

Anyway back to a solution. When I was building my 8x8x8 RGB LED cube, I had the same problem, random reseting around 10-20 seconds of on time. The solution was simple, add a bigger capacitor between the power lines. I had already had one but apparently it didn’t work well enough. Also make sure your RESET is tied to 5V through a 10k+ resistor.