Hi together,
I’ve started with arduino last year and soon found my way to esp8266 and after that to home assistant and ESPHome. Currently I’m working on a project which is supposed to work as follows.
I have two Arduinos in my backyard, one should monitor the watering process in the garden and the second is supposed to open/close a chicken door. As I sadly do not have access to my WiFi in the backyard, I want to use a 433mhz transceiver to communicate with a esp8266 being connected to ESPHome and allowing control of watering my garden and opening/closing chiecken door via Home Assistant. By now, the 433mhz connection works, however, I’m stuck when it comes to sharing the data from the esp8266 with ESPHome and switching things which are not GPIOs.
What I was hoping to find is basically a arduino scetch running independent of the ESPHome PollingComponent so that the PollingComponent would just get values at defined timepoints whereas the arduino scetch runs as usual. Any advice about what to read or where I could find beginner friendly help for this problem?
Here’s the code, I roughly want to use on the esp and which works so far (also if you can see a huge error within this code which might cause problems, please let me know)
#include <Arduino.h>
#include <SPI.h>
#include <RH_ASK.h>
#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>
#ifndef STASSID
#define STASSID ***
#define STAPSK ***
#endif
const char* ssid = STASSID;
const char* password = STAPSK;
RH_ASK driver(500, 13, 5, 0);
#define SERIAL_BAUD 9600
const int led_pin=13;
const int transmit_pin = 2;
const int receive_pin = 3;
unsigned long startMillis = 0;
unsigned long currentMillis;
unsigned long lastTXMillis = 0;
uint8_t sender_number = 0;
unsigned long t_last_package = 10000;
uint8_t counter = 1;
struct package
{
uint8_t sender_number;
uint8_t send_sender_number;
// you may add time as string
uint16_t hum_beet1;
uint16_t hum_beet2;
uint16_t hum_beet3;
uint16_t hum_beet4;
uint8_t temp;
uint8_t hum;
};
typedef struct package Package;
Package data;
void requestData(){
Serial.println("requesting data");
digitalWrite(led_pin, HIGH);
data.sender_number = sender_number;
if(counter == 1 || data.send_sender_number == 1){
Serial.println("data1");
data.send_sender_number = 1;
//counter++;
data.hum_beet1;
data.hum_beet2;
data.hum_beet3;
data.hum_beet4;
}
else if(counter == 2 || data.send_sender_number == 2){
data.send_sender_number = 2;
counter = 1;
}
else{
counter = 1;
}
driver.send((uint8_t *)&data, sizeof(data));
driver.waitPacketSent();
digitalWrite(led_pin, LOW);
}
void readData(){
uint8_t buf[sizeof(data)];
uint8_t buflen = sizeof(data);
if(driver.recv(buf, &buflen)){
memcpy(&data, &buf, buflen);
Serial.println("Got Data");
Serial.print("Beet1: ");
Serial.println(data.hum_beet1);
Serial.print("Beet2: ");
Serial.println(data.hum_beet2);
Serial.print("Beet3: ");
Serial.println(data.hum_beet3);
Serial.print("Beet4: ");
Serial.println(data.hum_beet4);
Serial.print("Buf: ");
Serial.write(buf, buflen);
}
}
void setup() {
Serial.begin(SERIAL_BAUD);
Serial.println("Booting");
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
while (WiFi.waitForConnectResult() != WL_CONNECTED) {
Serial.println("Connection Failed! Rebooting...");
delay(5000);
ESP.restart();
}
ArduinoOTA.setPassword("***");
ArduinoOTA.onStart([]() {
String type;
if (ArduinoOTA.getCommand() == U_FLASH) {
type = "sketch";
} else { // U_FS
type = "filesystem";
}
Serial.println("Start updating " + type);
});
ArduinoOTA.onEnd([]() {
Serial.println("\nEnd");
});
ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
});
ArduinoOTA.onError([](ota_error_t error) {
Serial.printf("Error[%u]: ", error);
if (error == OTA_AUTH_ERROR) {
Serial.println("Auth Failed");
} else if (error == OTA_BEGIN_ERROR) {
Serial.println("Begin Failed");
} else if (error == OTA_CONNECT_ERROR) {
Serial.println("Connect Failed");
} else if (error == OTA_RECEIVE_ERROR) {
Serial.println("Receive Failed");
} else if (error == OTA_END_ERROR) {
Serial.println("End Failed");
}
});
ArduinoOTA.setHostname("***");
ArduinoOTA.setPassword("***");
ArduinoOTA.begin();
Serial.println("Ready");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
ESP.wdtEnable(5000);
if(!driver.init())
{
Serial.println("init failied");
}
}
void loop() {
if(millis()<=600000)
ArduinoOTA.handle();
delay(10);
if(t_last_package <= millis()-startMillis){
startMillis = millis();
requestData();
}
readData();
}
in case you do also need the code for the “executing” component, meaning the arduino nano which is going to be placed in the backyard:
#include <Arduino.h>
#include <SPI.h>
#include <RH_ASK.h>
RH_ASK driver(500, 11, 12, 0);
#define SERIAL_BAUD 9600
const int led_pin=13;
const int transmit_pin = 2;
const int receive_pin = 3;
unsigned long startMillis = 0;
unsigned long currentMillis;
unsigned long lastTXMillis = 0;
uint8_t sender_number = 1;
int t_last_package = 5000;
const uint8_t hum_sensor[] = {A0, A1, A2, A3};
struct package
{
uint8_t sender_number;
uint8_t send_sender_number;
// you may add time as string
uint16_t hum_beet1;
uint16_t hum_beet2;
uint16_t hum_beet3;
uint16_t hum_beet4;
uint8_t temp;
uint8_t hum;
};
typedef struct package Package;
Package data;
void readSensor(){
data.hum_beet1 = analogRead(hum_sensor[0]);
data.hum_beet2 = analogRead(hum_sensor[1]);
data.hum_beet3 = analogRead(hum_sensor[2]);
data.hum_beet4 = analogRead(hum_sensor[3]);
}
void sendData(){
Serial.println("Sending data");
digitalWrite(led_pin, HIGH);
data.sender_number = sender_number;
data.send_sender_number = 0;
driver.send((uint8_t *)&data, sizeof(data));
driver.waitPacketSent();
digitalWrite(led_pin, LOW);
}
void readData(){
uint8_t buf[sizeof(data)];
uint8_t buflen = sizeof(data);
if(driver.recv(buf, &buflen)){
startMillis = millis();
memcpy(&data, &buf, buflen);
Serial.print("Read data: ");
Serial.println(data.send_sender_number);
Serial.print("Beet1: ");
Serial.println(data.hum_beet1);
Serial.print("Beet2: ");
Serial.println(data.hum_beet2);
Serial.print("Beet3: ");
Serial.println(data.hum_beet3);
Serial.print("Beet4: ");
Serial.println(data.hum_beet4);
Serial.print("Buf: ");
Serial.write(buf, buflen);
}
}
void setup() {
Serial.begin(SERIAL_BAUD);
if(!driver.init())
{
Serial.println("init failied");
}
}
void loop() {
readData();
delay(100);
if(data.send_sender_number == 1){
readSensor();
for(int i=0; i<5; i++)
sendData();
}
}
And here my first attempt to hand the data to Home Assistant. I am able to hand over individual data following the guide given here https://esphome.io/components/sensor/custom.html, however implementing the 433mhz transceiver fails
#include <Arduino.h>
#include <Wire.h>
#include <SPI.h>
#include <RH_ASK.h>
class MyCustomSensor: public PollingComponent, public Sensor {
public:
Sensor *beet1_sensor = new Sensor();
Sensor *beet2_sensor = new Sensor();
Sensor *beet3_sensor = new Sensor();
Sensor *beet4_sensor = new Sensor();
const int transmit_pin = 5;
const int receive_pin = 13;
unsigned long startMillis = 0;
unsigned long currentMillis;
unsigned long lastTXMillis = 0;
uint8_t sender_number = 0;
uint8_t send_sender_number;
int t_last_package = 10000;
uint8_t counter = 1;
int humidity1;
int humidity2;
int humidity3;
int humidity4;
const uint16_t transmit_rate = 500;
const uint8_t rx_pin = 13;
const uint8_t tx_pin = 5;
const bool push_to_talk = 0;
RH_ASK driver;
struct package
{
uint8_t sender_number;
uint8_t send_sender_number;
// you may add time as string
int hum_beet1;
int hum_beet2;
int hum_beet3;
int hum_beet4;
uint8_t temp;
uint8_t hum;
};
typedef struct package Package;
Package data;
void requestData(){
data.sender_number = sender_number;
if(counter == 1 || data.send_sender_number == 1){
Serial.println("data1");
data.send_sender_number = 1;
//counter++;
}
else if(counter == 2 || data.send_sender_number == 2){
data.send_sender_number = 2;
counter = 1;
}
else{
counter = 1;
}
driver.send((uint8_t *)&data, sizeof(data));
driver.waitPacketSent();
}
void readData(){
uint8_t buf[sizeof(data)];
uint8_t buflen = sizeof(data);
if(driver.recv(buf, &buflen))
memcpy(&data, &buf, buflen);
humidity1 = data.hum_beet1;
humidity2 = data.hum_beet2;
humidity3 = data.hum_beet3;
humidity4 = data.hum_beet4;
}
void publish(){
beet1_sensor->publish_state(humidity1);
beet2_sensor->publish_state(humidity2);
beet3_sensor->publish_state(humidity3);
beet4_sensor->publish_state(humidity4);
}
// constructor
MyCustomSensor() : PollingComponent(60000) {}
void setup() override {
RH_ASK driver(transmit_rate, rx_pin, tx_pin, push_to_talk);
}
void update() override {
requestData();
startMillis = millis();
while(10000>= millis()-startMillis){
readData();
delay(10);
}
publish();
}
};
I’m very thankfull for any help and I’m also willing to do some readingt and to do some reading about how to hand data over from a method to Home Assistant. It might already help, if you could point out why my code works if I define const values for the humidities and it fails when I want to receive data via 433mhz and what I might use to solve this issue.
And if there is something I should do differently when asking for help, please also let me know, this is my first post ever, so there is probably still a lot I can do better.
Best wishes