diff --git a/README.md b/README.md
index 53c8d15d..f0a04a59 100644
--- a/README.md
+++ b/README.md
@@ -35,8 +35,7 @@ Check out [IOT DEVICE PULLS ITS WEIGHT IN HOME BREWING](http://hackaday.com/2017
***
-## Firmware download:
-***https://github.com/universam1/iSpindel/releases***
+## [Firmware download here](https://github.com/universam1/iSpindel/releases)
***
@@ -44,10 +43,11 @@ Check out [IOT DEVICE PULLS ITS WEIGHT IN HOME BREWING](http://hackaday.com/2017
| Date | Note |
| :--------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| 16.08.2018 | Firmware 5.9.1: Fixing Ubidots issue and extending MQTT |
-| 09.08.2018 | Firmware 5.9.0: Support for MQTT, InfluxDB (Thanks to jmelhus, iceaway and thorrak) |
-| 13.05.2018 | Firmware 5.8.6: allow longer fields for polynominal, SSID and Password |
-| 15.03.2018 | Firmware 5.8.5: adding support for Prometheus Pushgateway, thanks to @jankeesv |
+| 22.08.2018 | **Firmware 6.0.0**:
1. Alternative pin for OneWire tempearuture sensor DS18B20 now possible. This allows a different PCB schema to use either pin `D1` or `D6`.
2. Auto detection of OneWire pin, successfull detected pin will be saved together with a config `save` action. Output of detailed debug information of OneWire Sensor during searches, helping those with hardware issues.
3. Increased battery lifetime of about 20% by reducing the runtime to ~2200ms through various tunings.
4. Using *Interrupts* instead of delays to read the Accelerometer, allows significant shorter read intervals
5. Shorter read cycles allow *more precision*, increased samples from 7 to 39 samples that still fit into the necessary wait state for the Temp sensor! |
+| 16.08.2018 | Firmware 5.9.1: Fixing Ubidots issue and extending MQTT |
+| 09.08.2018 | Firmware 5.9.0: Support for MQTT, InfluxDB (Thanks to jmelhus, iceaway and thorrak) |
+| 13.05.2018 | Firmware 5.8.6: allow longer fields for polynominal, SSID and Password |
+| 15.03.2018 | Firmware 5.8.5: adding support for Prometheus Pushgateway, thanks to @jankeesv |
| 08.03.2018 | Firmware 5.8.4: adding support for logging temperature data in Fahrenheit and Kelvin, thanks to @iceaway |
| 05.03.2018 | Firmware 5.8.3: Support for InfluxDB as additional backend, thanks to @iceaway |
| 23.02.2018 | New drawer version 'mwx-Edition' using threaded bolt nut and washer - thanks to @mwx |
diff --git a/pio/lib/Globals/Globals.h b/pio/lib/Globals/Globals.h
index dad6bef4..64ffee95 100644
--- a/pio/lib/Globals/Globals.h
+++ b/pio/lib/Globals/Globals.h
@@ -20,7 +20,7 @@
extern Ticker flasher;
// defines go here
-#define FIRMWAREVERSION "5.9.1"
+#define FIRMWAREVERSION "6.0.0"
#define API_FHEM true
#define API_UBIDOTS true
@@ -42,15 +42,15 @@ extern Ticker flasher;
#define CONSOLELN CONSOLE
#define CONSOLEF CONSOLE
#else
-#define CONSOLE(x) \
+#define CONSOLE(...) \
do \
{ \
- Serial.print(x); \
+ Serial.print(__VA_ARGS__); \
} while (0)
-#define CONSOLELN(x) \
+#define CONSOLELN(...) \
do \
{ \
- Serial.println(x); \
+ Serial.println(__VA_ARGS__); \
} while (0)
#endif
@@ -58,13 +58,13 @@ extern Ticker flasher;
#define ADCDIVISOR 191.8
#define ONE_WIRE_BUS D6 // DS18B20 on ESP pin12
+#define OW_PINS (const uint8_t[]){D1, D6}
#define RESOLUTION 12 // 12bit resolution == 750ms update rate
-#define OWinterval (800 / (1 << (12 - RESOLUTION)))
+#define OWinterval (760 / (1 << (12 - RESOLUTION)))
#define CFGFILE "/config.json"
#define TKIDSIZE 40
-#define MEDIANROUNDS 7
-#define ACCINTERVAL 200
-#define MEDIANAVRG 3
+#define MEDIANROUNDS 39
+#define MEDIANAVRG 29
#define CBP_ENDPOINT "/api/hydrometer/v1/data"
diff --git a/pio/lib/Sender/Sender.cpp b/pio/lib/Sender/Sender.cpp
index 7c9b5fcc..c3dc6750 100644
--- a/pio/lib/Sender/Sender.cpp
+++ b/pio/lib/Sender/Sender.cpp
@@ -33,45 +33,51 @@ void SenderClass::add(String id, int32_t value)
_jsonVariant[id] = value;
}
-bool SenderClass::sendMQTT(String server, uint16_t port, String username, String password, String name) {
- _mqttClient.setClient(_client);
- _mqttClient.setServer(server.c_str(), port);
- _mqttClient.setCallback([this](char* topic, byte* payload, unsigned int length) { this->mqttCallback(topic, payload, length); });
-
- while (!_mqttClient.connected()) {
- CONSOLELN(F("Attempting MQTT connection"));
- // Attempt to connect
- if (_mqttClient.connect(name.c_str(), username.c_str(), password.c_str())) {
- CONSOLELN(F("Connected to MQTT"));
- }
- else {
- CONSOLELN(F("Failed MQTT connection, return code:"));
- CONSOLELN(_mqttClient.state());
- CONSOLELN(F("Retrying MQTT connection in 5 seconds"));
- // Wait 5 seconds before retrying
- delay(5000);
- }
- }
- //MQTT publish values
- for (const auto &kv : _jsonVariant.as())
- {
- CONSOLELN("MQTT publish: ispindel/" + name + "/" + kv.key + "/" + kv.value.as());
- _mqttClient.publish(("ispindel/" + name + "/" + kv.key).c_str(), kv.value.as().c_str());
- _mqttClient.loop(); //This should be called regularly to allow the client to process incoming messages and maintain its connection to the server.
- }
-
- CONSOLELN(F("Closing MQTT connection"));
- _mqttClient.disconnect();
- delay(100); // allow gracefull session close
- return true;
+bool SenderClass::sendMQTT(String server, uint16_t port, String username, String password, String name)
+{
+ _mqttClient.setClient(_client);
+ _mqttClient.setServer(server.c_str(), port);
+ _mqttClient.setCallback([this](char *topic, byte *payload, unsigned int length) { this->mqttCallback(topic, payload, length); });
+
+ while (!_mqttClient.connected())
+ {
+ CONSOLELN(F("Attempting MQTT connection"));
+ // Attempt to connect
+ if (_mqttClient.connect(name.c_str(), username.c_str(), password.c_str()))
+ {
+ CONSOLELN(F("Connected to MQTT"));
+ }
+ else
+ {
+ CONSOLELN(F("Failed MQTT connection, return code:"));
+ CONSOLELN(_mqttClient.state());
+ CONSOLELN(F("Retrying MQTT connection in 5 seconds"));
+ // Wait 5 seconds before retrying
+ delay(5000);
+ }
+ }
+ //MQTT publish values
+ for (const auto &kv : _jsonVariant.as())
+ {
+ CONSOLELN("MQTT publish: ispindel/" + name + "/" + kv.key + "/" + kv.value.as());
+ _mqttClient.publish(("ispindel/" + name + "/" + kv.key).c_str(), kv.value.as().c_str());
+ _mqttClient.loop(); //This should be called regularly to allow the client to process incoming messages and maintain its connection to the server.
+ }
+
+ CONSOLELN(F("Closing MQTT connection"));
+ _mqttClient.disconnect();
+ delay(100); // allow gracefull session close
+ return true;
}
-void SenderClass::mqttCallback(char* topic, byte* payload, unsigned int length) {
- CONSOLELN(F("MQTT message arrived ["));
- CONSOLELN(topic);
- CONSOLELN(F("] "));
- for (unsigned int i = 0; i < length; i++) {
- CONSOLE((char)payload[i]);
- }
+void SenderClass::mqttCallback(char *topic, byte *payload, unsigned int length)
+{
+ CONSOLELN(F("MQTT message arrived ["));
+ CONSOLELN(topic);
+ CONSOLELN(F("] "));
+ for (unsigned int i = 0; i < length; i++)
+ {
+ CONSOLE((char)payload[i]);
+ }
}
bool SenderClass::sendTCP(String server, uint16_t port)
@@ -80,7 +86,7 @@ bool SenderClass::sendTCP(String server, uint16_t port)
if (_client.connect(server.c_str(), port))
{
- CONSOLELN(F("Sender: TCP stream"));
+ CONSOLELN(F("\nSender: TCP stream"));
_jsonVariant.printTo(_client);
_client.println();
}
@@ -139,6 +145,7 @@ bool SenderClass::sendGenericPost(String server, String url, uint16_t port)
}
http.end();
+ delay(100); // allow gracefull session close
return true;
}
@@ -155,7 +162,7 @@ bool SenderClass::sendInfluxDB(String server, uint16_t port, String db, String n
if (username.length() > 0)
{
- http.setAuthorization(username.c_str(), password.c_str());
+ http.setAuthorization(username.c_str(), password.c_str());
}
http.addHeader("User-Agent", "iSpindel");
@@ -196,14 +203,14 @@ bool SenderClass::sendInfluxDB(String server, uint16_t port, String db, String n
}
http.end();
-
+ delay(100); // allow gracefull session close
return true;
}
bool SenderClass::sendPrometheus(String server, uint16_t port, String job, String instance)
{
HTTPClient http;
-
+
// the path looks like /metrics/job/[/instance/]
String uri = "/metrics/job/";
uri += job;
@@ -254,6 +261,7 @@ bool SenderClass::sendPrometheus(String server, uint16_t port, String job, Strin
}
http.end();
+ delay(100); // allow gracefull session close
return true;
}
@@ -263,7 +271,7 @@ bool SenderClass::sendUbidots(String token, String name)
if (_client.connect(UBISERVER, 80))
{
- CONSOLELN(F("Sender: Ubidots posting"));
+ CONSOLELN(F("\nSender: Ubidots posting"));
String msg = F("POST /api/v1.6/devices/");
msg += name;
@@ -274,8 +282,6 @@ bool SenderClass::sendUbidots(String token, String name)
msg += "\r\n";
_client.println(msg);
- CONSOLELN(msg);
-
_jsonVariant.printTo(_client);
_client.println();
CONSOLELN(msg);
@@ -359,7 +365,7 @@ bool SenderClass::sendTCONTROL(String server, uint16_t port)
if (_client.connect(server.c_str(), port))
{
- CONSOLELN(F("Sender: TCONTROL"));
+ CONSOLELN(F("\nSender: TCONTROL"));
String msg;
for (const auto &kv : _jsonVariant.as())
diff --git a/pio/src/iSpindel.cpp b/pio/src/iSpindel.cpp
index b329ea5f..ac35113e 100644
--- a/pio/src/iSpindel.cpp
+++ b/pio/src/iSpindel.cpp
@@ -29,17 +29,19 @@ All rights reserverd by S.Lang
// definitions go here
MPU6050_Base accelgyro;
-OneWire oneWire(ONE_WIRE_BUS);
-DallasTemperature DS18B20(&oneWire);
+OneWire *oneWire;
+DallasTemperature DS18B20;
DeviceAddress tempDeviceAddress;
Ticker flasher;
RunningMedian samples = RunningMedian(MEDIANROUNDS);
+DoubleResetDetector drd(DRD_TIMEOUT, DRD_ADDRESS);
#define TEMP_CELSIUS 0
#define TEMP_FAHRENHEIT 1
#define TEMP_KELVIN 2
-DoubleResetDetector drd(DRD_TIMEOUT, DRD_ADDRESS);
+int detectTempSensor(const uint8_t pins[]);
+bool testAccel();
#ifdef USE_DMP
#include "MPU6050.h"
@@ -83,15 +85,14 @@ uint16_t my_port = 80;
float my_vfact = ADCDIVISOR;
int16_t my_aX = UNINIT, my_aY = UNINIT, my_aZ = UNINIT;
uint8_t my_tempscale = TEMP_CELSIUS;
+int8_t my_OWpin = -1;
-uint32_t DSreqTime;
+uint32_t DSreqTime = 0;
float pitch, roll;
int16_t ax, ay, az;
float Volt, Temperatur, Tilt, Gravity; // , corrGravity;
-bool DSrequested = false;
-
float scaleTemperature(float t)
{
if (my_tempscale == TEMP_CELSIUS)
@@ -116,7 +117,6 @@ String tempScaleLabel(void)
return "C"; // Invalid value for my_tempscale => default to celsius
}
-
// callback notifying us of the need to save config
void saveConfigCallback()
{
@@ -150,7 +150,6 @@ bool readConfig()
File configFile = SPIFFS.open(CFGFILE, "r");
if (configFile)
{
- CONSOLELN(F("opened config file"));
size_t size = configFile.size();
// Allocate a buffer to store contents of the file.
std::unique_ptr buf(new char[size]);
@@ -161,8 +160,6 @@ bool readConfig()
if (json.success())
{
- CONSOLELN(F("\nparsed json"));
-
if (json.containsKey("Name"))
strcpy(my_name, json["Name"]);
if (json.containsKey("Token"))
@@ -191,6 +188,8 @@ bool readConfig()
my_vfact = json["Vfact"];
if (json.containsKey("TS"))
my_tempscale = json["TS"];
+ if (json.containsKey("OWpin"))
+ my_OWpin = json["OWpin"];
if (json.containsKey("SSID"))
my_ssid = (const char *)json["SSID"];
if (json.containsKey("PSK"))
@@ -213,6 +212,7 @@ bool readConfig()
CONSOLELN(F("parsed config:"));
#ifdef DEBUG
json.printTo(Serial);
+ CONSOLELN();
#endif
return true;
}
@@ -233,7 +233,7 @@ bool readConfig()
return true;
}
-bool shouldStartConfig()
+bool shouldStartConfig(bool validConf)
{
// we make sure that configuration is properly set and we are not woken by
@@ -247,7 +247,7 @@ bool shouldStartConfig()
// The reset reason is "5" (woken from deep-sleep) in most cases (also after a power-cycle)
// I added a single reset detection as workaround to enter the config-mode easier
CONSOLE(F("Boot-Mode: "));
- CONSOLELN(_reset_reason);
+ CONSOLELN(ESP.getResetReason());
bool _poweredOnOffOn = _reset_reason == REASON_DEFAULT_RST || _reset_reason == REASON_EXT_SYS_RST;
if (_poweredOnOffOn)
CONSOLELN(F("power-cycle or reset detected, config mode"));
@@ -255,9 +255,6 @@ bool shouldStartConfig()
bool _dblreset = drd.detectDoubleReset();
if (_dblreset)
CONSOLELN(F("\nDouble Reset detected"));
- bool _validConf = readConfig();
- if (!_validConf)
- CONSOLELN(F("\nERROR config corrupted"));
bool _wifiCred = (WiFi.SSID() != "");
uint8_t c = 0;
@@ -275,7 +272,7 @@ bool shouldStartConfig()
if (!_wifiCred)
CONSOLELN(F("\nERROR no Wifi credentials"));
- if (_validConf && !_dblreset && _wifiCred && !_poweredOnOffOn)
+ if (validConf && !_dblreset && _wifiCred && !_poweredOnOffOn)
{
CONSOLELN(F("\nwoken from deepsleep, normal mode"));
return false;
@@ -296,48 +293,6 @@ void validateInput(const char *input, char *output)
tmp.toCharArray(output, tmp.length() + 1);
}
-// String urlencode(String str)
-// {
-// String encodedString = "";
-// char c;
-// char code0;
-// char code1;
-// char code2;
-// for (auto i = 0; i < str.length(); i++)
-// {
-// c = str.charAt(i);
-// if (c == ' ')
-// {
-// encodedString += '+';
-// }
-// else if (isalnum(c))
-// {
-// encodedString += c;
-// }
-// else
-// {
-// code1 = (c & 0xf) + '0';
-// if ((c & 0xf) > 9)
-// {
-// code1 = (c & 0xf) - 10 + 'A';
-// }
-// c = (c >> 4) & 0xf;
-// code0 = c + '0';
-// if (c > 9)
-// {
-// code0 = c - 10 + 'A';
-// }
-// code2 = '\0';
-// encodedString += '%';
-// encodedString += code0;
-// encodedString += code1;
-// //encodedString+=code2;
-// }
-// yield();
-// }
-// return encodedString;
-// }
-
String htmlencode(String str)
{
String encodedstr = "";
@@ -372,19 +327,19 @@ bool startConfiguration()
WiFiManagerParameter api_list(HTTP_API_LIST);
WiFiManagerParameter custom_api("selAPI", "selAPI", String(my_api).c_str(),
- 20, TYPE_HIDDEN, WFM_NO_LABEL);
+ 20, TYPE_HIDDEN, WFM_NO_LABEL);
WiFiManagerParameter custom_name("name", "iSpindel Name", htmlencode(my_name).c_str(),
- TKIDSIZE * 2);
+ TKIDSIZE * 2);
WiFiManagerParameter custom_sleep("sleep", "Update Intervall (s)",
- String(my_sleeptime).c_str(), 6, TYPE_NUMBER);
+ String(my_sleeptime).c_str(), 6, TYPE_NUMBER);
WiFiManagerParameter custom_token("token", "Token", htmlencode(my_token).c_str(),
- TKIDSIZE * 2);
+ TKIDSIZE * 2);
WiFiManagerParameter custom_server("server", "Server Address",
- my_server, TKIDSIZE);
+ my_server, TKIDSIZE);
WiFiManagerParameter custom_port("port", "Server Port",
- String(my_port).c_str(), TKIDSIZE,
- TYPE_NUMBER);
+ String(my_port).c_str(), TKIDSIZE,
+ TYPE_NUMBER);
WiFiManagerParameter custom_url("url", "Server URL", my_url, TKIDSIZE);
WiFiManagerParameter custom_db("db", "InfluxDB db", my_db, TKIDSIZE);
WiFiManagerParameter custom_username("username", "Username", my_username, TKIDSIZE);
@@ -392,11 +347,11 @@ bool startConfiguration()
WiFiManagerParameter custom_job("job", "Prometheus job", my_job, TKIDSIZE);
WiFiManagerParameter custom_instance("instance", "Prometheus instance", my_instance, TKIDSIZE);
WiFiManagerParameter custom_vfact("vfact", "Battery conversion factor",
- String(my_vfact).c_str(), 7, TYPE_NUMBER);
+ String(my_vfact).c_str(), 7, TYPE_NUMBER);
WiFiManagerParameter tempscale_list(HTTP_TEMPSCALE_LIST);
WiFiManagerParameter custom_tempscale("tempscale", "tempscale",
- String(my_tempscale).c_str(),
- 5, TYPE_HIDDEN, WFM_NO_LABEL);
+ String(my_tempscale).c_str(),
+ 5, TYPE_HIDDEN, WFM_NO_LABEL);
wifiManager.addParameter(&custom_name);
wifiManager.addParameter(&custom_sleep);
@@ -482,7 +437,7 @@ bool saveConfig()
// if SPIFFS is not usable
if (!SPIFFS.begin() || !SPIFFS.exists(CFGFILE) ||
- !SPIFFS.open(CFGFILE, "w"))
+ !SPIFFS.open(CFGFILE, "w"))
formatSpiffs();
DynamicJsonBuffer jsonBuffer;
@@ -504,6 +459,7 @@ bool saveConfig()
json["Instance"] = my_instance;
json["Vfact"] = my_vfact;
json["TS"] = my_tempscale;
+ json["OWpin"] = my_OWpin;
// Store current Wifi credentials
json["SSID"] = WiFi.SSID();
@@ -662,7 +618,7 @@ bool uploadData(uint8_t service)
return sender.sendTCONTROL(my_server, my_port);
}
#endif // DATABASESYSTEM ==
-return false;
+ return false;
}
void goodNight(uint32_t seconds)
@@ -675,8 +631,8 @@ void goodNight(uint32_t seconds)
drd.stop();
// workaround for DS not floating
- pinMode(ONE_WIRE_BUS, OUTPUT);
- digitalWrite(ONE_WIRE_BUS, LOW);
+ pinMode(my_OWpin, OUTPUT);
+ digitalWrite(my_OWpin, LOW);
// we need another incarnation before work run
if (_seconds > MAXSLEEPTIME)
@@ -684,10 +640,8 @@ void goodNight(uint32_t seconds)
left2sleep = _seconds - MAXSLEEPTIME;
ESP.rtcUserMemoryWrite(RTCSLEEPADDR, &left2sleep, sizeof(left2sleep));
ESP.rtcUserMemoryWrite(RTCSLEEPADDR + 1, &validflag, sizeof(validflag));
- CONSOLELN(String(F("\nStep-sleep: ")) + MAXSLEEPTIME + "s; left: " + left2sleep + "s; RT:" + millis());
+ CONSOLELN(String(F("\nStep-sleep: ")) + MAXSLEEPTIME + "s; left: " + left2sleep + "s; RT: " + millis());
ESP.deepSleep(MAXSLEEPTIME * 1e6, WAKE_RF_DISABLED);
- // workaround proper power state init
- delay(500);
}
// regular sleep with RF enabled after wakeup
else
@@ -696,12 +650,12 @@ void goodNight(uint32_t seconds)
left2sleep = 0;
ESP.rtcUserMemoryWrite(RTCSLEEPADDR, &left2sleep, sizeof(left2sleep));
ESP.rtcUserMemoryWrite(RTCSLEEPADDR + 1, &validflag, sizeof(validflag));
- CONSOLELN(String(F("\nFinal-sleep: ")) + _seconds + "s; RT:" + millis());
+ CONSOLELN(String(F("\nFinal-sleep: ")) + _seconds + "s; RT: " + millis());
// WAKE_RF_DEFAULT --> auto reconnect after wakeup
ESP.deepSleep(_seconds * 1e6, WAKE_RF_DEFAULT);
- // workaround proper power state init
- delay(500);
}
+ // workaround proper power state init
+ delay(500);
}
void sleepManager()
{
@@ -722,25 +676,51 @@ void sleepManager()
void requestTemp()
{
- if (!DSrequested)
+ if (!DSreqTime)
{
DS18B20.requestTemperatures();
DSreqTime = millis();
- DSrequested = true;
}
}
void initDS18B20()
{
-
- // workaround for DS not enough power to boot
- pinMode(ONE_WIRE_BUS, OUTPUT);
- digitalWrite(ONE_WIRE_BUS, LOW);
+ if (my_OWpin == -1)
+ {
+ my_OWpin = detectTempSensor(OW_PINS);
+ if (my_OWpin == -1)
+ {
+ CONSOLELN(F("ERROR: cannot find a OneWire Temperature Sensor!"));
+ return;
+ }
+ }
+ pinMode(my_OWpin, OUTPUT);
+ digitalWrite(my_OWpin, LOW);
delay(100);
-
+ oneWire = new OneWire(my_OWpin);
+ DS18B20 = DallasTemperature(oneWire);
DS18B20.begin();
+
+ bool device = DS18B20.getAddress(tempDeviceAddress, 0);
+ if (!device)
+ {
+ my_OWpin = detectTempSensor(OW_PINS);
+ if (my_OWpin == -1)
+ {
+ CONSOLELN(F("ERROR: cannot find a OneWire Temperature Sensor!"));
+ return;
+ }
+ else
+ {
+ delete oneWire;
+ oneWire = new OneWire(my_OWpin);
+ DS18B20 = DallasTemperature(oneWire);
+ DS18B20.begin();
+ DS18B20.getAddress(tempDeviceAddress, 0);
+ }
+ }
+
DS18B20.setWaitForConversion(false);
- DS18B20.getAddress(tempDeviceAddress, 0);
DS18B20.setResolution(tempDeviceAddress, RESOLUTION);
requestTemp();
}
@@ -754,12 +734,20 @@ void initAccel()
// init the Accel
accelgyro.initialize();
+ accelgyro.setFullScaleAccelRange(MPU6050_ACCEL_FS_2);
+ accelgyro.setFullScaleGyroRange(MPU6050_GYRO_FS_250);
accelgyro.setDLPFMode(MPU6050_DLPF_BW_5);
accelgyro.setTempSensorEnabled(true);
#ifdef USE_DMP
accelgyro.setDMPEnabled(true);
packetSize = accelgyro.dmpGetFIFOPacketSize();
#endif
+ accelgyro.setInterruptLatch(0); // pulse
+ accelgyro.setInterruptMode(1); // Active Low
+ accelgyro.setInterruptDrive(1); // Open drain
+ accelgyro.setRate(17);
+ accelgyro.setIntDataReadyEnabled(true);
+ testAccel();
}
float calculateTilt()
@@ -772,31 +760,37 @@ float calculateTilt()
return sqrt(pitch * pitch + roll * roll);
}
-void getAccSample()
+bool testAccel()
{
uint8_t res = Wire.status();
- uint8_t con = accelgyro.testConnection();
- if (res == I2C_OK && con == true)
- accelgyro.getAcceleration(&ax, &az, &ay);
- else
- {
- CONSOLELN(String(F("I2C ERROR: ")) + res + " con:" + con);
- }
+ if (res != I2C_OK)
+ CONSOLELN(String(F("I2C ERROR: ")) + res);
+
+ bool con = accelgyro.testConnection();
+ if (!con)
+ CONSOLELN(F("Acc Test Connection ERROR!"));
+
+ return res == I2C_OK && con == true;
+}
+
+void getAccSample()
+{
+ accelgyro.getAcceleration(&ax, &az, &ay);
}
float getTilt()
{
- // make sure enough time for Acc to start
- uint32_t start = ACCINTERVAL;
+ uint32_t start;
for (uint8_t i = 0; i < MEDIANROUNDS; i++)
{
- while (millis() - start < ACCINTERVAL)
- yield();
start = millis();
+ while (!accelgyro.getIntDataReadyStatus())
+ yield();
+ CONSOLE(String("IRQ: ") + (millis() - start));
getAccSample();
float _tilt = calculateTilt();
- CONSOLE(F("Spl "));
+ CONSOLE(F("ms - Spl "));
CONSOLE(i);
CONSOLE(": ");
CONSOLELN(_tilt);
@@ -807,38 +801,150 @@ float getTilt()
float getTemperature(bool block = false)
{
- // we need to wait for DS18b20 to finish conversion
float t = Temperatur;
+ // we need to wait for DS18b20 to finish conversion
+ if (!DSreqTime ||
+ (!block && (millis() - DSreqTime < OWinterval)))
+ return t;
+
// if we need the result we have to block
- while (block && (millis() - DSreqTime <= OWinterval))
+ while (millis() - DSreqTime < OWinterval)
yield();
+ DSreqTime = 0;
- if (millis() - DSreqTime >= OWinterval)
- {
- t = DS18B20.getTempCByIndex(0);
- DSrequested = false;
+ t = DS18B20.getTempCByIndex(0);
- if (t == DEVICE_DISCONNECTED_C || // DISCONNECTED
+ if (t == DEVICE_DISCONNECTED_C || // DISCONNECTED
t == 85.0) // we read 85 uninitialized
+ {
+ CONSOLELN(F("ERROR: OW DISCONNECTED"));
+ pinMode(my_OWpin, OUTPUT);
+ digitalWrite(my_OWpin, LOW);
+ delay(100);
+ oneWire->reset();
+
+ CONSOLELN(F("OW Retry"));
+ initDS18B20();
+ delay(OWinterval);
+ t = getTemperature(false);
+ }
+
+ return t;
+}
+
+int detectTempSensor(const uint8_t pins[])
+{
+
+ for (uint8_t p = 0; p < sizeof(pins); p++)
+ {
+ const byte pin = pins[p];
+ byte i;
+ byte present = 0;
+ byte type_s;
+ byte data[12];
+ byte addr[8];
+ float celsius;
+
+ CONSOLE(F("scanning for OW device on pin: "));
+ CONSOLELN(pin);
+ OneWire ds(pin);
+
+ if (!ds.search(addr))
{
- CONSOLELN(F("ERROR: OW DISCONNECTED"));
- pinMode(ONE_WIRE_BUS, OUTPUT);
- digitalWrite(ONE_WIRE_BUS, LOW);
- delay(100);
- oneWire.reset();
+ CONSOLELN(F("No devices found!"));
+ ds.reset_search();
+ delay(250);
+ continue;
+ }
+
+ CONSOLE("Found device with ROM =");
+ for (i = 0; i < 8; i++)
+ {
+ CONSOLE(' ');
+ CONSOLE(addr[i], HEX);
+ }
+
+ if (OneWire::crc8(addr, 7) != addr[7])
+ {
+ CONSOLELN(" CRC is not valid!");
+ continue;
+ }
+ CONSOLELN();
+
+ // the first ROM byte indicates which chip
+ switch (addr[0])
+ {
+ case 0x10:
+ CONSOLELN(" Chip = DS18S20"); // or old DS1820
+ type_s = 1;
+ break;
+ case 0x28:
+ CONSOLELN(" Chip = DS18B20");
+ type_s = 0;
+ break;
+ case 0x22:
+ CONSOLELN(" Chip = DS1822");
+ type_s = 0;
+ break;
+ default:
+ CONSOLELN("Device is not a DS18x20 family device.");
+ continue;
+ }
- if (block)
+ ds.reset();
+ ds.select(addr);
+ ds.write(0x44, 1); // start conversion, with parasite power on at the end
+
+ delay(900); // maybe 750ms is enough, maybe not
+ present = ds.reset();
+ ds.select(addr);
+ ds.write(0xBE); // Read Scratchpad
+
+ CONSOLE(" Data = ");
+ CONSOLE(present, HEX);
+ CONSOLE(" ");
+ for (i = 0; i < 9; i++)
+ { // we need 9 bytes
+ data[i] = ds.read();
+ CONSOLE(data[i], HEX);
+ CONSOLE(" ");
+ }
+ CONSOLE(" CRC=");
+ CONSOLELN(OneWire::crc8(data, 8), HEX);
+
+ // Convert the data to actual temperature
+ int16_t raw = (data[1] << 8) | data[0];
+ if (type_s)
+ {
+ raw = raw << 3; // 9 bit resolution default
+ if (data[7] == 0x10)
{
- CONSOLELN(F("OW Retry"));
- initDS18B20();
- delay(OWinterval + 100);
- t = getTemperature(false);
+ // "count remain" gives full 12 bit resolution
+ raw = (raw & 0xFFF0) + 12 - data[6];
}
}
+ else
+ {
+ byte cfg = (data[4] & 0x60);
+ // at lower res, the low bits are undefined, so let's zero them
+ if (cfg == 0x00)
+ raw = raw & ~7; // 9 bit resolution, 93.75 ms
+ else if (cfg == 0x20)
+ raw = raw & ~3; // 10 bit res, 187.5 ms
+ else if (cfg == 0x40)
+ raw = raw & ~1; // 11 bit res, 375 ms
+ //// default is 12 bit resolution, 750 ms conversion time
+ }
+ celsius = (float)raw / 16.0;
+ CONSOLE(F(" Temperature = "));
+ CONSOLE(celsius);
+ CONSOLELN(F(" Celsius, "));
+ return pin;
}
- return t;
+ return -1;
}
+
float getBattery()
{
analogRead(A0); // drop first read
@@ -851,7 +957,7 @@ float calculateGravity()
double _temp = Temperatur;
float _gravity = 0;
int err;
- te_variable vars[] = { { "tilt", &_tilt }, { "temp", &_temp } };
+ te_variable vars[] = {{"tilt", &_tilt}, {"temp", &_temp}};
te_expr *expr = te_compile(my_polynominal, vars, 2, &err);
if (expr)
@@ -870,7 +976,8 @@ void flash()
{
// triggers the LED
Volt = getBattery();
- getAccSample();
+ if (testAccel())
+ getAccSample();
Tilt = calculateTilt();
Temperatur = getTemperature(false);
Gravity = calculateGravity();
@@ -906,11 +1013,14 @@ void setup()
sleepManager();
- initAccel();
+ bool validConf = readConfig();
+ if (!validConf)
+ CONSOLELN(F("\nERROR config corrupted"));
initDS18B20();
+ initAccel();
// decide whether we want configuration mode or normal mode
- if (shouldStartConfig())
+ if (shouldStartConfig(validConf))
{
uint32_t tmp;
ESP.rtcUserMemoryRead(WIFIENADDR, &tmp, sizeof(tmp));
@@ -938,7 +1048,7 @@ void setup()
{
// test if ssid exists
if (WiFi.SSID() == "" &&
- my_ssid != "" && my_psk != "")
+ my_ssid != "" && my_psk != "")
{
connectBackupCredentials();
}
@@ -1012,31 +1122,31 @@ void setup()
}
#endif
- Temperatur = accelgyro.getTemperature() / 340.00 + 36.53;
+ float accTemp = accelgyro.getTemperature() / 340.00 + 36.53;
accelgyro.setSleepEnabled(true);
- CONSOLE(F("\na: "));
+ CONSOLE("x: ");
CONSOLE(ax);
- CONSOLE(F("\t"));
+ CONSOLE(" y: ");
CONSOLE(ay);
- CONSOLE(F("\t"));
- CONSOLE(az);
+ CONSOLE(" z: ");
+ CONSOLELN(az);
- CONSOLE(F("\tabsTilt: "));
- CONSOLE(Tilt);
- CONSOLE(F("\tT: "));
- CONSOLE(Temperatur);
- CONSOLE(F("\tV: "));
- CONSOLE(Volt);
+ CONSOLE(F("Tilt: "));
+ CONSOLELN(Tilt);
+ CONSOLE("Tacc: ");
+ CONSOLELN(accTemp);
+ CONSOLE("Volt: ");
+ CONSOLELN(Volt);
// call as late as possible since DS needs converge time
Temperatur = getTemperature(true);
- CONSOLE(F("\towT: "));
- CONSOLE(Temperatur);
+ CONSOLE("Temp: ");
+ CONSOLELN(Temperatur);
// calc gravity on user defined polynominal
Gravity = calculateGravity();
- CONSOLE(F("\tGravity: "));
+ CONSOLE(F("Gravity: "));
CONSOLELN(Gravity);
// water anomaly correction
@@ -1046,28 +1156,29 @@ void setup()
// CONSOLE(F("\tcorrGravity: "));
// CONSOLELN(corrGravity);
- unsigned long startedAt = millis();
- CONSOLE(F("After waiting "));
- // int connRes = WiFi.waitForConnectResult();
- uint8_t wait = 0;
- while (WiFi.status() == WL_DISCONNECTED)
+ if (WiFi.status() != WL_CONNECTED)
{
- delay(100);
- wait++;
- if (wait > 50)
- break;
+ unsigned long startedAt = millis();
+ CONSOLE(F("After waiting "));
+ // int connRes = WiFi.waitForConnectResult();
+ uint8_t wait = 0;
+ while (WiFi.status() == WL_DISCONNECTED)
+ {
+ delay(100);
+ wait++;
+ if (wait > 50)
+ break;
+ }
+ auto waited = (millis() - startedAt);
+ CONSOLE(waited);
+ CONSOLE(F("ms, result "));
+ CONSOLELN(WiFi.status());
}
- auto waited = (millis() - startedAt);
- CONSOLE(waited);
- CONSOLE(F("ms, result "));
- CONSOLELN(WiFi.status());
-
if (WiFi.status() == WL_CONNECTED)
{
CONSOLE(F("IP: "));
CONSOLELN(WiFi.localIP());
uploadData(my_api);
- delay(100); // workaround for https://github.com/esp8266/Arduino/issues/2750
}
else
{