diff --git a/TheThingsNetwork_Feather/ttn-otaa-feather-us915-dht22-OLED/ttn-otaa-feather-us915-dht22-OLED.ino b/TheThingsNetwork_Feather/ttn-otaa-feather-us915-dht22-OLED/ttn-otaa-feather-us915-dht22-OLED.ino new file mode 100644 index 000000000..49d74a220 --- /dev/null +++ b/TheThingsNetwork_Feather/ttn-otaa-feather-us915-dht22-OLED/ttn-otaa-feather-us915-dht22-OLED.ino @@ -0,0 +1,333 @@ +/******************************************************************************* + * The Things Network - Sensor Data Example with OLED + * + * 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" + +// include the FeatherWing OLED library +#include +#include +#include + +// DHT digital pin and sensor type +#define DHTPIN 10 +#define DHTTYPE DHT22 + +Adafruit_SSD1306 display = Adafruit_SSD1306(); + +#if (SSD1306_LCDHEIGHT != 32) + #error("Height incorrect, please fix Adafruit_SSD1306.h!"); +#endif + +// +// 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 = 10; + +// dht +float temperature; +float rHumidity; + +// 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: + display.print("TTN: Joining..."); + display.display(); + Serial.println(F("EV_JOINING")); + break; + case EV_JOINED: + display.clearDisplay(); + display.display(); + display.setCursor(0, 0); + display.println("TTN: Connected"); + display.display(); + 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); + Serial.println(F("EV_TXSTART")); + } + // Next TX is scheduled after TX_COMPLETE event. +} + +void setup() { + delay(5000); + while (! Serial); + Serial.begin(9600); + Serial.println(F("Starting")); + + dht.begin(); + // by default, we'll generate the high voltage from the 3.3v line internally! (neat!) + display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // initialize with the I2C addr 0x3C (for the 128x32) + Serial.println("OLED and DHT init'd"); + + // Show image buffer on the display hardware. + // Since the buffer is intialized with an Adafruit splashscreen + // internally, this will display the splashscreen. + display.display(); + delay(1000); + + // Clear the buffer. + display.clearDisplay(); + display.display(); + + // set text display size/location + display.setTextSize(1); + display.setTextColor(WHITE); + display.setCursor(0,0); + + // 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(); +}