Hi folks!
I built my own node with arduino pro mini (atmega 328P), RFM95 and DS18D20. I don’t use deep sleep mode but TPL5551 (Nano-Power System Timer for Power Gating) by TI. I am using this code from my county member who gave me his code. (This code works for him).
Click here to see code
/*******************************************************************************
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 will send Temperature and Air Pressure
using frequency and encryption settings matching those of
the The Things Network. Application will 'sleep' 7x8 seconds (56 seconds)
This uses ABP (Activation-by-personalisation), where a DevAddr and
Session keys are preconfigured (unlike OTAA, where a DevEUI and
application key is configured, while the DevAddr and session keys are
assigned/generated in the over-the-air-activation procedure).
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.
Adapted by A.Jenerts
*******************************************************************************/
#include <avr/wdt.h>
#include <lmic.h>
#include <hal/hal.h>
#include <SPI.h>
#include "LoraEncoder.h"
#include <EEPROM.h>
#include <OneWire.h>
#include <DallasTemperature.h>
const int batteryCheck = A0; // ADC pin that read battery level (3 pin)
const int DONE = 2; // pool this pin HIGH when uplink is done. (2 pin)
const int LedPin = A2; // on board LED
const int DS18B20Pin = 6; //define to what pin temperature sensor is connected
const int counterEEPROMaddress = 0; // adress where counter is store on EEPORM
bool joined = false;
bool done = false;
// LoRaWAN NwkSKey, network session key
static const PROGMEM u1_t NWKSKEY[16] = { 0xF1, 0x4F, 0x27, 0x25, 0x6A, 0x46, 0xBA, 0x85, 0x21, 0x79, 0x3D, 0x9C, 0xD8, 0x52, 0xF4, 0xFC };
static const PROGMEM u1_t APPSKEY[16] = { 0x34, 0x0A, 0x5E, 0x4C, 0x6D, 0xB9, 0xDE, 0xC7, 0x44, 0x66, 0x60, 0x61, 0x99, 0x58, 0x53, 0xD2 };
// LoRaWAN end-device address (DevAddr)
static const u4_t DEVADDR = 26011E62 ;
// These callbacks are only used in over-the-air activation, so they are
// left empty here (we cannot leave them out completely unless
// DISABLE_JOIN is set in config.h, otherwise the linker will complain).
void os_getArtEui (u1_t* buf) { }
void os_getDevEui (u1_t* buf) { }
void os_getDevKey (u1_t* buf) { }
static osjob_t sendjob;
static osjob_t initjob;
// Pin mapping is hardware specific.
const lmic_pinmap lmic_pins = {
.nss = 10,
.rxtx = LMIC_UNUSED_PIN,
.rst = 9,
.dio = {7,8, LMIC_UNUSED_PIN },
};
// setup one wire interface
OneWire oneWire(DS18B20Pin);
// create temperature sensor object
DallasTemperature TempSens(&oneWire);
void do_send(osjob_t* j) {
digitalWrite(LedPin, LOW); //pools led low when data reading is started
byte buffer[4]; // buffer for storing values for sending
LoraEncoder encoder(buffer);
encoder.writeUint16(analogRead(batteryCheck)); //adds value to buffer
TempSens.requestTemperatures(); // Send the command to get temperatures
encoder.writeTemperature(TempSens.getTempCByIndex(0)); // saves temprature from DS18B20 to buffer
digitalWrite(LedPin, HIGH); // indicated that data has been read and decoded
// Check if there is not a current TX/RX job running
if (LMIC.opmode & OP_TXRXPEND) {
Serial.println(F("OP_TXRXPEND, not sending"));
}
else {
// Prepare upstream data transmission at the next possible time.
LMIC_setTxData2(1, buffer, sizeof(buffer), 0);
}
}
void setup()
{
Serial.begin(57600);
TempSens.begin();
pinMode(LedPin, OUTPUT);
pinMode(DONE, OUTPUT);
digitalWrite(LedPin, HIGH);
// LMIC init
os_init();
// Reset the MAC state. Session and pending data transfers will be discarded.
LMIC_reset();
// Set static session parameters. Instead of dynamically establishing a session
// by joining the network, precomputed session parameters are be provided.
uint8_t appskey[sizeof(APPSKEY)];
uint8_t nwkskey[sizeof(NWKSKEY)];
memcpy_P(appskey, APPSKEY, sizeof(APPSKEY));
memcpy_P(nwkskey, NWKSKEY, sizeof(NWKSKEY));
LMIC_setSession (0x1, DEVADDR, nwkskey, appskey);
#if defined(CFG_eu868)
LMIC_setupChannel(0, 868100000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band
LMIC_setupChannel(1, 868300000, DR_RANGE_MAP(DR_SF12, DR_SF7B), BAND_CENTI); // g-band
LMIC_setupChannel(2, 868500000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band
LMIC_setupChannel(3, 867100000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band
LMIC_setupChannel(4, 867300000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band
LMIC_setupChannel(5, 867500000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band
LMIC_setupChannel(6, 867700000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band
LMIC_setupChannel(7, 867900000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band
LMIC_setupChannel(8, 868800000, DR_RANGE_MAP(DR_FSK, DR_FSK), BAND_MILLI); // g2-band
#elif defined(CFG_us915)
LMIC_selectSubBand(1);
#endif
/*
//disable all but one channel
for (int channel = 1; channel < 8; channel++) {
LMIC_disableChannel(channel);
}
*/
// Disable link check validation
LMIC_setLinkCheckMode(0);
// TTN uses SF9 for its RX2 window.
LMIC.dn2Dr = DR_SF9;
// Set data rate and transmit power for uplink (note: txpow seems to be ignored by the library)
LMIC_setDrTxpow(DR_SF7, 14);
LMIC.seqnoUp = EEPROMReadCounter(counterEEPROMaddress);
}
void loop() {
do_send(&sendjob); // Sent sensor values
while (done == false)
{
digitalWrite(LedPin, HIGH);
os_runloop_once();
}
done = false;
digitalWrite(LedPin, LOW);
delay(10);
//save new counter
EEPROMWriteCounter(counterEEPROMaddress, (EEPROMReadCounter(counterEEPROMaddress) + 1) );
digitalWrite(LedPin, HIGH);
delay(30);
//siganl TPL5111 to de assert DRVn line
digitalWrite(DONE, HIGH);
}
long EEPROMReadCounter(long address)
{
//Read the 4 bytes from the eeprom memory.
long four = EEPROM.read(address);
long three = EEPROM.read(address + 1);
long two = EEPROM.read(address + 2);
long one = EEPROM.read(address + 3);
//Return the recomposed long by using bitshift.
return ((four << 0) & 0xFF) + ((three << 8) & 0xFFFF) + ((two << 16) & 0xFFFFFF) + ((one << 24) & 0xFFFFFFFF);
}
void EEPROMWriteCounter(int address, unsigned long value)
{
byte four = (value & 0xFF);
byte three = ((value >> 8) & 0xFF);
byte two = ((value >> 16) & 0XFF);
byte one = ((value >> 24) & 0xFF);
EEPROM.write(address, four);
EEPROM.write(address + 1, three);
EEPROM.write(address + 2, two);
EEPROM.write(address + 3, one);
}
void onEvent (ev_t ev) {
int i, j;
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);
// after Joining a job with the values will be sent.
joined = true;
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"));
// Re-init
os_setCallback(&initjob, initfunc);
break;
case EV_TXCOMPLETE:
done = true;
if (LMIC.dataLen) {
// data received in rx slot after tx
// if any data received, a LED will blink
// this number of times, with a maximum of 10
Serial.print(F("Data Received: "));
Serial.println(LMIC.frame[LMIC.dataBeg], HEX);
i = (LMIC.frame[LMIC.dataBeg]);
}
Serial.println(F("EV_TXCOMPLETE (includes waiting for RX windows)"));
delay(50); // delay to complete Serial Output before Sleeping
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;
}
}
// initial job
static void initfunc (osjob_t* j) {
// reset MAC state
LMIC_reset();
// start joining
LMIC_startJoining();
// init done - onEvent() callback will be invoked...
}
Here is my schematical:
Schematic_LoRa-Wan-Atmega-328P-RFM95W-Node.v.1.1.pdf (53.7 KB)
I added my node in TTN aplications by ABP activation mode. When my node tried to send data I have “EV_RESET” and I can’t figure out what is the reason.
I don’t change setups at config.h, because default was good for me.