Demo of DHT11->mDot->TTN

Dependencies:   DHT22 DS18B20_1wire SHTx TSL2561_I2C libmDot mbed-rtos mbed

Fork of mDot_TTN_DHT11 by Chris Merck

Revision:
14:e4574212176a
Parent:
13:761b9c929a3f
Child:
15:c61c5f1533e8
--- a/main.cpp	Thu May 19 15:18:05 2016 +0000
+++ b/main.cpp	Wed Aug 17 18:20:58 2016 +0000
@@ -1,6 +1,4 @@
-/** mDot_TTN_DS18B20 - Simple mDot temperature sensor using Dallas Semiconductors DS18B20 OneWire temperature sensor.
- * It used the MANUAL join mode with parameters for The Things Network.
- *
+/** mDot_TTN_DHT11 -- The Things Network Temperature & Humidity Sensor
  *
  * Uses MultiTech mDot developer board http://www.multitech.com/models/94558010LF
  * Requires a MultiTech MultiConnect Conduit http://www.multitech.com/models/94557203LF
@@ -10,7 +8,7 @@
  */
 
 #include "mbed.h"
-#include "DS1820.h"
+#include "DHT11.h"
 #include "mDot.h"
 #include "MTSLog.h"
 #include "MTSText.h"
@@ -22,57 +20,82 @@
 #define MIN(a,b) (((a)<(b))?(a):(b))
 #define MAX(a,b) (((a)>(b))?(a):(b))
 
-// Values as used by The Things Network
-//const uint8_t AppKey[16]={0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C};
-// Application session key
-uint8_t AppSKey[16]= {0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C};
-// Network session key
-uint8_t NwkSKey[16]= {0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C};
 
-// Network Address - Get your own address range at http://thethingsnetwork.org/wiki/AddressSpace
-uint8_t NetworkAddr[4]= {0x02,0x01,0x00,0x00};      // Our Network address or Node ID
+/** ABP
+ * Register your device and update these values:
+ * https://account.thethingsnetwork.org/
+ */
+uint8_t AppSKey[16]= { 0x50, 0x41, 0xE5, 0x57, 0xB6, 0x24, 0x7D, 0x4E, 0x6F, 0xF9, 0x9D, 0x0E, 0xDE, 0x13, 0xD6, 0xA2, };
+uint8_t NwkSKey[16]= { 0x3E, 0x1C, 0xA9, 0x8A, 0x4C, 0x0A, 0xA9, 0x91, 0x3A, 0xFD, 0xAE, 0x70, 0x66, 0x37, 0x51, 0x9D, };
+uint8_t NetworkAddr[4]= {0x26,0xFC,0x2A,0x9B};
 
 
 // Some defines for the LoRa configuration
-#define LORA_SF mDot::SF_12
+#define LORA_SF mDot::SF_7
 #define LORA_ACK 0
-#define LORA_TXPOWER 14
+#define LORA_TXPOWER 20
+static uint8_t config_frequency_sub_band = 2;
 
-// Ignoring sub band for EU modules.
-static uint8_t config_frequency_sub_band = 7;
+// functions for ensuring network endianness (little-endian)
+uint16_t hton16(const uint16_t x)
+{
+  uint16_t t = x;
+  uint8_t * a = (uint8_t*)&t;
+  a[0] = x>>(8*1);
+  a[1] = x>>(8*0);
+  return t;
+}
+void hton16(uint16_t * x)
+{
+  *x = hton16(*x);
+}
+
 
-// DS18B20 OneWire pin
-// D13 on Dev Board, pin 18 on mDot, Compatible with Oxford Flood Network PCB temperature sensor.
-#define DATA_PIN     PA_5
-// A0 on Dev Board, pin 20 on mDot
-//#define DATA_PIN     PB_1
+// packet payload format
+#pragma pack(push, 1) // exact fit - no padding
+struct sigmap_packet_t {
+  uint16_t seq;
+  uint8_t pwr;    /* tx power in dbm, +128 offset */
+  uint16_t temp;  /* temperature, in hundreths of a degree C, +32768 offset  */
+  uint16_t humid; /* relative humidity, in hundreths of a percent, +32768 offset */
+  void hton() {
+    hton16(&seq);
+    hton16(&temp);
+    hton16(&humid);
+  }
+};
+#pragma pack(pop) // back to whatever the previous packing mode was 
 
 // Temperature sensor object
-DS1820 probe(DATA_PIN);
+#define DHT_PIN PB_1
+DHT11 dht(DHT_PIN);
 
 // Serial via USB for debugging only
 Serial pc(USBTX,USBRX);
 
 int main()
 {
+    sigmap_packet_t pkt;
+    
     int32_t ret;
     mDot* dot;
     std::vector<uint8_t> send_data;
     std::vector<uint8_t> recv_data;
     std::vector<uint8_t> nwkSKey;
+    std::vector<uint8_t> appSKey;
     std::vector<uint8_t> nodeAddr;
     std::vector<uint8_t> networkAddr;
 
     float temperature = 0.0;
 
     pc.baud(115200);
-    pc.printf("TTN mDot LoRa Temperature sensor\n\r");
+    pc.printf("TTN mDot LoRa Temperature  & Humidity Sensor\n\r");
 
     // get a mDot handle
     dot = mDot::getInstance();
 
-    dot->setLogLevel(MTSLog::WARNING_LEVEL);
-//    dot->setLogLevel(MTSLog::TRACE_LEVEL);
+//  dot->setLogLevel(MTSLog::WARNING_LEVEL);
+    dot->setLogLevel(MTSLog::TRACE_LEVEL);
 
     logInfo("Checking Config");
 
@@ -82,6 +105,10 @@
     uint8_t *it = NwkSKey;
     for (uint8_t i = 0; i<16; i++)
         nwkSKey.push_back((uint8_t) *it++);
+        
+    it = AppSKey;
+    for (uint8_t i = 0; i<16; i++)
+        appSKey.push_back((uint8_t) *it++);
 
     it = NetworkAddr;
     for (uint8_t i = 0; i<4; i++)
@@ -95,12 +122,7 @@
 //    dot->setJoinByteOrder(mDot::LSB);
     dot->setJoinByteOrder(mDot::MSB);       // This is default for > 1.0.30 Conduit
 
-    // Set Spreading Factor, higher is lower data rate, smaller packets but longer range
-    // Lower is higher data rate, larger packets and shorter range.
-    logInfo("Set SF");
-    if((ret = dot->setTxDataRate( LORA_SF )) != mDot::MDOT_OK) {
-        logError("Failed to set SF %d:%s", ret, mDot::getReturnCodeString(ret).c_str());
-    }
+
 
     logInfo("Set TxPower");
     if((ret = dot->setTxPower( LORA_TXPOWER )) != mDot::MDOT_OK) {
@@ -134,7 +156,7 @@
     }
 
     logInfo("Set Data Session Key");
-    if ((ret = dot->setDataSessionKey(nwkSKey)) != mDot::MDOT_OK) {
+    if ((ret = dot->setDataSessionKey(appSKey)) != mDot::MDOT_OK) {
         logError("Failed to set Data Session Key %d:%s", ret, mDot::getReturnCodeString(ret).c_str());
     }
 
@@ -199,33 +221,84 @@
 
     logInfo("Joined Network");
 
-    // Set the Temperature sesnor resolution, 9 bits is enough and makes it faster to provide a reading.
-    probe.setResolution(9);
-
     char dataBuf[50];
+    uint16_t seq = 0;
+    char * sf_str;
     while( 1 ) {
-        //Start temperature conversion, wait until ready
-        probe.convertTemperature(true, DS1820::all_devices);
-        // Output data as JSON e.g. {"t":21.3}
-        temperature = probe.temperature();
-        sprintf(dataBuf, "{\"t\":%3.1f}", temperature );
-        send_data.clear();
-        // probably not the most efficent way to do this
-        for( int i=0; i< strlen(dataBuf); i++ )
-            send_data.push_back( dataBuf[i] );
+        
+        /* cycle through spreading factors */
+        uint8_t sf;
+        switch (seq % 4) {
+            case 0:
+                sf = mDot::SF_7;
+                sf_str = "SF7";
+                break;
+            case 1:
+                sf = mDot::SF_8;
+                sf_str = "SF8";
+                break;
+            case 2:
+                sf = mDot::SF_9;
+                sf_str = "SF9";
+                break;
+            case 3:
+                sf = mDot::SF_10;
+                sf_str = "SF10";
+                break;
+        }        
+        // Set Spreading Factor, higher is lower data rate, smaller packets but longer range
+        // Lower is higher data rate, larger packets and shorter range.
+        logInfo("Set SF: %s",sf_str);
+        if((ret = dot->setTxDataRate( sf )) != mDot::MDOT_OK) {
+            logError("Failed to set SF %d:%s", ret, mDot::getReturnCodeString(ret).c_str());
+        }
+        
+        /* set default data values */
+        int temp = 0;
+        int humid = -1;
+        
+        /* read from sensor */
+        int r = dht.readData();
+        switch (r) {
+            case DHT11::OK:
+            {
+                temp = dht.readTemperature();
+                humid = dht.readHumidity();
+                pc.printf("[DHT] T %d degC   H %d %%\r\n",temp,humid);
+                break;
+            }
+            default:
+            {
+                pc.printf("[DHT] ERROR %d\r\n",r);
+                break;
+            }
+        };
+        
+        /* build packet */
+        pkt.seq = seq;
+        pkt.pwr = LORA_TXPOWER + 128;
+        pkt.temp = temp*100 + 32768;
+        pkt.humid = humid*100 + 32768;
+        
+        /* load vector */
+        pkt.hton();        
+        send_data.clear();        
+        for( int i=0; i< sizeof(pkt); i++ )
+            send_data.push_back( ((uint8_t*)&pkt)[i] );
 
+        /* send packet */
         if ((ret = dot->send(send_data)) != mDot::MDOT_OK) {
             logError("failed to send: [%d][%s]", ret, mDot::getReturnCodeString(ret).c_str());
         } else {
             logInfo("send data: %s", Text::bin2hexString(send_data).c_str());
         }
 
-        // Should  sleep here and wakeup after a set 10 minute interval.
-        uint32_t sleep_time = MAX((dot->getNextTxMs() / 1000), 600);
+        /* sleep */
+        uint32_t sleep_time = MAX((dot->getNextTxMs() / 1000), 10 /* use 6000 for 10min */);
         logInfo("going to sleep for %d seconds", sleep_time);
-
-        // go to sleep and wake up automatically sleep_time seconds later
-        dot->sleep(sleep_time, mDot::RTC_ALARM);
+        wait_ms(10*1000);
+        
+        seq++;
     }
 
     return 0;