モジュラーマルチチャンネルADCの作成

さまざまなプロジェクトでは、多くの場合、アナログ値で表される多くのパラメーターを監視する必要があります。 もちろん、マイクロコントローラーで十分な場合もよくありますが、処理アルゴリズムが複雑すぎて、本格的なコンピューターの使用が必要になる場合があります。 さらに、ログの保存と美しいデータの視覚化がはるかに簡単になります。 この場合、既成の産業用ソリューション(もちろん高価ですが、多くの場合冗長です)が採用されるか、または自家製の何かが行われます。 最も一般的なケースでは、analogReadとserial.writeからの無限ループを持つArduinoボードです。 多くの入力データ(アナログ入力よりも多い)が​​ある場合、いくつかのボードが必要になり、コンピューターからそれらを正しく調べる方法などを見つけます。この質問)、デバッグの時間を節約し、比較的単純で明確なシステムアーキテクチャを作成します。







このソリューションがあなたに適しているかどうかを理解するために、その特性に慣れることをお勧めします。



チャネルの最大数: 44。

サンプリングレート: 1000ヘルツ;

解像度: 8ビット。



特性はどちらかと言えば平凡ですが、多くのタスクに適しています。 これはオシロスコープではなく、センサー尋問システムです。 さらに、彼女の例では、他の目的でUSARTを使用する方法を知ることができます。



システムは、ATMEGA8マイクロコントローラーに基づいた個別のADCモジュールで構成されます(ファームウェアを少し変更する場合、ADCとUSARTハードウェアモジュールでAVRファミリーの別のMKを使用できます)。 1つまたは複数のモジュールがあり、それぞれがマイクロコントローラーのケースに応じて6または8個のADCを提供します(出力バージョンには6個のADCがあり、表面実装用には8個)。チャンネルの合計数は44を超えてはなりません。モジュールの数に必要なのは、コンピューター側から1つのUSARTのみです(これはUSBアダプターまたはハードウェアCOMポートの場合があります)。 これは、すべてのマイクロコントローラーのUSARTが直列に接続され(一方のRXが他方のTXに)、チェーンの最後のRXおよびTXピンが既にコンピューターに接続されているという事実により達成されます。



ここで、ADCの解像度は正確に8ビットではなく、256階調ではなく255階調にすぎないことに注意してください。値0xFFは特別な目的のために予約されています。 マイクロコントローラーがそれを受け取ると、ADCの次のチャネルから毎回値を提供し始め、それらが終了すると、チェーンのさらに下の0xFFを中継します。 0xFF以外の値がUSART入力に到着すると、チップは単にバイトをさらに送信します。 したがって、1つの任意の値と44 0xFFを渡すと、すべてのADCのすべてのチャネルから値を取得できます(ADCが小さい場合、余分なチャネルは0xFFになります)。 すべてのモジュールが0xFFを受信したときに送信する必要がある現在のADCチャネルへのポインターをリセットするために、任意の値が必要です。 実際には、45 0xFFを送信して受信の終了を確実に判断する方が便利です(0xFFを受信した場合、チャネルは終了しています)。



回路図にはあまり多くの詳細が含まれていません。





AVRのプログラムは非常にシンプルに見え、300バイト弱のメモリを使用します。



#include <avr/io.h> #include <avr/interrupt.h> #include <avr/wdt.h> #include <util/delay.h> // Firmware options #define USART_BAUDRATE 460800 #define LED_PIN 1 #define ADC_COUNT 6 #define STARTUP_DELAY 1000 // Calculated UBRR value #define UBRR (F_CPU / (16 * (uint32_t)USART_BAUDRATE) - 1) // Global variables uint8_t adc[ADC_COUNT]; // Buffer uint8_t cur_in_adc; // Input byte index uint8_t cur_out_adc; // Output byte index // USART interrupt handler ISR(USART_RXC_vect) { // Read data from USART uint8_t buffer = UDR; if (buffer == 0xFF) { if (cur_out_adc < ADC_COUNT) { // Return data byte from buffer UDR = adc[cur_out_adc]; cur_out_adc++; // Activate led PORTB |= _BV(LED_PIN); } else { // Chain 0xFF UDR = 0xFF; // Deactivate led PORTB &= ~_BV(LED_PIN); } } else { // Chain data byte UDR = buffer; // Reset byte counter cur_out_adc = 0; // Deactivate led PORTB &= ~_BV(LED_PIN); } } // Main function void main() { // Setup watchdog timer wdt_enable(WDTO_15MS); // Setup pin for led DDRB |= _BV(LED_PIN); // Blink led PORTB |= _BV(LED_PIN); for (uint8_t i = 0; i < STARTUP_DELAY / 5; i++) { _delay_ms(5); wdt_reset(); } PORTB &= ~_BV(LED_PIN); // Setup ADC ADMUX = _BV(REFS1) | _BV(REFS0) | _BV(ADLAR); ADCSRA = _BV(ADEN) | _BV(ADPS2) | _BV(ADPS1) | _BV(ADPS0); // Setup USART UBRRL = UBRR & 0xFF; UBRRH = UBRR >> 8; UCSRA = 0; UCSRB = _BV(RXCIE) | _BV(RXEN) | _BV(TXEN); UCSRC = _BV(URSEL) | _BV(UCSZ1) | _BV(UCSZ0); // Enable interrupts sei(); // Main loop while (1) { // Reset watchdog timer wdt_reset(); // Select ADC channel ADMUX = _BV(REFS1) | _BV(REFS0) | _BV(ADLAR) | cur_in_adc; // Start conversion and wait until it performed ADCSRA |= _BV(ADIF) | _BV(ADSC); while (ADCSRA & _BV(ADSC)); // Put value from ADC to buffer uint8_t value = ADCH; adc[cur_in_adc] = (value != 0xFF) ? value : 0xFE; // Switch to next channel cur_in_adc++; if (cur_in_adc >= ADC_COUNT) { cur_in_adc = 0; } } }
      
      







GitHubリポジトリには、KiCadの回路ファイルと回路基板ファイル、およびこのシステムからデータを読み取りCSV形式で出力するコンピューター用のサンプルプログラムがあります。



シリアルポートはほぼその能力の限界まで使用されるため、データの同期を心配する必要はありません(ADCを読み取るために1000コマンドを送信するだけです)-毎秒460800ビットの速度で毎秒46キロバイトのデータを送信すると、 46バイトのデータブロック(1回の測定)がミリ秒ごとに到着することを完全に確認してください(OSカーネルとUSBアダプターでのバッファリングはもちろん遅延をもたらしますが、測定は常に正しい周波数で実行されます)。



回路基板はKiCadで設計されました。







すべてのボードはチェーンで接続され、最後のボードでRXとTXはジャンパーで接続されます。

ADCの品質は、10 Hzのこぎりのこの画像から推定できます。







比較のため、DS203オシロスコープの画像(ジェネレーターとしても機能します):







残念ながら、より良い信号源はありませんが、低周波信号の場合、システムは動作するはずです。



すべてのUSART-USBコンバーターがフルチャネルロードで460800 bpsの速度を提供するわけではないことに注意してください。 CP2102ベースのコンバーターにより、FT232を試すまで、長い間、自分のコードのエラーを探すことができました。 また、データの約0.17%の損失が観察されます(データ同期が失われないようにコンピュータープログラムで対策が取られました)。 ほとんどの場合、これは悪いUSARTライン、またはプログラムの欠陥が原因です。 一般に、アプリケーションの90%については重要ではありませんが、ほとんどの場合、原子力発電所に置く価値はありません。



そして最後に、すべての部品を中国から注文する場合、1つのモジュールのコストは約50〜60ルーブルであるため、このソリューションは非常に魅力的です。



All Articles