cycle through analog values on 4digit 7 Segment display

i'm having a hard time cycling through analog values displayed on a 4 digit 7 segment led display. the display works as expected and it will display the values read via A0 to A3 but I can't seem to get it to really show one value after the other. it seems like it randomly displays the values.

of course this has to do with my approach using millis() currentmillis and previousmillis, but since delay() does not seem to work with sevseg.h ( values just flash for a fractions of a second when using delay() ) i had to go this way.

but see for yourselves, here's my sketch:

#include <SevSeg.h>
SevSeg display;
int moisture1 = 0, moisture2 = 0, moisture3 = 0, moisture4 = 0;

long previousMillis = 0;
long interval = 2000;
void setup() {
// initialize 7-Segment Display Common Anode  
display.Begin(1,2,3,4,5,6,7,8,9,10,11,12,13);
// initialize serial communication at 9600 bits per second:
Serial.begin(9600);
}


void loop() {



moisture1 = analogRead(A0);
unsigned long currentMillis = millis();
display.PrintOutput();
if(currentMillis - previousMillis > interval) {
  previousMillis = currentMillis;
  display.PrintOutput();
  display.NewNum(moisture1,(byte) 4);
  Serial.println("moisture1: ");Serial.println(moisture1);}



moisture2 = analogRead(A1);
display.PrintOutput();
currentMillis = millis();
if(currentMillis - previousMillis > interval) {
  previousMillis = currentMillis;
  display.PrintOutput();
  display.NewNum(moisture2,(byte) 4);
  Serial.println("moisture2: ");Serial.println(moisture2);}


moisture3 = analogRead(A2);
display.PrintOutput();
currentMillis = millis();
if(currentMillis - previousMillis > interval) {
  previousMillis = currentMillis;
  display.PrintOutput();
  display.NewNum(moisture3,(byte) 4);
  Serial.println("moisture3: ");Serial.println(moisture3);}


moisture4 = analogRead(A3);
display.PrintOutput();
currentMillis = millis();
if(currentMillis - previousMillis > interval) {
  previousMillis = currentMillis;
  display.PrintOutput();
  display.NewNum(moisture4,(byte) 4);
Serial.println("moisture4: ");Serial.println(moisture4);}


}

i added serial output as well and this clearly shows that all of the values get displayed eventually, the code just doesnt cycle through them in a specific order and constant interval:

moisture3: 
359
moisture4: 
376
moisture4: 
374
moisture2: 
470
moisture2: 
471
moisture1: 
370
moisture4: 
374
moisture3: 
359
moisture3: 
359
moisture2: 
471
moisture1: 
370
moisture2: 
468
moisture2: 
469

Any suggestions on how to modify my code for this to work properly?

thnx in advance, and please excuse me if this is a really stupid question, i'm just starting programming for the arduino.

moisture1 = analogRead(A0);
unsigned long currentMillis = millis();
display.PrintOutput(); //this executes every time through loop(). Is that what you want?
if(currentMillis - previousMillis > interval) {
previousMillis = currentMillis;
display.PrintOutput();
display.NewNum(moisture1,(byte) 4);
Serial.println("moisture1: ");Serial.println(moisture1);}

i just tried commenting these lines out, except the one inside the IF constructions, when i do that, the display doesnt show the values it just flickers them for fractions of a second. so i guess this is needed.

see sevseg documentation:

http://playground.arduino.cc/Main/SevenSegmentLibrary

...The calling program must run the PrintOutput() function repeatedly to get
the number displayed...

anyone got another suggestion?

Read the Analog pins twice and use the 2nd reading.
The reason being, there is only one ADC in the chip and fast reads will sometimes repeat the prior reading, even if on a different pin.
Example:

moisture2 = analogRead(A1);
moisture2 = analogRead(A1);
display.PrintOutput();

tried your suggestion, still does not work. :frowning:

ok just a quick info what i've done so far and how i modified and simplyfied my code:

  1. i simplyfied the if statements and how the time gets calculated, eliminated some of the variables from the first code
  2. changed sevseg.h version to latest sparkfun fork GitHub - sparkfun/SevSeg: Seven Segment library for Arduino
  3. made the necessary changes to code in order to use the new display commands rom the new sevseg version.
  4. Added A B C D for moisture1 moisture2 moisture3 moisture4 in front of the displayed string in order to see results directly on the display instead of serial monitor.

What happenes now:

  1. Values are still not displayed in order, order seems random
  2. Display does not just display the values but blinks them for a split second and then waits for the next value to display
#include <SevSegNEW.h>
SevSeg display;
int moisture1 = 0, moisture2 = 0, moisture3 = 0, moisture4 = 0;
unsigned long timer;

void setup() {
int displayType = COMMON_ANODE; 

 

   int digit1 = 2; //Pin 12 on my 4 digit display
   int digit2 = 3; //Pin 9 on my 4 digit display
   int digit3 = 4; //Pin 8 on my 4 digit display
   int digit4 = 5; //Pin 6 on my 4 digit display
   
   
   int segA = 6; //Pin 11 on my 4 digit display
   int segB = 7; //Pin 7 on my 4 digit display
   int segC = 8; //Pin 4 on my 4 digit display
   int segD = 9; //Pin 2 on my 4 digit display
   int segE = 10; //Pin 1 on my 4 digit display
   int segF = 11; //Pin 10 on my 4 digit display
   int segG = 12; //Pin 5 on my 4 digit display
   int segDP= 13; //Pin 3 on my 4 digit display
   

  int numberOfDigits = 4; 

  display.Begin(displayType, numberOfDigits, digit1, digit2, digit3, digit4, segA, segB, segC, segD, segE, segF, segG, segDP);
  
  display.SetBrightness(100); //Set the display to 100% brightness level
  timer = millis();
 
}


void loop() {



moisture1 = analogRead(A0);
moisture1 = analogRead(A0);
char moistureString1[4];
sprintf(moistureString1,"a%3d",moisture1);
if(millis() - timer >= 2000) {
timer = millis();
display.DisplayString(moistureString1, 1);
}


moisture2 = analogRead(A1);
moisture2 = analogRead(A1);
char moistureString2[4];
sprintf(moistureString2,"b%3d",moisture2);
if(millis() - timer >= 2000) {
timer = millis();
display.DisplayString(moistureString2, 1);
}

moisture3 = analogRead(A2);
moisture3 = analogRead(A2);
char moistureString3[4];
sprintf(moistureString3,"c%3d",moisture3);
if(millis() - timer >= 2000) {
timer = millis();
display.DisplayString(moistureString3, 1);
}

moisture4 = analogRead(A3);
moisture4 = analogRead(A3);
char moistureString4[4];
sprintf(moistureString4,"d%3d",moisture4);
if(millis() - timer >= 2000) {
timer = millis();
display.DisplayString(moistureString4, 1);
}
}

Why not put all the reading in the if statement?

if(millis() - timer >= 2000) {
timer = millis();
moisture3 = analogRead(A2);
moisture3 = analogRead(A2);
char moistureString3[4];
sprintf(moistureString3,"c%3d",moisture3);
display.DisplayString(moistureString3, 1);
}

Oh I think I know......
You're using the same timer = millis(); for all of them.
Use a different timer variable for each one like timer1, timer2, timer3, timer4

@uuzi, One topic, one discussion please.
If you'd like the topic moved to another forum, we can do that.

I'm with steinie44 on the timing of it.
Try this: add delay(2000) between the 4 readings, see if the reading/display part is working. If so, then can go back to blink without delay style timing and do something where a new reading is allowed only when 2 seconds have elapsed after the prior reading.

sorry for the duplicate posts.

when adding

delay(2000);

after each reading/display, the order seems to work as expected, but the issue remains that the value just gets flashed for a split second.

new code:

#include <SevSegNEW.h>
SevSeg display;
int moisture1 = 0, moisture2 = 0, moisture3 = 0, moisture4 = 0;
unsigned long timer;

void setup() {
int displayType = COMMON_ANODE; 

 

   int digit1 = 2; //Pin 12 on my 4 digit display
   int digit2 = 3; //Pin 9 on my 4 digit display
   int digit3 = 4; //Pin 8 on my 4 digit display
   int digit4 = 5; //Pin 6 on my 4 digit display
   
   
   int segA = 6; //Pin 11 on my 4 digit display
   int segB = 7; //Pin 7 on my 4 digit display
   int segC = 8; //Pin 4 on my 4 digit display
   int segD = 9; //Pin 2 on my 4 digit display
   int segE = 10; //Pin 1 on my 4 digit display
   int segF = 11; //Pin 10 on my 4 digit display
   int segG = 12; //Pin 5 on my 4 digit display
   int segDP= 13; //Pin 3 on my 4 digit display
   

  int numberOfDigits = 4; 

  display.Begin(displayType, numberOfDigits, digit1, digit2, digit3, digit4, segA, segB, segC, segD, segE, segF, segG, segDP);
  
  display.SetBrightness(100); //Set the display to 100% brightness level
  timer = millis();
 
}


void loop() {



moisture1 = analogRead(A0);
moisture1 = analogRead(A0);
char moistureString1[4];
sprintf(moistureString1,"a%3d",moisture1);
//if(millis() - timer >= 2000) {
display.DisplayString(moistureString1, 1);
//timer = millis();
//}
delay(2000);

moisture2 = analogRead(A1);
moisture2 = analogRead(A1);
char moistureString2[4];
sprintf(moistureString2,"b%3d",moisture2);
//if(millis() - timer >= 2000) {
display.DisplayString(moistureString2, 1);
//timer = millis();
//}
delay(2000);

moisture3 = analogRead(A2);
moisture3 = analogRead(A2);
char moistureString3[4];
sprintf(moistureString3,"c%3d",moisture3);
//if(millis() - timer >= 2000) {
display.DisplayString(moistureString3, 1);
//timer = millis();
//}
delay(2000);

moisture4 = analogRead(A3);
moisture4 = analogRead(A3);
char moistureString4[4];
sprintf(moistureString4,"d%3d",moisture4);
//if(millis() - timer >= 2000) {
display.DisplayString(moistureString4, 1);
//timer = millis();
//}
delay(2000);

}

steinie44:
Why not put all the reading in the if statement?

if(millis() - timer >= 2000) {

timer = millis();
moisture3 = analogRead(A2);
moisture3 = analogRead(A2);
char moistureString3[4];
sprintf(moistureString3,"c%3d",moisture3);
display.DisplayString(moistureString3, 1);
}



Oh I think I know......
You're using the same timer = millis(); for all of them.
Use a different timer variable for each one like timer1, timer2, timer3, timer4

tried that but still the problems remain.

Try this:

moisture1 = analogRead(A0);
moisture1 = analogRead(A0);
char moistureString1[4];
sprintf(moistureString1,"a%3d",moisture1);
timer = millis() + 2000UL; // timer declared as unsigned long
while (millis() <= timer ) {
display.DisplayString(moistureString1, 1); // keep calling the display command
}

CrossRoads:
Try this:

moisture1 = analogRead(A0);

moisture1 = analogRead(A0);
char moistureString1[4];
sprintf(moistureString1,"a%3d",moisture1);
timer = millis() + 2000UL; // timer declared as unsigned long
while (millis() <= timer ) {
display.DisplayString(moistureString1, 1); // keep calling the display command
}

Thank you very much! i though about a "while"-construction but dismissed it.... don't really know why..

code works perfectly now.

working code:

#include <SevSegNEW.h>
SevSeg display;
int moisture1 = 0, moisture2 = 0, moisture3 = 0, moisture4 = 0;
unsigned long timer;

void setup() {
int displayType = COMMON_ANODE; 

 

   int digit1 = 2; //Pin 12 on my 4 digit display
   int digit2 = 3; //Pin 9 on my 4 digit display
   int digit3 = 4; //Pin 8 on my 4 digit display
   int digit4 = 5; //Pin 6 on my 4 digit display
   
   
   int segA = 6; //Pin 11 on my 4 digit display
   int segB = 7; //Pin 7 on my 4 digit display
   int segC = 8; //Pin 4 on my 4 digit display
   int segD = 9; //Pin 2 on my 4 digit display
   int segE = 10; //Pin 1 on my 4 digit display
   int segF = 11; //Pin 10 on my 4 digit display
   int segG = 12; //Pin 5 on my 4 digit display
   int segDP= 13; //Pin 3 on my 4 digit display
   

  int numberOfDigits = 4; 

  display.Begin(displayType, numberOfDigits, digit1, digit2, digit3, digit4, segA, segB, segC, segD, segE, segF, segG, segDP);
  
  display.SetBrightness(100); //Set the display to 100% brightness level
  timer = millis();
 
}


void loop() {



moisture1 = analogRead(A0);
moisture1 = analogRead(A0);
char moistureString1[4];
sprintf(moistureString1,"a%3d",moisture1);
timer = millis() + 2000UL; 
while (millis() <= timer ) {
display.DisplayString(moistureString1, 1); 
}


moisture2 = analogRead(A1);
moisture2 = analogRead(A1);
char moistureString2[4];
sprintf(moistureString2,"b%3d",moisture2);
timer = millis() + 2000UL; 
while (millis() <= timer ) {
display.DisplayString(moistureString2, 1);}

moisture3 = analogRead(A2);
moisture3 = analogRead(A2);
char moistureString3[4];
sprintf(moistureString3,"c%3d",moisture3);
timer = millis() + 2000UL;
while (millis() <= timer ) {
display.DisplayString(moistureString3, 1);}


moisture4 = analogRead(A3);
moisture4 = analogRead(A3);
char moistureString4[4];
sprintf(moistureString4,"d%3d",moisture4);
timer = millis() + 2000UL; 
while (millis() <= timer ) {
display.DisplayString(moistureString4, 1);}


}

I wouldn't say perfectly - I'd say this library
#include <SevSegNEW.h>
has a problem if you have to resort to that to use it.