Arduino uno IR remote with piezo buzzer

I`m coding to make sure that the piezo buzzer makes sounds(do, re, me, fa...) by controlling the IR remote controller. However, it only works when I press the button 1(Do) first. The other buttons do not work...
What I want is to make the piezo buzzer to make Do, Re, Me.....Si sounds sequentially, pressing the button 1 to 7. And the buzzer must make the sound for 1 second.
Can someone help me please?

This code uses an IR remote to play musical notes (C5 to B5) on a piezo speaker, corresponding to buttons pressed on the remote. It is designed to receive signals via an IR receiver, identify the button pressed, and map it to a specific musical note frequency.
You need to install the library "IRremote" by Armin 4.4.1

#include <IRremote.h>

#define IR_RECEIVE_PIN 2  // IR remote receiver pin
#define SPEAKER_PIN 8     // Piezo speaker pin

// Frequencies for C5, D5, E5, F5, G5, A5, B5 notes
const int notes[] = {523, 587, 659, 698, 784, 880, 988}; // C5, D5, E5, F5, G5, A5, B5

// Signal values for remote control buttons (as obtained from the serial monitor)
unsigned long buttonValues[] = {
    0xBA45FF00, // Button '1' -> C5 (Do)
    0xB946FF00, // Button '2' -> D5 (Re)
    0xB847FF00, // Button '3' -> E5 (Mi)
    0xBB44FF00, // Button '4' -> F5 (Fa)
    0xBF40FF00, // Button '5' -> G5 (Sol)
    0xBC43FF00, // Button '6' -> A5 (La)
    0xF807FF00  // Button '7' -> B5 (Si)
};

void setup() {
  pinMode(SPEAKER_PIN, OUTPUT);  // Set the piezo speaker pin as output
  Serial.begin(9600);            // Start serial communication
  IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK); // Initialize the IR remote receiver
  Serial.println("Ready to receive IR signals...");
}

void loop() {
  if (IrReceiver.decode()) {  // IR remote signal detected
    unsigned long value = IrReceiver.decodedIRData.decodedRawData; // Store the received signal value
    Serial.print("Received: ");
    Serial.println(value, HEX);  // Print the received signal value in hexadecimal format

    // Check the button value and play the corresponding note
    for (int i = 0; i < 7; i++) {
      if (value == buttonValues[i]) {  // If the received signal matches a value in the array
        playTone(i); // Play the corresponding note
        break;       // Stop searching after finding a match
      }
    }

    IrReceiver.resume(); // Prepare the IR receiver for the next signal
  }
}

// Function to play a specific note
void playTone(int index) {
  tone(SPEAKER_PIN, notes[index], 500); // Play the frequency for 500ms
  delay(500);                          // Wait for 0.5 seconds
  noTone(SPEAKER_PIN);                 // Stop the sound
}

Please edit your post and enclose the whole and only code within the "code" tag (select the code, then press the "<CODE/>" toolbar button then save).

It's not a matter of aesthetics, but without the "code" tags the forum modifies the text by interpreting certain sequences and therefore making your code difficult to read and probably incomplete.

PS: if possible, use english comments when asking us to help you... Help us to help you! :wink:

1 Like

Thank you :slight_smile:

What help is needed?

I think this is his problem:

it only works when I press the button 1(Do) first. The other buttons do not work...

1 Like

I haven't tested the code (and I don't have the same remote to test it with...) but it looks ok.
What I haven't got is what you mean "when I press the button 1(Do) first": do you mean only the button 1 works while others don't ever do it, independently from the sequence? Or the 1 is the only key/note working?

I mean, what do you mean with "first": if you "first" (i.e. after starting the code) press any other key it works, or not? And I see you wait 500 ms after starting the sound: remember you need to press the keys not quicker than that.
And when you press any other key are you sure the IR code from "decodedRawData" (and printed on serial) are exactly the ones you have on "buttonValues"? I think/hope so, but a deeper check is a good idea (run the code, press the keys from 1 to 7 in sequence.

Could you please better describe the behaviour, a short sequence of steps of what you do and what you consequently get (including the serial output, if possible)?

Just as a side note, if you use the "tone()" function with a duration, you don't need to add a delay() to wait for sound ending, thus you don't need to use "noTone()" because the tone will stop after the specified time. Just remove them

After a quick investigation, I think it's a problem between tone() and IRremote (i.e. a timer conflict), maybe causing the program to stop.

Read this section of the IRremote "README", describing a possible workaround (timer change):

1 Like

When I upload the code and run it on the Arduino Uno, only Button 1 (C note) works initially, and the other buttons do not respond. If I press any button other than Button 1 first, none of them work, but Button 1 works just once and then no sound is produced afterward. I have verified the IR codes and entered them correctly, but I noticed an issue where the IR code displayed on the serial monitor changes every time I press a button.

It seems that the issue lies in the IR code recognition, causing the malfunction. I would appreciate it if you could help me fix this. The IR codes currently written in the code are correct. However, since the IR codes displayed on the serial monitor vary with each press, this part likely needs to be addressed. Thank you for your assistance.

Well, if you read that link the library author says there's a conflict between IRremote and tone()...
BTW, something is still missing: when the program "stops working", what you exactly read on the serial monitor? Nothing? Something? Everything?
Now try changing the "playTone()" function to print out a message when the tone starts:

// Function to play a specific note
void playTone(int index) {
  Serial.print("  * TONE ");Serial.println(index);
  tone(SPEAKER_PIN, notes[index], 500); // Play the frequency for 500ms
}

Run the sketch again, and press the "1" key and see what happens, then press "2" and see what happens. And post the full serial output here.
Then restart the board and now press the "2" key first, then the "3", and see again what happens. And post also this second serial output here.

Thank you so much for help.
But it still has the same error. The serial monitor shows different codes every time I press the button. Depending on the duration I press the button, the code changes.

This is what it shows. (button 1~7)
Ready to receive IR signals...
Received: BA45FF00

  • TONE 0
    Received: 0
    Received: 5CF75618
    Received: 47983C
    Received: 8000
    Received: 141C887B
    Received: 94A
    Received: 508765FD

May I suggest you to:
Install and use new IRremote 4.4.1 library
#include <IRremote.hpp> (not <IRremote.h>)

Upload demo receiver code and play with that together with your hardware until you have 100% consistent receiver printout.

Then decide if you want to change the default timer2 to timer 1
or
stop and restart the timer after every Tone:

IrReceiver.stopTimer(); // Stop timer consistently before calling tone() or other functions using the timer resource.
tone(TONE_PIN, 2200, 8);
delay(8);
IrReceiver.restartTimer(); // Restart IR timer after timer resource is no longer blocked.

Why? He's using the 4.4.1 from shirriff and ArminJo, the same I successfully use...

I used IRremote many times, and in my experience the first cause is when you either have an IR receiver with a wrong carrier frequency (e.g. the remote has 52 kHz and the sensor is 38 kHz). Another reason is if you read the IR code with a standard, while the trasmitter uses a different one (e.g. NEC instead of SAMSUNG).

Just as a note, in one of my previous projects I don't use "IrReceiver.decodedIRData.decodedRawData" after the ".decode()" call, I use "results".
My code does:

...
  if (irrecv.decode(&results)) {
    if (results.decode_type == SAMSUNG) {
      unsigned long kCode = results.value - PROTO_OFFSET;
      Serial.print(" 0x"); Serial.print(kCode, HEX);
... etc ...

So the first thing you should do is make sure your receiver has the same carrier frequency of the remote, and then which standard (decode_type) your IR signal follows, running one of the library examples (like "ReceiveDump").

1 Like

Me too.
But I don't know for sure what OP is using, good indication would be suggested #include <IRremote.hpp>

1 Like

It still does not work...
I will paste my assignment here.

When the number 1 is pressed on the remote control, the sound "Do" should play for 1 second. Similarly, pressing 2 should produce the sound "Re" for 1 second, 3 should produce "Mi," 4 should produce "Fa," 5 should produce "Sol," 6 should produce "La," and 7 should produce "Si" for 1 second each through the piezo speaker. The frequencies corresponding to "Do~Si" are C5, D5, E5, F5, G5, A5, and B5. Refer to a reliable source for the exact frequencies and write a sketch to implement this functionality. Use the tone() function to generate the sound. Refer to the official Arduino website for information on how to use the tone() function.

(I'm using IRremote 4.4.1 library by Armin)

Ok, I've got your assignment (btw, I alread did it), but what "it does not work" means exactly? I asked you this question on my post #9, but no answer from you! I also gave you some things to check with, but "It still does not work" is an incomplete answer, if you don't post the code you tested on, together with the serial output I already asked you.

So, if you still want my help, please read what I asked you on post #9 and the things you need to check on post #12 and provide a full answer with all the details.
If you reply "doesn't work" again without enough information, I cannot do anything more, and I'll quit.

Oh my God! I entered all the codes you gave me. Finally, it works properly!!

Thank you so much for your help. God bless you!

Good!
Just for completeness, please post here the working code here so you can also be useful to someone who might have a similar problem.

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.