Ciao a tutti, mi sto avvicinando da poco all'elettronica, vi spiego subito cosa voglio fare: voglio leggere il valore di concentrazione di Co2 in una stanza con arduino.
Il mio problema è che non riesco a "decifrare" il valore che entra in arduino tramite la porta analogica nel valore corrispondente in ppm. Su internet alcuni usano il logaritmo e altri effettuano delle calibrazioni.
Io vorrei usare il logaritmo ma le formule che ho trovato su internet non mi danno valori corretti, sareste cosi gentili da spiegarmi come ricavare la formula per convertire il valore di arduino in ppm, dal grafico del datasheet non riesco a capire perchè è fuori scala.
Per adesso, visto che ancora non ho un arduino sto facendo solo delle simulazioni al computer.
Grazie a tutti in anticipo. 
Sensore con datasheet: MG-811 CO2 Sensor Module | Sandbox Electronics
Formula che ho provato: Antilog converter linearizes carbon dioxide sensor -
Il cross-posting è vietato.
http://forum.arduino.cc/index.php?topic=304868.msg2119798#msg2119798
Poi in sezione internazionale DEVI usare l'inglese.
Ti invitiamo a presentarti (dicci quali conoscenze hai di elettronica e di programmazione) qui: Presentazioni
e a leggere il regolamento: Regolamento
Si, avevo sbagliato sezione, adesso mi presento 
ma scusa, al link che hai nesso tu stesso MG-811 CO2 Sensor Module | Sandbox Electronics c'è anche il codice bello e fatto!
credo di non avere capito la domanda!
La formula del secondo link fa riferimento al solo sensore (range uscita 265-325 mV).
Il primo link, invece, fa riferimento al modulo che comprende anche un amplificatore operazionale per aumentare il segnale in uscita sino ai 5V di Arduino.
Intanto vi ringrazio, il problema è che anche con i calcoli di sandboxelectronics mi da dei risultati errati.
Cyberhs sapresti dirmi come fare per ottenere la formula con il logaritmo con il sensore montato sul modulo?
Fammi vedere il tuo listato che provo a verificarlo.
Ok, il programma è questo, spero che tu riesca a capire:
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
LiquidCrystal_I2C lcd(0x27,16,2); // set the LCD address to 0x27 for a 16 chars and 2 line display
const int apertura = 13;
const int chiusura = 12;
const int analogPin = A0;
int ValoreConvertire;
int Valoreppm;
int stato = 1; //imposto inizialmente la finestra chiusa
float deltavs;
float v400ppm = 4.535; //IMPOSTARE CON CALIBRAZIONE /_____________________________________
float v40000ppm = 3.206; //IMPOSTARE CON CALIBRAZIONE \
float deltavs = (v400ppm - v40000ppm);
float A = deltavs/(log10(400) - log10(40000));
float B = log10(400);
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void setup() {
pinMode(apertura, OUTPUT); //definisce i pin apertura e chiusura come output
pinMode(chiusura, OUTPUT);
// inizia comunicazione seriale a 9600
Serial.begin(9600);
lcd.init();
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void loop() {
int ValoreConvertire = analogRead(analogPin); //legge valore da sensore
float voltaggio = ValoreConvertire/204.6; //converte valore da sensore in voltaggio
float power = ((voltaggio - v400ppm)/A) + B; //calcola CO2 con formula e logaritmo
float co2ppm = pow(10,power);
Valoreppm = co2ppm;
lcd.home();
lcd.print("Co2 in ppm = ");
lcd.print(Valoreppm);
// attiva pin 13 apertura se valore ppm superiore a 1300
if ((Valoreppm>1300)&&(stato == 1)){
lcd.home();
lcd.print("Valore superiore a 1300ppm... ");
digitalWrite(chiusura, LOW); // spengo segnale di chiusura voglio essere sicuro che il segnale di chiusura sia spento, il motore si era gia spento dal circuito fisico con fc
lcd.setCursor(0,1);
lcd.print("Apro la finestra");
digitalWrite(apertura, HIGH); //faccio partire l'apertura con circuito fisico si ferma quando aperta del tutto
stato = 1 - stato; //0 = finestra aperta o in apertura
}
if ((Valoreppm<800)&&(stato == 0)){
lcd.home();
lcd.print("Valore inferiore a 800ppm... ");
digitalWrite(apertura, LOW); //spengo o lascio spento il segnale di apertura voglio essere sicuro che il segnale di apertura sia spento, il motore era già spento dal circuito fisico con fc
lcd.setCursor(0,1);
lcd.print("Chiudo la finestra");
digitalWrite(chiusura, HIGH); //faccio partire la chiusura con circuito fisico si ferma quando chiusa del tutto
stato = 1 - stato; //0 = finestra chiusa o in chiusura
}
delay(5000); //aspetta mezzo secondo prima di ripartire
}
Se hai il modulo della Sandbox devi usare il loro software, eventualmente modificato per le tue esigenze.
Comunque, ho notato che leggi solo una volta l'ingresso analogico: devi fare almeno 10 misure e fare la media dei valori.
float voltaggio = ValoreConvertire / 204.6;
Non capisco da dove hai tirato fuori questa conversione.
L'amplificatore del modulo amplifica il segnale di 8.5 volte quindi il massimo che leggerai sarà 8.5 x 322mV = 2.74V: considerando che il convertitore ha un passo di circa 5mv dovresti leggere il valore 548.
Hai usato poi la costante float v40000ppm = 3.206; ma quel sensore ha un range sino a 10000 ppm.
Grazie mille! Il codice l'avevo preso da questo sito: http://www.projectems.it/monitoraggio-ambientale-monitoraggio-co2-arduino/
Su alcuni calcoli ero in dubbio anche io ma non sapevo cosa fare. Il programma di sandbox è questo, prima di provarlo mi potresti dire come funziona e a cosa servono tutti i calcoli che fa?
E' questo:
/*******************Demo for MG-811 Gas Sensor Module V1.1*****************************
Author: Tiequan Shao: tiequan.shao@sandboxelectronics.com
Peng Wei: peng.wei@sandboxelectronics.com
Lisence: Attribution-NonCommercial-ShareAlike 3.0 Unported (CC BY-NC-SA 3.0)
Note: This piece of source code is supposed to be used as a demostration ONLY. More
sophisticated calibration is required for industrial field application.
Sandbox Electronics 2012-05-31
************************************************************************************/
/************************Hardware Related Macros************************************/
#define MG_PIN (0) //define which analog input channel you are going to use
#define BOOL_PIN (2)
#define DC_GAIN (8.5) //define the DC gain of amplifier
/***********************Software Related Macros************************************/
#define READ_SAMPLE_INTERVAL (50) //define how many samples you are going to take in normal operation
#define READ_SAMPLE_TIMES (5) //define the time interval(in milisecond) between each samples in
//normal operation
/**********************Application Related Macros**********************************/
//These two values differ from sensor to sensor. user should derermine this value.
#define ZERO_POINT_VOLTAGE (0.220) //define the output of the sensor in volts when the concentration of CO2 is 400PPM
#define REACTION_VOLTGAE (0.020) //define the voltage drop of the sensor when move the sensor from air into 1000ppm CO2
/*****************************Globals***********************************************/
float CO2Curve[3] = {2.602,ZERO_POINT_VOLTAGE,(REACTION_VOLTGAE/(2.602-3))};
//two points are taken from the curve.
//with these two points, a line is formed which is
//"approximately equivalent" to the original curve.
//data format:{ x, y, slope}; point1: (lg400, 0.324), point2: (lg4000, 0.280)
//slope = ( reaction voltage ) / (log400 –log1000)
void setup()
{
Serial.begin(9600); //UART setup, baudrate = 9600bps
pinMode(BOOL_PIN, INPUT); //set pin to input
digitalWrite(BOOL_PIN, HIGH); //turn on pullup resistors
Serial.print("MG-811 Demostration\n");
}
void loop()
{
int percentage;
float volts;
volts = MGRead(MG_PIN);
Serial.print( "SEN-00007:" );
Serial.print(volts);
Serial.print( "V " );
percentage = MGGetPercentage(volts,CO2Curve);
Serial.print("CO2:");
if (percentage == -1) {
Serial.print( "<400" );
} else {
Serial.print(percentage);
}
Serial.print( "ppm" );
Serial.print("\n");
if (digitalRead(BOOL_PIN) ){
Serial.print( "=====BOOL is HIGH======" );
} else {
Serial.print( "=====BOOL is LOW======" );
}
Serial.print("\n");
delay(200);
}
/***************************** MGRead *********************************************
Input: mg_pin - analog channel
Output: output of SEN-000007
Remarks: This function reads the output of SEN-000007
************************************************************************************/
float MGRead(int mg_pin)
{
int i;
float v=0;
for (i=0;i<READ_SAMPLE_TIMES;i++) {
v += analogRead(mg_pin);
delay(READ_SAMPLE_INTERVAL);
}
v = (v/READ_SAMPLE_TIMES) *5/1024 ;
return v;
}
/***************************** MQGetPercentage **********************************
Input: volts - SEN-000007 output measured in volts
pcurve - pointer to the curve of the target gas
Output: ppm of the target gas
Remarks: By using the slope and a point of the line. The x(logarithmic value of ppm)
of the line could be derived if y(MG-811 output) is provided. As it is a
logarithmic coordinate, power of 10 is used to convert the result to non-logarithmic
value.
************************************************************************************/
int MGGetPercentage(float volts, float *pcurve)
{
if ((volts/DC_GAIN )>=ZERO_POINT_VOLTAGE) {
return -1;
} else {
return pow(10, ((volts/DC_GAIN)-pcurve[1])/pcurve[2]+pcurve[0]);
}
}