It seems that I somehow deleted the old answer, but this one is better suited anyways. Good to hear that your sensor is working. To do other commands, follow the comment block about the command packets located right before the declaration of send_bytes. So for wireless communication the button command it would look like this:
byte[] button_bytes = {0xf8, 0x00, 0xfa, 0xfa};
And for the tare command:
byte[] tare_bytes = {0xf8, 0x00, 0x60, 0x60};
You can find the list of commands and some more detail about the commands in the Wireless Manual.
Here are the scripts we have edited to have the button states and taring in them. They are timed based, so if you wanted to use keyboard commands you will have to look up how to capture keyboard events in Unity. There is also some bug fixes that were not apparent before that Mono has when reading from a serial port.
Communicating via USB or Bluetooth
using UnityEngine;
using System;
using System.Collections;
using System.IO.Ports;
public class cube_rotator : MonoBehaviour{
// Connect to the serial port the 3-Space Sensor is connected to
public static SerialPort sp = new SerialPort("\\\\.\\COM4");
// Command packet for getting the filtered tared orientation as a quaternion
// {header byte, command byte, [data bytes], checksum byte}
// checksum = (command byte + data bytes) % 256
public static byte[] send_bytes = {0xf7, 0x00, 0x00};
public static byte[] button_bytes = {0xf7, 0xfa, 0xfa};
public static byte[] tare_bytes = {0xf7, 0x60, 0x60};
public int counter = 0;
// Use this for initialization
void Start(){
// Allow the user to set the appropriate properties.
sp.BaudRate = 115200;
sp.Parity = Parity.None;
sp.DataBits = 8;
sp.StopBits = StopBits.One;
// Set the read/write timeouts
sp.WriteTimeout = 500;
sp.ReadTimeout = 500;
sp.Open();
sp.Write(send_bytes,0,3);
}
// Helper function for taking the bytes read from the 3-Space Sensor and converting them into a float
float bytesToFloat(byte[] raw_bytes, int offset){
byte[] big_bytes = new byte[4];
big_bytes[0] = raw_bytes[offset+3];
big_bytes[1] = raw_bytes[offset+2];
big_bytes[2] = raw_bytes[offset+1];
big_bytes[3] = raw_bytes[offset+0];
return BitConverter.ToSingle(big_bytes,0);
}
void getButtonState(){
sp.Write(button_bytes, 0, 3);
byte[] read_bytes = new byte[1];
int fail_counter = 0;
// Mono, for some reason, seems to randomly fail on the first read after a wirte so we must loop
// through to make sure the bytes are read
while (true){
try{
sp.Read(read_bytes, 0, 1);
break;
}
catch{
++fail_counter;
// Failed to read from serial port
}
if (fail_counter > 100){
throw new System.Exception("Failed to read from port too many times." +
" This could mean the port is not open or the Mono serial read is not responding.");
}
}
if (read_bytes[0] == 0){
print("No buttons are pressed.");
}
else if (read_bytes[0] == 1){
print("Right button is pressed.");
}
else if (read_bytes[0] == 2){
print("Left button is pressed.");
}
else if (read_bytes[0] == 3){
print("Left and Right buttons are pressed.");
}
}
void tareSensor(){
sp.Write(tare_bytes, 0, 3);
}
// Update is called once per frame
void Update(){
counter++;
// A quaternion consists of 4 floats which is 16 bytes
byte[] read_bytes = new byte[16];
// Mono, for some reason, seems to randomly fail on the first read after a wirte so we must loop
// through to make sure the bytes are read and Mono also seems not to always read the amount asked
// so we must also read one byte at a time
int read_counter = 100;
int byte_idx = 0;
while (read_counter > 0){
try{
byte_idx += sp.Read(read_bytes, byte_idx, 1);
}
catch{
// Failed to read from serial port
}
if (byte_idx == 16){
break;
}
if (read_counter <= 0){
throw new System.Exception("Failed to read quaternion from port too many times." +
" This could mean the port is not open or the Mono serial read is not responding.");
}
--read_counter;
}
// Convert bytes to floats
float x = bytesToFloat(read_bytes,0);
float y = bytesToFloat(read_bytes,4);
float z = bytesToFloat(read_bytes,8);
float w = bytesToFloat(read_bytes,12);
// Create a quaternion
Quaternion quat = new Quaternion(x,y,z,w);
// Perform rotation
transform.rotation = quat;
if ((counter % 25) == 0){
getButtonState();
}
else if (counter > 150){
tareSensor();
counter = 1;
}
// Send command
sp.Write(send_bytes,0,3);
}
}
Communicating via Wireless
using UnityEngine;
using System;
using System.Collections;
using System.IO.Ports;
public class cube_rotator_wireless : MonoBehaviour{
// Connect to the serial port the 3-Space Dongle is connected to
public static SerialPort sp = new SerialPort("\\\\.\\COM3");
// Wireless Command packet for getting the filtered tared orientation as
// a quaternion
// {header byte, id byte + command byte, [data bytes], checksum byte}
// checksum = (id byte + command byte + data bytes) % 256
public static byte[] send_bytes = {0xf8, 0x00, 0x00, 0x00};
public static byte[] button_bytes = {0xf8, 0x00, 0xfa, 0xfa};
public static byte[] tare_bytes = {0xf8, 0x00, 0x60, 0x60};
public int counter = 0;
// Use this for initialization
void Start(){
// Allow the user to set the appropriate properties.
sp.BaudRate = 115200;
sp.Parity = Parity.None;
sp.DataBits = 8;
sp.StopBits = StopBits.One;
// Set the read/write timeouts
sp.WriteTimeout = 500;
sp.ReadTimeout = 500;
sp.Open();
sp.Write(send_bytes, 0, 4);
}
// Helper function for taking the bytes read from the 3-Space Sensor and
// converting them into a float
float bytesToFloat(byte[] raw_bytes, int offset){
byte[] big_bytes = new byte[4];
big_bytes[0] = raw_bytes[offset + 3];
big_bytes[1] = raw_bytes[offset + 2];
big_bytes[2] = raw_bytes[offset + 1];
big_bytes[3] = raw_bytes[offset + 0];
return BitConverter.ToSingle(big_bytes, 0);
}
void getButtonState(){
sp.Write(button_bytes, 0, 4);
// Wireless packets always have a confirm and id byte pre-appened to the data
byte[] confirm_byte = new byte[1];
byte[] id_byte = new byte[1];
int fail_counter = 0;
// Mono, for some reason, seems to randomly fail on the first read after a wirte so we must loop
// through to make sure the bytes are read
while (true){
try{
sp.Read(confirm_byte, 0, 1);
sp.Read(id_byte, 0, 1);
break;
}
catch{
++fail_counter;
// Failed to read from serial port
}
if (fail_counter > 100){
throw new System.Exception("Failed to read from port too many times." +
" This could mean the port is not open or the Mono serial read is not responding.");
}
}
if (confirm_byte[0] == 0){
// Read data length of packet
byte[] length_byte = new byte[1];
sp.Read(length_byte, 0, 1);
byte length = length_byte[0];
// Read the length of the data in the packet
byte[] read_bytes = new byte[length];
sp.Read(read_bytes, 0, length);
if (read_bytes[0] == 0){
print("No buttons are pressed.");
}
else if (read_bytes[0] == 1){
print("Right button is pressed.");
}
else if (read_bytes[0] == 2){
print("Left button is pressed.");
}
else if (read_bytes[0] == 3){
print("Left and Right buttons are pressed.");
}
}
}
void tareSensor(){
sp.Write(tare_bytes, 0, 4);
// Wireless packets always have a confirm and id byte pre-appened to the data
byte[] confirm_byte = new byte[1];
byte[] id_byte = new byte[1];
int fail_counter = 0;
// Mono, for some reason, seems to randomly fail on the first read after a wirte so we must loop
// through to make sure the bytes are read
while (true){
try{
sp.Read(confirm_byte, 0, 1);
sp.Read(id_byte, 0, 1);
break;
}
catch{
++fail_counter;
// Failed to read from serial port
}
if (fail_counter > 100){
throw new System.Exception("Failed to read from port too many times." +
" This could mean the port is not open or the Mono serial read is not responding.");
}
}
if (confirm_byte[0] == 0){
// Read data length of packet
byte[] length_byte = new byte[1];
sp.Read(length_byte, 0, 1);
byte length = length_byte[0];
// Read the length of the data in the packet
byte[] read_bytes = new byte[length];
sp.Read(read_bytes, 0, length);
}
}
// Update is called once per frame
void Update(){
counter++;
// Wireless packets always have a confirm and id byte pre-appened to the data
byte[] confirm_byte = new byte[1];
byte[] id_byte = new byte[1];
int fail_counter = 0;
// Mono, for some reason, seems to randomly fail on the first read after a wirte so we must loop
// through to make sure the bytes are read
while (true){
try{
sp.Read(confirm_byte, 0, 1);
sp.Read(id_byte, 0, 1);
break;
}
catch{
++fail_counter;
// Failed to read from serial port
}
if (fail_counter > 100){
throw new System.Exception("Failed to read from port too many times." +
" This could mean the port is not open or the Mono serial read is not responding.");
}
}
if (confirm_byte[0] == 0){
// Read data length of packet
byte[] length_byte = new byte[1];
sp.Read(length_byte, 0, 1);
byte length = length_byte[0];
// Read the length of the data in the packet
byte[] read_bytes = new byte[length];
sp.Read(read_bytes, 0, length);
// Convert bytes to floats
float x = bytesToFloat(read_bytes, 0);
float y = bytesToFloat(read_bytes, 4);
float z = bytesToFloat(read_bytes, 8);
float w = bytesToFloat(read_bytes, 12);
// Create a quaternion
Quaternion quat = new Quaternion(x, y, z, w);
// Perform rotation
transform.rotation = quat;
}
if ((counter % 25) == 0){
getButtonState();
}
else if (counter > 150){
tareSensor();
counter = 1;
}
sp.Write(send_bytes, 0, 4);
}
}