【发布时间】:2018-09-04 21:47:31
【问题描述】:
我是 Arduino 和串行通信的新手,我有一段时间没有编码了,但我正在尝试做我认为应该相当简单的事情,并且遇到了很多麻烦。我想做的是在 Windows 窗体上创建一个简单的 GUI 并控制一个 Arduino。每次新会话时,我似乎都会遇到不同的问题。
我一直在尝试做的是创建一个简单的 GUI,可以打开和关闭 LED,然后使用 NumericUpDown 来切换它的闪烁。以前,我可以让 numericUpDown 切换值,但没有任何反应,现在如果我尝试切换,它会告诉我端口已关闭。我一直在尝试不同的端口通信方法。由于表单说我的端口已关闭,因此我无法测试我所写的内容是否有效。请忽略注释代码,因为我还在尝试不同的东西。
当我尝试调用 blink 函数时,与我将它保持在循环中相比,它在 if 语句中没有正确闪烁。我不确定如何以及在何处将值从 Winform 发送到 Arduino。
Winform 与使用串行监视器命令有很大不同吗?
EDIT1:我离开了我的计算机,现在当我运行 Windows 窗体时,它没有显示任何错误,但程序已退出,代码为 0 (0x0)。我有计时器,还没有真正搞砸它,但它没有早点告诉我这个错误,并且运行表单很好。
我的 Arduino 代码:
// 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;
}
}
}
我的 Windows 窗体代码
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)
{
}
我一直在查看这些链接:
点击here我如何切换LED
点击here如何返回int,因为NumericUpDown返回小数 点击[这里] (https://www.instructables.com/id/Arduino-Visual-Studio-Serial-Communication/) Arduino Visual Studio 串口通讯定时器的东西 点击[这里] (https://www.instructables.com/id/Communication-From-a-WinForms-to-a-TinyDuino/) Winforms to TinyDuino的说明,他们应该使用与Arduino类似的命令吧?
所以我决定做一个小修。我没有尝试处理发送多种不同类型的输入(String 和 int),而是决定将所有内容更改为字节数组,然后一次性发送。
关于 1. 我真的只是想知道是否可以创建一个函数来返回一个值,而不仅仅是在 void 函数中构建代码。所以我尝试了它并且它起作用了,因此发生了变化。据我了解并看到您的受保护覆盖 bool ProcessCmdKey,基本上您想查看该键是否是箭头键。如果是返回真。所以我所做的基本上是如果它是选定的颜色之一,返回一个与颜色对应的值。
- 我只是希望您能帮助我了解串行和 COM 端口连接,或者如果您有更多解释的链接。早些时候,当我尝试发送一个字符串(开/关)然后发送一个数字(字节/整数)来设置闪烁次数时,我无法确定 COM 端口是否有点像单个通道。如果我从 Windows 窗体发送一个字符串,我可以在同一个通道中发送一个 int/byte 吗?现在一切都是一个关键字(字节),我可以创建一个字节数组并找出 Windows 窗体和 Arduino 之间的通信。我对底层的 Serial 方面有点困惑。当我看到你的代码时,我开始有一些不同的想法。
在你的代码中,如果我理解正确的话,似乎 MyVCOM 是如何来回通信的,就像 port.Write 一样。我相信它是单一的,因为它基本上就像旧的电话线,如果我正在通话,你打电话给我,你的电话被阻止,因为我的线路已经被使用。 因此,在您的 ConnReset 中,您要确保 COM 未打开,以便您可以设置通信。因此,如果它已经打开,您的 ConReset 将清除该行。我感到困惑的是其他部分。如果你的端口没有打开,打开COM+PortNumber,所以基本上打开通道可以通信,但是你声明的端口号是8,所以你不应该只使用:
MyVCOM.PortName = "COM8";
用户在哪里选择哪个 COM?所有的通信都是在 COM8 上完成的,不是吗?或者那部分是内置库的所有部分吗?我相信我现在需要做的就是将我的字节数组发送到我的 Arduino,然后在后端工作以获取 Windows 窗体正在发送的数据。
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();
*/
}
【问题讨论】:
标签: c# winforms arduino serial-communication