ArduinずLED、たたは子䟛のデザむナヌをアップグレヌドする方法





私の息子は、 マグネティックコンストラクタヌMagformersにしっかりず「フック」したした。 同じコンストラクタヌが玹介されおいる䞀連のFixiksを芋おみるず、子䟛は「お父さん、なぜフィクティックスには茝いおいる詳现がありたすが、私たちにはありたせんか」ず尋ねたした。



「Magformers Neon LED Set」のセットが実際にあり、通垞のビルディングブロックに加えお、LEDを備えた芁玠もありたす。 この時点たでに、考えられるすべおの圢状ずサむズの磁石の箱党䜓をすでに集めおいたので私にずっおは、 䞭囜のマグフォヌマヌは元のものよりも劣っおいたせん、電球のためだけに別のセットを賌入したくはありたせんでした。 さらに、このセットは、バックラむトなしの同様のセットよりも倧幅にコストがかかりたす。



そこにある成分はほんの数ドルで、そのほずんどはすでに持っおいるず掚定したので、モルグルカを集めるこずにしたした。 はい、オリゞナルにはない効果がありたす。



猫の䞋には、ATTiny85のりむンカヌずWS8212 LEDのLEDパネルのオプションがありたす。 回路、バッテリヌからこの党䜓をどのように䟛絊したか、そしお途䞭でかき集めた明癜でない問題に぀いお話したす。 たた、プロゞェクトの゜フトりェアコンポヌネントに぀いお詳しく説明したす。



最初のステップ



通垞のLEDRGBでさえもの茝きは退屈で平凡なように思えたした。 しかし、WS8212のようなものを感じるのは面癜そうです。 ebeeでは、個別のLEDず最倧16x16サむズのマトリックスの䞡方が提䟛されたした。 いく぀かの異なるモゞュヌルを賌入したので、4x4マトリックスを決定したした。 モゞュヌルにはさたざたな芖芚効果にふけるためのLEDがたくさんありたすが、モゞュヌルのサむズはデザむナヌの正方圢ブロックのりィンドりに匹敵したす。







LEDマトリックスを制埡するには、マむクロコントロヌラヌの1぀のピンで十分であるため、arduino nanoでもバストのように芋えたすさらに、ケヌスに収たりたせん。 しかし、ATTiny85コントロヌラヌのdigisparkクロヌンはちょうど良いこずが刀明したした。メモリヌずピンはそれほど倚くありたせんが、LEDりむンカヌには十分です。 このモゞュヌルはArduino IDEず完党に統合され、USBブヌトロヌダヌが搭茉されおいるため、このモゞュヌルのプログラミングは非垞に簡単で快適です。 私はずっず詊しおみたいず思っおいたした。



最も単玔なスキヌムから始めたした。







この圢匏では、すべおのグロヌ/ブリンクアルゎリズム以䞋に぀いおをすばやくデバッグできたした。 しかし、ワむダヌで動くおもちゃはそうではありたせん。バッテリヌの電力に぀いお考える必芁がありたす。 さらに、フィンガヌバッテリヌで砎産しないようにさらに、これぱンベロヌプに収たらない、リチりムを䜿甚するこずが決定されたした。 リチりム電池があるので、充電方法を考える必芁がありたす。 ビンで、TP4056チップ䞊でその機䌚に賌入された「人気の」充電コントロヌラヌを芋぀けたした。



しかし、すぐには機胜したせんでした。 Digispark ATTiny85モゞュヌルの回路はこのためにあたり蚭蚈されおいたせん-USB電源はありたすが、電源はマむクロコントロヌラに盎接䟛絊されたす+5バス経由、たたはVIN入力からですが、電源は7805リニアスタビラむザヌを通過したす。 USBコネクタずマむクロコントロヌラの間の隙間に挿入されるものは提䟛されたせん。 回路を少し修正し、䜙分な詳现を削陀する必芁がありたした。







そのため、USB電源がVINピンに䟛絊されおから、充電噚入力に進みたす。 充電噚の出力実際には、バッテリヌは盎接接続されおいたすは、5Vフットを介しおボヌドに戻りたす。 たた、実際には3〜4.2Vバッテリヌ電圧がありたすが、これは非垞に正垞です-マむクロコントロヌラヌの動䜜電圧範囲は1.8〜5.5Vです。 たた、LEDモゞュヌルでさえ2.7Vから正垞に動䜜したすが、3.2V未満では青色のLEDが少し䞍足し、色が少し黄色に「浮いおいたす」。



゚ネルギヌを節玄するために、垞時点灯のD2 LEDも消えたした。 䞀般的なスキヌムは次のようになりたす







充電噚のUSBコネクタから回路に絊電するこずは可胜ですが、コントロヌラヌボヌドのUSBコネクタを介しおファヌムりェアをアップロヌドする機胜は倱われたす。 充電甚ずファヌムりェア甚の2぀のUSBコネクタをさたざたな目的で残すこずができたすが、これは䜕らかの圢で間違っおいたす。



eBayで6x25x35サむズのバッテリヌを賌入したしたが、䞍良品であるか、短絡たたは高充電電流ボヌドのデフォルト充電電流は1Aであり、電流を枛らすために1぀の抵抗噚をはんだ付けする必芁がありたすでそれを殺したした。 いずれにせよ、負荷が接続されたずき、10 mAでも、バッテリヌの電圧は1 Vに䜎䞋したした。 テストの時点で、私は小さなクワドロコプタヌから半分死んだリポバッテリヌに切り替えたした。 少し埌に、別の売り手にバッテリヌを泚文したしたが、それは良いこずがわかりたした。



原則ずしお、これで停止し、接続ワむダをはんだ付けしお、ある皮のケヌスにすべおを静かに抌し蟌むこずは可胜ですが、回路の消費量を枬定するこずにしたした。 そしお泣いた。 さお、動䜜状態電球が完党に光るずきでは、このこずは最倧130mAを消費するため、安静時の消費は25mA以䞊です ぀たり このりむンカヌは、600mAhのバッテリヌを1日もかからずに消耗させたす



箄10 mAがLEDを消費するこずが刀明したした。 点灯しおいなくおも、マむクロコントロヌラヌはそれぞれで動䜜し、コマンドを埅機したす。 ぀たり LEDのパワヌダりン回路を考え出す必芁がありたす。



残りの15 mAはマむクロコントロヌラヌによっお消費されたす。 はい、それはベッドに眮くこずができ、デヌタシヌトによるず、消費はマむクロアンペアで枬定されたすが、実際には1 mA未満を埗るこずができたせんでした。 ADCをオフにしお、ピンを入力に倉換したした。 回路のどこかに䜕らかの挏れがあるように芋えたすが、電子機噚に぀いおの私のささやかな知識ではそれを芋぀けお理解するには䞍十分です。



スキヌムを耇雑にしたす



それから私は、私自身がテストのためにPT1502チップを賌入したこずを思い出したした。 このチップは、いく぀かの制埡入力を備えた電源を備えたリチりム電池充電コントロヌラヌです。 唯䞀の難点は、超小型回路が4x4 mm QFN20パッケヌゞに入っおおり、ストラップが必芁なこずです。 これを自宅ではんだ付けするこずは困難ですが、可胜です。 通垞のLUTでは料金は難しく、䞭囜から泚文する必芁がありたす。 しかし、私たちは困難を恐れたせんよね



いく぀かのボックスで、スキヌムを次のように説明できたす。







オフ状態では、コントロヌラヌずLEDに電力は䟛絊されたせん。 デバむスには「電源」ボタンがあり、りむンカヌをオンにしたすモヌドも切り替えたす。 LEDは、たずえば1分間点灯し、ナヌザヌの操䜜がない堎合誰もボタンを抌さない堎合、デバむスはオフになりたす。 ぀たり スリヌプ状態になるだけでなく、Power Hold信号によっお自身の電源をオフにしたす。 そしお、マむクロコントロヌラずLEDの䞡方を䞀床にすべおオフにしたす。 電源オンおよびオフ機胜はPT1502チップ内に実装されおいたす



あずは、回路図を描いお回路基板を䜜成するだけです。 このスキヌムの倧郚分は、PT1502デヌタシヌトずDigispark ATTiny85モゞュヌルで構成されおいたす。 PT1502パワヌコントロヌラヌマむクロチップは機胜的にいく぀かの郚分に分割されおいるため、回路内のブロックに分割されおいたす。







実際、これは独自のハヌネスを備えたリチりム電池充電コントロヌラヌです。 LED1は充電状態を瀺したす-オンの堎合、充電はオンです。 抵抗R6は充電電流を470mAに蚭定したす。 私は600mAhのバッテリヌを持っおいるので、原則ずしお、電流を増やしお、最倧600mAたで780-800オヌムの抵抗を眮くこずができたす。 ただし、バッテリヌの特別な品質に぀いおは確信がありたせん。よりゆっくり充電する方が良いのですが、長持ちしたす。



電源プランを怜蚎する







SW1ボタンはシステム党䜓を起動したす-PT1502チップはそれ自䜓を起動し、すべおの電源うち3぀を起動したす。 電源がむンストヌルされるず、マむクロ回路はRESET信号を解攟しおマむクロコントロヌラヌを起動したす。 デバッグを簡単にするために、個別のリセットボタンも远加したした。



HOLD信号は、システム党䜓をオフにするために䜿甚されたす。 マむクロコントロヌラヌが起動するず、このラむンでナニットを蚭定する必芁がありたす。 四捚五入する時間になるず、マむクロコントロヌラはHOLDラむンにれロを蚭定し、PT1502電源チップはすべおの電源を停止したす。



BAT_LOW出力の助けを借りお䜎バッテリヌレベルを远跡するこずは可胜ですが、この蚘事ではそれを採点したした-デヌタを保存する必芁はなく、時間内にバッテリヌ切れに気付かない堎合は䜕も爆発したせん。 死ぬほど死ぬ。 しかし、念のため、取締圹䌚はこのビゞネスの連絡先を提䟛したした。



SW1ボタンに戻りたしょう。 電源をオンにするためず制埡するために、2぀の個別のボタンを䜜成しないこずにしたした。 したがっお、同じボタンがATTiny85にも接続され、動䜜䞭に点滅モヌドが切り替わりたす。 分呚噚R7〜R8の倀は、PB2マむクロコントロヌラヌのポヌトを焌かないように遞択されたす。 すべおのバッテリヌ電圧範囲3.3-4.2Vで、指定されたデヌタシヌト制限0.7 * VCC-VCC + 0.5V内でコントロヌラヌの足に電圧が䟛絊されたす。



電源を怜蚎する







これは、パルスDC-DCコンバヌタヌです。 出力電圧は抵抗R10〜R11によっお蚭定され、デヌタシヌトの匏に埓っお3.3Vに蚭定されたす。 他のすべおは単玔なストラップです。



良いこずには、このようなだたされた電源は実際には必芁ありたせん。䞀般にバッテリヌから盎接マむクロコントロヌラヌに電力を䟛絊するこずが可胜です。 この゜ヌスはすでにPT1502チップに実装されおおり、必芁なずきにオン/オフできるので、䜿甚しないのはなぜですか







チップには2぀の線圢安定装眮もありたすが、私はそれらを䜿甚したせん。 残念ながら、刀明したように、この゜ヌスに入力電圧を䟛絊する必芁がありたす。そうしないず、マむクロ回路は電力がただ十分に安定しおいないず刀断し、マむクロコントロヌラを起動したせん



論理郚分に移りたしょう。







USBケヌブルは、倉曎されずにDigisparkボヌドからラップされたす。 これは、USB電圧3.3Vを実行ずマむクロコントロヌラの信号オリゞナルでは5Vで駆動を䞀臎させるために必芁です。 私の堎合、マむクロコントロヌラも3.3Vで駆動されるため、回路を簡玠化できたすが、念のため、ボヌド䞊の元の回路ず離婚したした。







マむクロコントロヌラヌのバむンディングには興味深いものはありたせん。



最埌の仕䞊げはコネクタです







実際、USBサポヌトを備えたATTiny85ず、リチりムバッテリヌを備えた電源コントロヌラヌで、このようなデバッグボヌドを手に入れたした。 したがっお、LEDにラむンを出力するだけにずどたりたせんでした。 代わりに、マむクロコントロヌラヌのすべおのラむンをくしに持っおきたした-同時にプログラマヌに接続するず䟿利です。



そしお、ほがすべおの回線を特定の機胜PB1-保留回線、PB2-電源ボタン、PB3 / PB4-USB、PB5-リセットに厳密に結び付けお、将来、いく぀かの制限をバむパスできるようにしたす。 たずえば、USBケヌブルをはんだ付けせず、PB3 / PB4ラむンを解攟しないでください。 たたは、たずえば、リセットを䞭止しおPB5を解攟したす。 それたでの間、PB0のみがフリヌのたたで、LEDを接続したす。



ボヌドに枡したす。 40x40mmのボヌドのサむズ、コンポヌネントの数、PT1502チップのQFN20ハりゞングの制限を考えるず、ボヌドを自宅で補造するこずすら考えおいたせんでした。 したがっお、私はすぐに最もコンパクトな2局ボヌドを繁殖し始めたした。 それは私が埗たものです







䜿いやすさのために、裏偎ですべおの可胜な出力機胜に眲名したしたアむデアはDigisparkボヌドに匕っかかっおいたす







JLCPCBでボヌドを泚文したした 。 正盎なずころ、品質にあたり満足しおいたせん。チップを䜕床もはんだ付けするず、PT1502の小さな接点の近くのマスクが少し曇っおしたいたす。 さお、小さな碑文が少し浮かんできたした。 ただし、すべおが初めおはんだ付けされる堎合は、暙準です。



QFN20をはんだ付けするには、はんだごおが必芁です。他のすべおのものは、特定のはんだごおで特定のスキルではんだ付けできたす。 これは、はんだ付けされたボヌドの倖芳です







本䜓



身䜓に移る時です。 3Dプリンタヌで印刷したした。 食り気のないデザむン-ボックスずボタン。 デザむナヌの暙準的な正方圢モゞュヌルにホタルをむンストヌルするための特別なフックがボックスに甚意されおいたす。







メむンボヌドずバッテリヌはケヌスに収玍されおいたす。











LEDパネルはカバヌに取り付けられおおり、カバヌはメむンボックスにネゞで固定されおいたす



最初はネゞでLEDパネルをカバヌにねじ蟌むこずを考えおいたしたが、最終的には䞡面テヌプに貌り付けたした。 このようになった







この圢匏では、デバむスはすでに䜿甚できたすが、それでもstillいように芋えたす-十分なディフュヌザヌがありたせん。



私は、建物のドラむダヌでのペットボトルの収瞮の技術を䜿甚しお、ディフュヌザヌの最初のバヌゞョンを䜜ろうずしたした航空機のモデルで芗きたした。



そのため、最初に空癜が必芁です。 私は石膏からそれを䜜り、それを3Dプリンタヌで印刷したフォヌムに泚ぎたした。 最初のバヌゞョンでは、金型はワンピヌスで、キャストディスクを取り出すこずができたせんでした。 そのため、2ピヌスのフォヌムを䜜成する必芁がありたした。







この方法の考え方は次のずおりです。 ベビヌペヌグルトのボトルをブランクの䞊に眮き、建蚭甚ヘアドラむダヌず䞀緒に座りたす。 これは、異なる牛乳の䞋から20個の異なる容噚の䞀郚を再移怍するだけです。折り目や泡のないこのものをうたく配眮するこずはできたせんでした。 どうやら、䜕らかの真空装眮をフェンスで囲み、プラスチックシヌトを取り付ける必芁がありたす。 䞀般的に、そのような技術には難しすぎるこずが刀明したした。



ホリネズミを䞍平を蚀った埌、数メヌトルのVerbatim PET Transparentプラスチックプロヌブを芋぀けたした。 ただ印刷するためにディフュヌザヌを詊すこずにしたした。 プリンタの入り口ではプラスチックは透明に芋えたすが、実際の郚分はマットです。 これはおそらく、内郚構造によるものです。 レむダヌはボリュヌムを完党には埋めたせんが、ギャップやギャップず重なりたす。 さらに、衚面をより滑らかにするためにサンドペヌパヌで郚品を凊理しようずするず、さらにマットがかかりたす。 ただし、これはたさに私が必芁ずしたものです。



私はディフュヌザヌのマりントを気にするのが面倒だったので、ホットグルヌに远加したした。 したがっお、私のデザむンは条件付きで折りたたみ可胜になりたした。 ある皮のラッチの発明ず混同される可胜性がありたすが、すでに透明なプラスチックプロヌブが䞍足しおいたす。 それでホットメルトにしたしょう。











ファヌムりェア



LEDりむンカヌの堎合、特にマむクロコントロヌラヌの呚蟺に飛び蟌む必芁はありたせん。GPIOを操䜜するための機胜は2぀あれば十分です。 しかし、モゞュヌルはArduinoプラットフォヌムにドッキングされおいるので、これを掻甚しおみたせんか



最初に、いく぀かの定矩ず定数



// Number of total LEDs on the board. Mine has 4x4 LEDs #define NUM_HW_PIXELS 16 // Pin number where LED data pin is attached #define DATA_PIN 0 // Pin number where mode switch button is attached #define BUTTON_PIN 2 // Power Enabled pin #define POWER_EN_PIN 1 // Max brightness (dimming the light for debugging) #define MAX_VAL 255
      
      





これにより、マトリックスのピクセル数、ピン番号、およびLEDの最倧茝床が決たりたすデバッグ䞭は、目を盲目にしないように50に蚭定するず䟿利でした



私のマトリックス内のLEDは、ゞグザグずいうかなり非自明な方法で配眮されおいたす。 したがっお、さたざたな効果のために、番号を付け盎す必芁がありたした。



 // LED indexes for different patterns uint8_t circleLEDIndexes[] = {0, 1, 2, 3, 4, 11, 12, 13, 14, 15, 8, 7}; uint8_t beaconLEDIndexes[] = {6, 5, 10, 9}; uint8_t policeLEDIndexes[] = {7, 6, 10, 11, 4, 5, 9, 8};
      
      





LEDを制埡するために、私は自転車を発明せず、WS8211 LEDを操䜜するための既補のラむブラリを甚意したした 。 ラむブラリむンタヌフェヌスはわずかに癜塗りされおいたす。 いく぀かの補助機胜たずえば、HSVからRGBぞの倉換もそこに留たりたした。



最初に、ボヌドずWS8211ラむブラリを初期化する必芁がありたす。



 // Driver Ai_WS2811 ws2811; void setup() { // Set up power pinMode(POWER_EN_PIN, OUTPUT); digitalWrite(POWER_EN_PIN, HIGH); // initialize LED data pin pinMode(LED_PIN, OUTPUT); // Initialize button pin pinMode(BUTTON_PIN, INPUT); // Initialize WS8211 library static CRGB ledsBuf[NUM_HW_PIXELS]; ws2811.init(DATA_PIN, NUM_HW_PIXELS, ledsBuf); // Set the watchdog timer to 2 sec wdt_enable(WDTO_2S); }
      
      





たず、POWER HOLD信号を1に蚭定する必芁がありたす。これは、マむクロコントロヌラヌが巻き䞊げられ、正垞に動䜜しおいるこずを瀺すPT1502チップぞの信号になりたす。 次に、HOLD信号が1に蚭定されるたで、マむクロ回路はマむクロコントロヌラヌずLEDに定期的に電力を䟛絊したす。



次に、出力のLEDず入力のボタンを制埡するための脚を構成したす。 その埌、WS8211ラむブラリを初期化できたす。



これはかなり自埋的なデバむスであるため、マむクロコントロヌラヌが理解できない状態に固執し、バッテリヌ党䜓を消耗させるこずは䞍可胜です。 これを行うには、りォッチドッグタむマヌを2秒間起動したす。 タむマヌはメむンプログラムルヌプで再起動したす。



ここで、いく぀かの補助関数を定矩する必芁がありたす。 WS8211ラむブラリは、各LEDの色の倀を含むバッファを保存したす。 特定のLEDにRGB倀を曞き蟌むための単玔な関数を䜜成したため、バッファを盎接操䜜するこずはあたり䟿利ではありたせん。



 void setRgb(uint8_t led_idx, uint8_t r, uint8_t g, uint8_t b) { CRGB * leds = ws2811.getRGBData(); leds[led_idx].r = r; leds[led_idx].g = g; leds[led_idx].b = b; }
      
      





しかし、ほずんどの堎合、RGBカラヌモデルでは、色のカりントはあたり䟿利ではなく、䞍可胜です。 たずえば、あらゆる皮類の虹を描く堎合、HSVカラヌモデルを䜿甚するず䟿利です。 各ピクセルの色は、色調ず明るさの倀によっお蚭定されたす。 簡単にするために圩床は省略されおいたす最倧倀が䜿甚されたす。 色盞倀は、暙準の0-359ではなく0-255の範囲に瞮小されたす。



 /** * HVS to RGB conversion (simplified to the range 0-255) **/ void setHue(uint8_t led_idx, int hue, int brightness) { //this is the algorithm to convert from RGB to HSV double r = 0; double g = 0; double b = 0; double hf = hue/42.6; // Not /60 as range is _not_ 0-360 int i=(int)floor(hue/42.6); double f = hue/42.6 - i; double qv = 1 - f; double tv = f; switch (i) { case 0: r = 1; g = tv; break; case 1: r = qv; g = 1; break; case 2: g = 1; b = tv; break; case 3: g = qv; b = 1; break; case 4: r = tv; b = 1; break; case 5: r = 1; b = qv; break; } brightness = constrain(brightness, 0, MAX_VAL); setRgb(led_idx, constrain(brightness*r, 0, MAX_VAL), constrain(brightness*g, 0, MAX_VAL), constrain(brightness*b, 0, MAX_VAL) ); }
      
      





この関数はAi_WS8211ラむブラリから取埗され、わずかにファむルされおいたす。 ラむブラリのこの関数の元のバヌゞョンには、虹の色がぎざぎざで衚瀺されおいたいく぀かのバグがありたした。



さたざたな効果の実装に移りたしょう。 各関数はメむンルヌプから呌び出され、1぀の「フレヌム」を描画したす。 各゚フェクトは呌び出し間で異なるパラメヌタヌで動䜜するため、静的倉数に栌玍されたす。



これが最も簡単な効果です。すべおのLEDが1色で塗り぀ぶされおおり、滑らかに倉化したす。



 void rainbow() { static uint8_t hue = 0; hue++; for (int led = 0; led < NUM_HW_PIXELS; led++) setHue(led, hue, MAX_VAL); ws2811.sendLedData(); delay(80); }
      
      





次の効果はより興味深い-マトリックスの茪郭に沿っお虹を衚瀺し、虹の色が埐々に円にシフトしたす。



 void slidingRainbow() { static uint8_t pos = 0; pos++; for (int led = 0; led < ARRAY_SIZE(circleLEDIndexes); led++) { int hue = (pos + led*256/ARRAY_SIZE(circleLEDIndexes)) % 256; setHue(circleLEDIndexes[led], hue, MAX_VAL); } ws2811.sendLedData(); delay(10); }
      
      





そしお、この効果は、マトリックス党䜓をランダムな色で塗り぀ぶしたす。ランダムな色は、最初は滑らかに点灯し、次に滑らかに消えたす。



 void randomColorsFadeInOut() { static uint8_t color = 0; static bool goesUp = false; static uint8_t curLevel = 0; if(curLevel == 0 && !goesUp) { color = rand() % 256; goesUp = true; } if(curLevel == MAX_VAL && goesUp) { goesUp = false; } for(int led = 0; led < NUM_HW_PIXELS; led++) setHue(led, color, curLevel); if(goesUp) curLevel++; else curLevel--; ws2811.sendLedData(); delay(10); }
      
      





次のグルヌプの゚フェクトは、異なる点滅ビヌコンを描画したす。 したがっお、たずえば、子䟛は磁石でブルドヌザヌを䜜るのが奜きで、そこでオレンゞ色のフラッシャヌが非垞に圹立ちたす。



 void orangeBeacon() { const int ORANGE_HUE = 17; static uint8_t pos = 0; pos+=3; for (int led = 0; led < ARRAY_SIZE(circleLEDIndexes); led++) { int brightness = brightnessByPos(pos, led*255/ARRAY_SIZE(circleLEDIndexes), 70); setHue(circleLEDIndexes[led], ORANGE_HUE, brightness); } ws2811.sendLedData(); delay(1); }
      
      





技術的には、効果はマトリックスに沿っお移動する明るいドットのように芋えたす。 しかし、芋た目を矎しくするために、メむンポむントから離れるず、隣接するLEDは埐々に消えおいきたす。 したがっお、この同じ明るさを蚈算する関数が必芁でした。



 int brightnessByPos(int pos, int ledPos, int delta) { int diff = abs(pos - ledPos); if(diff > 127) diff = abs(256-diff); int brightness = MAX_VAL - constrain(MAX_VAL*diff/delta, 0, MAX_VAL); return brightness; }
      
      





Posは、明るさの茝点の特定の条件付き䜍眮であり、ルヌプバック範囲0〜255にマッピングされたす。 ledPosは、茝床を蚈算する必芁があるLED同じ範囲に衚瀺されるの䜍眮です。 䜍眮の差がデルタより倧きい堎合、LEDは点灯せず、䜍眮に近づくほど明るくなりたす。



たたは、たずえば、譊察の赀青点滅ラむト



 void policeBeacon() { const int RED_HUE = 0; const int BLUE_HUE = 170; static uint8_t pos = 0; pos += 2; for (int led = 0; led < ARRAY_SIZE(policeLEDIndexes); led++) { int ledPos = led*255/ARRAY_SIZE(policeLEDIndexes); int brightness = brightnessByPos(pos, ledPos, 50); setHue(policeLEDIndexes[led], RED_HUE, brightness); if(brightness == 0) { brightness = brightnessByPos((pos+100) % 256, ledPos, 50); setHue(policeLEDIndexes[led], BLUE_HUE, brightness); } } ws2811.sendLedData(); delay(1); }
      
      





車に぀いお話しおいるので、ここの信号機は実装するのに問題ではありたせん。



これらは、さたざたな䜍眮にさたざたな亀通信号を含む機胜です。



 void clearPixels() { for(int i=0; i<NUM_HW_PIXELS; i++) { setRgb(i, 0, 0, 0); } } void redTrafficLights() { for(int i=0; i<4; i++) setRgb(i, MAX_VAL, 0, 0); ws2811.sendLedData(); } void yellowTrafficLights() { for(int i=4; i<8; i++) setRgb(i, MAX_VAL, MAX_VAL, 0); ws2811.sendLedData(); } void greenTrafficLights() { for(int i=8; i<16; i++) setRgb(i, 0, MAX_VAL, 0); ws2811.sendLedData(); }
      
      





それを埩掻させる時が来たした。 信号機は、䞀皮のバむトコヌドで定矩された特別なプログラムに埓っお動䜜したす。 プレヌトには、モヌドず、このモヌドをオンにする必芁のある時間が蚘茉されおいたす。



 enum TRAFFIC_LIGHTS { NONE, RED, YELLOW, GREEN }; struct trafficLightState { uint8_t state; uint16_t duration; }; const trafficLightState trafficLightStates[] = { {NONE, 1}, // clear yellow {RED, 7000}, // red {YELLOW, 2000}, // red + yellow {NONE, 1}, // clear red+yellow {GREEN, 7000}, // green {NONE, 300}, // Blinking green {GREEN, 300}, // Blinking green {NONE, 300}, // Blinking green {GREEN, 300}, // Blinking green {NONE, 300}, // Blinking green {GREEN, 300}, // Blinking green {NONE, 1}, // clear green {YELLOW, 2000}, // yellow };
      
      





実際にそれをすべお凊理する機胜



 void trafficLights() { static uint8_t curStateIdx = 0; static unsigned long curStateTimeStamp = 0; // Switch to a new state when time comes if(millis() - curStateTimeStamp > (unsigned long)trafficLightStates[curStateIdx].duration) { curStateIdx++; curStateIdx %= ARRAY_SIZE(trafficLightStates); curStateTimeStamp = millis(); } switch(trafficLightStates[curStateIdx].state) { case NONE: clearPixels(); ws2811.sendLedData(); break; case RED: redTrafficLights(); break; case YELLOW: yellowTrafficLights(); break; case GREEN: greenTrafficLights(); break; default: break; } // Just waiting delay(10); }
      
      





蚭定した時間間隔に達するず、次の信号モヌドがオンになり、カりントダりンが再び開始されたす。



私の想像力で十分だった最埌の効果はアスタリスクです。 5個のランダムLEDがランダムな明るさで点灯しおから、スムヌズに消灯したす。 1぀の星が消えるず、ランダムな堎所にある別の星が点灯したす。



 void stars() { const uint8_t numleds = 5; static uint8_t ledIndexes[numleds] = {0}; static uint8_t curVal[numleds] = {0}; static uint8_t maxVal[numleds] = {0}; for(int i=0; i<numleds; i++) { if(ledIndexes[i] == 0) { uint8_t led = rand() % (NUM_HW_PIXELS+1); CRGB * leds = ws2811.getRGBData(); if(leds[led].r == 0) { ledIndexes[i] = led; maxVal[i] = rand() % (MAX_VAL-1) + 1; curVal[i] = 0; } } else { uint8_t led = ledIndexes[i]; if(curVal[i] < maxVal[i]) curVal[i]++; else if(curVal[i] == maxVal[i]) maxVal[i] = 0; else if(curVal[i] == 0 || --curVal[i] == 0) ledIndexes[i] = 0; setRgb(led-1, curVal[i], curVal[i], curVal[i]); } } ws2811.sendLedData(); delay(80); }
      
      





ここのどこかに邪悪なバグが忍び蟌んできたした。 時々、星が鋭く点灯したり、逆に突然消えたりしたす。 しかし、正盎なずころ、私はこれに察凊するのが面倒でした-それは非垞に普通に芋えたす。



バッテリヌの節玄に぀いお考える時が来たした。 私はすでにこのすべおの消費䟡倀を䞎えおいたす。 電源を切るこずを考えない堎合、LEDは数時間でバッテリヌを消耗したす。 この機胜は、90秒間䜕も操䜜しないず電源を切る圹割を果たしたす。 最初は60秒でしたが、実際のゲヌムではこれでは十分ではなく、2分はすでに䜕ずか長いこずがわかりたした。



 void shutdownOnTimeOut(bool resetTimer = false) { static unsigned long periodStartTime = 0; if(periodStartTime == 0 || resetTimer) { periodStartTime = millis(); return; } if(millis() - periodStartTime >= 90000UL) { periodStartTime = 0; shutDown(); } }
      
      





実際には、次のように電源が切れたす。



 void shutDown() { clearPixels(); ws2811.sendLedData(); wdt_disable(); digitalWrite(POWER_EN_PIN, LOW); // No power after this point while(true) ; }
      
      





ナヌザヌがボタンを抌すず、タむマヌがリセットされたす。 蚭定時間が経過するず、この関数はHOLD信号をれロに蚭定したす。これは、電源をオフにするPT1502コマンドです。 ちなみに、りォッチドッグも停止する必芁がありたす。停止しないず、2秒埌にシステムがりェむクアップされ、電源が再びオンになりたす。



最埌に、すべおを開始するメむンルヌプ



 // List of pointers to functions that serve different modes void (*Modes[])() = { rainbow, slidingRainbow, orangeBeacon, policeBeacon, trafficLights, stars, randomColorsFadeInOut }; void loop() { static uint8_t mode = eeprom_read_byte( (uint8_t*) 10 ); static bool waitingForBtnUp = false; static long btnPressTimeStamp; // Button switches mode if(digitalRead(BUTTON_PIN) == HIGH && !waitingForBtnUp) { delay(20); if(digitalRead(BUTTON_PIN) == HIGH) { mode++; mode %= ARRAY_SIZE(Modes); // num modes clearPixels(); ws2811.sendLedData(); delay(1); eeprom_write_byte( (uint8_t*) 10, mode ); waitingForBtnUp = true; btnPressTimeStamp = millis(); shutdownOnTimeOut(true); } } // Shut down on long press over 5s if(digitalRead(BUTTON_PIN) == HIGH && waitingForBtnUp && millis() - btnPressTimeStamp > 5000) shutDown(); // Detect button release if(digitalRead(BUTTON_PIN) == LOW && waitingForBtnUp) waitingForBtnUp = false; // display LEDs according to current mode Modes[mode](); // pong shutdown timer shutdownOnTimeOut(); // Yes, we still alive wdt_reset(); }
      
      





ボタンを抌すず、モヌドが切り替わり、自動オフタむマヌがリセットされたす。 珟圚のモヌドに応じお、「モヌド」リストの゚フェクト機胜の1぀が起動したす。 各サむクルで、りォッチドッグもリセットされたす。



たずえば、子䟛がパトカヌをプレむしおいお、1.5分埌に非垞灯がオフになった堎合、2番目のタヌン埌に息子がパトカヌをプレむし続ける可胜性が高くなりたす。 これを行うには、遞択したモヌドがEEPROMに保存されたすセル番号10はブルドヌザヌから遞択されたす。



これがすべおの仕組みを瀺すビデオです。





ブヌトロヌダヌ



ほずんどすべおの準備が敎いたした。 しかし、提出する必芁があるもう1぀のものがありたす-ブヌトロヌダヌ。 実際には、暙準のブヌトロヌダヌは私たちに適しおいないずいうこずです。



たず、電源を入れるず、6秒間埅機したす-ファヌムりェアが電源を入れ始める可胜性がありたす。 この制埡がメむンファヌムりェアに転送された埌にのみ。 これは開発段階では䟿利ですが、完成したデバむスでは迷惑になりたす。



次に、暙準のブヌトロヌダヌはPT1502チップに぀いお䜕も認識しおいたせん。これは、HOLDシグナルを䞎えるず䟿利です。 この信号がなければ、マむクロ回路は、マむクロコントロヌラが起動しなかったか、たたは逆にオフにしたいず考えおいたす。 もしそうなら、数ミリ秒埌にPT1502は回路党䜓ぞの電力を遮断したす。



䞡方の問題を修正するこずの利点は難しくありたせん。 digispark ATTiny85は小栞ブヌトロヌダヌを䜿甚したす 。 このブヌトロヌダヌは、必芁に応じおファむルを䜜成するのが非垞に簡単です。 構成ファむル内の察応する定矩を修正するだけです。



たず、暙準ファヌムりェア\ configuration \ t85_default configurationを自分のディレクトリにコピヌし、すでにすべおの倉曎を加えたした。 そのため、元のブヌトロヌダヌに簡単にロヌルバックできたす。



bootloaderconfig.hファむルには、ブヌトロヌダヌに入る方法の遞択がありたす。 箱から出しお提䟛されるものから、私たちに適したものはありたせんが、最も近いオプションはENTRY_JUMPERです。 このバヌゞョンでは、特定のレベルが特定のピンに衚瀺されおいる堎合にのみブヌトロヌダヌにアクセスしたすボヌド䞊でゞャンパヌが閉じられたす。



 #define ENTRYMODE ENTRY_JUMPER
      
      





ゞャンパヌはありたせんが、PB2の脚にボタンがありたす。 電源がオンになったずきにボタンを5〜7秒間抌し続けるず、ブヌトロヌダヌが起動したす。 ただし、抌しお離すず、メむンファヌムりェアぞの移行がすぐに行われたす。



3぀の関数を定矩する必芁がありたす-初期化、初期化解陀、そしお実際にブヌトロヌダヌに入る時かどうかの確認。 オリゞナルでは、それらはすべおシンプルで、マクロで実装されおいたす。 最初の2぀だけがシンプルになりたす



 #define HOLD_PIN PB1 #define JUMPER_PIN PB2 #define JUMPER_PORT PORTB #define JUMPER_DDR DDRB #define JUMPER_INP PINB #define bootLoaderInit() {JUMPER_DDR &= ~_BV(JUMPER_PIN); JUMPER_DDR |= _BV(HOLD_PIN); JUMPER_PORT &= ~_BV(JUMPER_PIN); JUMPER_PORT |= _BV(HOLD_PIN); _delay_ms(1);} #define bootLoaderExit() {;}
      
      





bootLoaderInitは、ボタンピンJUMPER_PINがサスペンダヌに入るように蚭定し、オフにしたす。 さらに、ボヌド䞊のプルアップが既に地面にあり、ピンのボタンを抌すず、反察にボタンがありたす。 同時に、すぐにホヌルド信号を蚭定しお出力し、ナニットを蚭定するこずができたす...



ビット挔算の説明に぀いおは、たずえばここを参照しおください。AVRコントロヌラヌのGPIOセットアップレゞスタに぀いおは、たずえばここから参照できたす 。



bootLoaderExit関数は空です 公開された構成は、メむンファヌムりェアぞの埌続の移行に非垞に適しおいたす



bootLoaderStartCondition関数は、ブヌトロヌダヌをマクロ圢匏で入力する圹割を担っおいたすが、適合しおいないため、本栌的な機胜になりたした。



 #ifndef __ASSEMBLER__ // Bootloader condition is to hold the button for 5 seconds inline unsigned char bootLoaderStartCondition() { long int i; for(i=0; i<10000000; i++) if( !(JUMPER_INP & _BV(JUMPER_PIN))) return 0; return 1; } #endif
      
      





数秒以内実際には玄6〜7に関数がボタンのステヌタスをチェックしたす。 ボタンが以前にリリヌスされた堎合、ブヌトロヌダヌに入る必芁はありたせん。 患者ず氞続的なブヌトロヌダヌに蚱可されおいたす。



刀明したように、bootloaderconfig.hファむルはアセンブラファむルのコンパむルに関䞎しおおり、このファむル内のコヌドが゚ラヌを匕き起こしたす。 関数を#ifndef __ASSEMBLER__ブロックに入れる必芁がありたした



私が埮調敎した別のパラメヌタヌは、USBに接続されおいない堎合の察凊方法をブヌトロヌダヌに指瀺したす-1秒埌に終了したす。 実際には、䟵入䞭に、息子がボタンを抌すこずが倚く、誀っおブヌトロヌダヌに䟵入したこずがありたす。 どれほど奇跡的かはわかりたせんが、ブヌトロヌダヌがUSB接続を認識しないず、誀っお䞀郚のメモリペヌゞが䞊曞きされる可胜性がありたす。 したがっお、接続がない堎合、単にメむンプログラムに戻りたす。



 /* * Define bootloader timeout value. * * The bootloader will only time out if a user program was loaded. * * AUTO_EXIT_NO_USB_MS The bootloader will exit after this delay if no USB is connected. * Set to 0 to disable * Adds ~6 bytes. * (This will wait for an USB SE0 reset from the host) * * All values are approx. in milliseconds */ #define AUTO_EXIT_NO_USB_MS 1000
      
      





コンパむルしたす...そしお、割り圓おられたブヌトロヌダヌスペヌスにコヌドが収たらないずいう゚ラヌが衚瀺されたす。 コントロヌラヌのフラッシュメモリは非垞に小さいため、ブヌトロヌダヌはメむンプログラム甚により倚くのスペヌスを確保するために最倧限に圧瞮されたす。 ただし、これはMakefile.incファむルで指瀺に埓っお簡単に修正できたす。



 # hexadecimal address for bootloader section to begin. To calculate the best value: # - make clean; make main.hex; ### output will list data: 2124 (or something like that) # - for the size of your device (8kb = 1024 * 8 = 8192) subtract above value 2124... = 6068 # - How many pages in is that? 6068 / 64 (tiny85 page size in bytes) = 94.8125 # - round that down to 94 - our new bootloader address is 94 * 64 = 6016, in hex = 1780 BOOTLOADER_ADDRESS = 1940
      
      





次に、ブヌトロヌダヌの開始アドレスを1ペヌゞ64バむトに枛らし、ブヌトロヌダヌのスペヌスを増やしたした。



それ以倖の堎合、USBAspプログラマヌを䜿甚しおブヌトロヌダヌをコンパむルおよびアップロヌドするこずは問題ではありたせんでした。



おわりに



ブレッドボヌド䞊のプロトタむプから完成したデバむスたで非垞に興味深い方法でした。 arduinoレッスンの普通のたばたきのように芋えたすが、実際、䜜業の過皋で、私は倚くの興味深い問題を解決しなければなりたせんでした-消費ずの闘争、芁玠ベヌスの遞択、ケヌスのデザむン、そしおブヌトロヌダヌを備えたファヌムりェアを思い浮かべたす。 私の経隓が誰かに圹立぀こずを心から願っおいたす。



簡単だったでしょうか もちろんできたす。 トランゞスタですべおができるず思いたす。 残念ながら、ボヌドをはんだ付けした埌にこの蚘事を読みたした。 私は以前の蚘事を芋るだろう-私は同じ人気のTP4056ですべおをするだろう-それをはんだ付けする方が簡単です。 ずにかく、このデバむスのPT1502内にあるDC-DCコンバヌタヌは、必芁ありたせん。 ただし、PT1502超小型回路の実甚的な研究は、QFN20パッケヌゞで超小型回路をはんだ付けする胜力ず同様に、他のプロゞェクトにも圹立ちたす。



最埌に、私のプロゞェクトぞのリンクは次のずおりです。



ファヌムりェアコヌド

回路ずボヌド

ケヌスずディフュヌザヌモデル

印刷甚のすぐに䜿えるSTLモデル



All Articles