IoTの全体像の例「照度センサーの情報を表示する」
http://ameblo.jp/smeokano/entry-12240624461.html
の続きです。上記のエントリーで
「それぞれの詳しいプログラムは、後日、この下に掲示します。」
とありますが、その「詳しいプログラム」第一弾、センサー部分です。
●センサー部概要
センサー部は、
1.センサー
2.マイコン
3.通信モジュール
からなります。
1.センサーは、「照度センサーの例」ですので、照度センサーNJL7502L
を使いました。秋葉原のマルツで購入。使い方の詳細は
照度センサ(フォト・トランジスタ)NJL7502L
http://www.eleki-jack.com/akifan/2012/08/njl7502l.html
2.マイコンは、今回、PIC12F1822を利用しました。
照度センサーのデータをアナログ入力し(RA1から入力)、
RS485通信でデータを送信している。スピードは57600
TXはRA4,RXはRA5、DE/REは一緒にしてRA2で制御している
通信内容は、
・GWから、0x02または$ではじまり
0x03または#で終わる電文を受信したら
→data_getの処理
・GWへ、0x02を送信した後、
→data_getの処理
・GWへ、0x02を送信した後、
アナログ値を4桁で送信後、
0x03を送信している
→data_sendの処理
・送信するにはRA2を1、受信するにはRA2を0にする。
・なお、RA2のピン切り替え後、10マイクロ秒待っている。
こんなに待たなくていいかも
・送信後、380μ秒待っているのは、
→data_sendの処理
・送信するにはRA2を1、受信するにはRA2を0にする。
・なお、RA2のピン切り替え後、10マイクロ秒待っている。
こんなに待たなくていいかも
・送信後、380μ秒待っているのは、
バッファに残っているデータを送りきるため
2つのバッファがあること、
2つのバッファがあること、
スピードが57600
であることから、この時間待ってる
秋月のネット販売で購入
http://akizukidenshi.com/catalog/g/gI-04557/
3.通信モジュールは、RS485ということで、
TIのsn75176bpを秋月のネット販売で購入
http://akizukidenshi.com/catalog/g/gI-07430/
●プログラム
プログラムとして組めるのは、マイコン部分。
マイコン部分のプログラムは、以下のような感じ(青字がプログラム)
/*
* File: main.c
* アナログセンサー送信:RS-485 57600ボーレート
* 1 VDD 8 VSS
* RX 2 RA5 7 RA0
* TX 3 RA4 6 RA1 AN1
* 4 MCLR 5 RA2 DE/RE
*
*/
#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
#define _XTAL_FREQ 8000000 // delay用に必要(クロック8MHzを指定)
// コンフィギュレーション1の設定
#pragma config FOSC = INTOSC // 内部クロック使用する(INTOSC)
#pragma config WDTE = OFF // ウオッチドッグタイマー無し(OFF)
#pragma config PWRTE = ON // 電源ONから64ms後にプログラムを開始する(ON)
#pragma config MCLRE = OFF // 外部リセット信号は使用せずにデジタル入力(RA3)ピンとする(OFF)
#pragma config CP = OFF // プログラムメモリーを保護しない(OFF)
#pragma config CPD = OFF // データメモリーを保護しない(OFF)
#pragma config BOREN = ON // 電源電圧降下常時監視機能ON(ON)
#pragma config CLKOUTEN = OFF // CLKOUTピンをRA4ピンで使用する(OFF)
#pragma config IESO = OFF // 外部・内部クロックの切替えでの起動はなし(OFF)
#pragma config FCMEN = OFF // 外部クロック監視しない(OFF)
// コンフィギュレーション2の設定
#pragma config WRT = OFF // Flashメモリーを保護しない(OFF)
#pragma config PLLEN = OFF // PLLイネーブル(OFF)
#pragma config STVREN = ON // スタックがオーバフローやアンダーフローしたらリセットをする(ON)
#pragma config BORV = HI // 電源電圧降下常時監視電圧(2.5V)設定(HI)
#pragma config LVP = OFF // 低電圧プログラミング機能使用しない(OFF)
//=====================================//
// グローバル宣言 //
//=====================================//
unsigned char buf[16];
int sts = 0;
int len = 0;
void putch(unsigned char ch) {
}
//=====================================//
// 受信部分 //
//=====================================//
int data_get(char RxData)
{
if ( sts == 0)
{
if ( (RxData == 0x2) || (RxData == '$') )
{
buf[len] = RxData;
len++;
sts = 1;
}
}
else
{
buf[len] = RxData;
len++;
if ( ( RxData == 0x3) || (RxData == '#') )
{
len = 0;
sts = 0;
data_send();
}
if ( len > 14 ) // データが長すぎる:壊れた?
{
buf[15] = 0;
len = 0;
sts = 0;
data_send();
}
}
return 0;
}
//=====================================//
// データ送信部分 //
//=====================================//
int data_send()
{
// DE切り替え
RA2=1; // DE=ON(送信モード)
__delay_us(10); // 切り替え待ち(こんなにいらない?)
buf[0] = 0x02;
// アナログデータ受信
GO = 1; // AD変換開始
while(GO); // AD変換終了待ち
sprintf(&(buf[1]),"%04d",ADRES); // AD変換結果送信
buf[5] = 0x03;
buf[6] = 0;
// データ送信
for( int i = 0 ; i < 6 ; i ++)
{
while (!TXIF); //送信待ち
TXREG = buf[i];
}
__delay_us(380); // 2文字程度待つ
RA2=0; // DE=OFF(受信モード)
__delay_us(10); // 切り替え待ち(こんなにいらない?)
len = 0;
sts = 0;
return 0;
}
//=====================================//
// USART通信の受信割込み処理 //
//=====================================//
void interrupt InterReceiver( void )
{
char RxData;
if (RCIF == 1) { // 割込みはUSART通信の受信か?
RxData=RCREG; // DE=OFF(受信モード)
RCIF = 0;
if (RxData != 0)
{
data_get(RxData);
}
}
}
//=====================================//
// メインプログラム:ここから始まる //
//=====================================//
void main() {
// 全体的な指定
OSCCON = 0b01110010; // 内部クロック8Mhz
PORTA = 0b00000000;
TRISA = 0b11111011; //RA2:出力 他は入力
nWPUEN = 0;
// UART関連レジスタ設定
RCSTA = 0b10010000; // 8 bit 連続受信
TXSTA = 0b00100100; // 2:BRGH
BAUDCON = 0b00001000; // 3:16 bit SPBRG
RXDTSEL = 1 ; // 2番ピン(RA5)をRX受信ピンとする
TXCKSEL = 1 ; // 3番ピン(RA4)をTX送信ピンとする
SPBRGH = 0;
SPBRGL = 34; // ボーレート:57600
// 割り込み関連指定
CREN = 1; /* 受信許可 */
RCIF = 0; // シリアル割込みの受信フラグを初期化
RCIE = 1; // シリアル割込みの受信を有効
PEIE = 1; // 周辺装置割込みを有効
GIE = 1; // 全割込み処理を許可
// アナログ関連指定
ANSELA = 0b00000010; //AN1(6ピン)をアナログ
ADCON1 = 0b10010000;
ADCON0 = 0b00000101;
__delay_us(10); // 設定待ち
// DE切り替え
RA2=0; // DE=OFF(受信モード)
len = 0;
sts = 0;
while(1);
}
●その他
回路図などは、あとで公開します。
焼きかたとかも、今度まとめて書く予定。
●参考サイト
プログラム及びコメントなどは、以下のサイトから引用させてもらってます。
http://www.geocities.jp/zattouka/GarageHouse/micon/MPLAB/12F1822/LEDblink/LEDblink.htm
http://sky.geocities.jp/home_iwamoto/page/Pother/P12_A06.htm
http://sky.geocities.jp/home_iwamoto/page/Pother/P12_A07.htm
http://www48.atpages.jp/cent22/Electronics/PIC/Usart_Calc_Baudrate/Usart_Calc_Baudrate.html
http://www.geocities.jp/zattouka/GarageHouse/micon/MPLAB/12F1822/VRtoLED2/VRtoLED2.htm
http://sky.geocities.jp/home_iwamoto/page/Pother/P12_A10.htm
秋月のネット販売で購入
http://akizukidenshi.com/catalog/g/gI-04557/
3.通信モジュールは、RS485ということで、
TIのsn75176bpを秋月のネット販売で購入
http://akizukidenshi.com/catalog/g/gI-07430/
●プログラム
プログラムとして組めるのは、マイコン部分。
マイコン部分のプログラムは、以下のような感じ(青字がプログラム)
/*
* File: main.c
* アナログセンサー送信:RS-485 57600ボーレート
* 1 VDD 8 VSS
* RX 2 RA5 7 RA0
* TX 3 RA4 6 RA1 AN1
* 4 MCLR 5 RA2 DE/RE
*
*/
#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
#define _XTAL_FREQ 8000000 // delay用に必要(クロック8MHzを指定)
// コンフィギュレーション1の設定
#pragma config FOSC = INTOSC // 内部クロック使用する(INTOSC)
#pragma config WDTE = OFF // ウオッチドッグタイマー無し(OFF)
#pragma config PWRTE = ON // 電源ONから64ms後にプログラムを開始する(ON)
#pragma config MCLRE = OFF // 外部リセット信号は使用せずにデジタル入力(RA3)ピンとする(OFF)
#pragma config CP = OFF // プログラムメモリーを保護しない(OFF)
#pragma config CPD = OFF // データメモリーを保護しない(OFF)
#pragma config BOREN = ON // 電源電圧降下常時監視機能ON(ON)
#pragma config CLKOUTEN = OFF // CLKOUTピンをRA4ピンで使用する(OFF)
#pragma config IESO = OFF // 外部・内部クロックの切替えでの起動はなし(OFF)
#pragma config FCMEN = OFF // 外部クロック監視しない(OFF)
// コンフィギュレーション2の設定
#pragma config WRT = OFF // Flashメモリーを保護しない(OFF)
#pragma config PLLEN = OFF // PLLイネーブル(OFF)
#pragma config STVREN = ON // スタックがオーバフローやアンダーフローしたらリセットをする(ON)
#pragma config BORV = HI // 電源電圧降下常時監視電圧(2.5V)設定(HI)
#pragma config LVP = OFF // 低電圧プログラミング機能使用しない(OFF)
//=====================================//
// グローバル宣言 //
//=====================================//
unsigned char buf[16];
int sts = 0;
int len = 0;
void putch(unsigned char ch) {
}
//=====================================//
// 受信部分 //
//=====================================//
int data_get(char RxData)
{
if ( sts == 0)
{
if ( (RxData == 0x2) || (RxData == '$') )
{
buf[len] = RxData;
len++;
sts = 1;
}
}
else
{
buf[len] = RxData;
len++;
if ( ( RxData == 0x3) || (RxData == '#') )
{
len = 0;
sts = 0;
data_send();
}
if ( len > 14 ) // データが長すぎる:壊れた?
{
buf[15] = 0;
len = 0;
sts = 0;
data_send();
}
}
return 0;
}
//=====================================//
// データ送信部分 //
//=====================================//
int data_send()
{
// DE切り替え
RA2=1; // DE=ON(送信モード)
__delay_us(10); // 切り替え待ち(こんなにいらない?)
buf[0] = 0x02;
// アナログデータ受信
GO = 1; // AD変換開始
while(GO); // AD変換終了待ち
sprintf(&(buf[1]),"%04d",ADRES); // AD変換結果送信
buf[5] = 0x03;
buf[6] = 0;
// データ送信
for( int i = 0 ; i < 6 ; i ++)
{
while (!TXIF); //送信待ち
TXREG = buf[i];
}
__delay_us(380); // 2文字程度待つ
RA2=0; // DE=OFF(受信モード)
__delay_us(10); // 切り替え待ち(こんなにいらない?)
len = 0;
sts = 0;
return 0;
}
//=====================================//
// USART通信の受信割込み処理 //
//=====================================//
void interrupt InterReceiver( void )
{
char RxData;
if (RCIF == 1) { // 割込みはUSART通信の受信か?
RxData=RCREG; // DE=OFF(受信モード)
RCIF = 0;
if (RxData != 0)
{
data_get(RxData);
}
}
}
//=====================================//
// メインプログラム:ここから始まる //
//=====================================//
void main() {
// 全体的な指定
OSCCON = 0b01110010; // 内部クロック8Mhz
PORTA = 0b00000000;
TRISA = 0b11111011; //RA2:出力 他は入力
nWPUEN = 0;
// UART関連レジスタ設定
RCSTA = 0b10010000; // 8 bit 連続受信
TXSTA = 0b00100100; // 2:BRGH
BAUDCON = 0b00001000; // 3:16 bit SPBRG
RXDTSEL = 1 ; // 2番ピン(RA5)をRX受信ピンとする
TXCKSEL = 1 ; // 3番ピン(RA4)をTX送信ピンとする
SPBRGH = 0;
SPBRGL = 34; // ボーレート:57600
// 割り込み関連指定
CREN = 1; /* 受信許可 */
RCIF = 0; // シリアル割込みの受信フラグを初期化
RCIE = 1; // シリアル割込みの受信を有効
PEIE = 1; // 周辺装置割込みを有効
GIE = 1; // 全割込み処理を許可
// アナログ関連指定
ANSELA = 0b00000010; //AN1(6ピン)をアナログ
ADCON1 = 0b10010000;
ADCON0 = 0b00000101;
__delay_us(10); // 設定待ち
// DE切り替え
RA2=0; // DE=OFF(受信モード)
len = 0;
sts = 0;
while(1);
}
●その他
回路図などは、あとで公開します。
焼きかたとかも、今度まとめて書く予定。
●参考サイト
プログラム及びコメントなどは、以下のサイトから引用させてもらってます。
http://www.geocities.jp/zattouka/GarageHouse/micon/MPLAB/12F1822/LEDblink/LEDblink.htm
http://sky.geocities.jp/home_iwamoto/page/Pother/P12_A06.htm
http://sky.geocities.jp/home_iwamoto/page/Pother/P12_A07.htm
http://www48.atpages.jp/cent22/Electronics/PIC/Usart_Calc_Baudrate/Usart_Calc_Baudrate.html
http://www.geocities.jp/zattouka/GarageHouse/micon/MPLAB/12F1822/VRtoLED2/VRtoLED2.htm
http://sky.geocities.jp/home_iwamoto/page/Pother/P12_A10.htm