Possibly faulty data from pins

Hello!

Info about the project
We're in the process of creating a low cost air quality measing platform. At the moment, we're trying to implement two sensors, measuring NO2 and O3, to the Adafruit Feather M0. The sensors are connected to an AFE.

Data sheets:
Sensors data sheet:

AFE data sheet:

Adafruit Feather M0:

This is the code we're currently using:

// Variables and pins
int SN1_WE;
int SN1_Aux;
int SN2_WE;
int SN2_Aux;
int Volt_PT;
int WE1Pin = A2; //OP1
int Aux1Pin = A5; //OP2
int WE2Pin = A1; //OP3
int Aux2Pin = 9; //OP4
int PTPin = 6; //Pt1000+

// Variables in formulas
float Temp_PT;        // PT1000
float SN1_WE_Real;    // NO2 WE
float SN1_Aux_Real;   // NO2 Aux
float NO2;            // NO2 ppb
float SN2_WE_Real;    // O3 WE
float SN2_Aux_Real;   // O3 Aux
float O3;             // O3 ppb

//Calibration constants (taken from calibration sheet)
// for SN1 or NO2
float SN1_TOTAL_WE = 0.288;
float SN1_TOTAL_AE = 0.299;
float SN1_SENSITIVITY = 0.188; 
// for SN2 or O3
float SN2_TOTAL_WE = 0.403;
float SN2_TOTAL_AE = 0.405;
float SN2_SENSITIVITY = 0.344;

void setup ()
{
  Serial.begin (9600);
}

void loop()
{
  SN1_WE = analogRead(WE1Pin);
  delay(10);
  SN1_Aux = analogRead(Aux1Pin);
  delay(10);
  SN2_WE = analogRead(WE2Pin);
  delay(10);
  SN2_Aux = analogRead(Aux2Pin);
  delay(10);
  Volt_PT = analogRead(PTPin);
  
  Temp_PT = 20 + ((Volt_PT - (0.297)*(0.3000))/(0.0010)); // From user manual: V = 0.297(V_20C)+0.0010*(T-T_20C) => T = T_20C + (V-0.297*V_20C)/0.0010
  Serial.print("Temperature = ");
  Serial.print(Temp_PT);
  Serial.println();

  Serial.print("Volt_Pt = ");
  Serial.print(Volt_PT);
  Serial.println();

    SN1_WE_Real = SN1_WE - SN1_TOTAL_WE;
    SN1_Aux_Real = SN1_Aux - SN1_TOTAL_AE; 
    NO2 = (SN1_WE_Real - SN1_Aux_Real)/(SN1_SENSITIVITY);
    Serial.print("NO2 Voltage = ");
    Serial.print(SN1_WE);
    Serial.print(" V");
    Serial.print(" ");
    Serial.print(SN1_Aux);
    Serial.print(" V");
    Serial.print(" - NO2 CONCENTRATION = ");
    Serial.print(NO2);
    Serial.print(" ppb");
    Serial.println();
  
    SN2_WE_Real = SN2_WE - SN2_TOTAL_WE;
    SN2_Aux_Real = SN2_Aux - SN2_TOTAL_AE;
    O3 = (SN2_WE_Real - SN2_Aux_Real)/(SN2_SENSITIVITY);
    Serial.print("O3 Voltage = ");
    Serial.print(SN2_WE);
    Serial.print(" V");
    Serial.print(" ");
    Serial.print(SN2_Aux);
    Serial.print(" V");
    Serial.print(" - O3 CONCENTRATION = ");
    Serial.print(O3);
    Serial.print(" ppb");
    Serial.println();

  }
  delay(1000);
  
}

Note: The code was largely copied from another topic: My Codes in AlphaSenseSensor "Help With our Project Air Quality Monitoring" - Project Guidance - Arduino Forum

This is a snippet of our output:
Temperature = 347930,91
Volt_Pt = 348
NO2 Voltage = 2 V 13 V - NO2 CONCENTRATION = -63.77 ppb
O3 Voltage = 1 V 15 V - O3 CONCENTRATION = -43.60 ppb

What is wrong? The volt reading from the Pt1000+ is around 350 Volts. This corresponds to a temperature of rougly 350 000 C, obviously incorrect. Furthermore, we have negative concentrations of O3 and NO2, also very incorrect.

What do we need help with? We're not sure what's causing the issues here. We believe there might be an error with the calibration and perhaps some grounding issues.

Any help/feedback is greatly appreciated.

A schematic and photos of your wiring could help.

The variable Volt_Pt is not a voltage, it is a count from the Arduino ADC. The count varies from 0 to 1023 (for example, assuming a 10 bit ADC). This is converted to a voltage by something like:
v = aref * (count / 1023)
where aref can be either external or internal to the Feather. See the Arduino analogRead documentation for more info. You will need to know the reference voltage and bit resolution of the Feather's ADC.

Because the Volt_Pt is a count and not a voltage, your temperature calculation is somewhere out in left field. First convert the Arduino count to an actual voltage and then go from there.
S.

Volt_PT = analogRead(PTPin);

Temp_PT = 20 + ((Volt_PT - (0.297)*(0.3000))/(0.0010));

//From user manual: V = 0.297(V_20C)+0.0010*(T-T_20C) => T = T_20C + (V-0.297*V_20C)/0.0010[
/quote]

As srturner says, Volt_PT is not a voltage so you cant use it in your next calculation.

That is why you get

The volt reading from the Pt1000+ is around 350 Volts

which should have been a clue.

srturner:
The variable Volt_Pt is not a voltage, it is a count from the Arduino ADC. The count varies from 0 to 1023 (for example, assuming a 10 bit ADC). This is converted to a voltage by something like:
v = aref * (count / 1023)
where aref can be either external or internal to the Feather. See the Arduino analogRead documentation for more info. You will need to know the reference voltage and bit resolution of the Feather's ADC.

Because the Volt_Pt is a count and not a voltage, your temperature calculation is somewhere out in left field. First convert the Arduino count to an actual voltage and then go from there.
S.

Thank you for the reply!
I tried looking up aRef (reference voltage) for the Feather M0 and found 3.3 V. I wasn't able to find the bit resolution, however. Do you think this code would give the correct reading of the voltage? Or do I need the make the variable sensorValue_PT an int?

sensorValue_PT = analogRead(PTPin);

volt_PT = 3.3*(sensorValue_PT/1023);

This link: https://www.arduino.cc/en/Tutorial/BuiltInExamples/ReadAnalogVoltage suggests the code

int sensorValue_PT = analogRead(PTPin);

float Volt_PT = sensorValue_PT*(5.0/1023);

Again, thank you for helping.

kandidat2021:

sensorValue_PT = analogRead(PTPin);

volt_PT = 3.3*(sensorValue_PT/1023);

Yes.
My previous post was not very clear, as I was called away abruptly while writing it. The following may be a bit more clear:

ADCs of this type produce an ouput which is a count. The value of the count is proportional to input voltage and two other parameters. The general equation for converting this to a voltage is:

voltage = Vref * (count / maxcount)

Vref is a reference voltage. This can often be either internal to the device or externally applied. It should be as stable as possible and as accurately known as possible because the value is directly reflected in the calculated voltage. Note that your input voltage should not exceed Vref.

maxcount is the maximum count which will be produced when Vin = Vref. It it equal to 2^(bit_resolution) minus 1 (because the count starts at 0). So for a 10 bit device it would be 1023. Bit resolutions of 8, 10, 12, and 16 are common. Sometimes the bit resolution is programmable. The device documentation and other code examples are good resources.
Note that the division must be floating, not integer operation. So you'd normally want to use an expression like
(float)sensorValue_PT / 1023
or something similar, to force a floating division.
In your specific case, it appears Vref is 3.3, but I'm not sure about the bit resolution. So try the set of equations above and see. You won't hurt anything by using the wrong bit resolution, you'll just get numbers which are half or twice (or 1/4 or 4x ...) what they should be.
This analysis is a bit simplified. Some ADCs can accept inputs which go negative, for example. You can tackle those as the need arises.
S.

Thank you for your help!

We're still not able to read the correct temperature, however. We're not able to retrieve any correct concentration, either.

Do you believe we have to convert each reading to a voltage before applying them to the equations?

This is our current code.

// Definiera variabler eller pins
int SN1_WE_read;
int SN1_Aux_read;
int SN2_WE_read;
int SN2_Aux_read;
int WE1Pin = A2; //OP1
int Aux1Pin = A5; //OP2
int WE2Pin = A1; //OP3
int Aux2Pin = 13; //OP4
int PTPin = 6; //Pt1000+         

// Används i formler
float Temp_PT;        // PT1000
float sensorValue_PT; // PT1000
float Volt_PT; // PT1000
float SN1_WE_Real;    // NO2 WE
float SN1_Aux_Real;   // NO2 Aux
float NO2;            // NO2 ppb
float SN2_WE_Real;    // O3 WE
float SN2_Aux_Real;   // O3 Aux
float O3_withoutCorrection; //O3 without correction
float O3;             // O3 ppb
float SN1_WE;
float SN1_Aux;
float SN2_WE;
float SN2_Aux;


//Calibration constants
// för SN1 eller NO2
float SN1_TOTAL_WE = 0.288;
float SN1_TOTAL_AE = 0.299;
float SN1_SENSITIVITY = 0.188; //(mV/ppb)
// för SN2 eller O3
float SN2_TOTAL_WE = 0.403;
float SN2_TOTAL_AE = 0.405;
float SN2_SENSITIVITY = 0.344;

void setup ()
{
  Serial.begin (9600);
}

void loop()
{
  SN1_WE_read = analogRead(WE1Pin);
  SN1_WE = 3.3*(float(SN1_WE_read)/1023.0);
  delay(10);
  SN1_Aux_read = analogRead(Aux1Pin);
  SN1_Aux = 3.3*(float(SN1_Aux_read)/1023.0);
  delay(10);
  SN2_WE_read = analogRead(WE2Pin);
  SN2_WE = 3.3*(float(SN2_WE_read)/1023.0);
  delay(10);
  SN2_Aux_read = analogRead(Aux2Pin);
  SN2_Aux = 3.3*(float(SN2_Aux_read)/1023.0);
  delay(10);  

  sensorValue_PT = analogRead(PTPin); 
  Volt_PT = 3.3*(sensorValue_PT/1023.0); 
  
  // From user manual: V = 0.297(V_20C)+0.0010*(T-T_20C) => T = T_20C + (V-0.297(V_20C))/0.0010
                 
  Temp_PT = 20 + (Volt_PT - (0.297/0.0010));
  Serial.print("Temperature = ");
  Serial.print(Temp_PT);
  Serial.println();

  Serial.print("Volt_Pt = ");
  Serial.print(Volt_PT);
  Serial.println();

  SN1_WE_Real = SN1_WE - SN1_TOTAL_WE; //Read value (SN1_WE) minus offset-value(SN1_TOTAL_WE)
  SN1_Aux_Real = 1.35*(SN1_Aux - SN1_TOTAL_AE); //Read value (SN1_AUX) minus offset-value(SN1_TOTAL_AE), scaled.
  NO2 = (SN1_WE_Real - SN1_Aux_Real)/(SN1_SENSITIVITY); 
  Serial.print("NO2 Voltage = ");
  Serial.print(SN1_WE);
  Serial.print(" V");
  Serial.print(" ");
  Serial.print(SN1_Aux);
  Serial.print(" V");
  Serial.print(" - NO2 CONCENTRATION = ");
  Serial.print(NO2);
  Serial.print(" ppb");
  Serial.println();
  
  SN2_WE_Real = SN2_WE - SN2_TOTAL_WE;
  SN2_Aux_Real = 1.28*(SN2_Aux - SN2_TOTAL_AE);
  O3_withoutCorrection = (SN2_WE_Real - SN2_Aux_Real)/(SN2_SENSITIVITY); 
  O3 = O3_withoutCorrection-NO2;
  Serial.print("O3 Voltage = ");
  Serial.print(SN2_WE);
  Serial.print(" V");
  Serial.print(" ");
  Serial.print(SN2_Aux);
  Serial.print(" V");
  Serial.print(" - O3 CONCENTRATION = ");
  Serial.print(O3);
  Serial.print(" ppb");
  Serial.println();
  
  delay(1000);
}

This is our output:

Temperature = -275.72
Volt_Pt = 1.28
NO2 Voltage = 0.00 V 1.32 V - NO2 CONCENTRATION = -8.82 ppb
O3 Voltage = 0.00 V 1.49 V - O3 CONCENTRATION = 3.63 ppb

The pins which read the sensors need to be set as inputs, by statements such as
pinMode(PTPin, INPUT);
These are usually placed in the setup() routine.

If you still have trouble, I would suggest simplifying your code to just read and display a single sensor (display count, voltage, and calculated temperature). When you have this working properly, it is usually easy to add the other sensors. If you can't get a single sensor working right, there might be a problem with your wiring or the sensor itself.
S.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.