JAndrassy / ArduinoOTA

Arduino library to upload sketch over network to Arduino board with WiFi or Ethernet libraries
GNU Lesser General Public License v2.1
437 stars 89 forks source link

Error when 'Upload using programmer' to Mega 2560 with optiboot bootloader #129

Closed RStaes closed 2 years ago

RStaes commented 2 years ago

Hello,

i have this problem: I have an Arduino Mega 2560 and flashed the optiboot bootloader to it with an uno as programmer. All went fine. I uploaded my sketch, see code below, with use of the serial port. When upload is ready i can ping the Mega. Then, after a restart of Arduino IDE, i can't see the network port. But when i choose for programmer 'Arduino OTA 192.168.1.119' and click 'Upload using programmer' I get this error:

Can you help me out?

Arduino: 1.8.13 (Windows 10), Board: "Optiboot on Mega2560"

Sketch uses 41456 bytes (15%) of program storage space. Maximum is 261120 bytes.

Global variables use 3174 bytes (38%) of dynamic memory, leaving 5018 bytes for local variables. Maximum is 8192 bytes.

C:\Users\Robin\AppData\Local\Arduino15\packages\Optiboot\hardware\avr/tools/arduinoOTA.exe -address 192.168.1.119 -port 65280 -t 30 -username arduino -password password -sketch C:\Users\Robin\AppData\Local\Temp\arduino_build_384939/Zoneverwarming3.ino.bin -upload /sketch -b 

Connecting to board ...  done
Uploading sketch ...  done
Flashing sketch ... Error flashing the sketch
Error flashing the sketch

This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.

Sketch:

#include <Ethernet.h>
#include <ArduinoOTA.h>
#include <SPI.h>
#include "PubSubClient.h"
#include <OneWire.h>
#include <DallasTemperature.h>
#include <avr/wdt.h> // for Watchdog

#define ONE_WIRE_BUS 2
#define CLIENT_ID       "meterkast"
#define PUBLISH_DELAY   10000
#define FAST_MODE // 50 times faster execution; consider to disconnect your real CV/Pump!

// In Normal operation to loop runs 10 times per second; so 10 counts/second (600 represents ca 1 minute)
#define VALVE_TIME             3000L    // 5 minutes to open/close a valve (on the safe site; takes typically 3 to 5 minutes)
#ifdef  FAST_MODE
#define PUMP_MAINTENANCE_TIME  108000L // For evaluation, activates Floor Unit pump maintenance run once per 4 minutes (time stamp 3 hours)
#else
#define PUMP_MAINTENANCE_TIME  1300000L // Activates Floor Unit pump maintenance run once per 36 hours. Needed to keep pump working
#endif
#define PUMP_ACTIVATION_TIME   5000L    // Activates the pump for ca 8 minutes (10 seconds in test mode)
#define COOLDOWN_TIME          18000L   // When heating is done, continue water circulation for another 30 minutes (40 seconds in test mode)
                                        // This enables further dissipation the heat into the floor (typically takes 15 to 30 minutes)

#include "./Devices.h" // valves, pumps, thermostat classes (use the constants defines above)

#define HEATER_PIN      33 // output to a Relay that is wired with the Thermostat input of your heating system
#define FU_PUMP_PIN     25 // output to a Relay that switches the Floor Unit Pump
#define PORCH_RELAY     24 // Zone 1: output to a Relay that controls the Valve(s)
#define LIVING_RELAY    27 // Zone 2: output to a Relay that controls the Valve(s)
#define PLAYROOM_RELAY  26 // Zone 3: output to a Relay that controls the Valve(s)
#define OFFICE_RELAY    29 // Zone 4: output to a Relay that controls the Valve(s)
#define BATHROOM_RELAY  32 // Zone 5: output to a Relay that controls the Valve(s)
#define STORAGE_RELAY   31 // Zone 6: output to a Relay that controls the Valve(s)
#define UPSTAIRS_RELAY  34 // Zone 7: output to a Relay that controls the Valve(s)

#define HEATING_LED     41 // On when heating, Alternates during cooldown, is Off in idle mode
#define INDICATION_LED  13 // Alternates the on board LED to indicate board runs; can be easily removed to free an extra IO pin!!

// Configure the Floor Unit Zones/rooms. Each zone/room owns a name, valve and thermostat:
#define NR_ZONES 7
#define NR_ZONETHERMOSTATS 7

OneWire oneWire(ONE_WIRE_BUS);  
DallasTemperature sensors(&oneWire);
byte mac[]    = {  0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED };
IPAddress ip2(192, 168, 1, 64);
EthernetClient ethClient;
PubSubClient mqttClient(ethClient);
DeviceAddress Thermometer;
long previousMillis;
const int controlPin[] = {25,24,27,26,29,32,31,34,33,36,35,38,37,40,39,41}; // define pins
const int triggerType = LOW;// your relay type
int deviceCount = 0;
int Counter = 0;
bool Thermo           = false;  
float IsTemp          = 18.0;
float SetTemp         = 21.0;
String IsTopic        = "/is";
String SetTopic       = "/set";
String ModeTopic      = "/mode";                 //0 = “off”, 1 = “heat”, 2 = “cool”
String ModeStateTopic = "/modestate"; 
String ActionTopic    = "/action";
String Action         = "off";
String Mode           = "";
String ModeState      = "heat";
int hysteresis        = 2;
int offset            = 0;

struct Zone {
  String name;
  Valve valve;
  bool thermostat;
  byte  sensor[8];
  float IsTemp;
  float SetTemp;
  String IsTopic;
  String SetTopic;
  String ModeTopic;         //0 = “off”, 1 = “heat”, 2 = “cool”
  String ActionTopic;
  String ModeStateTopic;
  String Action;
  String Mode;
  String ModeState;
};
Zone Zones[NR_ZONES] = { {"portiek",    Valve(PORCH_RELAY,    "Portiek Relay"),     Thermo,  { 0x28, 0xFF, 0x29, 0xD0, 0xA1, 0x17, 0x05, 0xA2 }, IsTemp, SetTemp, IsTopic, SetTopic, ModeTopic, ActionTopic, ModeStateTopic, Action, Mode, ModeState},
                         {"woonkamer",  Valve(LIVING_RELAY,   "Woonkamer Relay"),   Thermo,  { 0x28, 0xFF, 0x29, 0xD0, 0xA1, 0x17, 0x05, 0xA2 }, IsTemp, SetTemp, IsTopic, SetTopic, ModeTopic, ActionTopic, ModeStateTopic, Action, Mode, ModeState},
                         {"speelkamer", Valve(PLAYROOM_RELAY, "Speelkamer Relay"),  Thermo,  { 0x28, 0xE2, 0xCE, 0x0D, 0x5A, 0x20, 0x01, 0xCA }, IsTemp, SetTemp, IsTopic, SetTopic, ModeTopic, ActionTopic, ModeStateTopic, Action, Mode, ModeState},
                         {"kantoor",    Valve(OFFICE_RELAY,   "Kantoor Relay"),     Thermo,  { 0x28, 0xBB, 0xA9, 0xF9, 0x59, 0x20, 0x01, 0xA9 }, IsTemp, SetTemp, IsTopic, SetTopic, ModeTopic, ActionTopic, ModeStateTopic, Action, Mode, ModeState},
                         {"badkamer",   Valve(BATHROOM_RELAY, "Badkamer Relay"),    Thermo,  { 0x28, 0xFF, 0x29, 0xD0, 0xA1, 0x17, 0x05, 0xA2 }, IsTemp, SetTemp, IsTopic, SetTopic, ModeTopic, ActionTopic, ModeStateTopic, Action, Mode, ModeState},
                         {"berging",    Valve(STORAGE_RELAY,  "Berging Relay"),     Thermo,  { 0x28, 0xBB, 0xA9, 0xF9, 0x59, 0x20, 0x01, 0xA9 }, IsTemp, SetTemp, IsTopic, SetTopic, ModeTopic, ActionTopic, ModeStateTopic, Action, Mode, ModeState},
                         {"boven",      Valve(UPSTAIRS_RELAY, "Boven Relay"),       Thermo,  { 0x28, 0xBB, 0xA9, 0xF9, 0x59, 0x20, 0x01, 0xA9 }, IsTemp, SetTemp, IsTopic, SetTopic, ModeTopic, ActionTopic, ModeStateTopic, Action, Mode, ModeState}
                         };

LED           iLED(INDICATION_LED, "Indicator LED"); // can be removed if you run out of IO's
LED           hLED(HEATING_LED, "Heating LED");
Manipulator   CV(HEATER_PIN, "CV Heater");
Pump          FUPump(FU_PUMP_PIN, "Floor Unit Pump");

void printConfiguration() {
   Serial.println("------ Board Configuration: ---------");
   iLED.Print();
   hLED.Print();
   CV.Print();
   FUPump.Print();
   for(int i=0; i<NR_ZONES; i++) {
      Serial.print("Zone["); Serial.print(i+1); 
      Serial.print("]: "); Serial.println(Zones[i].name);
      Serial.print(" - "); Zones[i].valve.Print();
      //Serial.print(" - "); Zones[i].thermostat.Print();
   }
   Serial.println("-------------------------------------");
}

// state machine, with both transition and state handling actions
class State
{
  public:
  enum states {
    idle,
    on,
    cooldown
  };

  private:
  //vars
  states _State;
  unsigned long cooldownCount;

  public: 
  //constructor
  StateMAchine()   {
    _State = idle;
  }

  // Getter
  states const& operator()() const {
      return _State;    
  }

  // Setter
  void operator()(states const& newState) {
      printTimeStamp();
      Serial.print(": State change from [");
      Print();
      _State = newState;
      Serial.print("] to [");
      Print();
      Serial.println("]");
      // deal with transition actions to the new state
      switch(_State)
      {
       case idle:
          hLED.Off();
          CV.Off();  // stop heating
          FUPump.Off(); 
          allValvesOff();
          break;
       case on:
          hLED.On();
          CV.On(); // start heating, but Floor unit pump has to wait till at least one zone is open
          break;
       case cooldown:
          CV.Off();  // stop heating
          allValvesOn(); // open all zones for cooldown; pump has to wait for this
          break;  
       default: 
         Serial.println("WARNING Unhandled State transition");
         break;
      }
  }

  // Do the state handling; to be called repatively by the loop()  
  void doProcessingActions() {
    switch(_State) {
       case on:
        onProcessing(); // As long heating is requested open/close zones matching the heating requests
        break;    
      case cooldown:
        coolDownProcessing(); // take 30 minutes to dissipate remaing Heat into the floor
        break;
      case idle:
        idleProcessing(); // operate pumps/valves once per day
        break;
      default: 
        Serial.println("ERROR Unhandled State");
        break;
    }
  }

  void setCoolDownNeeded() {
    cooldownCount = COOLDOWN_TIME;
  }
  bool whileCoolDownNeeded() { // down counts the time
     if (cooldownCount > 0) {
        cooldownCount--;
     }
     return checkCoolDownNeeded();
  }
  bool checkCoolDownNeeded() {
     return (cooldownCount> 0);
  }

  void Print()   {
    switch(_State)
    {
     case idle:
        Serial.print("idle");
        break;
     case on:
        Serial.print("on");
        break;
     case cooldown:
         Serial.print("cooldown");
        break;  
    }
  }
};

// The global state machine
State    CVState;

void setup(void)
{ 
  Serial.begin(9600);
  SetPins();
  sensors.begin();
  SetEthernet();
  CheckDataChange();
  printTimeStamp();
  Serial.print(": ");
  #ifdef FAST_MODE
    Serial.println("CV Zone Controller started in TestMode!\n"
                  " - Board time runs ca 50 times faster\n"
                  " - Pump maintenance cycle runs ever 3 hours instead once per 36 hours");
  #else
    Serial.println("CV Zone Controller started. Time stamps (dd:hh:mm:ss)");
  #endif
  Serial.println(" - Time stamps format (dd:hh:mm:ss)");
  printConfiguration();
  Serial.print("Hysteresis = ");
  Serial.println(hysteresis);
  Serial.print("Offset = ");
  Serial.println(offset);
  wdt_enable(WDTO_2S);  // Watchdog: reset board after two seconds, if no "pat the dog" received
  // start the OTEthernet library with internal (flash) based storage
  ArduinoOTA.begin(Ethernet.localIP(), "arduino", "password", InternalStorage);
}

void loop(void){
  #ifdef FAST_MODE
    delay(2); // 50 times faster so minutes become roughly seconds for debugging purpose; so every count for cooldown or idle is 0.002 second
  #else
    delay(100); // Normal operation: loops approx 10 times per second; so every count for cooldown or idle is 0.1 second
  #endif

  // check for updates
  ArduinoOTA.poll();

  if (millis() - previousMillis > PUBLISH_DELAY) {
    if (CheckDataChange()) {
      CheckThermostatOn();
      sendData();
    }
    previousMillis = millis();
  }
  mqttClient.loop();
  mqttReconnect();
  iLED.Alternate();
  FUPump.Update();
  for (int i=0; i<NR_ZONES; i++) {
    // Update valve administration for transition times to open/close
    Zones[i].valve.Update();
  }
  // Reset the WatchDog timer (pat the dog)
  wdt_reset();
  // Do the state handling
  CVState.doProcessingActions();
}

void mqttReconnect() {
  //Make sure we stay connected to the mqtt broker
  if (!mqttClient.connected()) {
    mqttConnect();
  }
  if (!mqttClient.loop()) {
    mqttClient.connect(CLIENT_ID, "mqtt-user", "Robin81");
  }
}

void mqttConnect() {
  mqttClient.setServer("192.168.1.63", 1883);
  while (!mqttClient.connected()) {
    Serial.print(F("MQTT connecting..."));
    mqttClient.setCallback(callback);

  if (mqttClient.connect(CLIENT_ID, "mqtt-user", "Robin81")) {
    // connection succeeded
    Serial.println("Connected ");
    for (int i=0; i<NR_ZONES; i++) {
      String str = Zones[i].name + Zones[i].SetTopic; 
      int str_len = str.length() + 1; 
      char char_array[str_len];
      str.toCharArray(char_array, str_len);
      Serial.println(str);
      mqttClient.subscribe(char_array);
      str = Zones[i].name + Zones[i].ModeTopic; 
      str_len = str.length() + 1; 
      char_array[str_len];
      str.toCharArray(char_array, str_len);
      mqttClient.subscribe(char_array);
      Serial.println(str);
    }
    mqttClient.subscribe("hysteresis/set");
    mqttClient.subscribe("offset/set");
  } 
  else {
    Serial.println("Connection failed ");
  }
  }
}
void printAddress(DeviceAddress deviceAddress)
{ 
  for (uint8_t i = 0; i < 8; i++)
  {
    Serial.print("0x");
    if (deviceAddress[i] < 0x10) Serial.print("0");
    Serial.print(deviceAddress[i], HEX);
    if (i < 7) Serial.print(", ");
  }
  Serial.print("");
}
void sendData() {
  if (mqttClient.connect(CLIENT_ID)) {
    for (int i=0; i<NR_ZONES; i++) {
      mqttClient.publish((Zones[i].name + Zones[i].IsTopic).c_str(), String(Zones[i].IsTemp).c_str());
      mqttClient.publish((Zones[i].name + Zones[i].ActionTopic).c_str(), String(Zones[i].Action).c_str());
      mqttClient.publish((Zones[i].name + Zones[i].ModeStateTopic).c_str(), String(Zones[i].ModeState).c_str());
  }
  printTimeStamp();
  Serial.print(": ");
  Serial.println("Data send");
//    float tempC = sensors.getTempC(sensor1);
//    mqttClient.publish("lus1", String(tempC).c_str());
//    tempC = sensors.getTempC(sensor2);
//    mqttClient.publish("lus2", String(tempC).c_str());
//    tempC = sensors.getTempC(sensor3);
//    mqttClient.publish("lus3", String(tempC).c_str());
//    tempC = sensors.getTempC(sensor4);
//    mqttClient.publish("lus4", String(tempC).c_str());
//    tempC = sensors.getTempC(sensor5);
//    mqttClient.publish("lus5", String(tempC).c_str());
//    tempC = sensors.getTempC(sensor6);
//    mqttClient.publish("lus6", String(tempC).c_str());
//    tempC = sensors.getTempC(sensor7);
//    mqttClient.publish("lus7", String(tempC).c_str());
//    tempC = sensors.getTempC(sensor8);
//    mqttClient.publish("lus8", String(tempC).c_str());
//    tempC = sensors.getTempC(sensor9);
//    mqttClient.publish("lus9", String(tempC).c_str());
//    tempC = sensors.getTempC(sensor10);
//    mqttClient.publish("lus10", String(tempC).c_str());
//    tempC = sensors.getTempC(sensor11);
//    mqttClient.publish("lus11", String(tempC).c_str());
//    tempC = sensors.getTempC(sensor12);
//    mqttClient.publish("lus12", String(tempC).c_str());
//    tempC = sensors.getTempC(sensor13);
//    mqttClient.publish("lus13", String(tempC).c_str());
//    tempC = sensors.getTempC(sensor14);
//    mqttClient.publish("lus14", String(tempC).c_str());
  }
}

////////////////////////////////////////////////////////////////////
// Processing Methods for each CV State
/////////////////////////////////////////

void  onProcessing() {
  if (ProcessThermostats())  { // returns true if at least one of the thermostats is on (switch closed) => stay in this state
    if (FloorPumpingAllowed())   {
       FUPump.On();
    }
    else {
       FUPump.Off(); 
    }
  }
  else if ( CVState.checkCoolDownNeeded() ) {  // Continue in cooldown state to keep pump running for a while
      CVState(State::cooldown); 
  }
  else  {  // skip cooldown for floor unit, go back to idle
      CVState(State::idle); 
  }
}

void coolDownProcessing() {
  hLED.Alternate();
  if (HeatingRequested()) {   // returns true when one of the thermostats is closed
    CVState(State::on);
  }
  else  {
    if ( CVState.whileCoolDownNeeded() ) {
      if (FloorPumpingAllowed()) {
         FUPump.On();
      } else {
         FUPump.Off();  
      }        
    }
    else {
      CVState(State::idle);
    }
  }
}

void idleProcessing() 
{

  if (HeatingRequested())  {    // returns true when one of the thermostats is closed
    CVState(State::on);
  }
  else
  {
    // During idle period this check will activate the Floor Unit Pump for 8 minutes per 36 hours to keep them operatable
    if ( FUPump.doMaintenanceRun()) {
      if (FUPump.IsOff()) {
        if ( allValvesOpen() == false ) { // start opening just once
          printTimeStamp(); Serial.println(": Start daily cycle for Floor Unit Pump; open valves: ");
          allValvesOn();
        }
        if (FloorPumpingAllowed()) { 
          // this takes ca 5 minutes after activating the valves (6 seconds in test mode)
          printTimeStamp(); Serial.println(": Start daily cycle for Floor Unit Pump; start pump ");
          FUPump.On(); 
        }

      }
    } 
    else if (FUPump.IsOn()) {  // no Maintenance needed. So stop pump if still running
        printTimeStamp(); Serial.println(": Stop daily cycle for Floor Unit Pump; stop pump and close valves");
        FUPump.Off();
        allValvesOff();
    }
  }
}

////////////////////////////////////////////////////////////////////
// Helper Methods used by the State handlers
/////////////////////////////////////////

void allValvesOff() {
  for (int i=0; i<NR_ZONES; i++) {
    Zones[i].valve.Off();
  }    
}

void allValvesOn() {
  for (int i=0; i<NR_ZONES; i++) {
    Zones[i].valve.On();
  }    
}

bool allValvesOpen() {
  for (int i=0; i<NR_ZONES; i++) {
    if ( Zones[i].valve.IsOff() ) {
       return false;
    }
  }
  return true;
}

bool FloorPumpingAllowed() 
{
  // returns true if at least one zone is open, taking Valve transition into account
  for (int i=0; i<NR_ZONES; i++) {
    if (Zones[i].valve.ValveIsOpen() ) {
      return true;
    }
  }
  return false; // all valves are closed
}

bool ProcessThermostats() // returns true when one of the thermostats is closed
{                         // (De-)Activates Floor zones
   bool heating=false;
   bool requested[NR_ZONES]; 

   for (int i=0; i<NR_ZONES; i++) {
     // record heating requests only once to avoid race conditions due changes in between
     requested[i] = Zones[i].thermostat;
     if ( requested[i] ) {
       heating = true;
       CVState.setCoolDownNeeded(); // remember if there was a request for heating a floor unit zone
     }
   }
   for (int i=0; i<NR_ZONES; i++) {
     if ( requested[i] ) {
       // Selectively open valves for zones that request heating 
       Zones[i].valve.On();
     }
     else if (heating) {
       // Selectively close valves for zones that don't require heating anymore
       // Only close them if heating is still required because in cooldown all zones need to be open
       Zones[i].valve.Off();
     }
   }
   return heating;
}

bool HeatingRequested()
{
  for (int i=0; i<NR_ZONES; i++) {
    if (Zones[i].thermostat == true) {
      return true;
    }
  }
  return false; // all Thermostats are open (no heating needed)
}

void printTimeStamp() {
  #ifdef FAST_MODE
    // 50 times faster; represent the time it would be in normal mode
     unsigned long seconds = millis()/(unsigned long)20;
  #else
    // Normal operation
     unsigned long seconds = millis()/(unsigned long)1000;
  #endif
    unsigned long minutes, hours, days;
    minutes = seconds / 60L;
    seconds %= 60L; 
    hours = minutes / 60L;
    minutes %= 60L;
    days = hours / 24L;
    hours %= 24L;
    char time[30]; 
    sprintf(time, "%02d:%02d:%02d:%02d", (int)days, (int)hours, (int)minutes, (int)seconds);
    Serial.print(time);
}

void callback(char* topic, byte* payload, unsigned int length) {
  payload[length] = '\0';  
  for (int i=0;i<length;i++) {
    Serial.print((char)payload[i]);
  }
  for (int i=0; i<NR_ZONES; i++) {
    if (String(topic) == Zones[i].name + Zones[i].SetTopic) {
      Serial.println(String(Zones[i].SetTemp,1));
      Serial.print("Message arrived [");
      Serial.print(topic);
      Serial.print("] ");

      Serial.println("");
      Serial.println((char *)payload);
      Zones[i].SetTemp = atof((char *)payload);
    }
    else if (String(topic) == Zones[i].name + Zones[i].ModeTopic) {
      if (strcmp(((char *)payload), "off") == 0){
        Zones[i].ModeState = "off";
      }
      else if (strcmp(((char *)payload), "heat") == 0){
        Zones[i].ModeState = "heat";
      }
      else if (strcmp(((char *)payload), "cool") == 0){
        Zones[i].ModeState = "cool";
      }
    }
  }
  if (String(topic) == "hysteresis/set") {
      Serial.print("Message arrived [");
      Serial.print(topic);
      Serial.print("] ");
      Serial.println((char *)payload);
      hysteresis = atoi((char *)payload);
    }
    else if (String(topic) == "offset/set") {
      Serial.print(offset);
      Serial.print("Message arrived [");
      Serial.print(topic);
      Serial.print("] ");
      Serial.println((char *)payload);
      offset = atoi((char *)payload);

  }
    else if (String(topic) == "ha/status") {
      Serial.print(offset);
      Serial.print("Message arrived [");
      Serial.print(topic);
      Serial.print("] ");
      Serial.println((char *)payload);
      offset = atoi((char *)payload);

  }
  CheckDataChange();
  CheckThermostatOn();
}
void SetPins(){
  Serial.println("SetPins2");
  for(int i=0; i<16; i++)
  {
    pinMode(controlPin[i], OUTPUT);// set pin as output
    if(triggerType ==LOW){
      digitalWrite(controlPin[i], HIGH); // set initial state OFF for low trigger relay
    }else{
       digitalWrite(controlPin[i], LOW); // set initial state OFF for high trigger relay     
    }
  }
}
void SetEthernet(){
  Serial.println("SetEthernet");  
  Ethernet.begin(mac);
  Serial.print("IP address: ");
  Serial.println(Ethernet.localIP());
}
bool CheckDataChange(){
  bool change = false;
  sensors.requestTemperatures();
  for (int i=0; i<NR_ZONES; i++) {
    byte addr[8];
      for (int f = 0; f < 8; f++) {
        addr[f] = Zones[i].sensor[f];
    }
    float temp = sensors.getTempC(addr);
    if (temp != -127){
      if (temp != Zones[i].IsTemp){
      change = true;
      Zones[i].IsTemp = temp;
      }
    }
    else {
      Zones[i].ModeState = "off";
      Zones[i].IsTemp = temp;
    }

  }
  return change;
}
void CheckThermostatOn(){
  for (int i=0; i<NR_ZONES; i++) {
    if (Zones[i].ModeState == "heat"){
      Serial.println(Zones[i].name);
      if (Zones[i].IsTemp < (Zones[i].SetTemp - hysteresis)){
      Serial.println(Zones[i].IsTemp);
      Serial.println(Zones[i].SetTemp);
      Zones[i].thermostat = true;
      Zones[i].Action = "heating";
      }
      else if (Zones[i].IsTemp > (Zones[i].SetTemp + hysteresis)){
        Zones[i].thermostat = false;
        Zones[i].Action = "idle";
      }
      else{
        Zones[i].Action = "idle";      
      }
    }
    else if (Zones[i].ModeState == "off"){
        Zones[i].thermostat = false;
        Zones[i].Action = "off";
    }
  }
  PrintZones();
  sendData();
}
void PrintZones(){
  for (int i=0; i<NR_ZONES; i++) {
    Serial.println(Zones[i].name);
    Serial.println(Zones[i].IsTemp);
    Serial.println(Zones[i].SetTemp);
    Serial.println(Zones[i].Action);
    Serial.println(Zones[i].Mode);
    Serial.println(Zones[i].ModeState);
    Serial.println("");
  }
}
JAndrassy commented 2 years ago

I guess it is a timeout in the upload tool. my_boards now has a version of the upload tool with timeout parameter and in avr platform.txt 30 seconds is set as timeout. get the files from my_boards repo or If you don't want to use an exe downloaded from internet, you can download the source code of arduinoOTA and build it with the Go language builder (which is simple to install)

RStaes commented 2 years ago

Hey thanks! Where do i put this files? Now i have them in

C:\Users\User\AppData\Local\Arduino15\packages\arduino\hardware\avr\tools.

The platform.txt contains this line:

C:\Users\User\AppData\Local\Arduino15\packages\Optiboot\hardware\avr/tools/arduinoOTA.exe -address 192.168.1.119 -port 65280 -t 30 -username arduino -password password -sketch C:\Users\User\AppData\Local\Temp\arduino_build_384939/Zoneverwarming3.ino.bin -upload /sketch -b

Note the / and the \ in the path. Is that right? I put this in the bottom of the platform.txt file with -t 30:

## Create output (bin file)
recipe.objcopy.bin.pattern="{compiler.path}{compiler.elf2hex.cmd}" -O binary {compiler.elf2hex.extra_flags} "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.bin"

build.preferred_out_format=bin

## Save hex
recipe.output.tmp_file={build.project_name}.{build.preferred_out_format}
recipe.output.save_file={build.project_name}.{build.variant}.{build.preferred_out_format}

tools.avrdude.upload.network_pattern="{network_cmd}" -address {serial.port} -port 65280 -username arduino -password password -sketch "{build.path}/{build.project_name}.bin" -upload /sketch -b

tools.avrdude.program.pattern="{cmd.path}" "-C{config.path}" {program.verbose} {program.verify} -p{build.mcu} -c{protocol} {program.extra_params} "-Uflash:w:{build.path}/{build.project_name}.with_bootloader.hex:i"

tools.arduinoOTA.cmd={runtime.hardware.path}/tools/arduinoOTA
tools.arduinoOTA.cmd.windows={runtime.hardware.path}/tools/arduinoOTA.exe
tools.arduinoOTA.program.params.verbose=
tools.arduinoOTA.program.params.quiet=
tools.arduinoOTA.program.pattern="{cmd}" -address {ip} -port 65280 -t 30 -username arduino -password password -sketch "{build.path}/{build.project_name}.bin" -upload /sketch -b

The platform.txt file is located here:

C:\Users\User\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.4

JAndrassy commented 2 years ago

sorry, I modified only the 'programmer' definition, not the standard network_pattern.

in the past it was not possible to setup the network_command with keys other than the "runtime.tools." so I recommend you to use the fake programmer method

in tools.arduinoOTA.cmd={runtime.hardware.path}/tools/arduinoOTA the runtime.hardware.path points to my_boards folder

RStaes commented 2 years ago

Still not working. I have the same error as before: I even tried with a 60 seconds en 180 seconds timeout.

Arduino: 1.8.13 (Windows 10), Board: "Arduino Mega 2560 (Optiboot)"

Sketch uses 41442 bytes (15%) of program storage space. Maximum is 261120 bytes.

Global variables use 3172 bytes (38%) of dynamic memory, leaving 5020 bytes for local variables. Maximum is 8192 bytes.

C:\Users\User\Documents\Arduino\hardware\my_boards-master/tools/arduinoOTA.exe -address 192.168.1.119 -port 65280 -t 60 -username arduino -password password -sketch C:\Users\User\AppData\Local\Temp\arduino_build_739379/Zoneverwarming3.ino.bin -upload /sketch -b 

Connecting to board ...  done
Uploading sketch ...  done
Flashing sketch ... Error flashing the sketch
Error flashing the sketch

I'm missing something, but what?

JAndrassy commented 2 years ago

turn on upload verbose mode in IDE Preferences

JAndrassy commented 2 years ago

turn off the watchdog

you can Use ArduinoOTA.beforeApply to register a callback function. For example in setup ArduinoOTA.beforeApply(shutdown); and add the function to to sketch:

void shutdown() { wdt_disable(); }

RStaes commented 2 years ago

Hero!! It was the watchdog!

RStaes commented 2 years ago

And with ArduinoOTA.beforeApply I can disable the watchdog and still use it in my sketch. Thank you very much!!

JAndrassy commented 2 years ago

And with ArduinoOTA.beforeApply I can disable the watchdog and still use it in my sketch. Thank you very much!!

with a small sketch a longer watchdog time may work. I use watchdog interrupt in my Regulator project to extended the watchdog time. I activate a reset in second interrupt so I have a 16 seconds watchdog