文書の表示以前のリビジョンバックリンクPDF の出力全て展開する/折り畳むODT 出力文書の先頭へ この文書は読取専用です。文書のソースを閲覧することは可能ですが、変更はできません。もし変更したい場合は管理者に連絡してください。 ====== アナログデータロガー(複数PIC使用) ====== ===== 概要 ===== 最近の殆どのPICには、A/Dコンバータが標準で実装されているので、簡単なロガーであれば容易に実現可能です。 しかし、チャネル数としては、現時点で入手が容易な、40ピンのPIC18F4550でも、13チャネルが最大です。 測定の分野によっては、もう少しチャネル数が必要となる場合があります。 そこで今回は、複数のPICを組み合わせることにより、**最大49チャネル**のアナログデータロガーを製作してみました。 <仕様> * チャネル数は、最小7チャネル、最大49チャネルとします。(7チャネル×7PIC) * A/D変換の精度は10ビットとします。 * 測定データは、パソコンにRS232C経由で転送します。(9600bps) * PICを最大、8個使用し、全体の制御は、MASTER/SLAVE方式(ポーリング)とします。 * 一つのPICに、MASTERの機能とSLAVEの機能を実装し、起動時に選択可能とします。 ===== 動作原理 ===== MASTER配下には、最大7台のSLAVEをシリアル(USART)で接続します。各SLAVEには、アドレス(1~7)が割り当てられます。(各SLAVEのスイッチで設定する) * 全てのSLAVEのRx(受信信号)は一つにつながれ、MASTERのTx(送信信号)に接続されます。\\ ※つまり全てのSLAVEが、MASTERからの制御コードを同時に受信することができます。 * 全てのSLAVEのTx(送信信号)は一つにつながれ、MASTERのRx(受信信号)に接続されます。\\ ※PICのTxピンは、出力モードなので、直接にTx同士を繋ぐと、PICが破壊されてしまいます。\\ ※そこで、トランジスタによる非反転回路をかませることにより、破壊を防止します。\\ ※回路の簡素化のために、1個のトランジスタ(2SA1015)による非反転回路(1)を採用しました。 <MASTER> - スレーブ(アドレス=1)に対して、データ要求の制御コードを送信します。(9600bps) - スレーブ(アドレス=1)より、ETB(End of Transmission Block)コードが来るまで、データを受信します。 - 受信したデータを、パソコンにRS232C経由で送信します。(9600bps) - 受信したデータを、LCDに表示します。 - 1.~4.の処理を、スレーブ数分だけ繰り返します。(スレーブ数は、スイッチで指定します) <SLAVE> - MASTERからの、制御コードを受信します。 - 制御コードが、自分宛で無ければ無視します。(スレーブのアドレスは、スイッチで指定します) - 制御コードが、自分宛であれば、CH1~CH7までをA/D変換します。(このときLEDを点灯させます) - 変換したデータを、MASTERに送信します。 - データの最後を示す、ETBコードを、MASTERに送信します。 - 1.に戻ります。 <MASTERとSLAVEの接続> {{:imgpaste:202004:htmikan-20200430-131924.png?500}} <制御コードのフォーマット> {{:imgpaste:202004:htmikan-20200430-131932.png?500}} <トランジスタによる非反転回路>※PICのTxピン同士の接続のために必要となります。 {{:imgpaste:202004:htmikan-20200430-131940.png?500}} ===== 回路図 ===== {{:imgpaste:202004:htmikan-20200430-131952.png}} ===== ソースコード ===== <code c ad_logger_multi_pic.c> //********************************************************************** /* 「ADロガー(マルチPIC)」 */ //********************************************************************** //master & slave #define SW_MODE PORTA.F5 //master #define LCD_D6 PORTA.F0 #define LCD_D7 PORTA.F1 #define SW PORTA.F2 #define SW_ADDR0M PORTA.F3 #define SW_ADDR1M PORTA.F4 #define LCD_D5 PORTA.F6 #define LCD_D4 PORTA.F7 #define Rx_1 PORTB.F0 #define Tx_1 PORTB.F1 #define Rx_2 PORTB.F2 #define SW_ADDR2M PORTB.F3 #define LCD_RS PORTB.F4 #define Tx_2 PORTB.F5 #define LCD_RW PORTB.F6 #define LCD_E PORTB.F7 //slave #define AN0 PORTA.F0 #define AN1 PORTA.F1 #define AN2 PORTA.F2 #define AN3 PORTA.F3 #define AN4 PORTA.F4 #define NON_1 PORTA.F6 #define NON_2 PORTA.F7 #define SW_ADDR0S PORTB.F0 #define SW_ADDR1S PORTB.F1 #define Rx PORTB.F2 #define SW_ADDR2S PORTB.F3 #define LED PORTB.F4 #define Tx PORTB.F5 #define AN5 PORTB.F6 #define AN6 PORTB.F7 #define CR 0x0D #define LF 0x0A #define ETB 0x23 //********************************************************************** static char msg[48], buf[16]; //********************************************************************** void Usart_Write_Str(unsigned short *pData) { while (*pData != 0x00) { Usart_Write(*pData); pData++; Delay_ms(10); } } //********************************************************************** void master() { static unsigned short rd, *rec, len, addr, addr_max, hd; static unsigned int cnt; // addr_max = 0; addr_max.F0 = SW_ADDR0M; addr_max.F1 = SW_ADDR1M; addr_max.F2 = SW_ADDR2M; // cnt = 0; // while (1) { if (SW == 0) { while (SW == 0) { Delay_ms(100); } // while (1) { for (addr = 1; addr <= addr_max; addr++) { hd = addr << 4; hd.F7 = 1; Soft_Uart_Write(hd); // len = 0; while (1) { rd = Soft_Uart_Read(rec); if (rd == ETB) { msg[len] = 0x00; break; } msg[len] = rd; len++; } Usart_Write_Str(msg); // Lcd_Custom_Chr(1, 9 + addr, 0xFF); // msg[16] = 0x00; Lcd_Custom_Out(2, 1, msg); } Usart_Write(CR); Usart_Write(LF); // cnt++; WordToStr(cnt, buf); Lcd_Custom_Out(1, 1, buf); Lcd_Custom_Out(1, 10, " "); // if (SW == 0) { while (SW == 0) { Delay_ms(100); } cnt = 0; break; } // Delay_ms(100); } } } } //********************************************************************** void slave() { static unsigned short addr, hd, rd; static double ad; // addr = 0; addr.F0 = SW_ADDR0S; addr.F1 = SW_ADDR1S; addr.F2 = SW_ADDR2S; hd = addr << 4; hd.F7 = 1; // LED = 0; while (1) { //ヘッダーの受信 if (Usart_Data_Ready() == 0) continue; rd = Usart_Read(); if (rd.F7 != 1) continue; if ((rd & 0xF0) != (hd)) continue; // LED = 1; // ad = Adc_Read(0); ad = ad * 4.8828125; WordToStr(ad, msg); Usart_Write_Str(msg); // ad = Adc_Read(1); ad = ad * 4.8828125; WordToStr(ad, msg); Usart_Write_Str(msg); // ad = Adc_Read(2); ad = ad * 4.8828125; WordToStr(ad, msg); Usart_Write_Str(msg); // ad = Adc_Read(3); ad = ad * 4.8828125; WordToStr(ad, msg); Usart_Write_Str(msg); // ad = Adc_Read(4); ad = ad * 4.8828125; WordToStr(ad, msg); Usart_Write_Str(msg); // ad = Adc_Read(5); ad = ad * 4.8828125; WordToStr(ad, msg); Usart_Write_Str(msg); // ad = Adc_Read(6); ad = ad * 4.8828125; WordToStr(ad, msg); Usart_Write_Str(msg); // Usart_Write(ETB); // LED = 0; } } //********************************************************************** void main() { static short mode, cnt; // OSCCON = 0b01110000; CMCON = 0b00000111; mode = SW_MODE; if (mode == 1) { ANSEL = 0b00000000; TRISA = 0b00111100; TRISB = 0b00001101; } else { ANSEL = 0b01111111; TRISA = 0b11111111; TRISB = 0b11001111; } //USARTの初期化 Usart_Init(9600); if (mode == 1) { Soft_Uart_Init(PORTB, 0, 1, 9600, 0); } // if (mode == 1) { //masterモード Lcd_Custom_Config(&PORTA, 1, 0, 7, 6, &PORTB, 4, 6, 7); Lcd_Custom_Cmd(LCD_CURSOR_OFF); Lcd_Custom_Cmd(LCD_CLEAR); Lcd_Custom_Out(1, 1, "ad-logger(49ch)"); Lcd_Custom_Out(2, 1, " multi pic"); Delay_ms(1000); Lcd_Custom_Cmd(LCD_CLEAR); // master(); } else { //slaveモード for (cnt = 0; cnt< 10; cnt++) { LED = 1; Delay_ms(50); LED = 0; Delay_ms(50); } // slave(); } } //********************************************************************** </code> ===== 動作確認 ===== 左側から、SLAVE(2)、SLAVE(1)、MASTER、LCDです。 この回路では、SLAVEを2台にしました。 従って、14チャネルのアナログデータをロギングすることが出来ます。 MASTER側のスイッチ(ADDR0~ADDR2)で、SLAVEが2台接続されていることを指定します。 {{:imgpaste:202004:htmikan-20200430-132159.png?500}} 左側:非反転回路(2SA1015×2個)です。 右側:RS232Cレベル変換回路(2SC1815)とDSUB-9Pのコネクタです。 {{:imgpaste:202004:htmikan-20200430-132209.png}}{{:imgpaste:202004:htmikan-20200430-132214.png}} MASTER側のLCDの表示内容です。 LCDの左上は、SLAVEからのデータの受信カウント数です。 LCDの右上は、どのSLAVEとやり取りをしているかを示すマークです。SLAVE数に応じて増えていきます。 LCDの2行目は、SLAVEから送られてくるデータ(7CH分)の内の、CH1~CH3の値です。 {{:imgpaste:202004:htmikan-20200430-132224.png}}{{:imgpaste:202004:htmikan-20200430-132228.png}} SLAVE側の様子です。LEDが点灯しているSLAVEが、MASTERとやり取りをしています。 {{:imgpaste:202004:htmikan-20200430-132235.png}}{{:imgpaste:202004:htmikan-20200430-132238.png}} MASTERが、パソコンにデータを送っている様子です。 ハイパーターミナルで、受信データを表示させて見ました。左側からCH1~CH14です。 {{:imgpaste:202004:htmikan-20200430-132246.png}} 受信したデータを、Excelでグラフ表示させて見ました。 入力がオープン状態なので、ノイズ成分が含まれています。 {{:imgpaste:202004:htmikan-20200430-132252.png}} 如何ですか? 制御コードには、予備用のビットがまだありますので、SLAVE数を増やしたり、機能コードを追加することにより、いろいろな拡張が考えられます。 <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/pic16f88/131.txt 最終更新: 2025/10/17 14:29by 127.0.0.1