先日、コクピットのドアの点滅の様子をPICを使って実際にプログラミングしてみて、試行錯誤の末なんとか動かすことができました。
最初うまく動かなかったのは、先日の推測では消費電流が大きすぎたと書きましたが、もう一つ、タイマーの周波数が高すぎたことも原因でした。
PIC16F886で24個のLEDを制御
最初のプログラムでは、訳も分からず参考にしたサイトの例をそのまま使って125,000,000Hz、すなわち125MHzで動作させていましたが、修正版では8MHzとしました。
この違いは、消費電流の差と安定動作に直接関わってくるので、少数のLEDしか制御できなかったこと、動作が不安定になった事の説明がつきます。
先日は12個プラスα個しか安定動作しませんでしたが、周波数を下げ、適宜抵抗を加える事で24個すべてのLEDを点灯、制御させることができました。
発熱もほとんど無く、安定動作しています。
LEDの割り振り
これらのLEDをどう配分するか、点滅パターンをどうするか考えてみました。ドアもそうですが、どうでもよさげなところにパワーを費やす悪いクセがまた。。
ナビシステムはちょっと凝りたい
照明の動作をみていると、それぞれがランダムに発光しておらず、いくつかのグループに分かれて定期的に点滅している部分がほとんどですが、向かって左上部にあるナビシステムは円形に取り巻くように赤、オレンジ(この色は他のシーンにより黄色や電球色に見えてどうしようか悩んでます。)、青の常時点滅、中央のレーダー部分はかなり高速に点滅しており、他のパーツとは独立させたいと考えました。
大部分のインジゲータは、常灯している部分と点滅している部分とに分け、背面から照射するLEDパネルと蛍光灯(これで通じると思うけど)は常時点灯させます。
中央コンソールは、あまり派手な点滅はしていないので常時点灯とし、中央コンソール側のナビ用に1つ確保しましたが、もしかしたら白LED1個にするかもしれません。
ガラクタらしく、エンストもさせてみた
ホスからの脱出時に一瞬エンスト後、ハンが壁ドンして再起動する様子も再現してみました。
とまった時間や、一瞬点灯するタイミング、再起動までの時間の微調整はこれからです。
点滅の様子(動画)
動画を撮りました。iMovieで字幕を複数入れる方法でしばし悩みました。「分割」しないとダメなのね。。
LED配分表(暫定)
24個あるLEDは次の様に割り振りました。いくつか検討か所もあり、この先変更するかも。自分用メモです。
PORT番号 | 個数 | 用途 | 初期 | エンスト | 無限ループ | 備考 |
RA0~RA2 | 3 | ドア#1 | 消灯 | 消灯 | 点滅 | |
RA3~RA5 | 3 | ドア#2 | 消灯 | 消灯 | 点滅 | |
RC0~RC2 | 3 | ドア#3 | 消灯 | 消灯 | 点滅 | |
RC3~RC5 | 3 | ドア#4 | 消灯 | 消灯 | 点滅 | |
RA6 | 1 | ナビ点滅 | 消灯 | 消灯 | ランダムに高速点滅 | |
RA7 | 1 | ナビ常時点灯(赤) | 消灯 | 消灯 | 常時点灯 | |
RC6 | 1 | ナビ常時点灯(黄) | 消灯 | 消灯 | 常時点灯 | |
RC7 | 1 | ナビ常套点灯(青) | 消灯 | 消灯 | 常時点灯 | 現在はLEDパネルを接続 |
RB0 | 1 | LEDパネル(デアゴ純正) | 点灯 | フラッシュ | 常時点灯 | 現在はLED赤を接続中 |
RB1 | 1 | 背面パネル(赤)パターンA | 点灯 | フラッシュ | 常時点灯 | |
RB2 | 1 | 背面パネル(赤)パターンB | 点灯 | フラッシュ | ランダムにゆっくり点滅 | |
RB3 | 1 | 背面パネル(オレンジ)パターンA | 点灯 | フラッシュ | ランダムにゆっくり点滅 | |
RB4 | 1 | 背面パネル(オレンジ)パターンB | 点灯 | フラッシュ | ランダムにゆっくり点灯 | |
RB5 | 1 | 中央コンソール(LED白) | 消灯 | 消灯 | 常時点灯 | |
RB6 | 1 | 中央コンソールナビ(青) | 消灯 | 消灯 | ゆらぎ点灯 | フルカラーLED検討 |
RB7 | 1 | 隔壁(チップLED白) | 点灯 | フラッシュ | 常時点灯 | 今はエンスト時消灯している |
PICプログラムについて
ちょっとだけ改修して、今回の点滅制御を加えたプログラムです。
改修点
前回、有償版じゃないと配列が使えないということが分かり、やっつけでベタ書きしてた部分を関数化しました。
配列が使えないので、結局はパラメータ全て書いていてちょっとカッコ悪いんですが、main処理はシンプルに
なりました。
ランダム点灯について
乱数を発生させて、ある数値で割り算した余剰により制御を変える、すごく原始的な作りです。
6jiroさんのサイトで、なんだか難しい式を見かけましたがチンプンカンプンだったのと、この方法の方がアナログ感が出てるみたいなので(表現が乏しくすみません)、あまり深く考えないことにしました。なお、乱数といっても再起動後に発生するパターンは同じなので、毎回同じランダム(これも表現が乏しい。。)数値となります。
無限ループに入ると、ドアの点滅パターンを2秒で20パターン(100msec/パターン)で制御しているため、この中に他の制御を詰め込んでいます。
ナビの高速点滅は行う、行わないの判断を乱数から得た値で行い、行う場合はフラグを立てて点滅。。という処理を繰り返しています。
その他の点滅は、1秒ごとに点灯・消灯どちらにするかを乱数の結果で判断することで実現しています。
ソースコード
ソースコード置いときます。上でのべた様にちょっと恥ずかしい感じです。可読性向上と、時間の微調整はこれからです。
で、一応お約束。
- プログラムは自由に使用していただいて結構ですが、生じた不具合、損害は関知しません。自己責任でお願いします。
- 実際に回路を作製する際は、チャタリング防止やプルアップORプルダウン、念のためパスコンを入れる必要があると思います。
- 供給した電源はDC 5V、1A(iPhoneの充電器の仕様と同じ)です。電源については機会があればブログを作製します。
//****************************************************************************** // DeAgostini STARWARS Millennium Falcon // Cockpit Backdoor LED Blink Pattern // Auther : asenchu // Date : 27/Feb/2016 // // for PIC16F886 //****************************************************************************** // PIC16F886 Configuration Bit Settings // 'C' source line config statements #include <stdio.h> #include <stdlib.h> #include <xc.h> // #pragma config statements should precede project file includes. // Use project enums instead of #define for ON and OFF. // CONFIG1 //#pragma config FOSC = INTRC_CLKOUT// Oscillator Selection bits (INTOSC oscillator: CLKOUT function on RA6/OSC2/CLKOUT pin, I/O function on RA7/OSC1/CLKIN) #pragma config FOSC = INTRC_NOCLKOUT// Oscillator Selection bits (INTOSCIO oscillator: I/O function on RA6/OSC2/CLKOUT pin, I/O function on RA7/OSC1/CLKIN) #pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled and can be enabled by SWDTEN bit of the WDTCON register) #pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled) #pragma config MCLRE = ON // RE3/MCLR pin function select bit (RE3/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 Reset Selection bits (BOR enabled) #pragma config IESO = ON // Internal External Switchover bit (Internal/External Switchover mode is enabled) #pragma config FCMEN = ON // Fail-Safe Clock Monitor Enabled bit (Fail-Safe Clock Monitor is enabled) #pragma config LVP = OFF // Low Voltage Programming Enable bit (RB3 pin has digital I/O, HV on MCLR must be used for programming) // CONFIG2 #pragma config BOR4V = BOR21V // Brown-out Reset Selection bit (Brown-out Reset set to 2.1V) #pragma config WRT = OFF // Flash Program Memory Self Write Enable bits (Write protection off) #define _XTAL_FREQ 8000000 // Clock 8MHz // msec timer void wait_msec(unsigned int n) { while(n) { __delay_ms(1); // wait 1msec n--; } } void led_all_control(int a0,int a1,int a2,int a3,int a4,int a5,int a6,int a7, int b0,int b1,int b2,int b3,int b4,int b5,int b6,int b7, int c0,int c1,int c2,int c3,int c4,int c5,int c6,int c7 ){ RA0=a0; RA1=a1; RA2=a2; RA3=a3; RA4=a4; RA5=a5; RA6=a6; RA7=a7; RB0=b0; RB1=b1; RB2=b2; RB3=b3; RB4=b4; RB5=b5; RB6=b6; RB7=b7; RC0=c0; RC1=c1; RC2=c2; RC3=c3; RC4=c4; RC5=c5; RC6=c6; RC7=c7; } void led_door_control(int a0,int a1,int a2,int a3,int a4,int a5, int c0,int c1,int c2,int c3,int c4,int c5) { RA0=a0; RA1=a1; RA2=a2; RA3=a3; RA4=a4; RA5=a5; RC0=c0; RC1=c1; RC2=c2; RC3=c3; RC4=c4; RC5=c5; } void main() { GIE = 0; // no interrupt ANSEL = 0b00000000; // Digital I/O // http://blog.goo.ne.jp/unitec_alfa/e/f277202f4a9eba1540773f3c849826be ANSELH = 0b00000000; OSCCON = 0b01110000; TRISA = 0b00000000; // PORTA PORTA = 0b00000000; // PORTA TRISB = 0b00000000; // PORTB PORTB = 0b00000000; // PORTB TRISC = 0b00000000; // PORTC PORTC = 0b00000000; // PORTC unsigned int waittime=100; // 0.1sec // int m,n,navi_blk; //Phase 1 : // 3秒全消灯 led_all_control(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); wait_msec(4000); // LEDパネル、ナビ赤、ナビ黄点灯 led_all_control(0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1); wait_msec(3000); led_all_control(0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,1,1); wait_msec(2500); led_all_control(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); wait_msec(3000); // LEDパネル、ナビ赤、ナビ黄、パネル、蛍光灯点灯するもエンスト led_all_control(0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,1,1); wait_msec(100); led_all_control(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); wait_msec(100); led_all_control(0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,1,1); wait_msec(150); led_all_control(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); wait_msec(1500); led_all_control(0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,1,1); while(1) { n = rand() % 7; m = rand() % 10; RB0=1; RB1=1; RB2=1; RB3=1; RB4=1; RB5=1; RB6=1; RB7=1; if(m==0||m==1||m==2 || m==3||m==4||m==9){navi_blk=1;}else{navi_blk=0;} //#1 led_door_control(1,1,1,1,1,1,1,0,1,1,1,1); if(navi_blk==1){ RA6=1; } if(n==0){ RB1=0; } if(m==0){ RB2=0; } if(m==3||n==1){ RB3=0; } if(m==2||n==3){ RB4=0; if(n==0||m==2||n==3){ RB2=0; } } wait_msec(waittime); //#2 led_door_control(0,1,0,1,1,1,0,0,0,0,1,0); if(navi_blk==1){ RA6=0; } wait_msec(waittime); //#3 led_door_control(1,0,1,1,0,1,0,0,0,0,1,0); if(navi_blk==1){ RA6=1; } wait_msec(waittime); //#4 led_door_control(1,0,1,1,0,1,1,0,0,0,1,0); if(navi_blk==1){ RA6=0; } wait_msec(waittime); //#5 led_door_control(1,1,1,1,1,1,1,1,0,1,0,1); if(navi_blk==1){ RA6=1; } wait_msec(waittime); //#6 led_door_control(0,1,0,1,1,1,1,1,0,1,1,0); if(navi_blk==1){ RA6=0; } wait_msec(waittime); //#7 led_door_control(1,0,1,1,0,1,1,1,0,1,1,1); if(navi_blk==1){ RA6=1; } wait_msec(waittime); //#8 led_door_control(1,1,1,1,1,0,1,0,1,1,1,1); if(navi_blk==1){ RA6=0; } wait_msec(waittime); //#9 led_door_control(1,1,1,1,1,1,1,0,1,1,1,1); if(navi_blk==1){ RA6=1; } wait_msec(waittime); //#10 led_door_control(0,1,0,1,1,1,0,0,0,0,1,0); if(navi_blk==1){ RA6=0; } wait_msec(waittime); if(n==0){ RB2=0; } if(m==0){ RB3=0; } if(m==3||n==1){ RB4=0; } if(m==2||n==3 || m==7||n==4){ RB2=0; if(n==1||m==7||n==2){ RB5=0; } } //#11 led_door_control(1,0,1,1,0,1,0,0,0,0,1,0); if(navi_blk==1){ RA6=1; } wait_msec(waittime); //#12 led_door_control(1,1,1,1,1,0,1,1,0,1,0,1); if(navi_blk==1){ RA6=0; } wait_msec(waittime); //#13 if(navi_blk==1){ RA6=1; } //#14 led_door_control(1,1,1,1,1,1,1,1,0,1,0,1); if(navi_blk==1){ RA6=0; } wait_msec(waittime); //#15 led_door_control(1,0,1,1,0,1,1,1,0,1,1,0); if(navi_blk==1){ RA6=1; } wait_msec(waittime); //#16 led_door_control(1,1,1,1,1,0,1,1,1,1,1,1); if(navi_blk==1){ RA6=0; } wait_msec(waittime); //#17 led_door_control(1,1,1,1,1,1,1,1,1,1,1,1); if(navi_blk==1){ RA6=1; } wait_msec(waittime); //#18 led_door_control(0,1,0,1,1,1,1,1,1,1,1,0); if(navi_blk==1){ RA6=0; } wait_msec(waittime); //#19 led_door_control(1,0,1,1,0,1,1,1,1,1,1,0); if(navi_blk==0){ RA6=1; } wait_msec(waittime); //#20 led_door_control(1,1,1,1,1,0,1,0,1,1,1,1); if(navi_blk==1){ RA6=0; } wait_msec(waittime); } }
もっと他にやることが。。
作業が一向に進みませんが、(誰も心配してないけど)安心してください。ちょっと手をつけてます!(画像ちっさ!)
これらのブログは後で~。
コメント
おはようございます!
良い感じで点灯していますね〜!
エンストの演出私も考えてました〜^^。ハズブロのアルテメットファルコンのジャンクパーツと絡めてやってみたいなと思っています。
ランダム点灯ですが、私のあの変な式はAVRではrand()関数が使用できないので使用した物で、正直私もあの式の意味よく分かっていませんw
この点滅があの隔壁部分で見られると綺麗でしょうね〜。楽しみです!
>6jiroさん
返信遅くなり申し訳ありません。
ありがとうございます。後はちゃんとコレを仕込めるか、ですね(笑)
エンストはガラクタ感を出すのに一役買っていると思います。ハズブロの回路分解した記事も拝見しましたが、スケールも同じだしそのままうまく使えそうですね〜。
>AVRではrand()関数が使えない〜
そういう話なんですね。
AVRは扱った事はないんですがソースコードを見る限りPICと比べてもかなり直感的で分かりやすいと感じました!
こんばんは~!
回路についてはサッパリ解りませんが、
完成したら面白ですね~
楽しみです(^^)
>レッサーかずさん
おはようございます!返信遅くなり申し訳ありません。
>完成したら面白
コクピットコンテストで、番外のウケ狙い賞狙いますかね(笑)
早速セットしたいんですが、今はエッチングパーツの取り付けと遮光に苦労しています。。
回路やプログラムは、巷にこのPICの情報が少ないので結構ハマりました。
ほぼそのまま使えるのと、改造も簡単なので、万が一使って下さる方がいらっしゃれば、と、後は自分用のメモとして記録してます。
っていっても扱わない場合はナンダコレハ!?ってかんじですよね(笑)
初めまして
PS-STUDIOの番頭のプリン頭と申します。長いので通常は「番頭」だけで済ましていますw
凄いですね!エンストからのアレやコレや!
僕は全くの不得意分野なので完全に無視して進めていますが、こうして見るとうらやましくなります。
当初は配線とうのノウハウを学習するつもりではいたのですが、すっかり諦め重箱の隅をつつく“それがどうした的な”作業に専念しています。
これからもちょくちょく見に来ては草葉の陰からうらやましがらせてもらいますので、よろしくお願いしますm(_ _)m
>番頭さん(でいいのかな?)
初めまして。ご訪問頂きありがとうございます。
重箱の隅的なブログが逆にツボでして、いつも拝見させていただいております!
>凄いですね!エンストからのアレやコレや!
どろぼうひげ氏の様に、何もかもカッコ良くキメられればいいんですが、そこまでのスキルもアイディアも残念ながら持ち合わせていないため、スキルの無駄遣い的な内容をネタにして、持ちこたえております。^^;
次の問題は、これを組み込めるかどうかですね(笑)
これからも、懲りずに、生ぬるく見守って頂ければ幸いです~。