Hi HeliBob, I got it working and it works exactly as I planned, where it reads an input on the CONTROLLER board, and sends the output to the same IO on the SLAVE board - works beautifully.
That's the good news. The bad news is that my design won't work in the application for which I intended
. I have searched and searched online for the answer, and I am not even sure if what I want is possible - but I keep thinking that it must be programmable.
- I want to install two boards into a 24VDC system. Each module (each enclosure - one for CONTROLLER and one for SLAVE) has a converter board (24V to 5V) to power the boards using available power and eliminating the need for a battery.
- The SLAVE has constant battery power.
- The CONTROLLER only receives power when signaled (a 24V signal to the board is the trigger, and only power)
- The idea is that I need the SLAVE to send an output at 3.3 V to D4 only when the CONTROLLER is powered.
- GOOD NEWS - when the CONTROLLER transmits, everything works well - signal is received by the SLAVE, and and the SLAVE outputs 3.3 V on D4
- BAD NEWS - when the CONTROLLER loses power, the SLAVE follows whatever instruction it was last given, which was OUTPUT D4 - and power remains at D4 of the SLAVE instead of reading LOW as I want it to.
A lot of the above are absolutes and cannot be changed, which is the challenge. All I really need to do is bring constant power to the CONTROLLER too, and then when the signal comes and goes, the CONTROLLER communicates updates to the SLAVE.
My searching on the internet was to find how to program the ESPnow to be in a loop, where it looks for a signal from the CONTROLLER every 15 seconds (for example), and when it sees the signal, it activates D4 OUTPUT to high. If the CONTROLLER stops transmitting because it lost its signal (no power to the CONTROLLER), when the SLAVE checks again in 15 seconds, it will see that the CONTROLLER is not transmitting, and then the SLAVE turns D4 to LOW (off).
I programmed last when I was 15 in 1985 on a Commodore SuperPET in Basic - a fair bit different than this
.
Is what I am trying to do even possible? How advanced is the programming?
Here are the programs for the CONTROLLER and SLAVE:
CONTROLLER:
#include<ESP8266WiFi.h>
#include<espnow.h>
#define MY_NAME "CONTROLLER_NODE"
#define MY_ROLE ESP_NOW_ROLE_CONTROLLER // set the role of this device: CONTROLLER, SLAVE, COMBO
#define RECEIVER_ROLE ESP_NOW_ROLE_SLAVE // set the role of the receiver
#define WIFI_CHANNEL 1
uint8_t receiverAddress[] = {0x44, 0x17, 0x93, 0x1C, 0x3B, 0x6B}; // please update this with the MAC address of the receiver
struct __attribute__((packed)) dataPacket {
int sensor1;
};
void transmissionComplete(uint8_t *receiver_mac, uint8_t transmissionStatus) {
if (transmissionStatus == 0) {
Serial.println("Data sent successfully");
} else {
Serial.print("Error code: ");
Serial.println(transmissionStatus);
}
}
void setup() {
Serial.begin(115200); // initialize serial port
Serial.println();
Serial.println();
Serial.println();
Serial.print("Initializing...");
Serial.println(MY_NAME);
Serial.print("My MAC address is: ");
Serial.println(WiFi.macAddress());
WiFi.mode(WIFI_STA);
WiFi.disconnect(); // we do not want to connect to a WiFi network
pinMode(4, INPUT);
if (esp_now_init() != 0) {
Serial.println("ESP-NOW initialization failed");
return;
}
esp_now_set_self_role(MY_ROLE);
esp_now_register_send_cb(transmissionComplete); // this function will get called once all data is sent
esp_now_add_peer(receiverAddress, RECEIVER_ROLE, WIFI_CHANNEL, NULL, 0);
Serial.println("Initialized.");
}
void loop() {
dataPacket packet;
packet.sensor1 = digitalRead(4);
esp_now_send(receiverAddress, (uint8_t *) &packet, sizeof(packet));
Serial.println(packet.sensor1);
}
And here is the program for the SLAVE:
#include<ESP8266WiFi.h>
#include<espnow.h>
#define MY_NAME "SLAVE_NODE"
struct __attribute__((packed)) dataPacket {
int sensor1;
};
void setup() {
Serial.begin(115200); // initialize serial port
Serial.println();
Serial.println();
Serial.println();
Serial.print("Initializing...");
Serial.println(MY_NAME);
Serial.print("My MAC address is: ");
Serial.println(WiFi.macAddress());
WiFi.mode(WIFI_STA);
WiFi.disconnect(); // we do not want to connect to a WiFi network
pinMode(4, OUTPUT);
// digitalWrite(4, 0); attempt to start with LOW - didn't work
if (esp_now_init() != 0) {
Serial.println("ESP-NOW initialization failed");
return;
}
esp_now_register_recv_cb(dataReceived); // this function will get called once all data is sent
Serial.println("Initialized.");
}
void dataReceived(uint8_t *senderMac, uint8_t *data, uint8_t dataLength) {
char macStr[18];
dataPacket packet;
snprintf(macStr, sizeof(macStr), "%02x:%02x:%02x:%02x:%02x:%02x", senderMac[0], senderMac[1], senderMac[2], senderMac[3], senderMac[4], senderMac[5]);
Serial.println();
Serial.print("Received data from: ");
Serial.println(macStr);
memcpy(&packet, data, sizeof(packet));
Serial.print("sensor1: ");
Serial.println(packet.sensor1);
digitalWrite(4, packet.sensor1);
Serial.print("Actual "); // my attempt to read the actual, so that I could better compare to dmm
Serial.println(digitalRead(4)); // same as previous line
}
void loop() {
// Serial.println("Void Loop "); //My newbie test to understand how program is flowing
}