Nikon万能投影機からArduinoへデータ読み込み

前にも書いたネタかもしれませんが、やり直しているので忘備録的に記事をアップします。Nikonの万能投影機の座標をコンピュータに取り込んで自動でDXFデータを作成するためのプロジェクト。以前はRhinocerosのplug-inのGrasshopperにデータを入れて処理をしていましたが、色々と使いにくいのでmacOSかRasPIのPythonでDXFを書き出すプログラムに変更しようと作り直してます。
次の写真が基板。
IMG_4868
投影機のカウンタsc102の出力からArduino megaにつないでmegaでシリアル通信でデータを送れる形に変換しています。以下はそのプログラム。以前は基板上のボタンを押すとデータを送信していましたが、今回は一定間隔でデータを送信しているだけになってます。

//Nikon profile projector data processing unit sc102
//Arduino Mega
//RasPi3にシリアル通信でデータを送る。データは連続して送るだけ。
//データフォーマットはx=0000.000,y=0000.000;
//Arduino上のボタンは使用しない。

//ピンの定義
const int ledPin8 =  54;
const int ledPin7 =  55;
const int ledPin6 =  56;
const int ledPin5 =  57;
const int ledPin4 =  58;
const int ledPin3 =  59;
const int ledPin2 =  60;
const int ledPin1 =  61;

const int buttonPin8 = 65;
const int buttonPin7 = 64;
const int buttonPin6 = 63;
const int buttonPin5 = 62;
const int buttonPin4 = 69;
const int buttonPin3 = 68;
const int buttonPin2 = 67;
const int buttonPin1 = 66;

//data pin
//X-AXE
const int X_D8 = 38;
const int X_D7 = 39;
const int X_D6 = 40;
const int X_D5 = 41;
const int X_D4 = 42;
const int X_D3 = 43;
const int X_D2 = 44;
const int X_D1 = 45;
const int X_D = 46;
const int X_C = 47;
const int X_B = 48;
const int X_A = 49;

//Y-AXE
const int Y_D8 = 22;
const int Y_D7 = 23;
const int Y_D6 = 24;
const int Y_D5 = 25;
const int Y_D4 = 26;
const int Y_D3 = 27;
const int Y_D2 = 28;
const int Y_D1 = 29;
const int Y_D = 30;
const int Y_C = 31;
const int Y_B = 32;
const int Y_A = 33;

int xAxe[8];
int yAxe[8];


String sendString = "";
String lastSendString = "";

void setup() {
  Serial.begin(57600);

  //initilize array
  for (int i = 0 ; i < 8 ; i++) {
    xAxe[i] = 0;
    yAxe[i] = 0;
  }

  //set pinmode for led
  pinMode(ledPin1, OUTPUT);
  pinMode(ledPin2, OUTPUT);
  pinMode(ledPin3, OUTPUT);
  pinMode(ledPin4, OUTPUT);
  pinMode(ledPin5, OUTPUT);
  pinMode(ledPin6, OUTPUT);
  pinMode(ledPin7, OUTPUT);
  pinMode(ledPin8, OUTPUT);

  //set pinmode for button pin
  pinMode(buttonPin1, INPUT);
  pinMode(buttonPin2, INPUT);
  pinMode(buttonPin3, INPUT);
  pinMode(buttonPin4, INPUT);
  pinMode(buttonPin5, INPUT);
  pinMode(buttonPin6, INPUT);
  pinMode(buttonPin7, INPUT);
  pinMode(buttonPin8, INPUT);

  //set pinmode for data input
  pinMode(X_D8, INPUT);
  pinMode(X_D7, INPUT);
  pinMode(X_D6, INPUT);
  pinMode(X_D5, INPUT);
  pinMode(X_D4, INPUT);
  pinMode(X_D3, INPUT);
  pinMode(X_D2, INPUT);
  pinMode(X_D1, INPUT);

  pinMode(Y_D8, INPUT);
  pinMode(Y_D7, INPUT);
  pinMode(Y_D6, INPUT);
  pinMode(Y_D5, INPUT);
  pinMode(Y_D4, INPUT);
  pinMode(Y_D3, INPUT);
  pinMode(Y_D2, INPUT);
  pinMode(Y_D1, INPUT);

  pinMode(Y_D, INPUT);
  pinMode(Y_C, INPUT);
  pinMode(Y_B, INPUT);
  pinMode(Y_A, INPUT);

  pinMode(X_D, INPUT);
  pinMode(X_C, INPUT);
  pinMode(X_B, INPUT);
  pinMode(X_A, INPUT);

  //led all off
  digitalWrite(ledPin1, LOW);
  digitalWrite(ledPin2, LOW);
  digitalWrite(ledPin3, LOW);
  digitalWrite(ledPin4, LOW);
  digitalWrite(ledPin5, LOW);
  digitalWrite(ledPin6, LOW);
  digitalWrite(ledPin7, LOW);
  digitalWrite(ledPin8, LOW);

}


//SC102に表示されるX、Yの文字列を返すfunction
String counterString(int data[8]) {
  char outputChar;
  String outStr;

  for (int i = 0 ; i < 8 ; i++) {
    switch (data[i]) {
      case 11:
        outputChar = ' ';
        break;
      case 10:
        outputChar = '-';
        break;
      case 0:
        outputChar = '0';
        break;
      case 1:
        outputChar = '1';
        break;
      case 2:
        outputChar = '2';
        break;
      case 3:
        outputChar = '3';
        break;
      case 4:
        outputChar = '4' ;
        break;
      case 5:
        outputChar = '5';
        break;
      case 6:
        outputChar = '6';
        break;
      case 7:
        outputChar = '7';
        break;
      case 8:
        outputChar = '8';
        break;
      case 9:
        outputChar = '9';
        break;
    }
    outStr += outputChar;
    if (i == 4) {
      outStr += '.';
    }
  }
  return outStr;
  //Serial.println(outStr);
}

//シリアルでデータ送信
void sendXYData() {
  //Serial.println("x=" + counterString(xAxe));
  //Serial.println("y=" + counterString(yAxe));
  String sendString = "x=" + counterString(xAxe) + ", y=" + counterString(yAxe) + ";";//送信するデータをxAxe,yAxeから作る。

  Serial.println(sendString);//シリアル出力
}

int readXBCD_data() {
  int A = digitalRead(X_A);
  int B = digitalRead(X_B);
  int C = digitalRead(X_C);
  int D = digitalRead(X_D);
  int Value = A  + B * 2 + C * 4 + D * 8;
  return (Value);
}

int readYBCD_data() {
  int A = digitalRead(Y_A);
  int B = digitalRead(Y_B);
  int C = digitalRead(Y_C);
  int D = digitalRead(Y_D);
  int Value = A  + B * 2 + C * 4 + D * 8;
  return (Value);
}

void readSC102data_X() {
  //D8がlowからhighに変わるところを捕まえる。最長で7370μSec
  //Serial.println("start readSC102data_X");
  while (digitalRead(X_D8) == HIGH) {
    //D8がHIGHの時はこのループで待つ
   // Serial.println("digitalRead(X_D8) is not HIGH");
  }
  while (digitalRead(X_D8) == LOW) {
    //D8がLOWの時はこのループで待つ
    //Serial.println("digitalRead(X_D8) is not LOW");
  }
  
  //D8がHIGHになった。800μSecの間にABCDのデータを読み込む。
  xAxe[0] = readXBCD_data();
  //Serial.println("X[0]");

  while (digitalRead(X_D7) == LOW)
  {
    //D7がLOWの時はこのループで待つ
  }
  xAxe[1] = readXBCD_data();
  //Serial.println("X[1]");

  while (digitalRead(X_D6) == LOW)
  {
    //D6がLOWの時はこのループで待つ
  }
  xAxe[2] = readXBCD_data();
  //Serial.println("X[2]");

  while (digitalRead(X_D5) == LOW)
  {
    //D5がLOWの時はこのループで待つ
  }
  xAxe[3] = readXBCD_data();
  //Serial.println("X[3]");

  while (digitalRead(X_D4) == LOW)
  {
    //D4がLOWの時はこのループで待つ
  }
  xAxe[4] = readXBCD_data();
  //Serial.println("X[4]");

  while (digitalRead(X_D3) == LOW)
  {
    //D3がLOWの時はこのループで待つ
  }
  xAxe[5] = readXBCD_data();
  //Serial.println("X[5]");

  while (digitalRead(X_D2) == LOW)
  {
    //D2がLOWの時はこのループで待つ
  }
  xAxe[6] = readXBCD_data();
  //Serial.println("X[6]");

  while (digitalRead(X_D1) == LOW)
  {
    //D1がLOWの時はこのループで待つ
  }
  xAxe[7] = readXBCD_data();
  //Serial.println("X[7]");
}


void readSC102data_Y() {
  //D8がlowからhighに変わるところを捕まえる。最長で7370μSec
  while (digitalRead(Y_D8) == HIGH) {
    //D8がHIGHの時はこのループで待つ
  }
  while (digitalRead(Y_D8) == LOW) {
    //D8がLOWの時はこのループで待つ
  }
  //D8がHIGHになった。800μSecの間にABCDのデータを読み込む。
  yAxe[0] = readYBCD_data();
  //Serial.println("Y[0]");

  while (digitalRead(Y_D7) == LOW)
  {
    //D7がLOWの時はこのループで待つ
  }
  yAxe[1] = readYBCD_data();
  //Serial.println("Y[1]");

  while (digitalRead(Y_D6) == LOW)
  {
    //D6がLOWの時はこのループで待つ
  }
  yAxe[2] = readYBCD_data();
  //Serial.println("Y[2]");

  while (digitalRead(Y_D5) == LOW)
  {
    //D5がLOWの時はこのループで待つ
  }
  yAxe[3] = readYBCD_data();
  //Serial.println("Y[3]");

  while (digitalRead(Y_D4) == LOW)
  {
    //D4がLOWの時はこのループで待つ
  }
  yAxe[4] = readYBCD_data();
  //Serial.println("Y[4]");

  while (digitalRead(Y_D3) == LOW)
  {
    //D3がLOWの時はこのループで待つ
  }
  yAxe[5] = readYBCD_data();
  //Serial.println("Y[5]");

  while (digitalRead(Y_D2) == LOW)
  {
    //D2がLOWの時はこのループで待つ
  }
  yAxe[6] = readYBCD_data();
  //Serial.println("Y[6]");

  while (digitalRead(Y_D1) == LOW)
  {
    //D1がLOWの時はこのループで待つ
  }
  yAxe[7] = readYBCD_data();
  //Serial.println("Y[7]");
}

void readSC102data() {
  for (int i = 0 ; i < 10000; i++) {
    //X-AXE Input
    int xA = digitalRead(X_A);
    int xB = digitalRead(X_B);
    int xC = digitalRead(X_C);
    int xD = digitalRead(X_D);

    //Y-AXE Input
    int yA = digitalRead(Y_A);
    int yB = digitalRead(Y_B);
    int yC = digitalRead(Y_C);
    int yD = digitalRead(Y_D);

    int xD1 = digitalRead(X_D1);
    int xD2 = digitalRead(X_D2);
    int xD3 = digitalRead(X_D3);
    int xD4 = digitalRead(X_D4);
    int xD5 = digitalRead(X_D5);
    int xD6 = digitalRead(X_D6);
    int xD7 = digitalRead(X_D7);
    int xD8 = digitalRead(X_D8);

    int yD1 = digitalRead(Y_D1);
    int yD2 = digitalRead(Y_D2);
    int yD3 = digitalRead(Y_D3);
    int yD4 = digitalRead(Y_D4);
    int yD5 = digitalRead(Y_D5);
    int yD6 = digitalRead(Y_D6);
    int yD7 = digitalRead(Y_D7);
    int yD8 = digitalRead(Y_D8);

    int yValue = yA  + yB * 2 + yC * 4 + yD * 8;
    int xValue = xA  + xB * 2 + xC * 4 + xD * 8;

    if (xD1) xAxe[7] = xValue;
    if (xD2) xAxe[6] = xValue;
    if (xD3) xAxe[5] = xValue;
    if (xD4) xAxe[4] = xValue;
    if (xD5) xAxe[3] = xValue;
    if (xD6) xAxe[2] = xValue;
    if (xD7) xAxe[1] = xValue;
    if (xD8) xAxe[0] = xValue;

    if (yD1) yAxe[7] = yValue;
    if (yD2) yAxe[6] = yValue;
    if (yD3) yAxe[5] = yValue;
    if (yD4) yAxe[4] = yValue;
    if (yD5) yAxe[3] = yValue;
    if (yD6) yAxe[2] = yValue;
    if (yD7) yAxe[1] = yValue;
    if (yD8) yAxe[0] = yValue;
  }
}


void loop() {
  // readSC102data();
  readSC102data_X();
  readSC102data_Y();
  sendXYData();

  delay(100);//最高速度を1/10secに決めておく
}