前回は製作したジャムびんLEDランタンの全体像について紹介しました。今回は、マイコンの設定、プログラム等について紹介していきます。
各ピンの割り当て
使用したマイコンは「PIC12F683」です。各ピンの割り当てはこのようにしました。
- 1ピン:電源入力
- 2ピン:(未使用)
- 3ピン:アナログ入力
- 4ピン:MCLR
- 5ピン:デジタル出力(MOSFETをドライブ)
- 6ピン:A/D変換用基準電圧入力
- 7ピン:(未使用)
- 8ピン:GND
基本思想・設定
割り込みは使用せず、すべての処理はメインループにて行っています。
- ほとんど処理がないため、低速で構わないので、消費電力を下げるためにクロック(Fosc)を「31kHz」と低く設定しました。
- 未使用ピンは入力にして、Weak pull upとしました。
- 4ピンはMCLRとして使う予定はなかったが、デジタル入力と設定しても、(デジタルI/Oとしたときには)内蔵Weak pull upが無効っぽいので、MCLRとしました。一応、外部抵抗(10kΩ)でプルアップしています。
- ウォッチドックタイマ(WDT)は有効としています。
プリスケーラはタイマ0に使うことにしたので、WDTのタイムアウト時間は、プリスケーラなしでの最大値
としました。WDTのクリア処理は、メインループ内で毎回実行します。
タイマOFF機能
タイマOFF用の時間管理はタイマ0を使うことにしました。本当はタイマ1の方が良いのですが、厳密な時間管理は不要なので、まあいいかと。
タイマ0のクロックを内部クロックとして(31kHz/4=7750Hz)、プリスケーラは256と設定すると、TMR0レジスタは33.024msごとにカウントアップされます。
TMR0レジスタは8bitなので、256カウントでオーバーフローします。今回の設定では、オーバーフローは8.454144sで発生するので、オーバーフローが426回発生したら1h経過と判断できます。
TMR0レジスタがオーバーフローしたらT0IFフラグが1となり、割り込みを許可していると、これをトリガに割り込みが発生させることができます。しかし、今回は割り込みを使うほどでもなかったので、メインループでこのフラグ(T0IF)をポーリングでチェックして処理しています。
タイマOFF機能の処理フローチャートはこんな感じです。(メインループ内で処理)
過放電防止機能
製作したLEDランタンでは、昇圧DC/DCコンバータでニッケル水素電池1.2Vを5Vに昇圧して回路を動かています。使用した昇圧DC/DCコンバータボードは入力電圧0.9Vでも動作します。
しかし、ニッケル水素電池の放電終止電圧は1.0Vくらいと言われているので、この1.0Vで回路動作を停止して、ニッケル水素電池の過放電を防止する、というのがこの機能の目的です。
処理としては、A/D変換によってニッケル水素電池の電池電圧を取得して、しきい値(1.0V)を5回連続で下回ったら、電源をラッチしているMOSFETをOFFして回路を停止させます。
また、立ち上げ直後は判定から除外しています。
過放電防止機能の処理フローチャートはこんな感じです。(メインループ内で処理)
ソースコード
main.c
/******************************************************* NiMH過放電防止&タイマOFF 2023,5/26 Ver.0.00 電気系ものづくりブログ https://www.sonohen.page/ MCU:PIC12F683 Internal OSC Freq:31kHz GP0: GP1:Vref GP2:GPIO(out):電源ラッチ GP3:MCLR GP4:AN3:Ni-MH Voltage GP5: *********************************************************/ #include <xc.h> // CONFIG #pragma config FOSC = INTOSCIO // Oscillator Selection bits (INTOSCIO oscillator: I/O function on RA4/OSC2/CLKOUT pin, I/O function on RA5/OSC1/CLKIN) #pragma config WDTE = ON // Watchdog Timer Enable bit (WDT enabled) #pragma config PWRTE = ON // Power-up Timer Enable bit (PWRT enabled) #pragma config MCLRE = ON // MCLR Pin Function Select bit (MCLR pin function is MCLR) #pragma config CP = OFF // Code Protection bit (Program memory code protection is disabled) #pragma config CPD = OFF // Data Code Protection bit (Data memory code protection is disabled) #pragma config BOREN = ON // Brown Out Detect (BOR enabled) #pragma config IESO = OFF // Internal External Switchover bit (Internal External Switchover mode is disabled) #pragma config FCMEN = ON // Fail-Safe Clock Monitor Enabled bit (Fail-Safe Clock Monitor is enabled) /*関数のプロトタイプ宣言*****************/ void Setting(void); unsigned char ADC8bit(unsigned char); #define START_UP 150 //起動後、この回数メインループが回るまでは過放電防止判定しない void main( void ){ unsigned short time_cnt; unsigned char Vbat; unsigned char Low_cnt; unsigned char MainLoopCnt; //各種設定 Setting(); time_cnt = 0; Low_cnt = 0; MainLoopCnt = 0; GPIObits.GP2 = 1; //電源ラッチON //Mainloop while(1){ if(INTCONbits.T0IF){ //flag check //8.454144s毎 time_cnt++; if(time_cnt >= 426){ //1h=3600s GPIObits.GP2 = 0; //電源ラッチOFF(Auto Power off) } INTCONbits.T0IF = 0; //flag clear } if(MainLoopCnt < START_UP){ //電源投入直後は過放電判定しない MainLoopCnt++; } Vbat = ADC8bit(3); if( (Vbat < 95) && (MainLoopCnt >= START_UP) ){ //(Vbat < 1V)? Low_cnt++; if(Low_cnt > 4){ //5回連続 GPIObits.GP2 = 0; //電源ラッチOFF(過放電防止) } } else{ Low_cnt = 0; } CLRWDT(); } }
setting.c
#include <xc.h> #define _XTAL_FREQ 31000 //CLK:31kHz void Setting(void){ OSCCON = 0x00; // 0000_0000 31kHz WDTCON = 0x17; // 0001_0111 プリスケーラ65536, WDT:2.11sくらい? TMR0 = 0; OPTION_REG = 0x47; // 0100_0111 GPIOプルアップ、TMR0クロックソースFosc/4、PS=256(TMR0) INTCON =0x00; // 0000_0000 割り込み不許可 PIE1 = 0x00; PIR1 = 0x00; CMCON0 = 0x07; //0000_0111 Comp OFF TRISIO = 0x3B; //0011_1011 GP2:out ANSEL = 0x3A; //0011_1010 ADC_clk:Frc, AN3,1:Analog WPU = 0x21; //0010_0001 GP5,0 Weak Pull-up ADRESL = 0x00; // ADC Result Clear ADRESH = 0x00; ADCON0 = 0x40; //データ左詰め、Vref=AN1、 } /*******************************************************/ //内蔵ADCを8bitで使う //注意:ADFMにてデータを左詰め設定をしておくこと /*******************************************************/ unsigned char ADC8bit(unsigned char ch){ ADCON0bits.ADON = 1; //ADC enable if(ch<4){ ADCON0bits.CHS = ch; //channel set } else{ return (0); } __delay_us(20); //wait 20us ADCON0bits.GO = 1; //ADC start while(ADCON0bits.GO){ } return (ADRESH); }
0 件のコメント:
コメントを投稿