How would I change this code to toggle on off the LEDs?

UKHeliBob:
Do you mean that it makes the LED flash on/off whilst you hold the button down or just on and off once ?

What do you actually send when a button is held down ? If it is a stream of the same character, such as 'r', then the Arduino will continually change the state of the associated LED. You either need to change the PC program to send a character when the button becomes pressed rather than is pressed or have it send a different character for a press and a release, perhaps 'R' and 'r' so that the Arduino code can be written to differentiate between the press and the release.

Thanks UKHeliBob,
When I press the button the LED turns on but then flashes, it will turn off when I click the button again but when on it flashes, lol can't have my devices switching on and off when they need to be either on or off lol :wink:
I posted in a comment below the code from the "Sending" script from Unity just incase the issue is in there.

here is a screen capture of one of my interfaces, not the one I'm experimenting with but just so you get an idea of the toggle effect needed by the buttons in order to:
One click = device ON
Click Again = device OFF

UKHeliBob:
What is it in the Unity code that triggers the send* functions ?
Does Unity open the serial connection each time it sends data or does it remain open ? Opening the serial connection to most Arduinos will cause it to reset.

Well that code above has the sending stuff in it, there is another line on my actual buttons script that simply has:

"Sending.sendBlue();" which tells the "Sending" script to send the character "b"

Scripts talking to each other always tends to mess with my head a little :wink:

Knightriderguy:
Scripts talking to each other always tends to mess with my head a little :wink:

That, and they mess with each other when they're not working. That is why it is imperative that you not debug them together. Divide and conquer.

aarg:
That, and they mess with each other when they're not working. That is why it is imperative that you not debug them together. Divide and conquer.

Well as near as I can tell the character is being sent correctly but for some reason it makes the LED flash instead of stay on or off.

Well as near as I can tell the character is being sent correctly but for some reason it makes the LED flash instead of stay on or off.

It looks like the character is sent twice then.

florinc:
It looks like the character is sent twice then.

Not that I can tell by looking at the sending script, unless I'm not seeing something? Perhaps another set of eyes on this might help :wink:

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

public class Sending : MonoBehaviour {
    
    //public static SerialPort sp = new SerialPort("COM4", 9600, Parity.None, 8, StopBits.One);
	public static SerialPort sp = new SerialPort("/dev/cu.wchusbserial1420", 9600);
	public string message2;
	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;
		//}
	}

	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();
    }

    public static void sendYellow(){
    	sp.Write("y");
    }

    public static void sendGreen(){
    	sp.Write("g");
    	//sp.Write("\n");
    }
	

	public static void sendRed(){
    	sp.Write("r");
    }


	public static void sendBlue(){
		sp.Write("b");
	}
}

What also seems to happen even if I try this through the serial port tool, is if I key in r the red LED flashes, and if I hit r again the LED stays on and still flashes until I hit say b and then the blue LED comes on and flashes and the red LED turns off, if I hit b again the blue LED stays on and still flashes.
It does this for all of them.

Knightriderguy:
What also seems to happen even if I try this through the serial port tool, is if I key in r the red LED flashes, and if I hit r again the LED stays on and still flashes until I hit say b and then the blue LED comes on and flashes and the red LED turns off, if I hit b again the blue LED stays on and still flashes.
It does this for all of them.

That is with using this Arduino code:

int gLed = 10;
int yLed = 11;
int rLed = 12;
int bLed = 13;

byte Tog_r, Tog_y, Tog_g, Tog_b;
char myCol[20];

void setup() {  
   Serial.begin (9600);  
   pinMode(gLed, OUTPUT);    
   pinMode(yLed, OUTPUT);   
   pinMode(rLed, OUTPUT);
   pinMode(bLed, OUTPUT);   
  
   digitalWrite(gLed, LOW);
   digitalWrite(yLed, LOW);
   digitalWrite(rLed, LOW);
   digitalWrite(bLed, LOW); 
 
}


void loop() {
  int lf = 10;
  Serial.readBytesUntil(lf, myCol, 1);
    if(strcmp(myCol,"r")==0){
      Tog_r = !Tog_r; // enter r, LED on, enter r again LED off
       digitalWrite(rLed, Tog_r);
   }
   
  if(strcmp(myCol,"y")==0){
    Tog_y = !Tog_y; // enter y, LED on, enter y again LED off
      digitalWrite(yLed, Tog_y);
   }
  if(strcmp(myCol,"g")==0){
       Tog_g = !Tog_g; // enter g, LED on, enter g again LED off
      digitalWrite(gLed, Tog_g); 
   }
   if(strcmp(myCol,"b")==0){
       Tog_b = !Tog_b; // enter b, LED on, enter b again LED off
      digitalWrite(bLed, Tog_b);
   }
}

What do you see if you print myCol in the Serial monitor ?

Another observation. If Serial.readBytesUntil() times out without getting the character it is waiting for what does myCol get set to ? If it is unchanged since the previous read then the LED will toggle its state even if the character is not received.

How fast is this flashing? It continues when there is no input?

readBytesUntil has a terrible track record for this sort of thing. I would recommend changing to something like the code described in "serial input basics". I don't have the link to that, because I developed my own serial code that basically follows that plan anyway.

I figured I would go back to basics a little and try this code out. I can get the LEDs to turn on one at at time with each button press and they stay on, now all I need is for when I press the button again for each one to turn off with each button assigned to it.

int gLed = 10;
int yLed = 11;
int rLed = 12;
int bLed = 9;


char myCol[20];

void setup() {  
   Serial.begin (9600);  
   pinMode(gLed, OUTPUT); //Sets all the LED pins to Output on start up   
   pinMode(yLed, OUTPUT);   
   pinMode(rLed, OUTPUT);
   pinMode(bLed, OUTPUT);   
  
   digitalWrite(gLed, LOW); //turns all LEDs off
   digitalWrite(yLed, LOW);
   digitalWrite(rLed, LOW);
   digitalWrite(bLed, LOW); 
 
}


void loop() {
  int lf = 10;
  Serial.readBytesUntil(lf, myCol, 1);
    if(strcmp(myCol,"r")==0){
       digitalWrite(rLed, HIGH); //Turns Red LED on
   }
   
  if(strcmp(myCol,"y")==0){
      digitalWrite(yLed, HIGH); //Turns Yellow LED on
   }
  if(strcmp(myCol,"g")==0){
      digitalWrite(gLed, HIGH); //Turns Green LED on
   }
   if(strcmp(myCol,"b")==0){
      digitalWrite(bLed, HIGH); //Turns Blue LED on
   }
   
}

now all I need is for when I press the button again for each one to turn off with each button assigned to it.

So, what is the problem? You need to keep track of the state of each pin. When a letter arrives, set the stored state to the opposite state, and apply the stored state to the pin.

   if(strcmp(myCol,"r")==0)
   {
       redState = !redState;
       digitalWrite(rLed, redState); //Turns Red LED on
   }

UKHeliBob:
Do you mean that it makes the LED flash on/off whilst you hold the button down or just on and off once ?

What do you actually send when a button is held down ? If it is a stream of the same character, such as ‘r’, then the Arduino will continually change the state of the associated LED. You either need to change the PC program to send a character when the button becomes pressed rather than is pressed or have it send a different character for a press and a release, perhaps ‘R’ and ‘r’ so that the Arduino code can be written to differentiate between the press and the release.

Well it’s a digital button in the interface so you don’t hold it down you just click it in the same way that you would click the cubes in the tutorial I was following here

http://r3dstar.co.uk/?p=211

How do you know that the LEDs are not being turned on over and over again ?

Suggestions :

  1. Only read Serial data when there is some available rather than blindly using readBytesUntil() when there is nothing to read
  2. Print the value of myCol to see what you are receiving and when.
  3. Stop using readBytesUntil() and write your own function, but still only read from Serial when there is actually some data to read.
  1. Most of the Arduino demos and tutorials on the web are garbage. Take them as a starting point only.

PaulS:
So, what is the problem? You need to keep track of the state of each pin. When a letter arrives, set the stored state to the opposite state, and apply the stored state to the pin.

   if(strcmp(myCol,"r")==0)

{
      redState = !redState;
      digitalWrite(rLed, redState); //Turns Red LED on
  }

Hi Paul,
I changed my section of the code to what you have there and I get the following error:
RYGFromUnity:34: error: 'redState' was not declared in this scope
'redState' was not declared in this scope

Hi Paul,
I changed my section of the code to what you have there and I get the following error:
RYGFromUnity:34: error: 'redState' was not declared in this scope
'redState' was not declared in this scope

I did say "You need to keep track of the state of each pin." That means that YOU needed to add a global variable, called redState.

byte redState = LOW;

PaulS:
I did say "You need to keep track of the state of each pin." That means that YOU needed to add a global variable, called redState.

byte redState = LOW;

OK I'm missing something The code compiles and uploads ok but it still makes my LED flash on and off.

Here is my complete code.

int gLed = 10;
int yLed = 11;
int rLed = 12;
int bLed = 9;

byte redState = LOW;
char myCol[20];

void setup() {  
   Serial.begin (9600);  
   pinMode(gLed, OUTPUT); //Sets all the LED pins to Output on start up   
   pinMode(yLed, OUTPUT);   
   pinMode(rLed, OUTPUT);
   pinMode(bLed, OUTPUT);   
  
   digitalWrite(gLed, LOW); //turns all LEDs off
   digitalWrite(yLed, LOW);
   digitalWrite(rLed, LOW);
   digitalWrite(bLed, LOW); 
 
}


void loop() {
  int lf = 10;
  Serial.readBytesUntil(lf, myCol, 1);
    if(strcmp(myCol,"r")==0)
   {
       redState = !redState;
       digitalWrite(rLed, redState); //Turns Red LED on
   }

  if(strcmp(myCol,"y")==0){
      digitalWrite(yLed, HIGH); //Turns Yellow LED on
   }
  if(strcmp(myCol,"g")==0){
      digitalWrite(gLed, HIGH); //Turns Green LED on
   }
   if(strcmp(myCol,"b")==0){
      digitalWrite(bLed, HIGH); //Turns Blue LED on
   }
   
}

The code compiles and uploads ok but it still makes my LED flash on and off.

You are still reading serial input when there may not be any data to read. You still don't know what the value of myCol is when you use readBytesUntil() but no data is available, or at any other time for that matter. What sort of frequency does the LED flash at ? It would not happen to be once per second by any chance, would it ? That is the default value for serial timeout (used by readBytesUntil()) unless you have changed it.

UKHeliBob:
What sort of frequency does the LED flash at ?

Asked in reply #29, no answer.