Novas formas de interação com o computador e jogos podem ser desenvolvidas a partir da integração entre o Arduino conectado a um acelerômetro e a engine para desenvolvimento de jogos Unity3D.
Conexão do hardware
Código fonte para o Arduino
/* | |
Autor: Marco T. Chella | |
Em: 28/09/2016 | |
Para saber mais: | |
*/ | |
void setup() { | |
// initialize serial communication at 9600 bits per second: | |
Serial.begin(9600); | |
} | |
// the loop routine runs over and over again forever: | |
void loop() { | |
// read the input on analog pin 0: | |
String vx = String (analogRead(A0)); | |
String vy = String (analogRead(A1)); | |
String vz = String (analogRead(A2)); | |
Serial.println(vx + "," + vy + "," + vz); | |
delay(10); // delay in between reads for stability | |
} |
Código fonte para o Unity3D
/* | |
Autor Marco T. Chella | |
em: 28/09/2016 | |
Para saber mais: | |
*/ | |
using UnityEngine; | |
using System.Collections; | |
using System.IO.Ports; | |
using System.Threading; | |
public class com_serial : MonoBehaviour { | |
public SerialPort sp; | |
public Thread serialThread; | |
float x_mapeado; | |
float angleX_filtrado; | |
float y_mapeado; | |
float angley_filtrado; | |
void Start () { | |
print("app iniciando…."); | |
x_mapeado = 0; | |
angleX_filtrado =0; | |
angley_filtrado = 0; | |
sp = new SerialPort("COM3", 9600); | |
sp.Open(); | |
sp.ReadTimeout = 50; | |
sp.Handshake = Handshake.None; | |
serialThread = new Thread(recData); | |
serialThread.Start(); | |
print("app iniciado!"); | |
} | |
// Update is called once per frame | |
void Update () { | |
// atualiza posicao do cubo com valores do acelerometro ja processados | |
GameObject.Find("Cube").transform.rotation= Quaternion.Euler( new Vector3(x_mapeado, 0, y_mapeado)); | |
} | |
public void Close() | |
{ | |
sp.Close(); | |
Debug.Log("Fechar"); | |
} | |
void OnDestroy() | |
{ | |
EndThread(); | |
sp.Close(); | |
Debug.Log("Destroi"); | |
} | |
// thread da comunicacao serial | |
void recData() | |
{ | |
string data; | |
while (1 == 1) | |
{ | |
if ((sp != null) && (sp.IsOpen)) | |
{ | |
try | |
{ | |
data = sp.ReadLine(); | |
string[] tokens = data.Split(','); | |
// parse da string recebida do arduino ex: "125,592,8" | |
int eixo_x = System.Convert.ToInt16(tokens[0]); | |
int eixo_y = System.Convert.ToInt16(tokens[1]); | |
int eixo_z = System.Convert.ToInt16(tokens[2]); | |
float vx = (float) eixo_x * 5f / 1023f; | |
float vy = (float)eixo_y * 5f / 1023f; | |
float vz = (float)eixo_z * 5f / 1023f; | |
float z = 1.8f * 5.1f / 5f; //1.8 corresponde a 0G do acelerometro | |
vx -= z; | |
vy -= z; | |
vz -= z; | |
float sensitivity = 200 * 5.1f / 5f; // sensibilidade | |
sensitivity = sensitivity / 1000; | |
float gx = vx * sensitivity; | |
float gy = vy * sensitivity; | |
float gz = vz * sensitivity; | |
// calculo do angulo | |
float m = (float)System.Math.Sqrt (gx * gx + gy * gy + gz * gz); | |
float angleX = (float)System.Math.Acos(gx / m); | |
float angleY = (float)System.Math.Acos(gy / m); | |
float angleZ = (float)System.Math.Acos(gz / m); | |
// converte angulo para graus | |
angleX = angleX * 180f / 3.14f; | |
angleY = angleY * 180f / 3.14f; | |
angleZ = angleZ * 180f / 3.14f; | |
// filtro passa-baixa | |
float alpha = 0.1f; | |
angleX_filtrado = angleX * alpha + (angleX_filtrado * (1.0f – alpha)); | |
angley_filtrado = angleY * alpha + (angley_filtrado * (1.0f – alpha)); | |
//normalizar valores | |
x_mapeado = mapear(angleX_filtrado, 20, 166, 90, –90); | |
y_mapeado = mapear(angley_filtrado, 15, 160, 90, –90); | |
//Debug.Log(angleX + "," + x_mapeado); | |
//Debug.Log(angleX + "," + angleY + "," + angleZ); | |
Debug.Log(vx + "," + vy + "," + vz); //valor raw dos sensores | |
// Debug.Log(tokens[0] + "," + tokens[1] + "," + tokens[2]); | |
} | |
catch (System.TimeoutException) | |
{ | |
data = null; | |
} | |
//print(data); | |
} | |
Thread.Sleep(1); | |
} | |
} | |
// encerrar thread | |
void EndThread() | |
{ | |
try | |
{ | |
if (serialThread.IsAlive) | |
{ | |
serialThread.Abort(); | |
Debug.Log("tentativa encerrar thread"); | |
} | |
} | |
catch | |
{ | |
Debug.Log("falha encerramento da thread"); | |
} | |
} | |
float mapear(float x, float in_min, float in_max, float out_min, float out_max) | |
{ | |
return (x – in_min) * (out_max – out_min) / (in_max – in_min) + out_min; | |
} | |
} |
Algumas referências: