How2Computing

ArduinoとProcessingで超低速オシロスコープを作る

氏間さんに相談されて、 Arduinoで取得した複数個のアナログデータをPCにシリアルで転送して、 PCでグラフ化するプログラムを書いてみた。 こんなもの50分でできると見栄はったけど半日かかってしまった。 ProcessingのSerialのavailable()とreadStringUntil()の動作を理解する試行錯誤に手間がかかってしまった。

ここではArduinoのAnalog 0ピンの値を1msサンプリングレートで512個取得して (ArduinoのADCは10bitなので値は0から1023)、 これをシリアルで転送して、 Macintosh側のProcessingプログラムでグラフ化する。 超低速のオシロスコープ (Oscilloscope)のようなものである。

Aruduinoのプログラムは以下。 512個の値を測定したあと、これをテキストで転送している。 最初に+++を転送してから、最後に---を転送している。この間が数値。 改行はLine Feed (ASCIIコードで10) を使っている。 (mySerial.println()を使うと13, 10の2バイトが改行コードになるので面倒なので避けた) テキストで転送しているので、ここをバイナリーにすればもっと高速化できるはず。

int data[512];

void setup() {
  Serial.begin(38400);
  
}

void loop() {
  int i;
  
  Serial.print("+++"); Serial.write(10);

  for(i=0; i<512; i++) {
    data[i] = analogRead(0); 
    delay(1);
  }
  
  for(i=0; i<512; i++) {
    Serial.print(data[i]); 
    Serial.write(10);
  }
  Serial.print("---"); Serial.write(10);
  //delay(1000);
}

これを下のProcessingプログラムで表示したもの。 Analog 0を指で触ってノイズを入れてみた。 1msでサンプリングしているので、50Hzのノイズが多く現れていることがわかる。

http://is.ocha.ac.jp/~siio/gyazo/20140726200334.png

下はProcessingのソース。

import processing.serial.*;

final int dataSize=512; //size of data sent from Arduino
final int maxValue=1024; //max of data, 10bit ADC = 1023
final int xSize=dataSize; //screen size X
final int ySize=512; //screen size Y

Serial myPort; //seria port
int data[] = new int[dataSize]; //array to receive the data
int nth = 0; //index to handle the array
Boolean isDataStarted= false; //while data transmission, it becomes true

void setup() {
  myPort = new Serial(this, "/dev/tty.usbmodem3a11", 38400);
  myPort.clear();
  size(xSize, ySize);
  background(255);
}

int convertValue2ScreenX(int x) { //convert datat to screen
  return ( x * xSize / dataSize);
}

int convertValue2ScreenY(int y) {
  return ySize - (y * ySize / maxValue);
}

void draw() {
  String received; //received string from serial
  
  while(myPort.available()>0) { //while data is received
    received=myPort.readStringUntil(10);//read until Life Feed (10)
    if(received == null) continue; //if no data with line feed
    if(received.charAt(0)=='+') { //start of data
      isDataStarted=true; 
      nth=0;
      continue;
    }
    if(received.charAt(0)=='-') { //end of data
      int x, y, lastX, lastY;
      isDataStarted=false;
      background(255); //clear the screen
      //draw the graph
      lastX=convertValue2ScreenX(0);
      lastY=convertValue2ScreenY(data[0]);
      for(int i=1; i<dataSize; i++) {
        x=convertValue2ScreenX(i);
        y=convertValue2ScreenY(data[i]);
        line(lastX, lastY, x, y);
        lastX=x; lastY=y;
      }
      continue;
    }
    if(isDataStarted) {
      //remove the last char (line feed)
      if (nth >= dataSize) continue;
      received = received.substring(0, received.length() -1 );
      data[nth++] = parseInt(received);
      //println(data[nth - 1]);
    }
  } //end of while
}

同じような構成で本格的なオシロスコープ作った人がいた。

http://www.iizuka.kyutech.ac.jp/faculty/physicalcomputing/pc_kitscope/


トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2021-10-22 (金) 23:27:11