lancaster-university / codal-microbit-v2

CODAL target for the micro:bit v2.x series of devices
MIT License
44 stars 52 forks source link

Radio throwing error: conversion from 'codal::PacketBuffer' to non-scalar type 'codal::ManagedString' requested #161

Open mytechnotalent opened 2 years ago

mytechnotalent commented 2 years ago

When trying to implement a simple radio program that will send and recv data which is based on the micro:bit DAL runtime example it is breaking.

https://lancaster-university.github.io/microbit-docs/ubit/radio/

Actual Results: code

#include "MicroBit.h"

MicroBit uBit;

void onData(MicroBitEvent e)
{
    ManagedString s = uBit.radio.datagram.recv();

    if (s == "1")
    {
        uBit.display.print("A");
    }
    if (s == "2")
    {
        uBit.display.print("B");
    }
}

int main(void)
{
    uBit.init();;

    uBit.messageBus.listen(MICROBIT_ID_RADIO, MICROBIT_RADIO_EVT_DATAGRAM, onData);
    uBit.radio.enable();

    while(1)
    {
        if(uBit.buttonA.isPressed())
        {
            uBit.radio.datagram.send("1");
        }
        else if(uBit.buttonB.isPressed())
        {
            uBit.radio.datagram.send("2");
        }

        uBit.sleep(100);
    }       
}

error

/Users/developer/microbit-v2-samples/source/main.cpp: In function 'void onData(MicroBitEvent)':
/Users/developer/microbit-v2-samples/source/main.cpp:7:47: error: conversion from 'codal::PacketBuffer' to non-scalar type 'codal::ManagedString' requested
    7 |     ManagedString s = uBit.radio.datagram.recv();
      |                       ~~~~~~~~~~~~~~~~~~~~~~~~^~
make[2]: *** [CMakeFiles/MICROBIT.dir/source/main.cpp.o] Error 1
make[1]: *** [CMakeFiles/MICROBIT.dir/all] Error 2

@microbit-carlos

mytechnotalent commented 2 years ago

I have also attempted with packetbuffer. This compiles but no result from either micro:bit when pressing any of the buttons. @microbit-carlos


#include "MicroBit.h"

MicroBit uBit;

void onData(MicroBitEvent e)
{
    PacketBuffer p = uBit.radio.datagram.recv();

    if (p[0] == 1)
    {
        uBit.io.P0.setServoValue(0);
        uBit.display.print("A");
    }

    if (p[0] == 2)
    {
        uBit.io.P0.setServoValue(180);
        uBit.display.print("B");
    }
}

int main(void)
{
    uBit.init();
    uBit.radio.enable();

    // Create a packet containing just a single byte.
    PacketBuffer b(1);

    uBit.messageBus.listen(MICROBIT_ID_RADIO, MICROBIT_RADIO_EVT_DATAGRAM, onData);

    while(1)
    {
        b[0] = 0;
        if (uBit.buttonA.isPressed())
            b[0] = 1;

        else if (uBit.buttonB.isPressed())
            b[0] = 2;

        uBit.radio.datagram.send(b);
        uBit.sleep(100);
    }
}
martinwork commented 2 years ago

@mytechnotalent I hope @microbit-carlos won't mind be jumping in here! The second program, using PacketBuffer, works for me, so long a both micro:bits have it!

For the first program, so long as the radio data is simple text, this converts the PacketBuffer to a ManagedString:

    PacketBuffer p = uBit.radio.datagram.recv();
    ManagedString s( (const char *) p.getBytes(), p.length());

The two programs won't talk to each other because the first is using characters '1' and '2', while the second is using bytes 1 and 2.

mytechnotalent commented 2 years ago

@martinwork yes the 2nd one works now. The issue I had and did not realize is one was a V1 and the other was a V2. The second program works when both are V2. Thanks for the help!

microbit-carlos commented 2 years ago

The main reason the original code example doesn't work is probably because ManageString doesn't have a PacketBuffer constructor in CODAL:

I haven't looked much further, but if I remember correctly PacketBuffer is a type defined here in codal-microbit-v2, which would explain why it is not included in the codal-core ManagedString. But as @martinwork has covered, it should be possible to create a ManagedString using the PacketBuffer.getBytes() method.

martinwork commented 2 years ago
#include "MicroBit.h"

MicroBit uBit;

void onData(MicroBitEvent e)
{
    PacketBuffer p = uBit.radio.datagram.recv();
    ManagedString s( (const char *) p.getBytes(), p.length());

    if (s == "1")
    {
        uBit.display.print("A");
    }
    if (s == "2")
    {
        uBit.display.print("B");
    }
}

int main(void)
{
    uBit.init();;

    uBit.messageBus.listen(MICROBIT_ID_RADIO, MICROBIT_RADIO_EVT_DATAGRAM, onData);
    uBit.radio.enable();

    while(1)
    {
        if(uBit.buttonA.isPressed())
        {
            uBit.radio.datagram.send("1");
        }
        else if(uBit.buttonB.isPressed())
        {
            uBit.radio.datagram.send("2");
        }

        uBit.sleep(100);
    }       
}
microbit-carlos commented 2 years ago

The issue I had and did not realize is one was a V1 and the other was a V2. The second program works when both are V2.

In theory if that code works in V1 DAL it should work mixing micro:bit V1 & V2, as the radio should be compatible, otherwise we can consider it a bug.

Can you confirm which version of the programme compiled with DAL & CODAL doesn't work together (but works together when using two identical micro:bits).

mytechnotalent commented 2 years ago

@microbit-carlos the below worked when compiling with DAL & CODAL on the V2.


#include "MicroBit.h"

MicroBit uBit;

void onData(MicroBitEvent e)
{
    PacketBuffer p = uBit.radio.datagram.recv();

    if (p[0] == 1)
    {
        uBit.io.P0.setServoValue(0);
        uBit.display.print("A");
    }

    if (p[0] == 2)
    {
        uBit.io.P0.setServoValue(180);
        uBit.display.print("B");
    }
}

int main(void)
{
    uBit.init();
    uBit.radio.enable();

    // Create a packet containing just a single byte.
    PacketBuffer b(1);

    uBit.messageBus.listen(MICROBIT_ID_RADIO, MICROBIT_RADIO_EVT_DATAGRAM, onData);

    while(1)
    {
        b[0] = 0;
        if (uBit.buttonA.isPressed())
            b[0] = 1;

        else if (uBit.buttonB.isPressed())
            b[0] = 2;

        uBit.radio.datagram.send(b);
        uBit.sleep(100);
    }
}
microbit-carlos commented 2 years ago

Thanks @mytechnotalent! And what version of the programme doesn't work when used with V1 and V2?

mytechnotalent commented 2 years ago

@microbit-carlos neither example works when using a V1 and a V2 in combination.

microbit-carlos commented 2 years ago

Is that also the case when setting the radio frequency and group in the code? (in case the defaults are different) https://lancaster-university.github.io/microbit-docs/ubit/radio/#int-setgroup-uint8_t-group https://lancaster-university.github.io/microbit-docs/ubit/radio/#int-setfrequencyband-int-band

mytechnotalent commented 2 years ago

I have not tested those.

martinwork commented 2 years ago

Just remembered, for PacketBuffer/ManagedString, see https://github.com/lancaster-university/codal-microbit-v2/issues/89

Setting group and frequency doesn't seem to help V1 and V2 talk. I think the default V1 and V2 settings match. In fact my V1 build was not working at all!

I think the solution is that for V1, microbit-samples needs a config.json for radio to work, otherwise BLE in enabled by default, like this: https://github.com/lancaster-university/microbit-samples/blob/master/source/examples/simple-radio-rx/config.json

microbit-v2-samples comes with a no-BLE codal.json.