在本文中,我们将学习如何在openFrameworks中创建一个滑块,并使用Wekinator机器学习软件控制连接到Arduino的舵机。
工作原理
openFrameworks应用程序将X和Y的值发送到Wekinator的特定端口6448,并使用OSC通信方式来发送数据。Wekinator将根据X和Y的值来进行学习,并将OCS消息发送回openFrameworks的12000端口。然后openFrameworks通过串口将消息发送给Arduino,并通过串口控制舵机。
电路图
舵机与Arduino的连接如下:
- 舵机的黄线是信号线,连接到Arduino上的数字引脚2。
- 舵机的棕线是接地线,连接到Arduino上的GND。
- 舵机的红线是电源线,连接到Arduino上的5V引脚。
Arduino的代码
在Arduino代码中,我们首先引入了servo库,并为servo初始化了一些变量。然后在setup函数中,我们将舵机附加在Arduino的引脚 2上,开始串口通信。在loop函数中,代码将寻找输入的数据,如果有任何数据可用,就读取它,并根据这个读取的值来控制舵机移动。
// 使用wekinator从openframeworks控制舵机的代码 #include <Servo.h> //including the servo library Servo sg90; //including a variable for servo named sg90 int servo_pin = 2; void setup() { sg90.attach(servo_pin); //Giving the command to arduino to control pin 2 for servo // Start the serial communication Serial.begin(9600); } void loop() { if (Serial.available()) { // If there is any data available int inByte = Serial.read(); // Get the incoming data sg90.write(inByte); } }
OpenFrameworks的代码
在openFrameworks侧,我们需要三个文件,它们主要用于从Wekinator发送和接收数据,同时实现将数据发送到Arduino。
1、Main.cpp:运行应用程序并打开输出窗口。
#include "ofMain.h" #include "ofApp.h" //======================================================================== int main( ){ ofSetupOpenGL(600, 480, 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 ofApp()); }
2、OfApp.cpp:它实现Arduino和openFrameworks之间串口通信,也实现了openFrameworks和Wekinator之间的OSC通信。
#include "ofApp.h" #include "ofxOsc.h" //-------------------------------------------------------------- void ofApp::setup(){ sender.setup(HOST, SENDPORT); receiver.setup(RECEIVEPORT); ofSetFrameRate(60); serial.listDevices(); vector <ofSerialDeviceInfo> deviceList = serial.getDeviceList(); // this should be set to whatever com port your serial device is connected to. // (ie, COM4 on a pc, /dev/tty.... on linux, /dev/tty... on a mac) // arduino users check in arduino app.... int baud = 9600; serial.setup(0, baud); //open the first device // windows example //serial.setup("COM10", baud); // mac osx example //serial.setup("/dev/tty.usbserial-A4001JEC", baud); //linux example //serial.setup("/dev/ttyUSB0", baud); } //-------------------------------------------------------------- void ofApp::update(){ // Sending data to the wekinator ofxOscMessage m; m.setAddress(string(SENDMESSAGE)); m.addFloatArg((float)mouseX); m.addFloatArg((float)mouseY); sender.sendMessage(m, false); // looking for incoming messages from wekinator while (receiver.hasWaitingMessages()) { ofxOscMessage msg; receiver.getNextMessage(&msg); // Get Message if (msg.getAddress() == RECEIVEMESSAGE) { outputData = msg.getArgAsFloat(0); // Stored it } } serial.writeByte(outputData); // sending the data to arduino } //-------------------------------------------------------------- void ofApp::draw(){ ofSetColor(255, 0, 0); string buf = "Sending message " + string(SENDMESSAGE) + " to " + string(HOST) + " on port " + ofToString(SENDPORT); ofDrawBitmapString(buf, 10, 20); buf = "X=" + ofToString(mouseX) + ", Y=" + ofToString(mouseY); ofDrawBitmapString(buf, 10, 50); ofSetColor(0, 255, 0); ofDrawRectangle(mouseX, mouseY, boxSize, boxSize); } //-------------------------------------------------------------- void ofApp::mouseDragged(int x, int y, int button){ mouseX = x; mouseY = y; }
代码在setup()函数中,首先设置发送方和接收方,然后开始寻找串口端口号。一旦找到,就会自动连接。在update()函数中,代码首先将滑块的X和Y值发送给Wekinator。然后,寻找来自接收端的传入消息,当接收任何数据时,它将数据存储下来,同时将其发送到Arduino。在draw()函数中,将创建了一个拖动时就会移动的滑块。
OfApp.h:是头文件。
#pragma once #include "ofMain.h" #include "ofxOsc.h" //Defaults for OSC: #define HOST "127.0.0.1" #define SENDPORT 6448 #define RECEIVEPORT 12000 #define SENDMESSAGE "/wek/inputs" #define RECEIVEMESSAGE "/wek/outputs" class ofApp : public ofBaseApp{ public: void setup(); void update(); void draw(); void mouseDragged(int x, int y, int button); ofxOscSender sender; ofxOscReceiver receiver; ofSerial serial; int mouseX = 0; int mouseY = 0; int boxSize = 30; char outputData; };
如何运行openFrameworks
在openFrameworks中使用项目生成器创建一个新项目,本项目需要“Ofxosc”插件。将上一节给出的代码复制到相应的文件中并构建项目。在构建项目之后,你将看到如下所示的输出窗口。
在Wekinator中设置项目
在openFrameworks中建立项目后,打开Wekinator并调整设置,如下图所示:将输入设置为2,输出设置为1。选择输出类型为“custom”,点击“configure”。
接下来,将最小值设置为0,最大值设置为180,点击“done”。
单击“next”,将出现新的项目窗口。
将窗口中的绿色框拖到屏幕左侧中心,点击“randomize”。启动记录一秒,并允许Wekinator记录样本。
现在将窗口中的绿色框拖到窗口中心,点击“randomize”。开始录音半秒钟。
最后,将窗口中的绿色框拖到右边中间,然后单击randomize。开始录音半秒钟。
为Wekinator完成三组学习后,单击“train”,然后单击“run”。现在,当我们在openFrameworks窗口中拖动滑块时,它将能控制连接到Arduino的舵机移动起来。