Brendan Kelly
/
mDot_soil_moisture_ABPA
Analogue soil moisture reader - simple
main.cpp@1:15442a59c47f, 2017-11-01 (annotated)
- Committer:
- kellybs1
- Date:
- Wed Nov 01 03:51:21 2017 +0000
- Revision:
- 1:15442a59c47f
- Parent:
- 0:3d2e0dbfbc41
- Child:
- 2:d8858f9fc425
working version
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
kellybs1 | 0:3d2e0dbfbc41 | 1 | /* |
kellybs1 | 0:3d2e0dbfbc41 | 2 | This program: |
kellybs1 | 0:3d2e0dbfbc41 | 3 | - connects to a LoRaWAN by ABP/MANUAL |
kellybs1 | 0:3d2e0dbfbc41 | 4 | - reads moisture from an analogue SparkFun SEN-13322 moisture sensor |
kellybs1 | 0:3d2e0dbfbc41 | 5 | - sends the recorded data onto the LoRaWAN |
kellybs1 | 0:3d2e0dbfbc41 | 6 | - sets the mDot to sleep |
kellybs1 | 0:3d2e0dbfbc41 | 7 | - repeats these operations in a loop |
kellybs1 | 0:3d2e0dbfbc41 | 8 | */ |
kellybs1 | 0:3d2e0dbfbc41 | 9 | |
kellybs1 | 0:3d2e0dbfbc41 | 10 | #include "mbed.h" |
kellybs1 | 0:3d2e0dbfbc41 | 11 | #include "mDot.h" |
kellybs1 | 0:3d2e0dbfbc41 | 12 | #include "ChannelPlans.h" |
kellybs1 | 0:3d2e0dbfbc41 | 13 | #include "MTSLog.h" |
kellybs1 | 0:3d2e0dbfbc41 | 14 | #include "dot_util.h" |
kellybs1 | 0:3d2e0dbfbc41 | 15 | #include "mbed.h" |
kellybs1 | 0:3d2e0dbfbc41 | 16 | #include <string> |
kellybs1 | 0:3d2e0dbfbc41 | 17 | #include <vector> |
kellybs1 | 0:3d2e0dbfbc41 | 18 | #include <algorithm> |
kellybs1 | 0:3d2e0dbfbc41 | 19 | #include <sstream> |
kellybs1 | 0:3d2e0dbfbc41 | 20 | |
kellybs1 | 0:3d2e0dbfbc41 | 21 | //Sensor pin on soil moisture sensor (A0 on Multitech UDK 2) |
kellybs1 | 0:3d2e0dbfbc41 | 22 | AnalogIn a0(PB_1); |
kellybs1 | 0:3d2e0dbfbc41 | 23 | |
kellybs1 | 0:3d2e0dbfbc41 | 24 | // these options must match the settings on your gateway/server |
kellybs1 | 0:3d2e0dbfbc41 | 25 | /* |
kellybs1 | 0:3d2e0dbfbc41 | 26 | */ |
kellybs1 | 0:3d2e0dbfbc41 | 27 | //device address |
kellybs1 | 1:15442a59c47f | 28 | static uint8_t network_address[] = { 0x07, 0x47, 0x2b, 0xd0 }; |
kellybs1 | 0:3d2e0dbfbc41 | 29 | //network session key |
kellybs1 | 1:15442a59c47f | 30 | static uint8_t network_session_key[] = { 0xd8, 0x0b, 0x02, 0xd3, 0xf9, 0x06, 0x7f, 0x85, 0x75, 0xa6, 0xbe, 0x82, 0x23, 0x6e, 0xbd, 0x77 }; |
kellybs1 | 0:3d2e0dbfbc41 | 31 | //application sesssion or data session key |
kellybs1 | 1:15442a59c47f | 32 | static uint8_t data_session_key[] = { 0x86, 0x28, 0x35, 0x20, 0xa3, 0xc1, 0x16, 0x99, 0xdd, 0xf0, 0x3e, 0xa1, 0xa1, 0x42, 0x5f, 0x04 }; |
kellybs1 | 0:3d2e0dbfbc41 | 33 | static uint8_t frequency_sub_band = 2; //VFI |
kellybs1 | 0:3d2e0dbfbc41 | 34 | static bool public_network = true; |
kellybs1 | 0:3d2e0dbfbc41 | 35 | //enable receipt of ackknowledge packets 0 = No, 1 = Yes |
kellybs1 | 0:3d2e0dbfbc41 | 36 | static uint8_t ack = 0; |
kellybs1 | 0:3d2e0dbfbc41 | 37 | //adaptive data rate enabler |
kellybs1 | 0:3d2e0dbfbc41 | 38 | static bool adr = false; |
kellybs1 | 0:3d2e0dbfbc41 | 39 | |
kellybs1 | 0:3d2e0dbfbc41 | 40 | //USB serial |
kellybs1 | 0:3d2e0dbfbc41 | 41 | Serial pc(USBTX, USBRX); |
kellybs1 | 0:3d2e0dbfbc41 | 42 | |
kellybs1 | 0:3d2e0dbfbc41 | 43 | //get ourselves an mDot pointer - we will assign to it in main() |
kellybs1 | 0:3d2e0dbfbc41 | 44 | mDot* dot = NULL; |
kellybs1 | 0:3d2e0dbfbc41 | 45 | |
kellybs1 | 0:3d2e0dbfbc41 | 46 | //converts value to string |
kellybs1 | 0:3d2e0dbfbc41 | 47 | template <typename T> |
kellybs1 | 0:3d2e0dbfbc41 | 48 | string ToString(T val) { |
kellybs1 | 0:3d2e0dbfbc41 | 49 | stringstream stream; |
kellybs1 | 0:3d2e0dbfbc41 | 50 | stream << val; |
kellybs1 | 0:3d2e0dbfbc41 | 51 | return stream.str(); |
kellybs1 | 0:3d2e0dbfbc41 | 52 | } |
kellybs1 | 0:3d2e0dbfbc41 | 53 | |
kellybs1 | 0:3d2e0dbfbc41 | 54 | int main() { |
kellybs1 | 0:3d2e0dbfbc41 | 55 | //setting serial rate |
kellybs1 | 0:3d2e0dbfbc41 | 56 | pc.baud(9600); |
kellybs1 | 0:3d2e0dbfbc41 | 57 | |
kellybs1 | 0:3d2e0dbfbc41 | 58 | // use AU915 plan |
kellybs1 | 0:3d2e0dbfbc41 | 59 | lora::ChannelPlan* plan = new lora::ChannelPlan_AU915(); |
kellybs1 | 0:3d2e0dbfbc41 | 60 | assert(plan); |
kellybs1 | 0:3d2e0dbfbc41 | 61 | // get a mDot handle with the plan we chose |
kellybs1 | 0:3d2e0dbfbc41 | 62 | dot = mDot::getInstance(plan); |
kellybs1 | 0:3d2e0dbfbc41 | 63 | assert(dot); |
kellybs1 | 0:3d2e0dbfbc41 | 64 | |
kellybs1 | 0:3d2e0dbfbc41 | 65 | if (!dot->getStandbyFlag()) { |
kellybs1 | 0:3d2e0dbfbc41 | 66 | logInfo("mbed-os library version: %d", MBED_LIBRARY_VERSION); |
kellybs1 | 0:3d2e0dbfbc41 | 67 | |
kellybs1 | 0:3d2e0dbfbc41 | 68 | // start from a well-known state |
kellybs1 | 0:3d2e0dbfbc41 | 69 | logInfo("defaulting Dot configuration"); |
kellybs1 | 0:3d2e0dbfbc41 | 70 | dot->resetConfig(); |
kellybs1 | 0:3d2e0dbfbc41 | 71 | dot->resetNetworkSession(); |
kellybs1 | 0:3d2e0dbfbc41 | 72 | |
kellybs1 | 0:3d2e0dbfbc41 | 73 | // make sure library logging is turned on |
kellybs1 | 0:3d2e0dbfbc41 | 74 | dot->setLogLevel(mts::MTSLog::DEBUG_LEVEL); |
kellybs1 | 0:3d2e0dbfbc41 | 75 | |
kellybs1 | 0:3d2e0dbfbc41 | 76 | // update configuration if necessary |
kellybs1 | 0:3d2e0dbfbc41 | 77 | if (dot->getJoinMode() != mDot::MANUAL) { |
kellybs1 | 0:3d2e0dbfbc41 | 78 | logInfo("changing network join mode to MANUAL"); |
kellybs1 | 0:3d2e0dbfbc41 | 79 | if (dot->setJoinMode(mDot::MANUAL) != mDot::MDOT_OK) { |
kellybs1 | 0:3d2e0dbfbc41 | 80 | logError("failed to set network join mode to MANUAL"); |
kellybs1 | 0:3d2e0dbfbc41 | 81 | } |
kellybs1 | 0:3d2e0dbfbc41 | 82 | } |
kellybs1 | 0:3d2e0dbfbc41 | 83 | // in MANUAL join mode there is no join request/response transaction |
kellybs1 | 0:3d2e0dbfbc41 | 84 | // as long as the Dot is configured correctly and provisioned correctly on the gateway, it should be able to communicate |
kellybs1 | 0:3d2e0dbfbc41 | 85 | // network address - 4 bytes (00000001 - FFFFFFFE) |
kellybs1 | 0:3d2e0dbfbc41 | 86 | // network session key - 16 bytes |
kellybs1 | 0:3d2e0dbfbc41 | 87 | // data session key - 16 bytes |
kellybs1 | 0:3d2e0dbfbc41 | 88 | // to provision your Dot with a Conduit gateway, follow the following steps |
kellybs1 | 0:3d2e0dbfbc41 | 89 | // * ssh into the Conduit |
kellybs1 | 0:3d2e0dbfbc41 | 90 | // * provision the Dot using the lora-query application: http://www.multitech.net/developer/software/lora/lora-network-server/ |
kellybs1 | 0:3d2e0dbfbc41 | 91 | // lora-query -a 01020304 A 0102030401020304 <your Dot's device ID> 01020304010203040102030401020304 01020304010203040102030401020304 |
kellybs1 | 0:3d2e0dbfbc41 | 92 | // * if you change the network address, network session key, or data session key, make sure you update them on the gateway |
kellybs1 | 0:3d2e0dbfbc41 | 93 | // to provision your Dot with a 3rd party gateway, see the gateway or network provider documentation |
kellybs1 | 0:3d2e0dbfbc41 | 94 | update_manual_config(network_address, network_session_key, data_session_key, frequency_sub_band, public_network, ack); |
kellybs1 | 0:3d2e0dbfbc41 | 95 | |
kellybs1 | 0:3d2e0dbfbc41 | 96 | |
kellybs1 | 0:3d2e0dbfbc41 | 97 | // enable or disable Adaptive Data Rate |
kellybs1 | 0:3d2e0dbfbc41 | 98 | dot->setAdr(adr); |
kellybs1 | 0:3d2e0dbfbc41 | 99 | |
kellybs1 | 0:3d2e0dbfbc41 | 100 | //* AU915 Datarates |
kellybs1 | 0:3d2e0dbfbc41 | 101 | //* --------------- |
kellybs1 | 0:3d2e0dbfbc41 | 102 | //* DR0 - SF10BW125 -- 11 bytes |
kellybs1 | 0:3d2e0dbfbc41 | 103 | //* DR1 - SF9BW125 -- 53 bytes |
kellybs1 | 0:3d2e0dbfbc41 | 104 | //* DR2 - SF8BW125 -- 129 byte |
kellybs1 | 0:3d2e0dbfbc41 | 105 | //* DR3 - SF7BW125 -- 242 bytes |
kellybs1 | 0:3d2e0dbfbc41 | 106 | //* DR4 - SF8BW500 -- 242 bytes |
kellybs1 | 0:3d2e0dbfbc41 | 107 | dot->setTxDataRate(mDot::DR2); |
kellybs1 | 0:3d2e0dbfbc41 | 108 | |
kellybs1 | 0:3d2e0dbfbc41 | 109 | // save changes to configuration |
kellybs1 | 0:3d2e0dbfbc41 | 110 | logInfo("saving configuration"); |
kellybs1 | 0:3d2e0dbfbc41 | 111 | if (!dot->saveConfig()) { |
kellybs1 | 0:3d2e0dbfbc41 | 112 | logError("failed to save configuration"); |
kellybs1 | 0:3d2e0dbfbc41 | 113 | } |
kellybs1 | 0:3d2e0dbfbc41 | 114 | |
kellybs1 | 0:3d2e0dbfbc41 | 115 | // display configuration |
kellybs1 | 0:3d2e0dbfbc41 | 116 | display_config(); |
kellybs1 | 0:3d2e0dbfbc41 | 117 | } else { |
kellybs1 | 0:3d2e0dbfbc41 | 118 | // restore the saved session if the dot woke from deepsleep mode |
kellybs1 | 0:3d2e0dbfbc41 | 119 | // useful to use with deepsleep because session info is otherwise lost when the dot enters deepsleep |
kellybs1 | 0:3d2e0dbfbc41 | 120 | logInfo("restoring network session from NVM"); |
kellybs1 | 0:3d2e0dbfbc41 | 121 | dot->restoreNetworkSession(); |
kellybs1 | 0:3d2e0dbfbc41 | 122 | } |
kellybs1 | 0:3d2e0dbfbc41 | 123 | |
kellybs1 | 0:3d2e0dbfbc41 | 124 | //this is where the magic happens |
kellybs1 | 0:3d2e0dbfbc41 | 125 | while (true) { |
kellybs1 | 0:3d2e0dbfbc41 | 126 | |
kellybs1 | 0:3d2e0dbfbc41 | 127 | //wake up |
kellybs1 | 0:3d2e0dbfbc41 | 128 | wait(2); |
kellybs1 | 0:3d2e0dbfbc41 | 129 | //init data variable |
kellybs1 | 0:3d2e0dbfbc41 | 130 | std::vector<uint8_t> data; |
kellybs1 | 0:3d2e0dbfbc41 | 131 | |
kellybs1 | 0:3d2e0dbfbc41 | 132 | //read sensor |
kellybs1 | 0:3d2e0dbfbc41 | 133 | //read multiple times - this just smoothes the value out a little bit |
kellybs1 | 1:15442a59c47f | 134 | float moist1 = a0.read() * 1023; |
kellybs1 | 0:3d2e0dbfbc41 | 135 | wait_ms(100); |
kellybs1 | 1:15442a59c47f | 136 | float moist2 = a0.read() * 1023; |
kellybs1 | 0:3d2e0dbfbc41 | 137 | wait_ms(100); |
kellybs1 | 1:15442a59c47f | 138 | float moist3 = a0.read() * 1023; |
kellybs1 | 0:3d2e0dbfbc41 | 139 | wait_ms(100); |
kellybs1 | 0:3d2e0dbfbc41 | 140 | //average the multiple readings |
kellybs1 | 0:3d2e0dbfbc41 | 141 | float moistF = (moist1 + moist2 + moist3) / 3; |
kellybs1 | 0:3d2e0dbfbc41 | 142 | |
kellybs1 | 0:3d2e0dbfbc41 | 143 | |
kellybs1 | 0:3d2e0dbfbc41 | 144 | //build our output string now |
kellybs1 | 0:3d2e0dbfbc41 | 145 | string output = ToString(moistF); |
kellybs1 | 0:3d2e0dbfbc41 | 146 | |
kellybs1 | 0:3d2e0dbfbc41 | 147 | //serial output for debugging |
kellybs1 | 0:3d2e0dbfbc41 | 148 | logInfo("Sending %s", output.c_str()); |
kellybs1 | 0:3d2e0dbfbc41 | 149 | |
kellybs1 | 0:3d2e0dbfbc41 | 150 | // format data for sending to the gateway |
kellybs1 | 0:3d2e0dbfbc41 | 151 | for (std::string::iterator it = output.begin(); it != output.end(); it++) |
kellybs1 | 0:3d2e0dbfbc41 | 152 | data.push_back((uint8_t) *it); |
kellybs1 | 0:3d2e0dbfbc41 | 153 | |
kellybs1 | 0:3d2e0dbfbc41 | 154 | //now send |
kellybs1 | 0:3d2e0dbfbc41 | 155 | send_data(data); |
kellybs1 | 0:3d2e0dbfbc41 | 156 | |
kellybs1 | 0:3d2e0dbfbc41 | 157 | // go to sleep and wake up automatically sleep_time seconds later |
kellybs1 | 1:15442a59c47f | 158 | uint32_t sleep_time = 30; |
kellybs1 | 0:3d2e0dbfbc41 | 159 | //false is "don't deep sleep" - mDot doesn't do that |
kellybs1 | 0:3d2e0dbfbc41 | 160 | dot->sleep(sleep_time, mDot::RTC_ALARM, false); |
kellybs1 | 0:3d2e0dbfbc41 | 161 | } |
kellybs1 | 0:3d2e0dbfbc41 | 162 | |
kellybs1 | 0:3d2e0dbfbc41 | 163 | return 0; //shouldn't happen |
kellybs1 | 0:3d2e0dbfbc41 | 164 | } |
kellybs1 | 0:3d2e0dbfbc41 | 165 |