serial communication between arduino and C#

Hi everyone...i dont know hoe to go about posing the rest of it because it involves a WPF C# application im writing but okay... so im making a lighting controller for my PCs lights...it uses serial to communicate between a WPF C# application and the arduino its self. im using Serial.parseInt() to read the string that the wpf app puts out but I get some strange results...whereas if i use the arduino serial terminal, it works....the string is sent in the form "Red Green Blue " as "255 255 255 "(spaces included as not numeric character) to tell serial.parse when the numeric value ends. please note that this may need some knowledge of C# in order to follow(im new at it myself)

arduino sketch:

//pinouts
int ledR = 9;
int ledG = 10;
int ledB = 11;

//sketch variables
int valR = 0;
int valG = 0;
int valB = 0;

void setup(){
	
	Serial.begin(9600);
	pinMode(ledR, OUTPUT);
	pinMode(ledG, OUTPUT);
	pinMode(ledB, OUTPUT);
}

void loop(){

	if (Serial.available() > 0) {
		valR = Serial.parseInt();
                valG = Serial.parseInt();
                valB = Serial.parseInt();
	}
}

void colorWrite(int amR, int amG, int amB){
	analogWrite(ledR, amR);
	analogWrite(ledG, amG);
	analogWrite(ledB, amB);
}

please note that this may need some knowledge of C# in order to follow(im new at it myself)

It doesn't if you don't post your C# code.

Since that code is working with the Serial Monitor, I think it's safe to say that the Arduino code is fine (though not necessarily optimum).

PaulS:
Since that code is working with the Serial Monitor, I think it's safe to say that the Arduino code is fine (though not necessarily optimum).

some tips as far as that is concerned would be greatly appreciated. im still learing the ropes and that would be a big part of it.

i dont know if this is going to help because to me it just seems out of context but we can safely assume thats due to my noobness haha:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

using System.IO.Ports;

namespace serial_send_test_2
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        string valR;
        string valG;
        string valB;

        private SerialPort serialPort1;

        public MainWindow()
        {
            InitializeComponent();
            serialPort1 = new SerialPort("COM3", 9600, Parity.None, 8, StopBits.One);
            serialPort1.Open();
        }


        //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        private void Slider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            var slider = sender as Slider;
            double value = slider.Value;
            valR = value.ToString();
            serialTransmit();
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            serialPort1.WriteLine("255 ");
        }

        private void Button_Click_1(object sender, RoutedEventArgs e)
        {
            serialPort1.WriteLine("0 ");
        }
        //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        private void Slider_ValueChanged_1(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            var slider = sender as Slider;
            double value = slider.Value;
            valG = value.ToString();
            serialTransmit();
        }

        private void Button_Click_3(object sender, RoutedEventArgs e)
        {
            serialPort1.WriteLine("255 ");
        }

        private void Button_Click_2(object sender, RoutedEventArgs e)
        {
            serialPort1.WriteLine("0 ");
        }

        //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        public void Slider_ValueChanged_2(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            var slider = sender as Slider;
            double value = slider.Value;
            valB = value.ToString();
            serialTransmit();
        }

        private void Button_Click_5(object sender, RoutedEventArgs e)
        {
            serialPort1.WriteLine("255 ");
        }

        private void Button_Click_4(object sender, RoutedEventArgs e)
        {
            serialPort1.WriteLine("0 ");
        }
        //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        public void serialTransmit()
        {
            serialPort1.WriteLine(valR + " " + valG + " " + valB + " ");
            this.Title = valR + " " + valG + " " + valB;
        }

        private void Window_closing()
        {
            serialPort1.Close();
            MessageBox.Show("Serial Port Closed");
        }
    }
}

the idea was to send the rgb values as a single string but if theres a easier/better way to to it, please let me know...also is there any general way to give an "address" via serial so that specific values could be directed within the sketch?

        string valR;
        string valG;
        string valB;

Every time a slider changes position, you send these three strings. What is sent when the first slider changes? Think about that. It may not be what you initially assumed.

okay but the function that sends the strings is called when any one of the 3 changes so even if it does send the other 2 it would just be telling the arduino to set that specific color to what it was before that? so if green was at 255 on the arduino and therefore the same on the wpf app then it would just stay the same? correct me if im missing something:/

okay but the function that sends the strings is called when any one of the 3 changes so even if it does send the other 2 it would just be telling the arduino to set that specific color to what it was before that? so if green was at 255 on the arduino and therefore the same on the wpf app then it would just stay the same? correct me if im missing something:/

I think that you are. You fire up the application. Where are the sliders? What values are in valR, valG, and valB?

You move a slider. Suppose you move the blue one. A value is assigned to valB, and the values in valR, valG, and valB are sent. What are all three values?

Add this to your sender:

Console.WriteLine("Red: [{0}]", valR);
Console.WriteLine("Grn: [{0}]", valG);
Console.WriteLine("Blu: [{0}]", valB);

so that you KNOW what is in those three strings.

I'm willing to bet that the strings do not always contain the values that you think they do.

Hi paul ive been out but thanks for your response i will try this as soon as possible...much thanks

okay I just tried it and attached is a screenshot of the results:
I moved through RGB as follows:
RED up to 22 - GREEN up to - and BLUE up to 42

the results seem to be right? my appologies if im being persistantly wrong with this...

im going to go out on a limb and ask...is it possible that the sliders values are being changed and sent too fast for the arduino to keep track of or does the serial buffer take care of that?

the results seem to be right?

Do they?

When you move one slider, and send "1 ", what is the Arduino going to see?
When you then move the second slider, and send "100 1 ", what is the Arduino going to see?

If you set the initial values of valR, valG, and valB to "0", what do you send when the first slider moved? Is that more like what the Arduino is expecting?

is it possible that the sliders values are being changed and sent too fast for the arduino to keep track of or does the serial buffer take care of that?

Yes, it is possible. That's up to you to control. But, you need to deal with the issue of sending crap first.

okay I understand what you were getting at now... so i assume the funky lighting was because when two of the slider values were declared but not initialized it was throwing off the alignment somewhat between the string being sent to the arduino and Serial.parseInt writing it?

i initialised the variables to 0 and it persisted so i then (roughly) implimented the easiest delay method i could find just before each slider calls the serial write function and with a delay of 2000ms it works(although still buggy at times) and fails at lower delays

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

using System.IO.Ports;

namespace serial_send_test_2
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        string valR = "0";
        string valG = "0";
        string valB = "0";

        private SerialPort serialPort1;

        public MainWindow()
        {
            InitializeComponent();
            serialPort1 = new SerialPort("COM6", 115200, Parity.None, 8, StopBits.One);
            serialPort1.Open();
        }


        //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        private async void Slider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            var slider = sender as Slider;
            double value = slider.Value;
            valR = value.ToString();
            await Task.Delay(500);
            serialTransmit();
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            serialPort1.WriteLine("255 ");
        }

        private void Button_Click_1(object sender, RoutedEventArgs e)
        {
            serialPort1.WriteLine("0 ");
        }
        //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        private async void Slider_ValueChanged_1(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            var slider = sender as Slider;
            double value = slider.Value;
            valG = value.ToString();
            await Task.Delay(500);
            serialTransmit();
        }

        private void Button_Click_3(object sender, RoutedEventArgs e)
        {
            serialPort1.WriteLine("255 ");
        }

        private void Button_Click_2(object sender, RoutedEventArgs e)
        {
            serialPort1.WriteLine("0 ");
        }

        //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        public async void Slider_ValueChanged_2(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            var slider = sender as Slider;
            double value = slider.Value;
            valB = value.ToString();
            await Task.Delay(500);
            serialTransmit();
        }

        private void Button_Click_5(object sender, RoutedEventArgs e)
        {
            serialPort1.WriteLine("255 ");
        }

        private void Button_Click_4(object sender, RoutedEventArgs e)
        {
            serialPort1.WriteLine("0 ");
        }
        //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        public void serialTransmit()
        {
            serialPort1.WriteLine(" " + valR + " " + valG + " " + valB + " ");
            this.Title = valR + " " + valG + " " + valB;
            Console.WriteLine("[{0}] [{1}] [{2}]", valR, valG, valB);
        }



        private void MainWindow_Closing()
        {
            serialPort1.Close();
            MessageBox.Show("Serial Port Closed");
        }
    }
}

That said, is there any way to go about using an address based configuration instead? for example if i were to send a value from the red slider then i could send something like:

 serialPort1.WriteLine("R");
 serialPort1.WriteLine(valR);

and have the arduino identify it as the desired pin to write the value to? i only ask because my current method seems problematic and restrictive if i were to expand on it. ive tried it like that but im assuming the fact that any character is still just a number on the ascii table makes it harder to not have address info and pin values misread

PS i apologize if im jumping ahead of things

oh ive noticed that the lighting goes glitchy when im changing slider values while its being written and sent. so as long as whatever slider im moving is moving(saving/sending values) during that delay however long it may be, it prints just fine(or reasonably so). but i dont know what that means though...

so i assume the funky lighting was because when two of the slider values were declared but not initialized it was throwing off the alignment somewhat between the string being sent to the arduino and Serial.parseInt writing it?

Exactly. You told the Arduino to expect three values separated by spaces. You only send 1 or 2, so instead of r g b, it got r r r and used it as r g b, or it got r g r g and used that as r g b.

i initialised the variables to 0 and it persisted

Hmmm. You need to have the Arduino echo what it gets, and have the C# application read that reply.

That said, is there any way to go about using an address based configuration instead? for example if i were to send a value from the red slider then i could send something like

Yes. That is a better approach. You'd need to change the Arduino code some.

I went and echoed the values back inside the arduino sketch and tried it with the arduino serial terminal and after sending a couple of RGB sets the returned values goes wrong so i take it its pretty safe to assume that its my method of using a single string and having Serial.parseInt() manage it is pretty unreliable and a new (address based) approach is due lol...i didnt have C# print the values back because thats out of my expertise level at the moment im new at C# and the only thing that got me this far is its similarity to C++ in the arduino IDE.

ive been thinking about the addressing approach for a couple of days now but i dont know how to go about implimenting it...can you please give me some direction into the method? i cant just do use an if statment with the condition being serial.read() = R because it would read R as the number 82 which will give a false positive if say the green slider sends a value of 82.