Heb de sketch geprobeerd op de houtkachel - lijkt prima te werken, maar ik heb nog steeds veel vragen over - met name - de excess air en co2 formule's. Ik ga de komende periode het systeem uitvoerig testen om te kijken of de nieuwe formule's wel kloppen en überhaupt nuttig zijn. Eerste stap is om een nieuwe controller te proberen zodat er in ieder geval twee solide, nauwkeurig gemeten gegevens zijn: lambda en O2%.
De onderstaande, aangepaste sketch deel ik dus met vrachtwagenladingen voorbehoud.
/***************************************************
ST_version_1.0 - 15 April 2016
Some of the following code and associated libraries were written by Limor Fried and Ladyada for Adafruit. This code is used to obtain data from the Adafruit Amplifier Board (MAX31855). The board is available from
https://www.adafruit.com/products/269 - BSD license. Other bits of the code were written by Nathan Seidle for SparkFun Electronics. His code (and libraries) are used to obtain data from the Sprakfun HTU21D temperature & humidity sensor. The rest of the code was cobbled together by Vincent Busch for the stovething project.
ST version 1.0 outputs lambda, AFR, oxygen percentage, excess air percentage, carbon dioxode percentage and stove efficiency. NOTE: THE FORMULAS USED HERE HAVE KNOWN FLAWS AND SHORTCOMINGS - THESE ARE EXPLAINED IN THE SKETCH. THE SKETCH IS PROVIDED FOR EXPERIMENTAL PURPOSES ONLY. WITH THE EXCEPTION OF LAMBDA, THE ACCURACY OF THE DATA HAS NOT BEEN VERIFIED. Hopefully that's enough of a disclaimer.
***************************************************/
#include <Wire.h>
#include <SparkFunHTU21D.h>
#include <SPI.h>
#include "Adafruit_MAX31855.h"
/*-------DEFINE TEMPERATURE & HUMIDITY SENSOR-------*/
//Create an instance for the temperature/humidity sensor
HTU21D myHumidity;
/* Version 1.0 uses two thermocouples (software SPI on any four digital IO pins). The CLK (clock) and CS (chip select) are shared; thermocouple 1 is assigned DO1 (data out) while thermocouple 2 uses DO 2. Pins and thermocouples are defined below. */
/*-------DEFINE THERMOCOUPLES-------*/
#define DO1 10
#define DO2 11
#define CS 12
#define CLK 13
Adafruit_MAX31855 thermocouple1(CLK, CS, DO1);
Adafruit_MAX31855 thermocouple2(CLK, CS, DO2);
/*-------SETUP SECTION-------*/
void setup() {
Serial.begin(9600);
delay(1000);
// Start Sprakfun HTU21D temperature & humidity sensor
myHumidity.begin();
delay(1000);
}
/*-------LOOP SECTION-------*/
void loop() {
/*-------HUMIDITY AND TEMPERATURE SENSOR-------*/
/* The code below retrieves temeprature and humidity data from the Sparkfun sensor. */
float temp = myHumidity.readTemperature();
float humd = myHumidity.readHumidity();
/*-------THERMOCOUPLE 1-------*/
/* The following code reads the on-board temperature module on the Adafruit MAX31855 for thermocouple 1 - it is not used here. Instead the temperature is derived from the SparkFun chip. */
// Serial.print("Internal Temp = ");
// Serial.println(thermocouple1.readInternal());
/* The code below reads the temperature from thermocouple 1, in Celsius. */
double c1 = thermocouple1.readCelsius();
/* If you prefer the temperature to be displayed in Fahrenheit, uncomment the code below (and comment out the code above). */
// double f1 = thermocouple1.readFahrenheit();
/* This sketch formats and outputs data for processing in MakerPlot. If you intend to use the Arduino serial monitor, you may wish to uncomment the following (and comment out the MakerPlot section). Note: if you have changed the temperature setting to Fahrenheit, remember to adjust the below code accordingly (to f1). */
// if (isnan(c1)) {
// Serial.println("T1 not working!");
// } else {
// Serial.print("T1 = ");
// Serial.println(c1);
// }
/*-------THERMOCOUPLE 2-------*/
/* The following code reads the on-board temperature module on the Adafruit MAX31855 for thermocouple 2 - it is not used here. */
// Serial.print("Internal Temp = ");
// Serial.println(thermocouple2.readInternal());
/* The code below reads the temperature from thermocouple 2, in Celsius. */
double c2 = thermocouple2.readCelsius();
/* If you prefer the temperature to be displayed in Fahrenheit, uncomment the code below (and comment out the code above). */
// double f2 = thermocouple2.readFahrenheit();
/* This sketch formats and outputs data for processing in MakerPlot. If you intend to use the Arduino serial monitor, you may wish to uncomment the following (and comment out the appropriate lines of the MakerPlot section). Note: if you have changed the temperature setting to Fahrenheit, remember to adjust the code below accordingly (to f2). */
// if (isnan(c2)) {
// Serial.println("T2 not working!");
// } else {
// Serial.print("T2 = ");
// Serial.println(c2);
// }
/*-------WIDEBAND OXYGEN SENSOR------------*/
/* The signal from the wideband oxygen controller is sent to analog pin 0 (A0). */
int sensorValue = analogRead(A0);
/* LAMBDA - the sensor controller is programmed to output 0 volts at lambda 0.80 and 5 volts at lambda 8.19. The difference is 7.39. These numbers are included in the formula below, and should be changed if the sensor settings are changed (read: if the controller is re-programmed). */
float LAMBDA = 0.80 + (sensorValue * (7.39 / 1023.0));
/* AFR - the AFR figure shown is a multiple of the AFR figure defined in the LM software (set to 6.4, the setting for methanol). Based on the above lambda settings, the AFR is 5.12 at 0 volts and 52.41 at 5 volts. The difference is 47.29. These numbers are included in the formula below and should be changed if the sensor controller settings are changed/reprogrammed via LM Programmer. Please note that the controller can be set to a user-defined AFR multiple.*/
float AFR = 5.12 + (sensorValue * (47.29 / 1023.0));
/* OXYGEN PERCENTAGE - the lambda value can be used to calculate the oxygen percentage in the exhaust gas. Please note that the formula used here was developed for the lean part of the lambda range (where lambda <1). Future versions of the system will retrieve the oxygen percentage directly from the controller/sensor. The formula used for now is x02=3*(La-1)/(1+3*K*La), where x02 = oxygen percentage, La = lambda, and K is either 4.76 or 4.77. The correction factor of 2.68 is compensated proportionally for values in excess of lambda 1.0. This is done in the output section (it is assumes that lambda will never be less than 1 in a woodstove). This is very much a patch! For reference purposes: outside air contains 20.95% oxygen.*/
float OXYGENPERCENT = (3 * ((LAMBDA - 1) / (1 + 3 * 4.765 * LAMBDA)) * 100);
/* EXCESS AIR - there are various ways to calculate access air. As the lambda value is obtained directly from the sensor (as opposed to being calculated) it is used here. The formula used is: lambda = (percentage excess air / 100) + 1. Or, expressed in terms of excess air: percentage excess air = (lambda - 1) * 100. */
float EXCESSAIR = (((LAMBDA) - 1) * 100);
/* CO2 PERCENTAGE - the oxygen percentage can also be used to estimate the carbon dioxide percentage in the exhaust gas. The formula is: CO2% = maximum CO2 for fuel type * ((20.95 - %O2) / 20.95). Please note that the figure for maximum CO2 for wood tends to vary, and is generally quoted for dry wood (wood rarely is). I have encountered 19.2 as well as 19.7. I have used 19.5. There are other shortcomings. */
float CO2PERCENT = 19.5 * ((20.95 - OXYGENPERCENT) / 20.95);
/*-------STOVE EFFICIENCY -------*/
/* The flue gas temperature, the ambient temperature and the carbon dioxide (CO2) percentage can be used to obtain some indication of the woodstove's efficiency. The formula is: stove efficiency = 100 - ((MeanFlueTemp - MeanRoomTemp) x (A1 / CO2%)), where A1 is 0.65. As thermocouple 1 is attached to the flue, MeanFlueTemp = (c1) while MeanRoomTemp (temp, 1). */
float STOVEEFFICIENCY = 100 - (((c1) - (temp, 1)) * (0.65 / CO2PERCENT));
/*-------DATA OUTPUT TO MAKERPLOT-------*/
{
// The code below outputs data in comma delimited form. This allows it to be read in MakerPlot.
Serial.print(c1); // temperature reading thermocouple 1, displayed in Celsius
// Serial.print(f1); // temperature reading thermocouple 1, displayed in Fahrenheit
Serial.print(","); // comma delimiter
Serial.print(c2); // temperature reading thermocouple 2, displayed in Celsius
// Serial.print(f2); // temperature reading thermocouple 2, displayed in Fahrenheit
Serial.print(","); // comma delimiter
Serial.print(temp, 1); // ambient temperature from SprakFun temperature & humidity sensor
Serial.print(","); // comma delimiter
Serial.print(humd, 1); //humidity reading from SprakFun temperature & humidity sensor
Serial.print(","); // comma delimiter
Serial.print(LAMBDA);
Serial.print(","); // comma delimiter
Serial.print(AFR);
Serial.print(","); // comma delimiter
if ((OXYGENPERCENT < 0) && (LAMBDA >1))
{
Serial.print(0.00);
Serial.print(","); // comma delimiter
}
else
{
Serial.print(OXYGENPERCENT + (LAMBDA * (2.61/7.99)));
Serial.print(","); // comma delimiter
}
if (EXCESSAIR > 100)
{
Serial.print(100);
Serial.print(","); // comma delimiter
}
else
{
Serial.print(EXCESSAIR);
Serial.print(","); // comma delimiter
}
if (CO2PERCENT < 0)
{
Serial.print(0.00);
Serial.print(","); // comma delimiter
}
else
{
Serial.print(CO2PERCENT);
Serial.print(","); // comma delimiter
}
if (STOVEEFFICIENCY < 0)
{
Serial.print(0.00);
Serial.print(","); // comma delimiter;
}
else
{
Serial.print(STOVEEFFICIENCY);
Serial.print(","); // comma delimiter;
Serial.println();
}
/*-------DATA OUTPUT SERIAL-------*/
/*
{
Serial.print("Thermocouple 1: "); // label thermocouple 1
Serial.print(c1); // temperature reading thermocouple 1, displayed in Celsius
// Serial.print(f1); // temperature reading thermocouple 1, displayed in Fahrenheit
Serial.println(); // new line.
Serial.print("Thermocouple 2: "); // label thermocouple 2
Serial.print(c2); // temperature reading thermocouple 2, displayed in Celsius
// Serial.print(f2); // temperature reading thermocouple 2, displayed in Fahrenheit
Serial.println(); // new line.
Serial.print("Ambient temperature: "); // label ambient temperature
Serial.print(temp, 1); // ambient temperature from SprakFun temperature & humidity sensor
Serial.println(); // new line
Serial.print("Ambient humidity: "); // label ambient humidity
Serial.print(humd, 1); //humidity reading from SprakFun temperature & humidity sensor
Serial.println(); // new line
Serial.print("Lambda: "); // lambda label
Serial.print(LAMBDA);
Serial.println(); // new line
Serial.print("Air Fuel Ratio: "); // AFR label
Serial.print(AFR);
Serial.println(); // new line
if ((OXYGENPERCENT < 0) && (LAMBDA >1))
{
Serial.print("Oxygen percentage: "); // label oxygen percentage
Serial.print(0.00);
Serial.println(); // new line
}
else
{
Serial.print("Oxygen percentage: "); // label oxygen percentage
Serial.print(OXYGENPERCENT + (LAMBDA * (2.61/7.99)));
Serial.println(); // new line
}
if (EXCESSAIR > 100)
{
Serial.print("Excess Air percentage: "); // label excess air percentage
Serial.print(100);
Serial.println(); // new line
}
else
{
Serial.print("Excess Air percentage: "); // label excess air percentage
Serial.print(EXCESSAIR);
Serial.println(); // new line
}
if (CO2PERCENT < 0)
{
Serial.print("CO2 percentage: "); // label CO2 percentage
Serial.print(0.00);
Serial.println(); // new line
}
else
{
Serial.print("CO2 percentage: "); // label CO2 percentage
Serial.print(CO2PERCENT);
Serial.println(); // new line
}
if (STOVEEFFICIENCY < 0)
{
Serial.print("Stove efficiency (%): "); // label stove efficiency
Serial.print(0.00);
Serial.println();
}
else
{
Serial.print("Stove efficiency (%): "); // label stove efficiency
Serial.print(STOVEEFFICIENCY);
Serial.println();
Serial.println();
}
*/
// the delay below defines how often data is sent to MakerPlot (once a second = 1000).
delay(1000);
}} // remember to change this when uncommenting/commenting out