Problem with serial communication. Multiple battery voltage read.

Hi!

I've made simple shield for arduino nano for reading voltage from multiple bateries.
I use 4067 chip for switching batteries (one of 16) and connecting it to analog pin.

Here is the code:

float voltage;

//Battery control pins
int b0 = 5;
int b1 = 6;
int b2 = 4;
int b3 = 3;

int led = 2;

//time between measurement series
int gap = 60*1;

//led on before measurement [s]
int info = 15;

int pom = 0;

void setup(){
  pinMode(b0, OUTPUT); 
  pinMode(b1, OUTPUT); 
  pinMode(b2, OUTPUT); 
  pinMode(b3, OUTPUT);
 
  pinMode(b3, OUTPUT); 

  digitalWrite(b0, LOW);
  digitalWrite(b1, LOW);
  digitalWrite(b2, LOW);
  digitalWrite(b3, LOW);
  
  digitalWrite(led, LOW);
  
  pinMode(A0, INPUT);
  
  Serial.begin(9600);
  analogReference(INTERNAL);
  
  for(int i=0; i<10; i++){
    analogRead(A0);
    delay(100);
  }
  
  Serial.println("Up and running.");
  Serial.println("[t]\t[0]\t[1]\t[2]\t[3]\t[4]\t[5]\t[6]\t[7]\t[8]\t[9]\t[10]\t[11]\t[12]\t[13]\t[14]\t[15]");
}


void loop(){
  
  if (millis()/1000 > gap*pom-info || pom == 0){

      digitalWrite(led, HIGH);
      
      while(millis()/1000 < gap*pom){
          void();  
      }
      
      float val = 0;
      
      Serial.print(millis()/60000);
      //Loop through and read all 16 values
      for(int i = 0; i < 16; i ++){
        
        val = readBatteryOnLoad(i, 1, 1000)*1000;
        Serial.print("\t");
        Serial.print(val,0);
      }
      
      Serial.println(" ");
      digitalWrite(led, LOW);
      pom++;
  
  }

}

double readBatteryOnLoad(int battery, int load, int del){
  int controlPinBat[] = {b0, b1, b2, b3};

  int muxChannel[16][4]={
    {0,0,0,0}, //channel 0
    {1,0,0,0}, //channel 1
    {0,1,0,0}, //channel 2
    {1,1,0,0}, //channel 3
    {0,0,1,0}, //channel 4
    {1,0,1,0}, //channel 5
    {0,1,1,0}, //channel 6
    {1,1,1,0}, //channel 7
    {0,0,0,1}, //channel 8
    {1,0,0,1}, //channel 9
    {0,1,0,1}, //channel 10
    {1,1,0,1}, //channel 11
    {0,0,1,1}, //channel 12
    {1,0,1,1}, //channel 13
    {0,1,1,1}, //channel 14
    {1,1,1,1}  //channel 15
  };
  
  //loop through the 4 sig of Battery controller
  for(int i = 0; i < 4; i ++){
    digitalWrite(controlPinBat[i], muxChannel[battery][i]);
  }
  
  delay(del);
  
  voltage = (float)analogRead(A0)*1.1/1023;
  
  return voltage;
}

The problem is that serial stops communicate after some time 240-1000 min.
Can anyon help me to resolve this problem?

Best regards!

One problem is your use of millis() for interval timing. You always have to do unsigned math, and compare the elapsed time with the desired interval:

static uint32_t startTime; // set it somewhere to millis()
static uint32_t interval = 1000; // one second

void loop() {
  if (millis() - startTime > interval) {
    // do something now!

    // ... and set it to go off again
    startTime += interval;  // forces it to be evenly spaced, without "creep"
                            //   or  startTime = millis(); if it's ok to creep

Search for "millis rollover".

Cheers,
/dev

What is the purpose of

      while(millis()/1000 < gap*pom){
          void(); 
      }

I suspect the compiler will ignore it completely. If you want a time interval use the technique that @/dev has mentioned. It is illustrated in Several Things at a Time

...R

/dev:
One problem is your use of millis() for interval timing. You always have to do unsigned math, and compare the elapsed time with the desired interval

How about it now?:

static uint32_t startTime; // set it somewhere to millis()
static uint32_t interval = 300000; // one minute * num of mins
static uint32_t info = 15000;

float voltage;

//Battery control pins
int b0 = 5;
int b1 = 6;
int b2 = 4;
int b3 = 3;

int led = 2;

//Czas pomiędzy pomiarami
//int gap = 60*1;

//sekundy przed pomiarem - led on
//int info = 15;

int pom = 0;

void setup(){
  pinMode(b0, OUTPUT); 
  pinMode(b1, OUTPUT); 
  pinMode(b2, OUTPUT); 
  pinMode(b3, OUTPUT);
 
  pinMode(b3, OUTPUT); 

  digitalWrite(b0, LOW);
  digitalWrite(b1, LOW);
  digitalWrite(b2, LOW);
  digitalWrite(b3, LOW);
  
  digitalWrite(led, LOW);
  
  pinMode(A0, INPUT);
  
  Serial.begin(9600);
  //analogReference(EXTERNAL);
  analogReference(INTERNAL);
  
  for(int i=0; i<10; i++){
    analogRead(A0);
    delay(100);
  }
  
  startTime = millis();
  
  Serial.println("Up and running.");
  Serial.println("[t]\t[0]\t[1]\t[2]\t[3]\t[4]\t[5]\t[6]\t[7]\t[8]\t[9]\t[10]\t[11]\t[12]\t[13]\t[14]\t[15]");
}


void loop(){
  
  if (millis() - startTime - info > interval || pom == 0){

      digitalWrite(led, HIGH);
      
      while(millis() - startTime < interval){
          delay(500);  
      }
      
      float val = 0;
      
      Serial.print(millis()/60000);
      //int i=1;
      //Loop through and read all 16 values
      //Reports back Value at channel 6 is: 346
      for(int i = 0; i < 16; i ++){
        val = readBatteryOnLoad(i, 1, 1000)*1000;
        Serial.print("\t");
        Serial.print(val,0);
      }
      
      Serial.println(" ");
      digitalWrite(led, LOW);
      
      pom++;
      startTime += interval;
  }

}

double readBatteryOnLoad(int battery, int load, int del){
  int controlPinBat[] = {b0, b1, b2, b3};

  int muxChannel[16][4]={
    {0,0,0,0}, //channel 0
    {1,0,0,0}, //channel 1
    {0,1,0,0}, //channel 2
    {1,1,0,0}, //channel 3
    {0,0,1,0}, //channel 4
    {1,0,1,0}, //channel 5
    {0,1,1,0}, //channel 6
    {1,1,1,0}, //channel 7
    {0,0,0,1}, //channel 8
    {1,0,0,1}, //channel 9
    {0,1,0,1}, //channel 10
    {1,1,0,1}, //channel 11
    {0,0,1,1}, //channel 12
    {1,0,1,1}, //channel 13
    {0,1,1,1}, //channel 14
    {1,1,1,1}  //channel 15
  };
  
  //loop through the 4 sig of Battery controller
  for(int i = 0; i < 4; i ++){
    digitalWrite(controlPinBat[i], muxChannel[battery][i]);
  }
  
  delay(del);
  
  voltage = (float)analogRead(A0)*1.1/1023;
  
  return voltage;
}

/dev:
Search for "millis rollover".

I've checked it allready:

This number will overflow (go back to zero), after approximately 50 days.

It's fair enough for me :wink:

Robin2:

      while(millis()/1000 < gap*pom){

void();
      }



I suspect the compiler will ignore it completely. If you want a time interval use the technique that @/dev has mentioned. It is illustrated in [Several Things at a Time](http://forum.arduino.cc/index.php?topic=223286.0)

...R

It was not ignored and worked well. It was only for swich led on, while there was measurement being done (and some time before).

Thak You for Your responses.
Best regards!