Can anyone shed some clarity in this ACK business? (Hek?)



  • Using v1.4 in a simple two node configuration , End-node and Gateway a few feet apart, with the Gateway node hooked up to the very elegant MYScontroller to display and dissect the messages from the GW.

    I'm having trouble to understand the function of the ACK flag on .send() and .sendBatteryLevel() as well as the affect the macro mSetACK(msg, bool) has on the thing.

    My end node sends two messages each wake cycle. The first one with the battery level , the second with a measurement reading .

    If I call both send messages with false for the ACK flag I get both readings on the GW as I expected and I see that the ACK flag on MYSC is indicating "NO". When I then set ACK to true on the send BatteryLevel() the second message with my measurement value is not being received anymore, except every 30th time or so, and MYSController still reports "NO" ACK for the Battery level message.

    If I change the script around to send the measurement first (with ack set) then the BatteryLevel message disappears, but still with a "NO" for "ACK" on the GW.

    If I call mSetAck on the msg object for the measurement then the GW shows a "YES" for ACK , but still only the first message ever makes it through.

    I can not find a description for this ACK mechanism in the documentation. The API reference is mum about what the return values from .send() and .sendBatteryLevel() mean.

    When I look at the return values from these calls I get a true while I'm close to the GW, but a false when I move the nodes apart a couple of yards even though the message actually still made it all the way to the GW..

    How is one to use this to receive a simple true/false indicating that the message was received at the GW.
    My application needs to send data for 4 child sensors plus the battery level each time the sensor wakes up. AND it needs to sound an alarm when communication is failing !

    This is NOT a hardware problem --

    Thanks for your help


  • Admin

    @GaryStofer

    Requesting ack:s requires more power (for a short glimpse of time). It will first send the hardware ack and then the end-to-end software ack provided by the MySensors library. If the gateway radio isn't fed properly it might fail with this operation.

    mSetAck sets a bit in the header saying that "This is an ack message". If you want to request an ack you should use the mSetRequestAck.

    But the request-ack bit is not exposed through the serial protocol which MYScontroller uses. So it can't show if node requested an ack message or not.



  • Thanks Hek for the quick reply.

    The 3.3V power rail feeding the radio chips is rock solid at 3.3V, checked on both nodes with DSO.

    The bit about mSetAck makes sense. So what does the ack argument on the send functions do ? Does it set the RequestAck (bit?) as well?

    Does a true return from .send() mean that the message was acknowledge all the way, even if a router was in the path? Likewise does a false mean that the ack was not received by the sending node.

    Is .send() blocking when called with request ack, or should I call sleep() or process() in between the individual .send()'s.


  • Admin

    @GaryStofer said:

    Thanks Hek for the quick reply.

    The bit about mSetAck makes sense. So what does the ack argument on the send functions do ? Does it set the RequestAck (bit?) as well?

    The ack argument to the api-functions sets the request-ack-bit on the message before sending it off to the destination.

    When a node (or gateway) receives a message with request-ack-bit it sends they send same message back to the sender (but with ack-bit set). So ack-bit inidicates that a message is an "ack".

    Does a true return from .send() mean that the message was acknowledge all the way, even if a router was in the path? Likewise does a false mean that the ack was not received by the sending node

    No, true only indicates inter-node (hardware) ack was received. The other end-to-end ack messsage must be picked up in the incomingMessage-callback.
    .

    Is .send() blocking when called with request ack, or should I call sleep() or process() in between the individual .send()'s.

    Send is blocking long enough to pick up the hardware inter-node ack. For the end-to-end ack you must keep node awake and call process().



  • So I have looked at this some more and I can see that with the following loop function in the node sketch I get an ACK response storm from the gateway. This is still in a single hop network ...

    MySensor gw;
    MyMessage msg( CHILD_ID_LIGHT, V_LIGHT_LEVEL);
    
    void loop ()
    {
        bool received_by1st_hop;
        msg.set(12);
       received_by1st_hop = gw.send(msg, true);   // send this with an ACK request
       /*
        for (int i =0; i <10; i++
        {
            delay(1);
            gw.process();
        }*/
    
     // gw.sendBatteryLevel(44,false);
    
       gw.sleep(3000);
    }
    

    On the air I get an initial message from the node to the GW with the ReqAck bit set, followed by 16 messages from the gateway spaced about 2 ms apart with the IsAck bit set. This is in addition to the HW ack that the radio chip on the GW already sent out.

    The GW keeps sending isAck messages out, presumably because it waits for an hardware ack i.e. it waits for an ack for its isAck reply. This is highly unexpected -- One doesn't usually have to acknowledge the acknowledgement.

    See the Wireshark trace below, note however that hardware aks are not captured.

    MYSensor_WS.PNG

    The second send of the Batterylevel, if enabled, is being sent during the time the GW is busy sending isAck messages and they either collide midair (as evident in CRC errors in Wireshark, not shown above) or are otherwise not seen by the GW being busy.

    If I un-comment the for loop calling delay() and process() after each send request I get the proper behavior from the GW by only sending out a single isACK message, presumably because it gets its desired hw ack.

    This double ack mechanism is entirely confusing and at least should be better explained if indeed it is supposed to work this way, needing and hw ack for an IsAck mesage.

    How is this working in the RF 69 implementation? I'm trying to wite an application that is going to deploy with nrf24 and/or rf69 hardware.

    Cheers Gary


  • Admin

    The hardware ack:ing in enabled for all messages (except for broadcasting).
    https://github.com/mysensors/Arduino/blob/master/libraries/MySensors/MySensor.cpp#L107


 

254
Online

8.6k
Users

9.4k
Topics

99.0k
Posts