Control brightness of an LED using Arduino and C#

Hi guys,
Let me go straight ahead to the problem: I’m using Arduino UNO R3 to control the brightness of an LED - which is connected to pin 9 ( to use PWM ). When user input a value in the range 0 → 255 through serial monitor, the brightness of the LED will correspondingly change. Then I use this method to make a graphical user interface using C# in Visual studio. In the design, I use the slider control in Visual studio to get the value of brightness that I want, then pass this value to the serial. The problem is that: when i use the mouse pointer to change the position of slider, the brightness of the LED still changes but after I stop changing the slider, the LED turns off. What I expected is after changing the slider, the LED’s brightness remains as before without turning off.

Here is the Arduino code:

int LED = 9;
int brightness;

void setup()
{
  pinMode(LED, OUTPUT);  
  Serial.begin(9600);
}

void loop()
{
  if(Serial.available() > 0){
    brightness = Serial.parseInt();
    Serial.println(brightness);
    analogWrite(LED, brightness);  
  }
}

Here is the C# code:

using System;
using System.IO.Ports;
using System.Windows;


namespace Arduino_control_brightness_of_LED {
    public partial class MainWindow {
        SerialPort myPort;
        public MainWindow() {
            InitializeComponent();
            init();
        }

        private void init() {
            myPort = new SerialPort();
            myPort.PortName = "COM3";
            myPort.BaudRate = 9600;

            try {
                myPort.Open();
                myPort.WriteLine("0");//turn off first
            }
            catch(Exception ex) {
                System.Windows.MessageBox.Show(ex.Message);
            }
        }

        private void sldBrightness_Scroll(object sender, RoutedPropertyChangedEventArgs<double> e) {
                if(myPort.IsOpen) {                
                    int temp = (int)sldBrightness.Value;
                    myPort.WriteLine(temp.ToString());
                    txtBrightness.Text = temp.ToString();
                }               
        }        
    }
}

Here is the link to the C# project folder: https://drive.google.com/folderview?id=0B_h63TpxB2txNkNVZms1ZFhhQW8&usp=sharing

Please help me.
Many thanks.

                    myPort.WriteLine(temp.ToString());

This sends a carriage return and a line feed after the string.

    brightness = Serial.parseInt();

The carriage return terminates the reading of the int.

Next time through loop(), there is serial data to read (the line feed is still in the buffer). So, parseInt() gets called again. There are no digits before the first non-digit character (the line feed), so it returns 0, and has cleared the buffer.

Stop using WriteLine(). Use Write() to send the data AND to send something after the data, to delimit the int value.

PaulS:

                    myPort.WriteLine(temp.ToString());

This sends a carriage return and a line feed after the string.

    brightness = Serial.parseInt();

The carriage return terminates the reading of the int.

Next time through loop(), there is serial data to read (the line feed is still in the buffer). So, parseInt() gets called again. There are no digits before the first non-digit character (the line feed), so it returns 0, and has cleared the buffer.

Stop using WriteLine(). Use Write() to send the data AND to send something after the data, to delimit the int value.

I changed to Wite() and it seems the problem is solved, but as I see, the LED doesn't react as fast as before. It means after a while from the moment I change the slider, the brightness starts to change.( not smooth at all ). Do u know how to fix this?

parseInt() has a 1000millisecond timeout, and you may be seeing that affecting how quickly the number is parsed.

try playing with Serial.setTimeOut() to reduce the timeout but still get all of the stream that contains the number.

I changed to Wite() and it seems the problem is solved, but as I see, the LED doesn't react as fast as before.

Because you ignored this part:

AND to send something after the data, to delimit the int value.

That's my guess, anyway, since you changed your code but didn't post it after changing it.

PaulS:
Because you ignored this part:
That’s my guess, anyway, since you changed your code but didn’t post it after changing it.

hehe sorry I didn’t notice about that.
My code after changing:

using System;
using System.IO.Ports;
using System.Windows;


namespace Arduino_control_brightness_of_LED {
    public partial class MainWindow {
        SerialPort myPort;
        public MainWindow() {
            InitializeComponent();
            init();
        }

        private void init() {
            myPort = new SerialPort();
            myPort.PortName = "COM3";
            myPort.BaudRate = 9600;

            try {
                myPort.Open();
                myPort.WriteLine("0");//turn off first
            }
            catch(Exception ex) {
                System.Windows.MessageBox.Show(ex.Message);
            }
        }

        private void sldBrightness_Scroll(object sender, RoutedPropertyChangedEventArgs<double> e) {
                if(myPort.IsOpen) {                
                    int temp = (int)sldBrightness.Value;
                    myPort.Write(temp.ToString());
                    txtBrightness.Text = temp.ToString();
                }               
        }        
    }
}

tranvannhancu:
My code after changing:

... and what was the result?

aarg:
... and what was the result?

As I said above, the speed of changing the brightness of the LED is very slow

BulldogLowell:
parseInt() has a 1000millisecond timeout, and you may be seeing that affecting how quickly the number is parsed.

try playing with Serial.setTimeOut() to reduce the timeout but still get all of the stream that contains the number.

Is this how to use it:

int LED = 9;
int brightness;

void setup()
{
  pinMode(LED, OUTPUT);  
  Serial.begin(9600);
  Serial.setTimeout(100); // Can i change this value??? Which should I change???
}

void loop()
{
}

void serialEvent()
{
  if(Serial.available() > 0){
    brightness = Serial.parseInt();
    Serial.println(brightness);
    analogWrite(LED, brightness);  
  }
}

First I change it to Serial.setTimeout(1) but LED seems not get its maximum brightness, then I change it to Serial.setTimeout(100)

Sorry, but you need to go back to @PaulS's comments

you should be terminating the int on the Tx side with a non-numeric char.

when parseInt() comes across the char, it completes the function.

What are you doing on the Tx side now?

                    int temp = (int)sldBrightness.Value;
                    myPort.Write(temp.ToString());
                    myPort.Write("!"); // Add this line!
                    txtBrightness.Text = temp.ToString();

PaulS:

                    int temp = (int)sldBrightness.Value;

myPort.Write(temp.ToString());
                    myPort.Write("!"); // Add this line!
                    txtBrightness.Text = temp.ToString();

If adding this line, then the problem happens again: after changing the slider, the LED turns off

If adding this line, then the problem happens again: after changing the slider, the LED turns off

Add a Serial.read() call after the parseInt() call, to consume the !.

Very simple method of receiving a delimited data packet and extracting the numeric value and the component (servos) to which the command is to be sent. Might be similar to what you want to do. You can try the code without having a servo connected just to see what is returned to the serial monitor.

//zoomkat 11-22-12 simple delimited ',' string parse 
//from serial port input (via serial monitor)
//and print result out serial port
//multi servos added 
// Powering a servo from the arduino usually *DOES NOT WORK*.

String readString;
#include <Servo.h> 
Servo myservoa, myservob, myservoc, myservod;  // create servo object to control a servo 

void setup() {
  Serial.begin(9600);

  //myservoa.writeMicroseconds(1500); //set initial servo position if desired

  myservoa.attach(6);  //the pin for the servoa control
  myservob.attach(7);  //the pin for the servob control
  myservoc.attach(8);  //the pin for the servoc control
  myservod.attach(9);  //the pin for the servod control 
  Serial.println("multi-servo-delimit-test-dual-input-11-22-12"); // so I can keep track of what is loaded
}

void loop() {

  //expect single strings like 700a, or 1500c, or 2000d,
  //or like 30c, or 90a, or 180d,
  //or combined like 30c,180b,70a,120d,

  if (Serial.available())  {
    char c = Serial.read();  //gets one byte from serial buffer
    if (c == ',') {
      if (readString.length() >1) {
        Serial.println(readString); //prints string to serial port out

        int n = readString.toInt();  //convert readString into a number

        // auto select appropriate value, copied from someone elses code.
        if(n >= 500)
        {
          Serial.print("writing Microseconds: ");
          Serial.println(n);
          if(readString.indexOf('a') >0) myservoa.writeMicroseconds(n);
          if(readString.indexOf('b') >0) myservob.writeMicroseconds(n);
          if(readString.indexOf('c') >0) myservoc.writeMicroseconds(n);
          if(readString.indexOf('d') >0) myservod.writeMicroseconds(n);
        }
        else
        {   
          Serial.print("writing Angle: ");
          Serial.println(n);
          if(readString.indexOf('a') >0) myservoa.write(n);
          if(readString.indexOf('b') >0) myservob.write(n);
          if(readString.indexOf('c') >0) myservoc.write(n);
          if(readString.indexOf('d') >0) myservod.write(n);
        }
         readString=""; //clears variable for new input
      }
    }  
    else {     
      readString += c; //makes the string readString
    }
  }
}

PaulS:
Add a Serial.read() call after the parseInt() call, to consume the !.

Thanks a lot. It works perfect