TOPへ戻る

20080705 ATtiny2313 LED PWM 出力の確認(ホタル2匹編)

ATtiny2313 の PWM を使用してLEDをホタルっぽい制御をするプログラムを書いてみました。

確認用回路図


#include <stdlib.h> #include <avr/io.h> #include <util/delay.h> #define MODE 1 #define Bright_Max 24000 // LEDによって消灯しない数値に調整 int type[3] = { 510, //ヘイケボタル1秒間隔 25500/50 255, //ゲンジボタル2秒間隔(西日本) 25500/100 127 //ゲンジボタル4秒間隔(東日本) 25500/200 }; typedef struct { unsigned char state; unsigned char cycle; int wait; unsigned char time; long bright; int sw; }HOTAL_TBL; static HOTAL_TBL hotal_a; static HOTAL_TBL hotal_b; enum { STATE_A, // 条件設定 STATE_B, // 消灯 STATE_C, // 点灯 STATE_D, // cycle STATE_E, // WAIT }; void IoInit(void) { OCR1A = 0x00ff; // いきなり点灯しなように OCR0A = 0x00ff; // いきなり点灯しなように DDRB = 0xff; // portB output TCCR1B = 0x03; // ck / 256 TCCR1A = 0xc1; // normal 8bit TCCR0B = 0x03; // ck / 256 TCCR0A = 0xc1; // normal 8bit } int main(void){ IoInit(); hotal_a.state = STATE_A; // STATE の初期化 hotal_b.state = STATE_A; // STATE の初期化 for(;;){ // 10ms+α ループ _delay_ms(10); switch(hotal_a.state) { // OCR1A LEDの処理 case STATE_A: // STATE:条件設定 hotal_a.cycle = rand()%20+5; // 点滅回数を乱数で求める 5〜25回 hotal_a.wait = (rand()%10 + 1)*100; // 1周期終了後のウエイト 1〜10秒 hotal_a.bright = Bright_Max; hotal_a.state = STATE_B; hotal_a.sw = (rand()%100)-50; // 揺らぎ break; case STATE_B: // STATE:LED点灯 hotal_a.bright -= type[MODE] + hotal_a.sw; if(hotal_a.bright <0){ hotal_a.bright = 0; hotal_a.state = STATE_C; } break; case STATE_C: // STATE:LED消灯 hotal_a.bright += type[MODE] + hotal_a.sw; if(hotal_a.bright > Bright_Max){ hotal_a.bright = Bright_Max; hotal_a.state = STATE_D; } break; case STATE_D: // STATE:cycleチェック hotal_a.cycle --; if(hotal_a.cycle == 0) hotal_a.state = STATE_E; else hotal_a.state = STATE_B; break; case STATE_E: // STATE:wait hotal_a.wait--; hotal_a.bright += type[MODE]; // LED OFF + 突然消灯しない処理 if(hotal_a.bright > 25500) hotal_a.bright = 25500; if(hotal_a.wait==0) hotal_a.state = STATE_A; } switch(hotal_b.state) { // OCR0A LEDの処理 case STATE_A: // STATE:条件設定 hotal_b.cycle = rand()%20+5; // 点滅回数を乱数で求める 5〜25回 hotal_b.wait = (rand()%10 + 1)*100; // 1周期終了後のウエイト 1〜10秒 hotal_b.bright = Bright_Max; hotal_b.state = STATE_B; hotal_a.sw = (rand()%100)-50; // 揺らぎ break; case STATE_B: // STATE:LED点灯 hotal_b.bright -= type[MODE] + hotal_b.sw; if(hotal_b.bright <0){ hotal_b.bright = 0; hotal_b.state = STATE_C; } break; case STATE_C: // STATE:LED消灯 hotal_b.bright += type[MODE] + hotal_b.sw; if(hotal_b.bright > Bright_Max){ hotal_b.bright = Bright_Max; hotal_b.state = STATE_D; } break; case STATE_D: // STATE:cycleチェック hotal_b.cycle --; if(hotal_b.cycle == 0) hotal_b.state = STATE_E; else hotal_b.state = STATE_B; break; case STATE_E: // STATE:wait hotal_b.wait--; hotal_b.bright += type[MODE]; // LED OFF + 突然消灯しない処理 if(hotal_b.bright > 25500) hotal_b.bright = 25500; if(hotal_b.wait==0) hotal_b.state = STATE_A; } // 点灯処理 STATE_B STATE_C STATE_E の時に点灯 if(hotal_a.state==STATE_B || hotal_a.state==STATE_C || hotal_a.state==STATE_E){ OCR1A = (hotal_a.bright/100) & 0x00ff; } if(hotal_b.state==STATE_B || hotal_b.state==STATE_C || hotal_b.state==STATE_E){ OCR0A = (hotal_b.bright/100) & 0x00ff; } } }
ソースファイルのダウンロード


AVRSP-Gのヒューズビットの設定
内蔵クロック8MHz 分周比1/1 の設定です。

コンパイラは WinAVR-20070525 を使いました。

緑のLEDと白のLEDを使った動画を用意しました。いずれもカメラの性能のため荒いです(^^;


1)float を使わないようにするため、変数に100倍の値を使用している。
2)無駄な細工をしている。(^^;
3)OCR1B,OCR0Bに惑わされた(^^;
4)本当は10msタイマー割り込みでステートを動かそうと考えていましたが、ディレイで妥協(^^;