文書の表示以前のリビジョンバックリンクPDF の出力全て展開する/折り畳むODT 出力文書の先頭へ この文書は読取専用です。文書のソースを閲覧することは可能ですが、変更はできません。もし変更したい場合は管理者に連絡してください。 ====== 簡易ワンショット・ロガー(PIC18F2620) ====== ===== 概要 ===== オシロスコープは、周期的な波形(繰り返し波形)を観測するにはとても重宝するツールです。 しかし、極たまにしか発生しない信号、1回きりの信号、トリガ前の信号などの波形観測には、あまり向いていません。 そこで、今回は、これらの問題を解決すべく、簡易ワンショット・ロガーを製作しました。 <仕様> * 入力チャネル→1CH * 入力電圧レベル→最大10V * サンプリング速度→高速モード(約60usec)、低速モード(約1msec) * サンプリング数→イベント前(190件)、イベント後(1710件) * 測定時間→高速モードで約114msec、低速モードで約1.9秒 * トリガモード→立ち上がり(500mV)、立下り(4500mV)、連続 * データ転送→RS232C、230400bps ===== 動作原理 ===== データを蓄積する方法としては、EEPROMやSDカードなどがありますが、何れも書き込み時間に数msecを要してしまいます。 そこでPIC18F2620が内蔵する約4kバイトのメモリのみを使用して高速な記録を行います。 <測定モード> ◎サンプリング速度(約60usec)、データ数(1900個)、記録時間(約114msec) * モード(01):スイッチ押下後直ちに記録を開始する。1900個のデータを記録すると停止する。 * モード(02):スイッチ押下後直ちに入力電圧をチェックし、入力電圧が500mVを上回ると、\\ 1900個のデータを記録し、停止する。 * モード(03):スイッチ押下後直ちに記録を開始する。\\ 190個のデータをエンドレスで記録する。\\ 入力電圧が500mVを上回ると、更に、1710個のデータを記録し、停止する。 * モード(04):スイッチ押下後直ちに入力電圧をチェックし、入力電圧が4500mVを下回ると、\\ 1900個のデータを記録し、停止する。 * モード(05):スイッチ押下後直ちに記録を開始する。\\ 190個のデータをエンドレスで記録する。\\ 入力電圧が4500mVを下回ると、更に、1710個のデータを記録し、停止する。 * モード(11):スイッチ押下後直ちに記録を開始する。\\ 1900個のデータをエンドレスで記録する。\\ スイッチが再度押下されると記録を停止する。 ◎サンプリング速度(約1msec)、データ数(1900個)、記録時間(約1.9sec) * モード(06):スイッチ押下後直ちに記録を開始する。1900個のデータを記録すると停止する。 * モード(07):スイッチ押下後直ちに入力電圧をチェックし、入力電圧が500mVを上回ると、\\ 1900個のデータを記録し、停止する。 * モード(08):スイッチ押下後直ちに記録を開始する。\\ 190個のデータをエンドレスで記録する。\\ 入力電圧が500mVを上回ると、更に、1710個のデータを記録し、停止する。 * モード(09):スイッチ押下後直ちに入力電圧をチェックし、入力電圧が4500mVを下回ると、\\ 1900個のデータを記録し、停止する。 * モード(10):スイッチ押下後直ちに記録を開始する。\\ 190個のデータをエンドレスで記録する。\\ 入力電圧が4500mVを下回ると、更に、1710個のデータを記録し、停止する。 * モード(12):スイッチ押下後直ちに記録を開始する。\\ 1900個のデータをエンドレスで記録する。\\ スイッチが再度押下されると記録を停止する。 |<400px>| ^ ^ SW1 ^ SW2 ^ SW3 ^ SW4 ^ ^ モード(01) | ON | ON | ON | ON | ^ モード(02) | OFF | ON | ON | ON | ^ モード(03) | ON | OFF | ON | ON | ^ モード(04) | OFF | OFF | ON | ON | ^ モード(05) | ON | ON | OFF | ON | ^ モード(06) | OFF | ON | OFF | ON | ^ モード(07) | ON | OFF | OFF | ON | ^ モード(08) | OFF | OFF | OFF | ON | ^ モード(09) | ON | ON | ON | OFF | ^ モード(10) | OFF | ON | ON | OFF | ^ モード(11) | ON | OFF | ON | OFF | ^ モード(12) | OFF | OFF | ON | OFF | <イベント前のデータ蓄積> イベント前(トリガレベルに達する前)のデータは、メモリをリングバッファ(ring buffer)として使用し、トリガレベルに達するまで、データをエンドレスに蓄積し続けます。(リングバッファのサイズは、190件) <イベント後のデータ蓄積> 単純にバッファサイズに達するまで、データを蓄積し続けます。(バッファのサイズは、1710件) <データ転送> 測定が完了すると、メモリ内のデータ(1900件)を、RS232C経由(通信速度230400bps)で、パソコンに転送します。転送フォーマットは次のようになります。(電圧の単位はmVです) <code> $START 1234.5 2345.6 : : $STOP </code> ===== 回路図 ===== {{:imgpaste:202004:admin-20200430-204036.png}} ===== ソースコード ===== ※開発環境には、「mikroC PRO」を使用しています。 <code c trigger_adc_v3.c> //********************************************************************** /* <簡易ワンショット・ロガー> ■動作モード ◎サンプリング速度(約50usec)、データ数(1900個)、記録時間(95msec) ・モード(01) スイッチ押下後直ちに記録を開始する。1900個のデータを記録すると停止する。 ・モード(02) スイッチ押下後直ちに入力電圧をチェックし、入力電圧が500mVを上回ると、 1900個のデータを記録し、停止する。 ・モード(03) スイッチ押下後直ちに記録を開始する。 190個のデータをエンドレスで記録する。 入力電圧が500mVを上回ると、更に、1710個のデータを記録し、停止する。 ・モード(04) スイッチ押下後直ちに入力電圧をチェックし、入力電圧が4500mVを下回ると、 1900個のデータを記録し、停止する。 ・モード(05) スイッチ押下後直ちに記録を開始する。 190個のデータをエンドレスで記録する。 入力電圧が4500mVを下回ると、更に、1710個のデータを記録し、停止する。 ・モード(11) スイッチ押下後直ちに記録を開始する。 1900個のデータをエンドレスで記録する。 スイッチが再度押下されると記録を停止する。 ◎サンプリング速度(約1msec)、データ数(1900個)、記録時間(1.9sec) ・モード(06) スイッチ押下後直ちに記録を開始する。1900個のデータを記録すると停止する。 ・モード(07) スイッチ押下後直ちに入力電圧をチェックし、入力電圧が500mVを上回ると、 1900個のデータを記録し、停止する。 ・モード(08) スイッチ押下後直ちに記録を開始する。 190個のデータをエンドレスで記録する。 入力電圧が500mVを上回ると、更に、1710個のデータを記録し、停止する。 ・モード(09) スイッチ押下後直ちに入力電圧をチェックし、入力電圧が4500mVを下回ると、 1900個のデータを記録し、停止する。 ・モード(10) スイッチ押下後直ちに記録を開始する。 190個のデータをエンドレスで記録する。 入力電圧が4500mVを下回ると、更に、1710個のデータを記録し、停止する。 ・モード(12) スイッチ押下後直ちに記録を開始する。 1900個のデータをエンドレスで記録する。 スイッチが再度押下されると記録を停止する。 */ //********************************************************************** #define LED PORTC.F0 #define SW_START PORTC.F1 #define SW_MODE_1 PORTC.F2 #define SW_MODE_2 PORTC.F3 #define SW_MODE_3 PORTC.F4 #define SW_MODE_4 PORTC.F5 #define BUFF_SIZE 1900 #define BEFOR_SIZE 190 #define AFTER_SIZE 1710 #define THRESHOLD_LOW ((500.0 / 4.8828125) / 2.0) #define THRESHOLD_HIGH ((4500.0 / 4.8828125) / 2.0) //********************************************************************** static int ad[BUFF_SIZE], befor_cnt, after_cnt, normal_cnt, tmp; static char buf[16]; //********************************************************************** void data_transfer_1() { static int cnt; // UART1_Write_Text("\r\n$START\r\n"); for (cnt = 0; cnt < BUFF_SIZE; cnt++) { WordToStr(((double)ad[cnt]) * 48.828125 * 2.0, buf); buf[6] = 0x00; buf[5] = buf[4]; buf[4] = '.'; UART1_Write_Text(buf); UART1_Write_Text("\r\n"); } UART1_Write_Text("$STOP\r\n"); } void data_transfer_2() { static int cnt; // UART1_Write_Text("\r\n$START\r\n"); for (cnt = 0; cnt < BEFOR_SIZE; cnt++) { tmp = ad[befor_cnt]; befor_cnt++; if (befor_cnt == BEFOR_SIZE) befor_cnt = 0; WordToStr(((double)tmp) * 48.828125 * 2.0, buf); buf[6] = 0x00; buf[5] = buf[4]; buf[4] = '.'; UART1_Write_Text(buf); UART1_Write_Text("\r\n"); } for (cnt = BEFOR_SIZE; cnt < (BEFOR_SIZE + AFTER_SIZE); cnt++) { WordToStr(((double)ad[cnt]) * 48.828125 * 2.0, buf); buf[6] = 0x00; buf[5] = buf[4]; buf[4] = '.'; UART1_Write_Text(buf); UART1_Write_Text("\r\n"); } UART1_Write_Text("$STOP\r\n"); } void data_transfer_3() { static int cnt; // UART1_Write_Text("\r\n$START\r\n"); for (cnt = 0; cnt < BUFF_SIZE; cnt++) { tmp = ad[normal_cnt]; normal_cnt++; if (normal_cnt == BUFF_SIZE) normal_cnt = 0; WordToStr(((double)tmp) * 48.828125 * 2.0, buf); buf[6] = 0x00; buf[5] = buf[4]; buf[4] = '.'; UART1_Write_Text(buf); UART1_Write_Text("\r\n"); } UART1_Write_Text("$STOP\r\n"); } //********************************************************************** void measurement_01() { for (normal_cnt = 0; normal_cnt < BUFF_SIZE; normal_cnt++) { ad[normal_cnt] = Adc_Read(0); } // LED = 1; data_transfer_1(); LED = 0; } void measurement_02() { after_cnt = 0; while (1) { tmp = Adc_Read(0); if (tmp > THRESHOLD_LOW) break; } // ad[after_cnt] = tmp; for (after_cnt++; after_cnt < BUFF_SIZE; after_cnt++) { ad[after_cnt] = Adc_Read(0); } // LED = 1; data_transfer_1(); LED = 0; } void measurement_03() { befor_cnt = 0; while (1) { tmp = Adc_Read(0); if (tmp > THRESHOLD_LOW) break; ad[befor_cnt] = tmp; befor_cnt++; if (befor_cnt == BEFOR_SIZE) { befor_cnt = 0; } } // after_cnt = BEFOR_SIZE; ad[after_cnt] = tmp; for (after_cnt++; after_cnt < (BEFOR_SIZE + AFTER_SIZE); after_cnt++) { ad[after_cnt] = Adc_Read(0); Delay_us(10); } // LED = 1; data_transfer_2(); LED = 0; } void measurement_04() { after_cnt = 0; while (1) { tmp = Adc_Read(0); if (tmp < THRESHOLD_HIGH) break; } // ad[after_cnt] = tmp; for (after_cnt++; after_cnt < BUFF_SIZE; after_cnt++) { ad[after_cnt] = Adc_Read(0); } // LED = 1; data_transfer_1(); LED = 0; } void measurement_05() { befor_cnt = 0; while (1) { tmp = Adc_Read(0); if (tmp < THRESHOLD_HIGH) break; ad[befor_cnt] = tmp; befor_cnt++; if (befor_cnt == BEFOR_SIZE) { befor_cnt = 0; } } // after_cnt = BEFOR_SIZE; ad[after_cnt] = tmp; for (after_cnt++; after_cnt < (BEFOR_SIZE + AFTER_SIZE); after_cnt++) { ad[after_cnt] = Adc_Read(0); Delay_us(10); } // LED = 1; data_transfer_2(); LED = 0; } void measurement_06() { for (normal_cnt = 0; normal_cnt < BUFF_SIZE; normal_cnt++) { ad[normal_cnt] = Adc_Read(0); Delay_us(1000 - 50); } // LED = 1; data_transfer_1(); LED = 0; } void measurement_07() { after_cnt = 0; while (1) { tmp = Adc_Read(0); if (tmp > THRESHOLD_LOW) break; } // ad[after_cnt] = tmp; Delay_us(1000 - 50); for (after_cnt++; after_cnt < BUFF_SIZE; after_cnt++) { ad[after_cnt] = Adc_Read(0); Delay_us(1000 - 50); } // LED = 1; data_transfer_1(); LED = 0; } void measurement_08() { befor_cnt = 0; while (1) { tmp = Adc_Read(0); if (tmp > THRESHOLD_LOW) break; ad[befor_cnt] = tmp; befor_cnt++; if (befor_cnt == BEFOR_SIZE) { befor_cnt = 0; } Delay_us(1000 - 60); } // after_cnt = BEFOR_SIZE; ad[after_cnt] = tmp; Delay_us(1000 - 60); for (after_cnt++; after_cnt < (BEFOR_SIZE + AFTER_SIZE); after_cnt++) { ad[after_cnt] = Adc_Read(0); Delay_us(1000 - 50); } // LED = 1; data_transfer_2(); LED = 0; } void measurement_09() { after_cnt = 0; while (1) { tmp = Adc_Read(0); if (tmp < THRESHOLD_HIGH) break; } // ad[after_cnt] = tmp; for (after_cnt++; after_cnt < BUFF_SIZE; after_cnt++) { ad[after_cnt] = Adc_Read(0); Delay_us(1000 - 50); } // LED = 1; data_transfer_1(); LED = 0; } void measurement_10() { befor_cnt = 0; while (1) { tmp = Adc_Read(0); if (tmp < THRESHOLD_HIGH) break; ad[befor_cnt] = tmp; befor_cnt++; if (befor_cnt == BEFOR_SIZE) { befor_cnt = 0; } Delay_us(1000 - 60); } // after_cnt = BEFOR_SIZE; ad[after_cnt] = tmp; Delay_us(1000 - 60); for (after_cnt++; after_cnt < (BEFOR_SIZE + AFTER_SIZE); after_cnt++) { ad[after_cnt] = Adc_Read(0); Delay_us(1000 - 50); } // LED = 1; data_transfer_2(); LED = 0; } void measurement_11() { normal_cnt = 0; while (SW_START == 1) { ad[normal_cnt] = Adc_Read(0); normal_cnt++; if (befor_cnt == BUFF_SIZE) { normal_cnt = 0; } } // LED = 1; data_transfer_3(); LED = 0; } void measurement_12() { normal_cnt = 0; while (SW_START == 1) { ad[normal_cnt] = Adc_Read(0); normal_cnt++; if (befor_cnt == BUFF_SIZE) { normal_cnt = 0; } Delay_us(1000 - 50); } // LED = 1; data_transfer_3(); LED = 0; } //********************************************************************** void SwitchONcheck() { while (Button(&PORTC, 1, 1, 0) == 0) ; while (Button(&PORTC, 1, 1, 1) == 0) ; } //********************************************************************** void main() { static short cnt; //ポートの設定 TRISA = 0b00111101; TRISB = 0b11000000; TRISC = 0b10111110; //コンパレータは使用しない。 CMCON.CM2 = 1; CMCON.CM1 = 1; CMCON.CM0 = 1; //A/D変換の設定 ADCON1.PCFG3 = 1; ADCON1.PCFG2 = 1; ADCON1.PCFG1 = 1; ADCON1.PCFG0 = 0; // UART1_Init(230400); Delay_ms(500); // for (cnt = 0; cnt < 5; cnt++) { LED = 1; Delay_ms(100); LED = 0; Delay_ms(100); } // while (1) { SwitchONcheck(); // switch ((PORTC >> 2) & 0x0F) { case 0: measurement_01(); break; case 1: measurement_02(); break; case 2: measurement_03(); break; case 3: measurement_04(); break; case 4: measurement_05(); break; case 5: measurement_06(); break; case 6: measurement_07(); break; case 7: measurement_08(); break; case 8: measurement_09(); break; case 9: measurement_10(); break; case 10: measurement_11(); break; case 11: measurement_12(); break; } } } //********************************************************************** </code> ===== 動作確認 ===== 少し大きめのブレッドボードで動作確認しました。 {{:imgpaste:202004:admin-20200430-204237.png?500}} 左側:LED、プッシュスイッチ、ディップスイッチを汎用的に使えるように、基板に実装しました。 右側:オペアンプ(LMC662)とPIC18F2620です。 {{:imgpaste:202004:admin-20200430-204250.png}}{{:imgpaste:202004:admin-20200430-204255.png}} 左側:RS232Cレベル変換用のトランジスタ(2SC1815)です。 右側:USBシリアル変換モジュールです。 {{:imgpaste:202004:admin-20200430-204311.png}}{{:imgpaste:202004:admin-20200430-204316.png}} ハイパーターミナルで、データを取り込みます。(テキストのキャプチャー機能を使います) {{:imgpaste:202004:admin-20200430-204328.png}} 取り込んだデータをグラフ表示させて見ました。 CR積分回路(100kΩ、0.1uF)の波形です。サンプリング周期=60usec、トリガレベル=500mV 上側:イベント後の波形です。※トリガレベル以前のデータを見ることが出来ません。 下側:イベント前後の波形です。 {{:imgpaste:202004:admin-20200430-204337.png?500}} {{:imgpaste:202004:admin-20200430-204351.png?500}} CR積分回路(100kΩ、1000pF)の波形です。サンプリング周期=60usec、トリガレベル=500mV 上側:イベント後の波形です。※トリガレベル以前のデータを見ることが出来ません。 下側:イベント前後の波形です。 {{:imgpaste:202004:admin-20200430-204405.png?500}} {{:imgpaste:202004:admin-20200430-204419.png?500}} CR積分回路(100kΩ、1.2uF)の波形です。サンプリング周期=60usec、トリガレベル=500mV 上側:イベント後の波形です。※トリガレベル以前のデータを見ることが出来ません。 下側:イベント前後の波形です。 {{:imgpaste:202004:admin-20200430-204429.png?500}} {{:imgpaste:202004:admin-20200430-204442.png?500}} CR積分回路(100kΩ、10uF)の波形です。サンプリング周期=1msec、トリガレベル=500mV 上側:イベント後の波形です。※トリガレベル以前のデータを見ることが出来ません。 下側:イベント前後の波形です。 {{:imgpaste:202004:admin-20200430-204454.png?500}} {{:imgpaste:202004:admin-20200430-204507.png?500}} トランス式ACアダプタ(上側)とスイッチング式ACアダプタ(下側)の立ち上がりの波形です。 {{:imgpaste:202004:admin-20200430-204519.png?500}} {{:imgpaste:202004:admin-20200430-204528.png?500}} <callout type="warning" title="著作権表示 copyright notice"> このページは稲崎様の閉鎖したHPのコピーで、著作権は稲崎様にあります。[[elechobby:picdic:picdic|詳細]] This page is a copy of Mr. Inasaki's closed website, and the copyright is held by him.[[elechobby:picdic:picdic|Details]] </callout> elechobby/picdic/otherpic/185.txt 最終更新: 2025/10/17 14:29by 127.0.0.1