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]).