laser + servo by openFrameworks + Arduino

laser + servo by openFrameworks + Arduino
です.

thetaを変数としてparametric plotをArduinoと連携してやってみようというもの.
データの送信方法はserial通信:
http://qiita.com/keitasumiya/items/44908da606c8da1a635c
です.

variables

t

t ∈ [0,1023] で単調増加.
境界条件としてt>1023でt=0にしています.

if (t > 1023){
   t = 0;
}

theta

theta ∈ [0, 2 pi]

float theta = 2*PI*(float)t/1023;

x, y

基本的には

x = cos(x)
y = sin(y)

です.
が, Arduinoのservoは90を中心に[0,180]で変化します.
さらに, 2軸とも[0,180]で動かしてしまうと, 天球状のスクリーンが必要になります.
今回は垂直な壁にプロジェクションの予定だったので, x, yを[60, 120]に絞りました.

float x = 60*(cos(theta)+1)/2 + 60;
float y = 60*(sin(theta)+1)/2 + 60;

codes

#include <Servo.h>

const int val_size = 2;
int values[val_size] = {0, 0};
bool isValids[val_size] = {false, false};
const int OUT_PINs[val_size] = {5, 3};
Servo myservos[val_size];

void setup(){
  Serial.begin(115200);
  myservos[0].attach(OUT_PINs[0]);
  myservos[1].attach(OUT_PINs[1]);

}

void loop(){
  bool isValids[val_size] = {false, false};
  if (Serial.available() >= 3*val_size) {
    int head = Serial.read();
    for (int i=0; i<val_size; i++){
      if (head == 128+i) {
        int high = Serial.read();
        int low  = Serial.read();
        values[i] = (high<<7) + low;
        if (0 <= values[i] <= 1023) {
          myservos[i].write(values[i]);        
          isValids[i] = true;
        }
      }
    }
  }
}
#include "ofApp.h"

ofSerial mySerial;
const int val_size = 2;
int values[val_size] = {0, 0};
bool isValids[val_size] = {false, false};
int t = 0;

//--------------------------------------------------------------
void ofApp::setup(){
    ofSetFrameRate(120);
    mySerial.setup("/dev/cu.usbmodem1421",115200);
}

//--------------------------------------------------------------
void ofApp::update(){
    t += 4;
    if (t > 1023){
        t = 0;
    }
    float theta = 2*PI*(float)t/1023;
    float x = 60*(cos(theta)+1)/2 + 60;
    float y = 60*(sin(theta)+1)/2 + 60;
    values[0] = round(x);
    values[1] = round(y);

    bool isValids[val_size] = {false, false};
    for (int i=0; i<val_size; i++){
        int high = (values[i] >> 7) & 127;
        int low  = values[i] & 127;
        bool byteWasWritten1 = mySerial.writeByte(128+i);
        bool byteWasWritten2 = mySerial.writeByte(high);
        bool byteWasWritten3 = mySerial.writeByte(low);
        if ( byteWasWritten1 && byteWasWritten2 && byteWasWritten3 ) {
            printf("value is %d \n", values[i]);
            isValids[i] = true;
        } else {
            printf("an error occurred \n");
        }
    }
}

results

動画:
こんな感じです.

Anisotropic Kepler problem(AKP)で軌道を書いてみた例もあります
https://youtu.be/40Fag5gq5fU