Calibration with button

#include <SPI.h>
#include <Wire.h> // The pins for I2C are defined by the Wire-library. On an arduino UNO:A4(SDA), A5(SCL)
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h> // Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#include <SoftwareSerial.h> // Define a Software Serial object
#include <EEPROM.h>
#include <RunningAverage.h>


RunningAverage myRAFlow1(40);
RunningAverage myRAFlow2(40);
//RunningAverage myRASensor1(25);
RunningAverage myRATheretical(1);
int samples = 0;


//pin definition
const int sensorpin = 8 ; //pin connected to the CO2 sensor
const int CO2flow = A0; //pin connected to the CO2 flow sensor
const int N2flow = A1; //pin connected to the N2 flow sensor
const int buttonPin = 7 ; //pin connected to the calibration button
const int magicValueAddress = 0; //EEPROM address for magic value
const int calibrationOffsetaddress = 4; //EEPROM address for calibration offset

//magic value set up as a 4-byte array for compatibility with your EEPROM storage
const uint8_t magicValue [4] = {0xDE, 0xAD, 0xBE, 0xEF};
float calibrationOffset = 0.0; // Variable to store calibration offset

 float theoretical = 0.0;//variable for reading runningaverage of theretical
 float flowRate1 = 0.0;//variable for reading runningaverage of avgflowrate1
 float flowRate2 = 0.0;//variable for reading runningaverage of avgflowrate2
 float avgTheoretical = 0.0;//variable for reading runningaverage of avgtheoretical
 float avgSensor = 0.0; //variable for reading runningaverage avgsensor
 int buttonState = HIGH; //variable for reading the button status

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 32 // OLED display height, in pixels
#define OLED_RESET     -1 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
SoftwareSerial softSerial(8, 9);  //the used pins; RX, TX 

void setup() {
  //pinMode(sensorpin, INPUT);
  pinMode(buttonPin, INPUT_PULLUP);
  pinMode(CO2flow, INPUT);
  pinMode(N2flow, INPUT);
  Serial.begin(9600);
  softSerial.begin(9600);
  if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {// SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
    Serial.println(F("SSD1306 allocation failed"));
    for(;;); // Don't proceed, loop forever
  }


  display.display(); // Show initial display buffer contents on the screen. The library initializes this with an Adafruit splash screen.
  delay(500); // Holds splash screen. Must legally be included if redistributed.
  display.clearDisplay(); // Clear the buffer
  display.setTextColor(WHITE);
  display.setTextSize(2);
  pinMode(9, OUTPUT); //Red led
  pinMode(10, OUTPUT); //Green led
  digitalWrite(9, LOW); 
  digitalWrite(10, HIGH); 


// EEPROM Check for existing calibration
  uint8_t storedMagic[4];
  EEPROM.get(magicValueAddress, storedMagic);
  if (memcmp(magicValue, storedMagic, 4) == 0) {
    EEPROM.get(calibrationOffsetaddress, calibrationOffset);
  } else {
    // Store a magic value first time a new board is used
    EEPROM.put(magicValueAddress, magicValue);  // Ensure magicValue is an appropriately sized and declared variable
    calibrationOffset = 0.0; // Default to no calibration offset
    // Store the calibration offset in EEPROM
    EEPROM.put(calibrationOffsetaddress, calibrationOffset);  // Make sure calibrationOffsetAddress is correctly declared
  }

}

void ReadFlows() {
//read the raw sensorvalues
int sensorValue1 = analogRead(CO2flow);
int sensorValue2 = analogRead(N2flow);


 // Convert the sensor values to flow rate (assuming 1-5V corresponds to 0.1-5 L/min)
 float voltage1 = sensorValue1 * (5.0 / 1023.0);
 float voltage2 = sensorValue2 * (5.0 / 1023.0);
  
 float flowRate1 = ((voltage1 - 1) * (5.0 / 4.0));
 float flowRate2 = ((voltage2 - 1) * (5.0 / 4.0));
 // Calculate the theoretical concentration flowRate1 / (flowRate1 + flowRate2)

myRAFlow1.addValue(flowRate1);
float avgFlowRate1 = myRAFlow1.getAverage();

myRAFlow2.addValue(flowRate2);
float avgFlowRate2 = myRAFlow2.getAverage();

Serial.print(myRAFlow1.getCount());
Serial.print(" ");
Serial.print(myRAFlow2.getCount());
Serial.print(" ");
//Serial.print(myRASensor1.getCount());
//Serial.print(" ");

 theoretical = avgFlowRate1 / (avgFlowRate1 + avgFlowRate2) * 100;
 
myRATheretical.addValue(theoretical);
float avgTheoretical = myRATheretical.getAverage();


 Serial.print(avgFlowRate1);
 Serial.print(" ");
 Serial.print(avgFlowRate2);
 Serial.print(" ");
 Serial.println(avgTheoretical); 
}


//was here


void loop() {

  ReadFlows();
  buttonState = digitalRead(buttonPin); // Read the button state and store it in buttonState

    if (buttonState == LOW) { // Check if the button is pressed
        delay(50); // Simple debounce delay
        if (digitalRead(buttonPin) == LOW) { // Confirm button press after debounce
            calibrateSensor(); // Call your calibration function
}}

  
  String Z;
  String filtered1;
  String filtered2;
  String filtered3;
  String H;
  float h;
  float polynomium;
  float A2;
  float C;
  
  String output1;
  Z = softSerial.readStringUntil('\n'); //getting string input in variable "Z". String has format Z XXXXX z XXXXX where Z is filtered data and z is raw, both in decippm
  filtered1 = Z.substring(3,5); //first two numbers of filtered data, corresponding to whole percent.
  filtered2 = Z.substring(5,7); //last two numbers of unfiltered data, corresponding to decimals of percent. One more decimal is avivable.
  filtered3 = Z.substring(3,8); //all filtered data
 h = filtered3.toFloat()/1000;
 H = String(h);
  //output = "CO2 sensor\n    "+ filtered1 + "." + filtered2 + "%"; //Prepares filtered data for display. "/n" moves to the next line. 
polynomium = 2.37472 * pow(10, -30) * pow(h, 6) 
           - 2.70695 * pow(10, -25) * pow(h, 5) 
           + 1.24012 * pow(10, -20) * pow(h, 4) 
           - 2.91716 * pow(10, -16) * pow(h, 3) 
           + 3.62939 * pow(10, -12) * pow(h, 2) 
           - 1.82753 * pow(10, -8) * h 
           - 1.35129 * pow(10, -3);
A2 = (h / (1 + polynomium * (1013 - 1012.6)));
//delay(250);
//myRASensor1.addValue(A2);
//avgSensor = myRASensor1.getAverage();
C = A2 + calibrationOffset; 
 Serial.println(C);
 

String ValueAsText;
if (C < 10.0) {
  ValueAsText = ' ' + String(A2,1);
}
if (theoretical >= 10.0) {
  ValueAsText = ' ' + ValueAsText;
}

output1 = "S:" + ValueAsText + "%"; //Prepares filtered data for display. "/n" moves to the next line.
//output += "\nDir: " + String(direct_conversion) + "%";


String output2;

output2 = "F: " + String(theoretical,1) + "%";

display.setCursor(0, 0); //Set start of line for sensor concentration
display.clearDisplay();
display.println(output1); //Sends prepared filtered data to display buffer
display.setCursor(150,0); //set start of line for theoretical concentration
display.println(output2);
display.display(); //Updates display from display buffer




//Define led status
  if (filtered1 ==""){ //If no signal from sensor, red led on, green led off
    digitalWrite(9, HIGH);
    digitalWrite(10, LOW);  
  } else if (filtered1 =="20"){ //If sensor is outputting "20" (maximum percentage of CO2 in air measurable), red and green led on,
    digitalWrite(9, HIGH); 
    digitalWrite(10, HIGH); 
  } else { //If sensor is outbutting somthing else, all should be fine. Green on, red off.
    digitalWrite(9, LOW); 
    digitalWrite(10, HIGH);
  }
    }

void calibrateSensor(void) {
// Assuming you're reading a sensor value as a float for calibration
String sensorData = softSerial.readStringUntil('\n');
//float sensorValue = sensorData.toFloat(10.0); // Convert sensor data to float

if(A2 == theoretical){
  calibrationOffset == A2;
}
  else {
  calibrationOffset = theoretical - A2;
}
//if(A2 != theoretical){
  //calibrationOffset == theoretical - A2;
//}


// Store the calibration offset in EEPROM
EEPROM.put(calibrationOffsetaddress, calibrationOffset);  // Make sure calibrationOffsetAddress is correctly declared

Serial.println("Calibration completed.");
}

im using this code, and the theoretical calculations are correct and working, but the calibration of the CO2 sensor isn't i dont know if it is the button or the calibration loop that isn't working. i have used chatGPT to try and find a solution to my problems, but they don't work. do any of you guys have some ideas of how i could solve my problem :smiley:

which arduino do you use ?

A2 is the name of an analog pin usually

im using an arduino UNO

you should not use a variable named A2 for coherence

also you likely have a bug here where you use a comparison operator == instead of assignment =

you are right, i changed it, but the problem is still there. And why shouldn't i use A2 for coherence?

because A0, A1, A2, ... A5 on your UNO are constants defined (and understood) to represent the pin numbers of the analog port

You would do things like analogRead(A2); for example

➜ using the same denomination for something else is confusing (it works because you create a local variable obfuscating the global constant).

can you clarify what the exact problem is?

well the calibration isn't initiating when the button is pushed as it should, so in the display, the theoretical = 12 but the readings from the sensor says 5%, or 4% or whatever, i doesn't say what it should be. and i have tested if the button i connected correctly and that there is no loose connections. and thanks i did not consider that

How do you know?

calibrateSensor(); // Call your calibration function

Put print statements all over the place, like just before you call calibrateSensor(), when you enter it and to check the values of variables to see if they are plausible.

Try just getting the button to work in the simplest sketch you or chatGPT can write.

I'm thinking it isn't the button at all.

a7

can you clarify what pin 8 is used for ?


this call might be blocking until a timeout. also you have delays elsewhere in the code, are you sure you are getting what you need?

sensorpin 8 is the digital 8 pin, i'll try the print statements and see if it is working. until a timeout, like a delay? and i don't know really, i quite new at coding so i dont know if the delays mess up the script

You don't use it really in the code as sensorPin but it's meant to be the Rx pin of softSerial...
confusing...