経緯
Arduinoでスイッチの情報を取得して、openFrameworksに何番がONで何番がOFFなのか、データを送るときに、bit列を使おうと思った。理由は、なんとなく頭良さげだから。ひゃっほー。1
初めてだったこと
- bitで情報をやりとりする
- openFrameworksとArduinoの通信
いつもはFirmata使ってたし、データを送る先はProcessingしか使ったことがなかった。
今回使う回路
13番ピン-6番ピンに7つのスイッチを接続して、それぞれ、 ** ONのときHIGH, OFFのときLOW ** になるとする。
便宜上、13番ピンに接続されたスイッチをSW0, 12番ピンに接続されたスイッチをSW1, … , 6番ピンに接続されたスイッチをSW6と名前をつける。
やり方
方針としてそれぞれの状態を二進数として表すことにする。
例えば、SW0とSW3とSW5がONとしたとき、
0b0101001
を送る。
Arduino側のプログラム
// ピンの数 const int PINNUM = 7; void setup(){ int i; for(i=0; i<PINNUM; ++i){ // 13-6番ピンをインプット用に。 pinMode(13-i, INPUT); } } void draw(){ // 送信用のデータを格納する変数 unsigned int send_data; // データを作成 int i; for(i=0; i<PINNUM; ++i){ if(digitalRead(i)==HIGH){ send_data += (1 << i); } } // データを送信 Serial.write(send_data); }
地味に最後のSerial.write()
で詰まったSerial.print()
は文字列を送るためのもののようで、数字を文字列として扱ってしまうみたい。
openFrameworksのプログラム
受信するためのArduinoReceiver
というクラスを作った。
ArduinoReceiver.h
#ifndef __YourProject__ArduinoReceiver__ #define __YourProject__ArduinoReceiver__ #include "ofMain.h" enum PinStatus{ STAY_ON, STAY_OFF, TURN_ON, TURN_OFF }; class ArduinoReceiver{ public: ArduinoReceiver(); bool isOn(int pin_id); bool isTurnedOn(int pin_id); bool isTurnedOff(int pin_id); void setup(string modem, int rate); void update(); private: int getStatus(int pin_id); ofSerial serial; unsigned int data; unsigned int p_data; }; #endif
ArduinoReceiver.cpp
#include "ArduinoReceiver.h" // constructor ArduinoReceiver::ArduinoReceiver(){ data = 0; } // setup void ArduinoReceiver::setup(string modem, int rate){ // Serial通信のセットアップ serial.setup(modem, rate); } // update void ArduinoReceiver::update(){ // データを取得 p_data = data; if(serial.isInitialized()){ if(serial.available()){ data = serial.readByte(); cout << data << endl; } } } // isOn // ピンがONかどうかを調べる bool ArduinoReceiver::isOn(int pin_id){ return data & (1 << pin_id); } // isTrunedOn // ピンがONになった瞬間だけtrueになる。 bool ArduinoReceiver::isTurnedOn(int pin_id){ return getStatus(pin_id) == TURN_ON; } // isTurnedOff // ピンがOFFになった瞬間だけfalseになる。 bool ArduinoReceiver::isTurnedOff(int pin_id){ return getStatus(pin_id) == TURN_OFF; } // 今のピンの状態を取得する内部用の関数 // STAY_OFF: OFFのまま // STAY_ON: ONのまま // TURN_ON: OFF->ONになった // TURN_OFF: ON->OFFになった int ArduinoReceiver::getStatus(int pin_id){ int current_state = (data & (1 << pin_id))>0 ? 1 << 0 : 0; int prev_state = (p_data & (1 << pin_id))>0 ? 1 << 1 : 0; switch(current_state + prev_state){ case 0: return STAY_OFF; case 1: return TURN_ON; case 2: return TURN_OFF; case 3: return STAY_ON; } }
ArduinoReceiverの使い方
ofApp.h
#pragma once #define USB_MODEM "/dev/tty.usbmodem411" #include "ofMain.h" #include "ArduinoReceiver.h" class ofApp : public ofBaseApp{ public: void setup(); void update(); void draw(); // 中略 ArduinoReceiver ar; };
** ofApp.cpp **
//-------------------------------------------------------------- void ofApp::setup(){ ofBackground(0); ofSetVerticalSync(true); ofSetFrameRate(100); ar.setup(USB_MODEM, 9600); } //-------------------------------------------------------------- void ofApp::update(){ ar.update(); } //-------------------------------------------------------------- void ofApp::draw(){ ofSetColor(255); for (int i=0; i<7; ++i) { if(ar.isOn(i)){ ofFill(); }else{ ofNoFill(); } ofRect(100 + 30*i, 300, 10, 10); } } // 後略
まとめ
- bitを使うと頭良さそう。あと満足感がなんとなくある。
- Serialはそんなに怖くない。
- Firmataは便利だけど、Serialにすると、Arduinoで細かい処理ができるから幸せ。
- 馬鹿っぽい ↩
コメントを残す