Hi. I'm rookie of using arduino controller and sensors.
I tried to use MG-811 sensor. but there's no satisfying code and result of this.
of course, I found some code of developer build.
But, When I combine these code with mine, there's error on it.
In datasheet of MG-811. It gives 0-10000ppm, but my sensor makes negative values.
Here's the result of mine.
As you see, CO2 sensor makes negative values and BOOL PIN status got LOW.
also, there's no Voltage on CO2, It doesn't heat itself.
let me explain my circuit with images.
I tried my codes with the code by developers.
here's code of MG-811 by dev.
/*******************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 (A0) //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.030) //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( "SEN0159:" );
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(500);
}
/***************************** 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]);
}
}
I tried to combine this code with mine. which uses Arduino Mega2560 and several sensors with Wi-Fi module.
here's my code.
#define esp8266 Serial3 //esp8266선을 RX,TX3으로 수정
#define BAUDRATE 9600
#include <Wire.h> //BH1750 조도센서 라이브러리 포함
#include <BH1750FVI.h>
#include <DHT.h> //DHT22 라이브러리 포함
// 핀 설정 및 센서 기본 변수 설정
#define DEBUG true //esp 설정
#define DHTPIN A0 //DHT22 온습도 센서 핀 설정
#define DHTTYPE DHT22
#define MG_PIN A1 //MG811 CO2센서 핀 설정
#define VltS A2
#define BOOL_PIN 2
#define DC_GAIN 8.5
#define READ_SAMPLE_INTERVAL 5
#define READ_SAMPLE_TIMES 5
#define ZERO_POINT_VOLTAGE 0.220
#define REACTION_VOLTAGE 0.030
#define RCPin1 3
#define RCPin2 4
//라이브러리별 설정
DHT dht(DHTPIN, DHTTYPE);
BH1750FVI::eDeviceMode_t DEVICEMODE = BH1750FVI::k_DevModeContHighRes;
BH1750FVI LightSensor(DEVICEMODE);
//전역변수 설정
float hum;
float temp;
float CO2Curve[3] = {2.602, ZERO_POINT_VOLTAGE, (REACTION_VOLTAGE / (2.602 - 3))};
float volts;
float vout = 0.0;
float vin = 0.0;
float R1 = 30000.0;
float R2 = 7500.0;
float Latitude, Longitude;
int Vval = 0;
int RCValue1;
int RCValue2;
int Angle;
int Spd_rpm;
int Spd_rps;
//String형태로 입출력 변수 설정
String AP = "bime0304_2.5G"; //Wifi설정
String PASS = "bime0304";
String WApiKey = "CU8634SH66Q1MLO9"; //ThingSpeak 내 Write API
String RApiKey = "XMP6OYHXR8RYX55A"; //ThingSpeak 내 Read API
String HOST = "api.thingspeak.com";
String PORT = "80";
String fieldTemp = "field1"; //Air Temperature 필드1 설정(최대 8)
String fieldHum = "field2"; //Air humidity 필드2 설정
String fieldLight = "field3"; //Light Intensity 필드3 설정
String fieldCO2 = "field4"; //CO2 센서 필드 4 설정
String fieldVolt = "field5";
String fieldangle = "field6";
String fieldspeed = "field7";
int countTrueCommand; //ESP8266 커맨드 카운트 함수
int countTimeCommand;
boolean found = false;
int percentage; //CO2센서 전역변수 설정
//CO2 계산 함수
int MGGetPercentage(float volts, float * pcurve) //MGGetPercentage 변수
{
if ((volts / DC_GAIN ) >= ZERO_POINT_VOLTAGE) {
return -1;
} else {
return pow(10, ((volts / DC_GAIN) - pcurve[1]) / pcurve[2] + pcurve[0]);
}
}
float MGRead(int mg_pin) //MGRead변수
{
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;
}
void setup()
{
unsigned int i = 0;
// Open Serial1 communications and wait for port to open:
// 시리얼 1 통신 시작 및 열릴때까지 대기
esp8266.begin(BAUDRATE); //ESP8266 보드레이트 설정
esp8266.setTimeout(5000);
dht.begin(); //온습도 시작
LightSensor.begin(); //조도 센서 시작
Serial.begin(9600); //시리얼 통신 시작
pinMode(RCPin1, INPUT);
pinMode(RCPin2, INPUT);
pinMode(BOOL_PIN, INPUT);
pinMode(VltS, INPUT);
digitalWrite(BOOL_PIN, HIGH);
Serial.println("Thingspeak with ESP-01");
//ESPWiFi 셋팅
sendCommand("AT", 5, "OK");
sendCommand("AT+CWMODE=1", 5, "OK");
sendCommand("AT+CWJAP=\"" + AP + "\",\"" + PASS + "\"", 20, "OK");
//IP획득 및 표시
sendCommand("AT+CIFSR", 2, "OK");
delay(2000);
}
//반복 조건
void loop()
{
hum = dht.readHumidity(); //습도 읽는 함수
temp = dht.readTemperature(); //온도 읽는 함수
uint16_t lux = LightSensor.GetLightIntensity(); //조도 읽는 함수
Vval = analogRead(VltS);
vout = (Vval * 5.0) / 1024.0;
vin = vout / (R2 / (R1 + R2)); //전압 센서
volts = MGRead(MG_PIN); //CO2내 전압
percentage = MGGetPercentage(volts, CO2Curve);
RCValue1 = pulseIn(RCPin1, HIGH);
RCValue2 = pulseIn(RCPin2, HIGH);
Angle = map(RCValue2, 1000, 1900, -45, 45);
Spd_rpm = map(RCValue1, 1000, 1900, -15080, 15080);
Spd_rps = Spd_rpm / 60;
//시리얼 표시
Serial.print(" Spd: ");
Serial.print(Spd_rpm);
Serial.print(" Angle: ");
Serial.print(Angle);
Serial.print("Humidity: ");
Serial.print(hum, 1); //습도 소수점 첫째 표시
Serial.print(" %, Temp: ");
Serial.print(temp, 1); //온도 소수점 첫째 표시
Serial.print(" Celsius, ");
Serial.print(lux); //조도 표시
Serial.print(" lux, ");
Serial.print(vin); //배터리 볼트 표시
Serial.print("V, ");
if (percentage == -1) { //CO2 값 표시
Serial.print( "<400" );
}
else {
Serial.print(percentage);
}
Serial.print( "ppm, " );
if (digitalRead(BOOL_PIN)) //CO2 BoolPin 상태 보고
{
Serial.println( "HIGH" );
}
else
{
Serial.println( "LOW" );
}
//Thing Speak 서버에 업로드
//통합 시도
sendCommand("AT+CIPMUX=1", 5, "OK");
String getData = "GET /update?api_key=" + WApiKey + "&" + fieldTemp + "=" + String(temp) + "&" + fieldHum + "=" + String(hum) + "&" + fieldLight + "=" + String(lux) + "&" + fieldCO2 + "=" + String(percentage) + "&" + fieldVolt + "=" + String(vin) + "&" + fieldangle + "=" + String(Angle) + "&" + fieldspeed + "=" + String(Spd_rpm);
sendCommand("AT+CIPSTART=0,\"TCP\",\"" + HOST + "\"," + PORT, 15, "OK");
sendCommand("AT+CIPSEND=0," + String(getData.length() + 4), 4, ">");
esp8266.println(getData); countTrueCommand++;
sendCommand("AT+CIPCLOSE=0", 5, "OK");
}
// ESP 커맨드 입력 및 전송상태 수신
void sendCommand(String command, int maxTime, char readReplay[]) {
Serial.print(countTrueCommand);
Serial.print(". at command => ");
Serial.print(command);
Serial.print(" ");
while (countTimeCommand < (maxTime * 1))
{
esp8266.println(command);//at+cipsend
if (esp8266.find(readReplay)) //ok
{
found = true;
break;
}
countTimeCommand++;
}
if (found == true)
{
Serial.println("OYI");
countTrueCommand++;
countTimeCommand = 0;
}
if (found == false)
{
Serial.println("Fail");
countTrueCommand = 0;
countTimeCommand = 0;
}
found = false;
}
So, to sort things out,
- Normal output does not come out even though the code of MG-811 is used.
- BOOLPIN and Voltage value (CO2) should be output, which is output as LOW at 0V.
- MG-811 shows a negative value and measurement is not performed normally.
- If there is a problem in the code, please let me know the part to be corrected.
I would really appreciate if you could help me.

