2017-06-13 15 views
-1

私はこの質問をarduino.stackexchangeに掲載しましたが、この質問は言語(C)でのみ(多分)行う必要があると思います。ArduinoをIRリモコンで使用している車の電源をオン/オフする

私は車を持っていて、赤外線(IR)リモコンを使ってArduinoを使って曲を演奏すると、車の電源を切って何とかしようとしています。私はブザーを使って曲(SuperMario)を演奏することに決めました。そして、パワーオンボタンを押すとその曲がうまく動作します。

問題は、電源を切ったときに、曲の電源が切れるまで待つ必要があることです。

スレッドや何かが必要なのかもしれないと思っていましたが、わかりません。あるいはこれを修正するより良い方法があります。私はこれを持っているtranslateIR関数内

#include "IRremote.h" 

#define NOTE_B0 31 
#define NOTE_C1 33 
#define NOTE_CS1 35 
#define NOTE_D1 37 
#define NOTE_DS1 39 
#define NOTE_E1 41 
#define NOTE_F1 44 
#define NOTE_FS1 46 
#define NOTE_G1 49 
#define NOTE_GS1 52 
#define NOTE_A1 55 
#define NOTE_AS1 58 
#define NOTE_B1 62 
#define NOTE_C2 65 
#define NOTE_CS2 69 
#define NOTE_D2 73 
#define NOTE_DS2 78 
#define NOTE_E2 82 
#define NOTE_F2 87 
#define NOTE_FS2 93 
#define NOTE_G2 98 
#define NOTE_GS2 104 
#define NOTE_A2 110 
#define NOTE_AS2 117 
#define NOTE_B2 123 
#define NOTE_C3 131 
#define NOTE_CS3 139 
#define NOTE_D3 147 
#define NOTE_DS3 156 
#define NOTE_E3 165 
#define NOTE_F3 175 
#define NOTE_FS3 185 
#define NOTE_G3 196 
#define NOTE_GS3 208 
#define NOTE_A3 220 
#define NOTE_AS3 233 
#define NOTE_B3 247 
#define NOTE_C4 262 
#define NOTE_CS4 277 
#define NOTE_D4 294 
#define NOTE_DS4 311 
#define NOTE_E4 330 
#define NOTE_F4 349 
#define NOTE_FS4 370 
#define NOTE_G4 392 
#define NOTE_GS4 415 
#define NOTE_A4 440 
#define NOTE_AS4 466 
#define NOTE_B4 494 
#define NOTE_C5 523 
#define NOTE_CS5 554 
#define NOTE_D5 587 
#define NOTE_DS5 622 
#define NOTE_E5 659 
#define NOTE_F5 698 
#define NOTE_FS5 740 
#define NOTE_G5 784 
#define NOTE_GS5 831 
#define NOTE_A5 880 
#define NOTE_AS5 932 
#define NOTE_B5 988 
#define NOTE_C6 1047 
#define NOTE_CS6 1109 
#define NOTE_D6 1175 
#define NOTE_DS6 1245 
#define NOTE_E6 1319 
#define NOTE_F6 1397 
#define NOTE_FS6 1480 
#define NOTE_G6 1568 
#define NOTE_GS6 1661 
#define NOTE_A6 1760 
#define NOTE_AS6 1865 
#define NOTE_B6 1976 
#define NOTE_C7 2093 
#define NOTE_CS7 2217 
#define NOTE_D7 2349 
#define NOTE_DS7 2489 
#define NOTE_E7 2637 
#define NOTE_F7 2794 
#define NOTE_FS7 2960 
#define NOTE_G7 3136 
#define NOTE_GS7 3322 
#define NOTE_A7 3520 
#define NOTE_AS7 3729 
#define NOTE_B7 3951 
#define NOTE_C8 4186 
#define NOTE_CS8 4435 
#define NOTE_D8 4699 
#define NOTE_DS8 4978 

#define powerLedRed 2 
#define powerLedGreen 3 
#define receiver  5 
#define buzzer   7 

void translateIR(void); 
void powerON(void);; 
void powerOFF(void); 
void swap(int *x, int *y); 
void playSuperMario(void); 
void buzz(int targetPin, long frequency, long length); 

int power   = 2; 
int switchOFF  = 0; 
int switchON  = 1; 

int melody[] = { 
    NOTE_E7, NOTE_E7, 0, NOTE_E7, 0, NOTE_C7, NOTE_E7, 0, 
    NOTE_G7, 0, 0, 0, NOTE_G6, 0, 0, 0, 
    NOTE_C7, 0, 0, NOTE_G6, 0, 0, NOTE_E6, 0, 0, 
    NOTE_A6, 0, NOTE_B6, 0, NOTE_AS6, NOTE_A6, 0, 
    NOTE_G6, NOTE_E7, NOTE_G7, NOTE_A7, 0, NOTE_F7, NOTE_G7, 0, 
    NOTE_E7, 0, NOTE_C7, NOTE_D7, NOTE_B6, 0, 0, 
    NOTE_C7, 0, 0, NOTE_G6, 0, 0, NOTE_E6, 0, 0, 
    NOTE_A6, 0, NOTE_B6, 0, NOTE_AS6, NOTE_A6, 0, 
    NOTE_G6, NOTE_E7, NOTE_G7, NOTE_A7, 0, NOTE_F7, NOTE_G7, 0, 
    NOTE_E7, 0, NOTE_C7, NOTE_D7, NOTE_B6, 0, 0 
}; 

int tempo[] = { 
    12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 
    12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 
    9, 9, 9, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 
    12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 
    9, 9, 9, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 
}; 

int underworld_melody[] = { 
    NOTE_C4, NOTE_C5, NOTE_A3, NOTE_A4, NOTE_AS3, NOTE_AS4, 0, 0, 
    NOTE_C4, NOTE_C5, NOTE_A3, NOTE_A4, NOTE_AS3, NOTE_AS4, 0, 0, 
    NOTE_F3, NOTE_F4, NOTE_D3, NOTE_D4, NOTE_DS3, NOTE_DS4, 0, 0, 
    NOTE_F3, NOTE_F4, NOTE_D3, NOTE_D4, NOTE_DS3, NOTE_DS4, 0, 0, 
    NOTE_DS4, NOTE_CS4, NOTE_D4, NOTE_CS4, NOTE_DS4, NOTE_DS4, NOTE_GS3, 
    NOTE_G3, NOTE_CS4, NOTE_C4, NOTE_FS4, NOTE_F4, NOTE_E3, NOTE_AS4, NOTE_A4, 
    NOTE_GS4, NOTE_DS4, NOTE_B3, NOTE_AS3, NOTE_A3, NOTE_GS3, 0, 0, 0 
}; 

int underworld_tempo[] = { 
    12, 12, 12, 12, 12, 12, 6, 3, 
    12, 12, 12, 12, 12, 12, 6, 3, 
    12, 12, 12, 12, 12, 12, 6, 3, 
    12, 12, 12, 12, 12, 12, 6, 
    6, 18, 18, 18, 6, 6, 6, 6, 6, 6, 
    18, 18, 18, 18, 18, 18, 10, 10, 10, 
    10, 10, 10, 3, 3, 3 
}; 

IRrecv irrecv(receiver); 
decode_results results; 

void setup(void) 
{ 
    pinMode(buzzer, OUTPUT); 
    pinMode(powerLedGreen, OUTPUT); 
    pinMode(powerLedRed, OUTPUT); 
    Serial.begin(9600); 
    Serial.println("IR Receiver Button Decode"); 
    irrecv.enableIRIn(); 
} 

void loop(void) 
{ 
    if (power == 2) { 
    powerOFF(); 
    } 

    if (irrecv.decode(&results)) { 
    translateIR(); 
    irrecv.resume(); 
    } 
} 

void playSuperMario(void) { 
    Serial.println(" 'Mario Theme'"); 
    int size = sizeof(melody)/sizeof(int); 
    for (int thisNote = 0; thisNote < size; thisNote++) { 
    int noteDuration = 1000/tempo[thisNote]; 
    buzz(buzzer, melody[thisNote], noteDuration); 

    int pauseBetweenNotes = noteDuration * 1.30; 
    delay(pauseBetweenNotes); 

    buzz(buzzer, 0, noteDuration); 
    } 
} 

void buzz(int targetPin, long frequency, long length) { 
    digitalWrite(13, HIGH); 
    long delayValue = 1000000/frequency/2; // calculate the delay value between transitions 
    long numCycles = frequency * length/1000; // calculate the number of cycles for proper timing 

    for (long i = 0; i < numCycles; i++) { // for the calculated length of time... 
    digitalWrite(targetPin, HIGH); // write the buzzer pin high to push out the diaphram 
    delayMicroseconds(delayValue); // wait for the calculated delay value 
    digitalWrite(targetPin, LOW); // write the buzzer pin low to pull back the diaphram 
    delayMicroseconds(delayValue); // wait again or the calculated delay value 
    } 

    digitalWrite(13, LOW); 
} 

void translateIR(void) { 
    switch (results.value) { 
    case 0xFF02FD: 
     Serial.println(" -OK-"); 

     swap(&switchON, &switchOFF); 

     if (switchON == 0) 
     { 
     powerON(); 
     playSuperMario(); 
     } 
     else 
     { 
     powerOFF(); 
     } 
     break; 
    default: 
     Serial.println(" other button "); 
     power = 0; 
    } 
    //delay(500); 
} 

void powerOFF(void) { 
    digitalWrite(powerLedRed, HIGH); 
    digitalWrite(powerLedGreen, LOW); 
    power = 0; 
} 

void powerON(void) { 
    digitalWrite(powerLedRed, LOW); 
    digitalWrite(powerLedGreen, HIGH); 
} 

void swap(int *x, int *y) { 
    if (*x != *y) { 
    *x ^= *y; 
    *y ^= *x; 
    *x ^= *y; 
    } 
} 

:ここ

デモプログラムである

ここ
void translateIR(void) { 
    switch (results.value) { 
    case 0xFF02FD: 
     Serial.println(" -OK-"); 

     swap(&switchON, &switchOFF); 

     if (switchON == 0) 
     { 
     powerON(); 
     playSuperMario(); 
     } 
     else 
     { 
     powerOFF(); 
     } 
     break; 
    default: 
     Serial.println(" other button "); 
     power = 0; 
    } 
    //delay(500); 
} 

ので、私は電源OFFして何とか必要な機能、powerON()playSuperMario();両方と呼ばれていますソング中の車が再生されます。

ここにはVIDEO Demoがあります。 これを修正するには?

答えて

2

スレッドを忘れてしまった、これはここで話しているマイクロコントローラです。おそらく100ミリ秒ごとに1回発生するタイマーベースの割り込みをお勧めします。人間の耳のための短い時間ですが、1秒間に1600万命令を実行するマイクロ命令では、割り込み間に多くの時間が必要です。したがって、割り込みでは、ボタンが押されたかどうかを確認します。それがある場合は、メインループでチェックされる変数を設定し、設定されている場合は、メロディをオフにします。

最大レイテンシ= 100msプラス数クロックサイクル。

私はコードを書くつもりはありません。しかし、私は何をGoogleに教えてくれるでしょう。まずArduinoボード上にあるマイクロコントローラ用のデータシートを読む必要があります。 Atmelからダウンロードしてください。次に、CTCモードでタイマーを設定する方法、プリスケーラを設定する方法、選択したコンパイラIDEで割り込みをコーディングする方法、割り込み中にボタンを押す方法を検出する方法、 volatileの変数と、メインループ内のその変数をチェックしてメロディを中断する方法について説明します。埋め込みプログラミングで学ぶことがたくさんあります。インターネット上のすべてのところにあります。データシートから始めます。 ;)

0

プログラムをマルチスレッド化するために書き直すつもりはありませんが、特定の質問に答える範囲の背後にあります。私は出発点として何が必要かを説明することができます。

まず、スレッドなしでこれを修正する簡単な方法は、signalsのようなものを使用して曲の再生を止めることです。これはCtrl-Cを押すと起こります。あなたのプログラムは自分のIRからの入力を読み込んでいるので、IR入力の読み込みとサウンドの再生の両方に同時にスレッドが使用されていることがわかります。

私はArduinoに慣れていませんが、pthreadsのようなものがあると仮定しています。あなたはそれに精通している必要があります。スレッドを使用することは非常に異なるパラダイムであり、前にそれらを使用していない場合、あなたの頭の周りを取得するために時間がかかるので、些細な変更ではありません。頭を悩ます主なものは、コードが複数の場所で実行されていることです。

メインスレッドは、スレッドが作成される前の開始プロセスで、loop()を実行しているので、任意のIR入力に応答できます。それ自身のスレッドでそれを持つことは、任意のユーザー入力に応答することができます。あなたのコードの問題の問題は、新しい入力を処理する前に、playSuperMario()の曲の演奏が戻るのを待たなければならないということです。

初期化中にどこかのスレッドを作成します。このスレッドは、曲を再生するものになります。 IR入力に基づいて曲を開始できる必要があります。また、すでに再生中に "ON"ボタンを押すと何が起こるのかなどの動作を定義する必要がありますか?それは再び始まるか、止まるか、それは無視され、それは演奏を続けますか?

両方のスレッドで1つ以上の変数を使用する必要があります。これはmutex保護を必要とするので、一度に1つのスレッドだけがそれを読み書きできます。グローバル変数isPlayingが最初にtrueに設定されているとします。オフボタンを押すと、falseに変更されます。 playSuperMario()buzz()など関数は、この値がループ内で偽であるかどうかをチェックする必要があります。 falseの場合、すぐに戻ります。

これは、このような希望をどのように処理するかを示す一般的なポインタです。

+1

arduinoにはpthreadがありません - これはprotothreadsの非常に簡単なスレッド実装を持っています。最良の方法はおそらくスレッドを調べることではなく(実際にはここでは必要ない)、むしろタイマISRで音楽を再生することです。 – tofro

関連する問題