Design Tips of PicoBleAndroid for Mobile

Asset ‘PicoBleAndroid for Mobile’is an adapter interface tool for transfer from Pico W to Unity on Android mobile phone using BLE (Bluetooth low energy). By connecting the sensor device (gyro, accelerometer, GPS, etc.) with Pico W you can input various sense data to Unity. You can also output various data from Unity by connecting the display device (LED, LCD panel, etc.) with Pico W. This design tip explains how to modify for transfer data between Unity and Pico W based on the purchased Unity script example and the purchased Pico W code. This asset transfers array data up to 64 bytes from Unity to Pico W and array data up to 64 bytes from Pico W to Unity by changing the Unity script example and the Pico W code.

1. How to transfer data from Pico W to Unity
1.1 How to set up data to Unity in Pico W
1.2 How to get data from Pico W in Unity
2. How to transfer data from Unity to Pico W
2.1 How to set up data to Pico W in Unity
2.2 How to get data from Unity in Pico W

1. How to transfer data from Pico W to Unity

1.1 How to set up data to Unity in Pico W

The Pico W code ‘picoble.ino’ generates 3D Object‘tumbler’ tilt data ‘x, y, z’ using the “SIN” function and convert it to strings using the “sprintf” function of ‘gattReadCallback’function. The Pico W code needs to change the strings to byte array data type using ‘saccel.getBytes’ function for sending data to Unity when Pico W connects some sensors device.

  …

uint16_t gattReadCallback(uint16_t value_handle, uint8_t *buffer, uint16_t buffer_size) {
  (void)value_handle;
  (void)buffer_size;
  char sx[7];
  char sy[7];

  if (buffer) {
    sprintf(param, "degx:%d degy:%d", degx[value], degy[value]);
    Serial.println(param);

    x = sin(degx[value] / (180 / PI));
    y = sin(degy[value] / (180 / PI));
    dtostrf(x, 4, 2, sx);
    dtostrf(y, 4, 2, sy);

    sprintf(formatted_msg, "%s,%s,%s,", sx, sy, z);
    Serial.println(formatted_msg);

    String saccel = String(formatted_msg);
    byte sbyte[saccel.length()];
    saccel.getBytes(sbyte, saccel.length() + 1);

    for (int n = 0; n < saccel.length(); n++) {
      buffer[n] = sbyte[n];
      Serial.print(buffer[n], HEX);
      Serial.print(" ");
    }
    Serial.println("");
    // update deg array index
    value++;
    if (value >= (16 * 20)) {
      value = 0;
    }

    return saccel.length();
  }
  return 0;
} 
   …

‘gattReadCallback’function is the read callback from Unity to the Pico W. The tilt data ‘x, y, z’ is only stored in the provided buffer, if ‘buffer’ argument is not NULL.

1.2 How to get data from Pico W in Unity

Unity script example ‘PicoBleAndroidSampleCode.cs’ receives BLE data from Pico W as byte array data ‘str’ of return value of ‘obj.Call(“UpdateRead”)’ function. The byte array data ‘str’ encodes string code using ‘System.Text.Encoding.UTF8.GetString’ function and, using ‘text.Split’ function and ‘float.Parse’ function, the string code is converted to float position data.

       ...
// Update is called once per frame
void Update()
{
    float[] acceldata = new float[3];
    //byte[] indata = new byte[64];
    //int length = 0;

    byte[] str = obj.Call<byte[]>("UpdateRead");
    UnityEngine.Debug.LogWarning(TAG + " Update: " + str.Length);

    if (str.Length == 0)
    {
        UnityEngine.Debug.LogWarning(TAG + " Not connect ");
        return;
    }

    try
    {
        string text = System.Text.Encoding.UTF8.GetString(str);
        UnityEngine.Debug.LogWarning(TAG + " indata: " + text);

        string[] arr = text.Split(',');
        acceldata[0] = float.Parse(arr[0]);
        acceldata[1] = float.Parse(arr[1]);
        acceldata[2] = float.Parse(arr[2]);
        UnityEngine.Debug.LogWarning(TAG + " x: " + acceldata[0] + " y: " + acceldata[1] + " z: " + acceldata[2]);

        accelx = acceldata[0] * 100 + (-90);
        accely = acceldata[1] * 100;
        accelz = acceldata[2] * 100;

        transform.rotation = Quaternion.AngleAxis(accelx, Vector3.up) * Quaternion.AngleAxis(accely, Vector3.right);
    }
    catch (Exception e)
    {
        UnityEngine.Debug.LogWarning(TAG + e.ToString());
    }
    finally
    { }
}
       ...

Unity script example ‘PicoBleAndroidSampleCode.cs’ calls the ‘Call(“UpdateRead”)’ function in the following format for reading data from Pico W.

byte[] Call("UpdateRead");

2. How to transfer data from Unity to Pico W

2.1 How to set up data to Pico W in Unity

Unity script example ‘PicoBleAndroidSampleCode.cs’ call back ‘ButtonClick’ function at button ‘On’ clicked. ‘ButtonClick’ function inputs data from ’inputFieldno0’ / ‘inputFieldno1’, then calls ‘obj.Call(“Command”, writedata)’ function with the parameter of ‘writedata’ byte array.

   …
public void ButtonClick()
{
    UnityEngine.Debug.LogWarning(TAG + " ButtonClick "); ;

    byte[] writedata = new byte[2] { byte.Parse(inputFieldno0.text), byte.Parse(inputFieldno1.text) };

    bool result = obj.Call<bool>("Command", writedata);
    if (!result)
    {
        UnityEngine.Debug.LogWarning(TAG + " Not connect ");
        return;
    }

    UnityEngine.Debug.LogWarning(TAG + writedata[0] + " " + writedata[1]);
}

Unity script example ‘PicoBleAndroidSampleCode.cs’ calls the ‘Call(“Command”)’ function in the following format for sending byte array data to Pico W.

bool Call("Command", byte[] data);

2.2 How to get data from Unity in Pico W

The Pico W code ‘picoble.ino’calls back ‘gattWriteCallback’ function at received data from Unity. The ‘gattWriteCallback’ function receives Inputfield ’No0’ / Inputfield ‘No1’ of Unity as 2 bytes of data using the ‘buffer’ argument.

   …

int gattWriteCallback(uint16_t value_handle, uint8_t *buffer, uint16_t size) {
  (void)value_handle;
  (void)size;
  byte row;
  byte col;

  if (buffer) {
    row = buffer[0];
    col = buffer[1];
    Serial.println("\n************** receive data! ******************");
    Serial.println(row);
    Serial.println(col);
  }
  return 0;
}
   …

The Pico W code ‘picoble.ino’ calls the ‘getvalue’ function for receiving byte array data in the following format from Unity.

byte getvalue()[x];

x: byte array index
return: byte