简体   繁体   中英

Using Windows Form as a serial communicator to Arduino Uno

I'm new to the Arduino and serial communication, and I haven't coded in a while, but I'm trying to do what I think should be fairly simple, and have been having plenty of trouble. What I'd like to do is to create a simple GUI on Windows Forms and control a Arduino. I keep seeming to run into different problems every new session.

What I've been trying to do is to create a simple GUI that can toggle an LED on and off, and then to use NumericUpDown to toggle it blinking. Previously, I could get the numericUpDown to toggle values but nothing happens, now if I try and toggle, it tells me the port is closed. I've been trying different port communication methods. Since the Form is saying my port is closed, I cannot test to see if what I've written works. Please ignore the commented code as I'm still trying different things.

When I try to call the blink function, it hasn't blinked properly inside a if statement compared to if I kept it in the loop. I'm not sure how and where to send the value from the Winform to the Arduino.

Is Winform much different than using serial monitor commands?

EDIT1: I stepped away from my computer and now when I run the Windows Form, it shows no errors but The program has exited with code 0 (0x0). I've had the timer and haven't really messed with it yet but it wasn't telling me this error earlier and was running the form fine.

My Arduino Code:

// Define Function Prototypes that use User Types below here or use a .h file

    int dorun;
    int Blinks;

    void setup() {
// initialize digital pin LED_BUILTIN as an output.
pinMode(LED_BUILTIN, OUTPUT);
Serial.begin(9600);
getBlinks();
    }

    // the loop function runs over and over again forever
    void loop()
    {


if (Serial.available() > 0)
    /*
{
    byte Blinktimes = Serial.readBytes[];

}
*/
{
    String serialInput = Serial.readString();
    //Toggle LED
    if (serialInput == "On")    
        {
            digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN)); //I have this just to see that the LED is staying on and off, and will need to change things.
             for (int x = 1; x = Blinks; x++)
                {
                        blink();
                }
        }
    else
        {
            digitalWrite(LED_BUILTIN, LOW);   // turn the LED on (LOW is the voltage level)

        }
    Serial.flush();                         //Clear Serial
}
/*
digitalWrite(LED_BUILTIN, HIGH);
if ((Serial.available()))
{
    int dorun = Serial.read();
    if (dorun = 1)
    {
        blink();
    }
    else
    {
        digitalWrite(LED_BUILTIN, LOW);
    }
}
*/



/*turnon();
if (dorun == 1)
{
    blink();
}
else
{
    digitalWrite(LED_BUILTIN, LOW);
}
*/

    }
    void getBlinks()
    {
        byte message[3];
        if (Serial.available())        
        {
            Serial.readBytes(message, 3);
            Blinks = message[3];
        }
    }

    void blink()
    {
        digitalWrite(LED_BUILTIN, HIGH);   // turn the LED on (HIGH is the 
        voltage level)
        delay(250);                       // wait for a second
        digitalWrite(LED_BUILTIN, LOW);  //!digitalRead(LED_BUILTIN);    // turn the LED off by making the voltage LOW
        delay(1000);
    }

    void turnon()
    {
        if (Serial.available()> 0)
        {
            String run = Serial.readString();
            if (run == "Run")
            {
                dorun == 1;
            }
            if (run == "Off")
            {
                dorun == 0;
            }
        }
    }                

My Windows Form Code

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


    namespace WindowsFormsApp9
    {

        public partial class Form1 : Form
        {
            SerialPort serial;          // create serial port
                                        /*
    * public class Port
    {
    public string Name { get; set; }
    public int Value { get; set; }
    public Port(string n, int i)
    {
        Name = n;
        Value = i;
    }
    }
                                    */
            SerialPort port;
            string[] availablePorts = SerialPort.GetPortNames();
            public Form1()
            {
                InitializeComponent();
            }
        private void button1_Click(object sender, EventArgs e)
            {
        port = new SerialPort("COM3", 9600, Parity.None, 8, StopBits.One);
        port.Open();
        port.Write("On");
        port.Close();

    }
private void button2_Click(object sender, EventArgs e)
    {
        port = new SerialPort("COM3", 9600, Parity.None, 8, StopBits.One);
        port.Open();
        port.Write("Off");
        port.Close();

    }
private void numericUpDown1_ValueChanged(object sender, EventArgs e)
    {
        UpdateBlink();
    }
void UpdateBlink()
    {
        port = new SerialPort("COM3", 9600, Parity.None, 8, StopBits.One);
        port.Open();
        const byte messageType = 2;
        byte Blinkcount = (byte)numericUpDown1.Value;
        byte[] serialBlink = { messageType, Blinkcount };
        serialPort1.Write(serialBlink, 0, serialBlink.Length);
        port.Close();

    }





    private void timer1_Tick(object sender, EventArgs e)
    {

    }

    private void Form1_Load(object sender, EventArgs e)
    {

    }

    private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
    {

    }

I've been checking out these links:

Click here How I toggle the LED

Click here How to return an int since NumericUpDown returns a decimal Click [here] ( https://www.instructables.com/id/Arduino-Visual-Studio-Serial-Communication/ ) Arduino Visual Studio Serial communication timer things Click [here] ( https://www.instructables.com/id/Communication-From-a-WinForms-to-a-TinyDuino/ ) instructions about Winforms to TinyDuino, They should use similar commands as the Arduino right?


So I decided to do a slight overhaul. Instead of trying to deal with sending multiple different types of inputs(String and int) I have decided to just change everything into a byte array and then send it all at once.

Regarding 1. I was really just wondering if it'd be alright to create a function to return a value rather than just building the code in a void function. So I tried it and it worked, hence the change. From what I understood and saw that your protected override bool ProcessCmdKey, basically you wanted to see if the key was an arrow key. If it was return true. So what I did was basically if it's one of the selected colors, return a value corresponding to the color.

  1. I was just hoping you could either help me understand the Serial and COM port connection or if you had a link for more explanation. Earlier when I was trying to send a string(On/Off) and then send a numeric(byte/int) to set a number of blink times, I couldn't figure out if the COM port is kind of like a singular channel. If I'm sending a string from the Windows Form, could I send out a int/byte in the same channel? Now that everything is of one keyword (byte) I can just create a byte array and figure out the communication between the Windows Form and Arduino. I'm a little confused about the underlying Serial aspect. When I saw your code I started to think a little differently.

In your code, if I'm understanding it properly, it seems that MyVCOM is how to communicate back and forth, just like port.Write. I believe it's singular as it's basically like the old telephone line, if I'm on a call, and you call try to call me, your call is blocked since my line is already being used. So in your ConnReset, you want to make sure the COM's aren't open so you can set up communication. So your ConReset will clear the line if it's open already. What I'm confused about is the else part. If your port isn't open, open COM+PortNumber, so basically open the channel so you can communicate, but you declared port number to be 8, so shouldn't you just use:

MyVCOM.PortName = "COM8";

Where does the user select which COM? All of the communication is being done on COM8 isn't it? Or does is that part all part of a built in library? I believe all I need to do now is to send my byte array to my Arduino and then work on the Back End to take the data the Windows Form is sending.

        public int Colorselection(string label3, int color)     //Toggle a pin 
    {
        if (label3 == "Red")
        {
            color = 6;
        }
        else if (label3 == "Green")
        {
            color = 5;
        }
        else if (label3 == "Blue")
        {
            color = 3;
        }
        return color;
    }
    private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
    {
        String label4 = LEDColor.SelectedItem.ToString();               //Generate A string of selected Color
        int xled = Colorselection(label4, color);                       //Toggle the string into an int
        LEDLabel.Text = xled.ToString();                                //Generate a string from the int
    }

    private void Run_Click(object sender, EventArgs e)                  //Generate byte to send instead of sending strings and int/byte
    {
        byte RGBLED = Convert.ToByte(color);
        byte BlinkNum = Convert.ToByte(number1.Value);
        byte BlinkDur = Convert.ToByte(number2.Value);
        byte[] array2 = new byte[] { RGBLED, BlinkNum, BlinkDur };
        port = new SerialPort("COM3", 9600, Parity.None, 8, StopBits.One);
        /*
        port.Open();
        port.Write(array2, 0, 2);
        port.Close();
        */
    }

Your WinForms application assumes that your Arduino is connected to COM3. Do you know if that's actually the case, or is that sample code that you just copy and pasted? (Check the Windows Device Manager under COM ports to see what ports are available, then unplug/plug your device to see which port it's being mapped to)

Besides that, have you tried debugging your Arduino code on target to see what, if anything, is actually being received?

From the MS documentation, it's not clear how the SerialPort.Write command works exactly in terms of synchronization, so it may not be a great idea to close the port immediately after sending your command. Unfortunately, since I'm not in possession of an Arduino I can't test your code. But I did create a WinForms GUI to accomplish essentially the same task (and more that you probably don't need) several years ago that I've since posted to github ( https://github.com/mbhul/RoboCOM ). Let me know if that helps, otherwise please tell us more about your development environment.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM