前回は製作したジャムびん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 件のコメント:
コメントを投稿