北東北 LabVIEWユーザー会

キャンセル
次の結果を表示 
次の代わりに検索 
もしかして: 

できるだけ高速にArduinoのアナログ入力でデータ収録する方法 (祝 "LabVIEW Community Edition")

おおはしさま

 

さっそく、

ダウンロードさせていただきました。ありがとうございました。

 

この「できるだけ高速にArduinoのアナログ入力でデータ収録する方法 」ですが、この延長上で、多チャンネル化は簡単にできるものでしょうか?

 

0 件の賞賛
メッセージ11/17
116件の閲覧回数

このトピックでは1チャンネルの場合で書いていますが、ボーレートが115200のときには1チャンネルで4kHzがほぼ限界でしたので、4チャンネルでは1kHz、8chで500Hzはチャレンジできると思います。Arduino側でサーキュラバッファに1chだけ書いている部分を1ch,2ch,3ch...8chのデータを書くように変更し、LabVIEW側でチャンネルごとのデータに戻して表示させればできるのではないかと思います。

 

すでに記憶が飛んでいますが、ボーレートとAD変換クロックを変えて10kHzまでできたと書いているので、8chで1.25kHzまではさらにチャレンジできるのではないかと思います。

 

このトピックではシリアル通信がネックになっているので、イーサネットあるいはWiFiでTCP通信を使えばもっと多チャンネル化、高速化できるだろうと思います。

UNOではありませんがESP32で試した例がありました。

ESP32(Arduino)でTCPサーバーを作ってLabVIEWでデータを受け取る  

 

 

0 件の賞賛
メッセージ12/17
108件の閲覧回数

おおはしさま

 

ありがとうございます。

 

1kHz/4Chができれば十分です。

 

ためしに、1kHz/2Chをarduinoで書いてみました(下記)。

これでarduinoの方は動作はするようなのですが、LabVIEWで2Chの波形として表示できていません。

---

//analog read 1kHz and Serial Out 2Ch
//Arduino UNO
//MaDA Lab Koji Ohashi 2019.10.23/ Modified by Kintad

#include <TimerOne.h>

volatile int arrayIndex = 0;  //index of last measurement
const int T1_us=1000;         //timer1 interrupt interval (microseconds)---1kHz
const int SizeTx=30;          //serial out max data block size
const int SizeBuffer=128;     //analog read circular buffer size
const int margin=5;           //margin of data block
byte data1[(SizeTx+2)*2];      //serial out block array
byte data2[(SizeTx+2)*2];      //serial out block array
int circular1[SizeBuffer];     //circular buffer array
int circular2[SizeBuffer];     //circular buffer array
int startIndex=0;             //next serial out position of circular buffer

void setup() {
  Serial.begin(115200);
  Serial.println("Continuous_AnalogIn4kHz_SerialOut");
 
  Timer1.initialize(T1_us);
  Timer1.attachInterrupt(readAnalog);
  delay((SizeTx-margin)*T1_us/1000);
}

void readAnalog(){
  circular1[arrayIndex] = analogRead(A0);
  circular2[arrayIndex] = analogRead(A1);
  arrayIndex=(arrayIndex+1)%SizeBuffer;
}

void loop() {
  int actSizeTx, readIndex;
  noInterrupts();
  int currentIndex=(arrayIndex-1)%SizeBuffer;
  interrupts();
  if(currentIndex>=startIndex){
    actSizeTx=currentIndex-startIndex+1;
  } else{
    actSizeTx=currentIndex + SizeBuffer - startIndex+1;
  }
  data1[0]=255;
  data1[1]=255;
  data1[2]=0;
  data1[3]=actSizeTx;
  data2[0]=255;
  data2[1]=255;
  data2[2]=0;
  data2[3]=actSizeTx;
  for(int i=0; i<actSizeTx; i++){
    readIndex=(startIndex+i)%SizeBuffer;
    int sensor1Value = circular1[readIndex];
    int sensor2Value = circular2[readIndex];
    data1[(i+2)*2]= byte(sensor1Value >> 8);
    data1[(i+2)*2+1]= byte(sensor1Value & 0x00FF);
    data2[(i+2)*2]= byte(sensor2Value >> 8);
    data2[(i+2)*2+1]= byte(sensor2Value & 0x00FF);
  }
  Serial.write(data1,(actSizeTx+2)*2);
  Serial.write(data2,(actSizeTx+2)*2);
  startIndex=(readIndex+1)%SizeBuffer;
  delay(1);
}
0 件の賞賛
メッセージ13/17
102件の閲覧回数

Arduinoプログラムでは

サーキュラーバッファを追加するのではなく、元からある1本のサーキュラーバッファに2チャンネルのデータを交互に書き込むようにします。その方が送受信に関するプログラムの変更が少なくて済むと思います。

 

1チャンネル目を従来の信号、2チャンネル目を0V(GND)にすると、何も変更していないLabVIEW側でデータ1個おきに0Vで表示されるようになるはずです。そのようになっていれば1個おきにデータを取り出すのはLabVIEWでは比較的簡単です。

0 件の賞賛
メッセージ14/17
98件の閲覧回数

おおはしさま

 

最終的には、LabVIEWの出力あるいは、Arduinoの出力をそのまま、既に開発済みのMFC(C++)のWINDOWS Desktop解析アプリに取り込む予定なのです。ですので、LabVIEWは確認用と思っています。

0 件の賞賛
メッセージ15/17
89件の閲覧回数

WINDOWS Desktop解析アプリでは、

チャンネル1のN個のデータに続いてチャンネル2のN個のデータをシリアルポートで受け取りたい

ということでしょうか。

なるほど。

 

現状の2チャンネルのArduinoプログラムの場合、LabVIEWプログラムではどのようなデータを受け取っているのでしょうか?

想定と違うものが送られてきてうまく受け取れていないのでしょうか?

0 件の賞賛
メッセージ16/17
85件の閲覧回数

おおはしさま

 

そのWindows Desktopアプリのおおもとは私が作ったものではなくて、私は、改良を下に過ぎないのです。Desktopアプリは、nRF52マイコンの出力をUSBシリアル経由でパケットデータとして受け取っています。この書式をまだ理解してないので、引き続き、ここを攻めようと考えています。

 

明日はいちにち新幹線で遠くへ出張なので、ここらへんのソースを持っていって、うまくいきそうであれば、Arduinoの出力をこれに合わせられればと考えています。

 

「現状の2チャンネルのArduinoプログラムの場合、LabVIEWプログラムではどのようなデータを受け取っているのでしょうか?想定と違うものが送られてきてうまく受け取れていないのでしょうか?」についても考えてみようと思っています。

0 件の賞賛
メッセージ17/17
79件の閲覧回数