Send Pin Or LED Status From Arduino To Unity

My Arduino code is kind of set up as a series of toggle on off states that are being sent from Unity to the Arduino through the serial port as characters.

How can I send information from the Arduino with my current Arduino code so that In Unity 3D I can check the status of the pin or LED that is on the Arduino pin.

int lightPin = 0; //Define Pin For Photoresistor
int lightInt = 0;
//int lightLevel = analogRead(0);
//int threshold = 250;
//int range = 50;

const byte rLed = 12; //Sets Pin number LED is conneted too
const byte rLed2 = 1;
const byte yLed = 11;
const byte gLed = 10;
const byte gLed2 = 5;
const byte gLed3 = 4;
const byte wLed = 3;
const byte bLed = 2;
const byte bLed2 = 13;
char myChar;         //changed the name of this variable because they are not all colurs now
const byte pulsePins[] = {6, 7, 8, 9};  //pins for a pulse output
char pulseTriggers[] = {'p', 'q','R','L'};
const int NUMBER_OF_PULSE_PINS = sizeof(pulsePins);
unsigned long pulseStarts[NUMBER_OF_PULSE_PINS];
unsigned long pulseLength = 500;

void setup()
{
  //Serial.begin (9600);
  Serial.begin (115200);
  Serial.setTimeout(13); //Added today Sun Nov 22 ( not sure if this is needed? )
  pinMode(wLed, OUTPUT);
  pinMode(rLed, OUTPUT);
  pinMode(rLed2, OUTPUT);
  pinMode(yLed, OUTPUT);
  pinMode(gLed, OUTPUT);
  pinMode(gLed2, OUTPUT);
  pinMode(gLed3, OUTPUT);
  pinMode(bLed, OUTPUT);
  pinMode(bLed2, OUTPUT);
  digitalWrite(wLed, LOW);
  digitalWrite(rLed, LOW);
  digitalWrite(rLed2, LOW);
  digitalWrite(yLed, LOW);
  digitalWrite(gLed, LOW);
  digitalWrite(gLed2, LOW);
  digitalWrite(gLed3, LOW);
  digitalWrite(bLed, LOW);
  digitalWrite(bLed2, LOW);
  
  for (int p = 0; p < NUMBER_OF_PULSE_PINS; p++)
  {
    pinMode(pulsePins[p], OUTPUT);
    digitalWrite(pulsePins[p], LOW);
  }
}

void loop()
{ 
  //Light Sensor
    if((lightInt - analogRead(lightPin)) > 100 || (lightInt - analogRead(lightPin)) < -100){
      lightInt = analogRead(lightPin);
      Serial.println(lightInt);
    }
    //read the current light level.
    /*int lightLevel = analogRead(lightPin);
    //If the light level is within our desired range, send it to Unity.
    if(lightLevel > threshold - range && lightLevel < threshold + range)
    Serial.println(lightLevel);
    */
  if (Serial.available())              //if serial data is available
  {
    
    int lf = 10;

    myChar = Serial.read();             //read one character from serial
    if (myChar == 'r')                  //if it is an r
    {
      digitalWrite(rLed, !digitalRead(rLed));  //Oil Slick Toggle
    }
    
    if (myChar == 'b')
    {
      digitalWrite(bLed, !digitalRead(bLed)); //Surveillance Mode Toggle
    }

    if (myChar == 'y')
    {
      digitalWrite(yLed, !digitalRead(yLed)); //Movie Player Toggle
    }

    if (myChar == 'g')
    {
      digitalWrite(gLed, !digitalRead(gLed)); //Auto Phone Toggle
    }

    if (myChar == '1')
    {
      digitalWrite(bLed2, !digitalRead(bLed2)); //Scanner Toggle
    }

    if (myChar == 'f')
    {
      digitalWrite(gLed2, !digitalRead(gLed2)); //Fog Lights Toggle
    }

    if (myChar == 'h')
    {
      digitalWrite(gLed3, !digitalRead(gLed3)); //Head Lights Toggle
    }

    if (myChar == 'H')
    {
      digitalWrite(wLed, !digitalRead(wLed)); //High Beams Toggle
    }


    //Rear Hatch Popper
    for (int p = 0; p < NUMBER_OF_PULSE_PINS; p++)
    {
      if (myChar == pulseTriggers[p])
      {
        pulseStarts[p] = millis();  //save the time of receipt
        digitalWrite(pulsePins[p], HIGH);
      }
    }


    //Grappling Hook Launch
    for (int q = 0; q < NUMBER_OF_PULSE_PINS; q++)
    {
      if (myChar == pulseTriggers[q])
      {
        pulseStarts[q] = millis();  //save the time of receipt
        digitalWrite(pulsePins[q], HIGH);
      }
    }


    //Auto Doors Right Pulse
    for (int R = 0; R < NUMBER_OF_PULSE_PINS; R++)
    {
      if (myChar == pulseTriggers[R])
      {
        pulseStarts[R] = millis();  //save the time of receipt
        digitalWrite(pulsePins[R], HIGH);
      }
    }


    //Auto Doors Left Pulse
    for (int L = 0; L < NUMBER_OF_PULSE_PINS; L++)
    {
      if (myChar == pulseTriggers[L])
      {
        pulseStarts[L] = millis();  //save the time of receipt
        digitalWrite(pulsePins[L], HIGH);
      }
    }
  }

  //the following code runs each time through loop()
  for (int p = 0; p < NUMBER_OF_PULSE_PINS; p++)
  {
    if (millis() - pulseStarts[p] >= pulseLength)  //has the pin been HIGH long enough ?
    {
      digitalWrite(pulsePins[p], LOW);   //take the pulse pin LOW
    }
  }

  for (int q = 0; q < NUMBER_OF_PULSE_PINS; q++)
  {
    if (millis() - pulseStarts[q] >= pulseLength)  //has the pin been HIGH long enough ?
    {
      digitalWrite(pulsePins[q], LOW);   //take the pulse pin LOW
    }
  }
}

For the ignorant, what is "Unity"?

Weedpharma

weedpharma:
For the ignorant, what is "Unity"?

That must be me. :smiley:
I'd never heard of it until now.

@Knightriderguy, does this help at all? :-
Basic Arduino to Unity tutorial
I haven't watched it, but just spotted it while looking to see what "Unity" is and thought it might be helpful.

OldSteve:
That must be me. :smiley:
I'd never heard of it until now.

@Knightriderguy, does this help at all? :-
Basic Arduino to Unity tutorial
I haven't watched it, but just spotted it while looking to see what "Unity" is and thought it might be helpful.

Yes I have seen that one, I have a load of Unity to Arduino video saved into a playlist on my channel. None of the ones I have found really say a lot about how to read back the state of a pin on the Arduino so that in Unity you can update the UI. Which is a G.U.I. (Graphical User Interface) that one creates in Unity for their game interface, HUD displays etcetera.

I did see a video where a guy uses Unity and Arduino over an internet connection to update his UI in Unity but not being a coder its hard to sift through all the stuff in the code and figure out what is what.... I'd give my left nut for a coder with a little free time on his hands to help me out with my project, it would have been done by now instead of taking a year wracking my non code brain over stuff that an experience coder would whip through in seconds.... But because I have not been able to find anyone with any free time on their hands I have no choice but to muddle through.

Sorry for the whining I hate it as much as the next person but like I say I have no choice if I want to get this done. :wink:

Have you created a thread in Gigs and Collaboration (linking this one, and any other related ones)?

I'm sure that you are right, that someone who knows what they are doing could do this in nothing flat.

Having the Unity code that is to read the Arduino output would be a big help.

If the Arduino is free to define the format, then "n1:v1, n2:v2, ..., nN:vN" seems the simplest, where nN is a pin number and vN is the value read from that pin. : is the name/value pair separator, and , is the pair delimiter.

PaulS:
Have you created a thread in Gigs and Collaboration (linking this one, and any other related ones)?

I'm sure that you are right, that someone who knows what they are doing could do this in nothing flat.

Having the Unity code that is to read the Arduino output would be a big help.

If the Arduino is free to define the format, then "n1:v1, n2:v2, ..., nN:vN" seems the simplest, where nN is a pin number and vN is the value read from that pin. : is the name/value pair separator, and , is the pair delimiter.

Thanks PaulS
Yes I have tried a number of different forums and project posts to sequester some help. I have even offered a 50/50 split on anything the project makes. And I do have people within the Knight Rider community who build these K.I.T.T. car replicas very interested in the project when it is done.

For what it's worth here is the unity code that reads the data in from the Arduino:

using UnityEngine;
using System.Collections;
using System.IO.Ports;
using System.Threading;

public class Sending : MonoBehaviour {

	//Random Clips
	public AudioClip[] voices;

	//_isPlayingSound is true when a sound is currently playing - just as the name suggests.
	private bool _isPlayingSound;

	public GameObject worldLight;
	public static Sending sending;

    //public static SerialPort sp = new SerialPort("COM4", 9600, Parity.None, 8, StopBits.One);
	public static SerialPort sp = new SerialPort("/dev/cu.wchusbserial1420", 115200);

	public string message2;


	void Awake () {
		if (sending == null) {
			DontDestroyOnLoad (gameObject);
			sending = this;
		} else if (sending != this) {
			Destroy (gameObject);
		}
		
	}


	float timePassed = 0.0f;
	// Use this for initialization
	void Start () {
		OpenConnection();
	}
	
	// Update is called once per frame
	void Update () {
		//timePassed+=Time.deltaTime;
		//if(timePassed>=0.2f){

			//print("BytesToRead" +sp.BytesToRead);
			message2 = sp.ReadLine();
			//print(message2);
		//	timePassed = 0.0f;
		//}

		if (message2!="") {
			print("called");
			lightMeUp(message2);
		}
	}

	public void OpenConnection() 
    {
       if (sp != null) 
       {
         if (sp.IsOpen) 
         {
          sp.Close();
          print("Closing port, because it was already open!");
         }
         else 
         {
          sp.Open();  // opens the connection
          sp.ReadTimeout = 16;  // sets the timeout value before reporting error
          print("Port Opened!");
		//		message = "Port Opened!";
         }
       }
       else 
       {
         if (sp.IsOpen)
         {
          print("Port is already open");
         }
         else 
         {
          print("Port == null");
         }
       }
    }

    void OnApplicationQuit() 
    {
       sp.Close();
    }

	//Movie Player Toggle
    public static void sendYellow(){
    	sp.Write("y");
    }

	//Auto Phone Toggle
    public static void sendGreen(){
    	sp.Write("g");
    	//sp.Write("\n");
    }
	
	//Oil Slick Toggle
	public static void sendRed(){
    	sp.Write("r");
    }

	//Surveillance Mode Toggle
	public static void sendBlue(){ 
		sp.Write("b");
	}

	//Scanner Toggle
	public static void sendRed2(){
		sp.Write("1");
	}

	//Fog Lights Toggle
	public static void sendGreen2(){
		sp.Write("f");
	}

	//Head Lights Toggle
	public static void sendGreen3(){
		sp.Write("h");
	}

	//Hight Beams Toggle
	public static void sendWhite(){
		sp.Write("H");
	}

	//Rear Hatch Popper
	public static void sendPulse1(){
		sp.Write("p");
	}
	
	//Grappling Hook Launch
	public static void sendPulse2(){
		sp.Write("q");
	}

	//Auto Doors Right Pulse
	public static void sendPulse3(){
		sp.Write("R");
	}

	//Auto Doors Left Pulse
	public static void sendPulse4(){
		sp.Write("L");
	}



	void lightMeUp(string message){
		//If there is a sound currently playing, return immediately so we don't play another sound simultaneously.
		//if(_isPlayingSound) is shorthand for if(_isPlayingSound == true), in case you where wondering.
		if (_isPlayingSound)
			return;
		print (message);
		float fl = float.Parse (message) / 100.0f;
		fl = 1.0f - fl;

		//Do something Here if Light Value on the LDR is near Darkness

		//Do Something Here if the Light Value on the LDR is near Daylight brightness

		//BONUS if Possible Do something if the LDR is deliberately played with like waving hand over or blocking and un blocking the sensor.




			//Pick a random sound.
			AudioClip randomClip = voices [UnityEngine.Random.Range (0, voices.Length)];
			//Play that sound.
			GetComponent<AudioSource> ().PlayOneShot (randomClip);
			//Flag that we are currently playing a sound.
			_isPlayingSound = true;
			//Start a coroutine that will set the flag to false once the sound stops playing, so we can start playing a new sound.
			StartCoroutine (RunResetIsPlayingSoundFlag (randomClip.length));

	}
	private IEnumerator RunResetIsPlayingSoundFlag(float soundDuration)
	{
		//Wait until the sound finishes playing.
		yield return new WaitForSeconds(soundDuration);
		//Disable the _isPlayingSound flag, so we can play a new sound since this one is over.
		_isPlayingSound = false;
	
	}	
}

So, lightMeUp() is called if there is serial data to be read, once the serial data has been read.

			message2 = sp.ReadLine();

expects that the sender will terminate the message with a carriage return and line feed. The Serial.println() method does that.

lightMeUp() expects the serial data to be a string representation of a float between 0 and 100.

So, if you read the value of an LDR:

  int val = analogRead(LDR);
  float valToSend = val / 1023 * 100;

  byte stg[10];
  dtostrf(valToSend, 8, 3, stg);
  Serial.println(stg);

The value from the pin will be between 0 and 1023. The value in valToSend will be between 0 and 1.0, after the division, and will be between 0 and 100.0 after the multiplication. The dtostrf() function converts the value to a string, and the last line sends it to the serial port, where Unity is presumably listening.

PaulS:
So, lightMeUp() is called if there is serial data to be read, once the serial data has been read.

			message2 = sp.ReadLine();

expects that the sender will terminate the message with a carriage return and line feed. The Serial.println() method does that.

lightMeUp() expects the serial data to be a string representation of a float between 0 and 100.

So, if you read the value of an LDR:

  int val = analogRead(LDR);

float valToSend = val / 1023 * 100;

byte stg[10];
  dtostrf(valToSend, 8, 3, stg);
  Serial.println(stg);




The value from the pin will be between 0 and 1023. The value in valToSend will be between 0 and 1.0, after the division, and will be between 0 and 100.0 after the multiplication. The dtostrf() function converts the value to a string, and the last line sends it to the serial port, where Unity is presumably listening.

Thanks PaulS
Yeah the LDR is part of one of my problems I have been struggling with.
Basically in Unity I'm trying to get it to Do something when the light value from the LDR reaches a level close to dusk it will play an audio clip from a random array of clips in Unity.

And when the LDR reaches a value close to sun up that it will play an audio clip from another array of clips.

Also as a bonus if possible to have it somehow play from another array of clips if someone was to be deliberately waving their hand over the LDR sensor.

I have no clue how or what in my code I need to tweak or change to do this.

There are the LED light states on the pins for the Arduino too that I somehow need to report back to Unity so that it can update the Interface / U.I. in unity.

An example is that I have a screen that has a toggle on/off button that sends a message to the Arduino as a character in order to turn on an LED, which works. The on/off toggle button in unity also starts an animation that needs to be set to play if I exit that scene and then return and the LED is on on the Arduino..... sorry if all that sounds confusing but I can quantify all of that with video if you like.?