CraftDuino v2.0
  • - это CraftDuino - наш вариант полностью Arduino-совместимой платы.
  • CraftDuino - настоящий конструктор, для очень быстрого прототипирования и реализации идей.
  • Любая возможность автоматизировать что-то с лёгкостью реализуется с CraftDuino!
Просто добавьте CraftDuino!

Практическое программирование Arduino/CraftDuino - общение с Arduino - программирование работы с COM-портом

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 <serialport> [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
  • +1
  • 27 августа 2009, 12:55
  • admin

Комментарии (2)

RSS свернуть / развернуть
+
0
Всем привет!
Кто нибудь пробовал работать с библиотекой LibSerial при написании программ в Linux???
Считываю из буфера порта всякую фигню, а программа «cu» всё читает идеально!..
avatar

SinauRus

  • 31 октября 2010, 15:33
+
0
Вопрос снимается, всё работает )))

Связка Arduino + C в AltLinux, показывает эффективные результаты!
При чтении информации из буфера, не забудьте его почистить (buf[i]).
avatar

SinauRus

  • 21 декабря 2010, 20:37

Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.