JonD1988

Reading Battery Voltages with Averaging

Jul 7th, 2023
1,523
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #include <Wire.h> //Needed to Use ADS1115 ADC - See Reference 12
  2. #include <ADS1115_lite.h> //Needed to Use ADS1115 ADC - See Reference 12
  3. ADS1115_lite ads(ADS1115_DEFAULT_ADDRESS); //0x48 addr pin connected to GND. Needed to Use ADS1115 ADC - See Reference 12
  4. long raw1 = 0, raw2 = 0; //Needed to Use ADS1115 ADC - See Reference 12
  5. double resolution=0; //Needed to Use ADS1115 ADC - See Reference 12
  6. int batt1Analog = 0, batt2Analog=0; //Analog readings from batt1Pin and batt2Pin and then actual battery voltages
  7. float batt1V=0, batt2V=0;
  8. unsigned long previousMillis = 0;      // will store last time the battery voltages were read
  9. const long interval = 10000;           // interval at which to read the battery voltage (milliseconds)
  10. #define battCutOff 3.0 //Voltage to Cutoff Motors to Protect the Batteries
  11. #define numReadsToAvg 3 //Number of Voltage Readings to Store and Take Average Of
  12. float batt1VArray[numReadsToAvg]; //Array to store batt1V readings i.e. battery 1 voltages
  13. float batt2VArray[numReadsToAvg]; //Array to store batt2V readings i.e. battery 2 voltages
  14. int batt1VIndex = 0, batt2VIndex = 0; //Keeps track of the array indexes for the batt1VArray and batt2VArray
  15. float batt1VAvg = 3.0, batt2VAvg = 3.0; //Initialize battery voltage reading averages to 3.0
  16. float batt1VSum = 0.0, batt2VSum = 0.0; //Sums all the elements in the batt1VArray and the batt2VArray for use in the average calculations
  17. int batt1VCount = 0, batt2VCount = 0; //Variable to keep track of the count of how many elements have been stored in the batt1VArray and batt2VArray - really only meant to be used initially before all elements of the arrays have been updated with non-zero values
  18.  
  19. void setup()
  20. { //start of void setup()
  21.   ads_config(); //Needed to Use ADS1115 ADC - See Reference 12
  22. } //end of void setup()
  23.  
  24. void loop()
  25. { //start of void loop()
  26.  
  27. unsigned long currentMillis = millis(); //Checks the current time
  28.  
  29.     if (currentMillis - previousMillis >= interval) //Check to see if it's time to read the battery voltages (if the difference between the current time and last time you read the battery voltages is bigger than the interval at which you want to read the battery voltages)
  30.     { //Start of if (currentMillis - previousMillis >= interval)
  31.         previousMillis = currentMillis; //save the last time you read the battery voltages before you read the battery voltages
  32.         readBatts(); //Read the battery voltages
  33.     } //End of if (currentMillis - previousMillis >= interval)
  34.  
  35. } //end of void loop()
  36.  
  37. void readBatts()
  38. { //Start of readBatts function definition
  39.   raw1 = ads_read1(); //Reads A0 from ADS1115 - Reference 12
  40.   resolution=4096.00/32752.00;
  41.   delay(200);
  42.   float result1=(raw1*resolution)/1000.00; //batt1 voltage + batt2 voltage
  43.   raw2 = ads_read2(); //Reads A0 from ADS1115 - Reference 12
  44.   delay(200);
  45.   float result2=(raw2*resolution)/1000.00; //batt2 voltage alone
  46.   batt1V = result1 - result2; //Assigns battery 1 voltage alone to batt1V variable
  47.   batt1V = 11.03*batt1V;
  48.   batt2V = result2; //Assigns result2 to the batt2V variable
  49.   batt2V = 11.0*batt2V;
  50.  
  51.   batt1VArray[batt1VIndex] = batt1V; //Store the current batt1V value into the element of the batt1VArray that matches batt1VIndex
  52.   batt2VArray[batt2VIndex] = batt2V; //Store the current batt2V value into the element of the batt2VArray that matches batt2VIndex
  53.   batt1VIndex = (batt1VIndex + 1) % numReadsToAvg; //Increments batt1VIndex by 1 each time this line runs and the % numReadsToAvg means that the batt1VIndex will take on values from 0 up to but not including numReadsToAvg (i.e. 0, 1, 2, 0, 1, 2, etc. if numReadsToAvg = 3)
  54.   batt2VIndex = (batt2VIndex + 1) % numReadsToAvg; //Increments batt2VIndex by 1 each time this line runs and the % numReadsToAvg means that the batt2VIndex will take on values from 0 up to but not including numReadsToAvg (i.e. 0, 1, 2, 0, 1, 2, etc. if numReadsToAvg = 3)
  55.  
  56.   //Perform the average calculation with non-zero elements of the batt1VArray and batt2VArray
  57.   for(int i=0; i<numReadsToAvg; i++)
  58.   { //Start of for loop to step through the elements in the batt1VArray
  59.       if(batt1VArray[i] != 0.0) //If the current value is non-zero
  60.       { //Start of if statement to check if the current element of the batt1VArray is non-zero
  61.           batt1VSum += batt1VArray[i]; //Add the current value to the running sum for the average calculation
  62.           batt1VCount++; //Increment the counter to keep track of the current number of non-zero elements in the sum
  63.       } //End of if statement to check if the current element of the batt1VArray is non-zero
  64.   } //end of for loop to step through the elements in the batt1VArray
  65.  
  66.   if (batt1VCount > 0 && batt1VCount < numReadsToAvg)
  67.   {
  68.       batt1VAvg = batt1VSum / batt1VCount; //Calculates the average
  69.   }
  70.   //Without the following two lines of code batt1VSum and batt1VCount could increase without limit (as much as those variable types can hold) retaining impact from values beyond the current set of stored readings in the array and therefore wouldn't react to newer voltage readings after a while
  71.   batt1VSum = 0.0; //After the sum is used in the calculation of the current batt1VAvg set it back to its initial value so that it isn't impacted by past readings. The sum is meant to be used for the current set of numReadsToAvg
  72.   batt1VCount = 0; //After the count is used in the calculation of the current batt1VAvg set it back to its initial value so that it isn't impacted by past readings.  The count is meant to be used for the current set of numReadsToAvg
  73.  
  74.   for(int j=0; j<numReadsToAvg; j++)
  75.   { //Start of for loop to step through the elements in the batt2VArray
  76.       if(batt2VArray[j] != 0.0) //If the current value is non-zero
  77.       { //Start of if statement to check if the current element of the batt2VArray is non-zero
  78.           batt2VSum += batt2VArray[j]; //Add the current value to the running sum for the average calculation
  79.           batt2VCount++; //Increment the counter to keep track of the current number of non-zero elements in the sum
  80.       } //End of if statement to check if the current element of the batt2VArray is non-zero
  81.   } //end of for loop to step through the elements in the batt2VArray
  82.  
  83.   if (batt2VCount > 0 && batt2VCount < numReadsToAvg)
  84.   {
  85.       batt2VAvg = batt2VSum / batt2VCount; //Calculates the average
  86.   }
  87.   //Without the following two lines of code batt2VSum and batt2VCount could increase without limit (as much as those variable types can hold) retaining impact from values beyond the current set of stored readings in the array and therefore wouldn't react to newer voltage readings after a while
  88.   batt2VSum = 0.0; //After the sum is used in the calculation of the current batt2VAvg set it back to its initial value so that it isn't impacted by past readings. The sum is meant to be used for the current set of numReadsToAvg
  89.   batt2VCount = 0; //After the count is used in the calculation of the current batt2VAvg set it back to its initial value so that it isn't impacted by past readings.  The count is meant to be used for the current set of numReadsToAvg
  90.  
  91.   //This section of code sends the battery voltages to the Android app
  92.   SerialBT.print("|");  //Delimeter separating values which the receiving app is programmed to recognize
  93.   SerialBT.print("W");  //Delimeter separating values which the receiving app is programmed to recognize
  94.   SerialBT.print("|");  //Delimeter separating values which the receiving app is programmed to recognize
  95.   //SerialBT.print(batt1V);
  96.   SerialBT.print(batt1VAvg);  
  97.   SerialBT.print("|");  //Delimeter separating values which the receiving app is programmed to recognize
  98.   SerialBT.print("w");  //Delimeter separating values which the receiving app is programmed to recognize
  99.  
  100.   SerialBT.print("|");  //Delimeter separating values which the receiving app is programmed to recognize
  101.   SerialBT.print("Z");  //Delimeter separating values which the receiving app is programmed to recognize
  102.   SerialBT.print("|");  //Delimeter separating values which the receiving app is programmed to recognize
  103.   //SerialBT.print(batt2V);
  104.   SerialBT.print(batt2VAvg);
  105.   SerialBT.print("|");  //Delimeter separating values which the receiving app is programmed to recognize      
  106.   SerialBT.print("z");  //Delimeter separating values which the receiving app is programmed to recognize
  107.  
  108.   //if (batt1V < battCutOff || batt2V < battCutOff) //If either battery drops below the cutoff voltage
  109.   if (batt1VAvg < battCutOff || batt2VAvg < battCutOff) //If either battery drops below the cutoff voltage
  110.   { //Start of if (batt1V < battCutOff || batt2V < battCutOff)
  111.     stopVehicle(); //Stop Power to the Motors
  112.     lightFState = 0; //Turns Off Front Lights
  113.     lightBState = 0; //Turns Off Back Lights
  114.     hornH(); //Turns horn on briefly
  115.     delay(100);
  116.     hornL();
  117.    } //End of if (batt1V < battCutOff || batt2V < battCutOff)
  118.  
  119. } //End of readBatts function definition
  120.  
  121. void ads_config(){
  122.   ads.setGain(ADS1115_REG_CONFIG_PGA_4_096V); // GAIN_ONE and resolution to ± 4.096V
  123.   ads.setSampleRate(ADS1115_REG_CONFIG_DR_8SPS); // Set to the fastest MODE 860Samples per sec
  124. }
  125.  
  126. int16_t ads_read1(){
  127.   ads.setMux(ADS1115_REG_CONFIG_MUX_SINGLE_0);  // Single mode input on AIN0 (AIN0 - GND)
  128.   ads.triggerConversion();  // Triggered mannually
  129.   return ads.getConversion();  // returns int16_t value
  130. }
  131.  
  132. int16_t ads_read2(){
  133.   ads.setMux(ADS1115_REG_CONFIG_MUX_SINGLE_1);  // Single mode input on AIN1 (AIN1 - GND)
  134.   ads.triggerConversion();  // Triggered mannually
  135.   return ads.getConversion();  // returns int16_t value
  136. }
  137. //Reference 12- Reading Analog Voltages Using ADS1115 https://www.youtube.com/watch?v=u-1TRpLGH04
Advertisement
Add Comment
Please, Sign In to add comment