old files

This commit is contained in:
coelner 2018-11-18 20:02:27 +01:00
parent fa6470723e
commit a5c9305452
8 changed files with 523 additions and 0 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

263
MQ-7/MQ-7.ino Executable file
View File

@ -0,0 +1,263 @@
/* sensor MQ7. alternate heater 5V/1.4V 60sec/90sec
// read sensor @ 88sec(of 90-period)
// Kn.Ny '16
// This program to be used as CO-alarm in tents wintertime during night. (gasoline or firewood burners)
// http://www.savvysolutions.info/savvymicrocontrollersolutions/arduino.php?topic=arduino-mq7-CO-gas-sensor
//http://www.savvysolutions.info/savvymicrocontrollersolutions/index.php?sensor=mq-7-gas-sensors
// ****************************************************************************************************/
#define plotting
#define a_pin5 A3
#define a_pin1 A4
#define powerpin 3
#define lotime 90000UL // 90 sek low heating
#define hitime 60000UL // 60 sek high heating
#define read_time 148000UL // read 2 sek ahead of end low period
#define warnlevel 50 // CO ppm Warnlevel
#define vdR1 560 //kOhm voltage divider first resistor <--Needs to be measured
#define vdR2 150 //kOhm voltage divider second resistor <-- Needs to be measured
//#define vdF 4.5 //factor of the voltage divider <-- ToDo (558600+147900)÷147900=4,776876268
/*
Real world measurements
Rs in clean air between 500 and 2000 Ohm AFTER measurement cycle
Rs in polluted air between 10000 and 50000 Ohm AFTER measurement cycle
*/
int start_val, end_val; // read analog value
unsigned long next_time;
boolean low_now, done_reading; // remember status
boolean alarmCO = false;
float ambTemp = 20.0;
float ambHum = 65.0;
// Adjust vRef to be the true supply voltage in mV.
float vRef = 5000.0;
const float RL = 9.84; // load resistor value in k ohms
float Ro = 10.0;
/*
default value 10 k ohms. Revised during calibration. In general it should be between 2-20k (for 100ppm? or in the range of 20-2000ppm? )as shown in datasheet.
Clean air leads to 500 Ohm. (At least in the beginning...)
*/
const float Ro_clean_air_factor = 26.09; //see datasheet
/*
It does not make any sense. Suggestion: the chinese missed for R0 a '/' to seperate 'clean air' from '100pm'.
If you can calibrate against 100pm that is fine. If not, use the resistance in clean air.
*/
float mV = 0.0;
/*
Revert the measurement over the 1.1V voltage divider
*/
float voltageDivider1V(float vMeasurement) {
double vIn = 0;
vIn = vMeasurement * (vdR1 + vdR2) / (float)vdR2;
return (float)vIn;
}
float RsRoAtAmbientTo20C65RH(float RsRo_atAmb, float ambTemp, float ambRH) {
// Using the datasheet for MQ-7 sensor, derive Rs/Ro values
// from - 10 to 50 C and 33, 65, and 85 % relative humidity.
// For the measured Rs/Ro, use linear interpolation to calculate the
// standard Rs/Ro values for the measured ambient temperature and RH.
// Next, calculate a correction factor from the standard Rs/Ro at ambient
// temp and RH relative to standard Rs/Ro at 20C and 65 RH.
// Apply this correction factor to the measured Rs/Ro value and return the
// corrected value. This corrected value may then be used against the Rs/Ro
// Rs/Ro vs CO concentration (ppm) chart to estimate the concentration of CO.
// Calc RsRo values at ambTemp & 33% RH, 65% and 85% RH
float RsRo_at_ambTemp_33RH = -0.00000593 * pow(ambTemp, 3) + 0.000533 * pow(ambTemp, 2) - 0.0182 * ambTemp + 1.20;
float RsRo_at_ambTemp_85RH = -0.0000000741 * pow(ambTemp, 3) + 0.000114 * pow(ambTemp, 2) - 0.0114 * ambTemp + 1.03;
//float RsRo_at_65RH = ((65.0-33.0)/(85.0-65.0));
float RsRo_at_ambTemp_65RH = ((65.0 - 33.0) / (85.0 - 33.0) * (RsRo_at_ambTemp_85RH - RsRo_at_ambTemp_33RH) + RsRo_at_ambTemp_33RH) * 1.102;
// Linear interpolate to get the RsRo at the ambient RH value (ambRH).
float RsRo_at_ambTemp_ambRH;
if (ambRH < 65.0) {
RsRo_at_ambTemp_ambRH = (ambRH - 33.0) / (65.0 - 33.0) * (RsRo_at_ambTemp_65RH - RsRo_at_ambTemp_33RH) + RsRo_at_ambTemp_33RH;
} else {
// ambRH > 65.0
RsRo_at_ambTemp_ambRH = (ambRH - 65.0) / (85.0 - 65.0) * (RsRo_at_ambTemp_85RH - RsRo_at_ambTemp_65RH) + RsRo_at_ambTemp_65RH;
}
// Calc the correction factor to bring RsRo at ambient temp & RH to 20 C and 65% RH.
const float refRsRo_at_20C65RH = 1.00;
float RsRoCorrPct = 1 + (refRsRo_at_20C65RH - RsRo_at_ambTemp_ambRH) / refRsRo_at_20C65RH;
// Calculate what the measured RsRo at ambient conditions would be corrected to the
// conditions for 20 C and 65% RH.
float measured_RsRo_at_20C65RH = RsRoCorrPct * RsRo_atAmb;
return measured_RsRo_at_20C65RH;
}
float CalcRsFromVRL(float VRL) {
// VRL = RL voltage in mV.
// VRef = supply voltage, 5000 mV
// RL = load resistor in k ohms
// The equation Rs = (Vc - Vo)*(RL/Vo)
// is derived from the voltage divider
// principle: Vo = RL * Vc (Rs + RL)
//
// Note. Alternatively you could calc
// Rs from ADC value using
// Rs = RL * (1024 - ADC) / ADC
float Rs = (vRef - VRL) * (RL / VRL);
return Rs;
}
unsigned int GetCOPpmForRatioRsRo(float RsRo_ratio) {
// If you extract the data points from the CO concentration
// versus Rs/Ro chart in the datasheet, plot the points,
// fit a polynomial curve to the points, you come up with the equation
// for the curve of: Rs/Ro = 22.073 * (CO ppm) ^ -0.66659
// This equation is valid for ambient conditions of 20 C and 65% RH.
// Solving for the concentration of CO you get:
// CO ppm = [(Rs/Ro)/22.073]^(1/-0.66666)
float ppm;
ppm = pow((RsRo_ratio / 22.073), (1 / -0.66659));
//ToDo Check this relation on my own. The 22.073 should be the value for clean air 26.09 as this stands for 0ppm.
return (unsigned int) ppm;
}
void burnIn() {
/*
if not flag in eeprom set
then burn in sensor
*/
}
void calibrateCleanAir() {
Serial.println("Calibrating MQ-7 CO sensor in clean air..");
measurementCycle();
//Serial.println("Calibrating in progress: First Measurement complete");
measurementCycle();
//Serial.println("Calibrating in progress: Second Measurement complete");
measurementCycle();
//Serial.println("Calibrating in progress: Last Measurement complete");
//Serial.println("***************************************************");
if (mV < 4000) {
Serial.println("WARNING! reactive material broken or not in clean air");
}
Serial.print(" Rs = ");
Serial.println(CalcRsFromVRL(mV));
Ro = CalcRsFromVRL(mV) * Ro_clean_air_factor;
Serial.print(" Ro = ");
Serial.println(Ro);
Serial.println("Sensor calibration in clean air complete");
Serial.println("Setup complete. Monitoring for CO..");
Serial.println(" ");
digitalWrite(powerpin, LOW);
mV = 0.0;
}
void measurementAnalog5v() {
//higher CO value leads to higher restance
//which leads to lower voltage at RL
int measurement5V = analogRead(a_pin5);
delay(100);
Serial.println("");
Serial.println("ADC 5V Read: " + String(measurement5V) + " counter");
// Voltage at pin in milliVolts = (reading from ADC) * (5000/1024)
mV = measurement5V * float(vRef / 1024.0);
Serial.println("ADC 5Voltage In: " + String(mV) + " mV");
}
void measurementAnalog1v() {
//higher CO value leads to higher restance
//which leads to lower voltage at RL
int measurement1V = analogRead(a_pin1);
delay(100);
/*
map the voltage to max voltage of vRef within the 1v voltage divider
Could be omitted; the difference is very small
*/
int m1v = map(measurement1V, 0, 1023, 0, 1056);
Serial.println("\n\rADC 1V Read: \t" + String(measurement1V) + " counter | " + String(m1v));
/*
* Revert the 1V voltage divider to get the voltage between RL and Rs ( antoher voltage divider)
*/
mV = voltageDivider1V(m1v);
/*
map the voltage to vRef within the sensor voltage divider
*/
m1v = map(mV, 0, 1023, 0, (int)vRef);
Serial.println("ADC 1Voltage In: \t" + String(mV) + " mV | " + String(m1v));
mV = m1v;
}
void measurementAnalog() {
measurementAnalog5v();
//measurementAnalog1v();
//calculate relation R0/Rs
float Rs = CalcRsFromVRL(mV);
//measurementAnalog1v();
Serial.println("current Rs " + String(Rs) + " kOhm");
//
// ToDo
float RsRo_ratio = Ro / Rs; //Rs / Ro; //Datasheet wrong/Misleaded interpretaion of quantisation
Serial.println("current RsR0_ratio: " + String(RsRo_ratio));
float co = GetCOPpmForRatioRsRo(RsRo_ratio);
/*
if ( co < 20 ) {
Serial.println("measurement out of range. Value to low to be precise!");
}
else {
if ( co > 2000) {
Serial.println("measurement out of range. Value to high to be precise!");
}
}
*/
Serial.println("calculated CO: \t" + String(co) + " ppm");
//
//
}
void measurementCycle() {
//set timer
unsigned long starttime = millis();
unsigned long currenttime = 0;
done_reading = true;
next_time = hitime + lotime; //set complete runtime for one measurement
//start cleaning sensitive part of sensor
Serial.println("-------------------------------------------------------------");
digitalWrite(powerpin, HIGH); // => 5V
Serial.print("5V:\t on");
while (currenttime < next_time) {
//refresh current time
currenttime = abs(millis() - starttime);
if (currenttime % 10000UL == 0) {
//Serial.println("DEBUG: ADC 5V Read: " + String(analogRead(a_pin5)) + " counter");
Serial.print(" " + String(currenttime / 1000UL) + "..");
delay(10);
}
if (done_reading && currenttime >= hitime) //sensor reach heating time limit
{
digitalWrite(powerpin, LOW); // => 1.4V
Serial.print("\n1.4V:\t on");
done_reading = false;
}
if (currenttime > read_time) // then do a reading now
{
measurementAnalog();
done_reading = true;
break;
//add nynquist thereom and sums up multiple measurements
}
}
}
//routine to measure temparature and humidity
void measurementAmbient() {
}
void setup()
{
Serial.begin(115200);
pinMode(powerpin, OUTPUT);
Serial.println("\n\n\rLow Preheating for Standby ...");
Serial.println("Start Calibration ...");
calibrateCleanAir();
}
void loop()
{
//Serial.println("Start looping ...");
measurementCycle();
}

View File

@ -0,0 +1,62 @@
/*
MQ7_LG_test.ino
MQ7_LG test library
The circuit:
* MQ7 gas sensor v1.3 or other
* VRL at analog input A0
* digital controlled supply on output pin 4
Optionaly :
* 1/2 of VCC connected on A3 by a resistor divider
* DOUT on pin 5
Created 21 january 2015
By Laurent Gibergues (laurent.gibergues (at) free.fr
http://forum.arduino.cc
*/
#include <Arduino.h>
#include "MQ7_LG.h"
#define MQ7_VRL_PIN A0
#define MQ7_HEATER_CTRL_PIN 4
// Optional parameter
#define MQ7_DOUT_PIN 5
#define MQ7_VOLTAGE_HEATER_PIN A3
#define PRINT_PERIOD 2000
MQ7_LG mq7(MQ7_VRL_PIN, MQ7_HEATER_CTRL_PIN, MQ7_DOUT_PIN, MQ7_VOLTAGE_HEATER_PIN);
unsigned long startTime;
void setup() {
Serial.begin(115200);
Serial.println("MQ7 CO gas sensor test");
Serial.println("Time;VRL;ppm CO;Heater voltage;DOut;");
mq7.init();
startTime = millis();
}
void loop() {
delay(PRINT_PERIOD);
mq7.run();
Serial.print((millis() - startTime) / 1000);
Serial.print(';');
Serial.print(mq7.getVRL());
Serial.print(';');
Serial.print(mq7.read());
Serial.print(';');
Serial.print(mq7.getHeaterVoltage());
Serial.print(';');
Serial.print(mq7.getDOut());
Serial.println(';');
}

86
MQ-7/MQ7_LG_test/MQ7_LH.c Executable file
View File

@ -0,0 +1,86 @@
#include <Arduino.h>
#include "MQ7_LG.h"
MQ7_LG::MQ7_LG(uint8_t VRLPin, uint8_t HeaterCtrlPin, int8_t DOutPin, int8_t HeaterVoltagePin)
: _VRLPin(VRLPin), _heaterCtrlPin(HeaterCtrlPin), _DOutPin(DOutPin), _heaterVoltagePin(HeaterVoltagePin) {
}
void MQ7_LG::init() {
_ppmCO = -1;
pinMode(_heaterCtrlPin, OUTPUT);
if (_DOutPin != -1) {
pinMode(_DOutPin, INPUT);
_DOutIsConnected = true;
}
else
_DOutIsConnected = false;
if (_heaterVoltagePin != -1)
_HeaterVoltageIsConnected = true;
else
_HeaterVoltageIsConnected = false;
// Start High Heating
digitalWrite(_heaterCtrlPin, LOW);
_state = HIGH_HEATING;
_prevTime = millis();
}
void MQ7_LG::run() {
unsigned long time = millis();
if (_state == HIGH_HEATING) {
if (time - _prevTime >= HIGH_HEATING_TIME) {
_ppmCO = toPpm(getVRL());
_state = LOW_HEATING;
digitalWrite(_heaterCtrlPin, HIGH);
_prevTime = time;
}
}
else {
if (time - _prevTime >= LOW_HEATING_TIME) {
_state = HIGH_HEATING;
digitalWrite(_heaterCtrlPin, LOW);
_prevTime = time;
}
}
}
float MQ7_LG::getVRL() {
float v;
v = analogRead(_VRLPin);
v = map(v, 0, 1024, 0, (int)(VCC_HEATER * 1000));
return v / 1000;
}
int MQ7_LG::getDOut() {
if (_DOutIsConnected)
return digitalRead(_DOutPin);
else
return -1;
}
float MQ7_LG::getHeaterVoltage() {
float v;
if (_HeaterVoltageIsConnected) {
v = analogRead(_heaterVoltagePin);
v = map(v, 0, 1024, 0, 10000); // Heater voltage measure is divided by 2 by hardware
v /= 1000;
}
else
v = -1;
return v;
}
int MQ7_LG::read() {
return _ppmCO; // -1 if data not available (during 60s after initialisation)
}
int MQ7_LG::toPpm(float VRL) {
return (int)(CONSTANT_B * pow((((float)RL / R0) * ((VCC_HEATER / VRL) - 1)), COEF_A));
}

53
MQ-7/MQ7_LG_test/MQ7_LH.h Executable file
View File

@ -0,0 +1,53 @@
/*
MQ7_LG.h - Library for MQ7 Monoxide Gas Sensor v1.3 hardware.
Created by Laurent Gibergues, January 21, 2015
Released into the public domain.
Hardware v1.3 need modification : see documentation please
*/
#ifndef MQ7_LG_h
#define MQ7_LG_h
#include <inttypes.h>
class MQ7_LG {
public :
MQ7_LG(uint8_t VRLPin, uint8_t HeaterCtrlPin, int8_t DOutPin = -1, int8_t HeaterVoltagePin = -1);
void init();
void run();
int read();
float getVRL();
int getDOut();
float getHeaterVoltage();
typedef enum states {HIGH_HEATING = 0, LOW_HEATING} state_t;
private :
int _ppmCO;
uint8_t _VRLPin;
uint8_t _heaterCtrlPin;
int8_t _DOutPin;
int8_t _heaterVoltagePin;
bool _HeaterVoltageIsConnected;
bool _DOutIsConnected;
state_t _state;
unsigned long _prevTime;
//functions
int toPpm(float VRL);
// Specifics data
const static unsigned long HIGH_HEATING_TIME = 60 * 1000L; // ms
const static unsigned long LOW_HEATING_TIME = 90 * 1000L; // ms
const static unsigned RL = 10000; // Ohms
const static unsigned R0 = 2000; // Ohms
const static float VCC_HEATER = 5.29; // Volts
const static float COEF_A = -1.6; // See MQ7 documentation :
const static float CONSTANT_B = 100; // log(ppmCO) = COEF_A * log(Rs/R0) + log(CONSTANT_B)
};
#endif

View File

@ -0,0 +1,59 @@
$ 1 0.000005 10.20027730826997 43 5 50
r 624 256 688 256 0 370000
p 800 256 688 256 1 0
r 528 256 592 256 0 100000
r 560 720 624 720 0 1000000
r 624 480 688 480 0 82
r 720 480 784 480 0 32
w 688 480 720 480 0
v 304 720 304 784 0 0 40 5 0 0 0.5
w 304 480 624 480 0
s 592 768 656 768 0 1 false
w 800 480 800 816 0
w 800 816 304 816 0
w 304 784 304 816 0
w 656 768 656 720 0
R 544 768 448 768 0 0 40 3.3 0 0 0.5
w 544 768 592 768 0
w 624 512 624 480 0
w 560 720 304 720 0
w 784 480 800 480 0
r 496 320 592 320 0 10000
w 624 384 624 416 0
w 688 256 688 320 0
w 624 256 592 256 0
w 528 256 304 256 1
w 304 352 304 480 0
w 800 480 800 416 0
w 800 384 752 384 0
w 304 720 304 592 0
w 656 720 656 688 0
p 800 416 688 416 1 0
w 688 416 688 480 0
w 800 416 800 384 0
w 688 512 688 480 0
w 656 688 656 576 0
w 304 176 304 256 0
w 624 512 640 512 0
w 688 512 672 512 0
w 304 592 304 480 0
p 592 176 528 176 1 0
w 592 176 592 256 0
w 528 176 304 176 0
p 688 416 624 416 1 0
w 624 416 624 480 0
w 800 384 800 256 0
p 688 176 592 176 1 0
w 688 176 688 256 0
f 656 576 656 512 0 1.5 20
w 624 720 640 688 0
w 304 320 496 320 1
w 304 256 304 320 0
174 752 384 640 368 0 20000 0.005 R Sensor
w 304 352 304 320 0
p 592 368 496 368 1 0
w 496 368 496 320 0
w 592 368 592 320 0
w 688 368 688 320 0
w 592 320 688 320 0