C#/.Net - Adjusting brightness

Hi everyone, having some trouble understanding/figuring out what to do here. If it helps to know, I'm using an Arduino UNO.

I have a C# program that turns an LED connected to Analog pin 9 - that works perfectly fine. I am now trying to add a text box to my program that will take a value entered (between 0-255) and adjust the brightness of the LED accordingly when I hit the "change" button. But I am having trouble understanding how to send a value like that, and how to have the Arduino "interpret" that - then adjust the brightness. I know how to "hard code" a brightness value straight into the Arduino sketch, but I want the brightness to be sort of like a variable that can be adjusted from my C# application.

Here is my C# Code at the moment:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports;


namespace ArduinoBlink
{

    public partial class Form1 : Form
    {

        public Form1()
        {
            InitializeComponent();

            serialPort1.PortName = "COM4"; //Using COM4 as serial port
            serialPort1.BaudRate = 9600; //Setting our Baud Rate to 9600
            serialPort1.Open(); //Opening our serial port

            ButtonOff.Enabled = false; //Disabling the off button when we start our program, as the LED is off by default
            BrightnessBox.Enabled = false; //Cannot adjust brightness until the LED is "on"
            ChangeButton.Enabled = false;  //Same as the line above


            //Check if port is open
            if (!serialPort1.IsOpen)
            {
                MessageBox.Show("Could not open port");
            }

        }


        private void ButtonOn_Click(object sender, EventArgs e)
        {

            //When "On" button is clicked, enable the Textbox "Brightness" and the "Change" button. Enables "Off" button.
            BrightnessBox.Enabled = true;
            ChangeButton.Enabled = true;
            ButtonOn.Enabled = false;
            ButtonOff.Enabled = true;


            //Writes "1" to the serial port, the arduino sees this and turns the LED on.
            serialPort1.Write("1");
            label1.Text = "LED is on!";
            label1.BackColor = Color.Green;

        }

        private void ButtonOff_Click(object sender, EventArgs e)
        {

            //When "Off" button is clicked, disable the Textbox "Brightness" and the "Change" button. Enables "On" button.
            BrightnessBox.Enabled = false;
            ChangeButton.Enabled = false;
            ButtonOn.Enabled = true;
            ButtonOff.Enabled = false;


            //Writes "0" to the serial port, the arduino sees this and turns the LED off.
            serialPort1.Write("0");
            label1.Text = "LED is off!";
            label1.BackColor = Color.Red;


        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {

            //If we close the form and the port is open, close it.
            if (serialPort1.IsOpen)
            {
                serialPort1.Close();
            }
        }


        private void ChangeButton_Click(object sender, EventArgs e)
        {
            //When I click the "change" button, I want to take the value in BrightnessBox.text (from 0-255)
            //and then send that to the Arduino. I then want the Arduino to do whatever is needed
            //To adjust the brightness via information sent from my C# program

        }


    }

}

And here's the Arduino code:

int ledPin = 9; 

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

void loop()                    
{
  if(Serial.available())
  {  
    
   char incomingChar = Serial.read(); 

//your protocol goes here
switch(incomingChar)
{
case '1':
 // led is ON
 analogWrite(ledPin, 255);
 break;
 
case '0':
 // led is OFF
 analogWrite(ledPin, 0);
 break;
 
   }      
  }
}

If it helps to understand what I'm trying to do better, here's a little screenshot of my c# program (Once the LED is "on" I want to be able to adjust the brightness of the LED):

Thanks in advanced, let me know if I can make something more clear. However, I am still very "noob" at this.

Use a slider instead of a textbox, it will prevent users from sending bogus data.

You could maybe modify the sketch similar to this:

static unsigned char PWMValue = 255;

switch(incomingChar)
{
case '1':
 // led is ON
 analogWrite(ledPin, PWMValue  );
 break;
 
case '0':
 // led is OFF
 analogWrite(ledPin, 0 );
 break;

default:
  
  //Set PWM
  PWMValue = incomingChar;

  //Need to check the LED is on first or, set the C# app to disable brightness level when LED is off.
  analogWrite(ledPin, PWMValue  );
 
   }

or send two bytes to the arduino, one saying which command its sending, then the second is the data.

Thanks Atomic, it seems to be on the right track. There are still some issues I am having though. Whenever I set the brightness in my C# to a value that contains a 0 (at the end of the value - such as a number like 20 or 100) the Arduino turns off the LED. Is it because I am sending the value as a string? I'm not sure how else to send it. You mentioned sending as bytes but I'm not really sure how to go about that.

Not sure how to go about this part:

        private void trackBar1_ValueChanged(object sender, EventArgs e)
        {
            label3.Text = trackBar1.Value.ToString();
            serialPort1.Write(trackBar1.Value.ToString());
        }

you will need to modify your arduino code to accept multiple bytes of data.

Using the value 25, it seems like your code may be setting it to level 2, then 5 straight away.
If you wish to keep using strings, send a message start and message end value. Or just send a null.

Or in your c# app send a byte rather than a string representing a byte:

serialPort1.Write( Convert.ToByte( trackBar1.Value ) );

Then modify your switch to accept integer literals rather than character literals:

switch(incomingChar){
  case 0: //Not '0'
    break;

  case 1:
    break;
}

Oops, meant to say thanks "Pyro" not Atomic, must have read your signature instead!

Visual studio seems to be having an issue with this line here:

serialPort1.Write( Convert.ToByte( trackBar1.Value ) );

The errors are as follows:

error CS1502: The best overloaded method match for 'System.IO.Ports.SerialPort.Write(string)' has some invalid arguments

error CS1503: Argument 1: cannot convert from 'byte' to 'string'

The only overloads it seems to accept are:

  • SerialPort.Write(string text)

  • SerialPort.Write (byte[] buffer, int offset, int count)

  • SerialPort.write (char[] buffer, int offset, int count)

I've not used C# too much at all really, only peeked at it.
However something like this may work:

  byte[] data = { Convert.ToByte(trackBar1.Value) };
  serialPort1.Write( data, 0, 1 );

Thanks! It's working 100% as intended now! But can I ask what the 0 and the 1 are in the following line and how it works? I'd like to learn what it actually means:

(data, 0, 1)

Sure, I used the msdn reference,

by searching google for "system.io.ports"

the second link has all the serial functionality, where I found this:

SerialPort.Write Method (Byte[], Int32, Int32)

Thank you

I am having trouble understanding "offset" however:

offset
Type: System.Int32
The zero-based byte offset in the buffer parameter at which to begin copying bytes to the port.

Can you explain to me what this means or give me something to read on it? Like I said in my first post, I'm still "very" new to this stuff. Sorry if it's extremely obvious and I'm not just "getting it".

data is an array so it can contain many elements, we only put one in it though.
So 0 means use the start ( first element ) in the array. and the 1 is the number of bytes to send.

I found this helpful:
What You Need to Know to Move from C++ to C#

But you need tutorials it seems. Arrays may help too.

And C# Programmer's Reference

Ahh ok, I understand it now from this post:

data is an array so it can contain many elements, we only put one in it though.
So 0 means use the start ( first element ) in the array. and the 1 is the number of bytes to send.

Thank you very much! You've helped me a lot today!