Освой Arduino играючи
/* Моя кошка замечательно разбирается в программировании. Стоит мне объяснить проблему ей - и все становится ясно. */
John Robbins, Debugging Applications, Microsoft Press, 2000
Visual Studio позволяет быстро и удобно писать программы, которые могут общаться с скетчами Arduino через последовательный порт.
Создайте консольное приложение и напишите код. За общение с последовательным портом отвечает пространство имён System.IO.Ports.
using System;
using System.IO.Ports;
using System.Threading;
namespace ConsoleApp1
{
class Program
{
static SerialPort serialPort;
static void Main(string[] args)
{
serialPort = new SerialPort();
serialPort.PortName = "COM4";
serialPort.BaudRate = 9600;
serialPort.Open();
while (true)
{
string msg = serialPort.ReadExisting();
Console.WriteLine(msg);
Thread.Sleep(200);
}
}
}
}
В приложении явно прописан номер порта, измените его в случае необходимости. В цикле while ждём поступление данных от Arduino.
Напишем скетч.
void setup() {
Serial.begin(9600);
}
void loop() {
Serial.print('1');
delay(200);
}
Прошиваем плату. Она начинает посылать единицы в порт. Запускаем консольное приложение. В окне консоли должны отобразиться принятые единицы. Базовый пример показывает, как просто взаимодействуют приложения на C# с Arduino.
Напишем приложение со свистелками и перделками, т.е. GUI-приложение. Создадим новый проект Desktop-типа. Добавим на форму кнопки, выпадающий список. На панели инструментов найдите элемент управления SerialPort и добавьте его на рабочую панель. Все настройки оставляем без изменений. Кстати, можно было получить доступ к SerialPort программным путём, но я решил показать простой привычный способ.
Файл Form1.Designers.cs получился следующим. Первая кнопка получает доступные порты и добавляет их в выпадающий список. Вторая кнопка соединяется по указанному порту. Третья и четвёртая кнопки посылают символы '1' и '0' соответственно, чтобы включить или выключить светодиод.
namespace DesktopApp1
{
partial class Form1
{
///
/// Required designer variable.
///
private System.ComponentModel.IContainer components = null;
///
/// Clean up any resources being used.
///
/// true if managed resources should be disposed; otherwise, false.
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
///
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
///
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.arduinoButton = new System.Windows.Forms.Button();
this.serialPort = new System.IO.Ports.SerialPort(this.components);
this.comboBox = new System.Windows.Forms.ComboBox();
this.connectButton = new System.Windows.Forms.Button();
this.turnOnButton = new System.Windows.Forms.Button();
this.turnOffButton = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// arduinoButton
//
this.arduinoButton.Location = new System.Drawing.Point(81, 35);
this.arduinoButton.Name = "arduinoButton";
this.arduinoButton.Size = new System.Drawing.Size(121, 23);
this.arduinoButton.TabIndex = 0;
this.arduinoButton.Text = "Get COM-port";
this.arduinoButton.UseVisualStyleBackColor = true;
this.arduinoButton.Click += new System.EventHandler(this.arduinoButton_Click);
//
// comboBox
//
this.comboBox.FormattingEnabled = true;
this.comboBox.Location = new System.Drawing.Point(81, 64);
this.comboBox.Name = "comboBox";
this.comboBox.Size = new System.Drawing.Size(121, 21);
this.comboBox.TabIndex = 4;
//
// connectButton
//
this.connectButton.Location = new System.Drawing.Point(81, 91);
this.connectButton.Name = "connectButton";
this.connectButton.Size = new System.Drawing.Size(121, 23);
this.connectButton.TabIndex = 5;
this.connectButton.Text = "Connect";
this.connectButton.UseVisualStyleBackColor = true;
this.connectButton.Click += new System.EventHandler(this.connectButton_Click);
//
// turnOnButton
//
this.turnOnButton.Location = new System.Drawing.Point(104, 178);
this.turnOnButton.Name = "turnOnButton";
this.turnOnButton.Size = new System.Drawing.Size(75, 23);
this.turnOnButton.TabIndex = 6;
this.turnOnButton.Text = "On";
this.turnOnButton.UseVisualStyleBackColor = true;
this.turnOnButton.Click += new System.EventHandler(this.button3_Click);
//
// turnOffButton
//
this.turnOffButton.Location = new System.Drawing.Point(104, 219);
this.turnOffButton.Name = "turnOffButton";
this.turnOffButton.Size = new System.Drawing.Size(75, 23);
this.turnOffButton.TabIndex = 7;
this.turnOffButton.Text = "Off";
this.turnOffButton.UseVisualStyleBackColor = true;
this.turnOffButton.Click += new System.EventHandler(this.button4_Click);
//
// Form1
//
this.ClientSize = new System.Drawing.Size(284, 261);
this.Controls.Add(this.turnOffButton);
this.Controls.Add(this.turnOnButton);
this.Controls.Add(this.connectButton);
this.Controls.Add(this.comboBox);
this.Controls.Add(this.arduinoButton);
this.Name = "Form1";
this.Load += new System.EventHandler(this.Form1_Load_1);
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.Button arduinoButton;
private System.IO.Ports.SerialPort serialPort;
private System.Windows.Forms.ComboBox comboBox;
private System.Windows.Forms.Button connectButton;
private System.Windows.Forms.Button turnOnButton;
private System.Windows.Forms.Button turnOffButton;
}
}
Сам код для коммуникации.
using System;
using System.Windows.Forms;
using System.IO.Ports;
// This is the code for your desktop app.
// Press Ctrl+F5 (or go to Debug > Start Without Debugging) to run your app.
namespace DesktopApp1
{
public partial class Form1 : Form
{
bool isConnected = false;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void arduinoButton_Click(object sender, EventArgs e)
{
comboBox.Items.Clear();
// Получаем список COM портов доступных в системе
string[] portnames = SerialPort.GetPortNames();
// Проверяем есть ли доступные
if (portnames.Length == 0)
{
MessageBox.Show("COM PORT not found");
}
foreach (string portName in portnames)
{
//добавляем доступные COM порты в список
comboBox.Items.Add(portName);
Console.WriteLine(portnames.Length);
if(portnames[0] != null)
{
comboBox.SelectedItem = portnames[0];
}
}
}
private void connectToArduino()
{
isConnected = true;
string selectedPort = comboBox.GetItemText(comboBox.SelectedItem);
serialPort.PortName = selectedPort;
serialPort.Open();
connectButton.Text = "Disconnect";
}
private void disconnectFromArduino()
{
isConnected = false;
serialPort.Close();
connectButton.Text = "Connect";
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
// При закрытии программы, закрываем порт
if (serialPort.IsOpen) serialPort.Close();
}
private void button3_Click(object sender, EventArgs e)
{
if(isConnected)
{
serialPort.Write("1");
}
}
private void button4_Click(object sender, EventArgs e)
{
serialPort.Write("0");
}
private void connectButton_Click(object sender, EventArgs e)
{
if (!isConnected)
{
connectToArduino();
}
else
{
disconnectFromArduino();
}
}
private void Form1_Load_1(object sender, EventArgs e)
{
}
}
}
Скетч для приёма сообщений.
char commandValue; // данные, поступаемые с последовательного порта
int ledPin = 13; // встроенный светодиод
void setup() {
pinMode(ledPin, OUTPUT); // режим на вывод данных
Serial.begin(9600);
}
void loop() {
if (Serial.available()) {
commandValue = Serial.read();
}
if (commandValue == '1') {
digitalWrite(ledPin, HIGH); // включаем светодиод
}
else {
digitalWrite(ledPin, LOW); // в противном случае выключаем
}
delay(10); // задержка перед следующим чтением данных
}
Запускаем приложение на C#, соединяется с платой и посылаем либо "1" (третья кнопка), либо "0" (четвёртая кнопка). В зависимости от нажатой кнопки на плате светодиод будет загораться или гаснуть.