PIC16F1503。 ポンプ用手押し車-2.ライト

以前は音についてでした。



私は最後の投稿を未完成のままにした。 覚えているなら、「まさに音」を拾うことができませんでした。 「直観による数字」を拾う試みは、通常の「ピウピウ」よりもはるかに悪いことが判明しました...一方では、とにかく-中国のツイーターから音はありませんが、他方では-「汚れた仕事、低クラス」。 この場合も、16 MHzのクロック周波数を駆動します...







一般的に、私はどこか間違ったことをしました。 翌日の夕方、音楽とそのリテラシーに関する教育プログラムは、以前よりもさらに多くの質問を投げかけました(鋭い鋭さがあるようですが、鋭い鋭さはないようですが、代わりにEフラット?)。 しかし、私は「トレーニングマニュアルで日本語を取る」ことに慣れていないので、理解し続けました。 同時に、顧客は仕様の変更について話し合いました(おなじみの画像ではありませんか?)。これは、「ボトムイルミネーション」を追加することでした。 これは実際にはパトカーであると言う私のti病な試みに対して、それは黒人地区のパトカーであるという答えが受け取られました...



そもそも、音を消すことにしました。 周波数とPWMを変更し、分周器を255で1に設定し、7692 Hzと62 Hzの周波数を取得しました。 範囲は少し変更されましたが、それでも-かなりです。



そして、何かが分周器128で周波数を測定するように私を引っ張った。私は(7692-62)/ 2 = 3815Hzのようなものを得ると思っていたが、何らかの理由で私は125しか得なかった...そして私は、鹿のセーターの私の好きなプログラマーのように、それは夜明け:周波数分周器の関係は線形であると誰が言ったのか? いくつかの余分な測定により、私は絶対に正しいことが示されました。 オシロスコープとエクセルを備えた小さなtrachytibidochは、このような美しいHz-Timer画像を提供しました(通常のように、オリジナルは投稿の最後にアーカイブにあります)。







今では、なぜ私の音がひどいものになったのかが明らかになりました。 さらに、コメントの中で、彼らは2KBのROMに曲が詰められているドアベルについて覚えていました...何を探すべきかを知っているとき、それは速いです。



最初の(のような)スキームは、92歳の雑誌Radioの第8号に掲載されました。 シックな(私にとって)タブレットがあった







そして次のページ-ファームウェア自体。 さらに多くのガグラージと2月93日、「アマチュアラジオ」が見つかります。 まったく同じ原理がありますが、さらにメロディーがあります。



Excelを再度充電し(2番目のタブのアーカイブで)、遅延をハードウェアからソフトウェアに変換します。



いくつかのコードを追加する



// come cool sound const uint8_t m1[31]={49,49,52,52,58,58,58,58,38,38,28,52,52,52,52,52,52,52,52,38,38,36,38,36,38,52,52,49,49,49,49}; const uint8_t m2[31]={49,42,38,38,49,42,38,42,49,52,58,52,49,42,52,65,49,42,38,38,49,42,38,42,49,52,58,42,49,42,52}; // play like this uint8_t c; for(c=0;c<31;c++) { PWM3_LoadDutyValue(m1[c]*2); TMR2_LoadPeriodRegister(m1[c]); __delay_ms(120); }
      
      





そして乾杯! 中国のツイーターからは、私の耳でさえ不快にならない非常に認識可能な音を聞くことができます。 原則として、私たちは自分自身を誇りに思うことができます-新しい要素ベースで、私たちは「論理」に関する20年のスキームを繰り返しました。 マシンがプレイできない場合でも、いつでもドアベルでリメイクできます:)



一般的に、最高の「すごい」を検索するプロセスは継続しますが、原則として音の問題は解決しました。 私たちは光に目を向けます。



最初の投稿で書いたように、ネイティブLEDは青色で非常に明るいものでした。 さらに、私は青い光が赤いフィルターを通して輝き、すべての調和に違反していることにoutりました。 したがって、変更する必要があります。



スタッシュから赤いLEDを取り出し、点灯させました。 最初の問題:明るさが異なります。 青は非常に明るいです。 「隠し場所から」に変更します-まだ違います。 もちろん、追加の抵抗を消音することもできますが、それはあまりにも単純です。 最後にRGB LEDに到達し、奇跡が起こりました! 同じ明るさのすべての色で輝いています。 原則として、「最も安い」の50ほどの費用がかかるため、驚くことではありません。



私はすべてのニーズ(シャンデリアの赤と青の部分、ヘッドライト、下部)に4つのRGB LEDを使用することにしました。 私のLEDには共通のカソードがあるため、3(RGB)* 4(ピース)-制御のために12本の脚が必要です。 繰り返しになりますが、マイクロコントローラーには12(通常14、ただし2つの電源)のレッグしかなく、その1つは「入力」(リセット)に割り当てられ、もう1つは「音楽」の下に割り当てられます。 そして、他のどこかで、スイッチを切って予備を残す必要があります。



通常、このような場合、彼らはまさにそれを行っています。ある種の「ポートエクスパンダー」を使用してインストールします。 最も一般的なオプションは、シフトレジスタタイプ74HC595です。 しかし、2番目のチップを並べて配置することは、破綻し、予算を完全に超過します。 すべてのプロジェクトがこれを行うと、パイには何も残りません...そして、studiovsemoe.comの私たちは本当に食べるのが大好きです:)



したがって、私は反対に行き、コントローラーですべてを行います。 このように足を広げます(すべて出口まで)







そして、私はこのようにLEDを接続します(いつものように、アーカイブ内の完全な回路)







図では、各LEDを3つの個別のLEDに「分割」して、動作原理を明確にしました。 まあ、何らかの理由で、抵抗は10kで止まりましたが、実際には200-300オームです。 その結果、4x3 LEDマトリックスができました。



重要:このスキームは1-2-3 LEDにのみ適しています。 さらに接続する予定がある場合-L298のような特別なドライバーを使用してください-さもなければ、マイクロ回路の出力を流れる電流が大きすぎます。



コードを追加する



 LATCbits.LATC0 = 1; // RED LATCbits.LATC1 = 1; // GREEN LATCbits.LATC2 = 1; // BLUE LATCbits.LATC3 = 0; LATCbits.LATC4 = 0; LATCbits.LATC5 = 0; LATAbits.LATA5 = 0;
      
      







ここでは、レッグC0〜C2を1に設定し、C3〜C5とA5をゼロに設定します。 すべてが正しく組み立てられている場合は、すべてのLEDを「白色光」で点灯する必要があります。



どうした ご存知のように、電流は電位の高い場所から低い場所に流れます。 そして、片方の足には1(または+ 3V)があり、もう片方の足には-0があります。LEDが点灯します。 それらとそれらの脚にファイル0または1があれば、何も燃えません。 ところで、回路の汎用性もここから現れます-私のような共通のカソードではなく、共通のアノードを持つLEDがある場合、コード内で0から1に変更するだけで機能します。



その結果、脚C0〜C2の状態を組み合わせて、グローの色を選択できます。また、他のLEDが4つのうちどれを点灯するかを選択できるため、元の12脚の代わりに7年かかります。 あまりクールではありません(シフトレジスタを使用すると2つ実行できます)が、この目的には十分すぎるほどです。



ただし、少なくとも2つのLEDを異なる色(シャンデリアとヘッドライト、ヘッドライト、ボトムなど)で同時に点灯する必要があります。 ここでは、世界と同じくらい古いトリックを使用します。LEDをすばやく切り替えて、目的の色をオンにします。 十分に速く行われた場合、目はちらつきに気付かないでしょう。



色を点滅させようとします(意味は表記法から理解できると思います)



 LATCbits.LATC3 = 0; LATCbits.LATC4 = 0; LATCbits.LATC5 = 0; LATAbits.LATA5 = 0; while(1) { LATCbits.LATC0 = 1; LATCbits.LATC1 = 0; LATCbits.LATC2 = 0; __delay_ms(50); LATCbits.LATC0 = 0; LATCbits.LATC1 = 1; LATCbits.LATC2 = 0; __delay_ms(50); LATCbits.LATC0 = 0; LATCbits.LATC1 = 0; LATCbits.LATC2 = 1; __delay_ms(50); }
      
      







そして、LEDがどれほど美しく点滅し、色を分類しているかを確認します...



原則として、ポートで直接動作するように書き換えることができます-それは簡単です。



 while(1) { LATC=0b00000001; __delay_ms(50); LATC=0b00000010; __delay_ms(50); LATC=0b00000100; __delay_ms(50); }
      
      







違いは何ですか? 違いは 最初のオプションは(すべてのバインディングで)89バイト、2番目のオプションは8バイトの青の差を取ります。 さて、2番目の方が速く動作します:)



理解できない場合は、設計



 LATC=0b00000001;
      
      







完全に類似



 LATCbits.LATC0 = 1; LATCbits.LATC1 = 0; LATCbits.LATC2 = 0; LATCbits.LATC3 = 0; LATCbits.LATC4 = 0; LATCbits.LATC5 = 0; LATCbits.LATC6 = 0; LATCbits.LATC7 = 0;
      
      







短所はどこですか? 欠点は、いくつかのコントローラーでは有用な何かのために最も重要なビットを与えることができ、すべてをそこに押し込み、汚れた手で登るということです...



マイナスはどこですか? もう1つのマイナス点は、「恐怖」に対処する必要があることです。 まあ、これは私たちのような才能にとって価値のないことです。 ネカの鉄片がそれに従事しています。



サウンドを担当するタイマーがあります。 いいえ、彼には触れませんが、彼の隣人には触れます。 変更のために、TIM1を使用します



TIM2との違いは何ですか? まず、精度が高い-TIM2の範囲が255の部分に分割されている場合、ここでは65535に分割されます。つまり、周波数をより正確に取得できます。 第二に、彼は何にも執着せず、​​彼には何も執着しません。 そして最後に、その出力をマイクロコントローラーの足元に持ち込むことができます。 これはほとんど必要ないので、割り込みを許可し、割り込みハンドラーでLEDを点滅させます。



一般的に、このように設定します







ここでの主なことは、割り込みを含めることと、関数の各割り込みを呼び出すことに注意を払うことです(最終行)。



現在、最後のtmr1.cファイルには、64マイクロ秒ごとに呼び出される関数があります(ちなみに、幅広い機能([リロード値]フィールドに注意してください)により、この値を「4秒に1回」に変更できます)。



 void TMR1_ISR(void) { // Clear the TMR1 interrupt flag PIR1bits.TMR1IF = 0; TMR1H = (timer1ReloadVal >> 8); TMR1L = timer1ReloadVal; // Add your TMR1 interrupt custom code }
      
      







拡張可能で構成可能なコードが大好きなので、LEDを担当する2つのファイルをプロジェクトに追加します



led.h:

 // basic colors #define RED 1 #define GREEN 2 #define BLUE 4 #define OFF 0 // set led N to color C void setLed(uint8_t n,uint8_t c); // get color of led N uint8_t getLed(uint8_t n); extern volatile uint8_t lc[4]; // How LED connected #define _LED1_ LATCbits.LATC3 #define _LED2_ LATCbits.LATC4 #define _LED3_ LATCbits.LATC5 #define _LED4_ LATAbits.LATA5 #define _LEDR_ LATCbits.LATC0 #define _LEDG_ LATCbits.LATC1 #define _LEDB_ LATCbits.LATC2
      
      







次に、led.cに色付きの「作業」を追加します



 volatile uint8_t lc[4]; // current led colors 0 - off void setLed(uint8_t n,uint8_t c) { lc[n]=c; } uint8_t getLed(uint8_t n) { return lc[n]; }
      
      







そして、割り込みハンドラーコード



 switch(current_led) { case 0: _LED1_=0; _LED2_=1; _LED3_=1; _LED4_=1; break; case 1: _LED1_=1; _LED2_=0; _LED3_=1; _LED4_=1; break; case 2: _LED1_=1; _LED2_=1; _LED3_=0; _LED4_=1; break; case 3: _LED1_=1; _LED2_=1; _LED3_=1; _LED4_=0; break; } if((lc[current_led]&RED)==RED) _LEDR_=1; else _LEDR_=0; if((lc[current_led]&GREEN)==GREEN) _LEDG_=1; else _LEDG_=0; if((lc[current_led]&BLUE)==BLUE) _LEDB_=1; else _LEDB_=0; current_led++; if(current_led>3) current_led=0;
      
      







最後に、確認コードを書く以外にやることはありません。



 setLed(0,RED); setLed(1,GREEN); setLed(2,BLUE); setLed(3,RED+GREEN+BLUE); __delay_ms(50); setLed(1,RED); setLed(2,GREEN); setLed(3,BLUE); setLed(0,RED+GREEN+BLUE); __delay_ms(50); setLed(2,RED); setLed(3,GREEN); setLed(0,BLUE); setLed(1,RED+GREEN+BLUE); __delay_ms(50); setLed(3,RED); setLed(0,GREEN); setLed(1,BLUE); setLed(2,RED+GREEN+BLUE); __delay_ms(50);
      
      







コンパイルして実行し、完全な不満を取得します。 何も点滅せず、オーバーフローしません。 なんで? 考えたり探したりすることからあなたを救います 64マイクロ秒ごとに割り込みを生成するように設定したためです。 そして、プロセッサは62キロヘルツで動作しました。 つまり、1クロックサイクルには16マイクロ秒かかります。 プロセッサが上記のコマンドをすべて4クロックサイクルで積み重ねることができると信じている人はいますか? 信じられません。 その結果、マイクロコントローラーはタイマー割り込みハンドラーで永久にハングアップします。



論理的推論(実際には、通常の選択)により、1つの割り込みが3ミリ秒(またはタイマーカウンターのFFC0)のオーダーで処理されることがわかります。



何が見える? ちらつきのある色を変えるLEDが見えます。 そして、「純白」は見えません。 その理由は何ですか? 理由は時間、またはむしろ頻度です。 LEDは今どのように機能しますか? 3msはオンです-9msはオンではありません。 25%のカバレッジで80ヘルツのPWM周波数。 経験から、私は目が200ヘルツからどこかにPWMに気づかないことを知っています。



どうする 最も簡単な方法は、頻度を上げることです。 遅かれ早かれ、目はちらつきに気づかなくなります。 サウンド周波数が「フロートアウェイ」であっても、TIM2での予備分周器の可能な値-1:1、1:4、1:16、1:64を調べます。 周波数は62KHzになりました。つまり、62 * 4 = 250KHz、62 * 16 = 1MHz、または62 * 64 = 4MHzを設定できます。



最善は善の敵です。そのため、マイクロコントローラーの周波数を1 MHzに設定し、分周器を1:16に変更して、ファームウェアを再度満たします。 やった! ちらつきがなくなりました。







確かに、いくつかの色...実際にはそうではありません。 いいえ、これらは私が写真を撮ったiPhoneの不具合ではありません。 それは本当に赤のような赤だけです(実際には白赤青緑があるはずです)。 また、必要な50ミリ秒とはまったく異なり、スイッチは一種の緩慢です。



問題は何ですか? 繰り返しますが、悪役の物理学者は私たちを時流に乗せました:180マイクロ秒(3ms / 16)で、LEDには「燃え上がる」時間がありません。 結果は、写真に見えるものです。



何ができますか? 繰り返しになりますが、「額」ソリューションは、LEDが点灯した後に遅延を突くように頼みます。 原則として、解決策は良いです。 しかし、プログラマーに有利なスタートを切る方が良いです。



なんで? 思考実験を行い、さらに2つのLEDを追加しましょう。 25%のカバレッジでPWMを使用していた場合、16%になります。 さらに4つ追加すると、10%に減少します。 これは、結果のデザインが機能するように、頻度と遅延とセックスする方法を選択する必要がある方法です。



したがって、アルゴリズムをもう一度見てみましょう。 彼は今このように見える



-現在のLEDをオンにし、残りをオフにします

-現在のLEDの赤チャンネルに何かがありますか? はいの場合は、赤チャネルをオンにし、そうでない場合はオフにします

-現在のLEDには緑色のチャンネルに何かがありますか? はいの場合、緑色のチャネルをオンにし、そうでない場合はオフにします

-現在のLEDには青色のチャンネルに何かがありますか? はいの場合は、青チャネルをオンにし、そうでない場合はオフにします





そして今、私たちは各LEDにより多くの遅延を詰め込みます...再びフリッカーを取得し、再び周波数を上げます。 完全な不適格性と暗いコーナーでのすすり泣きが待っています。



すすり泣きたくないので、アルゴリズムを次のものに変更します



-チャンネルNをオンにします(赤、緑、青)

-LED M(0,1,2,3、...)で、現在のチャンネルHを点灯する必要がありますか? はいの場合は、オンにします。 そうでない場合は、オフにします。

-Mのサイクルを繰り返します

-最後のLEDが点灯するまで待ちましょう。

-Hのサイクルを繰り返します



違いはそれほど大きくないようですが、違いを感じてください。PWMLEDの数に関係なく、それらは33%いっぱいになります。 確認します。



1つのチャネルのコード(残りは完全に似ています)。 定義はフルバージョンでも見ることができますが、名前は明確になると思います。



 _LEDR_=_LEDON_; if ((lc[0] & RED) == RED) _LED1_ = _LEDOFF_; // INVERTED! else _LED1_ = _LEDON_; if ((lc[1] & RED) == RED) _LED2_ = _LEDOFF_; // INVERTED! else _LED2_ = _LEDON_; if ((lc[2] & RED) == RED) _LED3_ = _LEDOFF_; // INVERTED! else _LED3_ = _LEDON_; if ((lc[3] & RED) == RED) _LED4_ = _LEDOFF_; // INVERTED! else _LED4_ = _LEDON_; for(leds=0;leds<80;leds++) current_led++; _LEDR_=_LEDOFF_;
      
      







そして感心します。







これは写真ではそれほどよく見えませんが、実際には、緑が緑に変わり、青が青に変わります。



さて、「フィナーレのように」に変わります。



 setLed(3,RED+GREEN+BLUE); setLed(2,GREEN); setLed(0,RED); __delay_ms(100); setLed(0,OFF); setLed(1,BLUE); __delay_ms(100); setLed(1,OFF);
      
      







シャンデリアがウインク! ヘッドライトが輝いています! そして、底はすべてとても緑です! 一般に、私たちの取り組みにおける完全かつ無条件の成功。 かっこいいです! モチベーションには他に何が必要ですか? :)少し沈黙します:)顧客への結果の予備表示は、完全な承認と仕事のための追加のリソースの割り当てを受け取りました(「お父さん、あと2晩は非常に静かになります」と他の親の脅迫)



このことによるボーナス:ほとんどNYPDの点滅標準



 uint8_t c; setLed(3, RED + GREEN + BLUE); setLed(2, GREEN); while (1) { setLed(0, RED); setLed(1, OFF); __delay_ms(40); for (c = 0; c < 10; c++) { setLed(0, OFF); __delay_ms(10); setLed(0, RED); __delay_ms(10); } setLed(1, BLUE); setLed(0, OFF); __delay_ms(40); for (c = 0; c < 10; c++) { setLed(1, OFF); __delay_ms(10); setLed(1, BLUE); __delay_ms(10); } }
      
      







ショーダウンのための最も思慮深い質問:この場合__delay_ms(_X_)が設定された_X_ msの5倍以上休止するのはなぜですか?



しかし、それだけではありません。 次に、最も重要な質問である「 このビジネスをオフにする方法 」を検討します。



いつものように、すべての完全なセットがここにありますmultik.org/pic/policelight.rar



All Articles