kopia lustrzana https://github.com/helium/longfi-arduino
add feather m0 rfm95 example
rodzic
1fdb00718f
commit
436ab3def7
|
@ -0,0 +1,37 @@
|
|||
# Adafruit Feather M0 RFM95 - DHT22 CayenneLPP Example
|
||||
|
||||
[Quickstart Guide](https://docs.helium.com/use-the-network/devices/development/adafruit-feather-m0-rfm95/adafruitio)
|
||||
[Adafruit Feather M0 with RFM95 Product Page](https://www.adafruit.com/product/3178)
|
||||
[Adafruit Feather M0 with RFM95 Datasheets & Files](https://learn.adafruit.com/adafruit-feather-m0-radio-with-lora-radio-module/downloads).
|
||||
|
||||
## Required Arduino Libraries
|
||||
|
||||
### Important
|
||||
Make sure you do not have other LMIC arduino libraries installed, otherwise you will experience
|
||||
build errors. You can find your Arduino libraries for your operating system below, simply delete the directory if you would like to remove a library.
|
||||
|
||||
linux: /home/{user}/Arduino/libraries
|
||||
windows: Documents/Arduino/libraries
|
||||
mac os: Documents/Arduino/libraries
|
||||
|
||||
From the Arduino IDE, open the Library Manager (Sketch->Include Library->Manage Libraries). In the search box, type the library name below and install version `1.5.0+arduino-2`.
|
||||
|
||||
[IBM LMIC framework](https://github.com/matthijskooijman/arduino-lmic)
|
||||
|
||||
Next, search for and install both `CayenneLPP` and `DHT sensor library`
|
||||
|
||||
[CayenneLPP](https://github.com/ElectronicCats/CayenneLPP)
|
||||
[DHT sensor library](https://github.com/adafruit/DHT-sensor-library)
|
||||
|
||||
### Required Configuration
|
||||
This library requires that a config file be setup properly. After you have installed the `IBM LMIC framework` library, navigate to it's directory on your operating system found below. Next, replace the `config.h` file in this directory with this [config.h](https://github.com/helium/longfi-arduino/blob/master/Sparkfun-Pro-RF/longfi-us915/config.h) file.
|
||||
|
||||
linux: /home/{user}/Arduino/libraries/IBM_LMIC_framework/src/lmic
|
||||
windows: Documents/Arduino/libraries/IBM_LMIC_framework/src/lmic
|
||||
mac os: Documents/Arduino/libraries/IBM_LMIC_framework/src/lmic
|
||||
|
||||
## Required Arduino Board Support
|
||||
|
||||
1. Install Arduino SAMD Support, instructions [here](https://learn.adafruit.com/adafruit-feather-m0-radio-with-lora-radio-module/using-with-arduino-ide#install-samd-support-6-5).
|
||||
2. Install Adafruit SAMD Support, instructions [here](https://learn.adafruit.com/adafruit-feather-m0-radio-with-lora-radio-module/using-with-arduino-ide#install-adafruit-samd-6-7).
|
||||
3. (Windows 7 & 8 Only) Install drivers, instructions [here](https://learn.adafruit.com/adafruit-feather-m0-radio-with-lora-radio-module/using-with-arduino-ide#install-drivers-windows-7-and-8-only-6-11)
|
|
@ -0,0 +1,83 @@
|
|||
#ifndef _lmic_config_h_
|
||||
#define _lmic_config_h_
|
||||
|
||||
// In the original LMIC code, these config values were defined on the
|
||||
// gcc commandline. Since Arduino does not allow easily modifying the
|
||||
// compiler commandline, use this file instead.
|
||||
|
||||
// #define CFG_eu868 1
|
||||
#define CFG_us915 1
|
||||
// This is the SX1272/SX1273 radio, which is also used on the HopeRF
|
||||
// RFM92 boards.
|
||||
//#define CFG_sx1272_radio 1
|
||||
// This is the SX1276/SX1277/SX1278/SX1279 radio, which is also used on
|
||||
// the HopeRF RFM95 boards.
|
||||
#define CFG_sx1276_radio 1
|
||||
|
||||
// 16 μs per tick
|
||||
// LMIC requires ticks to be 15.5μs - 100 μs long
|
||||
#define US_PER_OSTICK_EXPONENT 4
|
||||
#define US_PER_OSTICK (1 << US_PER_OSTICK_EXPONENT)
|
||||
#define OSTICKS_PER_SEC (1000000 / US_PER_OSTICK)
|
||||
|
||||
// Set this to 1 to enable some basic debug output (using printf) about
|
||||
// RF settings used during transmission and reception. Set to 2 to
|
||||
// enable more verbose output. Make sure that printf is actually
|
||||
// configured (e.g. on AVR it is not by default), otherwise using it can
|
||||
// cause crashing.
|
||||
#define LMIC_DEBUG_LEVEL 0
|
||||
|
||||
// Enable this to allow using printf() to print to the given serial port
|
||||
// (or any other Print object). This can be easy for debugging. The
|
||||
// current implementation only works on AVR, though.
|
||||
//#define LMIC_PRINTF_TO Serial
|
||||
|
||||
// Any runtime assertion failures are printed to this serial port (or
|
||||
// any other Print object). If this is unset, any failures just silently
|
||||
// halt execution.
|
||||
#define LMIC_FAILURE_TO Serial
|
||||
|
||||
// Uncomment this to disable all code related to joining
|
||||
//#define DISABLE_JOIN
|
||||
// Uncomment this to disable all code related to ping
|
||||
//#define DISABLE_PING
|
||||
// Uncomment this to disable all code related to beacon tracking.
|
||||
// Requires ping to be disabled too
|
||||
//#define DISABLE_BEACONS
|
||||
|
||||
// Uncomment these to disable the corresponding MAC commands.
|
||||
// Class A
|
||||
//#define DISABLE_MCMD_DCAP_REQ // duty cycle cap
|
||||
//#define DISABLE_MCMD_DN2P_SET // 2nd DN window param
|
||||
//#define DISABLE_MCMD_SNCH_REQ // set new channel
|
||||
// Class B
|
||||
//#define DISABLE_MCMD_PING_SET // set ping freq, automatically disabled by DISABLE_PING
|
||||
//#define DISABLE_MCMD_BCNI_ANS // next beacon start, automatical disabled by DISABLE_BEACON
|
||||
|
||||
// In LoRaWAN, a gateway applies I/Q inversion on TX, and nodes do the
|
||||
// same on RX. This ensures that gateways can talk to nodes and vice
|
||||
// versa, but gateways will not hear other gateways and nodes will not
|
||||
// hear other nodes. By uncommenting this macro, this inversion is
|
||||
// disabled and this node can hear other nodes. If two nodes both have
|
||||
// this macro set, they can talk to each other (but they can no longer
|
||||
// hear gateways). This should probably only be used when debugging
|
||||
// and/or when talking to the radio directly (e.g. like in the "raw"
|
||||
// example).
|
||||
//#define DISABLE_INVERT_IQ_ON_RX
|
||||
|
||||
// This allows choosing between multiple included AES implementations.
|
||||
// Make sure exactly one of these is uncommented.
|
||||
//
|
||||
// This selects the original AES implementation included LMIC. This
|
||||
// implementation is optimized for speed on 32-bit processors using
|
||||
// fairly big lookup tables, but it takes up big amounts of flash on the
|
||||
// AVR architecture.
|
||||
// #define USE_ORIGINAL_AES
|
||||
//
|
||||
// This selects the AES implementation written by Ideetroon for their
|
||||
// own LoRaWAN library. It also uses lookup tables, but smaller
|
||||
// byte-oriented ones, making it use a lot less flash space (but it is
|
||||
// also about twice as slow as the original).
|
||||
#define USE_IDEETRON_AES
|
||||
|
||||
#endif // _lmic_config_h_
|
|
@ -0,0 +1,254 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2015 Thomas Telkamp and Matthijs Kooijman
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This example sends a valid LoRaWAN packet with payload "Hello,
|
||||
* world!", using frequency and encryption settings matching those of
|
||||
* the The Things Network.
|
||||
*
|
||||
* This uses OTAA (Over-the-air activation), where where a DevEUI and
|
||||
* application key is configured, which are used in an over-the-air
|
||||
* activation procedure where a DevAddr and session keys are
|
||||
* assigned/generated for use with all further communication.
|
||||
*
|
||||
* Note: LoRaWAN per sub-band duty-cycle limitation is enforced (1% in
|
||||
* g1, 0.1% in g2), but not the TTN fair usage policy (which is probably
|
||||
* violated by this sketch when left running for longer)!
|
||||
|
||||
* To use this sketch, first register your application and device with
|
||||
* the things network, to set or generate an AppEUI, DevEUI and AppKey.
|
||||
* Multiple devices can use the same AppEUI, but each device has its own
|
||||
* DevEUI and AppKey.
|
||||
*
|
||||
* Do not forget to define the radio type correctly in config.h.
|
||||
*
|
||||
*******************************************************************************/
|
||||
#include <lmic.h>
|
||||
#include <hal/hal.h>
|
||||
#include <SPI.h>
|
||||
|
||||
#include <Adafruit_Sensor.h>
|
||||
#include <DHT.h>
|
||||
#include <DHT_U.h>
|
||||
|
||||
#include <CayenneLPP.h>
|
||||
|
||||
#define DHTPIN 12
|
||||
#define DHTTYPE DHT22 // DHT 22 (AM2302)
|
||||
|
||||
DHT_Unified dht(DHTPIN, DHTTYPE);
|
||||
|
||||
// Init CayenneLPP Payload
|
||||
CayenneLPP lpp(51);
|
||||
|
||||
// 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]={ FILL_ME_IN };
|
||||
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]={ FILL_ME_IN };
|
||||
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 ttnctl can be copied as-is.
|
||||
// The key shown here is the semtech default key.
|
||||
static const u1_t PROGMEM APPKEY[16] = { FILL_ME_IN };
|
||||
void os_getDevKey (u1_t* buf) { memcpy_P(buf, APPKEY, 16);}
|
||||
|
||||
static osjob_t sendjob;
|
||||
|
||||
// Schedule TX every this many seconds (might become longer due to duty
|
||||
// cycle limitations).
|
||||
const unsigned TX_INTERVAL = 20;
|
||||
|
||||
// Pin mapping
|
||||
const lmic_pinmap lmic_pins = {
|
||||
.nss = 8,
|
||||
.rxtx = LMIC_UNUSED_PIN,
|
||||
.rst = 4,
|
||||
.dio = {3, 6, 2},
|
||||
};
|
||||
|
||||
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"));
|
||||
|
||||
// Disable link check validation (automatically enabled
|
||||
// during join, but not supported by TTN at this time).
|
||||
LMIC_setLinkCheckMode(0);
|
||||
break;
|
||||
case EV_RFU1:
|
||||
Serial.println(F("EV_RFU1"));
|
||||
break;
|
||||
case EV_JOIN_FAILED:
|
||||
Serial.println(F("EV_JOIN_FAILED"));
|
||||
break;
|
||||
case EV_REJOIN_FAILED:
|
||||
Serial.println(F("EV_REJOIN_FAILED"));
|
||||
break;
|
||||
break;
|
||||
case EV_TXCOMPLETE:
|
||||
Serial.println(F("EV_TXCOMPLETE (includes waiting for RX windows)"));
|
||||
if (LMIC.txrxFlags & TXRX_ACK)
|
||||
Serial.println(F("Received ack"));
|
||||
if (LMIC.dataLen) {
|
||||
Serial.println(F("Received "));
|
||||
Serial.println(LMIC.dataLen);
|
||||
Serial.println(F(" bytes of payload"));
|
||||
}
|
||||
// Schedule next transmission
|
||||
os_setTimedCallback(&sendjob, os_getTime()+sec2osticks(TX_INTERVAL), do_send);
|
||||
break;
|
||||
case EV_LOST_TSYNC:
|
||||
Serial.println(F("EV_LOST_TSYNC"));
|
||||
break;
|
||||
case EV_RESET:
|
||||
Serial.println(F("EV_RESET"));
|
||||
break;
|
||||
case EV_RXCOMPLETE:
|
||||
// data received in ping slot
|
||||
Serial.println(F("EV_RXCOMPLETE"));
|
||||
break;
|
||||
case EV_LINK_DEAD:
|
||||
Serial.println(F("EV_LINK_DEAD"));
|
||||
break;
|
||||
case EV_LINK_ALIVE:
|
||||
Serial.println(F("EV_LINK_ALIVE"));
|
||||
break;
|
||||
default:
|
||||
Serial.println(F("Unknown event"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void do_send(osjob_t* j){
|
||||
// Check if there is not a current TX/RX job running
|
||||
if (LMIC.opmode & OP_TXRXPEND) {
|
||||
Serial.println(F("OP_TXRXPEND, not sending"));
|
||||
} else {
|
||||
|
||||
// Clear Payload
|
||||
lpp.reset();
|
||||
|
||||
// Get temperature event and print its value.
|
||||
sensors_event_t event;
|
||||
dht.temperature().getEvent(&event);
|
||||
if (isnan(event.temperature)) {
|
||||
Serial.println(F("Error reading temperature!"));
|
||||
}
|
||||
else {
|
||||
Serial.print(F("Temperature: "));
|
||||
Serial.print(event.temperature);
|
||||
Serial.println(F("°C"));
|
||||
|
||||
lpp.addTemperature(1, event.temperature);
|
||||
}
|
||||
// Get humidity event and print its value.
|
||||
dht.humidity().getEvent(&event);
|
||||
if (isnan(event.relative_humidity)) {
|
||||
Serial.println(F("Error reading humidity!"));
|
||||
}
|
||||
else {
|
||||
Serial.print(F("Humidity: "));
|
||||
Serial.print(event.relative_humidity);
|
||||
Serial.println(F("%"));
|
||||
|
||||
lpp.addRelativeHumidity(2, event.relative_humidity);
|
||||
}
|
||||
|
||||
// Prepare upstream data transmission at the next possible time.
|
||||
LMIC_setTxData2(1, lpp.getBuffer(), lpp.getSize(), 0);
|
||||
Serial.println(F("Packet queued"));
|
||||
}
|
||||
// Next TX is scheduled after TX_COMPLETE event.
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
Serial.println(F("Starting"));
|
||||
|
||||
#ifdef VCC_ENABLE
|
||||
// For Pinoccio Scout boards
|
||||
pinMode(VCC_ENABLE, OUTPUT);
|
||||
digitalWrite(VCC_ENABLE, HIGH);
|
||||
delay(1000);
|
||||
#endif
|
||||
|
||||
// Initialize DHT22.
|
||||
dht.begin();
|
||||
Serial.println(F("DHTxx Unified Sensor Example"));
|
||||
// Print temperature sensor details.
|
||||
sensor_t sensor;
|
||||
dht.temperature().getSensor(&sensor);
|
||||
Serial.println(F("------------------------------------"));
|
||||
Serial.println(F("Temperature Sensor"));
|
||||
Serial.print (F("Sensor Type: ")); Serial.println(sensor.name);
|
||||
Serial.print (F("Driver Ver: ")); Serial.println(sensor.version);
|
||||
Serial.print (F("Unique ID: ")); Serial.println(sensor.sensor_id);
|
||||
Serial.print (F("Max Value: ")); Serial.print(sensor.max_value); Serial.println(F("°C"));
|
||||
Serial.print (F("Min Value: ")); Serial.print(sensor.min_value); Serial.println(F("°C"));
|
||||
Serial.print (F("Resolution: ")); Serial.print(sensor.resolution); Serial.println(F("°C"));
|
||||
Serial.println(F("------------------------------------"));
|
||||
// Print humidity sensor details.
|
||||
dht.humidity().getSensor(&sensor);
|
||||
Serial.println(F("Humidity Sensor"));
|
||||
Serial.print (F("Sensor Type: ")); Serial.println(sensor.name);
|
||||
Serial.print (F("Driver Ver: ")); Serial.println(sensor.version);
|
||||
Serial.print (F("Unique ID: ")); Serial.println(sensor.sensor_id);
|
||||
Serial.print (F("Max Value: ")); Serial.print(sensor.max_value); Serial.println(F("%"));
|
||||
Serial.print (F("Min Value: ")); Serial.print(sensor.min_value); Serial.println(F("%"));
|
||||
Serial.print (F("Resolution: ")); Serial.print(sensor.resolution); Serial.println(F("%"));
|
||||
Serial.println(F("------------------------------------"));
|
||||
|
||||
// LMIC init
|
||||
os_init();
|
||||
// Reset the MAC state. Session and pending data transfers will be discarded.
|
||||
LMIC_reset();
|
||||
|
||||
// allow much more clock error than the X/1000 default. See:
|
||||
// https://github.com/mcci-catena/arduino-lorawan/issues/74#issuecomment-462171974
|
||||
// https://github.com/mcci-catena/arduino-lmic/commit/42da75b56#diff-16d75524a9920f5d043fe731a27cf85aL633
|
||||
// the X/1000 means an error rate of 0.1%; the above issue discusses using
|
||||
// values up to 10%. so, values from 10 (10% error, the most lax) to 1000
|
||||
// (0.1% error, the most strict) can be used.
|
||||
LMIC_setClockError(1 * MAX_CLOCK_ERROR / 40);
|
||||
|
||||
// Sub-band 2 - Helium Network
|
||||
LMIC_selectSubBand(1); // zero indexed
|
||||
LMIC_setLinkCheckMode(0);
|
||||
LMIC_setDrTxpow(DR_SF7, 14);
|
||||
|
||||
// Start job (sending automatically starts OTAA too)
|
||||
do_send(&sendjob);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
os_runloop_once();
|
||||
}
|
Ładowanie…
Reference in New Issue