Arduinoのスターウォーズスタイルのミュージカルドアベル

みなさん、こんにちは。さっきの話ではありませんが、ビデオでArduinoを使用してAttiny13をフラッシュする方法を示しました。次に、この実用的なアプリケーションを紹介します。



すぐに言いますが、ヒューズ、HEXファイル形式のファームウェア、Cコード、Arduino IDEのスケッチ、Proteus 7のファイルは記事の最後にダウンロードできます。



まあ、なんてプル、それがどのように機能するかを紹介します:







ボタンを押したときにスターウォーズのエンパイアマーチ(帝国のマーチまたはダースベイダーのテーマ)を演奏するために、私は長い間このような音楽的なドアベルを持ちたいと思っていました。





上記のビデオの名前が示すように、デバイスの主要コンポーネントはAttiny13マイクロコントローラーであり、その使用により、ボードをマッチボックスよりも数倍小さくすることが可能になりました。



ボード寸法




そして今、すべてが接続されています:









電力範囲は約2 V〜6 V、つまり2〜4個の単三電池ですが、3〜4 Vの電圧を供給することが理想的です。つまり、携帯電話のリチウムイオン電池または18650電池がこれらの目的に最適です。私はまだ深い放電に対する保護を実装していないので、彼が保護されることが本当に望ましいです。



さて、私は回路に関するいくつかの言葉を言います:



ダイアグラムは次のようになります(Proteusファイルは記事の最後に添付されています。ブレッドボードには何も収集できません)。



プロテウスで描かれた
画像





マイクロコントローラーは、家全体で鳴るのに十分な音量を独立して引き出すことができないため、原則として、かなり一般的なトランジスタであるNPN 2N3904トランジスターを追加しました。

3本の単三電池を使用する場合、トランジスタは少し暖まり、2本使用する場合、ボリュームはまあまあのレベルのままでしたが、トランジスタはすでにわずかに暖かかっていました。

抵抗器R2はマイクロコントローラーの標準ハーネスであり、マイクロコントローラーの偶発的な再起動から保護します。原則として、抵抗器R2はそれなしで動作し、抵抗器R1はトランジスターに基づいて電流を制限します。

保護ダイオードも写真で見えます。これは不注意、つまり極性反転から保護します。私の場合、極性反転はマイクロコントローラーを非常に迅速に無効にし、花火や効果音は非常に可能です。 ところで、下の図では、10 Vの電圧と200 mAの電流用に設計されたダイオードが適切で、マイナスまたはプラスのいずれかでボードの入力と直列に配置されていることを示すのを忘れましたが、マイナスがあります。

ちなみに、古いZyxelダイヤルアップモデムのスピーカー、ところで、この会社のダイヤルアップモデムに関するジョークが1つあります。



逸話
2人のハッカーが座っており、猫が部屋に入ります。 1人のハッカーが尋ねる:

-あなたの猫?

-はい、私のもの。 名前はZuchelです!

-なぜズチェルなのか?

-ここを見て。 彼はほうきを取り、猫の中でそれらをつついて言います。

-Pshshshshshshshshshshshshshsh!







コードは、すぐに言ってグーグルで検索するか、YouTubeで見つけたものです。動画自体は次のとおりです。







ビデオの下に、コードへのリンクがあります 。ここにあります:



ビデオの説明からのコード
#include <avr/pgmspace.h> // by @tartakynov // programmed for ATtiny13 in Arduino IDE using core13 http://sourceforge.net/projects/ard-core13/ #define PIN_LED 1 #define PIN_BUZZER 0 #define COUNT_NOTES 39 word frequences[COUNT_NOTES] PROGMEM = { 392, 392, 392, 311, 466, 392, 311, 466, 392, 587, 587, 587, 622, 466, 369, 311, 466, 392, 784, 392, 392, 784, 739, 698, 659, 622, 659, 415, 554, 523, 493, 466, 440, 466, 311, 369, 311, 466, 392 }; word durations[COUNT_NOTES] PROGMEM = { 350, 350, 350, 250, 100, 350, 250, 100, 700, 350, 350, 350, 250, 100, 350, 250, 100, 700, 350, 250, 100, 350, 250, 100, 100, 100, 200, 100, 350, 250, 100, 100, 100, 200, 100, 350, 250, 100, 750 }; void setup() { pinMode(PIN_LED, OUTPUT); pinMode(PIN_BUZZER, OUTPUT); } void loop() { for (byte i = 0; i < COUNT_NOTES; i++) { buzz(PIN_BUZZER, pgm_read_word(&(frequences[i])), 2 * pgm_read_word(&(durations[i]))); delay(100); } delay(3000); } void buzz(unsigned char pin, word frequencyInHertz, word timeInMilliseconds) { long delayAmount = (long)(long(1000000) / (long)frequencyInHertz); long loopTime = (long)(((long)timeInMilliseconds * 500) / delayAmount); for (long i = 0; i < loopTime; i++) { digitalWrite(pin, HIGH); delayMicroseconds(delayAmount); digitalWrite(pin, LOW); delayMicroseconds(delayAmount); } }
      
      





バイナリのスケッチサイズ:946バイト(最大1,024バイトのうち)





ご覧のとおり、2つの周波数配列があります-英語、周波数、および期間-期間、単語タイプのすべてのデータ、PROGMEM-データはマイクロコントローラーのフラッシュメモリに格納されます(pgmspace.hライブラリを使用しないと機能しません)、周波数ジェネレーターがありますbuzz()は3つのパラメータを取ります-周波数が生成されるピン、2番目-ヘルツ単位の周波数、3番目-ミリ秒単位の期間。

このコードは、Arduinoと互換性があり、Arduino Uno、Arduino Nano、またはArduino Pro Miniおよびその他の不具合でも動作する必要があります。



ビデオで聞くことができるように、私のビデオの音は2番目のビデオとわずかに異なります。実際、ノートの持続時間をわずかに変更し、「科学的な突く」の一般的な方法を3倍にし、周波数を上げました。元々ボタンが追加されていたこれらの周波数、ボタンのないドアベルは何ですか?



自分で少し修正してコメントした
 // by @tartakynov: // http://youtu.be/5R7NeQkVS_8 // and me - vk.com/razniepodelki #define F_CPU 1200000L //     #include <avr/pgmspace.h> //   PROGMEM #define PIN_BUZZER 2 // PB2  #define BUTTON 4 // PB4  #define COUNT_NOTES 39 //   word frequences[COUNT_NOTES] PROGMEM = { //    392, 392, 392, 311, 466, 392, 311, 466, 392, 587, 587, 587, 622, 466, 369, 311, 466, 392, 784, 392, 392, 784, 739, 698, 659, 622, 659, 415, 554, 523, 493, 466, 440, 466, 311, 369, 311, 466, 392 }; word durations[COUNT_NOTES] PROGMEM = { //    350, 350, 350, 250, 100, 350, 250, 100, 700, 350, 350, 350, 250, 100, 350, 250, 100, 700, 350, 250, 100, 350, 250, 100, 100, 100, 450, 150, 350, 250, 100, 100, 100, 450, 150, 350, 250, 100, 750 }; //void setup() //{ int main( void ) //   void setup(),    { pinMode(PIN_BUZZER, OUTPUT); //   pinMode(BUTTON, INPUT); //    digitalWrite(BUTTON, HIGH); //    //LOW   //} //void loop() //{ while(1){ //  void loop()( ) if (digitalRead(BUTTON) == LOW) { //    for (byte i = 0; i < COUNT_NOTES; i++) //    { buzz(PIN_BUZZER, pgm_read_word(&(frequences[i])) * 3, 2 * pgm_read_word(&(durations[i]))); //  : // buzz(PIN_BUZZER, pgm_read_word(&(frequences[i])), 2 * pgm_read_word(&(durations[i]))); //      3 //(pgm_read_word(&(frequences[i])) * 3) //       //delay(100); //    } } //delay(3000); //   } //    return 0; // int main( void ) } //  while(1) void buzz(unsigned char pin, word frequencyInHertz, word timeInMilliseconds) //    { //   long delayAmount = (long)(long(1000000) / (long)frequencyInHertz); //  3  long loopTime = (long)(((long)timeInMilliseconds * 500) / delayAmount); // 1 -  for (long i = 0; i < loopTime; i++) // 2 -  { // 3 -  digitalWrite(pin, HIGH); //     delayMicroseconds(delayAmount); digitalWrite(pin, LOW); delayMicroseconds(delayAmount); } }
      
      





バイナリサイズのスケッチ:976バイト(最大1,024バイトのうち)





ご覧のとおり、ボタンがクリックされたときにトリガーを追加すると1024バイトを超え、attiny13に収まるようにCコードを挿入する必要がありました。

頻度は、バズ(PIN_BUZZER、pgm_read_word(&(frequencies [i])))* 3、2 * pgm_read_word(&(durations [i]))); それによって、生成された周波数を自分で乗算します。3で理解するように、これは純粋に私の気まぐれです。何も乗算することはできません。



経験豊富なArduinoの方は、コードでPB4ポートへのPULLUP抵抗のソフトウェアプルアップを行ったことにお気づきになると思います。

知らない人のために、これは次のように行われます。

ポートを入力に公開し、論理ユニットにフィードします。 これで、ポートの電圧は供給電圧にほぼ等しくなり、このポートがグランドに短絡すると、その状態が論理ユニットから論理ゼロに変わり、10-100 kOhmの公称値を持つ内部抵抗が使用されるため、マイクロコントローラーは影響を受けません。

私はこれを純粋にボードサイズを節約するために行いました。10kΩの抵抗をプラス電源と目的のポートにハンダ付けするだけでした。ボタンをクリックすると、「ポートをグランドにプル」して論理ゼロになります。



実際のAVR'schikovのクリーンAVR-Cにコードを追加します。



AVR-Cコード
 // by @tartakynov: // http://youtu.be/5R7NeQkVS_8 // and me - vk.com/razniepodelki #define F_CPU 1200000UL //     #include <avr/io.h> //    #include <util/delay.h> //      #include <avr/pgmspace.h> //   PROGMEM #define PIN_BUZZER 2 // PB2  #define BUTTON 4 // PB4  #define COUNT_NOTES 39 //   word frequences[COUNT_NOTES] PROGMEM = { //    392, 392, 392, 311, 466, 392, 311, 466, 392, 587, 587, 587, 622, 466, 369, 311, 466, 392, 784, 392, 392, 784, 739, 698, 659, 622, 659, 415, 554, 523, 493, 466, 440, 466, 311, 369, 311, 466, 392 }; word durations[COUNT_NOTES] PROGMEM = { //    350, 350, 350, 250, 100, 350, 250, 100, 700, 350, 350, 350, 250, 100, 350, 250, 100, 700, 350, 250, 100, 350, 250, 100, 100, 100, 450, 150, 350, 250, 100, 100, 100, 450, 150, 350, 250, 100, 750 }; //void setup() //{ int main( void ) //   void setup(),    { DDRB |= (1<<PIN_BUZZER); //   DDRB &= ~(1<<BUTTON); //    PORTB |= (1<<BUTTON); //    //0  () //} //void loop() //{ while(1){ //  void loop()( ) if (!(PINB & (1<<BUTTON))) { //    for (byte i = 0; i < COUNT_NOTES; i++) //    { buzz(pgm_read_word(&(frequences[i])) * 3, 2 * pgm_read_word(&(durations[i]))); //  : // buzz(PIN_BUZZER, pgm_read_word(&(frequences[i])), 2 * pgm_read_word(&(durations[i]))); //      3 //(pgm_read_word(&(frequences[i])) * 3) //       } //_delay_ms(100); //   } //_delay_ms(3000); //   } //    return 0; // int main( void ) } //  while(1) //void buzz(unsigned char pin, word frequencyInHertz, word timeInMilliseconds) void buzz(word frequencyInHertz, word timeInMilliseconds) //    { //   long delayAmount = (long)(long(1000000) / (long)frequencyInHertz); //  3  long loopTime = (long)(((long)timeInMilliseconds * 500) / delayAmount); // 1 -  for (long i = 0; i < loopTime; i++) // 2 -  { // 3 -  //digitalWrite(pin, HIGH); //     PORTB |= (1<<PIN_BUZZER); //       //delayMicroseconds(delayAmount); //     _delay_us(delayAmount); //   //digitalWrite(pin, LOW); PORTB &= ~(1<<PIN_BUZZER); //delayMicroseconds(delayAmount); //     _delay_us(delayAmount); //   } }
      
      









問題なくコンパイルできるはずですが、何らかの理由でこのコードをArduino IDEで使用する場合、hexファイルのサイズは少なくとも「バイナリでのスケッチサイズ:1 986バイト(最大1,024バイト)」の2倍になります。

_delay_us(*)を使用しているため、どのようにしてこれらすべてを見つけることができましたか。 Arduino関数delayMicroseconds(*); 本質的に同じことをします、これはteenager13のカーネルファイルの欠陥だと思います、ここは私がカーネルファイルを取得したarduinoブルジョアフォーラムのブランチです 、私はそれを少し修正しましたが、変更したカーネルファイルへのリンクはArduinoを使用したAttiny13ファームウェアに関する記事にあります

誰かがこのバグに対処するのを手伝ってくれるなら、純粋に理論的にはArduino IDEが問題なくCコードを飲み込むはずなので、私は嬉しいだけです。



さて、ファームウェアに関するいくつかの言葉-最初のビデオで、私は1.2 MHzの周波数でティンクを実行しました。なぜなら、120万回の操作でお気に入りのメロディを演奏するのに十分であり、同時にこの周波数用にhexファイルがコンパイルされる方法で、食べることはあまりないからです

融合計算機のヒューズは次とおりです。



非表示のテキスト
画像








これで、AVRプログラマーがいるすべての人がこのデバイスを繰り返すことができます。



記事の冒頭で約束したように、 必要なファイルはすべてここにあります。



すべての出版物



そして最後に-「力があなたと共に来るように」。



UPD 2015年1月5日



SparFハブブラウザーは、これまでずっと怠けていたこと、つまり、PB1ボタンを押したときに電力消費を思い起こさせて再生することを怠っていました。

さて、メロディを再生した後、MKはボタンを押すことを期待してさらに「ハンマー」ではなく、眠りに落ち、ボタンを押すたびに目覚め、私たちが愛する帝国の行進を失い、さらに眠りに落ちますが、ほとんど何も消費せずに、バッテリーはこの消費モードで10年間持続します。



図は次のようになります。
画像







コードは次のとおりです。
 /* Attiny13 Star Wars melody */ #define F_CPU 1200000UL #include <avr/io.h> #include <avr/pgmspace.h> #include <util/delay.h> #include <avr/interrupt.h> #include <avr/sleep.h> #define COUNT_NOTES 39 //  const uint16_t frequences[COUNT_NOTES] PROGMEM = { 392, 392, 392, 311, 466, 392, 311, 466, 392, 587, 587, 587, 622, 466, 369, 311, 466, 392, 784, 392, 392, 784, 739, 698, 659, 622, 659, 415, 554, 523, 493, 466, 440, 466, 311, 369, 311, 466, 392 }; //  const uint16_t durations[COUNT_NOTES] PROGMEM = { 350, 350, 350, 250, 100, 350, 250, 100, 700, 350, 350, 350, 250, 100, 350, 250, 100, 700, 350, 250, 100, 350, 250, 100, 100, 100, 450, 150, 350, 250, 100, 100, 100, 450, 150, 350, 250, 100, 750 }; int main( void ) { /*    () = PB1 , ..      INT0 -   ,         Power-down    () = PB0, ..      PB0  PB1,       */ DDRB = (1 << DDB0); // PB0   /* -,       INT0  ,     RESET:      ,       ...        */ PORTB = (1 << PORTB1); //   PB1 GIMSK = (1 << INT0); //  INT0 (PB1) set_sleep_mode(SLEEP_MODE_PWR_DOWN); //   Power-down sei(); //  while(1) sleep_mode(); //    } //   static inline void doSound(void) { //    TCCR0A = (1 << COM0A0) | (1 << WGM01); //Toggle OC0A (PB0) on Compare Match ; mode = CTC TCCR0B = (1 << CS01) | (1 << CS00); //Clock Select = F_CPU/64 //   for (uint8_t i = 0; i < COUNT_NOTES; i++) { //    int16_t freq = pgm_read_word(&(frequences[i])); int16_t dur = pgm_read_word(&(durations[i])); //   1.5  dur *= 3; dur /= 2; //    PB0 OCR0A = (F_CPU / (2UL * 64UL * freq)) - 1; //,    while (dur > 0) { _delay_ms(10); dur -= 10; } } //  TCCR0A = 0; TCCR0B = 0; } //   INT0 ISR(INT0_vect) { doSound(); }
      
      









コードはシームレスにArduino IDEにコンパイルされます。



ファイル



チェックすると、すべてが機能します:






All Articles