diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..01c7981 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.vscode +TTN-configuration.h \ No newline at end of file diff --git a/BME680-TTN.ino b/BME680-TTN.ino index f7d92de..28768ac 100644 --- a/BME680-TTN.ino +++ b/BME680-TTN.ino @@ -4,7 +4,6 @@ #define USE_DISPLAY #ifdef USE_DISPLAY - #include #ifdef U8X8_HAVE_HW_SPI #include @@ -14,14 +13,19 @@ #endif #include -#define LED_PIN 18 +#define LED_PIN 23 #define LED_COUNT 8 Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800); -//U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0, /* clock=*/ 15, /* data=*/ 4, /* reset=*/ 16); U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0, /* clock=*/ 15, /* data=*/ 4, /* reset=*/ 16); #endif +#include +SimpleLMIC ttn; +int TTNDebugLoopInterval = 1000; +uint32_t TTNDebugLoopMillis = millis() - TTNDebugLoopInterval; +int TTNSendLoopInterval = 10000; +uint32_t TTNSendLoopMillis = millis() - TTNSendLoopInterval; int DisplayUpdateLoopInterval = 1000; uint32_t DisplayUpdateLoopMillis = millis() - DisplayUpdateLoopInterval; @@ -72,11 +76,17 @@ void setup(void) strip.begin(); strip.show(); strip.setBrightness(50); + + ttn.begin(); + ttn.setSubBand(2); + ttn.onMessage(message); + ttn.join(devEui, appEui, appKey); } // Function that is looped forever void loop(void) { + ttn.loop(); unsigned long time_trigger = millis(); if (iaqSensor.run()) { // If new data is available output = String(time_trigger); @@ -99,6 +109,18 @@ void loop(void) updateDisplay(); #endif updateNeoPixel(); + + if (!ttn.isBusy() && ttn.isLink() && millis() - TTNSendLoopMillis > TTNSendLoopInterval) + { + TTNSendLoopMillis = millis(); + Serial.println("Not Busy!"); + Serial.println(iaqSensor.co2Equivalent); + Serial.println(sizeof(iaqSensor.co2Equivalent)); + uint8_t buffer[sizeof(iaqSensor.co2Equivalent)]; + ::memcpy(buffer, &iaqSensor.co2Equivalent, sizeof(iaqSensor.co2Equivalent)); + ttn.write(buffer, sizeof(buffer)); + ttn.send(); + } } // Helper function definitions @@ -168,6 +190,12 @@ void updateDisplay() { sprintf(displayText, "%20s", co2String); u8g2.drawStr(0,40,displayText); + sprintf(displayText, "ttn.isBusy(): %d", ttn.isBusy()); + u8g2.drawStr(0,50,displayText); + + sprintf(displayText, "ttn.isLink(): %d", ttn.isLink()); + u8g2.drawStr(0,60,displayText); + u8g2.sendBuffer(); } } @@ -192,4 +220,22 @@ void updateNeoPixel(){ strip.show(); } } -} \ No newline at end of file +} + +void printTTNDebug() { + Serial.print("ttn.isBusy(): "); + Serial.print(ttn.isBusy()); + Serial.print(" ttn.isLink(): "); + Serial.print(ttn.isLink()); + + Serial.println(); +} + +void message(uint8_t *payload, size_t size, uint8_t port) +{ + Serial.println("Received " + String(size) + " bytes on port " + String(port)); + switch (port) { + case 1: + break; + } +} diff --git a/TTN-configuration.template.h b/TTN-configuration.template.h new file mode 100644 index 0000000..f1a79d7 --- /dev/null +++ b/TTN-configuration.template.h @@ -0,0 +1,31 @@ +const char *devEui = ""; +const char *appEui = ""; +const char *appKey = ""; + +//config for Arduino Due, GPS connected to Serial2... Don't ask... +const lmic_pinmap lmic_pins = { + .nss = 10, + .rxtx = LMIC_UNUSED_PIN, + .rst = LMIC_UNUSED_PIN, + .dio = {2, 3, LMIC_UNUSED_PIN}, +}; +#define GPSSerial Serial2 + +//Config for TTGO T-Beam T22 v1.1 +const lmic_pinmap lmic_pins = { + .nss = 18, + .rxtx = LMIC_UNUSED_PIN, + .rst = 23, + .dio = {26, 33, 32}, +}; +#define GPSSerial Serial1 +//#define GPS_RX_PIN 34 +//#define GPS_TX_PIN 12 + +//Heltec Lora 32 v2 +const lmic_pinmap lmic_pins = { + .nss = 18, + .rxtx = LMIC_UNUSED_PIN, + .rst = 14, + .dio = {26, 34, 35}, +}; \ No newline at end of file diff --git a/decoder.js b/decoder.js new file mode 100644 index 0000000..ac3cf4b --- /dev/null +++ b/decoder.js @@ -0,0 +1,44 @@ +function decodeFloat32(bytes) { + var sign = (bytes & 0x80000000) ? -1 : 1; + var exponent = ((bytes >> 23) & 0xFF) - 127; + var significand = (bytes & ~(-1 << 23)); + + if (exponent == 128) + return sign * ((significand) ? Number.NaN : Number.POSITIVE_INFINITY); + + if (exponent == -127) { + if (significand == 0) return sign * 0.0; + exponent = -126; + significand /= (1 << 22); + } else significand = (significand | (1 << 23)) / (1 << 23); + + return sign * significand * Math.pow(2, exponent); +} + +function decodeInt16(bytes) { + if ((bytes & 1 << 15) > 0) { // value is negative (16bit 2's complement) + bytes = ((~bytes) & 0xffff) + 1; // invert 16bits & add 1 => now positive value + bytes = bytes * -1; + } + return bytes; +} + +function int16_LE(bytes, idx) { + bytes = bytes.slice(idx || 0); + return bytes[0] << 0 | bytes[1] << 8; +} + +function int32_LE(bytes, idx) { + bytes = bytes.slice(idx || 0); + return bytes[0] << 0 | bytes[1] << 8 | bytes[2] << 16 | bytes[3] << 24; +} + +function Decoder(bytes, port) { + // Decode an uplink message from a buffer + // (array) of bytes to an object of fields. + var decoded = { + co2: decodeFloat32(int32_LE(bytes, 0)), + }; + + return decoded; +} \ No newline at end of file