housekeeping

This commit is contained in:
Timm Bogner 2022-06-30 08:30:24 -05:00
parent 3856518c8b
commit 21c1b4be59
41 changed files with 1496 additions and 1612 deletions

View File

@ -8,23 +8,20 @@
#include "fdrs_sensor.h"
#include "sensor_setup.h"
FDRSLoRa FDRS(GTWY_MAC,READING_ID,MISO,MOSI,SCK,SS,RST,DIO0,BAND,SF);
float data1;
float data2;
void setup() {
FDRS.begin();
beginFDRS();
}
void loop() {
data1 = readHum();
FDRS.load(data1, HUMIDITY_T);
loadFDRS(data1, HUMIDITY_T);
data2 = readTemp();
FDRS.load(data2, TEMP_T);
FDRS.send();
FDRS.sleep(10); //Sleep time in seconds
loadFDRS(data2, TEMP_T);
sendFDRS();
sleepFDRS(10); //Sleep time in seconds
}
float readTemp() {

View File

@ -0,0 +1,178 @@
// FARM DATA RELAY SYSTEM
//
// "fdrs_sensor.h"
//
// Developed by Timm Bogner (timmbogner@gmail.com) for Sola Gratia Farm in Urbana, Illinois, USA.
//
#include "sensor_setup.h"
#if defined(ESP8266)
#include <ESP8266WiFi.h>
#include <espnow.h>
#elif defined(ESP32)
#include <esp_now.h>
#include <WiFi.h>
#include <esp_wifi.h>
#endif
#ifdef USE_LORA
#include <LoRa.h>
#endif
#ifdef GLOBALS
#define FDRS_BAND GLOBAL_BAND
#define FDRS_SF GLOBAL_SF
#else
#define FDRS_BAND BAND
#define FDRS_SF SF
#endif
#ifdef DEBUG
#define DBG(a) (Serial.println(a))
#else
#define DBG(a)
#endif
#define STATUS_T 0 // Status
#define TEMP_T 1 // Temperature
#define TEMP2_T 2 // Temperature #2
#define HUMIDITY_T 3 // Relative Humidity
#define PRESSURE_T 4 // Atmospheric Pressure
#define LIGHT_T 5 // Light (lux)
#define SOIL_T 6 // Soil Moisture
#define SOIL2_T 7 // Soil Moisture #2
#define SOILR_T 8 // Soil Resistance
#define SOILR2_T 9 // Soil Resistance #2
#define OXYGEN_T 10 // Oxygen
#define CO2_T 11 // Carbon Dioxide
#define WINDSPD_T 12 // Wind Speed
#define WINDHDG_T 13 // Wind Direction
#define RAINFALL_T 14 // Rainfall
#define MOTION_T 15 // Motion
#define VOLTAGE_T 16 // Voltage
#define VOLTAGE2_T 17 // Voltage #2
#define CURRENT_T 18 // Current
#define CURRENT2_T 19 // Current #2
#define IT_T 20 // Iterations
#define MAC_PREFIX 0xAA, 0xBB, 0xCC, 0xDD, 0xEE // Should only be changed if implementing multiple FDRS systems.
typedef struct __attribute__((packed)) DataReading {
float d;
uint16_t id;
uint8_t t;
} DataReading;
const uint16_t espnow_size = 250 / sizeof(DataReading);
uint8_t gatewayAddress[] = {MAC_PREFIX, GTWY_MAC};
uint8_t gtwyAddress[] = {gatewayAddress[3], gatewayAddress[4], GTWY_MAC};
uint8_t LoRaAddress[] = {0x42, 0x00};
uint32_t wait_time = 0;
DataReading fdrsData[espnow_size];
uint8_t data_count = 0;
void beginFDRS() {
#ifdef DEBUG
Serial.begin(115200);
#endif
DBG("FDRS Sensor ID " + String(READING_ID) + " initializing...");
DBG(" Gateway: " + String (GTWY_MAC, HEX));
#ifdef POWER_CTRL
DBG("Powering up the sensor array!");
pinMode(POWER_CTRL, OUTPUT);
digitalWrite(POWER_CTRL, 1);
#endif
// Init ESP-NOW for either ESP8266 or ESP32 and set MAC address
#ifdef USE_ESPNOW
DBG("Initializing ESP-NOW!");
WiFi.mode(WIFI_STA);
WiFi.disconnect();
#if defined(ESP8266)
if (esp_now_init() != 0) {
return;
}
esp_now_set_self_role(ESP_NOW_ROLE_COMBO);
// Register peers
esp_now_add_peer(gatewayAddress, ESP_NOW_ROLE_COMBO, 0, NULL, 0);
#elif defined(ESP32)
if (esp_now_init() != ESP_OK) {
DBG("Error initializing ESP-NOW");
return;
}
esp_now_peer_info_t peerInfo;
peerInfo.ifidx = WIFI_IF_STA;
peerInfo.channel = 0;
peerInfo.encrypt = false;
// Register first peer
memcpy(peerInfo.peer_addr, gatewayAddress, 6);
if (esp_now_add_peer(&peerInfo) != ESP_OK) {
DBG("Failed to add peer");
return;
}
#endif
DBG(" ESP-NOW Initialized.");
#endif
#ifdef USE_LORA
DBG("Initializing LoRa!");
DBG(BAND);
DBG(SF);
#ifndef __AVR__
SPI.begin(SCK, MISO, MOSI, SS);
#endif
LoRa.setPins(SS, RST, DIO0);
if (!LoRa.begin(FDRS_BAND)) {
while (1);
}
LoRa.setSpreadingFactor(FDRS_SF);
DBG(" LoRa Initialized.");
#endif
}
void transmitLoRa(uint8_t* mac, DataReading * packet, uint8_t len) {
#ifdef USE_LORA
uint8_t pkt[5 + (len * sizeof(DataReading))];
memcpy(&pkt, mac, 3); //
memcpy(&pkt[3], &LoRaAddress, 2);
memcpy(&pkt[5], packet, len * sizeof(DataReading));
LoRa.beginPacket();
LoRa.write((uint8_t*)&pkt, sizeof(pkt));
LoRa.endPacket();
#endif
}
void sendFDRS() {
DBG("Sending FDRS Packet!");
#ifdef USE_ESPNOW
esp_now_send(gatewayAddress, (uint8_t *) &fdrsData, data_count * sizeof(DataReading));
delay(5);
DBG(" ESP-NOW sent.");
#endif
#ifdef USE_LORA
transmitLoRa(gtwyAddress, fdrsData, data_count);
DBG(" LoRa sent.");
#endif
data_count = 0;
}
void loadFDRS(float d, uint8_t t) {
DBG("Data loaded. Type: " + String(t));
if (data_count > espnow_size) sendFDRS();
DataReading dr;
dr.id = READING_ID;
dr.t = t;
dr.d = d;
fdrsData[data_count] = dr;
data_count++;
}
void sleepFDRS(int sleep_time) {
DBG("Sleepytime!");
#ifdef DEEP_SLEEP
DBG(" Deep sleeping.");
#ifdef ESP32
esp_sleep_enable_timer_wakeup(sleep_time * 1000000);
esp_deep_sleep_start();
#endif
#ifdef ESP8266
ESP.deepSleep(sleep_time * 1000000);
#endif
#endif
DBG(" Delaying.");
delay(sleep_time * 1000);
}

View File

@ -9,6 +9,8 @@
#define READING_ID 1 //Unique ID for this sensor
#define GTWY_MAC 0x04 //Address of the nearest gateway
//#define USE_ESPNOW
#define USE_LORA
#define DEEP_SLEEP
//#define POWER_CTRL 14
#define DEBUG

View File

@ -7,23 +7,20 @@
//
#include "fdrs_sensor.h"
#include "sensor_setup.h"
float data1;
float data2;
FDRS_EspNow FDRS(GTWY_MAC,READING_ID);
void setup() {
FDRS.begin();
beginFDRS();
}
void loop() {
data1 = readHum();
FDRS.load(data1, HUMIDITY_T);
data2 = readTemp();
FDRS.load(data2, TEMP_T);
FDRS.send();
FDRS.sleep(10); //Sleep time in seconds
data1 = readHum();
loadFDRS(data1, HUMIDITY_T);
data2 = readTemp();
loadFDRS(data2, TEMP_T);
sendFDRS();
sleepFDRS(10); //Sleep time in seconds
}
float readTemp() {

View File

@ -0,0 +1,178 @@
// FARM DATA RELAY SYSTEM
//
// "fdrs_sensor.h"
//
// Developed by Timm Bogner (timmbogner@gmail.com) for Sola Gratia Farm in Urbana, Illinois, USA.
//
#include "sensor_setup.h"
#if defined(ESP8266)
#include <ESP8266WiFi.h>
#include <espnow.h>
#elif defined(ESP32)
#include <esp_now.h>
#include <WiFi.h>
#include <esp_wifi.h>
#endif
#ifdef USE_LORA
#include <LoRa.h>
#endif
#ifdef GLOBALS
#define FDRS_BAND GLOBAL_BAND
#define FDRS_SF GLOBAL_SF
#else
#define FDRS_BAND BAND
#define FDRS_SF SF
#endif
#ifdef DEBUG
#define DBG(a) (Serial.println(a))
#else
#define DBG(a)
#endif
#define STATUS_T 0 // Status
#define TEMP_T 1 // Temperature
#define TEMP2_T 2 // Temperature #2
#define HUMIDITY_T 3 // Relative Humidity
#define PRESSURE_T 4 // Atmospheric Pressure
#define LIGHT_T 5 // Light (lux)
#define SOIL_T 6 // Soil Moisture
#define SOIL2_T 7 // Soil Moisture #2
#define SOILR_T 8 // Soil Resistance
#define SOILR2_T 9 // Soil Resistance #2
#define OXYGEN_T 10 // Oxygen
#define CO2_T 11 // Carbon Dioxide
#define WINDSPD_T 12 // Wind Speed
#define WINDHDG_T 13 // Wind Direction
#define RAINFALL_T 14 // Rainfall
#define MOTION_T 15 // Motion
#define VOLTAGE_T 16 // Voltage
#define VOLTAGE2_T 17 // Voltage #2
#define CURRENT_T 18 // Current
#define CURRENT2_T 19 // Current #2
#define IT_T 20 // Iterations
#define MAC_PREFIX 0xAA, 0xBB, 0xCC, 0xDD, 0xEE // Should only be changed if implementing multiple FDRS systems.
typedef struct __attribute__((packed)) DataReading {
float d;
uint16_t id;
uint8_t t;
} DataReading;
const uint16_t espnow_size = 250 / sizeof(DataReading);
uint8_t gatewayAddress[] = {MAC_PREFIX, GTWY_MAC};
uint8_t gtwyAddress[] = {gatewayAddress[3], gatewayAddress[4], GTWY_MAC};
uint8_t LoRaAddress[] = {0x42, 0x00};
uint32_t wait_time = 0;
DataReading fdrsData[espnow_size];
uint8_t data_count = 0;
void beginFDRS() {
#ifdef DEBUG
Serial.begin(115200);
#endif
DBG("FDRS Sensor ID " + String(READING_ID) + " initializing...");
DBG(" Gateway: " + String (GTWY_MAC, HEX));
#ifdef POWER_CTRL
DBG("Powering up the sensor array!");
pinMode(POWER_CTRL, OUTPUT);
digitalWrite(POWER_CTRL, 1);
#endif
// Init ESP-NOW for either ESP8266 or ESP32 and set MAC address
#ifdef USE_ESPNOW
DBG("Initializing ESP-NOW!");
WiFi.mode(WIFI_STA);
WiFi.disconnect();
#if defined(ESP8266)
if (esp_now_init() != 0) {
return;
}
esp_now_set_self_role(ESP_NOW_ROLE_COMBO);
// Register peers
esp_now_add_peer(gatewayAddress, ESP_NOW_ROLE_COMBO, 0, NULL, 0);
#elif defined(ESP32)
if (esp_now_init() != ESP_OK) {
DBG("Error initializing ESP-NOW");
return;
}
esp_now_peer_info_t peerInfo;
peerInfo.ifidx = WIFI_IF_STA;
peerInfo.channel = 0;
peerInfo.encrypt = false;
// Register first peer
memcpy(peerInfo.peer_addr, gatewayAddress, 6);
if (esp_now_add_peer(&peerInfo) != ESP_OK) {
DBG("Failed to add peer");
return;
}
#endif
DBG(" ESP-NOW Initialized.");
#endif
#ifdef USE_LORA
DBG("Initializing LoRa!");
DBG(BAND);
DBG(SF);
#ifndef __AVR__
SPI.begin(SCK, MISO, MOSI, SS);
#endif
LoRa.setPins(SS, RST, DIO0);
if (!LoRa.begin(FDRS_BAND)) {
while (1);
}
LoRa.setSpreadingFactor(FDRS_SF);
DBG(" LoRa Initialized.");
#endif
}
void transmitLoRa(uint8_t* mac, DataReading * packet, uint8_t len) {
#ifdef USE_LORA
uint8_t pkt[5 + (len * sizeof(DataReading))];
memcpy(&pkt, mac, 3); //
memcpy(&pkt[3], &LoRaAddress, 2);
memcpy(&pkt[5], packet, len * sizeof(DataReading));
LoRa.beginPacket();
LoRa.write((uint8_t*)&pkt, sizeof(pkt));
LoRa.endPacket();
#endif
}
void sendFDRS() {
DBG("Sending FDRS Packet!");
#ifdef USE_ESPNOW
esp_now_send(gatewayAddress, (uint8_t *) &fdrsData, data_count * sizeof(DataReading));
delay(5);
DBG(" ESP-NOW sent.");
#endif
#ifdef USE_LORA
transmitLoRa(gtwyAddress, fdrsData, data_count);
DBG(" LoRa sent.");
#endif
data_count = 0;
}
void loadFDRS(float d, uint8_t t) {
DBG("Data loaded. Type: " + String(t));
if (data_count > espnow_size) sendFDRS();
DataReading dr;
dr.id = READING_ID;
dr.t = t;
dr.d = d;
fdrsData[data_count] = dr;
data_count++;
}
void sleepFDRS(int sleep_time) {
DBG("Sleepytime!");
#ifdef DEEP_SLEEP
DBG(" Deep sleeping.");
#ifdef ESP32
esp_sleep_enable_timer_wakeup(sleep_time * 1000000);
esp_deep_sleep_start();
#endif
#ifdef ESP8266
ESP.deepSleep(sleep_time * 1000000);
#endif
#endif
DBG(" Delaying.");
delay(sleep_time * 1000);
}

View File

@ -10,4 +10,20 @@
#define GTWY_MAC 0x03 //Address of the nearest gateway
#define USE_ESPNOW
//#define USE_LORA
#define DEEP_SLEEP
//#define POWER_CTRL 14
#define DEBUG
//LoRa Configuration
#define SCK 5
#define MISO 19
#define MOSI 27
#define SS 18
#define RST 14
#define DIO0 26
//433E6 for Asia
//866E6 for Europe
//915E6 for North America
#define BAND 915E6
#define SF 7

View File

@ -1,3 +0,0 @@
Please copy this directory into your Arduino "libraries" directory.
Edit the files in your libraries folder according to your needs with your WiFi info, LoRa band, etc.
Never edit them here!!!

View File

@ -1,8 +0,0 @@
#define GLOBAL_SSID "Your SSID"
#define GLOBAL_PASS "Password"
#define GLOBAL_MQTT_ADDR "192.168.0.8"
#define GLOBAL_BAND 915E6 //LoRa Frequency Band
#define GLOBAL_SF 7 //LoRa Spreading Factor
#define GLOBALS

View File

@ -1,8 +1,8 @@
// FARM DATA RELAY SYSTEM
//
// GATEWAY 2.000
// Experimental Universal Gateway
//
// Developed by Timm Bogner (timmbogner@gmail.com) for Sola Gratia Farm in Urbana, Illinois, USA.
// Under construction, feedback is appreciated!
//
#include "fdrs_config.h"

View File

Before

Width:  |  Height:  |  Size: 228 KiB

After

Width:  |  Height:  |  Size: 228 KiB

View File

Before

Width:  |  Height:  |  Size: 238 KiB

After

Width:  |  Height:  |  Size: 238 KiB

View File

Before

Width:  |  Height:  |  Size: 241 KiB

After

Width:  |  Height:  |  Size: 241 KiB

View File

Before

Width:  |  Height:  |  Size: 221 KiB

After

Width:  |  Height:  |  Size: 221 KiB

View File

@ -1,169 +1,169 @@
// FARM DATA RELAY SYSTEM
//
// GATEWAY 2.000
//
// Developed by Timm Bogner (timmbogner@gmail.com) for Sola Gratia Farm in Urbana, Illinois, USA.
//
#include "fdrs_config.h"
#ifdef ESP8266
#include <ESP8266WiFi.h>
#include <espnow.h>
#elif defined(ESP32)
#include <esp_now.h>
#include <WiFi.h>
#include <esp_wifi.h>
#endif
#include <ArduinoJson.h>
#ifdef USE_WIFI
#include <PubSubClient.h>
#endif
#ifdef USE_LORA
#include <LoRa.h>
#endif
#ifdef USE_LED
#include <FastLED.h>
#endif
#include "fdrs_functions.h"
void setup() {
#if defined(ESP8266)
Serial.begin(115200);
#elif defined(ESP32)
Serial.begin(115200);
UART_IF.begin(115200, SERIAL_8N1, RXD2, TXD2);
#endif
DBG("Address:" + String (UNIT_MAC, HEX));
#ifdef USE_LED
FastLED.addLeds<WS2812B, LED_PIN, GRB>(leds, NUM_LEDS);
leds[0] = CRGB::Blue;
FastLED.show();
#endif
#ifdef USE_WIFI
delay(10);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
DBG("Connecting to WiFi...");
DBG(FDRS_WIFI_SSID);
delay(500);
}
DBG("WiFi Connected");
client.setServer(mqtt_server, mqtt_port);
if (!client.connected()) {
DBG("Connecting MQTT...");
reconnect();
}
DBG("MQTT Connected");
client.setCallback(mqtt_callback);
#else
begin_espnow();
#endif
#ifdef USE_LORA
DBG("Initializing LoRa!");
SPI.begin(SCK, MISO, MOSI, SS);
LoRa.setPins(SS, RST, DIO0);
if (!LoRa.begin(FDRS_BAND)) {
while (1);
}
LoRa.setSpreadingFactor(FDRS_SF);
DBG(" LoRa initialized.");
#endif
//DBG(sizeof(DataReading));
#ifdef USE_WIFI
client.publish(TOPIC_STATUS, "FDRS initialized");
#endif
}
void loop() {
#ifdef ESPNOWG_DELAY
if (millis() > timeESPNOWG) {
timeESPNOWG += ESPNOWG_DELAY;
if (lenESPNOWG > 0) releaseESPNOW(0);
}
#endif
#ifdef ESPNOW1_DELAY
if (millis() > timeESPNOW1) {
timeESPNOW1 += ESPNOW1_DELAY;
if (lenESPNOW1 > 0) releaseESPNOW(1);
}
#endif
#ifdef ESPNOW2_DELAY
if (millis() > timeESPNOW2) {
timeESPNOW2 += ESPNOW2_DELAY;
if (lenESPNOW2 > 0) releaseESPNOW(2);
}
#endif
#ifdef SERIAL_DELAY
if (millis() > timeSERIAL) {
timeSERIAL += SERIAL_DELAY;
if (lenSERIAL > 0) releaseSerial();
}
#endif
#ifdef MQTT_DELAY
if (millis() > timeMQTT) {
timeMQTT += MQTT_DELAY;
if (lenMQTT > 0) releaseMQTT();
}
#endif
#ifdef LORAG_DELAY
if (millis() > timeLORAG) {
timeLORAG += LORAG_DELAY;
if (lenLORAG > 0) releaseLoRa(0);
}
#endif
#ifdef LORA1_DELAY
if (millis() > timeLORA1) {
timeLORA1 += LORA1_DELAY;
if (lenLORA1 > 0) releaseLoRa(1);
}
#endif
#ifdef LORA2_DELAY
if (millis() > timeLORA2) {
timeLORA2 += LORA2_DELAY;
if (lenLORA2 > 0) releaseLoRa(2);
}
#endif
while (UART_IF.available()) {
getSerial();
}
getLoRa();
#ifdef USE_WIFI
if (!client.connected()) {
DBG("Connecting MQTT...");
reconnect();
}
client.loop();
#endif
if (newData) {
switch (newData) {
case 1: //ESP-NOW #1
ESPNOW1_ACT
break;
case 2: //ESP-NOW #2
ESPNOW2_ACT
break;
case 3: //ESP-NOW General
ESPNOWG_ACT
break;
case 4: //Serial
SERIAL_ACT
break;
case 5: //MQTT
MQTT_ACT
break;
case 6: //LoRa General
LORAG_ACT
break;
case 7: //LoRa #1
LORA1_ACT
break;
case 8: //LoRa #2
LORA2_ACT
break;
}
newData = 0;
}
}
// FARM DATA RELAY SYSTEM
//
// GATEWAY 2.000
//
// Developed by Timm Bogner (timmbogner@gmail.com) for Sola Gratia Farm in Urbana, Illinois, USA.
//
#include "fdrs_config.h"
#ifdef ESP8266
#include <ESP8266WiFi.h>
#include <espnow.h>
#elif defined(ESP32)
#include <esp_now.h>
#include <WiFi.h>
#include <esp_wifi.h>
#endif
#include <ArduinoJson.h>
#ifdef USE_WIFI
#include <PubSubClient.h>
#endif
#ifdef USE_LORA
#include <LoRa.h>
#endif
#ifdef USE_LED
#include <FastLED.h>
#endif
#include "fdrs_functions.h"
void setup() {
#if defined(ESP8266)
Serial.begin(115200);
#elif defined(ESP32)
Serial.begin(115200);
UART_IF.begin(115200, SERIAL_8N1, RXD2, TXD2);
#endif
DBG("Address:" + String (UNIT_MAC, HEX));
#ifdef USE_LED
FastLED.addLeds<WS2812B, LED_PIN, GRB>(leds, NUM_LEDS);
leds[0] = CRGB::Blue;
FastLED.show();
#endif
#ifdef USE_WIFI
delay(10);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
DBG("Connecting to WiFi...");
DBG(FDRS_WIFI_SSID);
delay(500);
}
DBG("WiFi Connected");
client.setServer(mqtt_server, mqtt_port);
if (!client.connected()) {
DBG("Connecting MQTT...");
reconnect();
}
DBG("MQTT Connected");
client.setCallback(mqtt_callback);
#else
begin_espnow();
#endif
#ifdef USE_LORA
DBG("Initializing LoRa!");
SPI.begin(SCK, MISO, MOSI, SS);
LoRa.setPins(SS, RST, DIO0);
if (!LoRa.begin(FDRS_BAND)) {
while (1);
}
LoRa.setSpreadingFactor(FDRS_SF);
DBG(" LoRa initialized.");
#endif
//DBG(sizeof(DataReading));
#ifdef USE_WIFI
client.publish(TOPIC_STATUS, "FDRS initialized");
#endif
}
void loop() {
#ifdef ESPNOWG_DELAY
if (millis() > timeESPNOWG) {
timeESPNOWG += ESPNOWG_DELAY;
if (lenESPNOWG > 0) releaseESPNOW(0);
}
#endif
#ifdef ESPNOW1_DELAY
if (millis() > timeESPNOW1) {
timeESPNOW1 += ESPNOW1_DELAY;
if (lenESPNOW1 > 0) releaseESPNOW(1);
}
#endif
#ifdef ESPNOW2_DELAY
if (millis() > timeESPNOW2) {
timeESPNOW2 += ESPNOW2_DELAY;
if (lenESPNOW2 > 0) releaseESPNOW(2);
}
#endif
#ifdef SERIAL_DELAY
if (millis() > timeSERIAL) {
timeSERIAL += SERIAL_DELAY;
if (lenSERIAL > 0) releaseSerial();
}
#endif
#ifdef MQTT_DELAY
if (millis() > timeMQTT) {
timeMQTT += MQTT_DELAY;
if (lenMQTT > 0) releaseMQTT();
}
#endif
#ifdef LORAG_DELAY
if (millis() > timeLORAG) {
timeLORAG += LORAG_DELAY;
if (lenLORAG > 0) releaseLoRa(0);
}
#endif
#ifdef LORA1_DELAY
if (millis() > timeLORA1) {
timeLORA1 += LORA1_DELAY;
if (lenLORA1 > 0) releaseLoRa(1);
}
#endif
#ifdef LORA2_DELAY
if (millis() > timeLORA2) {
timeLORA2 += LORA2_DELAY;
if (lenLORA2 > 0) releaseLoRa(2);
}
#endif
while (UART_IF.available()) {
getSerial();
}
getLoRa();
#ifdef USE_WIFI
if (!client.connected()) {
DBG("Connecting MQTT...");
reconnect();
}
client.loop();
#endif
if (newData) {
switch (newData) {
case 1: //ESP-NOW #1
ESPNOW1_ACT
break;
case 2: //ESP-NOW #2
ESPNOW2_ACT
break;
case 3: //ESP-NOW General
ESPNOWG_ACT
break;
case 4: //Serial
SERIAL_ACT
break;
case 5: //MQTT
MQTT_ACT
break;
case 6: //LoRa General
LORAG_ACT
break;
case 7: //LoRa #1
LORA1_ACT
break;
case 8: //LoRa #2
LORA2_ACT
break;
}
newData = 0;
}
}

View File

@ -45,10 +45,10 @@ Buffers can hold a maximum of 256 DataReadings.
![Basic](/FDRS_Gateway2000/Basic_Setup.png)
![Basic](/FDRS_Gateway/Basic_Setup.png)
![Advanced](/FDRS_Gateway2000/Advanced_Setup.png)
![Advanced](/FDRS_Gateway/Advanced_Setup.png)
![Basic LoRa](/FDRS_Gateway2000/Basic_LoRa_Setup.png)
![Basic LoRa](/FDRS_Gateway/Basic_LoRa_Setup.png)
![Advanced LoRa](/FDRS_Gateway2000/Advanced_Setup_LoRa.png)
![Advanced LoRa](/FDRS_Gateway/Advanced_Setup_LoRa.png)

View File

@ -1,80 +1,80 @@
// FARM DATA RELAY SYSTEM
//
// GATEWAY 2.000 Configuration
//#include <fdrs_globals.h> //Uncomment if you install the globals file
#define DEBUG //Enable USB-Serial debugging
#define UNIT_MAC 0x01 // The address of this gateway
//Actions -- Define what happens when a packet arrives at each interface:
// Current function options are: sendESPNOW(MAC), sendSerial(), sendMQTT(),
// bufferLoRa(interface), bufferESPNOW(interface), bufferSerial(), and bufferMQTT().
#define ESPNOWG_ACT sendSerial();
#define SERIAL_ACT
#define MQTT_ACT
#define LORAG_ACT sendSerial();
//#define USE_LORA
//#define USE_WIFI //Used only for MQTT gateway
// Peer addresses
#define ESPNOW1_PEER 0x0E // ESPNOW1 Address
#define ESPNOW2_PEER 0x0F // ESPNOW2 Address
#define LORA1_PEER 0x0E // LoRa1 Address
#define LORA2_PEER 0x0F // LoRa2 Address
// Peer Actions
#define ESPNOW1_ACT
#define ESPNOW2_ACT
#define LORA1_ACT
#define LORA2_ACT
//Pins for UART data interface (ESP32 only)
#define RXD2 14
#define TXD2 15
//LoRa Configuration -- Needed only if using LoRa
#define SCK 5
#define MISO 19
#define MOSI 27
#define SS 18
#define RST 14
#define DIO0 26
//433E6 for Asia
//866E6 for Europe
//915E6 for North America
#define BAND 915E6
#define SF 7
// Buffer Delays - in milliseconds - Uncomment to enable any buffer
//#define ESPNOW1_DELAY 0
//#define ESPNOW2_DELAY 0
//#define ESPNOWG_DELAY 0
//#define SERIAL_DELAY 0
//#define MQTT_DELAY 0
//#define LORAG_DELAY 1000
//#define LORA1_DELAY 1000
//#define LORA2_DELAY 1000
//#define USE_LED //Not yet fully implemented
#define LED_PIN 32
#define NUM_LEDS 4
//WiFi and MQTT Credentials -- Needed only for MQTT gateway
#define WIFI_SSID "Your SSID"
#define WIFI_PASS "Your Password"
#define MQTT_ADDR "192.168.0.8"
#define MQTT_PORT 1883 // Default MQTT port is 1883
//MQTT Credentials -- Needed only if MQTT broker requires authentication
//#define MQTT_AUTH //uncomment to enable MQTT authentication
#define MQTT_USER "Your MQTT Username"
#define MQTT_PASS "Your MQTT Password"
// MQTT Topics
#define TOPIC_DATA "fdrs/data"
#define TOPIC_STATUS "fdrs/status"
#define TOPIC_COMMAND "fdrs/command"
// FARM DATA RELAY SYSTEM
//
// GATEWAY 2.000 Configuration
//#include <fdrs_globals.h> //Uncomment if you install the globals file
#define DEBUG //Enable USB-Serial debugging
#define UNIT_MAC 0x01 // The address of this gateway
//Actions -- Define what happens when a packet arrives at each interface:
// Current function options are: sendESPNOW(MAC), sendSerial(), sendMQTT(),
// bufferLoRa(interface), bufferESPNOW(interface), bufferSerial(), and bufferMQTT().
#define ESPNOWG_ACT sendSerial();
#define SERIAL_ACT
#define MQTT_ACT
#define LORAG_ACT sendSerial();
//#define USE_LORA
//#define USE_WIFI //Used only for MQTT gateway
// Peer addresses
#define ESPNOW1_PEER 0x0E // ESPNOW1 Address
#define ESPNOW2_PEER 0x0F // ESPNOW2 Address
#define LORA1_PEER 0x0E // LoRa1 Address
#define LORA2_PEER 0x0F // LoRa2 Address
// Peer Actions
#define ESPNOW1_ACT
#define ESPNOW2_ACT
#define LORA1_ACT
#define LORA2_ACT
//Pins for UART data interface (ESP32 only)
#define RXD2 14
#define TXD2 15
//LoRa Configuration -- Needed only if using LoRa
#define SCK 5
#define MISO 19
#define MOSI 27
#define SS 18
#define RST 14
#define DIO0 26
//433E6 for Asia
//866E6 for Europe
//915E6 for North America
#define BAND 915E6
#define SF 7
// Buffer Delays - in milliseconds - Uncomment to enable any buffer
//#define ESPNOW1_DELAY 0
//#define ESPNOW2_DELAY 0
//#define ESPNOWG_DELAY 0
//#define SERIAL_DELAY 0
//#define MQTT_DELAY 0
//#define LORAG_DELAY 1000
//#define LORA1_DELAY 1000
//#define LORA2_DELAY 1000
//#define USE_LED //Not yet fully implemented
#define LED_PIN 32
#define NUM_LEDS 4
//WiFi and MQTT Credentials -- Needed only for MQTT gateway
#define WIFI_SSID "Your SSID"
#define WIFI_PASS "Your Password"
#define MQTT_ADDR "192.168.0.8"
#define MQTT_PORT 1883 // Default MQTT port is 1883
//MQTT Credentials -- Needed only if MQTT broker requires authentication
//#define MQTT_AUTH //uncomment to enable MQTT authentication
#define MQTT_USER "Your MQTT Username"
#define MQTT_PASS "Your MQTT Password"
// MQTT Topics
#define TOPIC_DATA "fdrs/data"
#define TOPIC_STATUS "fdrs/status"
#define TOPIC_COMMAND "fdrs/command"

View File

@ -1,3 +1,3 @@
Please copy this directory into your Arduino "libraries" directory.
Edit the files in your libraries folder according to your needs with your WiFi info, LoRa band, etc.
Edit 'fdrs_globals.h' in your libraries folder according to your needs with your WiFi info, LoRa band, etc.
Never edit them here!!!

View File

@ -1,33 +1,33 @@
// FARM DATA RELAY SYSTEM
//
// Basic Sensor Example
//
// Developed by Timm Bogner (bogner1@gmail.com) for Sola Gratia Farm in Urbana, Illinois, USA.
// An example of how to send data using "fdrs_sensor.h".
//
#include "fdrs_sensor.h"
float data1;
float data2;
void setup() {
beginFDRS();
}
void loop() {
data1 = readHum();
loadFDRS(data1, HUMIDITY_T);
data2 = readTemp();
loadFDRS(data2, TEMP_T);
sendFDRS();
sleepFDRS(10); //Sleep time in seconds
}
float readTemp() {
return 42.069;
}
float readHum() {
return 21.0345;
}
// FARM DATA RELAY SYSTEM
//
// Basic Sensor Example
//
// Developed by Timm Bogner (bogner1@gmail.com) for Sola Gratia Farm in Urbana, Illinois, USA.
// An example of how to send data using "fdrs_sensor.h".
//
#include "fdrs_sensor.h"
float data1;
float data2;
void setup() {
beginFDRS();
}
void loop() {
data1 = readHum();
loadFDRS(data1, HUMIDITY_T);
data2 = readTemp();
loadFDRS(data2, TEMP_T);
sendFDRS();
sleepFDRS(10); //Sleep time in seconds
}
float readTemp() {
return 42.069;
}
float readHum() {
return 21.0345;
}

178
FDRS_Sensor/fdrs_sensor.h Normal file
View File

@ -0,0 +1,178 @@
// FARM DATA RELAY SYSTEM
//
// "fdrs_sensor.h"
//
// Developed by Timm Bogner (timmbogner@gmail.com) for Sola Gratia Farm in Urbana, Illinois, USA.
//
#include "sensor_setup.h"
#if defined(ESP8266)
#include <ESP8266WiFi.h>
#include <espnow.h>
#elif defined(ESP32)
#include <esp_now.h>
#include <WiFi.h>
#include <esp_wifi.h>
#endif
#ifdef USE_LORA
#include <LoRa.h>
#endif
#ifdef GLOBALS
#define FDRS_BAND GLOBAL_BAND
#define FDRS_SF GLOBAL_SF
#else
#define FDRS_BAND BAND
#define FDRS_SF SF
#endif
#ifdef DEBUG
#define DBG(a) (Serial.println(a))
#else
#define DBG(a)
#endif
#define STATUS_T 0 // Status
#define TEMP_T 1 // Temperature
#define TEMP2_T 2 // Temperature #2
#define HUMIDITY_T 3 // Relative Humidity
#define PRESSURE_T 4 // Atmospheric Pressure
#define LIGHT_T 5 // Light (lux)
#define SOIL_T 6 // Soil Moisture
#define SOIL2_T 7 // Soil Moisture #2
#define SOILR_T 8 // Soil Resistance
#define SOILR2_T 9 // Soil Resistance #2
#define OXYGEN_T 10 // Oxygen
#define CO2_T 11 // Carbon Dioxide
#define WINDSPD_T 12 // Wind Speed
#define WINDHDG_T 13 // Wind Direction
#define RAINFALL_T 14 // Rainfall
#define MOTION_T 15 // Motion
#define VOLTAGE_T 16 // Voltage
#define VOLTAGE2_T 17 // Voltage #2
#define CURRENT_T 18 // Current
#define CURRENT2_T 19 // Current #2
#define IT_T 20 // Iterations
#define MAC_PREFIX 0xAA, 0xBB, 0xCC, 0xDD, 0xEE // Should only be changed if implementing multiple FDRS systems.
typedef struct __attribute__((packed)) DataReading {
float d;
uint16_t id;
uint8_t t;
} DataReading;
const uint16_t espnow_size = 250 / sizeof(DataReading);
uint8_t gatewayAddress[] = {MAC_PREFIX, GTWY_MAC};
uint8_t gtwyAddress[] = {gatewayAddress[3], gatewayAddress[4], GTWY_MAC};
uint8_t LoRaAddress[] = {0x42, 0x00};
uint32_t wait_time = 0;
DataReading fdrsData[espnow_size];
uint8_t data_count = 0;
void beginFDRS() {
#ifdef DEBUG
Serial.begin(115200);
#endif
DBG("FDRS Sensor ID " + String(READING_ID) + " initializing...");
DBG(" Gateway: " + String (GTWY_MAC, HEX));
#ifdef POWER_CTRL
DBG("Powering up the sensor array!");
pinMode(POWER_CTRL, OUTPUT);
digitalWrite(POWER_CTRL, 1);
#endif
// Init ESP-NOW for either ESP8266 or ESP32 and set MAC address
#ifdef USE_ESPNOW
DBG("Initializing ESP-NOW!");
WiFi.mode(WIFI_STA);
WiFi.disconnect();
#if defined(ESP8266)
if (esp_now_init() != 0) {
return;
}
esp_now_set_self_role(ESP_NOW_ROLE_COMBO);
// Register peers
esp_now_add_peer(gatewayAddress, ESP_NOW_ROLE_COMBO, 0, NULL, 0);
#elif defined(ESP32)
if (esp_now_init() != ESP_OK) {
DBG("Error initializing ESP-NOW");
return;
}
esp_now_peer_info_t peerInfo;
peerInfo.ifidx = WIFI_IF_STA;
peerInfo.channel = 0;
peerInfo.encrypt = false;
// Register first peer
memcpy(peerInfo.peer_addr, gatewayAddress, 6);
if (esp_now_add_peer(&peerInfo) != ESP_OK) {
DBG("Failed to add peer");
return;
}
#endif
DBG(" ESP-NOW Initialized.");
#endif
#ifdef USE_LORA
DBG("Initializing LoRa!");
DBG(BAND);
DBG(SF);
#ifndef __AVR__
SPI.begin(SCK, MISO, MOSI, SS);
#endif
LoRa.setPins(SS, RST, DIO0);
if (!LoRa.begin(FDRS_BAND)) {
while (1);
}
LoRa.setSpreadingFactor(FDRS_SF);
DBG(" LoRa Initialized.");
#endif
}
void transmitLoRa(uint8_t* mac, DataReading * packet, uint8_t len) {
#ifdef USE_LORA
uint8_t pkt[5 + (len * sizeof(DataReading))];
memcpy(&pkt, mac, 3); //
memcpy(&pkt[3], &LoRaAddress, 2);
memcpy(&pkt[5], packet, len * sizeof(DataReading));
LoRa.beginPacket();
LoRa.write((uint8_t*)&pkt, sizeof(pkt));
LoRa.endPacket();
#endif
}
void sendFDRS() {
DBG("Sending FDRS Packet!");
#ifdef USE_ESPNOW
esp_now_send(gatewayAddress, (uint8_t *) &fdrsData, data_count * sizeof(DataReading));
delay(5);
DBG(" ESP-NOW sent.");
#endif
#ifdef USE_LORA
transmitLoRa(gtwyAddress, fdrsData, data_count);
DBG(" LoRa sent.");
#endif
data_count = 0;
}
void loadFDRS(float d, uint8_t t) {
DBG("Data loaded. Type: " + String(t));
if (data_count > espnow_size) sendFDRS();
DataReading dr;
dr.id = READING_ID;
dr.t = t;
dr.d = d;
fdrsData[data_count] = dr;
data_count++;
}
void sleepFDRS(int sleep_time) {
DBG("Sleepytime!");
#ifdef DEEP_SLEEP
DBG(" Deep sleeping.");
#ifdef ESP32
esp_sleep_enable_timer_wakeup(sleep_time * 1000000);
esp_deep_sleep_start();
#endif
#ifdef ESP8266
ESP.deepSleep(sleep_time * 1000000);
#endif
#endif
DBG(" Delaying.");
delay(sleep_time * 1000);
}

View File

@ -1,7 +0,0 @@
typedef struct DataReading {
float d;
uint16_t id;
uint8_t t;
} DataReading;

View File

@ -1,135 +0,0 @@
// FARM DATA RELAY SYSTEM
//
// GATEWAY MODULE
//
// Developed by Timm Bogner (bogner1@gmail.com) for Sola Gratia Farm in Urbana, Illinois, USA.
// Setup instructions located in the "fdrs_config.h" file.
#if defined(ESP8266)
#include <ESP8266WiFi.h>
#include <espnow.h>
#elif defined(ESP32)
#define RXD2 21
#define TXD2 22
#include <esp_now.h>
#include <WiFi.h>
#include <esp_wifi.h>
#endif
#include "fdrs_config.h"
#include <ArduinoJson.h>
#include "DataReading.h"
uint8_t broadcast_mac[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
uint8_t prevAddress[] = {MAC_PREFIX, PREV_MAC};
uint8_t selfAddress[] = {MAC_PREFIX, UNIT_MAC};
DataReading incData[31];
bool newData = false;
int pkt_readings;
uint8_t incMAC[6];
#if defined(ESP8266)
void OnDataSent(uint8_t *mac_addr, uint8_t sendStatus) {
}
void OnDataRecv(uint8_t * mac, uint8_t *incomingData, uint8_t len) {
#elif defined(ESP32)
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
}
void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len) {
#endif
memcpy(&incData, incomingData, len);
memcpy(&incMAC, mac, 6);
pkt_readings = len / sizeof(DataReading);
newData = true;
}
void setup() {
WiFi.mode(WIFI_STA);
WiFi.disconnect();
// Init ESP-NOW for either ESP8266 or ESP32 and set MAC address
#if defined(ESP8266)
Serial.begin(115200);
wifi_set_macaddr(STATION_IF, selfAddress);
if (esp_now_init() != 0) {
return;
}
esp_now_set_self_role(ESP_NOW_ROLE_COMBO);
esp_now_register_send_cb(OnDataSent);
esp_now_register_recv_cb(OnDataRecv);
// Register peer
esp_now_add_peer(prevAddress, ESP_NOW_ROLE_COMBO, 0, NULL, 0);
esp_now_add_peer(broadcast_mac, ESP_NOW_ROLE_COMBO, 0, NULL, 0);
#elif defined(ESP32)
Serial.begin(115200, SERIAL_8N1, RXD2, TXD2);
esp_wifi_set_mac(WIFI_IF_STA, &selfAddress[0]);
if (esp_now_init() != ESP_OK) {
Serial.println("Error initializing ESP-NOW");
return;
}
esp_now_register_send_cb(OnDataSent);
esp_now_register_recv_cb(OnDataRecv);
esp_now_peer_info_t peerInfo;
peerInfo.channel = 0;
peerInfo.encrypt = false;
memcpy(peerInfo.peer_addr, prevAddress, 6);
if (esp_now_add_peer(&peerInfo) != ESP_OK) {
Serial.println("Failed to add peer");
return;
}
memcpy(peerInfo.peer_addr, broadcast_mac, 6);
if (esp_now_add_peer(&peerInfo) != ESP_OK) {
Serial.println("Failed to add peer");
return;
}
#endif
}
//CMD example {"id":72,"type":201,"data":166}
void getSerial() {
DataReading theCommands[31];
String incomingString = Serial.readStringUntil('\n');
StaticJsonDocument<2048> doc;
DeserializationError error = deserializeJson(doc, incomingString);
if (error) { // Test if parsing succeeds.
Serial.println("parse err");
return;
} else {
int s = doc.size();
//Serial.println(s);
for (int i = 0; i < s; i++) {
if (i > 31) break;
theCommands[i].id = doc[i]["id"];
theCommands[i].t = doc[i]["type"];
theCommands[i].d = doc[i]["data"];
}
esp_now_send(broadcast_mac, (uint8_t *) &theCommands, s * sizeof(DataReading));
}
}
void encodeJSON() {
StaticJsonDocument<2048> doc;
for (int i = 0; i < pkt_readings; i++) {
doc[i]["id"] = incData[i].id;
doc[i]["type"] = incData[i].t;
doc[i]["data"] = incData[i].d;
incData[i].id = 0;
incData[i].t = 0;
incData[i].d = 0;
}
serializeJson(doc, Serial);
Serial.println();
}
void loop() {
while (Serial.available()) {
getSerial();
}
if (newData) {
newData = false;
encodeJSON();
}
}

View File

@ -1,20 +0,0 @@
// To configure your FDRS Gateway:
// Each device in the system has a unique, one-byte address which
// is assigned to the last digit of its MAC address at startup.
// Each device is configured to know what the previous and/or next
// device in the line of communication is.
// The gateway should usually be assigned the address 0x00.
// The PREV_MAC is currently not used, as the gateway responds
// to all packets in the same manner.
// THIS UNIT
#define UNIT_MAC 0x00
#define PREV_MAC 0x01
//MAC prefix:
#define MAC_PREFIX 0xAA, 0xBB, 0xCC, 0xDD, 0xEE

View File

@ -1,141 +0,0 @@
// FARM DATA RELAY SYSTEM
//
// RELAY MODULE
//
// Developed by Timm Bogner (bogner1@gmail.com) for Sola Gratia Farm in Urbana, Illinois, USA.
// Setup instructions located in the "fdrs_config.h" file.
#if defined(ESP8266)
#include <ESP8266WiFi.h>
#include <espnow.h>
#elif defined(ESP32)
#include <esp_now.h>
#include <WiFi.h>
#include <esp_wifi.h>
#endif
#include "fdrs_config.h"
uint8_t prevAddress[] = {0xAA, 0xBB, 0xCC, 0xDD, 0xEE, PREV_MAC};
uint8_t selfAddress[] = {0xAA, 0xBB, 0xCC, 0xDD, 0xEE, UNIT_MAC};
uint8_t nextAddress[] = {0xAA, 0xBB, 0xCC, 0xDD, 0xEE, NEXT_MAC};
uint8_t outMAC[] = {0xAA, 0xBB, 0xCC, 0xDD, 0xEE, DEFT_MAC};
uint8_t incMAC[6];
uint8_t theData[250];
uint8_t ln;
bool newData = false;
bool isLocal = false;
void passOn() {
switch (incMAC[5]) {
case PREV_MAC:
outMAC[5] = NEXT_MAC;
break;
case NEXT_MAC:
outMAC[5] = PREV_MAC;
break;
default:
outMAC[5] = DEFT_MAC;
break;
}
if (!isLocal) outMAC[5] = DEFT_MAC;
Serial.print("Packet Received from device: ");
Serial.println(incMAC[5]);
Serial.print("and sending to: ");
Serial.println(outMAC[5]);
esp_now_send(outMAC, (uint8_t *) &theData, ln);
}
// Set ESP-NOW send and receive callbacks for either ESP8266 or ESP32
#if defined(ESP8266)
void OnDataSent(uint8_t *mac_addr, uint8_t sendStatus) {
Serial.print("Last Packet Send Status: ");
if (sendStatus == 0) {
Serial.println("Delivery success");
}
else {
Serial.println("Delivery fail");
}
}
void OnDataRecv(uint8_t* mac, uint8_t *incomingData, uint8_t len) {
#elif defined(ESP32)
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
Serial.print("Last Packet Send Status:");
Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
}
void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len) {
#endif
memcpy(&theData, incomingData, sizeof(theData));
memcpy(&incMAC, mac, sizeof(incMAC));
if (memcmp(&incMAC, &selfAddress, 5) != 0) {
isLocal = false;
} else {
isLocal = true;
}
Serial.print("Data received: ");
Serial.println(len);
ln = len;
newData = true;
}
void setup() {
// Init Serial Monitor
Serial.begin(115200);
// Init WiFi
WiFi.mode(WIFI_STA);
WiFi.disconnect();
// Init ESP-NOW for either ESP8266 or ESP32 and set MAC address
#if defined(ESP8266)
wifi_set_macaddr(STATION_IF, selfAddress);
if (esp_now_init() != 0) {
return;
}
esp_now_set_self_role(ESP_NOW_ROLE_COMBO);
esp_now_register_send_cb(OnDataSent);
esp_now_register_recv_cb(OnDataRecv);
// Register peers
esp_now_add_peer(prevAddress, ESP_NOW_ROLE_COMBO, 0, NULL, 0);
esp_now_add_peer(nextAddress, ESP_NOW_ROLE_COMBO, 0, NULL, 0);
#elif defined(ESP32)
esp_wifi_set_mac(WIFI_IF_STA, &selfAddress[0]);
if (esp_now_init() != ESP_OK) {
Serial.println("Error initializing ESP-NOW");
return;
}
esp_now_register_send_cb(OnDataSent);
esp_now_register_recv_cb(OnDataRecv);
esp_now_peer_info_t peerInfo;
peerInfo.channel = 0;
peerInfo.encrypt = false;
// Register first peer
memcpy(peerInfo.peer_addr, prevAddress, 6);
if (esp_now_add_peer(&peerInfo) != ESP_OK) {
Serial.println("Failed to add peer");
return;
}
// Register second peer
memcpy(peerInfo.peer_addr, nextAddress, 6);
if (esp_now_add_peer(&peerInfo) != ESP_OK) {
Serial.println("Failed to add peer");
return;
}
#endif
Serial.println();
Serial.println("FARM DATA RELAY SYSTEM :: Relay Module");
Serial.println("MAC:" + WiFi.macAddress());
Serial.print("Previous device: ");
Serial.println(PREV_MAC);
Serial.print("Next device: ");
Serial.println(NEXT_MAC);
Serial.print("Default device: ");
Serial.println(DEFT_MAC);
Serial.println(" ");
}
void loop() {
if (newData) {
newData = false;
passOn();
}
}

View File

@ -1,22 +0,0 @@
// To configure FDRS:
// Each device in the system has a unique, one-byte address which
// is assigned to the last digit of its MAC address at startup.
// Each relay receives data from its pre-programmed "PREV_MAC" device and
// sends the packet verbatim to the address corresponding to "NEXT_MAC".
// The gateway receives the data and outputs it as a json string over the serial port.
// THIS UNIT
#define UNIT_MAC 0x01
// NEXT UNIT
#define NEXT_MAC 0x00
// PREVIOUS UNIT
#define PREV_MAC 0x02
//Packets from unknown MACs are sent here.
#define DEFT_MAC NEXT_MAC

View File

@ -1,7 +0,0 @@
typedef struct DataReading {
float d;
uint16_t id;
uint8_t t;
} DataReading;

View File

@ -1,151 +0,0 @@
// FARM DATA RELAY SYSTEM
//
// TERMINAL MODULE
//
// Developed by Timm Bogner (bogner1@gmail.com) for Sola Gratia Farm in Urbana, Illinois, USA.
// Setup instructions located in the "fdrs_config.h" file.
#if defined(ESP8266)
#include <ESP8266WiFi.h>
#include <espnow.h>
#elif defined(ESP32)
#include <esp_now.h>
#include <WiFi.h>
#include <esp_wifi.h>
#endif
#include "fdrs_config.h"
#include "DataReading.h"
uint8_t selfAddress[] = {0xAA, 0xBB, 0xCC, 0xDD, 0xEE, UNIT_MAC};
uint8_t nextAddress[] = {0xAA, 0xBB, 0xCC, 0xDD, 0xEE, NEXT_MAC};
uint8_t broadcast_mac[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
DataReading incData[31];
DataReading theData[31];
DataReading theCommands[31];
bool newCMD = false;
int wait_time = 0;
int tot_readings = 0;
int tot_commands = 0;
#if defined(ESP8266)
void OnDataSent(uint8_t *mac_addr, uint8_t sendStatus) {
Serial.print("Last Packet Send Status: ");
if (sendStatus == 0) {
Serial.println("Delivery success");
}
else {
Serial.println("Delivery fail");
}
}
void OnDataRecv(uint8_t * mac, uint8_t *incomingData, uint8_t len) {
#elif defined(ESP32)
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
Serial.print("Last Packet Send Status:");
Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
}
void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len) {
#endif
uint8_t incMAC[6];
memcpy(&incData, incomingData, len);
memcpy(&mac, incMAC, 6);
//if (memcmp(&incMAC, &nextAddress, 6) == 0)
int pkt_readings = len / sizeof(DataReading);
Serial.println(":Packet:");
for (byte i = 0; i < pkt_readings; i++) {
Serial.println("SENSOR ID: " + String(incData[i].id) + " TYPE " + String(incData[i].t) + " DATA " + String(incData[i].d));
if (incData[i].t < 200) {
if (tot_readings >= 250 / sizeof(DataReading)) {
Serial.println("ERROR::Too many sensor readings sent within delay period.");
break;
}
theData[tot_readings] = incData[i]; //Save the current incoming reading to the next open packet slot
++tot_readings;
} else {
theCommands[tot_commands] = incData[i]; //Save the current incoming reading to the next open packet slot
++tot_commands;
newCMD = true;
}
}
}
void setup() {
// Init Serial
Serial.begin(115200);
// Init WiFi
WiFi.mode(WIFI_STA);
WiFi.disconnect();
// Init ESP-NOW for either ESP8266 or ESP32 and set MAC address
#if defined(ESP8266)
wifi_set_macaddr(STATION_IF, selfAddress);
if (esp_now_init() != 0) {
return;
}
esp_now_set_self_role(ESP_NOW_ROLE_COMBO);
esp_now_register_send_cb(OnDataSent);
esp_now_register_recv_cb(OnDataRecv);
// Register peer
esp_now_add_peer(nextAddress, ESP_NOW_ROLE_COMBO, 0, NULL, 0);
esp_now_add_peer(broadcast_mac, ESP_NOW_ROLE_COMBO, 0, NULL, 0);
#elif defined(ESP32)
esp_wifi_set_mac(WIFI_IF_STA, &selfAddress[0]);
if (esp_now_init() != ESP_OK) {
Serial.println("Error initializing ESP-NOW");
return;
}
esp_now_register_send_cb(OnDataSent);
esp_now_register_recv_cb(OnDataRecv);
esp_now_peer_info_t peerInfo;
peerInfo.channel = 0;
peerInfo.encrypt = false;
// Register peer
memcpy(peerInfo.peer_addr, nextAddress, 6);
if (esp_now_add_peer(&peerInfo) != ESP_OK) {
Serial.println("Failed to add peer");
return;
}
memcpy(peerInfo.peer_addr, broadcast_mac, 6);
if (esp_now_add_peer(&peerInfo) != ESP_OK) {
Serial.println("Failed to add peer");
return;
}
#endif
Serial.println();
Serial.println("FARM DATA RELAY SYSTEM :: Terminal Module");
Serial.println("MAC:" + WiFi.macAddress());
Serial.print("Next device: ");
Serial.println(NEXT_MAC);
// Serial.println(250 / sizeof(DataReading), DEC);
// Serial.println(sizeof(DataReading), DEC);
}
void loop() {
if (newCMD) sendCmd();
if (millis() > wait_time) {
wait_time = wait_time + DELAY;
if (tot_readings != 0) passForward();
}
}
void passForward() {
Serial.println("Passing Forward");
esp_now_send(nextAddress, (uint8_t *) &theData, sizeof(DataReading)*tot_readings);
tot_readings = 0;
for (int i = 0; i < 250 / sizeof(DataReading); i++) {
theData[i].d = 0;
theData[i].id = 0;
theData[i].t = 0;
}
}
void sendCmd() {
newCMD = false;
esp_now_send(broadcast_mac, (uint8_t *) &theCommands, tot_commands* sizeof(DataReading));
tot_commands = 0;
}

View File

@ -1,27 +0,0 @@
// To configure FDRS:
// Uncomment the code corresponding to the unit you are configuring,
// then uncomment the code corresponding to the unit you would like
// to be previous and/or next in the line of communication.
// Each device in the system has a unique, one-byte address which
// is assigned to the last digit of its MAC address at startup.
// Each device is configured to know what the previous and/or next
// device in the line of communication is.
// The terminal is considered the "first" device, which can be addressed
// to a relay or the gateway.
// Each relay receives data from its pre-programmed "PREV_MAC" device and
// sends the packet verbatim to the address corresponding to "NEXT_MAC".
// The gateway receives the data and outputs it as a json string over the serial port.
#define DELAY 15000
// THIS UNIT
#define UNIT_MAC 0x01
// NEXT UNIT
#define NEXT_MAC 0x00

View File

@ -1,7 +0,0 @@
typedef struct DataReading {
float d;
uint16_t id;
uint8_t t;
} DataReading;

View File

@ -1,151 +0,0 @@
// FARM DATA RELAY SYSTEM
//
// BLYNK FRONT-END MODULE
// Uses JSON data from the serial port to set Blynk variables.
//
// Developed by Timm Bogner (bogner1@gmail.com) for Sola Gratia Farm in Urbana, Illinois, USA.
// This code was written for the now-outdated version of Blynk, and is mostly here for reference.
//
#define STASSID "" //Your SSID
#define STAPSK "" //Your Password
#define BLKAUTH "" //Your Blynk auth code
#define DELAY 30000
#if defined(ESP8266)
#include <BlynkSimpleEsp8266.h>
#include <ESP8266WiFi.h>
#elif defined(ESP32)
#include <BlynkSimpleEsp32.h>
#include <WiFi.h>
#endif
#include <ArduinoJson.h>
#include "DataReading.h"
BlynkTimer timer;
WidgetTerminal terminal(V69);
DataReading allData[256];
int wait_time = DELAY;
char auth[] = BLKAUTH;
const char* ssid = STASSID;
const char* password = STAPSK;
bool is_new[255];
int new_readings;
bool term_flag;
String the_command;
BLYNK_WRITE(V69)
{
Serial.println("blynkwrite");
the_command = param.asStr();
term_flag = true;
}
void setup() {
Serial.begin(115200);
WiFi.mode(WIFI_STA);
Serial.println();
Serial.println("FDRS Blynk Module");
Serial.println("Connect to WiFi please?");
Blynk.begin(auth, ssid, password);
// Blynk.config(auth);
// Blynk.connectWiFi(ssid, password);
Serial.println("Thanks!");
//terminal.clear();
timer.setInterval(30000L, updateBlynk);
Blynk.run();
terminal.println("Hello, world!");
terminal.flush();
}
void loop() {
while (Serial.available()) {
Serial.println("waiting for tilda");
if (Serial.read() == '~') { //Waits for '~', then parses following data
getSerial();
Serial.println("getSerial done");
break;
}
}
// if (millis() > wait_time) {
// wait_time = wait_time + DELAY;
// if (Blynk.connected()) {
// updateBlynk();
// Serial.println("blynk updated");
// }
// }
if (term_flag) {
parseBlynkTerm(the_command);
term_flag = false;
}
Blynk.run();
timer.run();
}
void getSerial() {
String incomingString = Serial.readString();
StaticJsonDocument<3072> doc;
Serial.println("Received: " + incomingString);
DeserializationError error = deserializeJson(doc, incomingString);
if (error) { // Test if parsing succeeds.
Serial.print(F("deserializeJson() failed: "));
Serial.println(error.f_str());
return;
} else {
for (int i = 0; i < doc.size(); i++) {
Serial.println(doc.size());
DataReading newData;
newData.id = doc[i]["id"];
newData.t = doc[i]["type"];
newData.d = doc[i]["data"];
allData[newData.id] = newData;
is_new[newData.id] = true;
Serial.println("SENSOR ID: " + String(newData.id) + " TYPE " + String(newData.t) + " DATA " + String(newData.d));
yield();
}
}
}
void updateBlynk() {
Serial.println("Updateblynk");
for (int i = 0; i < 127; i++) {
if (is_new[i] == true) {
Serial.println("abt to write");
Blynk.virtualWrite(i, allData[i].d);
is_new[i] = false;
yield();
}
}
}
void parseBlynkTerm(String command) {
int ind1 = command.indexOf(" ");
String arg1 = command.substring(0, ind1);
if (arg1.equalsIgnoreCase(String("SET"))) {
int ind2 = command.indexOf(" ", ind1 + 1);
String arg2 = command.substring(ind1 + 1, ind2);
String arg3 = command.substring(ind2 + 1, command.length());
terminal.println("ARG1:" + arg1);
terminal.println("ARG2:" + arg2);
terminal.println("ARG3:" + arg3);
terminal.flush();
DataReading newCMD;
newCMD.id = arg2.toInt();
newCMD.t = 201;
newCMD.d = arg3.toFloat();
allData[newCMD.id] = newCMD;
StaticJsonDocument<2048> doc;
doc[0]["id"] = newCMD.id;
doc[0]["type"] = newCMD.t;
doc[0]["data"] = newCMD.d;
Serial.write('~');
serializeJson(doc, Serial);
Serial.println();
} else if (arg1.equalsIgnoreCase(String("GET"))) {
String arg2 = command.substring(ind1 + 1, command.length());
terminal.println("DataReading " + arg2 + " :: " + String(allData[arg2.toInt()].d));
terminal.flush();
}
}

View File

@ -1,44 +0,0 @@
# <p align="center">Ye Olde Farm Data Relay System
##### <p align="center">[***In loving memory of Gay Holman, an extraordinary woman.***](https://www.facebook.com/CFECI/posts/2967989419953119) #####
### This is the first version of my project, and is left here only for reference.
The Farm Data Relay System is an easy way to link remote sensors to the internet without the need for WiFi. It uses the ESP-NOW protocol on widely availabe ESP32 and ESP8266 microcontroller boards, and can be used to collect and transmit sensor data in situations where it would be too difficult or energy-consuming to provide full WiFi coverage.
A major consideration has been to make the system straight-forward and easy to set up, since the primary user may not be very familiar with Arduino. Using an assigned MAC address scheme allows for the whole system to be configured by setting just a handful of values in code.
Other than the nodes, each device in the system has a one-byte address. At boot, each device changes its MAC address to "AA:BB:CC:DD:EE:xx" where xx is the device's address identifier. Nodes can send their data to a terminal, a relay, or directly to a gateway. Each of these devices can be connected as needed in a chain that leads to a gateway, where the data is handed off to another system.
## Getting Started
To get started using FDRS with Node-Red, you'll first need to flash an ESP32 or 8266 device with the FDRS_Gateway sketch. Next, connect the device via serial port to a computer running Node-Red. You can then use the serialport node connected to a JSON node, and finally a split node to get your data ready to use. You can find the basic flow examples in the 'NodeRed-Basic.json' file. If you are using a usb-serial port, keep in mind that you may have to change the selected port after plugging in your device, or de-select the port when trying to flash the device from another program.
As you flash each sensor, you'll need to change the UNIT_ID to a unique integer (0-65535). For some sensors, you'll also need to adjust pin assignments and install libraries.
By default, all sensors have GTWY_MAC set to 0x00. You'll only need to change this if you are going to use a relay to extend the system's range.
If you need to get data from sensors that are out of reach of the gateway, place an FDRS_Relay device near the edge of the gateway's range. Flash this device with the default parameters, and then flash the sensors with GTWY_MAC set to 0x01. They will now send their data to the relay, which in turn sends it to the gateway.
## Sensors
```
typedef struct DataReading {
float d;
uint16_t id;
uint8_t t;
} DataReading;
```
Each sensor in the system sends its data over ESP-NOW as a float 'd' inside of a structure called a DataReading. Its global sensor address is represented by an integer 'id', and each type is represented by a single byte 't'. If sensors need to send multiple types of readings (ex: temp and humidity), then they are sent in an array of DataReadings. In this case each reading will share an id, but be differentiated by its type.
## Terminal
A terminal is a device that recieves data from the nodes and aggregates it into a larger array. The larger array is then periodically sent forward through the system to the gateway. The time between sends must be short enough so as not to exceed the maximum legnth of an ESP-NOW packet with DataReadings, which is 31.
## Relays
Relays are absolute ESP-NOW repeaters. They are programmed with the address of the previous and next device, and when data is received from one, it delivers it to the other. The "DEFT_MAC" setting defines where a relay will send an incoming packet with an unknown address. This can be used to direct sensor packets either to the terminal or the gateway.
In the FDRS, one can place as many relays as needed to span the distance to the gateway, which is the final device in the system.
## Gateway
The gateway takes the packet of DataReadings and interprets it into json format, then outputs it over the serial port. From here it can be collected by another microcontroller or a Raspberry Pi front-end to be sent to the cloud for further processing and storage.

View File

@ -7,15 +7,10 @@ Using an assigned MAC address scheme allows for the whole system to be configure
## Getting Started
### Dependencies
[LoRa library](https://github.com/sandeepmistry/arduino-LoRa)
The dependency can be removed by commenting out the `#define USE_LORA` in `fdrs_sensor.h`
### [Sensors](https://github.com/timmbogner/Farm-Data-Relay-System/tree/main/FDRS_Sensor2000)
### [Sensors](https://github.com/timmbogner/Farm-Data-Relay-System/tree/main/FDRS_Sensor)
Sensors gather data and send it to a gateway via ESP-NOW or LoRa.
### [Gateways](https://github.com/timmbogner/Farm-Data-Relay-System/tree/main/FDRS_Gateway2000)
### [Gateways](https://github.com/timmbogner/Farm-Data-Relay-System/tree/main/FDRS_Gateway)
Gateways listen for packets over ESP-NOW, LoRa, UART, and/or MQTT, then re-transmit the packets using one or more of the same interfaces.
### Front-end
@ -24,7 +19,9 @@ The Node-RED front-end can be set up with these nodes to format and send the dat
[{"id":"66d36c0f.cedf94","type":"influxdb out","z":"d7346a99.716ef8","influxdb":"905dd357.34717","name":"","measurement":"DataReading","precision":"","retentionPolicy":"","database":"database","precisionV18FluxV20":"ms","retentionPolicyV18Flux":"","org":"the_organization","bucket":"bkt","x":760,"y":240,"wires":[]},{"id":"93e9822a.3ad59","type":"mqtt in","z":"d7346a99.716ef8","name":"","topic":"esp/fdrs","qos":"2","datatype":"auto","broker":"c513f7e9.760658","nl":false,"rap":true,"rh":0,"x":170,"y":220,"wires":[["d377f9e0.faef98"]]},{"id":"d377f9e0.faef98","type":"json","z":"d7346a99.716ef8","name":"","property":"payload","action":"obj","pretty":false,"x":290,"y":220,"wires":[["ca383562.4014e8"]]},{"id":"ca383562.4014e8","type":"split","z":"d7346a99.716ef8","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":410,"y":220,"wires":[["6eaba8dd.429e38"]]},{"id":"6eaba8dd.429e38","type":"function","z":"d7346a99.716ef8","name":"Fields","func":"msg.payload = [{\n data: msg.payload.data\n},{\n id: msg.payload.id,\n type: msg.payload.type\n}]\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":530,"y":220,"wires":[["296d0f4b.37a46","66d36c0f.cedf94"]]},{"id":"296d0f4b.37a46","type":"debug","z":"d7346a99.716ef8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":670,"y":200,"wires":[]},{"id":"905dd357.34717","type":"influxdb","hostname":"127.0.0.1","port":"8086","protocol":"http","database":"database","name":"","usetls":false,"tls":"d50d0c9f.31e858","influxdbVersion":"2.0","url":"http://localhost:8086","rejectUnauthorized":true},{"id":"c513f7e9.760658","type":"mqtt-broker","name":"","broker":"localhost","port":"1883","clientid":"","usetls":false,"protocolVersion":"4","keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","birthMsg":{},"closeTopic":"","closeQos":"0","closePayload":"","closeMsg":{},"willTopic":"","willQos":"0","willPayload":"","willMsg":{},"sessionExpiry":""},{"id":"d50d0c9f.31e858","type":"tls-config","name":"","cert":"","key":"","ca":"","certname":"","keyname":"","caname":"","servername":"","verifyservercert":false}]
```
## Dependencies
[LoRa library](https://github.com/sandeepmistry/arduino-LoRa)
[ArduinoJson](https://arduinojson.org/)
## Future Plans
A few things that I intend to add are:
@ -46,5 +43,5 @@ Development of this project would not have been possible without the support of
![Basic](/FDRS_Gateway2000/Basic_Setup.png)
![Advanced](/FDRS_Gateway2000/Advanced_Setup.png)
![Basic](/FDRS_Gateway/Basic_Setup.png)
![Advanced](/FDRS_Gateway/Advanced_Setup.png)

View File

@ -0,0 +1,37 @@
// FARM DATA RELAY SYSTEM
//
// Basic Sensor Example
//
// Developed by Timm Bogner (bogner1@gmail.com) for Sola Gratia Farm in Urbana, Illinois, USA.
// An example of how to send data using "fdrs_sensor.h".
//
#include "fdrs_sensor.h"
#include "sensor_setup.h"
FDRSLoRa FDRS(GTWY_MAC,READING_ID,MISO,MOSI,SCK,SS,RST,DIO0,BAND,SF);
float data1;
float data2;
void setup() {
FDRS.begin();
}
void loop() {
data1 = readHum();
FDRS.load(data1, HUMIDITY_T);
data2 = readTemp();
FDRS.load(data2, TEMP_T);
FDRS.send();
FDRS.sleep(10); //Sleep time in seconds
}
float readTemp() {
return 42.069;
}
float readHum() {
return 21.0345;
}

View File

@ -151,7 +151,7 @@ void FDRSLoRa::init(void){
DBG("Initializing LoRa!");
DBG(_band);
DBG(_sf);
#ifndef __AVR__
#ifdef ESP32
SPI.begin(_sck, _miso, _mosi, _ss);
#endif
LoRa.setPins(_ss, _rst, _dio0);

View File

@ -0,0 +1,27 @@
// FARM DATA RELAY SYSTEM
//
// Sensor Configuration
// (This file will soon be known as 'sensor_config.h')
//
//#include <fdrs_globals.h> //Uncomment when you install the globals file
#define READING_ID 1 //Unique ID for this sensor
#define GTWY_MAC 0x04 //Address of the nearest gateway
#define DEEP_SLEEP
//#define POWER_CTRL 14
#define DEBUG
//LoRa Configuration
#define SCK 5
#define MISO 19
#define MOSI 27
#define SS 18
#define RST 14
#define DIO0 26
//433E6 for Asia
//866E6 for Europe
//915E6 for North America
#define BAND 915E6
#define SF 7