Test version for fermentation
This commit is contained in:
parent
7f782ad7bd
commit
876718602f
3
.gitignore
vendored
3
.gitignore
vendored
@ -3,4 +3,5 @@
|
||||
*.map
|
||||
test/*.md
|
||||
test/env/*
|
||||
test/*.py
|
||||
test/*.py
|
||||
TODO.md
|
10
README.md
10
README.md
@ -7,9 +7,11 @@ I started this project out of curiosity for how a motion sensor is working and s
|
||||
* Add support for Plato in device (today it assumes that formula is in SG).
|
||||
* Add support for converting between SG/Plato in device.
|
||||
* Add support for Blynk as endpoint
|
||||
* Add support for https connections (push)
|
||||
* Add support for https connections (push) - [need to reduce memory usage for this to work, gets out of memory error]
|
||||
* Add support for https web server (will require certificates to be created as part of build process)
|
||||
* Add iSpindle 3D print cradle + small PCB (what I use for my builds)
|
||||
* Validate max sleep time to 70 min (max time for ESP)
|
||||
* Check how much movement there is during fermentack (check run time) if we should go into sleep mode for a shorter time...
|
||||
|
||||
# Functionallity
|
||||
|
||||
@ -96,11 +98,7 @@ The second section contains the push settings, two URL's for http posts, Brewfat
|
||||
### This is the format for InfluxDB v2
|
||||
|
||||
```
|
||||
gravity,host=<mdns>,device=<id>,format=SG value=1.0004
|
||||
angle,host=<mdns>,device=<id> value=45.45
|
||||
temp,host=<mdns>,device=<id>,format=<C|F> value=20.1
|
||||
battery,host=<mdns>,device=<id> value=3.96
|
||||
rssi,host=<mdns>,device=<id> value=-18
|
||||
measurement,host=<mdns>,device=<id>,temp-format=<C|F>,gravity-format=SG gravity=1.0004,angle=45.45,temp=20.1,battery=3.96,rssi=-18
|
||||
```
|
||||
|
||||
__TODO: Update image for push settings.__
|
||||
|
Binary file not shown.
BIN
bin/firmware.bin
BIN
bin/firmware.bin
Binary file not shown.
@ -21,10 +21,14 @@ board = d1_mini
|
||||
build_unflags =
|
||||
build_flags = #-O0 -Wl,-Map,output.map
|
||||
-D BAUD=${common_env_data.monitor_speed}
|
||||
-D ACTIVATE_OTA
|
||||
-D ACTIVATE_OTA
|
||||
#-D DEBUG_ESP_HTTP_CLIENT
|
||||
#-D DEBUG_ESP_HTTP_SERVER
|
||||
#-D DEBUG_ESP_PORT=Serial
|
||||
#-D SKIP_SLEEPMODE
|
||||
#-D DOUBLERESETDETECTOR_DEBUG true
|
||||
-D USE_LITTLEFS=true
|
||||
-D EMBED_HTML
|
||||
-D EMBED_HTML # If this is not used the html files needs to be on the file system (can be uploaded)
|
||||
-D USER_SSID=\""\"" # =\""myssid\""
|
||||
-D USER_SSID_PWD=\""\"" # =\""mypwd\""
|
||||
-D CFG_APPVER="\"0.3.5\""
|
||||
@ -38,6 +42,7 @@ lib_deps =
|
||||
https://github.com/bblanchon/ArduinoJson
|
||||
https://github.com/PaulStoffregen/OneWire
|
||||
https://github.com/milesburton/Arduino-Temperature-Control-Library
|
||||
https://github.com/wollewald/INA219_WE # For measuring power consumption
|
||||
|
||||
[env:gravity-debug]
|
||||
upload_speed = ${common_env_data.upload_speed}
|
||||
|
@ -52,7 +52,7 @@ bool GyroSensor::setup() {
|
||||
Log.notice(F("GYRO: Connected to MPU6050 (gyro)." CR));
|
||||
sensorConnected = true;
|
||||
|
||||
// Configure ethe sensor
|
||||
// Configure the sensor
|
||||
accelgyro.setTempSensorEnabled(true);
|
||||
accelgyro.setFullScaleAccelRange(MPU6050_ACCEL_FS_2);
|
||||
accelgyro.setFullScaleGyroRange(MPU6050_GYRO_FS_250);
|
||||
@ -91,6 +91,7 @@ void GyroSensor::readSensor(RawGyroData &raw, const int noIterations, const int
|
||||
#if LOG_LEVEL==6
|
||||
Log.verbose(F("GYRO: Reading sensor with %d iterations %d us delay." CR), noIterations, delayTime );
|
||||
#endif
|
||||
|
||||
// Set some initial values
|
||||
#if defined( GYRO_SHOW_MINMAX )
|
||||
RawGyroData min, max;
|
||||
@ -99,7 +100,6 @@ void GyroSensor::readSensor(RawGyroData &raw, const int noIterations, const int
|
||||
min.temp = accelgyro.getTemperature();
|
||||
max = min;
|
||||
#endif
|
||||
|
||||
for(int cnt = 0; cnt < noIterations ; cnt ++) {
|
||||
accelgyro.getRotation( &raw.gx, &raw.gy, &raw.gz );
|
||||
accelgyro.getAcceleration( &raw.ax, &raw.ay, &raw.az );
|
||||
|
@ -26,6 +26,10 @@ SOFTWARE.
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <ESP8266HTTPClient.h>
|
||||
|
||||
#if defined( COLLECT_PERFDATA )
|
||||
#include <INA219_WE.h> // For measuring power consumption
|
||||
#endif
|
||||
|
||||
SerialDebug mySerial;
|
||||
BatteryVoltage myBatteryVoltage;
|
||||
|
||||
@ -95,27 +99,64 @@ void BatteryVoltage::read() {
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#if defined( COLLECT_PERFDATA )
|
||||
|
||||
PerfLogging myPerfLogging;
|
||||
INA219_WE ina219(0x40); // For measuring power consumption
|
||||
|
||||
//
|
||||
// Initialize
|
||||
//
|
||||
PerfLogging::PerfLogging() {
|
||||
if( ina219.init() )
|
||||
measurePower = true;
|
||||
|
||||
Log.notice( F("PERF: Performance logging enabled. Power sensor %s" CR), measurePower?"found":"not found");
|
||||
}
|
||||
|
||||
//
|
||||
// Initialize
|
||||
//
|
||||
void PerfLogging::readPowerSensor(PerfEntry *pe) {
|
||||
pe->mA = 0;
|
||||
pe->V = 0;
|
||||
|
||||
if( !measurePower )
|
||||
return;
|
||||
|
||||
if( ina219.getOverflow() )
|
||||
Log.error( F("PERF: Voltage sensor overflow detected." CR));
|
||||
|
||||
/*
|
||||
shuntVoltage_mV = ina219.getShuntVoltage_mV();
|
||||
busVoltage_V = ina219.getBusVoltage_V();
|
||||
current_mA = ina219.getCurrent_mA();
|
||||
power_mW = ina219.getBusPower();
|
||||
loadVoltage_V = busVoltage_V + (shuntVoltage_mV/1000);
|
||||
*/
|
||||
|
||||
pe->mA = ina219.getCurrent_mA();
|
||||
pe->V = ina219.getBusVoltage_V() + (ina219.getShuntVoltage_mV()/1000);
|
||||
}
|
||||
|
||||
//
|
||||
// Clear the current cache
|
||||
//
|
||||
void PerfLogging::clear() {
|
||||
// Clear the measurements
|
||||
if( first == 0 )
|
||||
return;
|
||||
|
||||
PerfEntry* pe = first;
|
||||
|
||||
do {
|
||||
PerfEntry* p = pe;
|
||||
pe->max = 0;
|
||||
pe->start = 0;
|
||||
pe->end = 0;
|
||||
pe->mA = 0;
|
||||
pe->V = 0;
|
||||
pe = pe->next;
|
||||
delete p;
|
||||
} while( pe != 0 );
|
||||
|
||||
first = 0;
|
||||
}
|
||||
|
||||
//
|
||||
@ -137,8 +178,10 @@ void PerfLogging::stop( const char* key ) {
|
||||
|
||||
unsigned long t = pe->end - pe->start;
|
||||
|
||||
if( t > pe->max )
|
||||
if( t > pe->max )
|
||||
pe->max = t;
|
||||
|
||||
readPowerSensor( pe );
|
||||
}
|
||||
}
|
||||
|
||||
@ -175,11 +218,19 @@ void PerfLogging::pushInflux() {
|
||||
String body;
|
||||
|
||||
PerfEntry* pe = first;
|
||||
char buf[100];
|
||||
sprintf( &buf[0], "perf,host=%s,device=%s ", myConfig.getMDNS(), myConfig.getID() );
|
||||
body += &buf[0];
|
||||
|
||||
while( pe != 0 ) {
|
||||
char buf[100];
|
||||
sprintf( &buf[0], "%s,host=%s,device=%s value=%ld\n", pe->key, myConfig.getMDNS(), myConfig.getID(), pe->max);
|
||||
body += &buf[0];
|
||||
if( pe->max ) {
|
||||
if( pe->next )
|
||||
sprintf( &buf[0], "%s=%ld,", pe->key, pe->max);
|
||||
else
|
||||
sprintf( &buf[0], "%s=%ld", pe->key, pe->max);
|
||||
|
||||
body += &buf[0];
|
||||
}
|
||||
pe = pe->next;
|
||||
}
|
||||
|
||||
|
10
src/helper.h
10
src/helper.h
@ -66,10 +66,15 @@ class PerfLogging {
|
||||
unsigned long end; // millis()
|
||||
unsigned long max; // max time in ms
|
||||
const char* key; // measurement
|
||||
PerfEntry* next; //
|
||||
|
||||
PerfEntry* next; // Next in the linked list
|
||||
|
||||
float mA; // Power consumption
|
||||
float V; // Power consumption
|
||||
};
|
||||
|
||||
PerfEntry* first = 0;
|
||||
bool measurePower = false;
|
||||
|
||||
PerfEntry* find( const char* k ) {
|
||||
if( first == 0 )
|
||||
@ -112,7 +117,10 @@ class PerfLogging {
|
||||
return pe;
|
||||
};
|
||||
|
||||
void readPowerSensor(PerfEntry* pe);
|
||||
|
||||
public:
|
||||
PerfLogging();
|
||||
void clear();
|
||||
void start( const char* key );
|
||||
void stop( const char* key );
|
||||
|
96
src/main.cpp
96
src/main.cpp
@ -35,7 +35,6 @@ SOFTWARE.
|
||||
#define ESP8266_DRD_USE_RTC true
|
||||
#define DRD_TIMEOUT 2
|
||||
#define DRD_ADDRESS 0
|
||||
#define DOUBLERESETDETECTOR_DEBUG true
|
||||
#include <ESP_DoubleResetDetector.h>
|
||||
DoubleResetDetector *drd;
|
||||
|
||||
@ -47,10 +46,12 @@ bool sleepModeAlwaysSkip = true; // Web interface can override normal
|
||||
const int interval = 200; // ms, time to wait between changes to output
|
||||
bool sleepModeAlwaysSkip = false; // Web interface can override normal behaviour
|
||||
#endif
|
||||
unsigned long lastMillis = 0;
|
||||
unsigned long startMillis;
|
||||
bool sleepModeActive = false;
|
||||
int loopCounter = 0;
|
||||
unsigned long loopMillis = 0; // Used for main loop to run the code every _interval_
|
||||
unsigned long runtimeMillis; // Used to calculate the total time since start/wakeup
|
||||
unsigned long stableGyroMillis; // Used to calculate the total time since last stable gyro reading
|
||||
bool sleepModeActive = false;
|
||||
bool goToSleep = false;
|
||||
int loopCounter = 0;
|
||||
|
||||
//
|
||||
// Check if we should be in sleep mode
|
||||
@ -78,7 +79,7 @@ void checkSleepMode( float angle, float volt ) {
|
||||
}
|
||||
|
||||
// Will not enter sleep mode if: charger is connected
|
||||
sleepModeActive = (volt<4.15 && angle>85) || (volt>4.15) ? false : true;
|
||||
sleepModeActive = (volt<4.15 && (angle>85 && angle<95)) || (volt>4.15) ? false : true;
|
||||
|
||||
// sleep mode active when flat
|
||||
//sleepModeActive = ( angle<85 && angle>5 ) ? true : false;
|
||||
@ -93,7 +94,7 @@ void checkSleepMode( float angle, float volt ) {
|
||||
void setup() {
|
||||
LOG_PERF_START("run-time");
|
||||
LOG_PERF_START("main-setup");
|
||||
startMillis = millis();
|
||||
runtimeMillis = millis();
|
||||
|
||||
drd = new DoubleResetDetector(DRD_TIMEOUT, DRD_ADDRESS);
|
||||
bool dt = drd->detectDoubleReset();
|
||||
@ -118,10 +119,10 @@ void setup() {
|
||||
LOG_PERF_STOP("main-temp-setup");
|
||||
|
||||
// Setup Gyro
|
||||
LOG_PERF_START("main-gyro-setup");
|
||||
//LOG_PERF_START("main-gyro-setup"); // Takes less than 5ms, so skip this measurment
|
||||
if( !myGyro.setup() )
|
||||
Log.error(F("Main: Failed to initialize the gyro." CR));
|
||||
LOG_PERF_STOP("main-gyro-setup");
|
||||
//LOG_PERF_STOP("main-gyro-setup");
|
||||
|
||||
if( dt )
|
||||
Log.notice(F("Main: Detected doubletap on reset." CR));
|
||||
@ -148,16 +149,15 @@ void setup() {
|
||||
LOG_PERF_STOP("main-wifi-ota");
|
||||
#endif
|
||||
if( !sleepModeActive ) {
|
||||
LOG_PERF_START("main-webserver-setup");
|
||||
//LOG_PERF_START("main-webserver-setup"); // Takes less than 4ms , so skip this measurment
|
||||
myWebServer.setupWebServer();
|
||||
LOG_PERF_STOP("main-webserver-setup");
|
||||
//LOG_PERF_STOP("main-webserver-setup");
|
||||
}
|
||||
}
|
||||
|
||||
LOG_PERF_STOP("main-setup");
|
||||
LOG_PERF_PRINT(); // Dump data to serial
|
||||
LOG_PERF_PUSH(); // Dump data to influx
|
||||
Log.notice(F("Main: Setup completed." CR));
|
||||
stableGyroMillis = millis(); // Put it here so we dont include time for wifi connection
|
||||
}
|
||||
|
||||
//
|
||||
@ -166,26 +166,31 @@ void setup() {
|
||||
void loop() {
|
||||
drd->loop();
|
||||
|
||||
if( sleepModeActive || abs(millis() - lastMillis) > interval ) {
|
||||
float angle = 90;
|
||||
if( sleepModeActive || abs(millis() - loopMillis) > interval ) {
|
||||
float angle = 0;
|
||||
float volt = myBatteryVoltage.getVoltage();
|
||||
float sensorTemp = 0;
|
||||
loopCounter++;
|
||||
#if LOG_LEVEL==6
|
||||
Log.verbose(F("Main: Entering main loop." CR) );
|
||||
#endif
|
||||
// Process the sensor values and push data to targets.
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// If we dont get any readings we just skip this and try again the next interval.
|
||||
//
|
||||
if( myGyro.hasValue() ) {
|
||||
angle = myGyro.getAngle(); // Gyro angle
|
||||
sensorTemp = myGyro.getSensorTempC(); // Temp in the Gyro
|
||||
|
||||
stableGyroMillis = millis(); // Reset timer
|
||||
|
||||
LOG_PERF_START("loop-temp-read");
|
||||
float temp = myTempSensor.getValueCelcius(); // The code is build around using C for temp.
|
||||
LOG_PERF_STOP("loop-temp-read");
|
||||
|
||||
LOG_PERF_START("loop-gravity-calc");
|
||||
//LOG_PERF_START("loop-gravity-calc"); // Takes less than 2ms , so skip this measurment
|
||||
float gravity = calculateGravity( angle, temp );
|
||||
LOG_PERF_STOP("loop-gravity-calc");
|
||||
//LOG_PERF_STOP("loop-gravity-calc");
|
||||
|
||||
#if LOG_LEVEL==6
|
||||
Log.verbose(F("Main: Sensor values gyro angle=%F gyro temp=%F, temp=%F, gravity=%F." CR), angle, sensorTemp, temp, gravity );
|
||||
@ -202,49 +207,62 @@ void loop() {
|
||||
// Limit the printout when sleep mode is not active.
|
||||
if( loopCounter%10 == 0 || sleepModeActive ) {
|
||||
Log.notice(F("Main: gyro angle=%F, gyro temp=%F, DS18B20 temp=%F, gravity=%F, batt=%F." CR), angle, sensorTemp, temp, gravity, volt );
|
||||
LOG_PERF_PRINT();
|
||||
}
|
||||
|
||||
unsigned long runTime = millis() - startMillis;
|
||||
|
||||
LOG_PERF_START("loop-push");
|
||||
myPushTarget.send( angle, gravity, temp, runTime/1000, sleepModeActive ); // Force the transmission if we are going to sleep
|
||||
myPushTarget.send( angle, gravity, temp, (millis()-runtimeMillis)/1000, sleepModeActive ); // Force the transmission if we are going to sleep
|
||||
LOG_PERF_STOP("loop-push");
|
||||
|
||||
// If we have completed the update lets go to sleep
|
||||
if( sleepModeActive )
|
||||
goToSleep = true;
|
||||
} else {
|
||||
Log.error(F("Main: No gyro value." CR) );
|
||||
}
|
||||
|
||||
if( sleepModeActive ) {
|
||||
unsigned long runTime = millis() - startMillis;
|
||||
|
||||
// Enter sleep mode...
|
||||
Log.notice(F("MAIN: Entering deep sleep for %d s, run time %l s, battery=%F V." CR), myConfig.getSleepInterval(), runTime/1000, volt );
|
||||
LittleFS.end();
|
||||
myGyro.enterSleep();
|
||||
drd->stop();
|
||||
LOG_PERF_STOP("run-time");
|
||||
LOG_PERF_PUSH();
|
||||
LOG_PERF_PRINT();
|
||||
delay(100);
|
||||
deepSleep( myConfig.getSleepInterval() );
|
||||
}
|
||||
|
||||
#if LOG_LEVEL==6
|
||||
Log.verbose(F("Main: Sleep mode not active." CR) );
|
||||
#endif
|
||||
int sleepInterval = myConfig.getSleepInterval();
|
||||
|
||||
// If the sensor is moving and we are not getting a clear reading, we enter sleep for a short time to conserve battery.
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
//
|
||||
if( sleepModeActive && ((millis()-stableGyroMillis)>10000L) ) { // 10s since last stable gyro reading
|
||||
Log.notice(F("MAIN: Unable to get a stable reading for 10s, sleeping for 60s." CR) );
|
||||
sleepInterval = 60; // 60s
|
||||
goToSleep = true;
|
||||
}
|
||||
|
||||
// Enter sleep mode if the conditions are right
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
//
|
||||
if( goToSleep ) {
|
||||
Log.notice(F("MAIN: Entering deep sleep for %d s, run time %l s, battery=%F V." CR), sleepInterval, (millis()-runtimeMillis)/1000, volt );
|
||||
LittleFS.end();
|
||||
myGyro.enterSleep();
|
||||
drd->stop();
|
||||
LOG_PERF_STOP("run-time");
|
||||
LOG_PERF_PUSH();
|
||||
delay(100);
|
||||
deepSleep( sleepInterval );
|
||||
}
|
||||
|
||||
// If we are running in normal mode we just continue
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Do these checks if we are running in normal mode (not sleep mode)
|
||||
//
|
||||
checkSleepMode( angle, volt );
|
||||
|
||||
LOG_PERF_START("loop-gyro-read");
|
||||
myGyro.read();
|
||||
LOG_PERF_STOP("loop-gyro-read");
|
||||
|
||||
LOG_PERF_START("loop-batt-read");
|
||||
//LOG_PERF_START("loop-batt-read"); // Takes less than 2ms , so skip this measurment
|
||||
myBatteryVoltage.read();
|
||||
LOG_PERF_STOP("loop-batt-read");
|
||||
//LOG_PERF_STOP("loop-batt-read");
|
||||
|
||||
lastMillis = millis();
|
||||
loopMillis = millis();
|
||||
#if LOG_LEVEL==6
|
||||
Log.verbose(F("Main: Heap %d kb FreeSketch %d kb." CR), ESP.getFreeHeap()/1024, ESP.getFreeSketchSpace()/1024 );
|
||||
Log.verbose(F("Main: HeapFrag %d %%." CR), ESP.getHeapFragmentation() );
|
||||
|
@ -23,6 +23,7 @@ SOFTWARE.
|
||||
*/
|
||||
#include "pushtarget.h"
|
||||
#include "config.h"
|
||||
#include "gyro.h" // For testing the tempsensor in the gyro
|
||||
|
||||
PushTarget myPushTarget;
|
||||
|
||||
@ -86,17 +87,11 @@ void PushTarget::sendInfluxDb2(float angle, float gravity, float temp, float run
|
||||
|
||||
// Create body for influxdb2
|
||||
char buf[1024];
|
||||
sprintf( &buf[0], "gravity,host=%s,device=%s,format=%s value=%.4f\n"
|
||||
"angle,host=%s,device=%s value=%.2f\n"
|
||||
"temp,host=%s,device=%s,format=%c value=%.1f\n"
|
||||
"battery,host=%s,device=%s value=%.2f\n"
|
||||
"rssi,host=%s,device=%s value=%d\n",
|
||||
sprintf( &buf[0], "measurement,host=%s,device=%s,temp-format=%c,gravity-format=%s "
|
||||
"gravity=%.4f,angle=%.2f,temp=%.2f,battery=%.2f,rssi=%d,temp2=%.2f\n",
|
||||
// TODO: Add support for plato format
|
||||
myConfig.getMDNS(), myConfig.getID(), "SG", gravity,
|
||||
myConfig.getMDNS(), myConfig.getID(), angle,
|
||||
myConfig.getMDNS(), myConfig.getID(), myConfig.getTempFormat(), temp,
|
||||
myConfig.getMDNS(), myConfig.getID(), myBatteryVoltage.getVoltage(),
|
||||
myConfig.getMDNS(), myConfig.getID(), WiFi.RSSI() );
|
||||
myConfig.getMDNS(), myConfig.getID(), myConfig.getTempFormat(), "SG",
|
||||
gravity, angle, temp, myBatteryVoltage.getVoltage(), WiFi.RSSI(), myGyro.getSensorTempC() ); // For comparing gyro tempsensor vs DSB1820
|
||||
|
||||
#if LOG_LEVEL==6
|
||||
Log.verbose(F("PUSH: url %s." CR), serverPath.c_str());
|
||||
@ -115,7 +110,6 @@ void PushTarget::sendInfluxDb2(float angle, float gravity, float temp, float run
|
||||
}
|
||||
|
||||
http.end();
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -21,7 +21,6 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
//#define DEBUG_ESP_HTTP_SERVER
|
||||
#include "webserver.h"
|
||||
#include "config.h"
|
||||
#include "helper.h"
|
||||
@ -31,7 +30,6 @@ SOFTWARE.
|
||||
#include <ArduinoJson.h>
|
||||
#include <incbin.h>
|
||||
#include <ESP8266WiFi.h>
|
||||
//#define DEBUG_ESP_HTTP_SERVER
|
||||
#include <ESP8266WebServer.h>
|
||||
#include <ESP8266mDNS.h>
|
||||
#include <LittleFS.h>
|
||||
|
Loading…
Reference in New Issue
Block a user