/******************************************************************************* * The Things Network - Sensor Data Example * * Example of sending a valid LoRaWAN packet with DHT22 temperature and * humidity data to The Things Networ using a Feather M0 LoRa. * * Learn Guide: https://learn.adafruit.com/the-things-network-for-feather * * Copyright (c) 2015 Thomas Telkamp and Matthijs Kooijman * Copyright (c) 2018 Terry Moore, MCCI * Copyright (c) 2018 Brent Rubell, Adafruit Industries * * Permission is hereby granted, free of charge, to anyone * obtaining a copy of this document and accompanying files, * to do whatever they want with them without any restriction, * including, but not limited to, copying, modification and redistribution. * NO WARRANTY OF ANY KIND IS PROVIDED. *******************************************************************************/ #include #include #include // include the DHT22 Sensor Library #include "DHT.h" // DHT digital pin and sensor type #define DHTPIN 10 #define DHTTYPE DHT22 // // For normal use, we require that you edit the sketch to replace FILLMEIN // with values assigned by the TTN console. However, for regression tests, // we want to be able to compile these scripts. The regression tests define // COMPILE_REGRESSION_TEST, and in that case we define FILLMEIN to a non- // working but innocuous value. // #ifdef COMPILE_REGRESSION_TEST #define FILLMEIN 0 #else #warning "You must replace the values marked FILLMEIN with real values from the TTN control panel!" #define FILLMEIN (#dont edit this, edit the lines that use FILLMEIN) #endif // This EUI must be in little-endian format, so least-significant-byte // first. When copying an EUI from ttnctl output, this means to reverse // the bytes. For TTN issued EUIs the last bytes should be 0xD5, 0xB3, // 0x70. static const u1_t PROGMEM APPEUI[8] = { FILLMEIN }; void os_getArtEui (u1_t* buf) { memcpy_P(buf, APPEUI, 8);} // This should also be in little endian format, see above. static const u1_t PROGMEM DEVEUI[8] = { FILLMEIN }; void os_getDevEui (u1_t* buf) { memcpy_P(buf, DEVEUI, 8);} // This key should be in big endian format (or, since it is not really a // number but a block of memory, endianness does not really apply). In // practice, a key taken from the TTN console can be copied as-is. static const u1_t PROGMEM APPKEY[16] = { FILLMEIN }; void os_getDevKey (u1_t* buf) { memcpy_P(buf, APPKEY, 16);} // payload to send to TTN gateway static uint8_t payload[5]; static osjob_t sendjob; // Schedule TX every this many seconds (might become longer due to duty // cycle limitations). const unsigned TX_INTERVAL = 30; // Pin mapping for Adafruit Feather M0 LoRa const lmic_pinmap lmic_pins = { .nss = 8, .rxtx = LMIC_UNUSED_PIN, .rst = 4, .dio = {3, 6, LMIC_UNUSED_PIN}, .rxtx_rx_active = 0, .rssi_cal = 8, // LBT cal for the Adafruit Feather M0 LoRa, in dB .spi_freq = 8000000, }; // init. DHT DHT dht(DHTPIN, DHTTYPE); void onEvent (ev_t ev) { Serial.print(os_getTime()); Serial.print(": "); switch(ev) { case EV_SCAN_TIMEOUT: Serial.println(F("EV_SCAN_TIMEOUT")); break; case EV_BEACON_FOUND: Serial.println(F("EV_BEACON_FOUND")); break; case EV_BEACON_MISSED: Serial.println(F("EV_BEACON_MISSED")); break; case EV_BEACON_TRACKED: Serial.println(F("EV_BEACON_TRACKED")); break; case EV_JOINING: Serial.println(F("EV_JOINING")); break; case EV_JOINED: Serial.println(F("EV_JOINED")); { u4_t netid = 0; devaddr_t devaddr = 0; u1_t nwkKey[16]; u1_t artKey[16]; LMIC_getSessionKeys(&netid, &devaddr, nwkKey, artKey); Serial.print("netid: "); Serial.println(netid, DEC); Serial.print("devaddr: "); Serial.println(devaddr, HEX); Serial.print("artKey: "); for (int i=0; i int // note: this uses the sflt16 datum (https://github.com/mcci-catena/arduino-lmic#sflt16) uint16_t payloadTemp = LMIC_f2sflt16(temperature); // int -> bytes byte tempLow = lowByte(payloadTemp); byte tempHigh = highByte(payloadTemp); // place the bytes into the payload payload[0] = tempLow; payload[1] = tempHigh; // float -> int uint16_t payloadHumid = LMIC_f2sflt16(rHumidity); // int -> bytes byte humidLow = lowByte(payloadHumid); byte humidHigh = highByte(payloadHumid); payload[2] = humidLow; payload[3] = humidHigh; // prepare upstream data transmission at the next possible time. // transmit on port 1 (the first parameter); you can use any value from 1 to 223 (others are reserved). // don't request an ack (the last parameter, if not zero, requests an ack from the network). // Remember, acks consume a lot of network resources; don't ask for an ack unless you really need it. LMIC_setTxData2(1, payload, sizeof(payload)-1, 0); } // Next TX is scheduled after TX_COMPLETE event. } void setup() { delay(5000); while (! Serial); Serial.begin(9600); Serial.println(F("Starting")); dht.begin(); // LMIC init os_init(); // Reset the MAC state. Session and pending data transfers will be discarded. LMIC_reset(); // Disable link-check mode and ADR, because ADR tends to complicate testing. LMIC_setLinkCheckMode(0); // Set the data rate to Spreading Factor 7. This is the fastest supported rate for 125 kHz channels, and it // minimizes air time and battery power. Set the transmission power to 14 dBi (25 mW). LMIC_setDrTxpow(DR_SF7,14); // in the US, with TTN, it saves join time if we start on subband 1 (channels 8-15). This will // get overridden after the join by parameters from the network. If working with other // networks or in other regions, this will need to be changed. LMIC_selectSubBand(1); // Start job (sending automatically starts OTAA too) do_send(&sendjob); } void loop() { // we call the LMIC's runloop processor. This will cause things to happen based on events and time. One // of the things that will happen is callbacks for transmission complete or received messages. We also // use this loop to queue periodic data transmissions. You can put other things here in the `loop()` routine, // but beware that LoRaWAN timing is pretty tight, so if you do more than a few milliseconds of work, you // will want to call `os_runloop_once()` every so often, to keep the radio running. os_runloop_once(); }