|
在本文中,我们将一个Arduino Pro Mini开发板连接到PC,并且使用C# Windows应用程序与其进行通信。
将硬件连接到PC是非常有利的,不仅是因为你可以发送命令以及监控状态,还可以实时调试代码。当你正在努力制作一个模块,想知道模块的响应以及跟踪你的状态机时,检查变量会特别有帮助。
关于Arduino Pro Mini和C# 首先,我想向大家描述一下我选择Arduino Pro Mini的原因。 在我看来,小尺寸是当今设计的一个优势。 如今,随着便携式物联网设备的日益普及,对小型化的需求变得越来越重要,而且Arduino Pro Mini开发板除了小,也没有其他特殊功能。
Arduino Pro Mini开发板针对小空间进行了优化(当您需要尽可能小的电路板时),但是当它用于构建项目时功能却十分强大。 另一个好处是它没有焊接插头,这会占用很多的垂直空间。 您可以通过将导线焊接到引脚来简单地访问所需的引脚。 由于其体积小,它没有内置USB组件,因此您需要为该功能使用其他的组件。 市场上有许多串行转USB转换器,但是,我个人更喜欢选择一个可以向我提供所有的握手引脚的转换器,而不仅仅只是Rx和Tx。
这就是为什么我设计了一个基于FT232R的简单接口板。 我使用了芯片上的所有的串行信号。 你可以在图1看到我从数据表中摘取的电路。
其次,我想解释一下为什么选择C#。 有众多的编程语言和许多使得Windows的可视化应用程序编程更简单的可视化程序。 每种编程语言都有各自的优势和缺点。 但是,对我来说,使用visual studio可以为我做很多工作。 它允许访问众多的预编译库和工具,帮助我们高效地构建我们的应用程序。 它还允许我们使用功能强大的C#语言进行编程。 所以在本文中我们使用C#,因为它很方便,并且我比较熟悉。
所需的硬件和软件 ● Arduino Pro Mini 5V ● FT232R USB转串口模块 ● 面包板 ● 导线,用于将插头连接到FT232R电路板以及将引脚3连接到LED ● Arduino IDE ● Visual Studio
设置 我使用我自己的FT232R电路板来编程以及与Arduino Pro Mini 5V开发板通信。 Arduino PM有的六个引脚用于编程,标记为“BLK”、“GND”、“VCC”、“RXI”、“TXO”和“GRN”,如图2所示。
在图3所示的用于编程的六个引脚中,第一个引脚BLK接地。 GND和VCC显然需要连接到FT232R电路板的VCC和GND。 这样,Arduino将由USB提供电源,不需要额外的电源。
我们应该考虑的事情是USB端口的电流限制。 如果我们的电路耗电超过500mA,我们应该增加一个外部电源。 RXI应连接到FT232的TX,TXO连接到FT232的RX,GRN连接到FT232的DTR,这将使得FT232可以在任何需要时复位开发板。
接线后,电路如图4所示。现在我们已经准备好对Arduino Pro Mini进行编程了。
上传代码草稿
出于测试的目的,我们将写一个简单的代码来读取串口的输入,并相应地设置引脚3的状态: - const int led = 3;
- int state=0;
- void setup()
- {
- Serial.begin(115200); //Starts the serial connection with 115200 Buad Rate
- pinMode(led, OUTPUT); //Sets led pin as an output
- Serial.write("ALL ABOUT CIRCUITS!");//Send "ALL ABOUT CIRCUITS!" to the PC
- }
- void loop()
- {
- String data = Serial.readString();//Read the serial buffer as a string
- if(data.indexOf("ON")!=-1)//checks if it is "ON"
- {
- digitalWrite(led, HIGH); // Sets the led ON
- state=0;// Sets the state value to 0
- }
- else if(data.indexOf("OFF")!=-1)//checks if it is "OFF"
- {
- digitalWrite(led, LOW); //Sets the led OFF
- state=0;// Sets the state value to 1
- }
- else if(data.indexOf("STATE")!=-1)//checks if it is "STATE"
- {
- Serial.write("state=");//Sends the state
- Serial.println(state);
- }
- }
复制代码
我们需要做的是将开发板设置为Arduino Pro或Pro Mini(见图5),然后上传我们的代码草稿。
编写C#应用程序 编写C#应用程序时,我们在Visual Studio开发环境中创建一个简单的窗体。 接下来,从工具箱部分,我们需要拖放“串行端口”工具。 可以在工具的属性部分中配置所有设置。 将端口名称设置为FT232的端口名称。 并且将波特率设置为115200,握手设置为“无”。 我们还需要添加一个按钮来切换LED状态以及一个文本框来显示接收到的数据。 我们可以简单地从工具箱中添加这些。 设置应如图6所示。
做完视图之后,我们可以准备写一些代码。 首先,为了使用串行端口,我们需要打开它,然后我们可以写入或从串行缓冲区读取。 我们可以在代码中访问串行中断。 串行通信中的中断提供更好的响应,因为我们只有在数据可用时才处理数据。 C#串行端口也有一个事件,当数据到达缓冲区时将触发该事件。 我们可以通过转到属性部分中的事件选项卡并双击DataReceived(参见图7)来使用此事件。 Visual studio将自动创建该事件。
在发送或接收数据之前,我们需要打开串口: - private void Form1_Load(object sender, EventArgs e)
- {
- serialPort1.Open();
- }
复制代码
然后我们可以读取或写入数据。 代码如下所示: - public delegate void AddDataDelegate(String myString);// Delegate for richtextbox
- public AddDataDelegate myDelegate;// An instance of AddDataDelegate
- public delegate void AddDataDelegate_button(String myString);// Delegate for button
- public AddDataDelegate_button myDelegate_button;// An instance of AddDataDelegate_button
- bool status=false;// LED status
- public Form1()
- {
- InitializeComponent();
- }
- private void Form1_Load(object sender, EventArgs e)
- {
- serialPort1.Open();//Opening the serial port
- this.myDelegate = new AddDataDelegate(AddDataMethod);//Assigning "the function that changes richtextbox text" to the delegate
- this.myDelegate_button = new AddDataDelegate_button(AddDataMethod_button);//Assigning "the function that changes button text" to the delegate
- serialPort1.WriteLine("STATE");
-
- }
- public void AddDataMethod_button(String myString)
- {
- button1.Text = myString;//changes button text
- }
- public void AddDataMethod(String myString)
- {
- richTextBox1.Text = myString + Environment.NewLine;//changes richtextbox text
- }
- private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
- {
- string s = serialPort1.ReadExisting();//reads the serialport buffer
- if (s.Contains("state="))//checks if it is status
- {
- s=s.Trim();
- string new_s = s.Replace("state=", "");
- if (new_s.Contains("0"))
- {
- status = false;
- button1.Invoke(this.myDelegate_button, new Object[] { "ON" });//sets button text to on
- }
- else
- {
- status = true;
- button1.Invoke(this.myDelegate_button, new Object[] { "OFF" });//sets button text to off
- }
- }
- else
- {
- richTextBox1.Invoke(this.myDelegate, new Object[] { s });//adds the recieved bytes to the richtextbox
- }
- }
- private void button1_Click(object sender, EventArgs e)
- {
- if(button1.Text.Contains("ON"))
- {
- serialPort1.WriteLine("OFF");//sends off command when the previous state was on
- button1.Text = "OFF";
- status = false;
- }
- else
- {
- serialPort1.WriteLine("ON");//sends on command when the previous state was off
- button1.Text = "ON";
- status = true;
- }
- }
复制代码
代码说明 示例代码通过ASCII字符进行通信。 这种方法比较方便并且可以扩展。
在C#代码中,我们需要从Arduino Pro Mini读取引脚的状态,所以我们向Arduino开发板发送“STATE”命令。 Arduino将通过串口回答“state = 0”或“state = 1”来进行应答。 Arduino向我们发送状态后,我们将相应地更新按钮文本。
事件在与主表单线程分开的线程中运行,因此它们具有不同的速度。例如,在我们的示例中,当我们从串行端口接收到文本时,我们可能希望在文本框中显示它。 然而,在从一开始创建所有控制处理程序的主Windows线程控制器中可能有一些其他控制器未完成的任务,这些控制器可以是一个文本框或按钮;在这种条件下,如果我们从与主处理程序分开的另一个线程中调用一个文本框,程序将会崩溃,因为是多线程的情况。 文本框控制器可能同时会有两个不同的属性,因此我们应该等到它的工作完成。
这就是为什么我们不能从另一个线程更改文本框文本,如串口接收线程。 为了避免这种情况,我们可以使用Invoke方法。 每个控制器都有一个Invoke方法,使得我们能够从另一个线程更改其属性;Invoke方法可以从另一个线程执行某个委托。 代理像C ++中的指针,这意味着它们引用某个特定的方法并安全地执行它。 因此,首先,我们需要定义一个更改控制器属性的代理,在代码中命名为“myDelegate”,然后将其关联到Invoke方法。 从代码中可以看出,使用Invoke函数,我们可以进行线程安全调用。
其余的代码很简单。 只要用户按下按钮,我们只需将“ON”或“OFF”命令写入串口。
总结 在本文中,我们学习了如何编写一个与Arduino Pro Mini开发板交互的C#应用程序。 我们使用简单的ASCII命令/响应协议,该协议可以很容易地适用于各种各样的应用程序。
|