Demo of DHT11->mDot->TTN
Dependencies: DHT22 DS18B20_1wire SHTx TSL2561_I2C libmDot mbed-rtos mbed
Fork of mDot_TTN_DHT11 by
Diff: main.cpp
- Revision:
- 14:e4574212176a
- Parent:
- 13:761b9c929a3f
- Child:
- 15:c61c5f1533e8
diff -r 761b9c929a3f -r e4574212176a main.cpp --- 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;