This is a demo Dragino LoRa Mini Dev featuring LoRa® technology client (based on one of the examples from Arduino-LoRa) that uploads telemetry data to my AdaFruit.IO and Azure IoT Hubs Windows 10 IoT Core on Raspberry PI proof of concept (PoC) field gateways.
Bill of materials (Prices Sep 2018)
- Draguino LoRa MiniDev USD23
- Seeedstudio Temperature&Humidity Sensor USD11.50 NZD20
- 4 pin Male Jumper to Grove 4 pin Conversion Cable USD2.90
The code is pretty basic, it shows how to pack the payload and set the necessary RFM9X/SX127X LoRa module configuration, has no power conservation, advanced wireless configuration etc.
The Grove 4 pin Male Jumper to Grove 4 pin Conversion Cable was a quick & convenient way to get the I2C Grove temperature and humidity sensor connected up.
/* Adapted from LoRa Duplex communication with Sync Word Sends temperature & humidity data from Seeedstudio https://www.seeedstudio.com/Grove-Temperature-Humidity-Sensor-High-Accuracy-Min-p-1921.html To my Windows 10 IoT Core RFM 9X library https://blog.devmobile.co.nz/2018/09/03/rfm9x-iotcore-payload-addressing/ */ #include #include #include const int csPin = 10; // LoRa radio chip select const int resetPin = 9; // LoRa radio reset const int irqPin = 2; // change for your board; must be a hardware interrupt pin // Field gateway configuration const byte FieldGatewayAddress[] = "LoRaIoT1"; const float FieldGatewayFrequency = 915000000.0; //const float FieldGatewayFrequency = 433000000.0; const byte FieldGatewaySyncWord = 0x12 ; // Payload configuration const int PayloadSizeMaximum = 64 ; char payload[PayloadSizeMaximum] = ""; const byte SensorReadingSeperator = ',' ; // Manual serial number configuration char DeviceId[] = {"LoRaMiniDev5"}; const int LoopSleepDelaySeconds = 10 ; void setup() { Serial.begin(9600); while (!Serial); Serial.print("LoRa Setup-"); Serial.println( DeviceId ) ; // override the default CS, reset, and IRQ pins (optional) LoRa.setPins(csPin, resetPin, irqPin);// set CS, reset, IRQ pin if (!LoRa.begin(FieldGatewayFrequency)) { Serial.println("LoRa init failed. Check your connections."); while (true); } // Need to do this so field gateways pays attention to messsages from this device LoRa.enableCrc(); LoRa.setSyncWord(FieldGatewaySyncWord); //LoRa.dumpRegisters(Serial); Serial.println("LoRa Setup done."); // Configure the Seeedstudio TH02 temperature & humidity sensor Serial.println("TH02 setup"); TH02.begin(); delay(100); Serial.println("TH02 Setup done"); Serial.println("Setup done"); } void loop() { int payloadLength = 0 ; float temperature ; float humidity ; Serial.println("Loop called"); memset(payload, 0, sizeof(payload)); // prepare the payload header with "To" Address length (top nibble) and "From" address length (bottom nibble) payload[0] = (strlen(FieldGatewayAddress)<<4) | strlen( DeviceId ) ; payloadLength += 1; // Copy the "To" address into payload memcpy(&payload[payloadLength], FieldGatewayAddress, strlen(FieldGatewayAddress)); payloadLength += strlen(FieldGatewayAddress) ; // Copy the "From" into payload memcpy(&payload[payloadLength], DeviceId, strlen(DeviceId)); payloadLength += strlen(DeviceId) ; // Read the temperature and humidity values then display nicely temperature = TH02.ReadTemperature(); humidity = TH02.ReadHumidity(); Serial.print("T:"); Serial.print( temperature, 1 ) ; Serial.print( "C" ) ; Serial.print(" H:"); Serial.print( humidity, 0 ) ; Serial.println( "%" ) ; // Copy the temperature into the payload payload[ payloadLength] = 't'; payloadLength += 1 ; payload[ payloadLength] = ' '; payloadLength += 1 ; payloadLength += strlen( dtostrf(temperature, -1, 1, &payload[payloadLength])); payload[ payloadLength] = SensorReadingSeperator; payloadLength += sizeof(SensorReadingSeperator) ; // Copy the humidity into the payload payload[ payloadLength] = 'h'; payloadLength += 1 ; payload[ payloadLength] = ' '; payloadLength += 1 ; payloadLength += strlen( dtostrf(humidity, -1, 0, &payload[payloadLength])); // display info about payload then send it (No ACK) with LoRa unlike nRF24L01 Serial.print( "RFM9X/SX127X Payload length:"); Serial.print( payloadLength ); Serial.println( " bytes" ); LoRa.beginPacket(); LoRa.write( payload, payloadLength ); LoRa.endPacket(); Serial.println("Loop done"); delay(LoopSleepDelaySeconds * 1000l); }
In the debug output window the messages from the device looked like this
09:53:05-RX From LoRaMiniDev5 PacketSnr 9.3 Packet RSSI -65dBm RSSI -109dBm = 11 byte message "t 16.8,h 98" Sensor LoRaMiniDev5t Value 16.8 Sensor LoRaMiniDev5h Value 98 AzureIoTHubClient SendEventAsync start AzureIoTHubClient SendEventAsync finish The thread 0xba0 has exited with code 0 (0x0). The thread 0xb24 has exited with code 0 (0x0). 09:53:15-RX From LoRaMiniDev5 PacketSnr 9.3 Packet RSSI -65dBm RSSI -108dBm = 11 byte message "t 16.7,h 98" Sensor LoRaMiniDev5t Value 16.7 Sensor LoRaMiniDev5h Value 98 AzureIoTHubClient SendEventAsync start AzureIoTHubClient SendEventAsync finish The thread 0x76c has exited with code 0 (0x0). The thread 0x91c has exited with code 0 (0x0).
Then in my Azure IoT Hub monitoring software
The dragino LoRa Mini Dev with an external antenna connector would be a good indoor data acquisition node for student project when powered by a 2nd hand cellphone charger.