0. Начало
1. Цифровой ввод — кнопка
2. Аналоговый вывод — Fading
3. Аналоговый ввод – потенциометр
4. Аналоговый ввод – осциллограф
5. Генерация звука – пьезоизлучатель.
6. Фоторезистор
7. Сенсор на светодиоде
8. Общение с Arduino — программирование работы с COM-портом.
Правильным местом с которого стоит начать своё изучение написание программ для взаимодействия с Arduino/CraftDuino является официальный сайт:
http://www.arduino.cc/playground/Main/InterfacingWithSoftware
— там приведены примеры работы с последовательным портом из разных языков и сред программирования.
Ниже рассмотрим примеры работы с Arduino на С, С++, С#, PERL и Python.
Arduino + C
http://todbot.com/blog/2006/12/06/arduino-serial-c-code-to-talk-to-arduino/
приводится в пример консольная POSIX C – программа, исходник которой можно скачать здесь
— программа может принимать и передавать данные на плату Arduino/Freeduino
Использование:
laptop% gcc -o arduino-serial arduino-serial.c laptop% ./arduino-serial Usage: arduino-serial -p [OPTIONS] Options: -h, --help Print this help message -p, --port=serialport Serial port Arduino is on -b, --baud=baudrate Baudrate (bps) of Arduino -s, --send=data Send data to Arduino -r, --receive Receive data from Arduino & print it out -n --num=num Send a number as a single byte -d --delay=millis Delay for specified milliseconds
Примечание:
Порядок параметров имеет значение! ‘-b’ нужно устанавливать перед указыванием порта ‘-p’.
Можно устанавливать несколько флагов для выполнения последовательности действий:
‘-d 2000 -s hello -d 100 -r’
Означает: «ждать 2 секунды, отправить ‘hello’, ждать 100msec, считать ответ»
Примеры использования:
1. Отправить в Arduino один ASCII-символ «6»
laptop% ./arduino-serial -b 9600 -p /dev/tty.usbserial -s 6
2. Отправить в Arduino строчку “furby”
laptop% ./arduino-serial -b 9600 -p /dev/cu.usbserial -s furby
3. Получить данные от Arduino
laptop% ./arduino-serial -b 9600 -p /dev/cu.usbserial -r read: 15 Hello world!
Данный пример показывает вывод данных от скетча serial_hello_world.pde
из проекта Spooky Arduino (Зловещий Ардуино).
Отправить ASCII-строчку “get” в Arduino и получить результат:
laptop% ./arduino-serial -b 9600 -p /dev/cu.usbserial -s get -r read: d=0
И немножко о внутреннем устройстве программы:
Там всего три интересных функции, которые показывают пример работы с последовательным портом на C:
int serialport_init(const char* serialport, int baud)
— получает имя порта («/dev/tty.usbserial»,»COM1″) и скорость работы, а возвращает файловый дескриптор открытого порта.
int serialport_write(int fd, const char* str)
– отправляет в порт (по файловому дескриптору) строчку данных
int serialport_read_until(int fd, char* buf, char until)
– считывает данные из последовательного порта в буфер, пока не встретит определённый символ (char until)
Arduino + C++ (using libSerial)
http://devlog.bigmonachus.org/2008/08/interfacing-arduino-with-c-and.html
Работа с последовательным портом с использованием библиотеки libSerial
libSerial работает в POSIX-системах (на Windows работать не будет)
подключение библиотеки:
#include < SerialStream.h > #include < iostream > #define PORT "/dev/ttyUSB0" // указывается порт, к которому подключена Arduino SerialStream ardu; using namespace std; using namespace LibSerial;
примеры работы:
void open()
{
ardu.Open(PORT);
/*The arduino must be setup to use the same baud rate*/
ardu.SetBaudRate(SerialStreamBuf::BAUD_9600);
ardu.SetCharSize(SerialStreamBuf::CHAR_SIZE_8);
}
int get(char out)
{
int res;
char str[SOME_BIG_SIZE];
ardu << out;
ardu >> str;
sscanf(str,"%d",&res);
return res;
}
Ссылки:
Serial Programming Guide for POSIX Operating Systems
Arduino + C++ (for windows)
http://www.arduino.cc/playground/Interfacing/CPPWindows
по ссылке можно найти пример класса для работы с последовательным портом в системах на базе Windows:
SerialClass.h (header)
#ifndef SERIALCLASS_H_INCLUDED
#define SERIALCLASS_H_INCLUDED
#define ARDUINO_WAIT_TIME 2000
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
class Serial
{
private:
// дескриптор COM-порта
HANDLE hSerial;
// статус соединения
bool connected;
// различная информация о соединении
COMSTAT status;
// последняя ошибка
DWORD errors;
public:
// инициализация с указанным COM-портом
Serial(char *portName);
// закрытие соединения
//NOTA: по каким-то причинам не удаётся переподключиться
// нужно перезапускать программу
~Serial();
// считываем данные в буфер – если nbChar больше, чем
// число доступных байт – возвращает только
// доступные данные
// возвращает -1 при ошибке
int ReadData(char *buffer, unsigned int nbChar);
// записывает данные из буфера в порт
// возвращает true при удаче
bool WriteData(char *buffer, unsigned int nbChar);
// возвращает статус соединения
bool IsConnected();
};
#endif // SERIALCLASS_H_INCLUDED
Serial.cpp (source code file)
#include "SerialClass.h"
Serial::Serial(char *portName)
{
// пока ещё не подключились
this->connected = false;
// пытаемся подключиться к порту посредством CreateFile
this->hSerial = CreateFile(portName,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
// проверяем – было ли соединение успешным
if(this->hSerial==INVALID_HANDLE_VALUE)
{
//если не было – выводим ошибку
if(GetLastError()==ERROR_FILE_NOT_FOUND){
// печатаем ошибку
printf("ERROR: Handle was not attached. Reason: %s not available.\n", portName);
}
else
{
printf("ERROR!!!");
}
}
else
{
// подключились – теперь устанавливаем параметры
DCB dcbSerialParams = {0};
// считываем текущие параметры
if (!GetCommState(this->hSerial, &dcbSerialParams))
{
// если невозможно – говорим о неудаче
printf("failed to get current serial parameters!");
}
else
{
// устанавливаем параметры для соединения с Arduino
dcbSerialParams.BaudRate=CBR_9600;
dcbSerialParams.ByteSize=8;
dcbSerialParams.StopBits=ONESTOPBIT;
dcbSerialParams.Parity=NOPARITY;
// применяем параметры
if(!SetCommState(hSerial, &dcbSerialParams))
{
printf("ALERT: Could not set Serial Port parameters");
}
else
{
// отлично! Мы успешно подлючились :)
this->connected = true;
//ждём пока Arduino перезагрузится
Sleep(ARDUINO_WAIT_TIME);
}
}
}
}
Serial::~Serial()
{
// проверяем статус подключение
if(this->connected)
{
// отключаемся
this->connected = false;
// закрываем дескриптор порта
CloseHandle(this->hSerial);
}
}
int Serial::ReadData(char *buffer, unsigned int nbChar)
{
// число считываемых байт
DWORD bytesRead;
// число байт, которое мы действительно хотим считать
unsigned int toRead;
// используем ClearCommError для получения информации о статусе последовательного порта
ClearCommError(this->hSerial, &this->errors, &this->status);
// проверяем – есть ли информация для считывания
if(this->status.cbInQue>0)
{
// если количество данных меньше требуемого – считываем
// столько, сколько есть
if(this->status.cbInQue>nbChar)
{
toRead = nbChar;
}
else
{
toRead = this->status.cbInQue;
}
// Пытаемся считать нужное количество данных и
//возвращаем число считанных байт при удачном завершении.
if(ReadFile(this->hSerial, buffer, toRead, &bytesRead, NULL) && bytesRead != 0)
{
return bytesRead;
}
}
// ничего не считали или где-то была ошибка – возвращаем -1
return -1;
}
bool Serial::WriteData(char *buffer, unsigned int nbChar)
{
DWORD bytesSend;
// пытаемся записать значение буфера buffer в COM-порт
if(!WriteFile(this->hSerial, (void *)buffer, nbChar, &bytesSend, 0))
{
// если не получилось – получаем код ошибки и возвращаем false
ClearCommError(this->hSerial, &this->errors, &this->status);
return false;
}
else
return true;
}
bool Serial::IsConnected()
{
// просто возвращаем статус соединения :)
return this->connected;
}
Пример использования:
#include <iostream>
#include "SerialClass.h"
#define COM_PORT "COM1"
#define BUF_SIZE 256
int main()
{
Serial com1(COM_PORT);
// обнуляем буфер
char buf[BUF_SIZE];
for(int i=0;i<BUF_SIZE;i++)
buf[i]='\0';
// считываем и выводим данные из порта
com1.ReadData(buf,BUF_SIZE-1);
std::cout <<buf<< std::endl;
return 0;
}
Данный пример тестировался в CodeBlocks
,но должен прекрасно работать и в Visual Studio 🙂
Arduino + C#
http://www.arduino.cc/playground/Interfacing/Csharp
.Net 2.0 предоставляет возможность просто работать с System.IO.Ports
— поэтому очень просто написать программу, например, которая будет принимать вводимую информацию с клавиатуры и перенаправлять её в порт.
using System;
using System.IO.Ports;
namespace test
{
class Program
{
static void Main(string[] args)
{
SerialPort port = new SerialPort("COM1", 9600);
port.Open();
while (true)
{
String s=Console.ReadLine();
if (s.Equals("exit"))
{
break;
}
port.Write(s+'\n');
}
port.Close();
}
}
}
Скомпилировать данный пример можно даже без сред разработки, а просто имея установленный .NET Framework. Для этого нужно перейти в директорию Framework-а – обычно это что-то вроде:
c:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\
теперь нужно скопировать туда файл с программой на C# — пусть это будет
com-cs.cs
Чтобы скомпилировать — нужно выполнить команду:
csc com-cs.cs

Компилятор отработает и в директории появится исполняемый файл
com-cs.exe
Примеры:
C# with Arduino Duemilanove + Led On/Off/Pwm Control
C# + Arduino Duemilanove + RGB Led Control
Arduino + PERL
http://www.arduino.cc/playground/Interfacing/PERL
требуется модуль Device::SerialPort
# установка параметров COM-порта
use Device::SerialPort;
my $port = Device::SerialPort->new("/dev/tty.usbserial");
# 19200, 81N on the USB ftdi driver
$port->baudrate(19200);
$port->databits(8);
$port->parity("none");
$port->stopbits(1);
Передача данных в порт:
$port->write("Whatever you feel like sending");
Получение данных от Arduino:
while (1) {
# пытаемся получить данные из порта
my $char = $port->lookfor();
# если данные есть – распечатываем :)
if ($char) {
print "Recieved character: $char \n";
}
}
Arduino + Python
http://www.arduino.cc/playground/Interfacing/Python
работая в UNIX-подобных системах, с последовательным портом можно общаться, как с файлом – считывать и записывать данные.
Но есть кросплатформенная библиотека – pySerial
, которая делает эти операции более наглядными.
эта библиотека уже упоминалась в посте про осциллограф на ардуине
Однако, для её работы под Windows понадобится ещё
pyWin32
#
# для работы с COM-портом нужна библиотека
# pySerial, кроме того, под винду понадобится еще pyWin32
#
import serial
SERIAL_PORT = 'COM1'
SERIAL_SPEED = 38400
ser = serial.Serial(SERIAL_PORT, SERIAL_SPEED)
while 1:
#s = ser.read() # считывается один байт
s = ser.readline().strip() # считывается строка и убираются символы “\r\n”
print s # печатаем на экран
писать данные в порт так же просто:
import serial
ser = serial.Serial('/dev/tty.usbserial', 9600)
ser.write('5')
Примеры:
если не хочется ничего ставить – можно посмотреть или использовать питоновский порт
arduino_serial.py
программы Tod E. Kurt-а arduino-serial.c
Arduino и IRC-бот на Python-е
Контроль Arduino с использованием HTML-форм на Python-е
Arduino + Processing
http://www.arduino.cc/playground/Interfacing/Processing
читать далее: 9. Аналоговый датчик температуры – LM335
Программа для управления портами Arduino/CraftDuino
По теме
Arduino, термины, начало работы
КМБ для начинающих ардуинщиков
Состав стартера (точка входа для начинающих ардуинщиков)
Arduino и Matlab
Arduino и LabVIEW
Processing и Arduino
openFrameworks и Arduino

0 комментариев на «“Практическое программирование Arduino/CraftDuino — общение с Arduino — программирование работы с COM-портом”»
Всем привет!
Кто нибудь пробовал работать с библиотекой LibSerial при написании программ в Linux???
Считываю из буфера порта всякую фигню, а программа «cu» всё читает идеально!..
Вопрос снимается, всё работает )))
Связка Arduino + C в AltLinux, показывает эффективные результаты!
При чтении информации из буфера, не забудьте его почистить (buf[i]).