top of page
  • Writer's pictureAlex V

S - Shopping: Final interaction

For the S we wanted a unique customizable interaction, like when you dress and choose every part to our outfit, we wanted to bring that feeling to the person using it.

In order to do that the user is going to use a tablet and paint a reference of the real S and then send the design to the real world. The Unity app is in the tablet, connected through bluetooth using the HC-05 dongle to an arduino that process all the information received and displays it in the neopixel.


In order to Unity to send the information through bluetooth to the Arduino I used the asset: https://assetstore.unity.com/packages/tools/input-management/android-microcontrollers-bluetooth-16467, it includes the java library for android and functions that allow you to send and receive information.


The Unity scene contains:

  • Main camera: A camera in orthographic mode.

  • Directional light: To view the objects in the scene.

  • InfoCanvas: The UI for connecting the tablet to the bluetooth module.

  • Canvas: The UI with the buttons for sending the colors and showing the instructions.

  • S: Empty gameobject with all the cubes as childs.

  • Cubes: A white cube with the size 1x1x1, a mesh renderer, a mesh filter, a box collider and the script Paint On Click.

  • BtConnector: Empty gameobject with the script Bluetooth Adapter, this is required in order to the asset to work.

  • EventSystem: Used to detect the user input.

  • ColorPicker: The prefab of the asset to choose the color.

  • InfoController: Is the manager of the scene, contains the script High Rate Terminal V2.

Using Unity, I created a scene that contains cubes positioned to look like the real S. Probably 2D sprites would have been a better option but I already have experience with 3D models and materials so I chose the tools I already know. To align the cubes I used the tool snap, found in Edit > Snap Settings...


To choose the color which the user is going to pain I used this Unity asset: https://assetstore.unity.com/packages/tools/gui/color-picker-triangle-91518, it includes a circular slider where the color is choosen and a triangle in the middle where user can adjust the white and black values of the color.


To adjust the cubes that form the S, I used this asset: https://assetstore.unity.com/packages/tools/utilities/ez-rename-31082 that allowed me to change the name of all the cubes beign child of the S gameobject to sort them later.


One of the biggest challenges when coding a Unity app is the lack of the debug screen in the Andoid device, this asset: https://assetstore.unity.com/packages/tools/gui/screen-logger-49114 allowed me to keep track of the logs in the screen.




Unity code


PaintOnClick.cs - Attached to every cube forming the S


using System.Collections;

using System.Collections.Generic;

using UnityEngine;


public class PaintOnClick : MonoBehaviour {


public ColorPickerTriangle ColorPickerTriangle;

public Renderer rend;


void Start () {

//Fetch the Renderer from the GameObject

rend = GetComponent<Renderer>();

}

void OnMouseOver()

{

// Change the color of the GameObject to the color chosen in the ColorPicker when the mouse is over GameObject

rend.material.color = ColorPickerTriangle.TheColor;

}

}



 

HighRateTerminalV2.cs uses a lot of functions of the asset to set up the bluetooth, so I will just describe the main ones.


public GameObject[] cubes; // Array of gameobjects containing the cubes

public string[] colorsArray; //Array containing the color of the cubes


// During the awake the connection to the bluetooth is set

void Awake()

{

BluetoothAdapter.askEnableBluetooth();//Ask user to enable Bluetooth


BluetoothAdapter.OnDeviceOFF += HandleOnDeviceOff;

BluetoothAdapter.OnDevicePicked += HandleOnDevicePicked; //To get what device the user picked out of the devices list


}


void Start()

{

//Find the cubes with the tag and order them

cubes = GameObject.FindGameObjectsWithTag("Cube").OrderBy(go => go.name, new AlphanumComparatorFast()).ToArray();

// Setting the length of the array to the total number of cubes

colorsArray = new string[cubes.Length];

}


// NOTE: This code is free to use in any program.

// ... It was developed by Dot Net Perls.

public class AlphanumComparatorFast : IComparer<string>

{

public int Compare(string x, string y)

{

string s1 = x as string;

if (s1 == null)

{

return 0;

}

string s2 = y as string;

if (s2 == null)

{

return 0;

}


int len1 = s1.Length;

int len2 = s2.Length;

int marker1 = 0;

int marker2 = 0;


// Walk through two the strings with two markers.

while (marker1 < len1 && marker2 < len2)

{

char ch1 = s1[marker1];

char ch2 = s2[marker2];


// Some buffers we can build up characters in for each chunk.

char[] space1 = new char[len1];

int loc1 = 0;

char[] space2 = new char[len2];

int loc2 = 0;


// Walk through all following characters that are digits or

// characters in BOTH strings starting at the appropriate marker.

// Collect char arrays.

do

{

space1[loc1++] = ch1;

marker1++;


if (marker1 < len1)

{

ch1 = s1[marker1];

}

else

{

break;

}

} while (char.IsDigit(ch1) == char.IsDigit(space1[0]));


do

{

space2[loc2++] = ch2;

marker2++;


if (marker2 < len2)

{

ch2 = s2[marker2];

}

else

{

break;

}

} while (char.IsDigit(ch2) == char.IsDigit(space2[0]));


// If we have collected numbers, compare them numerically.

// Otherwise, if we have strings, compare them alphabetically.

string str1 = new string(space1);

string str2 = new string(space2);


int result;


if (char.IsDigit(space1[0]) && char.IsDigit(space2[0]))

{

int thisNumericChunk = int.Parse(str1);

int thatNumericChunk = int.Parse(str2);

result = thisNumericChunk.CompareTo(thatNumericChunk);

}

else

{

result = str1.CompareTo(str2);

}


if (result != 0)

{

return result;

}

}

return len1 - len2;

}

}


// Once the button is pressed this function is called

public void Sending()

{


for (int i = 0; i < cubes.Length; i++) // Goes through all the array of colors

{

colorsArray[i] = ColorUtility.ToHtmlStringRGB(cubes[i].GetComponent<Renderer>().material.color); //Converts the colors to HEX

}


for (int i = 0; i < cubes.Length; i++) // Goes through all the array of colors and sends them as Bytes encoded in ASCII

{

device.send(System.Text.Encoding.ASCII.GetBytes(colorsArray[i]));


}


}



 

UIBehaviour.cs is for opening and closing the help menu


public class UIBehaviour : MonoBehaviour

{

public GameObject InfoSetup;

public void Activate()

{

InfoSetup.SetActive(true);

}


public void Dectivate()

{

InfoSetup.SetActive(false);

}

}



Arduino code


#include <FastLED.h> // Including library for the neopixel

#include <SoftwareSerial.h> // Including library for the bluetooth connection

#include <string.h> // Including library to use string functions


#define NUM_LEDS 84 // Total number of LEDs in the neopixel

#define DATA_PIN 6 // Defining the pin where the information is sent to the neopixel

#define CLOCK_PIN 7 // Defining the pin where the speed neopixel


SoftwareSerial Bluetooth(4, 3); // TX, RX // Defining the pins where the Bluetooth recieve the data


String incoming = ""; //store the received information of colors here

String subLED; //color of the LED to calculate

String lengthOfTheIncoming; //checks the length of the message recieved, in a future version to avoid data loss Arduino could request the message again if the length is below 504


CRGB leds[NUM_LEDS]; //assigning the number of LEDs to the neopixel


void setup() {

Serial.begin(57600); //Start the serial comunication

Bluetooth.begin(9600); //Start the serial comunication for the bluetooth module

FastLED.addLeds<WS2801, DATA_PIN, CLOCK_PIN, RBG >(leds, NUM_LEDS); //Start the LED strip

}


void loop()

{

while (Bluetooth.available()) // checks if the bluetooth is available

{

incoming = Bluetooth.readString(); // assign the recieved string to the variable


lengthOfTheIncoming = incoming.length(); // assign the string length to the variable


for (int i = 0; i < NUM_LEDS; i++) // goes through all the LEDs in he strip

{

subLED = incoming.substring(0 + i * 6, 6 + i * 6 ); // breaks the incoming message in sets of 6

String _red = subLED.substring(0, 2); // breaks the color in the digits corresponding to red

String _green = subLED.substring(2, 4); // breaks the color in the digits corresponding to green

String _blue = subLED.substring(4, 6); // breaks the color in the digits corresponding to blue


// converts the hexadecimal colors to decimal

long red = hexToDec(_red);

long green = hexToDec(_green);

long blue = hexToDec(_blue);


//apply to light system

leds [i] = CRGB(red, green, blue);

}

FastLED.show();

}


}


unsigned int hexToDec(String hexString) {


unsigned int decValue = 0;

int nextInt;


for (int i = 0; i < hexString.length(); i++) {


nextInt = int(hexString.charAt(i));

if (nextInt >= 48 && nextInt <= 57) nextInt = map(nextInt, 48, 57, 0, 9);

if (nextInt >= 65 && nextInt <= 70) nextInt = map(nextInt, 65, 70, 10, 15);

if (nextInt >= 97 && nextInt <= 102) nextInt = map(nextInt, 97, 102, 10, 15);

nextInt = constrain(nextInt, 0, 15);


decValue = (decValue * 16) + nextInt;

}


return decValue;

}


During the research through StackOverflow, Reddit... a lot of users suggested to stay away from using String, I ended up choosing String because is easier to declare and work with for me, also because this interaction is not that big the delay is not that big of a problem, if this required more LEDs or a faster interaction the code should use char arrays.

8 views0 comments

Recent Posts

See All

Sending the information from Unity to Arduino

So far this has been the most challenging task to complete, the first success was sending the information through a COM port from the Unity in the computer to Arduino. Once the build was in the tablet

NFC

bottom of page