LoRaWAN demo application using grove peripherals generating Cayenne LPP

Dependencies:   lorawan1v1

radio chip selection

Radio chip driver is not included, because two options are available.
If you're using SX1272 or SX1276, then import sx127x driver into your program.
if you're using SX1261 or SX1262, then import sx126x driver into your program.
If you're using NAmote72 or Murata discovery, then you must import only sx127x driver.

Grove peripherals -> Cayenne demo

Read LoRaWAN-1.1 page for configuration instructions.

This project adds support for Murata discovery board, in addition to LoRa shields on NUCLEO boards.

Use with sx1272 shield with grove peripherals connected:

D8 D9: ButtonRX TXA3 A4: TempSense
D6 D7:SCL SDA : LEDA1 A2: Pot

Button

Sends two different payload types: short press (under 1 sec)
long press: held down > 1 sec.

serial console keys

115200bps, 8N1
Enter key not used
Keys '0' to '3': cayenne channel number
'0': pot (rotary sensor)
'1': temperature
'2': digital out
'3': analog out

DevEUI configuration

For use on networks which force you to use DevEUI defined by network, comment out HardwareIDtoDevEUI().
HardwareIDtoDevEUI() obtains DevEUI from the CPU unique hardware serial number. However, some networks may force you to use their DevEUI value.

Revision:
4:72b8fdc9878e
Parent:
3:fc23bbc14475
Child:
5:53cd6c24a4ab
--- a/sensorDemoVT100.cpp	Mon Mar 19 14:46:37 2018 -0700
+++ b/sensorDemoVT100.cpp	Thu Mar 29 14:57:14 2018 -0700
@@ -41,7 +41,7 @@
 /*!
  * LoRaWAN confirmed messages
  */
-#define LORAWAN_CONFIRMED_MSG_ON                    true
+#define LORAWAN_CONFIRMED_MSG_ON                    false
 
 /*!
  * LoRaWAN Adaptive Data Rate
@@ -271,12 +271,14 @@
 #define CAYENNE_CH_AOUT     3
 #define CAYENNE_CH_TEMP     0
 #define CAYENNE_CH_POT      1
+#define CAYENNE_CH_DIN      4
 
 AnalogIn a1(A1);
 AnalogIn a3(A3);
 
 const unsigned R0 = 100000;
 const unsigned B = 4275;
+volatile bool dout_downlink;
 
 /*!
  * \brief   Prepares the payload of the frame
@@ -285,6 +287,7 @@
 {
     uint16_t u16, rot;
     float t, f, R;
+    static uint8_t seq;
 
     if (c_ch != 0xff) {
         gAppDataSize = 0;
@@ -367,9 +370,17 @@
             AppData[gAppDataSize++] = rot >> 8;
             AppData[gAppDataSize++] = rot;
 
-            AppData[gAppDataSize++] = CAYENNE_CH_DOUT;
-            AppData[gAppDataSize++] = LPP_DIGITAL_OUTPUT;
-            AppData[gAppDataSize++] = extLed.read();
+            /* limited packet size: either ack downlink, or send sequence number */
+            if (dout_downlink) {
+                AppData[gAppDataSize++] = CAYENNE_CH_DOUT;
+                AppData[gAppDataSize++] = LPP_DIGITAL_OUTPUT;
+                AppData[gAppDataSize++] = extLed.read();
+                dout_downlink = false;
+            } else {
+                AppData[gAppDataSize++] = CAYENNE_CH_DIN;
+                AppData[gAppDataSize++] = LPP_DIGITAL_INPUT;
+                AppData[gAppDataSize++] = seq++;
+            }
             break;
         case 224:
             if( ComplianceTest.LinkCheck == true ) {
@@ -583,6 +594,7 @@
             switch (mcpsIndication->Buffer[n]) {
                 case CAYENNE_CH_DOUT:
                     extLed.write(val);
+                    dout_downlink = true;
                     break;
                 case CAYENNE_CH_AOUT:
                     pwm.write(val / 100.0);
@@ -1071,6 +1083,9 @@
     jumper_out = 1;
     jumper_in.mode(PullDown);
     jumper_in.rise(jumper_callback);
+    // Q: does InterruptIn.rise() call immediately if already high?
+    if (jumper_in.read())
+        jumper_callback(); // A: probably not
 #endif /* JUMPER_ENABLE */
 
     while( 1 )