Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add renewed calibration sketch #13

Merged
merged 15 commits into from
Apr 7, 2017
12 changes: 8 additions & 4 deletions node-wifi-mqtt-homie-battery/CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,27 @@ in-progress
- Set some custom settings as default, limited at the moment by issue:
https://github.com/marvinroger/homie-esp8266/issues/323

2017-04-04 0.9.4
================
- Add temperature compensation in gram per degree.

2017-03-27 0.9.3
=================
================
- Add connection error handling to avoid battery drain (WIFI/MQTT Connection issues) Thanks to a broken WIFI and @amotl.

2017-03-27 0.9.2
=================
================
- Disable 3 of 4 default settings due to bug in homie-esp8266

2017-03-24 0.9.1
=================
================
- Make use of onHomieEvent to ensure a clean disconnect from broker before deepSleep
- Implement a battery check, create a low battery alarm topic to notify user and make the ESP sleep "forever"
- All needed settings are now settable via HomieSetting
- Modularized code
- Add versioning scheme

2017-03-18 0.9.0
=================
================
- Add JSON output for hiveeyes.org compatibility

4 changes: 1 addition & 3 deletions node-wifi-mqtt-homie-battery/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,7 @@ battery lifetime a lot.

.. Todo::

- Add some scale/temperature calibration curves. Actually not too important,
as some grams don't really matter while we are measuring up to 120kg.
But we can ;-)
- Describe how to determine scale's temperature compensation values.


.. include:: CHANGES.rst
Expand Down
17 changes: 16 additions & 1 deletion node-wifi-mqtt-homie-battery/node-wifi-mqtt-homie-battery.ino
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
#include <RunningMedian.h>

#define FW_NAME "node-wifi-mqtt-homie-battery"
#define FW_VERSION "0.9.3"
#define FW_VERSION "0.9.4"
const int DEFAULT_SLEEP_TIME = 600;

// PINs
Expand All @@ -65,6 +65,8 @@ const int DEFAULT_SLEEP_TIME = 600;
*/
const long DEFAULT_WEIGHT_OFFSET = 154231; // Load cell zero offset.
const float DEFAULT_KILOGRAM_DIVIDER = 21.76; // Load cell value per kilogram.
const float DEFAULT_CALIBRATION_TEMPERATURE = 20.0; // Temperature at which the scale has been calibrated for Temperature compensation
const float DEFAULT_CALIBRATION_FACTOR_GRAM_DEGREE = 0.0; // Calibration factor in gram per degree

/*
* Scale should be calibrated with a regulated input of 3.3V!
Expand All @@ -83,6 +85,8 @@ const float DEFAULT_VCC_ADJUST = 0.13;
HomieSetting<long> sleepTimeSetting("sleepTime", "SleepTime in seconds (max. 3600s!), default is 60s");
HomieSetting<long> weightOffsetSetting("weightOffset", "Offset value to zero. Use BeeScale-Calibration.ino to determine.");
HomieSetting<double> kilogramDividerSetting("kilogramDivider", "Scale value per kilogram. Use BeeScale-Calibration.ino to determine.");
HomieSetting<double> calibrationTemperatureSetting("calibrationTemperature", "Outside Temperature at which the scale has been calibrated");
HomieSetting<double> calibrationFactorSetting("calibrationFactor", "Calibration Factor in gram per degree. 0.0 to disable adjustment");
HomieSetting<double> vccAdjustSetting("vccAdjust", "Calibration value for input voltage. See sketch for details.");

HX711 scale;
Expand Down Expand Up @@ -197,6 +201,15 @@ void getWeight() {
scale.power_down();

weight = WeightSamples.getMedian();

//temperature compensation
Homie.getLogger() << "✔ uncompensated median Weight: " << weight << "g" << endl;
float calibrationTemperature = calibrationTemperatureSetting.get();
float calibrationFactor = calibrationFactorSetting.get();
if (temperature1 < calibrationTemperature) weight = weight+(fabs(temperature1 - calibrationTemperature)*calibrationFactor);
if (temperature1 > calibrationTemperature) weight = weight-(fabs(temperature1 - calibrationTemperature)*calibrationFactor);
Homie.getLogger() << "✔ compensated median Weight: " << weight << "g" << endl;

weight = weight / 1000 ; // we want kilogram
}

Expand Down Expand Up @@ -352,6 +365,8 @@ void setup() {
weightOffsetSetting.setDefaultValue(DEFAULT_WEIGHT_OFFSET);
kilogramDividerSetting.setDefaultValue(DEFAULT_KILOGRAM_DIVIDER);
vccAdjustSetting.setDefaultValue(DEFAULT_VCC_ADJUST);
calibrationTemperatureSetting.setDefaultValue(DEFAULT_CALIBRATION_TEMPERATURE);
calibrationFactorSetting.setDefaultValue(DEFAULT_CALIBRATION_FACTOR_GRAM_DEGREE);

//get all measurements *BEFORE* WIFI get's active. This saves around 4s at full mA
getTemperatures();
Expand Down
284 changes: 284 additions & 0 deletions node-wifi-mqtt-homie-calibration/node-wifi-mqtt-homie-calibration.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,284 @@
/***********************************************************************************************************
ESP8266 Calibration code for node-wifi-mqtt-homie[-battery]
(c)2014 - 2017 Alexander Wilms
https://www.imker-nettetal.de

GNU GPL v3 License
------------------
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, see:
<http://www.gnu.org/licenses/gpl-3.0.txt>,
or write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-------------------------------------------------------------------------


Credits: Marvin Roger for the awesome Homie Framework: https://github.com/marvinroger/homie-esp8266

Used libraries:
HX711: https://github.com/bogde/HX711
RunningMedian: https://github.com/RobTillaart/Arduino/tree/master/libraries/RunningMedian
Homie-esp8266: https://github.com/marvinroger/homie-esp8266
Bounce2: https://github.com/thomasfredericks/Bounce2
ESPAsyncTCP: https://github.com/me-no-dev/ESPAsyncTCP
async-mqtt-client: https://github.com/marvinroger/async-mqtt-client

Version 0.9.1

**********************************************************************************************************/

#include <Homie.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <Wire.h>
#include "HX711.h"
#include <RunningMedian.h>

// PINs
#define ONE_WIRE_BUS 14
#define DOUT 13
#define PD_SCK 12

RunningMedian offsetSamples = RunningMedian(10);
RunningMedian weightSamples = RunningMedian(10);

HX711 scale;
ADC_MODE(ADC_VCC);

char c;
long offset;
double kilogramDivider;
long knownWeight;

float weight;
float temperature0;
float temperature1;
float voltage;
float raw_voltage;
float vcc_adjust;

OneWire OneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&OneWire);

void getTemperatures() {
sensors.begin();
sensors.requestTemperatures(); // Send the command to get temperatures
temperature0 = sensors.getTempCByIndex(0);
if (temperature0 == -127) { //ignore wrong reading
delay(100);
temperature0 = sensors.getTempCByIndex(0);
}
temperature1 = sensors.getTempCByIndex(1);
if (temperature1 == -127) { //ignore wrong reading
delay(100);
}
temperature1 = sensors.getTempCByIndex(1);
}




void getOffset() {
yield();
for (int i = 0; i < 10; i++) {
Serial.print(".");
yield();
scale.power_up();
float offsetValue = scale.read_average(10);
yield();
offsetSamples.add(offsetValue);
scale.power_down();
yield();
delay(500);
yield();
}
offset = offsetSamples.getMedian();
}


void getKilogramDivider() {
for (int i = 0; i < 10; i++) {
Serial.print(".");
scale.power_up();
float weightValue = scale.read_average(10);
yield();
weightSamples.add(weightValue);
scale.power_down();
delay(500);
yield();
}
kilogramDivider = weightSamples.getMedian();
kilogramDivider = (kilogramDivider - offset) / knownWeight;
}

void getVccAdjust() {
raw_voltage = ESP.getVcc();
vcc_adjust = (3300 - raw_voltage) / 1000;

}


void step1() {
Serial << endl << endl;
Serial << " Step 1: enter the weight of a calibration weight " << endl;
Serial << "--------------------------------------------------" << endl;
Serial << " You need a calibration weigt of at least 1000g " << endl;
Serial << " for Step 3. Please measure it with *another* " << endl;
Serial << " (hopefully) exact scale and enter it's weight " << endl;
Serial << " in *gram* here and press ENTER when done... " << endl;
Serial.flush();
while(!Serial.available()) {
knownWeight = Serial.parseInt();
}
}

void step2() {
Serial << endl << endl;
Serial << " Step 2: tare scale " << endl;
Serial << "-------------------------------------------------" << endl;
Serial << " Remove all weight from the scale and " << endl;
Serial << " press 1 and ENTER to continue... " << endl;
Serial.flush();
while (c!='1') {
c = Serial.read();
yield();
};
getOffset();
c='x';
}

void step3() {
Serial << endl << endl;
Serial << " Step 3: determine gain per gramm " << endl;
Serial << "-------------------------------------------------" << endl;
Serial << "Now put the calibration weight of Step 1 onto the" << endl;
Serial << " scale press 1 and ENTER when you are done " << endl;
Serial.flush();
while (c!='1') {
c = Serial.read();
yield();
};
getKilogramDivider();
c='x';
}

void step4() {
Serial << endl << endl;
Serial << " Step 4: determine calibration temperature" << endl;
Serial << "-------------------------------------------------" << endl;
Serial << " Make sure, that the temperature sensors " << endl;
Serial << " are attached to the load cell " << endl;
Serial << " or at least at the same (room) temperature. " << endl;
Serial << " press 1 and ENTER to continue... " << endl;
Serial.flush();
while (c!='1') {
c = Serial.read();
yield();
}
getTemperatures();
c='x';
}

void step5() {
Serial << endl << endl;
Serial << " Step 5: determine volatge adjust " << endl;
Serial << "-------------------------------------------------" << endl;
Serial << " The ESP's ADC is not pretty acurate in ADC_VCC " << endl;
Serial << " mode. To determine offset make sure, that the " << endl;
Serial << " input voltage is stable above 3.5 V! " << endl;
Serial << " press 1 and ENTER to continue... " << endl;
Serial.flush();
while (c!='1') {
c = Serial.read();
yield();
}
getVccAdjust();
c='x';
}

void printResults() {
Serial << endl << endl;
Serial << " Done! Your calculated parameters are: " << endl;
Serial << "-------------------------------------------------" << endl;
Serial << "Your entered known weight was: " << knownWeight << "g" << endl;
Serial << "weightOffset is: " << offset << endl;
Serial << "kilogramDivider is: " << kilogramDivider << endl;
Serial << "calibration temperature is: " << temperature1 << endl;
Serial << "vccAdjust is: " << vcc_adjust << endl;
Serial << "The temperature calibration factor can not be " << endl;
Serial << "determined right here. It has to be evaluated and" << endl;
Serial << "calibrated while be scale is productive with real" << endl;
Serial << "temperature fluctuations. So use 0.0 for now. " << endl;
Serial << endl << endl;
}

void testResults() {
Serial << " You can test your calculated settings now! " << endl;
Serial << " press 1 and ENTER to continue... " << endl;
Serial << "-------------------------------------------------" << endl;
Serial.flush();
while (c!='1') {
c = Serial.read();
yield();
}
getWeight();
c='x';
}

void getWeight() {
scale.set_scale(kilogramDivider); //initialize scale
scale.set_offset(offset); //initialize scale
Serial << endl << endl;
Serial << "Reading scale, hold on" << endl;
scale.power_up();
for (int i = 0; i < 4; i++) {
float weightRaw = scale.get_units(10);
yield();
Serial << "✔ Raw measurements: " << weightRaw << "g" << endl;
weightSamples.add(weightRaw);
delay(100);
yield();
}
scale.power_down();

weight = weightSamples.getMedian();

weight = weight / 1000 ; // we want kilogram
}


void setup() {
wdt_disable();
wdt_enable(300000);
WiFi.forceSleepBegin();
yield();
Serial.begin(115200);
Serial << "Scale Adjustment for node-wifi-mqtt-homie / HX711" << endl;
Serial << "-------------------------------------------------" << endl;
scale.begin(DOUT, PD_SCK);
scale.set_scale();
scale.set_offset();
scale.power_down();
step1();
step2();
step3();
step4();
step5();
printResults();
}


void loop() {
testResults();
yield();
printResults();
}

7 changes: 7 additions & 0 deletions node-wifi-mqtt-homie/CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@ in-progress
- Set some custom settings as default, limited at the moment by issue:
https://github.com/marvinroger/homie-esp8266/issues/323

2017-03-27 0.9.4
=================
- Add temperature compensation in gram per degree

2017-03-27 0.9.3
=================
- ommited for the non battery version

2017-03-28 0.9.2
=================
Expand Down
Loading