Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@Thiemann96
Created May 20, 2020 10:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Thiemann96/d91dec7a03d8e287efac3172ede2e20f to your computer and use it in GitHub Desktop.
Save Thiemann96/d91dec7a03d8e287efac3172ede2e20f to your computer and use it in GitHub Desktop.
OSeM OTA Sketch
/*
Testing OTA OSeM Sketch
senseBox:home - Citizen Sensingplatform
Version: wifiv2_0.3
Date: 2019-12-06
Homepage: https://www.sensebox.de https://www.opensensemap.org
Author: Reedu GmbH & Co. KG
Note: Sketch for senseBox:home WiFi MCU Edition
Model: homeV2Wifi
Email: support@sensebox.de
Code is in the public domain.
https://github.com/sensebox/node-sketch-templater
*/
#include <WiFi101.h>
#include <Wire.h>
#include <SPI.h>
#include <senseBoxIO.h>
#include "OTA.h"
#include <Adafruit_Sensor.h>
#include <Adafruit_HDC1000.h>
#include <Adafruit_BMP280.h>
#include <Adafruit_BME680.h>
#include <Makerblog_TSL45315.h>
#include <VEML6070.h>
// Uncomment the next line to get debugging messages printed on the Serial port
// Do not leave this enabled for long time use
#define ENABLE_DEBUG
#ifdef ENABLE_DEBUG
#define DEBUG(str) Serial.println(str)
#define DEBUG_ARGS(str,str1) Serial.println(str,str1)
#define DEBUG2(str) Serial.print(str)
#define DEBUG_WRITE(c) Serial.write(c)
#else
#define DEBUG(str)
#define DEBUG_ARGS(str,str1)
#define DEBUG2(str)
#define DEBUG_WRITE(c)
#endif
/* ------------------------------------------------------------------------- */
/* ------------------------------Configuration------------------------------ */
/* ------------------------------------------------------------------------- */
// Wifi Credentials
const char *ssid = "YourWifi"; // your network SSID (name)
const char *pass = "YourWifiPassword"; // your network password
// Interval of measuring and submitting values in seconds
const unsigned int postingInterval = 60e3;
// address of the server to send to
const char server[] PROGMEM = "ingress.opensensemap.org";
// senseBox ID
const char SENSEBOX_ID[] PROGMEM = "BOX ID";
// Number of sensors
// Change this number if you add or remove sensors
// do not forget to remove or add the sensors on opensensemap.org
static const uint8_t NUM_SENSORS = 2;
// Connected sensors
// Temperatur
#define HDC1080_CONNECTED
// rel. Luftfeuchte
#define HDC1080_CONNECTED
// Sensor SENSOR_IDs
// Temperatur
const char TEMPERSENSOR_ID[] PROGMEM = "SENSOR ID";
// rel. Luftfeuchte
const char RELLUFSENSOR_ID[] PROGMEM = "SENSOR ID";
WiFiSSLClient client;
OTA ota_module;
//Load sensors / instances
#ifdef HDC1080_CONNECTED
Adafruit_HDC1000 HDC = Adafruit_HDC1000();
#endif
#ifdef BMP280_CONNECTED
Adafruit_BMP280 BMP;
#endif
#ifdef TSL45315_CONNECTED
Makerblog_TSL45315 TSL = Makerblog_TSL45315(TSL45315_TIME_M4);
#endif
#ifdef VEML6070_CONNECTED
VEML6070 VEML;
#endif
#ifdef SMT50_CONNECTED
#define SOILTEMPPIN 0
#define SOILMOISPIN 1
#endif
#ifdef SOUNDLEVELMETER_CONNECTED
#define SOUNDMETERPIN 0
#endif
#ifdef BME680_CONNECTED
Adafruit_BME680 BME;
#endif
typedef struct measurement {
const char *sensorId;
float value;
} measurement;
measurement measurements[NUM_SENSORS];
uint8_t num_measurements = 0;
// buffer for sprintf
char buffer[750];
/* ------------------------------------------------------------------------- */
/* --------------------------End of Configuration--------------------------- */
/* ------------------------------------------------------------------------- */
bool validateFlashedApp() {
/**
* Test reset vector of application @APP_START_ADDRESS+4
* Sanity check on the Reset_Handler address.
* TODO FIXME: proper CRC / signature check?
*/
/* Load the Reset Handler address of the application */
uint32_t app_reset_ptr = *(uint32_t *)(APP_START_ADDRESS + 4);
return (app_reset_ptr >= APP_START_ADDRESS && app_reset_ptr <= FLASH_SIZE);
}
void jumpToApp() {
/* Load the Reset Handler address of the application */
uint32_t app_reset_ptr = *(uint32_t *)(APP_START_ADDRESS + 4);
LOG.print("app_reset_ptr: ");
LOG.println(String(app_reset_ptr, HEX));
LOG.print("stack pointer: ");
LOG.println(String(*(uint32_t *)APP_START_ADDRESS, HEX));
LOG.print("vector table address: ");
LOG.println(String(((uint32_t)APP_START_ADDRESS & SCB_VTOR_TBLOFF_Msk), HEX));
/* Rebase the Stack Pointer */
__set_MSP(*(uint32_t *)APP_START_ADDRESS);
/* Rebase the vector table base address */
SCB->VTOR = ((uint32_t)APP_START_ADDRESS & SCB_VTOR_TBLOFF_Msk);
/* Jump to application Reset Handler in the application */
asm("bx %0" ::"r"(app_reset_ptr));
}
void addMeasurement(const char *sensorId, float value) {
measurements[num_measurements].sensorId = sensorId;
measurements[num_measurements].value = value;
num_measurements++;
}
void writeMeasurementsToClient() {
// iterate throug the measurements array
for (uint8_t i = 0; i < num_measurements; i++) {
sprintf_P(buffer, PSTR("%s,%9.2f\n"), measurements[i].sensorId,
measurements[i].value);
// transmit buffer to client
client.print(buffer);
DEBUG2(buffer);
}
// reset num_measurements
num_measurements = 0;
}
void submitValues() {
if (WiFi.status() != WL_CONNECTED) {
WiFi.disconnect();
delay(1000); // wait 1s
WiFi.begin(ssid, pass);
delay(5000); // wait 5s
}
// close any connection before send a new request.
// This will free the socket on the WiFi shield
if (client.connected()) {
client.stop();
delay(1000);
}
bool connected = false;
char _server[strlen_P(server)];
strcpy_P(_server, server);
for (uint8_t timeout = 2; timeout != 0; timeout--) {
Serial.println(F("connecting..."));
connected = client.connect(_server, 443);
if (connected == true) {
DEBUG(F("Connection successful, transferring..."));
// construct the HTTP POST request:
sprintf_P(buffer,
PSTR("POST /boxes/%s/data HTTP/1.1\nHost: %s\nContent-Type: "
"text/csv\nConnection: close\nContent-Length: %i\n\n"),
SENSEBOX_ID, server, num_measurements * 35);
DEBUG(buffer);
// send the HTTP POST request:
client.print(buffer);
// send measurements
writeMeasurementsToClient();
// send empty line to end the request
client.println();
uint16_t timeout = 0;
// allow the response to be computed
while (timeout <= 5000) {
delay(10);
timeout = timeout + 10;
if (client.available()) {
break;
}
}
while (client.available()) {
char c = client.read();
DEBUG_WRITE(c);
// if the server's disconnected, stop the client:
if (!client.connected()) {
DEBUG();
DEBUG(F("disconnecting from server."));
client.stop();
break;
}
}
DEBUG(F("done!"));
// reset number of measurements
num_measurements = 0;
break;
}
delay(1000);
}
if (connected == false) {
// Reset durchführen
DEBUG(F("connection failed. Restarting System."));
delay(5000);
noInterrupts();
NVIC_SystemReset();
while (1)
;
}
}
void checkI2CSensors() {
byte error;
int nDevices = 0;
byte sensorAddr[] = {41, 56, 57, 64, 118};
DEBUG(F("\nScanning..."));
for (int i = 0; i < sizeof(sensorAddr); i++) {
Wire.beginTransmission(sensorAddr[i]);
error = Wire.endTransmission();
if (error == 0) {
nDevices++;
switch (sensorAddr[i])
{
case 0x29:
DEBUG(F("TSL45315 found."));
break;
case 0x38: // &0x39
DEBUG(F("VEML6070 found."));
break;
case 0x40:
DEBUG(F("HDC1080 found."));
break;
case 0x76:
#ifdef BMP280_CONNECTED
DEBUG("BMP280 found.");
#else
DEBUG("BME680 found.");
#endif
break;
}
}
else if (error == 4)
{
DEBUG2(F("Unknown error at address 0x"));
if (sensorAddr[i] < 16)
DEBUG2(F("0"));
DEBUG_ARGS(sensorAddr[i], HEX);
}
}
if (nDevices == 0) {
DEBUG(F("No I2C devices found.\nCheck cable connections and press Reset."));
while(true);
} else {
DEBUG2(nDevices);
DEBUG(F(" sensors found.\n"));
}
}
void setup() {
pinMode(0, INPUT_PULLUP); // switch button
// Initialize serial and wait for port to open:
#ifdef ENABLE_DEBUG
Serial.begin(9600);
while (!Serial)
#endif
if (digitalRead(0) == LOW) {
LOG.println("[OTA] switch pressed, entering OTA mode");
} else if (validateFlashedApp()) {
LOG.println("[OTA] jumping to application");
jumpToApp();
} else {
LOG.println("[OTA] no valid app installed, entering OTA mode");
}
DEBUG2(F("xbee1 spi enable..."));
senseBoxIO.SPIselectXB1(); // select XBEE1 spi
DEBUG(F("done"));
senseBoxIO.powerXB1(false);
delay(200);
DEBUG2(F("xbee1 power on..."));
senseBoxIO.powerXB1(true); // power ON XBEE1
DEBUG(F("done"));
senseBoxIO.powerI2C(false);
delay(200);
senseBoxIO.powerI2C(true);
// Check WiFi Bee status
if (WiFi.status() == WL_NO_SHIELD) {
DEBUG(F("WiFi shield not present"));
// don't continue:
while (true);
}
uint8_t status = WL_IDLE_STATUS;
// attempt to connect to Wifi network:
while (status != WL_CONNECTED) {
DEBUG2(F("Attempting to connect to SSID: "));
DEBUG(ssid);
// Connect to WPA/WPA2 network. Change this line if using open or WEP
// network
status = WiFi.begin(ssid, pass);
// wait 10 seconds for connection:
DEBUG2(F("Waiting 10 seconds for connection..."));
IPAddress ip = WiFi.localIP();
delay(10000);
DEBUG(F("done."));
DEBUG2(F("Your IP Adress is: "));
DEBUG(ip);
}
DEBUG(F("Setting up OTA functionalities"));
delay(400);
ota_module.begin(false);
#ifdef ENABLE_DEBUG
// init I2C/wire library
Wire.begin();
checkI2CSensors();
#endif
// Sensor initialization
DEBUG(F("Initializing sensors..."));
#ifdef HDC1080_CONNECTED
HDC.begin();
#endif
#ifdef BMP280_CONNECTED
BMP.begin(0x76);
#endif
#ifdef VEML6070_CONNECTED
VEML.begin();
delay(500);
#endif
#ifdef TSL45315_CONNECTED
TSL.begin();
#endif
#ifdef BME680_CONNECTED
BME.begin(0x76);
BME.setTemperatureOversampling(BME680_OS_8X);
BME.setHumidityOversampling(BME680_OS_2X);
BME.setPressureOversampling(BME680_OS_4X);
BME.setIIRFilterSize(BME680_FILTER_SIZE_3);
#endif
DEBUG(F("Initializing sensors done!"));
DEBUG(F("Starting loop in 3 seconds."));
delay(3000);
}
void loop() {
DEBUG(F("Starting new measurement..."));
// capture loop start timestamp
unsigned long start = millis();
//-----Temperature-----//
//-----Humidity-----//
#ifdef HDC1080_CONNECTED
addMeasurement(TEMPERSENSOR_ID, HDC.readTemperature());
delay(200);
addMeasurement(RELLUFSENSOR_ID, HDC.readHumidity());
#endif
//-----Pressure-----//
#ifdef BMP280_CONNECTED
float pressure;
pressure = BMP.readPressure()/100;
addMeasurement(LUFTDRSENSOR_ID, pressure);
#endif
//-----Lux-----//
#ifdef TSL45315_CONNECTED
addMeasurement(BELEUCSENSOR_ID, TSL.readLux());
#endif
//-----UV intensity-----//
#ifdef VEML6070_CONNECTED
addMeasurement(UVINTESENSOR_ID, VEML.getUV());
#endif
//-----Soil Temperature & Moisture-----//
#ifdef SMT50_CONNECTED
float voltage = analogRead(SOILTEMPPIN) * (3.3 / 1024.0);
float soilTemperature = (voltage - 0.5) * 100;
addMeasurement(BODENTSENSOR_ID, soilTemperature);
voltage = analogRead(SOILMOISPIN) * (3.3 / 1024.0);
float soilMoisture = (voltage * 50) / 3;
addMeasurement(BODENFSENSOR_ID, soilMoisture);
#endif
//-----dB(A) Sound Level-----//
#ifdef SOUNDLEVELMETER_CONNECTED
float v = analogRead(SOUNDMETERPIN) * (3.3 / 1024.0);
float decibel = v * 50;
addMeasurement(LAUTSTSENSOR_ID, decibel);
#endif
//-----BME680-----//
#ifdef BME680_CONNECTED
BME.setGasHeater(0, 0);
if( BME.performReading()) {
addMeasurement(LUFTTESENSOR_ID, BME.temperature-1);
addMeasurement(LUFTFESENSOR_ID, BME.humidity);
addMeasurement(ATMLUFSENSOR_ID, BME.pressure/100);
}
BME.setGasHeater(320, 150); // 320*C for 150 ms
if( BME.performReading()) {
addMeasurement(VOCSENSOR_ID, BME.gas_resistance / 1000.0);
}
#endif
DEBUG(F("Submit values"));
submitValues();
// schedule next round of measurements
for (;;) {
unsigned long now = millis();
unsigned long elapsed = now - start;
ota_module.update();
if (elapsed >= postingInterval)
return;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment