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

openFrameworks и Arduino

openFrameworks
openFrameworks — это обёртка С++ классов вокруг нескольких библиотек, т.е. что-то вроде клея для соединения этих библиотек в единое целое:
* OpenGL — для отображения графики
* FreeImage — для манипуляций с изображениями
* Freetype — для отображения и работы со шрифтами
* rtAudio — для аудио
* Quicktime (mac или pc) — для проигрывания видео и видеозахвата
Ключевые концепции openFrameworks:
* упрощение вещей.
* вы можете использовать любую из его частей независимо от других.
* предоставление прямого доступа к данным; например, пиксели изображения.

OpenFrameworks предназначен для «творческого кодинга» («creative coding») и может работать под Windows, MacOS X и Linux.
тип лицензии: MIT

чтобы работать с OpenFrameworks нужно иметь установленный VS C++ 2008
(да, по сравнению с Processing, где всё идёт в комплекте — это минус).

Скачиваем zip-архив с OpenFrameworks.
Обратите внимание, что OpenFrameworks выкладывается в двух версиях.
Простой и «толстой» (FAT); в последней содержатся дополнительные примеры (например, работа с OpenCV).

of_preRelease_v0061_vs2008_FAT.zip

Полученый архив нужно просто распаковать в удобную директорию
Например:
c:\DevTools\of_preRelease_v0061_vs2008_FAT\

и всё. Можно смотреть примеры.
Переходим в
\apps\examples\
, выбираем понравившийся проект, открываем директорию и запускаем .vcproj
Запустится VS C++ и теперь остаётся только запустить сборку проекта.

Создание нового openFrameworks-проекта

В readme описан процесс создания нового OpenFrameworks-проекта
и состоит он в копировании тестового пустого проекта в проект с новым названием:

a) скопируйте директорию внутри apps и вставьте в ту же самую директорию
т.е. (скопируйте «emptyExample» и вставьте «копия emptyExample»)

b) переименуйте получившуюся директорию, а внутри директории, переименуйте файлы .vcproj и .sln
т.е. переименуйте:
emptyExample.vcproj
в
coolExample.vcproj

c) откройте файл .vcproj в текстовом редакторе. измените старое название проекта на новое:
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
	ProjectType="Visual C++"
	Version="9.00"
	Name="emptyExample"
	ProjectGUID="{7FD42DF7-442E-479A-BA76-D0022F99702A}"
	RootNamespace="emptyExample"


например, если скопировали emptyExample и хотите назвать его «coolExample», то файл должен выглядеть так:
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
	ProjectType="Visual C++"
	Version="9.00"
	Name="coolExample"
	ProjectGUID="{7FD42DF7-442E-479A-BA76-D0022F99702A}"
	RootNamespace="coolExample"


в solution-файле, измените название .vcproj -файла:
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "emptyExample", "emptyExample.vcproj", "{7FD42DF7-442E-479A-BA76-D0022F99702A}"
	ProjectSection(ProjectDependencies) = postProject
		{5837595D-ACA9-485C-8E76-729040CE4B0B} = {5837595D-ACA9-485C-8E76-729040CE4B0B}
	EndProjectSection
EndProject


на название, которое вы дали своему файлу:
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "coolExample", "coolExample.vcproj", "{7FD42DF7-442E-479A-BA76-D0022F99702A}"
	ProjectSection(ProjectDependencies) = postProject
		{5837595D-ACA9-485C-8E76-729040CE4B0B} = {5837595D-ACA9-485C-8E76-729040CE4B0B}
	EndProjectSection
EndProject

Обратите внимание, что в OpenFrameworks уже реализвано общение с контроллером Arduino по протоколу Firmata.
см. пример
apps\examples\firmataExample\

работа осуществляется через класс ofArduino (который, соответственно, использует класс ofSerial)
см.
libs\openFrameworks\communication\

пример OpenCV находится в дополнительных примерах, которые идут в расширенной («толстой») версии OpenFrameworks:
apps\addonsExamples\opencvExample\

поддержка OpenCV реализована в виде аддона:
addons\ofxOpenCv\
и по версии используемых lib-файлов
addons\ofxOpenCv\libs\opencv\lib\vs2008\
, используется версия OpenCV 1.1

openFrameworks и Arduino

Рассмотрим работу примера общения с Arduino в примере firmataExample, заодно поймём как нужно работать в OpenFrameworks.

Запустим проект
apps\examples\firmataExample\

Он состоит из трёх файлов:
main.cpp
testApp.h
testApp.cpp

содержимое main.cpp:
#include "ofMain.h"
#include "testApp.h"
#include "ofAppGlutWindow.h"

//========================================================================
int main( ){

    ofAppGlutWindow window;
	ofSetupOpenGL(&window, 800,600, OF_WINDOW);			// <-------- setup the GL context

	// this kicks off the running of my app
	// can be OF_WINDOW or OF_FULLSCREEN
	// pass in width and height too:
	ofRunApp( new testApp());

}

Кажется, тут всё понятно: создаётся окно, устанавливаются его параметры, а затем создаётся новый объект нашего testApp, который передаётся параметром в ofRunApp(), которая делает всю остальную работу, вызывая установочные testApp->setup() и testApp->update(), а затем в цикле отрисовки вызывая testApp->draw()

содержимое testApp.h:
#ifndef _TEST_APP
#define _TEST_APP

#include "ofMain.h"

class testApp : public ofSimpleApp{

public:

	void setup();
	void update();
	void draw();

	void keyPressed(int key);
	void keyReleased(int key);

	void mouseMoved(int x, int y );
	void mouseDragged(int x, int y, int button);
	void mousePressed(int x, int y, int button);
	void mouseReleased(int x, int y, int button);
	void windowResized(int w, int h);

	void setupArduino();
	void updateArduino();

	ofImage				bgImage;
	ofTrueTypeFont		font;
	ofArduino	ard;
	bool		bSetupArduino;			// flag variable for setting up arduino once

};
#endif


видим класс testApp, у которого объявлено несколько функций.
самые важные — это:
void setup();
void update();
void draw();

ниже задаются функции-обработчики событий от клавиатуры и мышки, а ещё ниже уже пользовательские функции и пользовательские переменные.

видим объект для общения с Arduino по протоколу Firmata:
ofArduino	ard;

Соответственно в testApp.cpp написана реализация функций класса:

setup(), как ясно из названия — это аналог setup() в Wiring-e и Processing-е; функция в которой происходит начальная установка и инициализация параметров.
В данном примере — установка фона, подгрузка картинки, загрузка шрифта и подключение к контроллеру Arduino:
#include "testApp.h"

void testApp::setup(){

	ofSetVerticalSync(true);
	ofSetFrameRate(60);

	ofBackground(255,0,130);

	bgImage.loadImage("firmata.png");
	font.loadFont("franklinGothic.otf", 20);

	// the connection speed has been changing in the
	// arduino firmata sketch. in 0017 it's 57600
	// if you have problems try commenting/uncommenting
	// to change the speed

	// ard.connect("/dev/ttyUSB0", 115200);
	ard.connect("/dev/ttyUSB0", 57600);

	bSetupArduino	= false;							// flag so we setup arduino when its ready, you don't need to touch this :)
}

Нужно отметить, что для подключения к COM-порту под Windows придётся писать строчку вида:
ard.connect("\\\\.\\COM19", 57600);

void testApp::update(){

	if ( ard.isArduinoReady()){

		// 1st: setup the arduino if haven't already:
		if (bSetupArduino == false){
			setupArduino();
			bSetupArduino = true;	// only do this once
		}
		// 2nd do the update of the arduino
		updateArduino();
	}

}

//--------------------------------------------------------------
void testApp::setupArduino(){

	// this is where you setup all the pins and pin modes, etc
	for (int i = 0; i < 13; i++){
		ard.sendDigitalPinMode(i, ARD_OUTPUT);
	}

	ard.sendDigitalPinMode(13, ARD_OUTPUT);
	ard.sendAnalogPinReporting(0, ARD_ANALOG);	// AB: report data
	ard.sendDigitalPinMode(11, ARD_PWM);		// on diecimelia: 11 pwm?*/
}

//--------------------------------------------------------------
void testApp::updateArduino(){

	// update the arduino, get any data or messages:
	ard.update();
	ard.sendPwm(11, (int)(128 + 128 * sin(ofGetElapsedTimef())));   // pwm...

}

Нетрудно догадаться, что функция draw() — аналог одноимённой функции Processing-а:
void testApp::draw(){
	bgImage.draw(0,0);

	if (!ard.isArduinoReady()){
		font.drawString("arduino not ready\n", 545, 40);
	} else {
		font.drawString("analog pin 0: " + ofToString(ard.getAnalog(0)) +
						"\nsending pwm: " + ofToString((int)(128 + 128 * sin(ofGetElapsedTimef()))), 545, 40);

	}
}

так же видим, что при нажатии/отпускании кнопки мышки контроллеру Ardunio будет послано сообщение зажечь/погасить сигнальный светодиод на 13 порту.
void testApp::mousePressed(int x, int y, int button){
	ard.sendDigital(13, ARD_HIGH);
}

//--------------------------------------------------------------
void testApp::mouseReleased(int x, int y, int button){
	ard.sendDigital(13, ARD_LOW);
}

После сборки проекта в каталоге
apps\examples\firmataExample\bin\

появится исполняемый файл
firmataExample.exe
, а так же будут скопированы необходимые для работы и распространения dll-ки:
fmodex.dll
fmodexL.dll
FreeImage.dll
FreeType-6.dll
glut32.dll
Zlib.dll


так же обратите на подкаталог data, в котором содержатся необходимые для работы файлы:
firmata.png — файл изображения Arduino
franklinGothic.otf — файл используемого шрифта

Cвой openFrameworks-проект для Arduino

Итак, вроде всё более-менее понятно.
Чтобы закрепить материал нужно попробовать написать свой проект :)
Т.к. проект будет для общения с Arduino — я скопирую не пустой проект emptyExample, а уже рассмотренный firmataExample.

Назову проект myArduinoExample
Проект будет аналогом рассмотренного ранее проекта Processing-а arduio_output.
Т.е. выведем в окошко квадратики состояния цифровых выходов ардуины; каждый квадратик будет обозначать один цифровой выход контроллера от 13 до 0. Щелкая по нему, мы переключаем состояние межу HIGH и LOW.
Однако просто выводить квадратики скучно, поэтому возьмём фотографию контроллера Arduino и будем щёлкать по изображению портов.

переименую и отредактирую файлы
myArduinoExample.sln
и
myArduinoExample.vcproj
заменив строчку firmataExample на myArduinoExample.
Заменим и переименуем картинку.
Пора редактировать код :)

Первым делом, нам нужно определить положение портов на картинке:
для этого добавим в класс testApp две переменные mouseX и mouseY для сохранения координат нажатия мышки.
Установку значения этих переменных будем производить по нажатию мышки в обработчике mousePressed():
void testApp::mousePressed(int x, int y, int button){
	printf("[click] x: %d y: %d\n", x, y);
	mouseX=x;
	mouseY=y;
	}

вывод координат добавим в функцию draw():
// выводим где был последний клик мышкой :)
	if(mouseX || mouseY){
		ofSetColor(50, 100, 200);
		font.drawString("x: " + ofToString(mouseX) + " y: " + ofToString(mouseY), 600, 100);
		ofSetColor(255, 255, 255);
	}

Обратите внимание — шрифт изначально выводится белым цветом :)
по примерам видно, что для того чтобы изменить цвет нужно добавить строчку
ofSetColor(50, 100, 200);
font.drawString("x: " + ofToString(mouseX) + " y: " + ofToString(mouseY), 600, 100);
в конце нужно добавить
ofSetColor(255, 255, 255);
, чтобы цвет не залил весь экран ;)

Собираем код, щёлкаем по картинке и получаем координаты:
по y - около 95
а по X:
13 - 300
12 - 320
11 - 340
10 - 360
9 - 380
8 - 400
7 - 440
6 - 460
5 - 480
4 - 500
3 - 520
2 - 540
Остаётся нарисовать в этих местах квадратики.
Как задаётся цвет мы уже знаем, квадратик же рисуется функцией
ofRect(x, y, w, h);


Вот и всё. Остаётся определить место клика мышкой и просто менять состояние порта на противоположное.

Для хранения текущего состояния порта заведём массив
int pins[PIN_COUNT];
Обнуляем этот массив в функции setup(), а затем добавляем проверочный код на какой квадратик порта кликнули в функцию-обработчик mousePressed():
void testApp::mousePressed(int x, int y, int button){
	printf("[click] x: %d y: %d\n", x, y);
	mouseX=x;
	mouseY=y;

	// проверка попадания по Y
	if(mouseY>90 && mouseY<105){
		printf("[i] Y ok!\n");

		// проверка попадания по X
		if(mouseX>290 && mouseX<560){
			// определяем куда кликнули :)
			for(int i=2; i<=13; i++){
				float xx;
				if(i<=7){
					xx = 540 - 20*(i-1) + 10;
				}
				else{
					xx = 400 - 20*(i-7) + 10;
				}
				if( abs(xx+7.5-x)<13 ){

					printf("[i] X ok! pin: %d\n", i);

					// меняем состояние порта
					if(pins[i]){
						ard.sendDigital(i, ARD_LOW);
						pins[i]=0;
					}
					else{
						ard.sendDigital(i, ARD_HIGH);
						pins[i]=1;
					}
					break;
				}
			}
		}
	}
}

и соответственно меняем цвет квадратика в функции draw():
void testApp::draw(){
	// показываем изображения (в качестве фона)
	bgImage.draw(0,0);

	if (!ard.isArduinoReady()){
		font.drawString("arduino not ready\n", 545, 40);
	} 
	
	// выводим где был последний клик мышкой :)
	if(mouseX || mouseY){
		ofSetColor(50, 100, 200);
		font.drawString("x: " + ofToString(mouseX) + " y: " + ofToString(mouseY), 600, 100);
		ofSetColor(255, 255, 255);
		
		//ofDrawBitmapString("x: " + ofToString(mouseX) + " y: " + ofToString(mouseY), 545, 130);
	}

	float x,y, w=15, h=15;
	// нарисуем квадратики портов
	for(int i=2; i<=13; i++){
		// в зависимости от состояния порта - определяем цвет
		if(pins[i]){
			ofSetColor(200, 0, 0);
		}
		else{
			ofSetColor(0, 200, 0);
		}
		y = 90;
		if(i<=7){
			x = 540 - 20*(i-1) + 10;
		}
		else{
			x = 400 - 20*(i-7) + 10;
		}
		// рисуем квадратик
		ofRect(x, y, w, h);
	}
	ofSetColor(255, 255, 255);
}

Вот как выглядит окошко программы:


Скачать программу с исходниками. (2.5 Mb — так много потому что в комплекте идут dll-библиотеки используемые openFrameworks-ом, без которых программа не запустится )

Вывод — действительно просто, быстро и удобно :) А ещё OpenGL ;)

читать ещё: openFrameworks vs Processing

Ссылки:
официальный сайт — www.openframeworks.cc
FAQ — www.openframeworks.cc/about/faq
форум — www.openframeworks.cc/forum/index.php
wiki — wiki.openframeworks.cc

http://en.wikipedia.org/wiki/OpenFrameworks
wiki.openframeworks.cc/index.php?title=OfAmsterdam
OpenGL tutorials

По теме:
Практическое программирование Arduino- программирование работы с COM-портом
Arduino и Matlab
Arduino и LabVIEW
Processing и Arduino
  • +1
  • 13 ноября 2010, 12:04
  • noonv

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

RSS свернуть / развернуть

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