Send Data to an ANT+ Device

Former Member
Former Member
Hi

I have managed to cobble enough code together to talk to an ANT+ device not supported by the current SDK. I want to now be able to send data to this device.

I assume I need to use the GenericChannel.sendBroadcast(data) function ? If so, does anyone have an example of how to send 8 bytes using this function ? This is more a MonkeyC question I suppose.

Thanks!

J
  • Former Member
    Former Member over 8 years ago
    You may have a look into the MO2Display Sample from the SDK:

    // Create and populat the data payload
    var payload = new [8];
    payload[0] = 0x10; // Command data page
    payload[1] = 0x00; // Set time command
    payload[2] = 0xFF; // Reserved
    payload[3] = 0; // Signed 2's complement value indicating local time offset in 15m intervals

    // Set the current time
    var moment = Time.now();
    for (var i = 0; i < 4; i++) {
    payload[i + 4] = ((moment.value() >> i) & 0x000000FF);
    }

    // Form and send the message
    var message = new Ant.Message();
    message.setPayload(payload);
    GenericChannel.sendAcknowledge(message);
  • Former Member
    Former Member over 8 years ago
    Hi

    Thanks for the reply. I appreciate it.

    I saw that code but I didn't think sendAcknowledge was the right method.. I was guessing it would be sendBroadcast. The documentation here is lacking not to mention the examples.

    Plus I don't quite get why they are sending an Ant Message when the API Docs says it just takes an array of bytes..

    Anyhow, I will give it a try and report back. Thanks

    J
  • Hi

    Thanks for the reply. I appreciate it.

    I saw that code but I didn't think sendAcknowledge was the right method.. I was guessing it would be sendBroadcast. The documentation here is lacking not to mention the examples.

    Plus I don't quite get why they are sending an Ant Message when the API Docs says it just takes an array of bytes..

    Anyhow, I will give it a try and report back. Thanks

    J


    Hi Stiple,

    You may want to take a look at this ANT+ Document. ANT Message Protocol and Usage

    On page 22 and 23 it describes Broadcast and Acknowledge messages. To the best of my knowledge, broadcast data can only be sent by the Master unless it's requested. Also, CIQ devices can not currently be setup as the master. See this thread. I'm not familiar with how a request for broadcast data can happen, but it seems like sendBroadcast might not be what you are looking for.

    Which ANT+ profile are you using? Is the data that you are trying to send from the watch to the ANT+ device defined as an acknowledge message in the profile? For example, Data Page 16 is defined in the MO2 profile as an acknowledge message to be sent from the watch to the sensor. This lets the watch send the current time to the sensor.

    Also, an ANT+ message is just an array of bytes.
  • Former Member
    Former Member over 8 years ago
    Hi

    Thanks again for the reply.

    I am trying to set target power on a FEC..

    I am able to talk to the FEC, it streams me data. The issue is sending it the target power. Here's the ANT+ spec for FEC data that I am concerned with:



    Here's my code:

    function sendTargetPower() {


    var payLoad = new[8];
    var temp = new[2];
    var power = 200;
    payLoad[0] = 49;
    payLoad[1] = 0;
    payLoad[2] = 0;
    payLoad[3] = 0;
    payLoad[4] = 0;
    payLoad[5] = 0;
    payLoad[6] = (power & 0xff);
    payLoad[7] = (power >> 8);

    // Form and send the message
    var message = new Ant.Message();
    message.setPayload(payload);
    GenericChannel.sendAcknowledge(payLoad); }

    }



    However, I am getting an error:

    Unexpected Type Error
    in sendTargetPower (src/FECSensor.mc:94)


    :94 is where I call setPayload

    So I copied pasted the code you put in, just to see and same error.. I went back to the docs and here is what I found:



    It's quite possible I am reading that wrong, but that sounds like you are supposed to send integers that actually represent the bytes. In other words, don't send bytes, send an array of integers.

    Which makes no sense to me..

    J
  • I'm not an expert on how the variable typing works, but I suspect that it's making your integers have more than 8 bits based on the first value that you are assigning to payload[0].

    Have you tried setting them as hex values like below so it makes payload be an array of 8 bit numbers?

    var payload = new [8];
    payload[0] = 0x10; // Command data page
    payload[1] = 0x03; // Lap Command
    payload[2] = 0xFF; // Reserved
    payload[3] = 0; // Signed 2's complement value indicating local time offset in 15m intervals
    payload[4] = 0; // not used for sending lap
    payload[5] = 0; // not used for sending lap
    payload[6] = 0; // not used for sending lap
    payload[7] = 0; // not used for sending lap

    //Form and send the message
    var message = new Ant.Message();
    message.setPayload(payload);

    mChannel.sendAcknowledge(message);
  • The values that you are putting into the payload array should be limited to 8-bit values. It looks like you're already doing this as 49 is 0x31 and 200 is 0x00C8, so you should be in the clear in that respect.

    The code that you've pasted above has a problem though. You declare a local variable payLoad (note the uppercase L in that variable name), but then when setting the payload, you use payload (note the lowercase l). If this is your actual code, I'm betting that you're sending something that you didn't intend.

    Additionally, you should be sure to set the reserved bytes to 0xFF as documented. Don't forget to handle scaling the target power before sending. It might also be a good idea to add a debug assert to range check the value before sending it.

    This code may, or may not, be correct. I haven't tested.

    function sendTargetPower(watts) {
    var payload = new[8];

    // the payload is .25W units, convert the whole units to quarters
    var quarter_watts = (watts * 4).toNumber();

    // make sure the result is legal. documented range is 0-4000W, and
    // we have already converted to quarter-watts...
    assert (0 <= quarter_watts && quarter_watts <= 16000);

    payload[0] = 0x31; // this is okay as it is
    payload[1] = 0xFF;
    payload[2] = 0xFF;
    payload[3] = 0xFF;
    payload[4] = 0xFF;
    payload[5] = 0xFF;
    payload[6] = (watts & 0xFF);
    payload[7] = (watts >> 8) & 0xFF;

    var message = new Ant.Message();
    message.setPayload(payload);

    GenericChannel.sendAcknowledge(payLoad);
    }
  • I'm not an expert on how the variable typing works, but I suspect that it's making your integers have more than 8 bits based on the first value that you are assigning to payload[0].

    In MonkeyC, both 0x31 and 49 are of type Lang.Number. There wasn't originally an 8-bit type in the language, so you were forced to use the 32-bit integer type to represent an 8-bit quantity and then write code to ensure that the value is not outside the expected range. Now there is Lang.Char, but it doesn't seem to be a good fit for what we're doing.

    As long as the value being sent is less than 255 (decimal) or 0xFF (hex), there should be no problems.
  • Former Member
    Former Member over 8 years ago
    Hi

    Thanks again for the replies.

    I have tried various forms of the answers and still no luck. Here is what I have now:

    function sendTargetPower() {

    var watts = 200;
    var msgLoad = new[8];

    // the payload is .25W units, convert the whole units to quarters
    var quarter_watts = (watts * 4).toNumber();

    // make sure the result is legal. documented range is 0-4000W, and
    // we have already converted to quarter-watts...
    assert (0 <= quarter_watts && quarter_watts <= 16000);

    msgLoad[0] = 0x31; // this is okay as it is
    msgLoad[1] = 0xFF;
    msgLoad[2] = 0xFF;
    msgLoad[3] = 0xFF;
    msgLoad[4] = 0xFF;
    msgLoad[5] = 0xFF;
    msgLoad[6] = (quarter_watts & 0xFF);
    msgLoad[7] = (quarter_watts >> 8) & 0xFF;

    var message = new Ant.Message();
    message.setPayload(msgLoad);
    GenericChannel.sendAcknowledge(message);

    }


    Travis, i assumed you wanted to send quarter_watts and not watts..

    The first error I get is at the assert:

    Failed invoking <symbol>
    Unexpected Type Error


    That is right on the assert.

    If I comment that out, I get the same error, but this time here:

    GenericChannel.sendAcknowledge(message);

    I tried sending msgLoad instead of the message variable and same result.

    I also tried just sending all 0xFF

    msgLoad[0] = 0xFF; // this is okay as it is
    msgLoad[1] = 0xFF;
    msgLoad[2] = 0xFF;
    msgLoad[3] = 0xFF;
    msgLoad[4] = 0xFF;
    msgLoad[5] = 0xFF;
    msgLoad[6] = 0xFF;
    msgLoad[7] = 0xFF;


    Same error..

    I am completely stumped.

    J
  • Former Member
    Former Member over 8 years ago
    Hi,

    Thanks for all the replies.

    I have tried various forms of all the code being sent and so far, no luck.

    Here is what I currently have:

    function sendTargetPower() {

    var watts = 200;
    var msgLoad = new[8];

    // the payload is .25W units, convert the whole units to quarters
    var quarter_watts = (watts * 4).toNumber();

    // make sure the result is legal. documented range is 0-4000W, and
    // we have already converted to quarter-watts...
    assert (0 >= quarter_watts && quarter_watts <= 16000);

    msgLoad[0] = 0x30; // this is okay as it is
    msgLoad[1] = 0xFF;
    msgLoad[2] = 0xFF;
    msgLoad[3] = 0xFF;
    msgLoad[4] = 0xFF;
    msgLoad[5] = 0xFF;
    msgLoad[6] = (watts & 0xFF);
    msgLoad[7] = (watts >> 8) & 0xFF;

    var message = new Ant.Message();
    message.setPayload(msgLoad);
    GenericChannel.sendAcknowledge(message);

    }


    The first error comes about at the assert:

    Failed invoking <symbol>
    Unexpected Type Error


    If I comment that out, I get the same error at the

    GenericChannel.sendAcknowledge(message);


    I have replaced message with msgLoad and no difference.

    I also tried with setting all of msgLoad with 0xFF and no change, same error.

    Long story short, I am completely stumped.

    J
  • The assert() function is something I use for my testing (it compile out in release builds). It isn't provided with the SDK. You should be able to use Test.assert(...) instead, but that isn't the actual problem. You could remove the line entirely as it isn't necessary.

    What does the code that creates the ChannelAssignment and DeviceConfig look like?