動作確認日2019/06/26
開発環境:
・Processing3.5.3
・M5STACK GRAY + Arduino IDE
目的:
マイコンのデータをシリアル通信で受け取って動作を確認する際に、一々グラフ描画するまでが面倒くさい。
→手っ取り早くデータの動きだけ見れるプログラムを作ろう!
Processingで構造体を受け取る方法が分からなかったので、シリアル通信を2Byte読んでint型を作るrecv_int関数と4Byte読んでlong型を作るrecv_long関数をそれぞれ実装しました。
マイコンで読み取る時間はmsとかが多いのでlong型、マイコンで読み取るデータとしてはAD値を想定してint型をそれぞれ受け取るサンプルブログラムが下になります。ちなみにProcessingではint型が4Byte扱えたはずなのでrecv_long関数なんて名前ですがint型で受け取ってます。(Arduino側がlong型で送ってたからこんな名前をつけたはず)
import processing.serial.*;
Serial port;
IntList time_list;
IntList data_list;
int GRAPH_HEIGHT = 400;
int GRAPH_WIDTH = 1000;
int GRAPH_OFFSETX = 40;
int GRAPH_OFFSETY = 50;
void setup () {
size (1200, 600);
port = new Serial (this, Serial.list ()[1], 115200);
time_list = new IntList();
data_list = new IntList();
}
void draw_graph(){
strokeWeight(4);
stroke(255, 89, 23);
for(int i=1; i< time_list.size(); i++){
PVector v1 = new PVector(GRAPH_OFFSETX + time_list.get(i-1) - time_list.min(), (height - GRAPH_OFFSETY) - data_list.get(i-1));
PVector v2 = new PVector(GRAPH_OFFSETX + time_list.get(i) - time_list.min(), (height - GRAPH_OFFSETY) - data_list.get(i));
line( v1.x, v1.y, v2.x, v2.y);
}
}
void draw_graph_outline(){
strokeWeight(5);
stroke(240, 240, 240);
PVector v1 = new PVector(GRAPH_OFFSETX, (height - GRAPH_OFFSETY));
PVector v2 = new PVector(GRAPH_OFFSETX, (height - GRAPH_OFFSETY) - GRAPH_HEIGHT);
PVector v3 = new PVector(GRAPH_OFFSETX + GRAPH_WIDTH, (height - GRAPH_OFFSETY));
line( v1.x, v1.y, v2.x, v2.y);
line( v1.x, v1.y, v3.x, v3.y);
}
void draw () {
background(45, 45, 45);
draw_graph_outline();
draw_graph();
}
int recv_int(Serial port){
int data1 = port.read();
int data2 = port.read();
int recv_data = data1 << 8 | data2 << 0 ;
return recv_data;
}
int recv_long(Serial port){
int data1 = port.read();
int data2 = port.read();
int data3 = port.read();
int data4 = port.read();
int recv_data = data1 << 24 | data2 << 16 | data3 << 8 | data4 << 0 ;
return recv_data;
}
void serialEvent (Serial port) {
if ( port.available() >= 7 ) {
if(port.read() == 'H'){
int recv_time = recv_long(port);
int recv_data = recv_int(port);
int time = (int)(recv_time / 10);
int data = (int)map(recv_data, 0, 4095, 0, GRAPH_HEIGHT);
time_list.append(time);
data_list.append(data);
if(time - time_list.min() > GRAPH_WIDTH){
time_list.remove(0);
data_list.remove(0);
}
print(recv_time);
print(",");
println(recv_data);
}
}
}
Processingの動作確認用に今回はM5STACKを使って、テキトーに正弦波をシリアル通信に垂れ流すプログラムを構築しました。
M5STACK側は構造体で送れたような気もしますが、頭を使いたくなかったのでProcessingと同じくwrite_int関数だのwrite_long関数だの実装してポチポチ送信しています。
#include<M5Stack.h>
int timer_begin = 0;
float pi = 3.14159265;
int counter = 0;
void setup() {
M5.begin();
Serial.begin(115200);
timer_begin = millis();
}
void write_long(long val, uint8_t d[4]){
uint32_t _data = val;
d[0] = (uint8_t)((_data >> 24) & 0xFF);
d[1] = (uint8_t)((_data >> 16) & 0xFF);
d[2] = (uint8_t)((_data >> 8) & 0xFF);
d[3] = (uint8_t)((_data >> 0) & 0xFF);
Serial.write(d[0]);
Serial.write(d[1]);
Serial.write(d[2]);
Serial.write(d[3]);
}
void write_int(int val, uint8_t d[2]){
uint32_t _data = val;
d[0] = (uint8_t)((_data >> 8) & 0xFF);
d[1] = (uint8_t)((_data >> 0) & 0xFF);
Serial.write(d[0]);
Serial.write(d[1]);
}
void loop() {
int send_data = 500 * sin(pi * counter / 100) + 2000;
counter++;
long timer = millis();
Serial.write('H');
byte data1[4];
byte data2[2];
write_long(timer-timer_begin, data1);
write_int(send_data, data2);
//uint8_t data0[6] = {data2[0], data2[1], data1[0], data1[1], data1[2], data1[3]};
//Serial.write(data0,6);
delay(10);
}