I'm getting an error everytime I try connecting to the COM5 in my ELEGOO UNO R3.
I try sending data using a C# Form Framework through a button that prints 1 into the serial port. Objective: The data is readed by an Arduino code that interpreates the data for later using it.
I try verifying by printing "one recieved" Problem: Either says the port is busy or straight up doesn't connect. Arduino code:
// VAR //
int ACT;
// SETUP //
void setup()
{
Serial.begin(9600);
Serial.println("Arduino Ready");
}
// PROGRAM //
void loop()
{
if(Serial.available() > 0)
{
ACT= Serial.parseInt();
switch(ACT)
{
case 1:
Serial.println("One recieved");
break;
case 2:
Serial.println("Two recieved");
break;
}
}
delay(50);
}
C# Form1.cs code:
using System;
using System.Windows.Forms;
using System.IO.Ports;
namespace gui2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
serialPort1.Open();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void uno_Click(object sender, EventArgs e)
{
serialPort1.Write("1");
}
private void dos_Click(object sender, EventArgs e)
{
serialPort1.Write("2");
}
}
}
I can run the arduino or the C# programs separately but when trying to have both so try to catch the sent information this error shows (Arduino opened first):
System.UnauthorizedAccessException: 'Se ha denegado el acceso al puerto 'COM5'.'
Or this (C# program opened first):
El Sketch usa 2090 bytes (6%) del espacio de almacenamiento de programa. El máximo es 32256 bytes.
Las variables Globales usan 228 bytes (11%) de la memoria dinámica, dejando 1820 bytes para las variables locales. El máximo es 2048 bytes.
avrdude: ser_open(): can't open device "\.\COM5": Acceso denegado.
you can only connect one Widows program to a serial port at a time, e.g. either the Arduino IDE serial monitor or the C# program
if the Arduino program is outputting information over serial the C# program should receive it and display it on a TextBox
the alternative is to use a second serial port to receive the data from the C# program using the first serial port for the IDE serial monitor IO
Like @horace already said, it looks like you're trying to open the same COM port with more than once.
To avoid this, if you close the C# program before uploading the sketch, the upload process should end without any errors.
Once you uploaded the code (close the serial monitor if you opened it) then open the C# program, and it'll send the command.
But your problem is you seem to need the messages from Arduino but you can't open Serial Monitor (e.g. to read "One received"...) while the C# program is running.
To check the program, add a LED to. let's say, pin 9 (connect the LED anode via a 220 Ohms resistor to pin 9 and cathode to GND) and use this code:
// VAR //
int ACT;
// SETUP //
void setup()
{
Serial.begin(9600);
pinMode(9, OUTPUT);
digitalWrite(9, HIGH); // turn leD on
}
// PROGRAM //
void loop()
{
if(Serial.available() > 0)
{
ACT= Serial.parseInt();
switch(ACT)
{
case 1:
digitalWrite(9, LOW);
break;
case 2:
digitalWrite(9, HIGH);
break;
}
}
delay(50);
}
If everything works correctly, you can turn the LED off with "1" button and on with "2" one, just as a visual confirmation of the whole process.
Another workaround could be adding a textbox to the C# program where any received character will be echoed to.
Lastly, you could even use SoftwareSerial library to add another "virtual" serial to Arduino, and use it to exchange data (commands or messages) using an USB-to-SerialTTL physical adapter.
Btw, any solution strictly depends on what you need to do with all this in the next future...
PS: I also suggest you to open the port from form Load event (and close it on unload), not on the constructor:
Thank you so much for the reply
I tried using the Serial Plotter before without the C# code running and seen the data was being readed when I typed "1" or "2".
The LED does turn on if I use the serial plotter.
However, when trying to press the buttons from the C# code there's the "RX" that flashes but the LED doesn't appear to change from the button presses.
Note: this RX flash would show before with my previous code but since I didn't understood it I assumed it was working properly, it might not? I'm not sure but here's the image of the connection and the current codes used. C# code:
using System;
using System.Windows.Forms;
using System.IO.Ports;
namespace gui2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
// serialPort1.Open();
}
private void Form1_Load(object sender, EventArgs e)
{
serialPort1.Open();
}
private void uno_Click(object sender, EventArgs e)
{
serialPort1.Write("1");
}
private void dos_Click(object sender, EventArgs e)
{
serialPort1.Write("2");
}
}
}
Arduino code:
// VAR //
int ACT;
// SETUP //
void setup()
{
Serial.begin(9600);
pinMode(9, OUTPUT);
digitalWrite(9, HIGH); // turn leD on
}
// PROGRAM //
void loop()
{
if(Serial.available() > 0)
{
ACT= Serial.parseInt();
switch(ACT)
{
case 1:
digitalWrite(9, LOW);
break;
case 2:
digitalWrite(9, HIGH);
break;
}
}
delay(50);
}
The first thing I'd do is to verify if the C# serial (the serialPort object I think you have on your form) has the same settings you have on Arduino, starting with speed (currently 9600 baud, but you can use any one even faster like 115200) and the data format (8N1, 8 data bits, no parity, 1 stop bit). Show us the parameters you used on your serial object.
Second thing I feel you need to know: when dealing with communication between programs you don't actually need to make it "human readable". I mean, if you want to send a command from one side to the other, use just single characters or, better, bytes. In this case this means you don't need a "Serial.parseInt()" because you don't send a string representing a value, you just send a single character. If you read the description of parseInt() function, you could notice it's a "blocking" statement, ending when the first non-digit is read, or after waiting for a (configurable) time-out value with no complete values returned.
And that's why it works if using Serial Monitor, because when you type the command (e.g. "1") and press "Enter" you are sending three characters: '1' '\r' '\n' ("1" followed by the line-terminating characters CD and LF), so parseInt() gets the "non-digit" character and returns the value 1.
Your C# program is sending just the command, without any other character:
serialPort1.Write("1");
So if you need to send just that command as a single character, read it as a single byte and compare it with the command characters:
...
// Configuration (pins, values...)
#define P_LED 9
// Global variables
byte cmd;
void setup()
{
Serial.begin(9600);
pinMode(P_LED, OUTPUT);
digitalWrite(P_LED, HIGH); // turn leD on
}
void loop()
{
if(Serial.available() > 0)
{
cmd= Serial.read();
switch(cmd)
{
case '1':
digitalWrite(P_LED, LOW);
break;
case '2':
digitalWrite(P_LED, HIGH);
break;
}
}
// Not really needed, anyway keep it just to "simulate" some other tasks...
delay(50);
}
A few more side notes (you can note them from the above code example):
Following conventional representation, always use full uppercase symbols for constants only, not for variables (where you can use any mix to make it readable, like "SensorValue")
Always indent "case" content (in doublt, use CtrlT IDE command, it'll do it for you)
Always use symbols/constants to define the pins you're using, and put them at the top of the code to make this "configuration" easily available, avoiding searching along the code to change a pin number.
Thank you so much! ,
With the current solution you provided I was able to get the basic understanding and a solution for what I'm trying to make. From here I will be able to further customize it if needed, I really appreciate the patience
I'll post the settings (that I didnt change) of my C# project if you we're curious:
I'm happy to read that you solved the problem!
If you use the sample code I posted you, you are able to define a large number of commands, because if you just stick with single ASCII characters to be sent, you have at least 62 possible commands (all the 26 letters uppercase and 26 lowercase, plus 10 digits), probably enough for many uses.
Please note it can be extended in the future to include more structured commands (e.g. "turn LED 10 on") and/or variable instructions lengths, so if and when you'll need that, ask me (us) again here, describing your needs and we'll try and give you hints or proper corrections, and maybe help you defining a specific "protocol" you could use.