Error sending switch command, check device/hardware !



  • I have got a new problem that I haven't had before.

    When I try to switch a node on or off from domoticz I see in MYSController that the command gets sent to the node. But domoticz says "Error sending switch command, check device/hardware !"
    I also see that domoticz sends the command at least twice.
    If I try the switch a couple of times more the same thing happens. But sometimes it works, and when that happens I see in MYSController that I that time also get a response from the node.

    When it don't work it looks like this:

    14888	2016-09-30 16:47:08	TX	200	1 - 200 RGB Led	C_SET	YES	V_LIGHT	0
    
    14889	2016-09-30 16:47:10	TX	200	1 - 200 RGB Led	C_SET	YES	V_LIGHT	0
    

    When it works it looks like this:

    14957	2016-09-30 16:49:25	TX	200	1 - 200 RGB Led	C_SET	YES	V_LIGHT	0
    
    14958	2016-09-30 16:49:25	RX	200	1 - 200 RGB Led	C_SET	YES	V_LIGHT	0
    

    The node also sends some status values regulary. Voltage of the mcu, Temperature of a ds18b20 and temperature of the mcu. All those messages get received without problems. So it doesn't seem to be a problem of the radios.

    When I change the status of a switch in domoticz, does it expect a response from the node? And if so, does the mysensors library send the response automatically? It seems like it does from the logs. And if the library sends the response why doesn't the response get received as it should? The statusvalues doesn't seem to get missed.


  • Mod

    @kk02067 are you switching relays? If so, how are they powered? Many relays use enough power when switching to disturb the radio. Does the problem still appear if you disconnect whatever you are switching? How is the radio powered and what capacitor(s) do you use?

    If you haven't seen it already, https://forum.mysensors.org/topic/666/debug-faq-and-how-ask-for-help has some great guides for troubleshooting.



  • @mfalkvidd No. I'm controling a ledstrip with ws2812b led's. The radio is powered from one of those small adapterboards with integrated regulator and capacitor. All driven from a 15W 5V switchmode powersupply.

    It seems that Domoticz is expecting a reply from the node with the same status as the command. Every time it works there is a reply from the node. And when I get the error Idont get that reply. I have not programmed in any replyprocedures in the sketch, so when it works it must be the library that send that reply from the node. But if thats the case, why not every time.

    I tried to modify the sketch to count any failed transmission and send that value back to the gateway to see if I have problems with the transmission. But the value is still Zero. Maybe my sketch is coded wrong but I dont think so.
    And even when domoticz says it failed the node still executes what was ordered.

    So the problem I think lies in the fact that domoticz seems to be waiting for an answer back with the new status from the node. The node send that status sometimes but more often not.

    This is the sketch:

    #define MY_RADIO_NRF24
    #define MY_NODE_ID 200
    #define MY_REPEATER_FEATURE
    //#define MY_DEBUG
    
    #include <MySensors.h>
    #include <SPI.h>
    #include "FastLED.h"
    #include <OneWire.h>
    #include <avr/pgmspace.h>
    
    
    #define DATA_PIN    2
    #define LED_TYPE    WS2812B
    #define COLOR_ORDER GRB
    #define NUM_LEDS    232
    #define BRIGHTNESS  96
    CRGB leds[NUM_LEDS];
    
    char actRGBvalue[] = "FFFFFF";               // Current RGB value
    uint16_t actRGBbrightness = 0xFF ;         // Controller Brightness
    int actRGBonoff = 0;                      // OnOff flag
    
    
    MyMessage msg(1, V_RGB);
    MyMessage msgtemp(2, V_TEMP);
    MyMessage msgcputemp(3, V_TEMP);
    MyMessage msgcpuvolt(4, V_VOLTAGE);
    MyMessage msgfailcount(5, V_VAR1);
    
    
    
    void SendColor2AllLEDs(const CRGB lcolor)
    {
      for (int i = 0 ; i < NUM_LEDS ; i++) {
        leds[i] = lcolor;
      }
    }
    
    OneWire ds(8);
    
    void setup() {
      wait(3000); // 3 second delay for recovery
    
      pinMode(7, OUTPUT);
      digitalWrite(7, HIGH);
    
      // tell FastLED about the LED strip configuration
      FastLED.addLeds<LED_TYPE, DATA_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
      //FastLED.addLeds<LED_TYPE,DATA_PIN,CLK_PIN,COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
    
      // set master brightness control
      FastLED.setBrightness(BRIGHTNESS);
    
      SendColor2AllLEDs(strtol(actRGBvalue, NULL, 16));
    
    }
    
    
    
    void presentation()
    {
    
      present(1, S_RGB_LIGHT, "200 RGB Led");
      wait(1000);
      present(2, S_TEMP, "200 Temperatur altan");
      wait(1000);
      present(3, S_TEMP, "200 Temperatur CPU");
      wait(1000);
      present(4, S_MULTIMETER, "200 Spänning CPU");
      wait(1000);
      present(5, S_CUSTOM, "200 Failcount");
      wait(1000);
      sendSketchInfo("Nod 200 - Altan", "V1.6");
      wait(1000);
    
    
    }
    
    
      unsigned int fail;
      
    void loop()
    {
    
    
      
      if(!send(msgtemp.set(getTemp(), 2)))
        {
        fail++;
        }
         
      wait(1000);
      if(!send(msgcputemp.set(GetTempCpu(),2)))
        {
        fail++;
        }
      
      wait(1000);
    
      if(!send(msgcpuvolt.set(readVcc(),3)))
        {
        fail++;
        }
      
      wait(30000);
    
      send(msgfailcount.set(fail));
    
      wait(1000);
    
    
    }
    
    
    void receive(const MyMessage &message)
    {
      if (message.type == V_RGB) {
        strcpy(actRGBvalue, message.getString());    // get the payload
        SendColor2AllLEDs(strtol(actRGBvalue, NULL, 16));
        Serial.println(F("RGB"));
        Serial.println(actRGBvalue);
      }
      else if (message.type == V_DIMMER) {
        actRGBbrightness = message.getByte();
        FastLED.setBrightness( actRGBbrightness );
        FastLED.show();
        Serial.println(F("DIMMER"));
        Serial.println(actRGBbrightness);
      }
      else if (message.type == V_STATUS) {           // if on/off type, toggle brightness
        actRGBonoff = message.getInt();
        FastLED.setBrightness((actRGBonoff == 1) ? actRGBbrightness : 0);
        FastLED.show();
        Serial.println(F("STATUS"));
        Serial.println(actRGBonoff);
      }
      //  FastLED.show();
    }
    
    
    float getTemp() {
      //returns the temperature from one DS18S20 in DEG Celsius
    
      byte data[12];
      byte addr[8];
    
      if ( !ds.search(addr)) {
        //no more sensors on chain, reset search
        ds.reset_search();
        return -1000;
      }
    
      if ( OneWire::crc8( addr, 7) != addr[7]) {
        Serial.println(PSTR("CRC is not valid!"));
        return -1000;
      }
    
      if ( addr[0] != 0x10 && addr[0] != 0x28) {
        Serial.print(PSTR("Device is not recognized"));
        return -1000;
      }
    
      ds.reset();
      ds.select(addr);
      ds.write(0x44, 1); // start conversion, with parasite power on at the end
    
      byte present = ds.reset();
      ds.select(addr);
      ds.write(0xBE); // Read Scratchpad
    
    
      for (int i = 0; i < 9; i++) { // we need 9 bytes
        data[i] = ds.read();
      }
    
      ds.reset_search();
    
      byte MSB = data[1];
      byte LSB = data[0];
    
      float tempRead = ((MSB << 8) | LSB); //using two's compliment
      float TemperatureSum = tempRead / 16;
    
      return TemperatureSum;
    
    }
    
    double GetTempCpu(void)
    {
      unsigned int wADC;
      double t;
    
      // The internal temperature has to be used
      // with the internal reference of 1.1V.
      // Channel 8 can not be selected with
      // the analogRead function yet.
    
      // Set the internal reference and mux.
      ADMUX = (_BV(REFS1) | _BV(REFS0) | _BV(MUX3));
      ADCSRA |= _BV(ADEN);  // enable the ADC
    
      wait(20);            // wait for voltages to become stable.
    
      ADCSRA |= _BV(ADSC);  // Start the ADC
    
      // Detect end-of-conversion
      while (bit_is_set(ADCSRA,ADSC));
    
      // Reading register "ADCW" takes care of how to read ADCL and ADCH.
      wADC = ADCW;
    
      // The offset of 324.31 could be wrong. It is just an indication.
      t = (wADC - 324.31 ) / 1.22;
    
      // The returned temperature is in degrees Celsius.
      return (t);
    }
    
    float readVcc() {
      // Read 1.1V reference against AVcc
      // set the reference to Vcc and the measurement to the internal 1.1V reference
      #if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
        ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
      #elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
        ADMUX = _BV(MUX5) | _BV(MUX0);
      #elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
        ADMUX = _BV(MUX3) | _BV(MUX2);
      #else
        ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
      #endif  
    
      wait(20); // Wait for Vref to settle
      ADCSRA |= _BV(ADSC); // Start conversion
      while (bit_is_set(ADCSRA,ADSC)); // measuring
    
      uint8_t low  = ADCL; // must read ADCL first - it then locks ADCH  
      uint8_t high = ADCH; // unlocks both
    
      float result = (high<<8) | low;
    
      result = 1125300L / result; // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000
      result=result/1000;
      return result; // Vcc in millivolts
    }
    
    
    

  • Mod

    @kk02067 I think what happens is that Domoticz wants an ack from the node, to make sure the switch command is received. I have not ised this feature myself, but these threads cover similar problems:
    https://forum.mysensors.org/topic/3904/node-are-not-receiving-messages-from-domoticz/
    https://forum.mysensors.org/topic/1992/domoticz-and-ack/

    Let us know whether the information in the threads help or not.



  • I put together another node exactly the same but keeping it at my workbench roughly the same distance from the gateway. It works without any troubles so far. The only change in the sketch is the node id and no ds18b20 temperature reading.
    The log from myscontroller show that it works even if the node doesn't send back the same status as the command. Domoticz doesn't complain as it does with the first node. This behaviour was last night.

    Now this morning the replys from the new nodes is also present. They weren't last night. At least not in the logs from MYScontroller.

    When domoticz sends a switchcommand to the gateway it does so with with ACK flag set. Does mysensors library automatically reply?
    I haven't programmed in a replyfunction in my sketch so it seems like it. But in that case why doesn't my first node reply every time?

    Strange. Have to investigate this further.



  • Having checked the serial output from the new node at my computer I see that the library returns the command when a ACK i requested. I also looked in the sourcecode for the library and it seems that it handles the ackmessage.
    So it seems that the ACK message get missed in the recieving node. Why, is the next question.

    Investigation continues...


  • Mod

    ... why doesn't my first node reply every time?

    My guess is that it does reply every time. But the message gets lost along the way. The most common reason is power problems on the sending node.



  • @mfalkvidd After Little more investigating and experimenting I am pretty sure I have found a bug in the library. I found that when debug is active all is working as expected. But if I commented out debug it starts to not work. I tried it about 10 times, once with debug and then without. And everytime debug is active it works, no debug it fails.
    I opened the transport sourcefile and added a delay(100) at the procedure where the debug message is sent. With that change it works everytime with or without debug. It seems that if the ackmessage is sent to quick it gets missed by the gateway. Any thoughts on this?


  • Hardware Contributor

    We should ping @tekka and @hek as well for this one @kk02067.


  • Mod

    The problem could be related to https://forum.mysensors.org/topic/4450/sensor-presentation-failure/ if the debug causes enough delay.


  • Admin

    We just discussed this in the core team. Unless it is a compiler problem (like the other one we experienced some time ago) the most probably cause is..

    1. Radio problems. Could be bad really bad clone, or that radio doesn't have time to "recharge" enough between transmissions.
    2. Slow node, Fast Gw => GW sends response and node isn't in RX mode yet. But this is also quite strange as GW retransmits 15x with a 1.5ms delay before failing.

  • Plugin Developer

    I've experienced a similar problem when testing OTA updates on SensebenderMicro. With debug active, no missed messages, with debug disabled, a lot of missed messages and retries. It was a really obvious difference, since the rate of messages during OTA updates is quite fast. Gateway was an UNO and radios were clones.



  • @kk02067 , Would you please post specifically where you added the delay(100). I have exactly the same problem as you and would like to be sure the ack gets back to the controller. Thank you!

    In other tests and explorations I had noticed that with debug enabled things seemed to work a bit more consistently - but had not tied it to this problem. Unfortunately, debug sacrifices quite a bit of flash which I need for other uses.



  • @novicit If I remember correctly i put it here: https://github.com/mysensors/MySensors/blob/master/core/MyTransport.cpp#L463
    just to test that it worked. Then I removed the change to keep the library source original.

    I turned on debug again to get it working again.. The reason why I wanted to have debuging disabled was to keep the hexfile size down so the OTA update wouldn't take so long time. I hope this issue will be fixed in a more elegant manner in a future release.



  • Update. Please note that when @kk02067 gave the response directly above it was for Ver 2.0 and referenced a line in that code. It appears that changes leading to Ver 2.1.1 the location has changed and the delay(100) line would not be added at L463 as referenced. In Ver 2.1.1 it is now added between L659 and L660. It will look like this I believe:

    L658 _msgTmp.destination = sender;
    L659 // send ACK, use transportSendRoute since ACK reply is not internal, i.e. if !transportOK do not reply
    ADD delay(100) here!!
    L660 (void)transportSendRoute(_msgTmp);

    Also, I have not yet used Ver 2.1.1, so don't know if the changes in the latest version might solve the Domoticz relay ack issue I had. This solution solved my problems 100% in Ver 2.0.


Log in to reply
 

Suggested Topics

  • 5
  • 3
  • 4
  • 1
  • 2
  • 1

14
Online

11.4k
Users

11.1k
Topics

112.7k
Posts