week14 : interface and application programming

Assignments: make an application which shows the inputs and / or outputs.

Since I started to study the interaction design, I usudally use Processing, Openframeworks and Arduino. So this week assignment was easy for me. Even though the serial communication is still messy and sometimes it works and sometimes it doesn't work. First I use the Processing and Arduino code to confirm the serial communciations between my board and Processing works correctly. For final project, I would like to use 3 hall sensros for inputs to detect the angle of my dolls. Actually I already have a board which has 3 analog pins, so I connected 3 hall sensors to it. In Arduino code, I use software serial and at the sending part, I use "serial.write()" like this.

  • serial.write(1);
  • serial.write(2);
  • serial.write(3);
  • serial.write(4);
  • serial.write(highByte(data));
  • serial.write(lowByte(data));
  • Here is the result. I draw the dots that "Y" was changed by sensors. Serial speed is 4800.

    Sorry for bad movie, but maybe you can see the 3 lines (white, green, red) and when I move the magnets, the lines change.

    Unity Communication

    Thanks for this great article.(The page is only Japanese.)

    Basically I use this program.

    Unity is the 3D game engine, if you wanna make 3D games (even wanna only use 3D models), it should be useful for you. In Unity, normally we program it with C# or Javascript. Unity doesn't support the serial port officially, but C# supports serial communication originally. It means that you can use your board and control your 3D model, charactors, everything in Unity (also outputs). However, Unity calls its programs 60 times/s because it's besically a game engine. To avoid that, I used a thread for serial port. It's first time for me and there is not any introductions on internet, so I would like to make a tutorial. (Please learn Unity basic tutorial first :) )

    You need to prepare these before.

  • Unity (I use version 5)
  • PCB board or arduino
  • FTDI cable
  • Here is the projects. Download this and open with Unity.

    Maybe you can see the box on the scene. First, you need to change the settings. Edit -> project settings -> player. Then you can see a new window in the right inspector window. Scroll down and in "other settings", you can find the "Api compatibility Level" under the "Optimization". Change it from .NET to .NET 2.0 (Maybe I changed it already in the files.)

    Open the "Serial Handler.cs".

  • public string portName = "/dev/tty.usbserial-FTH83HVZ";
  • public int baudRate = 4800;
  • Here it defines the Serial Port and baudRate.

  • private int data1=0; ~~ private int total3 =0;
  • you can defines the values for reading the data. I wanna read the 3 values (each are separed to 2 bytes, so I need at least 6 values). And in Arduino code, I send 1,2,3,4 before data, so totally I need 10 values for reading.

  • if (isNewMessageReceived_) {
  • OnDataReceived(total1.ToString("g") + "a"+ total2.ToString("g") +"a"+ total3 .ToString("g"));
  • }
  • I don't know why but C# serial functions only supports one String value, so I convert bytes to String. When the code gets the data, it sends the String to other functions.(I'll explain later.)

  • private void Open()
  • {
  • serialPort_ = new SerialPort(portName, baudRate, Parity.None, 8, StopBits.One);
  • serialPort_.Open();
  • Debug.Log("open the port ");
  • isRunning_ = true;
  • thread_ = new Thread(Read);
  • thread_.Start();
  • }
  • It defines the SerialPort. If you wanna know how it works, google the C# functions."Debug.Log()" is the Unity function which shows Log in Unity Console. If it can open the serial port correctly, then it establish the thread.

  • private void Read()
  • {
  • while (isRunning_ && serialPort_ != null && serialPort_.IsOpen) {
  • try {
  • if (serialPort_.BytesToRead > 0) {
  • data10 = data9;
  • data9 = data8;
  • data8 = data7;
  • data7 = data6;
  • data6 = data5;
  • data5 = data4;
  • data4 = data3;
  • data3 = data2;
  • data2 = data1;
  • data1 = serialPort_.ReadByte();
  • //Debug.Log("data is coming" + data6 + ":"+ data5 + ":"+ data4 + ":"+ data3 + ":"+ data2 + ":"+ data1);
  • if((data10 == 1) && (data9== 2) && (data8== 3) && (data7== 4)){
  • total1 = data6*256+data5;
  • total2 = data4*256+data3;
  • total3 = data2*256+data1;
  • //Debug.Log("data is coming" + total);
  • }
  • //message_ = serialPort_.ReadLine();
  • //Debug.Log("Reading port. " + data1);
  • isNewMessageReceived_ = true;
  • }
  • } catch (System.Exception e) {
  • Debug.LogWarning(e.Message);
  • }
  • }
  • }
  • It's reading part.As I said, I send the data set like "1,2,3,4,highbyte(data1),lowbyte(data1),,highbyte(data2),lowbyte(data2),highbyte(data3),lowbyte(data3)". If it can read correctly, it calculates totals. Then the recieved flag is gonna be true.

  • public void Write(string message)
  • {
  • try {
  • serialPort_.Write(message);
  • } catch (System.Exception e) {
  • Debug.LogWarning(e.Message);
  • }
  • }
  • In this time, I didn't use output, but if you want, you can use these functions.

    Next, I explain about RotateByAccelometors.cs. In this program, it recieves the data from SerialHandler and use it to rotate the box.

  • void OnDataReceived(string message) // reading data
  • {
  • var data = message.Split(
  • new string[]{"a"}, System.StringSplitOptions.None);
  • if (data.Length < 3 ) return;
  • try {
  • var angleX = float.Parse(data[0]);
  • var angleY = float.Parse(data[1]);
  • var angleZ = float.Parse (data[2]);
  • angle = new Vector3(angleX, angleY, angleZ);
  • } catch (System.Exception e) {
  • Debug.LogWarning(e.Message);
  • }
  • }
  • It gets the data as a String value and separates it to 3 angles. If you want to use serial data, make a C# program and add "public SerialHandler serialHandler;" and in "Start()"function, "serialHandler.OnDataReceived += OnDataReceived;".

    If you send the data to serial port, it's really easy. Just you can call "SerialHandler.Write(data)". You can find example in "LEDcontroller.cs".

    OpenFrameworks

    I also tried to connect with OpenFrameworks. It's really basic test but you can see the 3 rectangles linked to the hall sensors are moving in the movie.

    To use serial communication in openframeworks is really easy. you don't need any addons, just type

  • ofSerial = serial;
  • to define. Then type it in setup().

  • serial.oepn("device port",speed);
  • the part of communications should be in update() function. Reading is like this.

  • int value = serial.readByte();
  • Actually we have to clean buffers in the software when it finishes to read the data because otherwise too much data from ATtiny44 will stock in buffers and it makes your computer broken. To avoid that, call this function every you it finishes to read.

  • serial.flush();
  • You can Download all files in this week from final project page.