Buzzer sounds strange after connecting display and ir diode

Hi,
I am working on a music player using the Arduino Uno, a Lcd display and an IR remote. When testing the two buzzers without the other parts everything sounded great. But now with the display and the Ir diode the sound comes out distorted (with the exact same notes). I am assuming this is a power issue, but I have no idea. The IR diode ist connected to 3.3v and the display is connected to 5v.

Just in case it is not a power issue, here is my code:

#include <pitches.h>
#include "Songs.h"
#include "IRremote.h"
#include <LiquidCrystal_I2C.h>
#include <Wire.h>

const int buzzerPin1 = 6;
const int buzzerPin2 = 5;


const int RECEIVER = 9; 
IRrecv irrecv(RECEIVER);   
decode_results results;

LiquidCrystal_I2C lcd(0x27,20, 4);

const uint32_t POWER_BUTTON = 0xFFA25D;
const uint32_t PREV_BUTTON = 0xFF22DD;
const uint32_t NEXT_BUTTON = 0xFFC23D;
const uint32_t PAUSE_BUTTON = 0xFF02FD;
const uint32_t STOP = 0xFFE21D;



int selectedSong = 0;
int selectedMenu = 0;
bool play = false;

void setup() {
  pinMode(buzzerPin1, OUTPUT);
  pinMode(buzzerPin2, OUTPUT);
  irrecv.enableIRIn();
  lcd.begin();
  Serial.begin(9600);
  displayChanges();
}

void loop() {

    if (irrecv.decode(&results)) {
    Serial.println("received ir");

    handleIRCode(results.value);
    displayChanges();


    irrecv.resume();
  }


}

/* TODO:
- make compatible with every lcd display
*/

// Functions:


void handleIRCode(uint32_t code) {

  Serial.println(selectedMenu);


  if (selectedMenu == 0){  // in the start menu, listen for the play button

    switch (code)
    {
      case PAUSE_BUTTON:
        selectedMenu = 1;
        break;
      default:
        break;
    }
      
  } else if (selectedMenu == 1){ // song menu

    switch(code)
    {
      case STOP:                // go back to start menu
        selectedSong = 0;
        selectedMenu = 0;
        break;
      case NEXT_BUTTON:         // next song
        selectedSong = (selectedSong + 1) % totalSongs;
        break;
      case PREV_BUTTON:       // prev song
        selectedSong = (selectedSong - 1 + totalSongs) % totalSongs;
        break;
      case PAUSE_BUTTON:   // play the selected song
        play = !play;  // should be set from false to true always
        break;
      default:
        break;
    }
    
  } else {

    return;

  }
  return;

}

void displayChanges(){

  if (selectedMenu == 0){

    lcd.clear();
    lcd.setCursor(5,1);
    lcd.print("Press Play");
    lcd.setCursor(6,2);
    lcd.print("To Start");

  } else if (selectedMenu == 1){

    int startPos = (20 - strlen(songs[selectedSong].name)) / 2;
    lcd.clear();
    lcd.setCursor(startPos,1);
    lcd.print(songs[selectedSong].name);
    lcd.setCursor(0,3);
    lcd.print("<");
    lcd.setCursor(19,3);
    lcd.print(">");

    if (play){
      playSong(selectedSong);
    }

  } else {   // should never be the case at this point

    return;

  }
}


void playSong(int currentSong){
  delay(200);

  for (int i = 0; i < songs[currentSong].totalNotes; i++)
  {

     if (irrecv.decode(&results)) {
      Serial.println("received ir while playing");
      if (results.value == STOP){             // stop playing when stop button is pressed
        break;
      }
      irrecv.resume();
    }

    const int currentNoteLeft = songs[currentSong].notesLeft[i];
    const int currentNoteRight = songs[currentSong].notesRight[i];
    float wait = songs[currentSong].durations[i] / songs[currentSong].speed;

    if (currentNoteLeft != 0 && currentNoteRight != 0)
    {
      play2Notes(buzzerPin1, buzzerPin2, currentNoteLeft, currentNoteRight, wait); 

    }
    else
    {
      if (currentNoteLeft == 0){
        if (currentNoteRight == 0 ){
          noNote(buzzerPin1, wait);
        } else{
          playNote(buzzerPin2, currentNoteRight, wait);
        }

      } else {
        playNote(buzzerPin1, currentNoteLeft, wait);
      }
      
    }
  }

  play = false;

}


void play2Notes(int pin1, int pin2, int noteFrequency1, int noteFrequency2, int duration) {

  pinMode(pin1, OUTPUT);
  pinMode(pin2, OUTPUT);
  
  // calculate frequencies
  int period1 = 1000000 / noteFrequency1;
  int period2 = 1000000 / noteFrequency2;

  // remember starttime
  unsigned long startTime = millis();

  unsigned long start1 = micros();
  unsigned long start2 = micros();
  digitalWrite(pin1, LOW);
  digitalWrite(pin2, LOW);


  // check when to turn buzzers on and off for the duration of the note
  while (millis() - startTime < duration) {

    if (micros() - start1 >= period1){
      digitalWrite(pin1, LOW);
      start1 = micros();
    } else if (micros() - start1 >= period1 /2){
      digitalWrite(pin1, HIGH);
    } 

    if (micros() - start2 >= period2){
      digitalWrite(pin2, LOW);
      start2 = micros();
    } else if (micros() - start2 >= period2 /2){
      digitalWrite(pin2, HIGH);
    } 

    }

  // after the note is over, turn both buzzers off
  digitalWrite(pin1, LOW);
  digitalWrite(pin2, LOW);
} 


void playNote(int pin, int noteFrequency, int duration) {
 
  pinMode(pin, OUTPUT);

  int period = 1000000 / noteFrequency;

  unsigned long startTime = millis();

  while (millis() - startTime < duration) {

    digitalWrite(pin, HIGH);
    delayMicroseconds(period / 2);

    digitalWrite(pin, LOW);
    delayMicroseconds(period / 2);
  }

  digitalWrite(pin, LOW);
} 




void noNote(int pin, int duration) {

  pinMode(pin, OUTPUT);

  unsigned long startTime = millis();
  

  while (millis() - startTime < duration) {

    digitalWrite(pin, LOW);
  }
}


I would be grateful for any help :slight_smile:

EDIT:

Not an annoted schematic, but I hope this will do.

IR receiver: https:// sensorkit.joy-it.net/en/sensors/ky-022
(delete the space after //, i couldnt insert link since im beginner or sth)

LCD Display: HD44780 2004 LCD Display Bundle 4x20 Characters with I2C Interface

Sounds like a wiring error. Please post a hand drawn wiring diagram, with pins and all parts clearly labeled.

With what value series resistor?

1 Like

Thank you for your answer. I will post a diagram once im back home.

Im not using a resistor for the ir diode. But it is soldered onto a small board. Ive always thought In dont need a resistor for that :sweat_smile:

You need to post an annotated schematic (the language of electronics) not a wiring diagram as we are trying to troubleshoot. This needs to show exactly how it is wired. all grounds, all modules, power sources, components etc. Be sure to include links to technical information on each component/module.

i posted a diagram now. i basically just put together some lessons of an arduino starter kit and i didnt need resistors there, so i didnt use them here either

i posted a diagram now

In the future, please do not modify the original post. It makes the thread difficult or impossible to follow.

The IR diode ist connected to 3.3v

This is an IR Receiver, not a diode.

According to your post, the project was working before adding the display and the IR receiver. The best approach is to start over with a working project, and add ONE new item at at time, testing as you go. Make sure everything works before adding another new item.

Make sure that the display alone and IR receiver alone work with library examples, before adding either to the working project.

noted

ok i will do that.
i remember i disconnected the power of the display and the ir receiver while the song was playing, but that didnt change anything

I added only the IR receiver to the project and it stopped working at that point. I have no idea why that is.
I have also tried out playing only one note at a time. Once with my playNote function and once with the built in tone function. I think they all sound odd...

the problem seems to be the ir receiver. but i am not sure if i can do anything in the code to make it work. i wrote the play2Notes function myself, so maybe there is a mistake

the problem seems to be the ir receiver

The IRRemote library uses interrupts every 50 us while receiving, to sample the IR input pin and process IR data. This will make hash of your loop timing in the play note routines.

The IRRemote library claims to be compatible with the tone() function, so you could use that to play notes. Or turn off the IR receive function while playing music.

ah, that makes sense. i want to be able to stop the song while it is playing. i havent really gotten into timers and interrupts yet. cant i just set a different timer somewhere or just check for ir results differently?

i think the tone function can only play one note at a time, because it only uses a single timer or sth like that.

The IR library requires interrupts to process the data. That throws off timing for all other processes that use millis() or micros(). It is a form of time-sharing, because the processor can do only one thing at a time.

The code below simply won't work as you expect, with the IR library running in the background, as it temporarily diverts the processor every 50 us.

  // check when to turn buzzers on and off for the duration of the note
  while (millis() - startTime < duration) {

    if (micros() - start1 >= period1){
      digitalWrite(pin1, LOW);
      start1 = micros();
    } else if (micros() - start1 >= period1 /2){
      digitalWrite(pin1, HIGH);
    } 

ah ok. thank you. maybe i will just leave out the stop function then and turn the receiver off while playing

how would you go about doing that?
i couldnt find a disableIRIn function and just turning off the ir receiver with a pwm pin
also didnt stop the interrupts.

I believe this line restarts reception:

    irrecv.resume();

You can stop and restart the interrupt timer. The timers on the Uno and related processors are covered in this excellent tutorial.

Thank you, I will take a look at that.