Analogue soil moisture reader - simple

Dependencies:   libmDot-mbed5

Committer:
kellybs1
Date:
Mon Nov 06 03:56:17 2017 +0000
Revision:
2:d8858f9fc425
Parent:
1:15442a59c47f
initial

Who changed what in which revision?

UserRevisionLine numberNew 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 2:d8858f9fc425 28 static uint8_t network_address[] = { };
kellybs1 0:3d2e0dbfbc41 29 //network session key
kellybs1 2:d8858f9fc425 30 static uint8_t network_session_key[] = { };
kellybs1 0:3d2e0dbfbc41 31 //application sesssion or data session key
kellybs1 2:d8858f9fc425 32 static uint8_t data_session_key[] = { };
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 2:d8858f9fc425 158 uint32_t sleep_time = 60;
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