A simple LoRaWAN temperature sensor based on Multitech mDot module.

Dependencies:   DS1820 libmDot mbed-rtos mbed

Committer:
SomeRandomBloke
Date:
Tue Mar 01 23:15:43 2016 +0000
Revision:
7:62174a8286a2
Parent:
6:9b53147a345f
update

Who changed what in which revision?

UserRevisionLine numberNew contents of line
SomeRandomBloke 2:9db840d12557 1 /** mDot_DS18B20 - Simple mDot temperature sensor using Dallas Semiconductors DS18B20 OneWire temperature sensor.
SomeRandomBloke 4:f649ab1b61d1 2 * It used the OTA_AUTO join mode using saved parameters. If the config is to be reset then pin A2 on the
SomeRandomBloke 3:367aa95f9771 3 * dev board must be held low during a reset or power up.
SomeRandomBloke 2:9db840d12557 4 *
SomeRandomBloke 0:5a0b43f3b143 5 * Uses MultiTech mDot developer board http://www.multitech.com/models/94558010LF
SomeRandomBloke 0:5a0b43f3b143 6 * Requires a MultiTech MultiConnect Conduit http://www.multitech.com/models/94557203LF
SomeRandomBloke 0:5a0b43f3b143 7 *
SomeRandomBloke 0:5a0b43f3b143 8 * Example JSON received on Conduit:
SomeRandomBloke 0:5a0b43f3b143 9 { "chan": 5, "codr": "4/5", "datr": "SF9BW125", "freq": "869.5",
SomeRandomBloke 0:5a0b43f3b143 10 "lsnr": "8.8", "modu": "LORA", "rfch": 1, "rssi": -41, "seqn": 13,
SomeRandomBloke 0:5a0b43f3b143 11 "size": 12, "timestamp": "2015-07-22T21:19:11Z", "tmst": 517590990,
SomeRandomBloke 2:9db840d12557 12 "payload": "{\"tmp\":21.3}", "eui": "00:80:00:00:00:00:9a:63", "_msg
SomeRandomBloke 0:5a0b43f3b143 13 id": "73bcd8dd.8c4328" }
SomeRandomBloke 0:5a0b43f3b143 14 *
SomeRandomBloke 0:5a0b43f3b143 15 */
SomeRandomBloke 0:5a0b43f3b143 16
SomeRandomBloke 0:5a0b43f3b143 17 #include "mbed.h"
SomeRandomBloke 0:5a0b43f3b143 18 #include "DS1820.h"
SomeRandomBloke 0:5a0b43f3b143 19 #include "mDot.h"
SomeRandomBloke 0:5a0b43f3b143 20 #include "MTSLog.h"
SomeRandomBloke 0:5a0b43f3b143 21 #include "MTSText.h"
SomeRandomBloke 0:5a0b43f3b143 22 #include <string>
SomeRandomBloke 0:5a0b43f3b143 23 #include <vector>
SomeRandomBloke 0:5a0b43f3b143 24
SomeRandomBloke 0:5a0b43f3b143 25 using namespace mts;
SomeRandomBloke 0:5a0b43f3b143 26
SomeRandomBloke 4:f649ab1b61d1 27 #define MIN(a,b) (((a)<(b))?(a):(b))
SomeRandomBloke 4:f649ab1b61d1 28 #define MAX(a,b) (((a)>(b))?(a):(b))
SomeRandomBloke 4:f649ab1b61d1 29
SomeRandomBloke 0:5a0b43f3b143 30 // these options must match the settings on your Conduit in
SomeRandomBloke 0:5a0b43f3b143 31 // /var/config/lora/lora-network-server.conf
SomeRandomBloke 7:62174a8286a2 32 static std::string config_network_name = "xxx";
SomeRandomBloke 7:62174a8286a2 33 static std::string config_network_pass = "xxx";
SomeRandomBloke 5:dd77f0401170 34
SomeRandomBloke 3:367aa95f9771 35 // Ignoring sub band for EU modules.
SomeRandomBloke 1:45cec6aea002 36 //static uint8_t config_frequency_sub_band = 1;
SomeRandomBloke 0:5a0b43f3b143 37
SomeRandomBloke 0:5a0b43f3b143 38 // mDot/dev board activity LED
SomeRandomBloke 1:45cec6aea002 39 //#define ACTIVITY_LED PA_0
SomeRandomBloke 2:9db840d12557 40
SomeRandomBloke 2:9db840d12557 41 // DS18B20 OneWire pin
SomeRandomBloke 3:367aa95f9771 42 // D13 on Dev Board, pin 18 on mDot
SomeRandomBloke 1:45cec6aea002 43 #define DATA_PIN PA_5
SomeRandomBloke 3:367aa95f9771 44 // A0 on Dev Board, pin 20 on mDot
SomeRandomBloke 1:45cec6aea002 45 //#define DATA_PIN PB_1
SomeRandomBloke 0:5a0b43f3b143 46
SomeRandomBloke 3:367aa95f9771 47 // A2 - input to reset LoRaWAN config. Pin 15 om mDot.
SomeRandomBloke 3:367aa95f9771 48 #define CONFIG_RESET PC_1
SomeRandomBloke 3:367aa95f9771 49
SomeRandomBloke 3:367aa95f9771 50 // Config Reset intput
SomeRandomBloke 3:367aa95f9771 51 DigitalIn configReset(CONFIG_RESET);
SomeRandomBloke 3:367aa95f9771 52
SomeRandomBloke 3:367aa95f9771 53 // Temperature sensor object
SomeRandomBloke 0:5a0b43f3b143 54 DS1820 probe(DATA_PIN);
SomeRandomBloke 0:5a0b43f3b143 55
SomeRandomBloke 3:367aa95f9771 56 // Serial via USB for debugging only
SomeRandomBloke 0:5a0b43f3b143 57 Serial pc(USBTX,USBRX);
SomeRandomBloke 0:5a0b43f3b143 58
SomeRandomBloke 0:5a0b43f3b143 59
SomeRandomBloke 0:5a0b43f3b143 60 int main()
SomeRandomBloke 0:5a0b43f3b143 61 {
SomeRandomBloke 0:5a0b43f3b143 62 int32_t ret;
SomeRandomBloke 0:5a0b43f3b143 63 mDot* dot;
SomeRandomBloke 0:5a0b43f3b143 64 std::vector<uint8_t> send_data;
SomeRandomBloke 0:5a0b43f3b143 65 std::vector<uint8_t> recv_data;
SomeRandomBloke 0:5a0b43f3b143 66
SomeRandomBloke 0:5a0b43f3b143 67 float temperature = 0.0;
SomeRandomBloke 1:45cec6aea002 68
SomeRandomBloke 3:367aa95f9771 69 // Enable internal pullup on input pin
SomeRandomBloke 3:367aa95f9771 70 configReset.mode(PullUp);
SomeRandomBloke 3:367aa95f9771 71
SomeRandomBloke 0:5a0b43f3b143 72 pc.baud(115200);
SomeRandomBloke 5:dd77f0401170 73 pc.printf("Private LoRaWAN Temperature sensor\n\r");
SomeRandomBloke 6:9b53147a345f 74 pc.printf("Test\n\r");
SomeRandomBloke 1:45cec6aea002 75
SomeRandomBloke 0:5a0b43f3b143 76 // get a mDot handle
SomeRandomBloke 0:5a0b43f3b143 77 dot = mDot::getInstance();
SomeRandomBloke 0:5a0b43f3b143 78
SomeRandomBloke 4:f649ab1b61d1 79 // dot->setLogLevel(MTSLog::WARNING_LEVEL);
SomeRandomBloke 4:f649ab1b61d1 80 dot->setLogLevel(MTSLog::TRACE_LEVEL);
SomeRandomBloke 0:5a0b43f3b143 81
SomeRandomBloke 1:45cec6aea002 82 logInfo("Checking Config");
SomeRandomBloke 1:45cec6aea002 83
SomeRandomBloke 1:45cec6aea002 84 // Test if we've already saved the config
SomeRandomBloke 1:45cec6aea002 85 std::string configNetworkName = dot->getNetworkName();
SomeRandomBloke 5:dd77f0401170 86
SomeRandomBloke 5:dd77f0401170 87 pc.printf("Name: %s\r\n",config_network_name.c_str());
SomeRandomBloke 1:45cec6aea002 88
SomeRandomBloke 3:367aa95f9771 89 // Reset config if network name is different or pin is low then reset config.
SomeRandomBloke 3:367aa95f9771 90 if( config_network_name.compare(configNetworkName) != 0 || !configReset ) {
SomeRandomBloke 1:45cec6aea002 91 // Not saved config, reset
SomeRandomBloke 1:45cec6aea002 92 logInfo("Setting Config");
SomeRandomBloke 0:5a0b43f3b143 93
SomeRandomBloke 1:45cec6aea002 94 // reset to default config so we know what state we're in
SomeRandomBloke 1:45cec6aea002 95 dot->resetConfig();
SomeRandomBloke 1:45cec6aea002 96
SomeRandomBloke 5:dd77f0401170 97 // Set byte order - AEP less than 1.0.30 needs LSB
SomeRandomBloke 5:dd77f0401170 98 // dot->setJoinByteOrder(mDot::LSB);
SomeRandomBloke 6:9b53147a345f 99 // dot->setJoinByteOrder(mDot::MSB); // This is default for > 1.0.30 Conduit
SomeRandomBloke 0:5a0b43f3b143 100
SomeRandomBloke 5:dd77f0401170 101 dot->setPublicNetwork(true);
SomeRandomBloke 1:45cec6aea002 102 logInfo("setting Join mode");
SomeRandomBloke 1:45cec6aea002 103 if ((ret = dot->setJoinMode(mDot::AUTO_OTA)) != mDot::MDOT_OK) {
SomeRandomBloke 1:45cec6aea002 104 logError("failed to set Join Mode %d:%s", ret, mDot::getReturnCodeString(ret).c_str());
SomeRandomBloke 1:45cec6aea002 105 }
SomeRandomBloke 1:45cec6aea002 106
SomeRandomBloke 1:45cec6aea002 107 // If on developer board then you can enable activity LED
SomeRandomBloke 1:45cec6aea002 108 // Currently no spare pins that LEDs are connected too.
SomeRandomBloke 0:5a0b43f3b143 109 // dot->setActivityLedPin( ACTIVITY_LED );
SomeRandomBloke 0:5a0b43f3b143 110 // dot->setActivityLedEnable(false);
SomeRandomBloke 0:5a0b43f3b143 111
SomeRandomBloke 2:9db840d12557 112 // Have a decent nubmer of retries in connecting to LoRaWAN
SomeRandomBloke 2:9db840d12557 113 dot->setJoinRetries( 3 );
SomeRandomBloke 2:9db840d12557 114
SomeRandomBloke 2:9db840d12557 115 // Set Spreading Factor, higher is lower data rate, smaller packets but longer range
SomeRandomBloke 2:9db840d12557 116 // Lower is higher data rate, larger packets and shorter range.
SomeRandomBloke 2:9db840d12557 117 // dot->setTxDataRate( mDot::SF_9 );
SomeRandomBloke 3:367aa95f9771 118 dot->setTxDataRate( mDot::SF_12 );
SomeRandomBloke 1:45cec6aea002 119 dot->setTxPower( 14 );
SomeRandomBloke 1:45cec6aea002 120 dot->setAck( 0 ); // 1 retries on Ack, 0 to disable
SomeRandomBloke 3:367aa95f9771 121
SomeRandomBloke 1:45cec6aea002 122 // Not applicable for 868MHz in EU
SomeRandomBloke 1:45cec6aea002 123 // if ((ret = dot->setFrequencySubBand(config_frequency_sub_band)) != mDot::MDOT_OK) {
SomeRandomBloke 1:45cec6aea002 124 // initStatus = false;
SomeRandomBloke 0:5a0b43f3b143 125 // logError(dot, "failed to set frequency sub band", ret);
SomeRandomBloke 1:45cec6aea002 126 // }
SomeRandomBloke 1:45cec6aea002 127
SomeRandomBloke 1:45cec6aea002 128 if ((ret = dot->setNetworkName(config_network_name)) != mDot::MDOT_OK) {
SomeRandomBloke 1:45cec6aea002 129 logError("failed to set network name %d:%s", ret, mDot::getReturnCodeString(ret).c_str());
SomeRandomBloke 1:45cec6aea002 130 }
SomeRandomBloke 0:5a0b43f3b143 131
SomeRandomBloke 1:45cec6aea002 132 if ((ret = dot->setNetworkPassphrase(config_network_pass)) != mDot::MDOT_OK) {
SomeRandomBloke 1:45cec6aea002 133 logError("failed to set network password %d:%s", ret, mDot::getReturnCodeString(ret).c_str());
SomeRandomBloke 1:45cec6aea002 134 }
SomeRandomBloke 1:45cec6aea002 135
SomeRandomBloke 1:45cec6aea002 136 logInfo("Saving Config");
SomeRandomBloke 1:45cec6aea002 137
SomeRandomBloke 1:45cec6aea002 138 // Save config
SomeRandomBloke 1:45cec6aea002 139 if (! dot->saveConfig()) {
SomeRandomBloke 1:45cec6aea002 140 logError("failed to save configuration");
SomeRandomBloke 1:45cec6aea002 141 }
SomeRandomBloke 1:45cec6aea002 142 } else {
SomeRandomBloke 1:45cec6aea002 143 logInfo("Using existing Config");
SomeRandomBloke 0:5a0b43f3b143 144 }
SomeRandomBloke 5:dd77f0401170 145
SomeRandomBloke 4:f649ab1b61d1 146 logInfo("Joining Network");
SomeRandomBloke 4:f649ab1b61d1 147
SomeRandomBloke 0:5a0b43f3b143 148 while ((ret = dot->joinNetwork()) != mDot::MDOT_OK) {
SomeRandomBloke 0:5a0b43f3b143 149 logError("failed to join network [%d][%s]", ret, mDot::getReturnCodeString(ret).c_str());
SomeRandomBloke 0:5a0b43f3b143 150 wait_ms(dot->getNextTxMs() + 1);
SomeRandomBloke 0:5a0b43f3b143 151 }
SomeRandomBloke 1:45cec6aea002 152
SomeRandomBloke 4:f649ab1b61d1 153 logInfo("Joined Network");
SomeRandomBloke 4:f649ab1b61d1 154
SomeRandomBloke 0:5a0b43f3b143 155 probe.setResolution(9);
SomeRandomBloke 0:5a0b43f3b143 156
SomeRandomBloke 0:5a0b43f3b143 157 char dataBuf[50];
SomeRandomBloke 0:5a0b43f3b143 158 while( 1 ) {
SomeRandomBloke 0:5a0b43f3b143 159 // This takes upto 750mS, way too long. Change to 9 bit resolution if not already used.
SomeRandomBloke 1:45cec6aea002 160
SomeRandomBloke 0:5a0b43f3b143 161 probe.convertTemperature(true, DS1820::all_devices); //Start temperature conversion, wait until ready
SomeRandomBloke 0:5a0b43f3b143 162 // printf("It is %3.1fC\r\n", probe.temperature());
SomeRandomBloke 3:367aa95f9771 163 // Output data as JSON e.g. {"tmp":21.3}
SomeRandomBloke 0:5a0b43f3b143 164 temperature = probe.temperature();
SomeRandomBloke 1:45cec6aea002 165 sprintf(dataBuf, "{\"tmp\":%3.1f}", temperature );
SomeRandomBloke 0:5a0b43f3b143 166 send_data.clear();
SomeRandomBloke 0:5a0b43f3b143 167 // probably not the most efficent way to do this
SomeRandomBloke 0:5a0b43f3b143 168 for( int i=0; i< strlen(dataBuf); i++ )
SomeRandomBloke 0:5a0b43f3b143 169 send_data.push_back( dataBuf[i] );
SomeRandomBloke 0:5a0b43f3b143 170
SomeRandomBloke 0:5a0b43f3b143 171 if ((ret = dot->send(send_data)) != mDot::MDOT_OK) {
SomeRandomBloke 0:5a0b43f3b143 172 logError("failed to send: [%d][%s]", ret, mDot::getReturnCodeString(ret).c_str());
SomeRandomBloke 0:5a0b43f3b143 173 } else {
SomeRandomBloke 0:5a0b43f3b143 174 logInfo("send data: %s", Text::bin2hexString(send_data).c_str());
SomeRandomBloke 0:5a0b43f3b143 175 }
SomeRandomBloke 0:5a0b43f3b143 176
SomeRandomBloke 1:45cec6aea002 177 // Should sleep here and wakeup after a set interval.
SomeRandomBloke 4:f649ab1b61d1 178 uint32_t sleep_time = MAX((dot->getNextTxMs() / 1000), 60);
SomeRandomBloke 2:9db840d12557 179 logInfo("going to sleep for %d seconds", sleep_time);
SomeRandomBloke 0:5a0b43f3b143 180
SomeRandomBloke 1:45cec6aea002 181 // go to sleep and wake up automatically sleep_time seconds later
SomeRandomBloke 2:9db840d12557 182 dot->sleep(sleep_time, mDot::RTC_ALARM);
SomeRandomBloke 2:9db840d12557 183
SomeRandomBloke 5:dd77f0401170 184 // wait_ms(sleep_time * 1000);
SomeRandomBloke 0:5a0b43f3b143 185 }
SomeRandomBloke 2:9db840d12557 186
SomeRandomBloke 0:5a0b43f3b143 187 return 0;
SomeRandomBloke 0:5a0b43f3b143 188 }