Forum >is my SEN0219 giving normal output? See graph
is my SEN0219 giving normal output? See graph

Hello,
I am using the following code and it appears this sensor is all over the place!!


I decided to map out the data points to try and figure out what i was seeing. The data in the serial monitor seemed very erratic. Does my sensor have issues or is this normal? I thought these things were supposed to be accurate lol. Please help!
GRAPH: https://imgur.com/a/WKT2S
Arduino Sketch Code:
---------------------------------------------------------------
int sensorIn = A3;
void setup(){
Serial.begin(9600);
// Set the default voltage of the reference voltage
// analogReference(DEFAULT);
}
void loop(){
String CO2PPM;
CO2PPM = CO2Read();
Serial.println(CO2PPM);
delay(2);
}
String CO2Read(){
//Read voltage
int sensorValue = analogRead(sensorIn);
// The analog signal is converted to a voltage
float voltage = sensorValue*(5000/1024.0);
if(voltage == 0)
{
Serial.println("Fault");
}
else if(voltage < 400)
{
Serial.println("preheating");
}
else
{
int voltage_diference=voltage-400;
float concentration=voltage_diference*50.0/16.0;
return String(concentration);
}
}
-------------------- Python Pandas Plotting Code-------------------------------------------------
import pandas as pd
df = pd.read_csv('/home/myuser/co2.log', parse_dates=True, index_col=0, names = ['timestamp', 'co2reading'])
ax = df.plot(figsize=(40,10))
fig = ax.get_figure()
fig.savefig('asdf.png')
---------------------Python Script Write Data to file from Serial Out -----------------------------
## import the serial library
import serial
from time import localtime, strftime, sleep
## Boolean variable that will represent
## whether or not the arduino is connected
connected = False
## establish connection to the serial port that your arduino
## is connected to.
#locations=['/dev/ttyUSB0','/dev/ttyUSB1','/dev/ttyUSB2','/dev/ttyUSB3']
locations=['/dev/ttyACM0','/dev/ttyACM1','/dev/ttyACM2','/dev/ttyACM3']
for device in locations:
try:
print "Trying...",device
ser = serial.Serial(device, 9600)
break
except:
print "Failed to connect on",device
## loop until the arduino tells us it is ready
while not connected:
serin = ser.read()
connected = True
## open text file to store the current
text_file = open("/home/myuser/co2.log", 'w+')
counter = 0
while True:
if ser.inWaiting():
counter +=1
x = ser.readline()
x = x.decode('utf-8', 'ignore').encode("utf-8")
mytime = strftime("%Y-%m-%d %H:%M:%S", localtime())
msgformat = '{},{}'.format(mytime, x)
if counter > 500:
text_file.write(msgformat)
print msgformat
text_file.flush()
else:
print 'waiting'
continue
if x=="\n":
text_file.seek(0)
text_file.truncate()
## close the serial connection and text file
text_file.close()
ser.close()
I am using the following code and it appears this sensor is all over the place!!



I decided to map out the data points to try and figure out what i was seeing. The data in the serial monitor seemed very erratic. Does my sensor have issues or is this normal? I thought these things were supposed to be accurate lol. Please help!
GRAPH: https://imgur.com/a/WKT2S
Arduino Sketch Code:
---------------------------------------------------------------
int sensorIn = A3;
void setup(){
Serial.begin(9600);
// Set the default voltage of the reference voltage
// analogReference(DEFAULT);
}
void loop(){
String CO2PPM;
CO2PPM = CO2Read();
Serial.println(CO2PPM);
delay(2);
}
String CO2Read(){
//Read voltage
int sensorValue = analogRead(sensorIn);
// The analog signal is converted to a voltage
float voltage = sensorValue*(5000/1024.0);
if(voltage == 0)
{
Serial.println("Fault");
}
else if(voltage < 400)
{
Serial.println("preheating");
}
else
{
int voltage_diference=voltage-400;
float concentration=voltage_diference*50.0/16.0;
return String(concentration);
}
}
-------------------- Python Pandas Plotting Code-------------------------------------------------
import pandas as pd
df = pd.read_csv('/home/myuser/co2.log', parse_dates=True, index_col=0, names = ['timestamp', 'co2reading'])
ax = df.plot(figsize=(40,10))
fig = ax.get_figure()
fig.savefig('asdf.png')
---------------------Python Script Write Data to file from Serial Out -----------------------------
## import the serial library
import serial
from time import localtime, strftime, sleep
## Boolean variable that will represent
## whether or not the arduino is connected
connected = False
## establish connection to the serial port that your arduino
## is connected to.
#locations=['/dev/ttyUSB0','/dev/ttyUSB1','/dev/ttyUSB2','/dev/ttyUSB3']
locations=['/dev/ttyACM0','/dev/ttyACM1','/dev/ttyACM2','/dev/ttyACM3']
for device in locations:
try:
print "Trying...",device
ser = serial.Serial(device, 9600)
break
except:
print "Failed to connect on",device
## loop until the arduino tells us it is ready
while not connected:
serin = ser.read()
connected = True
## open text file to store the current
text_file = open("/home/myuser/co2.log", 'w+')
counter = 0
while True:
if ser.inWaiting():
counter +=1
x = ser.readline()
x = x.decode('utf-8', 'ignore').encode("utf-8")
mytime = strftime("%Y-%m-%d %H:%M:%S", localtime())
msgformat = '{},{}'.format(mytime, x)
if counter > 500:
text_file.write(msgformat)
print msgformat
text_file.flush()
else:
print 'waiting'
continue
if x=="\n":
text_file.seek(0)
text_file.truncate()
## close the serial connection and text file
text_file.close()
ser.close()
2017-05-23 04:32:47 Happy to help.
Yes, code returns -1 sometimes. This was just a prototype.
I suspect that it happens when no reading values are within 10% of initial mean value. For example, when values are [1, 1, 1, 1, 10, 10, 10, 10], the mean is 5.5. Now, it will recalculate the mean for values within 5.2225 and 5.775, and there are none. Hence new mean will be 0 divided by 0, which I suspect returns -1. Hence, you should introduce a if condition such as:
if(media_final == -1)
{
//do something... either
// media_final = media_total
//or calculate media_final using a higher percentage, for example 20%
}
jose.filipe.domingues
Yes, code returns -1 sometimes. This was just a prototype.
I suspect that it happens when no reading values are within 10% of initial mean value. For example, when values are [1, 1, 1, 1, 10, 10, 10, 10], the mean is 5.5. Now, it will recalculate the mean for values within 5.2225 and 5.775, and there are none. Hence new mean will be 0 divided by 0, which I suspect returns -1. Hence, you should introduce a if condition such as:
if(media_final == -1)
{
//do something... either
// media_final = media_total
//or calculate media_final using a higher percentage, for example 20%
}

2017-05-18 09:47:52 makes sense. Thanks a million for sharing your code. I have it working, however i've noticed for some reason most of the time my "MEAN FINAL" == -1. I've been playing around with the code a bit to try and determine what causes this without any luck. do you have any idea?
jose.filipe.domingues wrote:
> Hi,
>
> I got my sensor this week as well and had some trouble to understand how it works.
> I have a post from a few days back.
>
> The values seem OK to me. Here are a few recommendations based on my experience:
>
> 1. Develop an algorithm to avoid getting measures "all over the place", for example,
> mean. Record n values in array and then calculate the mean. You will start to see
> that values start to get consistent. If you want further accuracy then after calculating
> the mean try removing values too much outside of the mean.
>
> 2. Be aware that this sensor is very sensitive. I have it running for a few days
> non-stop. When I turn it on, being at the room, values range from 800 to 1100 ppm.
> When I leave the room for the night, the values lower to 350-400 ppm. A few minutes
> after returning to the room, in about 5 to 10 minutes the values go back to 800
> to 1100 ppm. The more people in the room, the higher the values. What I am trying
> to say, 10 minutes tests are insufficient to see the changes in CO2 that you would
> expect a lot faster.
>
> 3. Finally, be aware of the VCC input to the sensor. I noticed that using 4.8V or
> 5V seem to have minor impacts in the readings.
>
> You can try this code.
>
> int sensorIn = A0;
>
> int cycle_count = 0;
> const int array_number = 100;
> int co2_array[array_number];
> double sensor_error = 0.05; //10%
>
> void setup(){
> Serial.begin(9600);
> // Set the default voltage of the reference voltage
> analogReference(DEFAULT);
> }
>
> void loop()
> {
>
> if(cycle_count < array_number)
> {
>
> //Read voltage
> int sensorValue = analogRead(sensorIn);
>
> // The analog signal is converted to a voltage
> float voltage = sensorValue*(5000/1024.0);
> if(voltage == 0)
> {
> Serial.println("Fault");
> }
> else if(voltage < 400)
> {
> Serial.println("preheating");
> }
> else
> {
> int voltage_diference=voltage-400;
> int concentration=voltage_diference*50.0/16.0;
> // Print Voltage
> //Serial.print("voltage:");
> //Serial.print(voltage);
> //Serial.println("mv");
> //Print CO2 concentration
> //Serial.print(concentration);
> //Serial.println("ppm");
>
> co2_array[cycle_count] = concentration;
> cycle_count++;
> }
> }
> else
> {
> long media_total = 0;
> int margem_up = 0;
> int margem_down = 0;
> for(int i = 0; i < array_number; i++)
> {
> media_total = media_total + co2_array[i];
> }
> media_total = media_total / array_number;
> margem_up = media_total * (1 + sensor_error);
> margem_down = media_total * (1 - sensor_error);
>
> Serial.print("MEAN TOTAL: "); Serial.println(media_total);
> Serial.print("MARGIN UP : "); Serial.println(media_total * (1+sensor_error));
> Serial.print("MARGIN DOWN: "); Serial.println(media_total * (1-sensor_error));
>
> int valores_validos = 0;
> long media_final = 0;
> for(int i = 0; i < array_number; i++)
> {
> if((co2_array[i] < margem_up) &&
> (co2_array[i] > margem_down))
> {
> media_final = media_final + co2_array[i];
> valores_validos++;
> }
> }
> media_final = media_final / valores_validos;
>
> Serial.print("MEAN FINAL: "); Serial.println(media_final);
> Serial.print("NUM VALORES: "); Serial.println(valores_validos);
>
> cycle_count = 0;
> }
>
> delay(25);
> }
zachary.hatsis
jose.filipe.domingues wrote:
> Hi,
>
> I got my sensor this week as well and had some trouble to understand how it works.
> I have a post from a few days back.
>
> The values seem OK to me. Here are a few recommendations based on my experience:
>
> 1. Develop an algorithm to avoid getting measures "all over the place", for example,
> mean. Record n values in array and then calculate the mean. You will start to see
> that values start to get consistent. If you want further accuracy then after calculating
> the mean try removing values too much outside of the mean.
>
> 2. Be aware that this sensor is very sensitive. I have it running for a few days
> non-stop. When I turn it on, being at the room, values range from 800 to 1100 ppm.
> When I leave the room for the night, the values lower to 350-400 ppm. A few minutes
> after returning to the room, in about 5 to 10 minutes the values go back to 800
> to 1100 ppm. The more people in the room, the higher the values. What I am trying
> to say, 10 minutes tests are insufficient to see the changes in CO2 that you would
> expect a lot faster.
>
> 3. Finally, be aware of the VCC input to the sensor. I noticed that using 4.8V or
> 5V seem to have minor impacts in the readings.
>
> You can try this code.
>
> int sensorIn = A0;
>
> int cycle_count = 0;
> const int array_number = 100;
> int co2_array[array_number];
> double sensor_error = 0.05; //10%
>
> void setup(){
> Serial.begin(9600);
> // Set the default voltage of the reference voltage
> analogReference(DEFAULT);
> }
>
> void loop()
> {
>
> if(cycle_count < array_number)
> {
>
> //Read voltage
> int sensorValue = analogRead(sensorIn);
>
> // The analog signal is converted to a voltage
> float voltage = sensorValue*(5000/1024.0);
> if(voltage == 0)
> {
> Serial.println("Fault");
> }
> else if(voltage < 400)
> {
> Serial.println("preheating");
> }
> else
> {
> int voltage_diference=voltage-400;
> int concentration=voltage_diference*50.0/16.0;
> // Print Voltage
> //Serial.print("voltage:");
> //Serial.print(voltage);
> //Serial.println("mv");
> //Print CO2 concentration
> //Serial.print(concentration);
> //Serial.println("ppm");
>
> co2_array[cycle_count] = concentration;
> cycle_count++;
> }
> }
> else
> {
> long media_total = 0;
> int margem_up = 0;
> int margem_down = 0;
> for(int i = 0; i < array_number; i++)
> {
> media_total = media_total + co2_array[i];
> }
> media_total = media_total / array_number;
> margem_up = media_total * (1 + sensor_error);
> margem_down = media_total * (1 - sensor_error);
>
> Serial.print("MEAN TOTAL: "); Serial.println(media_total);
> Serial.print("MARGIN UP : "); Serial.println(media_total * (1+sensor_error));
> Serial.print("MARGIN DOWN: "); Serial.println(media_total * (1-sensor_error));
>
> int valores_validos = 0;
> long media_final = 0;
> for(int i = 0; i < array_number; i++)
> {
> if((co2_array[i] < margem_up) &&
> (co2_array[i] > margem_down))
> {
> media_final = media_final + co2_array[i];
> valores_validos++;
> }
> }
> media_final = media_final / valores_validos;
>
> Serial.print("MEAN FINAL: "); Serial.println(media_final);
> Serial.print("NUM VALORES: "); Serial.println(valores_validos);
>
> cycle_count = 0;
> }
>
> delay(25);
> }

2017-05-15 20:30:19 That's a good idea to do with the sensitive outputs. And the response time of the sensor is 120 seconds on the WIKI, it's comparatively slow.
robert.chen

2017-05-14 02:13:05 Hi,
I got my sensor this week as well and had some trouble to understand how it works. I have a post from a few days back.
The values seem OK to me. Here are a few recommendations based on my experience:
1. Develop an algorithm to avoid getting measures "all over the place", for example, mean. Record n values in array and then calculate the mean. You will start to see that values start to get consistent. If you want further accuracy then after calculating the mean try removing values too much outside of the mean.
2. Be aware that this sensor is very sensitive. I have it running for a few days non-stop. When I turn it on, being at the room, values range from 800 to 1100 ppm. When I leave the room for the night, the values lower to 350-400 ppm. A few minutes after returning to the room, in about 5 to 10 minutes the values go back to 800 to 1100 ppm. The more people in the room, the higher the values. What I am trying to say, 10 minutes tests are insufficient to see the changes in CO2 that you would expect a lot faster.
3. Finally, be aware of the VCC input to the sensor. I noticed that using 4.8V or 5V seem to have minor impacts in the readings.
You can try this code.
int sensorIn = A0;
int cycle_count = 0;
const int array_number = 100;
int co2_array[array_number];
double sensor_error = 0.05; //10%
void setup(){
Serial.begin(9600);
// Set the default voltage of the reference voltage
analogReference(DEFAULT);
}
void loop()
{
if(cycle_count < array_number)
{
//Read voltage
int sensorValue = analogRead(sensorIn);
// The analog signal is converted to a voltage
float voltage = sensorValue*(5000/1024.0);
if(voltage == 0)
{
Serial.println("Fault");
}
else if(voltage < 400)
{
Serial.println("preheating");
}
else
{
int voltage_diference=voltage-400;
int concentration=voltage_diference*50.0/16.0;
// Print Voltage
//Serial.print("voltage:");
//Serial.print(voltage);
//Serial.println("mv");
//Print CO2 concentration
//Serial.print(concentration);
//Serial.println("ppm");
co2_array[cycle_count] = concentration;
cycle_count++;
}
}
else
{
long media_total = 0;
int margem_up = 0;
int margem_down = 0;
for(int i = 0; i < array_number; i++)
{
media_total = media_total + co2_array[i];
}
media_total = media_total / array_number;
margem_up = media_total * (1 + sensor_error);
margem_down = media_total * (1 - sensor_error);
Serial.print("MEAN TOTAL: "); Serial.println(media_total);
Serial.print("MARGIN UP : "); Serial.println(media_total * (1+sensor_error));
Serial.print("MARGIN DOWN: "); Serial.println(media_total * (1-sensor_error));
int valores_validos = 0;
long media_final = 0;
for(int i = 0; i < array_number; i++)
{
if((co2_array[i] < margem_up) &&
(co2_array[i] > margem_down))
{
media_final = media_final + co2_array[i];
valores_validos++;
}
}
media_final = media_final / valores_validos;
Serial.print("MEAN FINAL: "); Serial.println(media_final);
Serial.print("NUM VALORES: "); Serial.println(valores_validos);
cycle_count = 0;
}
delay(25);
}
jose.filipe.domingues
I got my sensor this week as well and had some trouble to understand how it works. I have a post from a few days back.
The values seem OK to me. Here are a few recommendations based on my experience:
1. Develop an algorithm to avoid getting measures "all over the place", for example, mean. Record n values in array and then calculate the mean. You will start to see that values start to get consistent. If you want further accuracy then after calculating the mean try removing values too much outside of the mean.
2. Be aware that this sensor is very sensitive. I have it running for a few days non-stop. When I turn it on, being at the room, values range from 800 to 1100 ppm. When I leave the room for the night, the values lower to 350-400 ppm. A few minutes after returning to the room, in about 5 to 10 minutes the values go back to 800 to 1100 ppm. The more people in the room, the higher the values. What I am trying to say, 10 minutes tests are insufficient to see the changes in CO2 that you would expect a lot faster.
3. Finally, be aware of the VCC input to the sensor. I noticed that using 4.8V or 5V seem to have minor impacts in the readings.
You can try this code.
int sensorIn = A0;
int cycle_count = 0;
const int array_number = 100;
int co2_array[array_number];
double sensor_error = 0.05; //10%
void setup(){
Serial.begin(9600);
// Set the default voltage of the reference voltage
analogReference(DEFAULT);
}
void loop()
{
if(cycle_count < array_number)
{
//Read voltage
int sensorValue = analogRead(sensorIn);
// The analog signal is converted to a voltage
float voltage = sensorValue*(5000/1024.0);
if(voltage == 0)
{
Serial.println("Fault");
}
else if(voltage < 400)
{
Serial.println("preheating");
}
else
{
int voltage_diference=voltage-400;
int concentration=voltage_diference*50.0/16.0;
// Print Voltage
//Serial.print("voltage:");
//Serial.print(voltage);
//Serial.println("mv");
//Print CO2 concentration
//Serial.print(concentration);
//Serial.println("ppm");
co2_array[cycle_count] = concentration;
cycle_count++;
}
}
else
{
long media_total = 0;
int margem_up = 0;
int margem_down = 0;
for(int i = 0; i < array_number; i++)
{
media_total = media_total + co2_array[i];
}
media_total = media_total / array_number;
margem_up = media_total * (1 + sensor_error);
margem_down = media_total * (1 - sensor_error);
Serial.print("MEAN TOTAL: "); Serial.println(media_total);
Serial.print("MARGIN UP : "); Serial.println(media_total * (1+sensor_error));
Serial.print("MARGIN DOWN: "); Serial.println(media_total * (1-sensor_error));
int valores_validos = 0;
long media_final = 0;
for(int i = 0; i < array_number; i++)
{
if((co2_array[i] < margem_up) &&
(co2_array[i] > margem_down))
{
media_final = media_final + co2_array[i];
valores_validos++;
}
}
media_final = media_final / valores_validos;
Serial.print("MEAN FINAL: "); Serial.println(media_final);
Serial.print("NUM VALORES: "); Serial.println(valores_validos);
cycle_count = 0;
}
delay(25);
}
