Design Tips of PicoBle for PC

Asset ‘PicoBle for PC’ is an adapter interface tool for transfer from Pico W to Unity via Windows PC 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. Pico W 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‘glasses’ 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 ‘PicoBleSampleCode.cs’ receives BLE data from Pico W as byte array data ‘readdata’ of return value of ‘m_PicoBleLib.UpdateRead’ function. The byte array data ‘readdata’ 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()
{
    byte[] readdata = new byte[] { };
    //UnityEngine.Debug.LogWarning("Update");
    if (!m_PicoBleLib.UpdateRead(ref readdata))
    {
        return;
    }
    UnityEngine.Debug.LogWarning(" Read1: " + readdata[0] + " " + readdata[1] + " " + readdata[2]); 
    UnityEngine.Debug.LogWarning(" Read2: " + readdata.Length);

    string text = System.Text.Encoding.UTF8.GetString(readdata);
    UnityEngine.Debug.LogWarning(" Read3: " + text);
    string[] arr = text.Split(',');
    float[] acceldata = new float[3];
    acceldata[0] = float.Parse(arr[0]);
    acceldata[1] = float.Parse(arr[1]);
    acceldata[2] = float.Parse(arr[2]);


    UnityEngine.Debug.LogWarning(" Update: " + acceldata[0] + " " + acceldata[1] + " " + acceldata[2]);

    accelx = acceldata[0] * 100;
    accely = acceldata[1] * 100;
    accelz = acceldata[2] * 100;

    transform.rotation = Quaternion.AngleAxis(accelx, Vector3.up) * Quaternion.AngleAxis(accely, Vector3.right);
}
       ...

Unity script example ‘PicoBleSampleCode.cs’ calls the ‘UpdateRead’ function in the following format for reading data from Pico W.

bool UpdateRead(ref byte[] readdata)

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 ‘PicoBleSampleCode.cs’ call back ‘ButtonClick’ function at button ‘On’ clicked. ‘ButtonClick’ function inputs data from ’inputFieldno0’ / ‘inputFieldno1’, then calls ‘m_PicoBleLib.Command’ function with the parameter of ‘writedata’ byte array.

   …

public void ButtonClick()
{
    UnityEngine.Debug.LogWarning("ButtonClick: ");

    byte[] writedata = new byte[2] { byte.Parse(inputFieldno0.text) , byte.Parse(inputFieldno1.text) };
    UnityEngine.Debug.LogWarning(writedata[0] + " " + writedata[1]);
    m_PicoBleLib.Command(writedata);
}

   …

Unity script example ‘PicoBleSampleCode.cs’ calls the ‘Command’ function in the following format for sending byte array data to Pico W.

 
void Command(byte[] writedata);

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;
}
   …