[BC19-01] LEDキャンドル
ブレッドボードチャレンジ2019-01 [BC19-01]LEDキャンドル
ブレッドボードチャレンジ2019-01 [BC19-01]LEDキャンドル
マイコン1個にLED1個という、これ以上簡単なものは考えられない最小限の構成。
LEDがロウソクのようにゆらゆらっと光る
電池を入れると8時間光って16時間消える周期で繰り返す。
BC19-01の解説用PDF
00-bc19-01-candletimer-12f1822.pdf
部品
部品
ミニブレッドボード BB-601(白)[BB-601(White)]
PICマイコンPIC12F1822-I/P [PIC12F1822-I/P]
5mmウォームホワイト・キャンドル色LED OSM2DK5111A-UV (5個入)[OSM2DK5111A-UV]
(VFが2.9V程度のものなら、どんなLEDでも良い)
電池ボックス 単3×2本 Bスナップ・背中合わせ [BH-322-1B]
バッテリースナップ(電池スナップ・Bスナップ) 縦型 カバー付 [SBS-IR-1/150mm]
ブレッドボードとパターン互換のユニバーサル基板を小さく切ったものを使うと回路が小型化できて、LaQに組み込むことも可能。
(ユニバーサル基板で作るときに追加する部品)
(ユニバーサル基板で作るときに追加する部品)
片面ユニバーサル基板(ブレッドボード配線パターンタイプ) Dタイプ(47x36mm) ガラスコンポジット [AE-DB1]
ICソケット ( 8P) (10個入)[2227-08-03]
ピンソケット(メス) 1x4(4P) [FH-1x4SG/RH]
ピンソケット(メス) 1x2(2P)[FH-1x2SG/RH]
回路図
回路図
ファームウェア(ソースコード)
ファームウェア(ソースコード)
XC8 Compiler対応(文字Code :UTF-8)
/*
* File: ledcandle_12f1822.c
* Author: kaimu
*
* Created on April 13, 2019, 5:48 PM
*/
/*
* Output
* CCP1 (RA2) [PIN5] : LED
*/
#include <xc.h>
#include <stdint.h>
////// ここから、プログラミングのためのデータや関数を定義する /////
#pragma config FOSC = INTOSC // 内部クロック使用。
#pragma config WDTE = OFF // ウォッチドッグタイマなし。
#pragma config PWRTE = ON // 64ms後にプログラム開始。
#pragma config MCLRE = OFF // 外部リセットなし。RA3は入力ピン。
#pragma config CP = OFF // コード保護なし。
#pragma config CPD = OFF // データ保護なし。
#pragma config BOREN = ON // 電源電圧低下時のリセットあり。
#pragma config CLKOUTEN = OFF // クロック出力不可。
#pragma config IESO = OFF // 内部外部クロックなし。
#pragma config FCMEN = OFF // FCMなし。
// 動作設定その2
// Configuration 2
#pragma config WRT = OFF // 書き込み保護なし。
#pragma config PLLEN = OFF // PLLなし。
#pragma config STVREN = ON // スタックオーバー/アンダーフローでリセット。
#pragma config BORV = LO // 電源電圧低下監視閾値はLowモード
#pragma config LVP = OFF // 低電圧プログラムなし。
// LED点滅設定
#define LED_BLINK_PERIOD_MIN 50 // LEDが点滅する周期の最小値(20-100)
#define TIME_LIMIT 50
// I/Oポートの定義 (LEDを接続するポートが変わった時はここを変更する)
#define PORT_LED_1 RA2
#define TRISA_LED_1 TRISA2
#define ledOn() (PORT_LED_1 = 1)
#define ledOff() (PORT_LED_1 = 0)
#define led() (PORT_LED_1 ^= 1)
void wait(volatile uint32_t t)
// Delay
{
while (t-- > 0) NOP();
}
void initIo(void) {
//OSCCON = 0b01111010; // PLL disable, 16MHz internal clock
// OSCCON = 0b01100010; // PLL disable, 8MHz internal clock
OSCCON = 0b01101010; // PLL disable, 4MHz internal clock
//OSCCON = 0b01011010; // PLL disable, 1MHz internal clock
//OSCCON = 0b00111010; // PLL disable, 500kHz internal clock
INTEDG = 0; // Interrupt on falling edge of RB0/INT pin
INTE = 1; // External Interrupt Enable
GIE = 1; //Interrupt Enable
ANSELA = 0b00000000; //ALL digital port
CM1CON0 = 0x00; //Comparator disable
TRISA = 0b00001001; //I/O Direction. RA1-2,4-5 : output, RA0,3 : Input
LATA = 0b00000000; // PORTA Latch Settings
}
void initPwm(void) {
//Timer2 settings for PWM standard mode
PR2 = 0; // PWM Period = [(PR2) +1 ]*4*(1/FOSC)*(Timer2 Prescale value)
T2CON = 0b00000010; //00 = Prescaler is 1, 01 = Prescaler is 4,
// 10 = Prescaler is 16, 11 = Prescaler is 64
APFCON &= ~(1 << CCP1SEL); //CCP1 function is on RA2
//CCP1SEL = 1;//CCP1 function is on RA5
CCP1CON = 0b00001100; //PWM mode: P1A, P1C active-high; P1B, P1D active-high
CCPR1L = 64; // PWM Duty Cycle (CCPR1L:CCP1CON<5:4>)*(1/FOSC)*(TMR2 Prescale Value)
//Start PWM
TMR2 = 0;
TMR2ON = 1;
}
void stopPwm(void) {
CCP1ASE = 1;
TMR2ON = 0;
}
void startPwm(void) {
CCP1ASE = 0;
TMR2ON = 1;
}
void pwmPulseWidth(uint8_t value) {
CCPR1L = value;
}
volatile uint32_t TimerCounter; // Counter of Timer Interrupt
#define T0UNIT 15UL // TimerCounter at 1 sec.
void initTimer0(void)
//Initialize Timer 0
// count up every 256*256us = 65536us = 65.536ms (clock 4/4=1MHz, prescaler 1:256
// if you want t[s] timer, TimerCount <= t / 0.065536
{
TMR0IF = 0; // interrupt flag clear
TimerCounter = 0; // Timer Interrupt Counter clear
OPTION_REG = 0b11010111; // Timer0 Internal clock, Prescaler 1:256
// Timer0 Interrupt occured every 65.536ms
TMR0IE = 1; // enable Timer0 interrupt
GIE = 1; // enable interrupt
}
void __interrupt() intr(void)
// Interrupt processing function
{
if (INTF == 1) {
INTF = 0;
}
if (TMR0IF == 1) {
TMR0IF = 0; //Clear TMR0 Interrupt flag
TimerCounter++;
}
}
void initialize(void) {
initIo();
initPwm();
initTimer0();
}
void ledoff(void) {
ledOff();
}
void ledon(void) {
ledOn();
}
void waittimeout(uint32_t timeLimit) {
uint32_t timeLimitCount = timeLimit * T0UNIT; // 時間切れまでのカウント数
TimerCounter = 0; // タイマのリセット。計時開始。
timeLimitCount = T0UNIT * timeLimit;
while (TimerCounter < timeLimitCount) {
//制限時間になるまでの処理
}
}
void starttimer0() {
TimerCounter = 0; // タイマのリセット。計時開始。
}
int8_t istimeout0(uint32_t timeLimit)
//指定時間に達していなければ、0xffを返し、指定時間に達していたら0x0を返す。
{
uint8_t retvalue;
if (TimerCounter < T0UNIT * timeLimit) {
retvalue = 0xff;
} else {
retvalue = 0x00;
}
return retvalue;
}
////// ここまで、プログラミングのためのデータや関数を定義する /////
////// この後のmain(void) { から }までの間に、プログラムが書ける。 /////
void main(void) {
uint8_t pulsewidtharray[] = {0x40, 0x28, 0x3f, 0x1f, 0x2a, 0x30, 0x40, 0x38, 0x30, 0x3a, 0x2f, 0x30}; // pwm Pulse width array
uint8_t npwa = 12; // number of pwm pulsewidth array
uint8_t pwaindex = 1; // pulse width array index
uint8_t pulsewidth; // current pulsewidth
uint32_t ledontime = 28800; // 点灯時間28800sec.(8h)
uint32_t ledofftime = 57600; // 消灯時間5sec.(16h)
initialize(); //システムの初期化
stopPwm();
ledoff(); //LEDを消す
while (1) { //無限ループ。次の}までの間を無限回繰り返す。
starttimer0(); // タイマを開始
startPwm();
PR2 = 50;
while (istimeout0(ledontime)) {
pulsewidth = pulsewidtharray[pwaindex];
for (uint8_t i = pulsewidth / 8; i < pulsewidth; i++) {
pwmPulseWidth(i);
wait(2000);
}
for (uint8_t i = pulsewidth; i > pulsewidth / 8; i--) {
pwmPulseWidth(i);
wait(2000);
}
if (pwaindex > 0) {
pwaindex--;
} else {
pwaindex = npwa - 1;
}
}
//消灯時間の間LEDを消灯する
stopPwm();
ledoff();
starttimer0();
while (istimeout0(ledofftime));
}
}
////// この上の } より上にプログラムが書ける。 /////