/***
* PEPNOUN_SKID_01
* Device will send uplink every 20 seconds.
***/
#include "rak1906.h"
#include "rak1910.h"
rak1910 rak1910;
rak1906 rak1906;
#define LED_BUILTIN1 35
#define LED_BUILTIN2 36
#define MAX_SIZE 100
#define OTAA_PERIOD (20000)
/*************************************
LoRaWAN band setting:
RAK_REGION_EU433
RAK_REGION_CN470
RAK_REGION_RU864
RAK_REGION_IN865
RAK_REGION_EU868
RAK_REGION_US915
RAK_REGION_AU915
RAK_REGION_KR920
RAK_REGION_AS923
*************************************/
#define OTAA_BAND (RAK_REGION_EU868)
#define OTAA_DEVEUI {0xAC, 0x1F, 0x09, 0xFF, 0xFE, 0x08, 0x6C, 0x3D}
#define OTAA_APPEUI {0xAC, 0x1F, 0x09, 0xFF, 0xFE, 0x08, 0x6C, 0x3D}
#define OTAA_APPKEY {0x8A, 0xE9, 0xA1, 0xA9, 0x30, 0xB0, 0x77, 0x57, 0x82, 0x93, 0x83, 0x3F, 0xDF, 0xCE, 0x97, 0xA6}
#define PIN_VBAT WB_A0
uint32_t vbat_pin = PIN_VBAT;
#define VBAT_MV_PER_LSB (0.73242188F) // 3.0V ADC range and 12-bit ADC resolution = 3000mV/4096
#define VBAT_DIVIDER (0.4F) // 1.5M + 1M voltage divider on VBAT = (1.5M / (1M + 1.5M))
#define VBAT_DIVIDER_COMP (1.73) // (1.403F) // Compensation factor for the VBAT divider
#define REAL_VBAT_MV_PER_LSB (VBAT_DIVIDER_COMP * VBAT_MV_PER_LSB)
float readVBAT(void)
{
float raw;
raw = analogRead(vbat_pin);
return raw * REAL_VBAT_MV_PER_LSB;
}
uint8_t mvToPercent(float mvolts)
{
if (mvolts < 3300)
return 0;
if (mvolts < 3600)
{
mvolts -= 3300;
return mvolts / 30;
}
mvolts -= 3600;
return 10 + (mvolts * 0.15F);
}
uint8_t mvToLoRaWanBattVal(float mvolts)
{
if (mvolts < 3300)
return 0;
if (mvolts < 3600)
{
mvolts -= 3300;
return mvolts / 30 * 2.55;
}
mvolts -= 3600;
return (10 + (mvolts * 0.15F)) * 2.55;
}
uint8_t collected_data[64] = { 0 };
void recvCallback(SERVICE_LORA_RECEIVE_T * data)
{
if (data->BufferSize > 0) {
Serial.println("Something received!");
for (int i = 0; i < data->BufferSize; i++) {
Serial.printf("%x", data->Buffer[i]);
}
Serial.print("\r\n");
}
}
void joinCallback(int32_t status)
{
Serial.printf("Join status: %d\r\n", status);
}
/*************************************
* enum type for LoRa Event
RAK_LORAMAC_STATUS_OK = 0,
RAK_LORAMAC_STATUS_ERROR,
RAK_LORAMAC_STATUS_TX_TIMEOUT,
RAK_LORAMAC_STATUS_RX1_TIMEOUT,
RAK_LORAMAC_STATUS_RX2_TIMEOUT,
RAK_LORAMAC_STATUS_RX1_ERROR,
RAK_LORAMAC_STATUS_RX2_ERROR,
RAK_LORAMAC_STATUS_JOIN_FAIL,
RAK_LORAMAC_STATUS_DOWNLINK_REPEATED,
RAK_LORAMAC_STATUS_TX_DR_PAYLOAD_SIZE_ERROR,
RAK_LORAMAC_STATUS_DOWNLINK_TOO_MANY_FRAMES_LOSS,
RAK_LORAMAC_STATUS_ADDRESS_FAIL,
RAK_LORAMAC_STATUS_MIC_FAIL,
RAK_LORAMAC_STATUS_MULTICAST_FAIL,
RAK_LORAMAC_STATUS_BEACON_LOCKED,
RAK_LORAMAC_STATUS_BEACON_LOST,
RAK_LORAMAC_STATUS_BEACON_NOT_FOUND,
*************************************/
void sendCallback(int32_t status)
{
if (status == RAK_LORAMAC_STATUS_OK) {
Serial.println("Successfully sent");
} else {
Serial.println("Sending failed");
}
}
void setup()
{
pinMode(LED_BUILTIN1, OUTPUT);
pinMode(LED_BUILTIN2, OUTPUT);
digitalWrite(LED_BUILTIN1, HIGH);
digitalWrite(LED_BUILTIN2, HIGH);
Serial.begin(115200, RAK_AT_MODE);
delay(2000);
Wire.begin();
Serial.printf("RAK1906 init %s\r\n", rak1906.init() ? "Success" : "Fail");
rak1910.init();
Serial.printf("RAK1910 init %s\r\n", rak1910.init() ? "Success" : "Fail");
Serial.println("Pepnoun Node 1 : Skid No.1");
Serial.println("------------------------------------------------------");
if(api.lorawan.nwm.get() != 1)
{
Serial.printf("Set Node device work mode %s\r\n",
api.lorawan.nwm.set(1) ? "Success" : "Fail");
api.system.reboot();
}
// OTAA Device EUI MSB first
uint8_t node_device_eui[8] = OTAA_DEVEUI;
// OTAA Application EUI MSB first
uint8_t node_app_eui[8] = OTAA_APPEUI;
// OTAA Application Key MSB first
uint8_t node_app_key[16] = OTAA_APPKEY;
if (!api.lorawan.appeui.set(node_app_eui, 8)) {
Serial.printf("LoRaWan OTAA - set application EUI is incorrect! \r\n");
return;
}
if (!api.lorawan.appkey.set(node_app_key, 16)) {
Serial.printf("LoRaWan OTAA - set application key is incorrect! \r\n");
return;
}
if (!api.lorawan.deui.set(node_device_eui, 8)) {
Serial.printf("LoRaWan OTAA - set device EUI is incorrect! \r\n");
return;
}
if (!api.lorawan.band.set(OTAA_BAND)) {
Serial.printf("LoRaWan OTAA - set band is incorrect! \r\n");
return;
}
if (!api.lorawan.deviceClass.set(RAK_LORA_CLASS_A)) {
Serial.printf("LoRaWan OTAA - set device class is incorrect! \r\n");
return;
}
if (!api.lorawan.njm.set(RAK_LORA_OTAA))
{
Serial.printf("LoRaWan OTAA - set network join mode is incorrect! \r\n");
return;
}
if (!api.lorawan.join())
{
Serial.printf("LoRaWan OTAA - join fail! \r\n");
return;
}
/** Wait for Join success */
while (api.lorawan.njs.get() == 0) {
Serial.print("Wait for LoRaWAN join...");
api.lorawan.join();
delay(10000);
}
if (!api.lorawan.adr.set(true)) {
Serial.printf("LoRaWan OTAA - set adaptive data rate is incorrect! \r\n");
return;
}
if (!api.lorawan.rety.set(1)) {
Serial.printf("LoRaWan OTAA - set retry times is incorrect! \r\n");
return;
}
if (!api.lorawan.cfm.set(1)) {
Serial.printf("LoRaWan OTAA - set confirm mode is incorrect! \r\n");
return;
}
Serial.printf("Duty cycle is %s\r\n", api.lorawan.dcs.get()? "ON" : "OFF");
Serial.printf("Packet is %s\r\n", api.lorawan.cfm.get()? "CONFIRMED" : "UNCONFIRMED");
uint8_t assigned_dev_addr[4] = { 0 };
api.lorawan.daddr.get(assigned_dev_addr, 4);
Serial.printf("Device Address is %02X%02X%02X%02X\r\n", assigned_dev_addr[0], assigned_dev_addr[1], assigned_dev_addr[2], assigned_dev_addr[3]); // Check Device Address
Serial.printf("Uplink period is %ums\r\n", OTAA_PERIOD);
Serial.println("");
api.lorawan.registerRecvCallback(recvCallback);
api.lorawan.registerJoinCallback(joinCallback);
api.lorawan.registerSendCallback(sendCallback);
analogReference(AR_INTERNAL_3_0);
//analogResolution(12);
delay(1);
readVBAT();
digitalWrite(LED_BUILTIN1, LOW);
digitalWrite(LED_BUILTIN2, LOW);
}
void addInt32ToData(uint8_t* data, uint8_t* length, int32_t value) {
// Add each byte of the int32_t to the array
data[(*length)++] = (value >> 24) & 0xFF;
data[(*length)++] = (value >> 16) & 0xFF;
data[(*length)++] = (value >> 8) & 0xFF;
data[(*length)++] = value & 0xFF;
}
void uplink_routine()
{
digitalWrite(LED_BUILTIN1, HIGH); // Turn on LED1
digitalWrite(LED_BUILTIN2, HIGH); // Turn on LED2
// Read battery voltage
float vbat_mv = readVBAT();
int32_t vbat = static_cast<int32_t>(vbat_mv); // Convert to integer
// Read GPS data
float lat = rak1910.latitude();
float lon = rak1910.longitude();
int32_t lat_fixed = static_cast<int32_t>(lat * 1000000); // Convert to integer
int32_t lon_fixed = static_cast<int32_t>(lon * 1000000); // Convert to integer
// Read other sensor data
float temperature = rak1906.temperature();
float humidity = rak1906.humidity();
uint8_t temp = static_cast<uint8_t>(temperature * 10); // Convert to integer
uint8_t hum = static_cast<uint8_t>(humidity * 10); // Convert to integer
// Prepare data packet
uint8_t data_len = 0;
addInt32ToData(collected_data, &data_len, vbat); // Corrected function call
addInt32ToData(collected_data, &data_len, lat_fixed);
addInt32ToData(collected_data, &data_len, lon_fixed);
if (data_len < MAX_SIZE) collected_data[data_len++] = hum;
if (data_len < MAX_SIZE) collected_data[data_len++] = temp;
// Send data
if (api.lorawan.send(data_len, (uint8_t *) & collected_data, 2, true, 1)) {
Serial.println("Sending is requested");
} else {
Serial.println("Sending failed");
}
digitalWrite(LED_BUILTIN1, LOW); // Turn off LED1
digitalWrite(LED_BUILTIN2, LOW); // Turn off LED2
}
void addInt16ToData(uint8_t* data, uint8_t* length, int16_t value) {
data[(*length)++] = (value >> 8) & 0xFF;
data[(*length)++] = value & 0xFF;
}
void loop()
{
static uint64_t last = 0;
static uint64_t elapsed;
if ((elapsed = millis() - last) > OTAA_PERIOD) {
uplink_routine();
last = millis();
}
//Serial.printf("Try sleep %ums..", OTAA_PERIOD);
api.system.sleep.all(OTAA_PERIOD);
//Serial.println("Wakeup..");
}