phyphox / phyphox-android

Physical Phone Experiments
GNU General Public License v3.0
303 stars 39 forks source link

Xamarin Forms #32

Closed bojankostic81 closed 1 year ago

bojankostic81 commented 1 year ago

Hi, I'm using phypox for the Xamarin Forms project and I have an issue with the data I'm receiving. My sending method looks like this:

static void write(float&, float&, float&, float&, float&).

Data of interest for the client app is contained in the first two floats of this data load.

On the client side, I received byte[20] for 5 floats sent from the MC. I split my incoming byte array into 5 chunks of 4 bytes and took the first two to parse them to float.

void FormatInput(byte[] bytes)
{
    var arraysOf4Bytes = bytes
        .Select((b, i) => new { b, i })
        .GroupBy(x => x.i / 4)
        .Select(g => g.Select(x => x.b)
        .ToArray())
        .ToList();

    foreach (var item in arraysOf4Bytes.Take(2))
    {
        if (item != null)
        {
            var data = BitConverter.ToSingle(BitConverter.IsLittleEndian ? item.Reverse().ToArray() : item, 0);
            Output.Text += data.ToString() + Environment.NewLine;
        }
    }
}

However, I'm getting huge values after parsing with the code above. Expected values after parsing should be in the range between 0 and 100. Any idea what I'm doing wrong or how should I parse data I receive?

Staacks commented 1 year ago

I am not entirely sure I understand what you are trying to do, but let me try to unpack it: You are sending data with our Arduino library (judging from the function signature for write you are showing) and receiving it with your own code using Xamarin Forms? Where does phyphox come into it?

Anyhow, getting unexpectedly large numbers might be a byte order problem. Our library uses little endian and your code seems to follow the platform endianess, which would fail if your running it on a big endian platform. So, if my hunch is correct, you should just replace BitConverter.IsLittleEndian ? item.Reverse().ToArray() : item with only item.Reverse().ToArray().

Oh, and by the way, write is overloaded, so you can just use write(float&, float&) unless you really need to pad your data to 20B.

bojankostic81 commented 1 year ago

You are right, we are using you library to send data from MC, and we are trying to get these data in Xamarin Forms application. Here is our code for sending data using BLE:

#include <phyphoxBle.h> 
char board_name[] = "Flexisens";
void setup()
{   
        PhyphoxBLE::start(board_name); 
}

void loop() 
{
    float sense = analogRead(A1);
    PhyphoxBLE::write(sense);
    delay(50); 
}

Here we are sending data from temperature sensor. Strange thing is that we are sending only one float but we are receiving byte[20] on client side. We have tried your suggestion with replacingBitConverter.IsLittleEndian ? item.Reverse().ToArray() : item with only item.Reverse().ToArray(), but without success.

Do you any suggestion how we should proceed?

Staacks commented 1 year ago

I am not too surprised that receive 20B. That's the default limit for a characteristic (with the default MTU) and it is what our library sets to allow for a maximum of five floats (without changing the MTU). I cannot say if sending a shorter package would be possible or if it might be the Xamarin implementation that pads the values, but you should be able to safely ignore the remainder.

Before continuing, I would highly recommend to not use our library if you do not intent to use phyphox. Most of what our library does is generating an XML configuration file for phyphox and setting up additional characteristics to allow phyphox to find and load this configuration. This uses significant memory and resources without bringing any benefit when not using phyphox. If you really just use our Arduino library to set up a GATT server and write a few values to it, you should really search for a basic BLE tutorial. This will be way more efficient while giving you much more control (for example a 16bit int is sufficient to transfer the output from analogRead).

I am closing this issue as it has nothing to do with "phyphox-android".

However, if you really want to continue with this approach, feel free to answer here. I like a little binary riddle :) To figure out what went wrong here, I would suggest the following:

  1. Instead of sending real measured data, try sending a known sequence with a longer delay. For example, send 0, 1, 2, 3, 4, etc with a delay of 1000ms between each.
  2. Then use the app "nRF Connect" by Nordic Semiconductors (highly recommended, a central tool for us) to connect to your microcontroller and see if you can receive the sequence as expected by subscribing to the characteristic. (Take into account the that is sent as a Little Endian 32bit floating point number)
  3. Then check if you get these bytes in the correct order in "item" in your C# code.

Feel free to post the data here as well as the wrong numbers that you get after conversion. Maybe I can see what got mixed up. Right now I am a bit suspicious of that "select" command, but maybe that is just because I have never written anything in C#.

bojankostic81 commented 1 year ago

The biggest issue for me is that I'm receiving correct results while using your android app, so probably I'm doing something wrong.

bojankostic81 commented 1 year ago

Is there some guidance you can provide how to use phyphox with C#?

Staacks commented 1 year ago

Sorry, I have never done anything in C#. But I am also not entirely sure what you are trying to do? Do you want to use phyphox (which is an App for Android and iOS) after all or are you asking about how to use our Arduino library (which is just a tool to integrate Arduino projects with our app) with C#?

Maybe, if you describe what you want to achieve, I can give you a suggestion on how to approach it. Phyphox is very versatile and customizable...