====== 簡易ワンショット・ロガー(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です)
$START
1234.5
2345.6
:
:
$STOP
===== 回路図 =====
{{:imgpaste:202004:admin-20200430-204036.png}}
===== ソースコード =====
※開発環境には、「mikroC PRO」を使用しています。
//**********************************************************************
/*
<簡易ワンショット・ロガー>
■動作モード
◎サンプリング速度(約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;
}
}
}
//**********************************************************************
===== 動作確認 =====
少し大きめのブレッドボードで動作確認しました。
{{: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}}
このページは稲崎様の閉鎖した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]]