簡易ワンショット・ロガー(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個のデータをエンドレスで記録する。
    スイッチが再度押下されると記録を停止する。
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です)

$START
1234.5
2345.6
:
:
$STOP

※開発環境には、「mikroC PRO」を使用しています。

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;
                }
        }
}
 
//**********************************************************************

少し大きめのブレッドボードで動作確認しました。

左側:LED、プッシュスイッチ、ディップスイッチを汎用的に使えるように、基板に実装しました。
右側:オペアンプ(LMC662)とPIC18F2620です。

左側:RS232Cレベル変換用のトランジスタ(2SC1815)です。
右側:USBシリアル変換モジュールです。

ハイパーターミナルで、データを取り込みます。(テキストのキャプチャー機能を使います)

取り込んだデータをグラフ表示させて見ました。
CR積分回路(100kΩ、0.1uF)の波形です。サンプリング周期=60usec、トリガレベル=500mV
上側:イベント後の波形です。※トリガレベル以前のデータを見ることが出来ません。
下側:イベント前後の波形です。

CR積分回路(100kΩ、1000pF)の波形です。サンプリング周期=60usec、トリガレベル=500mV
上側:イベント後の波形です。※トリガレベル以前のデータを見ることが出来ません。
下側:イベント前後の波形です。

CR積分回路(100kΩ、1.2uF)の波形です。サンプリング周期=60usec、トリガレベル=500mV
上側:イベント後の波形です。※トリガレベル以前のデータを見ることが出来ません。
下側:イベント前後の波形です。

CR積分回路(100kΩ、10uF)の波形です。サンプリング周期=1msec、トリガレベル=500mV
上側:イベント後の波形です。※トリガレベル以前のデータを見ることが出来ません。
下側:イベント前後の波形です。

トランス式ACアダプタ(上側)とスイッチング式ACアダプタ(下側)の立ち上がりの波形です。

著作権表示 copyright notice

このページは稲崎様の閉鎖したHPのコピーで、著作権は稲崎様にあります。詳細
This page is a copy of Mr. Inasaki's closed website, and the copyright is held by him.Details
  • elechobby/picdic/otherpic/185.txt
  • 最終更新: 2025/10/17 14:29
  • by 127.0.0.1