Arduino relay controlling with C# - not working

Hi, I have to code an Arduino Relay controling software in C# for my final exam.
I have an Arduino Uno Wifi Rev2, a 4 relay shield (original Arduino).

Based on some codes that can be found on the Internet, I wrote this C# code (see Arduino code below):

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

namespace serial_port_teszt
{
    public partial class Form1 : Form
    {
        SerialPort port;

        public Form1()
        {
            InitializeComponent();
            try
            {
                if (port == null)
                {
                    port = new SerialPort("COM3", 9600);
                    port.Open();
                }
            }
            catch (Exception)
            {

                throw;
            }
            
        }

        private void r1_be_Click(object sender, EventArgs e)
        {
            PortWrite("a");
        }

        private void r1_ki_Click(object sender, EventArgs e)
        {
            PortWrite("b");
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (port != null && port.IsOpen)
            {
                port.Close();
            }
        }
        private void PortWrite(string m)
        {
            port.Write(m);
        }
    }
}

And this Arduino code:

String b;
int rele = 4;
int releAllapot = 0;

void setup() {
  // put your setup code here, to run once:
  pinMode(rele, OUTPUT);
  Serial.begin(9600);
}

void loop() {
  // put your main code here, to run repeatedly:
  if (Serial.available() > 0) {
    b = String(Serial.read());
    Serial.println(b);

    if (b == "a") {
      releAllapot = 1;
    }

    if (b == "b") {
      releAllapot = 0;
    }
    digitalWrite(rele, releAllapot);
  }
}

In the Arduino code I tried to use char instead of string, but nothing changed.
In the Arduino IDE I can control the relay with the serial monitor, but with the C# code I can't, and I don't understand why this codes aren't working, neither ChatGPT. :smiley:
The BAUD and the port (COM4) are right and the same in both code.

So I hope some of you can help me, because I have to present this in two weeks.

Thanks!

Kodonci from Hungary

What does your serial print show?

Unfortunatelly, I can't use the Arduino IDE and the C# software at the same time, because if I use the IDE, the Visual Stuido can't use the same port...

When I only use the IDE and then I print the data to the serial port, everything works fine - obviously.

Do you have another Arduino that the first one can talk to over software serial for debugging?

It is not much work to add a 2 or a 4 line LCD display to your Arduino and print the debug messages to it.

Unfortunatelly, the Uno Wifi Rev2 the only Arduino board I have.
I don't have any LCD display or other equipments like that. And if it's not necessary, I don't want to buy any just for this. I don't have enough time to experiment with this...

With your system design, how did you intend to debug your software?

Just to understand this,

Does the Arduino code you posted work correctly?

I thought that the IDE serial monitor and the C# code will able to run at the same time, and with (for example) Serial.println() I can monitor the datas, but don't.

Since I wrote the post I kept testing different codes, and I found one that give me a little step forward: the RX LED is now blinking when I click the button in the C# software, so now the only issue that I don't know why the other part of the code doesn't work.

C# code:

using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace konzol_teszt
{
    internal class Program
    {
        static void Main(string[] args)
        {
            string portName = "COM3";
            int baudRate = 9600;

            SerialPort arduinoPort = new SerialPort(portName, baudRate);

            try
            {
                arduinoPort.Open();

                Console.WriteLine("Soros port nyitva. A és B karaktereket küldhet.");

                while (true)
                {
                    Console.Write("Karakter küldése (A vagy B): ");
                    char input = Char.ToUpper(Console.ReadKey().KeyChar);

                    if (input == 'A' || input == 'B')
                    {
                        arduinoPort.Write(new byte[] { (byte)input }, 0, 1);
                        Console.WriteLine("\nKarakter elküldve: " + input);
                    }
                    else
                    {
                        Console.WriteLine("\nCsak A vagy B karaktereket fogadunk el.");
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Hiba történt: " + ex.Message);
            }
            finally
            {
                arduinoPort.Close();
            }
        }
    }
}

Arduino code:

char receivedChar;

void setup() {
  Serial.begin(9600);
  pinMode(LED_BUILTIN, OUTPUT);
  receivedChar = ' ';
}

void loop() {
  if (Serial.available() > 0) {
    receivedChar = Serial.read();
    Serial.println(receivedChar);
    
    if (receivedChar == 'A') {
      digitalWrite(LED_BUILTIN, HIGH);  // LED bekapcsolása
    }
    if (receivedChar == 'B') {
      digitalWrite(LED_BUILTIN, LOW);  // LED kikapcsolása
    }
  }
}

Yeah I tested the original one with IDE's serial monitor, with that were no problem.
With the newer one I may have an issue: after the letter B I get one cube character.
I think I end this for today because I'm kinda tired and I don't want to make any mistake by skip an obvious step in the coding or testing process. :sweat_smile:

Consider changing the C# code to display any message that is not an expected reply from the Arduino and change the Arduino code to write any debug messages to the C# on the PC. Then you can print debug messages and read them on the same PC.

Thanks for the idea, I tried it, and no response arriving from the Arduino to the C# code. The RX LED still blink for a moment when I sending an A or B letter from the console app.

I'm tried to add delay to each code, but nothing has changed. Maybe the C# code send the letter in wrong variable type?

Post the code you used for this.

For that matter, post the code each time you make a change and want some help with it - it's really hard to debug by guessing exactly what changed on each end.

Given that you see square symbols instead of readable chars, you might try echoing back the ascii value of each char the Arduino gets.

Have you tried changing the C# code to write to a text file instead of the serial port? Then you can test the code and check what has been written to the file after.

In C#:

Can you cast a character (such as 'a') to an integer and then print it to your monitor?
That would reveil which character set it is using...

Thanks for the ideas, I tried all of them, the results:

Writing the letters I send (and get) to a txt: everything is all right, it's writing A and B letters to the .txt file. I tried to write out the letters that sent back from the Arduino, but Arduino doesn't send anything back.

Character to integer: The A is 65, the B is 66. As I can see, this is the decimal value of the letters in the ASCII table.

This is the codes I use right now, and I won't change until any new suggestions. I hope this is useful information to get this story to the end and solve it finally - I'm out of ideas for now... :confused:

The C# code:

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

namespace konzol_teszt
{
    internal class Program
    {
        private static string kuldesiLogFileName = "kuldesi.log"; // A küldési log fájl neve
        private static string erkezesiLogFileName = "erkezesi.log"; // Az érkezési log fájl neve

        static void Main(string[] args)
        {
            string portName = "COM3";
            int baudRate = 9600;

            SerialPort arduinoPort = new SerialPort(portName, baudRate);

            try
            {
                arduinoPort.Open();
                arduinoPort.DataReceived += ArduinoDataReceived; // Hozzáadjuk a kezelőt az adat fogadásához

                Console.WriteLine("Soros port nyitva. A és B karaktereket küldhet.");

                while (true)
                {
                    Console.Write("Karakter küldése (A vagy B): ");
                    char input = Char.ToUpper(Console.ReadKey().KeyChar);

                    if (input == 'A' || input == 'B')
                    {
                        arduinoPort.Write(input.ToString()); // Karakterként küldjük az adatot
                        Console.WriteLine("\nKarakter elküldve: " + input);

                        // Cast the character to an integer and print it
                        int charAsInt = (int)input;
                        Console.WriteLine("Karakter értéke mint integer: " + charAsInt);

                        // Mentjük a küldött adatokat a küldési log fájlba
                        using (StreamWriter writer = File.AppendText(kuldesiLogFileName))
                        {
                            writer.WriteLine(DateTime.Now + ": " + input);
                        }

                        // Várakozás egy kis időt, hogy a válasz elküldődjön
                        System.Threading.Thread.Sleep(100); // Várakozás 100 milliszekundumig
                    }
                    else
                    {
                        Console.WriteLine("\nCsak A vagy B karaktereket fogadunk el.");
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Hiba történt: " + ex.Message);
            }
            finally
            {
                arduinoPort.Close();
            }
        }

        private static void ArduinoDataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            SerialPort port = (SerialPort)sender;
            string data = port.ReadExisting(); // Olvassuk ki az érkező adatokat
            Console.WriteLine("\nArduino válasza: " + data);

            // Mentjük az érkező adatokat az érkezési log fájlba
            using (StreamWriter writer = File.AppendText(erkezesiLogFileName))
            {
                writer.WriteLine(DateTime.Now + ": " + data);
            }
        }
    }
}

The Arduino code:

char receivedChar;

void setup() {
  Serial.begin(9600);
  pinMode(LED_BUILTIN, OUTPUT);
  receivedChar = ' ';
}

void loop() {
  if (Serial.available() > 0) {
    receivedChar = Serial.read();
    Serial.println(receivedChar);
    
    if (receivedChar == 'A') {
      digitalWrite(LED_BUILTIN, HIGH);
      Serial.write(receivedChar);
    }
    if (receivedChar == 'B') {
      digitalWrite(LED_BUILTIN, LOW);
      Serial.write(receivedChar);
    }
    delay(100);
  }
}

I tried with an other code to send the ASCII numbers from C# to Arduino, this doesn't worked too. There's no working solution with C# and Uno Wifi Rev2 at my current knowlege. I don't understand why the codes from the internet doesn't work, and I don't understand either why my codes doesn't work. I think there's a problem with the Arduino board, no other options left as I see.

Does your Arduino code work if you use the IDE to send A and B manually?

@kodonci here is a slightly modified version that displays info in the console app, do NOT use the serial monitor.

C#

using System.IO;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Linq;
using System.Text;
using System.IO.Ports;

namespace konzol_teszt
{
    internal class Program
    {

        static void Main(string[] args)
        {
            string portName = "COM3";
            int baudRate = 9600;

            SerialPort arduinoPort = new SerialPort(portName, baudRate);

            try
            {
                arduinoPort.Open();
                arduinoPort.DataReceived += ArduinoDataReceived; // Hozzáadjuk a kezelőt az adat fogadásához
                arduinoPort.ReadExisting();

                Console.WriteLine("Soros port nyitva. A és B karaktereket küldhet.");

                while (true)
                {
                    Console.Write("Karakter küldése (A vagy B): ");
                    char input = Char.ToUpper(Console.ReadKey().KeyChar);

                    if (input == 'A' || input == 'B')
                    {
                        arduinoPort.Write(input.ToString()); // Karakterként küldjük az adatot
                        Console.WriteLine("\nKarakter elküldve: " + input);

                        // Cast the character to an integer and print it
                        int charAsInt = (int)input;
                        Console.WriteLine("Karakter értéke mint integer: " + charAsInt);
                       
                    }
                    else
                    {
                        Console.WriteLine("\nCsak A vagy B karaktereket fogadunk el.");
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Hiba történt: " + ex.Message);
            }
            finally
            {
                arduinoPort.Close();
            }
        }

        private static void ArduinoDataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            SerialPort port = (SerialPort)sender;
            string data = port.ReadLine(); // Olvassuk ki az érkező adatokat
           
            Console.WriteLine("\nArduino válasza: " + Convert.ToString(data) + "\n\n\n");

        }
    }
}

Arduino

char receivedChar;

void setup() {
  Serial.begin(9600);
  pinMode(LED_BUILTIN, OUTPUT);
  receivedChar = ' ';
}

void loop() {
  if (Serial.available() > 0) {
    receivedChar = Serial.read();
    Serial.println(receivedChar);
    
    if (receivedChar == 'A') {
      digitalWrite(LED_BUILTIN, HIGH);
    }
    if (receivedChar == 'B') {
      digitalWrite(LED_BUILTIN, LOW);
    }
    delay(100);
  }
}

That's probably the least likely of the possibilities, especially if you can upload code to the board.

Did you try @wildbill's idea of forgetting the C# code and manually entering characters from the Serial Monitor?