NightRiderV1(残像方式)
概要
『ナイトライダー(Knight Rider)』は、1982年9月から1986年8月にかけて、米国で放映された特撮テレビドラマです。
そこに登場するK.I.T.Tという高性能人工知能を搭載した「ナイト2000(トランザム)」のボンネットには、残像を残しながら、左右に流れる赤いランプが搭載されていました。
そこでこれを再現(?)してみようと思い立ち製作してみました。
動作原理
単にLEDが左右に流れるだけでは、面白くありませんので、残像を残しながら流れるように工夫してみました。
つまり、先頭のLEDは明るく、後に続くLEDは徐々に暗くしていきます。
LEDの明るさの制御は、PWM(Pulse Width Modulation)方式としました。
PIC16F88には、PWMモジュールが搭載されていますが、1個だけなので利用はあきらめ、ソフトウエアで10個のPWMを実現することにしました。
PWMを使った制御では、周期(period)を設定し、デューティ比(duty cycle)を増減させることにより、LEDの明るさを可変します。
今回は、明るさを10段階としました。
<周期>
TIMER0の割り込みと割り込み回数を使用して、約33msecとします。
(1秒÷8MHz)×4(Fosc/4)×256(TMR0)×255(割り込み回数)
<デューティ比>
100%(255)、50%(128)、25%(64)、13%(32)、6%(16)、3%(8)、1.5%(4)、0.8%(2)、0.4%(1)、0%(0)
回路図
ソースコード
- NightRiderV1.c
//********************************************************************** /* <NightRiderV1(残像機能搭載)> */ //********************************************************************** #define ON 0 #define OFF 1 #define LED1 PORTB.F0 #define LED2 PORTB.F1 #define LED3 PORTB.F2 #define LED4 PORTB.F3 #define LED5 PORTB.F4 #define LED6 PORTB.F5 #define LED7 PORTB.F6 #define LED8 PORTB.F7 #define LED9 PORTA.F6 #define LED10 PORTA.F7 //********************************************************************** void SwitchONcheck() { while (Button(&PORTA, 2, 1, 0) == 0) ; while (Button(&PORTA, 2, 1, 1) == 0) ; } //********************************************************************** static unsigned short pwm_cnt, led_cnt[10]; void interrupt() { if (INTCON.T0IF == 1) { // 約0.128msec周期 INTCON.T0IF = 0; // LED1 = (pwm_cnt <= led_cnt[0]) ? ON : OFF; LED2 = (pwm_cnt <= led_cnt[1]) ? ON : OFF; LED3 = (pwm_cnt <= led_cnt[2]) ? ON : OFF; LED4 = (pwm_cnt <= led_cnt[3]) ? ON : OFF; LED5 = (pwm_cnt <= led_cnt[4]) ? ON : OFF; LED6 = (pwm_cnt <= led_cnt[5]) ? ON : OFF; LED7 = (pwm_cnt <= led_cnt[6]) ? ON : OFF; LED8 = (pwm_cnt <= led_cnt[7]) ? ON : OFF; LED9 = (pwm_cnt <= led_cnt[8]) ? ON : OFF; LED10 = (pwm_cnt <= led_cnt[9]) ? ON : OFF; // if (pwm_cnt < 255) pwm_cnt++; else pwm_cnt = 1; } } //********************************************************************** unsigned short Luminance[10] = {255, 128, 64, 32, 16, 8, 4, 2, 1, 0}; //unsigned short Luminance[10] = {255, 64, 16, 4, 1, 0, 0, 0, 0, 0}; void main() { unsigned short cnt; // CMCON = 0b00000111; ANSEL = 0b00000000; TRISA = 0b00111100; TRISB = 0b00000000; OSCCON = 0b01110000; // TIMER0の設定 INTCON.T0IE = 1; INTCON.T0IF = 0; OPTION_REG.T0CS = 0; OPTION_REG.PSA = 1; OPTION_REG.PS0 = 0; OPTION_REG.PS1 = 0; OPTION_REG.PS2 = 0; TMR0 = 0; // pwm_cnt = 1; // 割り込みを許可する。 INTCON.PEIE = 1; INTCON.GIE = 1; // for (cnt = 0; cnt < 10; cnt++) { led_cnt[cnt] = Luminance[cnt]; } Delay_ms(1000); // for (cnt = 0; cnt < 10; cnt++) { led_cnt[cnt] = Luminance[9 - cnt]; } Delay_ms(1000); // while (1) { for (cnt = 0; cnt < 10; cnt++) { led_cnt[9] = led_cnt[8]; led_cnt[8] = led_cnt[7]; led_cnt[7] = led_cnt[6]; led_cnt[6] = led_cnt[5]; led_cnt[5] = led_cnt[4]; led_cnt[4] = led_cnt[3]; led_cnt[3] = led_cnt[2]; led_cnt[2] = led_cnt[1]; led_cnt[1] = led_cnt[0]; led_cnt[0] = Luminance[cnt]; Delay_ms(30); } for (cnt = 0; cnt < 10; cnt++) { led_cnt[9] = led_cnt[8]; led_cnt[8] = led_cnt[7]; led_cnt[7] = led_cnt[6]; led_cnt[6] = led_cnt[5]; led_cnt[5] = led_cnt[4]; led_cnt[4] = led_cnt[3]; led_cnt[3] = led_cnt[2]; led_cnt[2] = led_cnt[1]; led_cnt[1] = led_cnt[0]; Delay_ms(30); } for (cnt = 0; cnt < 10; cnt++) { led_cnt[0] = led_cnt[1]; led_cnt[1] = led_cnt[2]; led_cnt[2] = led_cnt[3]; led_cnt[3] = led_cnt[4]; led_cnt[4] = led_cnt[5]; led_cnt[5] = led_cnt[6]; led_cnt[6] = led_cnt[7]; led_cnt[7] = led_cnt[8]; led_cnt[8] = led_cnt[9]; led_cnt[9] = Luminance[cnt]; Delay_ms(30); } for (cnt = 0; cnt < 10; cnt++) { led_cnt[0] = led_cnt[1]; led_cnt[1] = led_cnt[2]; led_cnt[2] = led_cnt[3]; led_cnt[3] = led_cnt[4]; led_cnt[4] = led_cnt[5]; led_cnt[5] = led_cnt[6]; led_cnt[6] = led_cnt[7]; led_cnt[7] = led_cnt[8]; led_cnt[8] = led_cnt[9]; Delay_ms(30); } } } //**********************************************************************




