I do not read analog input with millis function

Hi,
I am trying to make a program that is supposed to do this:

  1. generate the numbers 1, 2 and 3 randomly.

  2. I generate a first number.

  3. the number that comes out i display it on a SSD1331 display.

  4. simultaneously while the number is being displayed of the display, I start a 10-second timer with Millis() and read an analog input (A3) displaying the data coming out on the serial monitor.

  5. At the end of the 10 seconds, I switch to generating a new number.

  6. If it is equal to the previous one I discard it and go on to generate another one.

  7. when they all came out (1,2,3), I repeat the same procedure for another 10 times.

Currently the function readData() which is the one that should display a number of values on the serial monitor, in the 10 seconds displays only 1.
The sketch is as follows:

/***********************************
 *  Random numbers from 1 to 3
 * 
 * V 4.0  25 September 2024
 * v 5.0  26 September 
 * v 6.0  1 October 
 * v 7.0  4 Octobere 
 * v 8.0  10 October
 ***********************************/

  #include <Adafruit_GFX.h>
  #include <Adafruit_SSD1331.h>
  #include <SPI.h>
  #include <Wire.h>
  
  #define sclk 13
  #define mosi 11
  #define cs   10
  #define rst  9
  #define dc   8
  
  // +++++++++++++ color definition +++++++++
  #define BLACK           0x0000
  #define BLUE            0x001F
  #define RED             0xF800
  #define GREEN           0x07E0
  #define CYAN            0x07FF
  #define MAGENTA         0xF81F
  #define YELLOW          0xFFE0  
  #define WHITE           0xFFFF

// +++++++++++++ functions +++++++++++++++++
  void memorizzaDato();
  void allarme();
  void azzera();
  void leggeDato();
  void fine();
  
// +++++++++++++ global variables ++++++++
  unsigned long startMillis;
  unsigned long currentMillis;
  const unsigned long period = 10000;
  bool counting;
  int count;
  int indirizzo = 0;
  byte byteUno = 0;
  byte byteDue = 0;
  int dato;
  //int sogliaINF = 0;
  //int sogliaSUP = 0;
  unsigned long seed;
  const byte analogPin = A3; 
  int valore = 0;
  bool uscito1 = false;
  bool uscito2 = false;
  bool uscito3 = false;
  int dimTesto = 7;
  int giocate = 0;  // variable for repeat outputs
  
  Adafruit_SSD1331 display = Adafruit_SSD1331(cs, dc, rst);
  
 void setup() {
    Wire.begin();
    display.begin();
    display.fillScreen(GREEN);
    display.setCursor(20,20);  //column, row
    display.setTextColor(WHITE);
    display.setTextSize(2);
    display.print("ver.7");
    display.setCursor(25,50);  //colonna, riga
    display.setTextSize(1);
    display.print("10 ott 24");
    delay(3000);   
    Serial.begin(9600);
    counting = true;    //enable counting
    startMillis = millis(); 
    count = 0;
    unsigned long seed = analogRead(A0);
    for (int i=1; i<=3; ++i) {
      delay(50);
      seed += analogRead(A0) * 1024 * i;
    }
  randomSeed(seed);
  }

 void loop() {
    //currentMillis = millis();
    dato = random(1, 4);
    Serial.println(dato);

    switch (dato){
      case 1:
        if(uscito1 == false){
        display.fillScreen(BLACK);
        display.setCursor(30,5);  //column, row
        display.setTextColor(CYAN);
        display.setTextSize(dimTesto);
        display.print("1");
           leggeDato();
           //memorizzaDato(); 
          }
        uscito1 = true;
        break;
        
      case 2:
        if(uscito2 == false){
        display.fillScreen(BLACK);
        display.setCursor(30,5);  //column, row
        display.setTextColor(CYAN);
        display.setTextSize(dimTesto);
        display.print("2");
          leggeDato();
          //memorizzaDato(); 
          }
        uscito2 = true;
        break;
        
      case 3:
        dato = 3;
        if(uscito3 == false){
        display.fillScreen(BLACK);
        display.setCursor(30,0);  //column, row
        display.setTextColor(CYAN);
        display.setTextSize(dimTesto);
        display.print("3");
          leggeDato();
          //memorizzaDato();  
          }
        uscito3 = true;
        break;
    }
    azzera();
    fine();
    //allarme();
    //delay(1000);
 }
 
  /********************************************************
   *                Functions
   ********************************************************/
  void leggeDato(){
    currentMillis = millis();
     if (currentMillis - startMillis <= period){  //true until the end of the period  
        count++;    //increase count
        //Serial.print(count);
        valore = analogRead(analogPin);
        Serial.print(" ");
        Serial.println(valore);
      delay(100);
    }
    else  //period has ended
      if (counting == true){  //enable counting
        Serial.print(count);
        counting = false;    //block count 
    } 
   }
   
 void memorizzaDato(){   
      Wire.beginTransmission(0x50);    
      Wire.write(highByte(indirizzo));
      Wire.write(lowByte(indirizzo));    
      Wire.write(byte(giocate));    
      Wire.endTransmission();    
      indirizzo++;
      delay(5);
    
    // saves data in two consecutive bytes in the 24LC256 
      byteUno = ((analogPin >> 8) & 0xFF);
      byteDue = (analogPin & 0xFF);    
      Wire.beginTransmission(0x50);    
      Wire.write(highByte(indirizzo));
      Wire.write(lowByte(indirizzo));    
      Wire.write(byte(byteUno));    
      Wire.endTransmission();    
      indirizzo++;
      delay(5);
      Wire.beginTransmission(0x50); 
      Wire.write(highByte(indirizzo));
      Wire.write(lowByte(indirizzo));   
      Wire.write(byte(byteDue));   
      Wire.endTransmission();  
      indirizzo++;
      delay(5);
      Serial.println(" Stored data");
      if(indirizzo >= 32000){
          allarme();
        }
     }

void azzera(){
   if(uscito1 == true && uscito2 == true && uscito3 == true){
      uscito1 = false;
      uscito2 = false;
      uscito3 = false;
      giocate = ++giocate;
      display.fillScreen(BLACK);
      display.setCursor(40,25);  //column, row
      display.setTextColor(YELLOW);
      display.setTextSize(5);
      //display.print(giocate);
      Serial.println("--------");
      giocate = giocate++;
      Serial.println("--------");
      Serial.println(giocate);
      Serial.println("--------");
      Serial.println(" ");
       }   
    }

void allarme(){
    display.fillScreen(RED);
    display.setCursor(5,20);  //column, row
    display.setTextColor(WHITE);
    display.setTextSize(2);
    display.print("Memory full");
    while(1);   
  }

void fine(){         
    delay(1000);
    if(giocate > 10){
      display.fillScreen(RED);
      display.setCursor(25,20);  //column, row
      display.setTextColor(WHITE);
      display.setTextSize(2);
      display.print("End");
      Serial.println(" End");
      while(1);
    }
}

Then when this first part works for me I plan to save the analog input data to a 24LC256.
EzioGi

Your program stops at while(1);
See: https://docs.arduino.cc/language-reference/en/structure/control-structure/while/

The program stops after running 10 times and if the variable “giocate” is greater than 10, is correct.
My problem is the “leggeDati()” function is only executed once when it is called, instead of continuing to read the data for the 10 seconds that are set with Milli().

Do you mean that you want to stay in that function for 10 seconds?
If so try changing it to be like this:

void leggeDato() {
  currentMillis = millis();
  while (currentMillis - startMillis <= period) { //true until the end of the period
    count++;    //increase count
    //Serial.print(count);
    valore = analogRead(analogPin);
    Serial.print(" ");
    Serial.println(valore);
    delay(100);
  }
  //period has ended
  if (counting == true) { //enable counting
    Serial.print(count);
    counting = false;    //block count
  }
}

Hi Dave,
I made the change you recommended but when it first enters the while loop, it doesn't come out again.

Oh sorry, of course it won't. You need to update currentMillis in the while loop.

void leggeDato() {
  currentMillis = millis();
  while (currentMillis - startMillis <= period) { //true until the end of the period
    count++;    //increase count
    //Serial.print(count);
    valore = analogRead(analogPin);
    Serial.print(" ");
    Serial.println(valore);
    delay(100);
    currentMillis = millis(); // <--- Add this line
  }
  //period has ended
  if (counting == true) { //enable counting
    Serial.print(count);
    counting = false;    //block count
  }
}

Dave_Lowther did find a problem, his suggestion doesn't solve it.
Try while (millis() - startMillis <= period) {

Hi @stitech ,

if the idea is to repeat the main function inside "leggeDato()" for 10 seconds, the while() loop is ok, isn't it?

P.S.: But it should read

startMillis = millis()

I don't know what the OP's idea is. I do know that in his original sketch the condition never changes.

This seems to be the relevant part from post #1:

image

So reading for 10 seconds in a while loop would make sense to me ...

I created a Wokwi project based on the sketch from post #1 (since no SSD1331 is available, I'm using an ILI9341) so that modifications can be tested easily ...

Original Sketch on Wokwi (except ILI9341 display!)

Sketch with While() loop to read analog pin for 10 seconds

Modified Sketch
/*
  Forum: https://forum.arduino.cc/t/i-do-not-read-analog-input-with-millis-function/1310084
  Wokwi: https://wokwi.com/projects/411467196421173249

  Original Version see here Wokwi: https://wokwi.com/projects/411465414534821889

*/



/***********************************
    Random numbers from 1 to 3

   V 4.0  25 September 2024
   v 5.0  26 September
   v 6.0  1 October
   v 7.0  4 Octobere
   v 8.0  10 October
 ***********************************/

#define WOKWI

#include <Adafruit_GFX.h>

#include <SPI.h>
#include <Wire.h>

#ifdef WOKWI

#define TFT_CS   10
#define TFT_DC   8
#include "Adafruit_ILI9341.h"
Adafruit_ILI9341 display = Adafruit_ILI9341(TFT_CS, TFT_DC);


#else

#include <Adafruit_SSD1331.h>
#define sclk 13
#define mosi 11
#define cs   10
#define rst  9
#define dc   8
Adafruit_SSD1331 display = Adafruit_SSD1331(cs, dc, rst);

#endif



// +++++++++++++ color definition +++++++++
#define BLACK           0x0000
#define BLUE            0x001F
#define RED             0xF800
#define GREEN           0x07E0
#define CYAN            0x07FF
#define MAGENTA         0xF81F
#define YELLOW          0xFFE0
#define WHITE           0xFFFF

// +++++++++++++ functions +++++++++++++++++
void memorizzaDato();
void allarme();
void azzera();
void leggeDato();
void fine();

// +++++++++++++ global variables ++++++++
unsigned long startMillis;
unsigned long currentMillis;
const unsigned long period = 10000;
bool counting;
int count;
int indirizzo = 0;
byte byteUno = 0;
byte byteDue = 0;
int dato;
//int sogliaINF = 0;
//int sogliaSUP = 0;
unsigned long seed;
const byte analogPin = A3;
int valore = 0;
bool uscito1 = false;
bool uscito2 = false;
bool uscito3 = false;
int dimTesto = 7;
int giocate = 0;  // variable for repeat outputs

void setup() {
  Wire.begin();
  display.begin();
  display.fillScreen(GREEN);
  display.setCursor(20, 20); //column, row
  display.setTextColor(WHITE);
  display.setTextSize(2);
  display.print("ver.7");
  display.setCursor(25, 50); //colonna, riga
  display.setTextSize(1);
  display.print("10 ott 24");
  delay(3000);
  Serial.begin(9600);
  counting = true;    //enable counting
  startMillis = millis();
  count = 0;
  unsigned long seed = analogRead(A0);
  for (int i = 1; i <= 3; ++i) {
    delay(50);
    seed += analogRead(A0) * 1024 * i;
  }
  randomSeed(seed);
}

void loop() {
  //currentMillis = millis();
  dato = random(1, 4);
  Serial.println(dato);

  switch (dato) {
    case 1:
      if (uscito1 == false) {
        display.fillScreen(BLACK);
        display.setCursor(30, 5); //column, row
        display.setTextColor(CYAN);
        display.setTextSize(dimTesto);
        display.print("1");
        leggeDato();
        //memorizzaDato();
      }
      uscito1 = true;
      break;

    case 2:
      if (uscito2 == false) {
        display.fillScreen(BLACK);
        display.setCursor(30, 5); //column, row
        display.setTextColor(CYAN);
        display.setTextSize(dimTesto);
        display.print("2");
        leggeDato();
        //memorizzaDato();
      }
      uscito2 = true;
      break;

    case 3:
      dato = 3;
      if (uscito3 == false) {
        display.fillScreen(BLACK);
        display.setCursor(30, 0); //column, row
        display.setTextColor(CYAN);
        display.setTextSize(dimTesto);
        display.print("3");
        leggeDato();
        //memorizzaDato();
      }
      uscito3 = true;
      break;
  }
  azzera();
  fine();
  //allarme();
  //delay(1000);
}

/********************************************************
                  Functions
 ********************************************************/
void leggeDato() {
  startMillis = millis();
  while (millis() - startMillis <= period) { //true until the end of the period
    count++;    //increase count
    //Serial.print(count);
    valore = analogRead(analogPin);
    Serial.print(" ");
    Serial.println(valore);
    delay(100);
  }
  //period has ended
  if (counting == true) { //enable counting
    Serial.print("count = ");
    Serial.println(count);
    //counting = false;    //block count
  }
}

void memorizzaDato() {
  Wire.beginTransmission(0x50);
  Wire.write(highByte(indirizzo));
  Wire.write(lowByte(indirizzo));
  Wire.write(byte(giocate));
  Wire.endTransmission();
  indirizzo++;
  delay(5);

  // saves data in two consecutive bytes in the 24LC256
  byteUno = ((analogPin >> 8) & 0xFF);
  byteDue = (analogPin & 0xFF);
  Wire.beginTransmission(0x50);
  Wire.write(highByte(indirizzo));
  Wire.write(lowByte(indirizzo));
  Wire.write(byte(byteUno));
  Wire.endTransmission();
  indirizzo++;
  delay(5);
  Wire.beginTransmission(0x50);
  Wire.write(highByte(indirizzo));
  Wire.write(lowByte(indirizzo));
  Wire.write(byte(byteDue));
  Wire.endTransmission();
  indirizzo++;
  delay(5);
  Serial.println(" Stored data");
  if (indirizzo >= 32000) {
    allarme();
  }
}

void azzera() {
  if (uscito1 == true && uscito2 == true && uscito3 == true) {
    uscito1 = false;
    uscito2 = false;
    uscito3 = false;
    giocate = ++giocate;
    display.fillScreen(BLACK);
    display.setCursor(40, 25); //column, row
    display.setTextColor(YELLOW);
    display.setTextSize(5);
    //display.print(giocate);
    Serial.println("--------");
    giocate = giocate++;
    Serial.println("--------");
    Serial.println(giocate);
    Serial.println("--------");
    Serial.println(" ");
  }
}

void allarme() {
  display.fillScreen(RED);
  display.setCursor(5, 20); //column, row
  display.setTextColor(WHITE);
  display.setTextSize(2);
  display.print("Memory full");
  while (1);
}

void fine() {
  delay(1000);
  if (giocate > 10) {
    display.fillScreen(RED);
    display.setCursor(25, 20); //column, row
    display.setTextColor(WHITE);
    display.setTextSize(2);
    display.print("End");
    Serial.println(" End");
    while (1);
  }
}

The function leggeDato() has been modified like this:

void leggeDato() {
  startMillis = millis();
  while (millis() - startMillis <= period) { //true until the end of the period
    count++;    //increase count
    //Serial.print(count);
    valore = analogRead(analogPin);
    Serial.print(" ");
    Serial.println(valore);
    delay(100);
  }
  //period has ended
  if (counting == true) { //enable counting
    Serial.print("count = ");
    Serial.println(count);
    //counting = false;    //block count
  }
}

@eziogi,

please check if this change meets your intentions...

In general you have a lot of replicated code in your sketch which can be removed to ease the readability and understanding of your application.

Yes that needs to be added somewhere. I hadn't run the code until now. If it's added here:

void leggeDato() {
  startMillis = millis(); // DL: < ---- - Added
  // DL modified as suggested in post #4 and post #6
  currentMillis = millis();
  Serial.println("About to enter while loop"); // DL Added
  while (currentMillis - startMillis <= period) { //true until the end of the period
    count++;    //increase count
    //Serial.print(count);
    valore = analogRead(analogPin);
    Serial.print(" ");
    Serial.println(valore);
    delay(2000); // delay(100); DL: Changed to reduce amount of info on serial monitor
    currentMillis = millis();
  }
  Serial.println("Left while loop"); // DL Added
  if (counting == true) { //enable counting
    Serial.print(count);
    counting = false;    //block count
  }
}

it produces this serial output. I've no idea whether it's what the OP intended

3
About to enter while loop
 394
 303
 263
 252
 255
Left while loop
52
About to enter while loop
 263
 264
 258
 250
 244
Left while loop
3
2
1
About to enter while loop
 250
 260
 264
 264
 258
Left while loop
--------
--------
2
--------
 
2
About to enter while loop
 248
 242
 243
 252
 260
Left while loop
3
About to enter while loop
 263
 256
 248
 242
 244
Left while loop
3
3
2
1
About to enter while loop
 262
 254
 245
 241
 245
Left while loop
--------
--------
4
--------
 
1
About to enter while loop
 255
 261
 263
 259
 252
Left while loop
1
1
3
About to enter while loop
 243
 249
 256
 262
 263
Left while loop
2

Hi @Dave_Lowther ,

you can check your sketch on Wokwi by creating a copy of one of e.g. the link to the original version and make your changes to it. Just take care not to remove the Wokwi dependend modifications I did for the display :wink:

Good luck!
ec2021

Hi @eziogi ,

here is a version of your sketch where I replaced the switch-case statement by a single function call:

// Using an array of booleans now:
bool uscito[3] = {false,false,false};

void loop() {
  //currentMillis = millis();
  dato = random(1, 4);
  Serial.println(dato);
  displayAndReadData(dato);
  azzera();
  fine();
  //allarme();
  //delay(1000);
}

/********************************************************
                  Functions
 ********************************************************/

void displayAndReadData(int value){

  if (!uscito[value]){
        display.fillScreen(BLACK);
        display.setCursor(30, 5); //column, row
        display.setTextColor(CYAN);
        display.setTextSize(dimTesto);
        display.print(value);
        leggeDato();
        uscito[value] = false;
         //memorizzaDato();  
  }
}

https://wokwi.com/projects/411468014321108993

There is still more to do to make the sketch better readable. I assume you want to do it on your own, don't you?

Have fun!

Thanks for the tip. I've never used an Arduino simulator. I have Unos, Nanos, Leonardos, ATtiny85s, ESP32s, and ESP8266s to hand. I'll play with the simulator some time. I had covid + flu jabs earlier today and my brain isn't working at its best right now.

Hope you don't have to suffer further from the vaccinations ...

All the best!
ec2021

Do you mean that you want to stay in that function for 10 seconds?

Yes Dave,
I need that in the 10-second cycle I can continuously read the data coming to me from the analog input A3.

Thank you for the advice, but I am still in my infancy.
It's only a short time that I got acquainted with Arduino and I still have a lot to learn.
Maybe with this sketch I have exceeded my possibilities, my knowledge.
EzioGi

I saw the sketch you posted on Wokwi and it works the way I wanted to do it.
Thanks for the example, I will study it now and then put it into practice.
EzioGi

Okay, I will keep that in mind.

Sorry, best wishes for a speedy recovery
EzioGi