ESP8266, InfraRed, code works in loop but not outside of loop?

Hi all.

I'm building a thermostat device to control two AC units in the same room. Rather than have them fight each other, I figured I'd build a controller that measures temperature and then gets two separate devices to fire the same IR command to each unit, thus unifying them.

I'm using Wemos D1 Minis, and have used ESPNOW for the wireless communication and IRRemote for the IR interface.

Testing the code, the demo code "Out the box" for Daikin ACs worked in terms of successfully sending commands that were picked up by the unit.

However with my code that included a bunch of if statements to determine which settings to use, and a 2nd tab full of the different command functions, it appeared to send a command, but the data it sent was not recognised as a Daikin protocol. If I put the IR code back into the loop somewhere, it seems to work, but I am trying to understand why it didn't work as I had originally intended. I am assuming it is something to do with timings somewhere as the process essentially relies on ESPNOW picking up a command signal and then, based on the command, going to the relevant function which would send the IR code, all outside of the loop. See below:


#include <ESP8266WiFi.h>
#include <espnow.h>

#include <Arduino.h>
#include <IRremoteESP8266.h>
#include <IRsend.h>
#include <ir_Daikin.h>

const uint16_t kIrLed = D1;  // ESP8266 GPIO pin to use. Recommended: 4 (D2).
IRDaikinESP ac(kIrLed);      // Set the GPIO to be used to sending the message

int red = D8;
int green = D7;
int blue = D6;
bool commandsent;

// Structure example to receive data
// Must match the sender structure
typedef struct data_struct {
int acmode;
int tempsetting;
} data_struct;

// Create a struct_message called myData
data_struct myData;


void setup() {
// Initialize Serial Monitor
Serial.begin(115200);
ac.begin();
commandsent = true;

pinMode(red, OUTPUT);
pinMode(green, OUTPUT);
pinMode(blue, OUTPUT);
digitalWrite(red, LOW);
digitalWrite(green, LOW);
digitalWrite(blue, LOW);

// Set device as a Wi-Fi Station
WiFi.mode(WIFI_STA);
WiFi.disconnect();

// Init ESP-NOW
if (esp_now_init() != 0) {
  Serial.println("Error initializing ESP-NOW");
  return;
}

// Once ESPNow is successfully Init, we will register for recv CB to
// get recv packer info
esp_now_set_self_role(ESP_NOW_ROLE_SLAVE);
esp_now_register_recv_cb(OnDataRecv);
}


// Callback function that will be executed when data is received
void OnDataRecv(uint8_t *mac, uint8_t *incomingData, uint8_t len) {
memcpy(&myData, incomingData, sizeof(myData));
Serial.print("Bytes received: ");
Serial.println(len);
Serial.print("AC Mode: ");
Serial.println(myData.acmode);
Serial.print("Set Temp: ");
Serial.println(myData.tempsetting);
Serial.println();
commandsent = false;
}

void loop() {

if ((myData.acmode == 0) && (commandsent == false)) {
  turnoff();
}


if ((myData.acmode == 1) && (myData.tempsetting == 16) && (commandsent == false)) {
  heat16();
}

if ((myData.acmode == 1) && (myData.tempsetting == 17) && (commandsent == false)) {
  heat17();
}

if ((myData.acmode == 1) && (myData.tempsetting == 18) && (commandsent == false)) {
  heat18();
}

if ((myData.acmode == 1) && (myData.tempsetting == 19) && (commandsent == false)) {
  heat19();
}

if ((myData.acmode == 1) && (myData.tempsetting == 20) && (commandsent == false)) {
  heat20();
}

if ((myData.acmode == 1) && (myData.tempsetting == 21) && (commandsent == false)) {
  heat21();
}

if ((myData.acmode == 1) && (myData.tempsetting == 22) && (commandsent == false)) {
  heat22();
}

if ((myData.acmode == 1) && (myData.tempsetting == 23) && (commandsent == false)) {
  heat23();
}

if ((myData.acmode == 1) && (myData.tempsetting == 24) && (commandsent == false)) {
  heat24();
}

if ((myData.acmode == 1) && (myData.tempsetting == 25) && (commandsent == false)) {
  heat25();
}

if ((myData.acmode == 2) && (myData.tempsetting == 16) && (commandsent == false)) {
  cool16();
}

if ((myData.acmode == 2) && (myData.tempsetting == 17) && (commandsent == false)) {
  cool17();
}

if ((myData.acmode == 2) && (myData.tempsetting == 18) && (commandsent == false)) {
  cool18();
}

if ((myData.acmode == 2) && (myData.tempsetting == 19) && (commandsent == false)) {
  cool19();
}

if ((myData.acmode == 2) && (myData.tempsetting == 20) && (commandsent == false)) {
  cool20();
}

if ((myData.acmode == 2) && (myData.tempsetting == 21) && (commandsent == false)) {
  cool21();
}

if ((myData.acmode == 2) && (myData.tempsetting == 22) && (commandsent == false)) {
  cool22();
}

if ((myData.acmode == 2) && (myData.tempsetting == 23) && (commandsent == false)) {
  cool23();
}

if ((myData.acmode == 2) && (myData.tempsetting == 24) && (commandsent == false)) {
  cool24();
}

if ((myData.acmode == 2) && (myData.tempsetting == 25) && (commandsent == false)) {
  cool25();
}
}

I should add that I "Solved" my issue by adding the commandsent bool, so that the functions are now called from within the Loop. Previously all those if statements in the loop function, were in the OnDataRecv function, which was the issue...I'm just trying to find out why so I don't do it again.

This looks like a rather ambiguous solution, since commandsent flag is set to false after first command and no longer changes during the program.
That is, judging by the logic, this solution should work only once after start.
Check if you can accept more than one command

Sorry, the joys of have a 3 year old who should be in bed. I'd meant to add that in the functions that I didn't include (there's 400 lines for all the different AC commands), each one has a "commandsent = true; statement", resetting the flag so that I also don't end up going into an infinite loop of repeatedly sending the same command.

So the flow for that bool is that when an ESPNOW packet is received, commandsent is set to false. When the corresponding IR command is sent, the flag is reset to true, until the next ESPNOW packet comes in.

What I don't get is why I couldn't just have the IF statments in the OnDataRecv function, and go direct to the IR functions, without having to first go to the loop function, which until this point was empty?

Sorry, I dont understand you.
Could you please to show an example, illustrates the issue?

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.