My Arduino Loop (Arduino Uno) Not Looping

Thread Starter

Reloadron

Joined Jan 15, 2015
7,523
I am reading three analog channels in, A0, A1 and A2. I am taking each input ten samples of each input, getting a sum and dividing by 10 for an average. All of that seems to work just fine. Here is my current code:
Code:
//Libraries
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // Set the LCD I2C address.
// number of analog samples to take per reading
#define NUM_SAMPLES 10

int sum1 = 0; // sum of samples taken
int sum2 = 0;
int sum3 = 0;
unsigned char sample_count1 = 0;    // current sample number
unsigned char sample_count2 = 0;
unsigned char sample_count3 = 0;
float voltage1 = 0.0;                // calculated voltage
float voltage2 = 0.0;
float voltage3 = 0.0;
void setup(){
  Serial.begin(9600);
  lcd.begin(20,4);   // iInit the LCD for 20 chars 4 lines
  lcd.backlight();   // Turn on the backligt (try lcd.noBaklight() to turn it off)
  lcd.setCursor(1,0); //First line
  lcd.print("3 Axis Measurement");
  
}

void loop(){
  // take a number of analog samples and add them up
    while (sample_count1 < NUM_SAMPLES) {
        sum1 += analogRead(A0);
        sample_count1++;
        delay(10);
    }
    while (sample_count2 < NUM_SAMPLES) {
        sum2 += analogRead(A1);
        sample_count2++;
        delay(10);
    }
    while (sample_count3 < NUM_SAMPLES) {
        sum3 += analogRead(A2);
        sample_count3++;
        delay(10);
    }
    // calculate the voltage
    // use 5.0 for a 5.0V ADC reference voltage
    // 4.880V is the calibrated reference voltage
    voltage1 = ((float)sum1 / (float)NUM_SAMPLES * 4.880) / 1024.0;
    voltage2 = ((float)sum2 / (float)NUM_SAMPLES * 4.880) / 1024.0;
    voltage3 = ((float)sum3 / (float)NUM_SAMPLES * 4.880) / 1024.0;
  lcd.setCursor(1,0); //First line
  lcd.print("3 Axis Measurement");
  lcd.setCursor(0,1); //Second line
  lcd.print(voltage1);
  lcd.setCursor(0,2); //Third line
  lcd.print(voltage2);
  lcd.setCursor(0,3); //Fourth line
  lcd.print(voltage3);
  Serial.println (voltage1);
  Serial.println (voltage2);
  Serial.println (voltage3);
  delay (100);
}
As shown it takes the data and does exactly what I would expect with the exception of a refresh. It's like my code runs once and does not loop. Here is an example of my display:
LCD Display.png

The displayed numbers are three voltage readings which do not change when I tilt an axis. They are actually changing as I can watch them on a DMM but my display never updates. I added some Serial.Print functions to see what was going on and same, when I open the Serial Monitor the data displays but will not update. Eventually there will be more to this but until I get this much working there is nop sense on adding to the code.

I am not, nor was I ever a programming type. If my eating would have depended on my coding abilities I would have starved long ago at my desk in the workplace. What little coding I did was mostly VB 6.0. Now obviously I have something very wrong or missing in what I have here. I would appreciate any suggestions.

I also have tried it removing the delays to no avail.

Thank You
Ron
 
Last edited:

dendad

Joined Feb 20, 2016
4,481
One thing to do is to clear the sums 1,2 and 3 at the start of the loop each time.

void loop(){

sum1 = 0;
sum2 = 0;
sum3 = 0;


// take a number of analog samples and add them up
 
Last edited:
Where do you reset sample_count 1 2 and 3 to 0? You set those to 0 initially, but never again. So, when you increment them during the next pass through loop, they all fail the while test.

add:
C:
sample_count1 = 0;    // current sample number
sample_count2 = 0;
sample_count3 = 0;
right before delay(100) and try running it.
 

dendad

Joined Feb 20, 2016
4,481
Yes, I missed that too.
I am not, nor was I ever a programming type. If my eating would have depended on my coding abilities I would have starved long ago at my desk in the workplace
Mee too. Programming is not my thing either. I'm more hardware.

How about this?
Oh, you do not need a counter for each sample loop as you can use just the one over again.
Code:
// https://forum.allaboutcircuits.com/threads/my-arduino-loop-arduino-uno-not-looping.151321/
//Libraries
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // Set the LCD I2C address.
// number of analog samples to take per reading
#define NUM_SAMPLES 10
int sum1 = 0; // sum of samples taken
int sum2 = 0;
int sum3 = 0;

float voltage1 = 0.0;  // calculated voltage
float voltage2 = 0.0;
float voltage3 = 0.0;
void setup(){
  Serial.begin(9600);
  lcd.begin(20,4);  // iInit the LCD for 20 chars 4 lines
  lcd.backlight();  // Turn on the backligt (try lcd.noBaklight() to turn it off)
  lcd.setCursor(1,0); //First line
  lcd.print("3 Axis Measurement");
  
}
void loop(){
  sum1 = 0;
  sum2 = 0;
  sum3 = 0;
  // take a number of analog samples and add them up
  for(int sample_count = 0; sample_count < NUM_SAMPLES; sample_count++) { 
  sum1 += analogRead(A0);
  delay(10);
  }
  for(int sample_count = 0; sample_count < NUM_SAMPLES; sample_count++) { 
  sum2 += analogRead(A1);
  delay(10);
  }
  for(int sample_count = 0; sample_count < NUM_SAMPLES; sample_count++) { 
  sum3 += analogRead(A2);
  delay(10);
  }
  // calculate the voltage
  // use 5.0 for a 5.0V ADC reference voltage
  // 4.880V is the calibrated reference voltage
  voltage1 = ((float)sum1 / (float)NUM_SAMPLES * 4.880) / 1024.0;
  voltage2 = ((float)sum2 / (float)NUM_SAMPLES * 4.880) / 1024.0;
  voltage3 = ((float)sum3 / (float)NUM_SAMPLES * 4.880) / 1024.0;
  lcd.setCursor(1,0); //First line
  lcd.print("3 Axis Measurement");
  lcd.setCursor(0,1); //Second line
  lcd.print(voltage1);
  lcd.setCursor(0,2); //Third line
  lcd.print(voltage2);
  lcd.setCursor(0,3); //Fourth line
  lcd.print(voltage3);
  Serial.println (voltage1);
  Serial.println (voltage2);
  Serial.println (voltage3);
  delay (100);
}
 

Thread Starter

Reloadron

Joined Jan 15, 2015
7,523
Three knowledgeable members in about 3 min and it now works just fine. I just kept looking at this over several hours and the obvious never occurred to me. Now it is working and I can crawl along. Can't thank all of you enough.

Thanks A Bunch Guys
Ron
 

Thread Starter

Reloadron

Joined Jan 15, 2015
7,523
Yes, I missed that too.


Mee too. Programming is not my thing either. I'm more hardware.

How about this?
Oh, you do not need a counter for each sample loop as you can use just the one over again.
Code:
// https://forum.allaboutcircuits.com/threads/my-arduino-loop-arduino-uno-not-looping.151321/
//Libraries
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // Set the LCD I2C address.
// number of analog samples to take per reading
#define NUM_SAMPLES 10
int sum1 = 0; // sum of samples taken
int sum2 = 0;
int sum3 = 0;

float voltage1 = 0.0;  // calculated voltage
float voltage2 = 0.0;
float voltage3 = 0.0;
void setup(){
  Serial.begin(9600);
  lcd.begin(20,4);  // iInit the LCD for 20 chars 4 lines
  lcd.backlight();  // Turn on the backligt (try lcd.noBaklight() to turn it off)
  lcd.setCursor(1,0); //First line
  lcd.print("3 Axis Measurement");
 
}
void loop(){
  sum1 = 0;
  sum2 = 0;
  sum3 = 0;
  // take a number of analog samples and add them up
  for(int sample_count = 0; sample_count < NUM_SAMPLES; sample_count++) {
  sum1 += analogRead(A0);
  delay(10);
  }
  for(int sample_count = 0; sample_count < NUM_SAMPLES; sample_count++) {
  sum2 += analogRead(A1);
  delay(10);
  }
  for(int sample_count = 0; sample_count < NUM_SAMPLES; sample_count++) {
  sum3 += analogRead(A2);
  delay(10);
  }
  // calculate the voltage
  // use 5.0 for a 5.0V ADC reference voltage
  // 4.880V is the calibrated reference voltage
  voltage1 = ((float)sum1 / (float)NUM_SAMPLES * 4.880) / 1024.0;
  voltage2 = ((float)sum2 / (float)NUM_SAMPLES * 4.880) / 1024.0;
  voltage3 = ((float)sum3 / (float)NUM_SAMPLES * 4.880) / 1024.0;
  lcd.setCursor(1,0); //First line
  lcd.print("3 Axis Measurement");
  lcd.setCursor(0,1); //Second line
  lcd.print(voltage1);
  lcd.setCursor(0,2); //Third line
  lcd.print(voltage2);
  lcd.setCursor(0,3); //Fourth line
  lcd.print(voltage3);
  Serial.println (voltage1);
  Serial.println (voltage2);
  Serial.println (voltage3);
  delay (100);
}
That works real well, again I can't thank you guys enough.Eric, if you recall the accelerometer thred of a few days ago that is what I am messing with.I am using a ADXL 326 but found a ADXL 335.

Again, all of you many thanks.

Ron
 

MrChips

Joined Oct 2, 2009
30,824
I can show you another way to smooth readings and it does not require resetting the sum.
Also, integer arithmetic is always faster than floating point.

Method:
1. Take the sum of (new reading - average)
2. average = sum / NUM_SAMPLES

Code:
#define NUM_SAMPLES 10
long int sum = 0;
int average = 0;
int reading;

void main(void)
{
   while (1)
   {
      reading = analogRead(A0);
      sum += (reading - average);
      average = sum / NUM_SAMPLES;
      // convert to voltage
      // display
      // delay
   }
}
 
I had a mildly humorous observation - more about myself than the point of your thread, so I admit this is a bit off topic. The observation is what I am calling "age-induced recursion".

So, I read your topic this morning and then your post and then took a look at the code and so, oh there it is" and typed out my response. Then, I saw the response by @dendad and said "hummph" because I didn't see that, and I kind of felt like I should have...whatever. So, I looked at your code a little more thoroughly and I look at:

voltage1 = ((float)sum1 / (float)NUM_SAMPLES * 4.880) / 1024.0;

Ok, I see what you are doing and I like the use of 1024 (see Why ADC/1024 is correct, and ADC/1023 is just plain wrong! - a thread that is some 5 years old but is till the best reference in my opinion).

Then I see the float typecasting and I note that I don't do it that way, I use a double. So, then I go off on that road. Well, long story short, for the Arduino UNO, there is no difference - same number of bytes. Not so for other implementations. Slowly, I come to the same point - just use a double by habit/practice rather than a float...unless you have a long double...etc.and don't forget about speed and space..etc. Then it occurs to me that I have been down that road and reached the same endpoint before and that is why it is a habit... *sigh*, age-induced recursion. But there may be another side, youth may still make more mistakes, but maybe they just don't seem to care about them as much - just correct them and move on...or so I tell myself :)
 

MrChips

Joined Oct 2, 2009
30,824
Rather than multiply by 4.880 in FP, multiply by 488 and then divide by 100.
Rather than divide by 1024.0, just shift right 10 bits.

I will let that sink in for awhile then I will show you how to optimize n * 4.880 / 1024.0 with integer arithmetic.
 

Thread Starter

Reloadron

Joined Jan 15, 2015
7,523
Mr. Chipps and Raymond, thank you both for the further enlightenment. I'll get that into my code Mr. Chipps and Raymond:

I had a mildly humorous observation - more about myself than the point of your thread, so I admit this is a bit off topic. The observation is what I am calling "age-induced recursion".
Yeah, pretty sure I know what you mean. :)

Ron
.
 

Phil-S

Joined Dec 4, 2015
238
The old Arduino example "Smoothing" works quite well for most averaging jobs.
Somewhere in StackExchange, Tom Igoe has a discussion going on a one line averaging method, but I couldn't get it to work so went back to the array method.
If the first loading of values into the array upsets things like temperature readings, set a Boolean to pick up the first run through the array, then clear it on the second iteration to ignore the first set of readings while the average is building up
 

Thread Starter

Reloadron

Joined Jan 15, 2015
7,523
The old Arduino example "Smoothing" works quite well for most averaging jobs.
Somewhere in StackExchange, Tom Igoe has a discussion going on a one line averaging method, but I couldn't get it to work so went back to the array method.
If the first loading of values into the array upsets things like temperature readings, set a Boolean to pick up the first run through the array, then clear it on the second iteration to ignore the first set of readings while the average is building up
Thanks Phil for that information, much appreciated.

Ron
 
Top