Skip to content

Instantly share code, notes, and snippets.

@Tech500
Last active February 7, 2022 20:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Tech500/6b8d4e887de4945e0afc5ea8ece66f29 to your computer and use it in GitHub Desktop.
Save Tech500/6b8d4e887de4945e0afc5ea8ece66f29 to your computer and use it in GitHub Desktop.
ESP-NOW ESP32_Sender --working
#include <esp_now.h>
#include <esp_wifi.h>
#include <WiFi.h>
#include <WiFiUdp.h>
#include <sys/time.h> // struct timeval --> Needed to sync time
#include <time.h> // time() ctime() --> Needed to sync time
#include <BME280I2C.h> //Use the Arduino Library Manager, get BME280 by Tyler Glenn
#include <EnvironmentCalculations.h> //Use the Arduino Library Manager, get BME280 by Tyler Glenn
#include <Wire.h> //Part of version 1.0.4 ESP32 Board Manager install -----> Used for I2C protocol
//The gateway access point credentials
const char* APssid = "ESP32-Access-Point";
const char* APpassword = "123456789";
// Replace with your network details
const char* ssid = "R2D2";
const char* password = "sissy4357";
//setting the addresses
IPAddress staticIP(10, 0, 0, 200);
IPAddress gateway(10, 0, 0, 1);
IPAddress subnet(255, 255, 255, 0);
IPAddress primaryDNS(10,0,0,1);
IPAddress secondaryDNS(10,0,0,1);
// Set your Board ID (ESP32 Sender #1 = BOARD_ID 1, ESP32 Sender #2 = BOARD_ID 2, etc)
#define BOARD_ID 1
// this is the MAC Address of the remote ESP server which receives these sensor readings
uint8_t remoteMac[] = {0x7C, 0x9E, 0xBD, 0xF5, 0x58, 0x08};
//uint8_t remoteMac2[] = {0xEE, 0xFA, 0xBC, 0x9B, 0xF5, 0x6D};
//Wi-Fi channel (must match the gateway wi-fi channel as an access point)
#define CHAN_AP 1
#define uS_TO_S_FACTOR 1000000ull /* Conversion factor for micro seconds to minutes */
#define TIME_TO_SLEEP 5 // 5 minutes
//#define SEND_TIMEOUT .2 // 245 millis seconds timeout
//Structure example to send data
//Must match the receiver structure
typedef struct struct_message {
int id;
float temp;
float heat;
float hum;
float dew;
float press;
unsigned long int readingId;
} struct_message;
static const uint32_t GPSBaud = 9600; // Ublox GPS default Baud Rate is 9600
const double Home_LAT = 88.888888; // Your Home Latitude --edit with your data
const double Home_LNG = 88.888888; // Your Home Longitude --edit with your data
const char* WiFi_hostname = "esp32";
#define RXD2 17
#define TXD2 16
HardwareSerial uart(2); //change to uart(2) <--GPIO pins 16 and 17
//MAC Address of the receiver
uint8_t broadcastAddress[] = {0x7C, 0x9E, 0xBD, 0xF5, 0x58, 0x08};
//BME280
// Assumed environmental values:
float referencePressure = 1021.1; // hPa local QFF (official meteor-station reading) -> KEYE, Indianapolis, IND
float outdoorTemp = 35.6; // °F measured local outdoor temp.
float barometerAltitude = 250.698; // meters ... map readings + barometer position -> 824 Feet Garmin, GPS measured Altitude.
BME280I2C::Settings settings(
BME280::OSR_X1,
BME280::OSR_X1,
BME280::OSR_X1,
BME280::Mode_Forced,
BME280::StandbyTime_1000ms,
BME280::Filter_16,
BME280::SpiEnable_False,
BME280I2C::I2CAddr_0x76
);
BME280I2C bme(settings);
float temp(NAN), temperature, hum(NAN), pres(NAN),heatIndex, dewPoint, absHum, altitude, seaLevel;
float currentPressure;
float pastPressure;
float difference; //change in barometric pressure drop; greater than .020 inches of mercury.
float heatId; //Conversion of heatIndex to Farenheit
float dewPt; //Conversion of dewPoint to Farenheit
float altFeet; //Conversion of altitude to Feet
RTC_DATA_ATTR unsigned int readingId;
void getWeatherData()
{
BME280::TempUnit tempUnit(BME280::TempUnit_Celsius);
BME280::PresUnit presUnit(BME280::PresUnit_hPa);
bme.read(pres, temp, hum, tempUnit, presUnit);
EnvironmentCalculations::AltitudeUnit envAltUnit = EnvironmentCalculations::AltitudeUnit_Meters;
EnvironmentCalculations::TempUnit envTempUnit = EnvironmentCalculations::TempUnit_Celsius;
delay(300);
/// To get correct local altitude/height (QNE) the reference Pressure
/// should be taken from meteorologic messages (QNH or QFF)
/// To get correct seaLevel pressure (QNH, QFF)
/// the altitude value should be independent on measured pressure.
/// It is necessary to use fixed altitude point e.g. the altitude of barometer read in a map
absHum = EnvironmentCalculations::AbsoluteHumidity(temp, hum, envTempUnit);
altitude = EnvironmentCalculations::Altitude(pres, envAltUnit, referencePressure, outdoorTemp, envTempUnit);
dewPoint = EnvironmentCalculations::DewPoint(temp, hum, envTempUnit);
heatIndex = EnvironmentCalculations::HeatIndex(temp, hum, envTempUnit);
seaLevel = EnvironmentCalculations::EquivalentSeaLevelPressure(barometerAltitude, temp, pres, envAltUnit, envTempUnit);
heatId = (heatIndex * 1.8) + 32;
dewPt = (dewPoint * 1.8) + 32;
altFeet = 843;
temperature = (temp * 1.8) + 32; //Convert to Fahrenheit
currentPressure = seaLevel * 0.02953; //Convert from hPa to in Hg.
}
//Create a struct_message called myData
struct_message myData;
unsigned long previousMillis = 0; // Stores last time temperature was published
unsigned long delayTime;
RTC_DATA_ATTR int bootCount = 0;
void print_wakeup_reason() {
esp_sleep_wakeup_cause_t wakeup_reason;
wakeup_reason = esp_sleep_get_wakeup_cause();
switch (wakeup_reason)
{
case ESP_SLEEP_WAKEUP_EXT0 : Serial.println("Wakeup caused by external signal using RTC_IO"); break;
case ESP_SLEEP_WAKEUP_EXT1 : Serial.println("Wakeup caused by external signal using RTC_CNTL"); break;
case ESP_SLEEP_WAKEUP_TIMER : Serial.println("Wakeup caused by timer"); break;
case ESP_SLEEP_WAKEUP_TOUCHPAD : Serial.println("Wakeup caused by touchpad"); break;
case ESP_SLEEP_WAKEUP_ULP : Serial.println("Wakeup caused by ULP program"); break;
default : Serial.printf("Wakeup was not caused by deep sleep: %d\n\n", wakeup_reason); break;
}
}
// callback when data is sent
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
Serial.print("\r\nLast Packet Send Status:\t\n");
Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
Serial.println("");
}//volatile boolean callbackCalled;
WiFiClient client;
///Are we currently connected?
boolean connected = false;
///////////////////////////////////////////////
WiFiUDP udp;
// local port to listen for UDP packets
//Settings pertain to NTP
const int udpPort = 1337;
//NTP Time Servers
const char * udpAddress1 = "us.pool.ntp.org";
const char * udpAddress2 = "time.nist.gov";
char incomingPacket[255];
char replyPacket[] = "Hi there! Got the message :-)";
/*
Found this reference on setting TZ: http://www.gnu.org/software/libc/manual/html_node/TZ-Variable.html
Here are some example TZ values, including the appropriate Daylight Saving Time and its dates of applicability. In North American Eastern Standard Time (EST) and Eastern Daylight Time (EDT), the normal offset from UTC is 5 hours; since this is west of the prime meridian, the sign is positive. Summer time begins on March’s second Sunday at 2:00am, and ends on November’s first Sunday at 2:00am.
*/
#define TZ "EST+5EDT,M3.2.0/2,M11.1.0/2"
int DOW, MONTH, DATE, YEAR, HOUR, MINUTE, SECOND;
int lc = 0;
time_t tnow;
char strftime_buf[64];
String dtStamp(strftime_buf);
esp_now_peer_info_t peerInfo;
void setup()
{
Serial.begin(9600);
while (!Serial);
Serial.println();
WiFi.persistent( false ); // for time saving
// Connecting to local WiFi network
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.mode(WIFI_STA);
WiFi.config(staticIP, gateway, subnet, primaryDNS, secondaryDNS);
WiFi.begin(ssid, password);
delay(10);
while (WiFi.status() != WL_CONNECTED)
{
Serial.print(".");
delay(1000);
}
Serial.println("");
Serial.println("WiFi connected");
Serial.print("MAC: ");
Serial.println(WiFi.macAddress());
Serial.print("Server IP: ");
Serial.println(WiFi.localIP());
Serial.println("");
configTime(0, 0, udpAddress1, udpAddress2);
setenv("TZ", "EST+5EDT,M3.2.0/2,M11.1.0/2", 3); // this sets TZ to Indianapolis, Indiana
tzset();
//udp only send data when connected
if (connected)
{
//Send a packet
udp.beginPacket(udpAddress1, udpPort);
udp.printf("Seconds since boot: %u", millis() / 1000);
udp.endPacket();
}
Serial.print("wait for first valid timestamp ");
while (time(nullptr) < 100000ul)
{
Serial.print(".");
delay(1000);
}
Serial.println(" time synced");
getDateTime();
Serial.println(dtStamp);
WiFi.disconnect(true);
Serial.print("WiFi SSID Disconnected: ");
Serial.println(ssid);
Serial.println("");
WiFi.mode(WIFI_OFF);
// read sensor first before awake generates heat
getWeatherData();
//Set device as a Wi-Fi Station
WiFi.persistent( false ); // for time saving ---setup Access Point
WiFi.mode(WIFI_STA);
WiFi.begin(APssid, APpassword);
while ((WiFi.status() != WL_CONNECTED) && (WiFi.status() == ! WL_NO_SSID_AVAIL)){
delay(1000);
Serial.println("Connecting to Access Point...");
}
Serial.printf("This mac: %s, ", WiFi.macAddress().c_str());
Serial.printf("target mac: %02x%02x%02x%02x%02x%02x", remoteMac[0], remoteMac[1], remoteMac[2], remoteMac[3], remoteMac[4], remoteMac[5]);
Serial.printf(", channel: %i\n", CHAN_AP);
Wire.begin(21, 22);
while (!bme.begin()) {
Serial.println("");
Serial.println("Could not find BME280 sensor!");
delayTime = 1000;
}
// bme.chipID(); // Deprecated. See chipModel().
switch (bme.chipModel()) {
case BME280::ChipModel_BME280:
Serial.println("");
Serial.println("Found BME280 sensor! Success.");
break;
case BME280::ChipModel_BMP280:
Serial.println("");
Serial.println("Found BMP280 sensor! No Humidity available.");
break;
default:
Serial.println("");
Serial.println("Found UNKNOWN sensor! Error!");
}
//Init ESP-NOW
if (esp_now_init() != ESP_OK) {
Serial.println("Error initializing ESP-NOW");
return;
}
// Once ESPNow is successfully Init, we will register for Send CB to
// get the status of Trasnmitted packet
esp_now_register_send_cb(OnDataSent);
//Register peer
esp_now_peer_info_t peerInfo;
memcpy(peerInfo.peer_addr, broadcastAddress, 6);
peerInfo.channel = CHAN_AP;
peerInfo.encrypt = false;
//Add peer
if (esp_now_add_peer(&peerInfo) != ESP_OK) {
Serial.println("Failed to add peer");
return;
}
//Increment boot number and print it every reboot
++bootCount;
Serial.println("Boot number: " + String(bootCount));
//Print the wakeup reason for ESP32
print_wakeup_reason();
/*
First we configure the wake up source
We set our ESP32 to wake up every 5 seconds
*/
esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
Serial.println("");
Serial.println("ESP32_Sender going into Deep Sleep for: " + String(TIME_TO_SLEEP) + " Minutes");
Serial.println("");
}
void loop()
{
/* Updates frequently */
//unsigned long currentTime = millis();
//udp only send data when connected
if (connected)
{
//Send a packet
udp.beginPacket(udpAddress1, udpPort);
udp.printf("Seconds since boot: %u", millis() / 1000);
udp.endPacket();
}
getDateTime();
if ((MINUTE % 5 == 0) && (SECOND == 0))
{
getWeatherData();
delay(500);
++readingId; //Added today
//Set values to send
myData.id = BOARD_ID;
myData.temp = temperature;
myData.heat = heatId;
myData.hum = hum;
myData.dew = dewPt;
myData.press = currentPressure;
myData.readingId = readingId; //Changed today
esp_wifi_start();
//Send message via ESP-NOW
esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *) &myData, sizeof(myData));
if (result == ESP_OK) {
Serial.println("Sent with success");
Serial.println("readingId: " + (String)readingId);
Serial.println(dtStamp);
esp_wifi_stop();
Serial.println("Going to sleep now");
Serial.flush();
esp_deep_sleep_start();
Serial.println("This will never be printed");
}
else {
Serial.println("Error sending the data");
}
}
}
String getDateTime()
{
struct tm *ti;
tnow = time(nullptr) + 1;
//strftime(strftime_buf, sizeof(strftime_buf), "%c", localtime(&tnow));
ti = localtime(&tnow);
DOW = ti->tm_wday;
YEAR = ti->tm_year + 1900;
MONTH = ti->tm_mon + 1;
DATE = ti->tm_mday;
HOUR = ti->tm_hour;
MINUTE = ti->tm_min;
SECOND = ti->tm_sec;
strftime(strftime_buf, sizeof(strftime_buf), "%a , %m/%d/%Y , %H:%M:%S %Z", localtime(&tnow));
dtStamp = strftime_buf;
return (dtStamp);
}
@Tech500
Copy link
Author

Tech500 commented Feb 7, 2022

Working code...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment