Apple ir remote problem

Hi guys

I’m trying to program the remote to adjust the volume to me for my audio preamp, reading on various forums, I copied the sketch to understand the operation, everything works perfectly, I can use the keys, but when I hold down the button, the volume does not increase, but stays put, what should you change? where am I wrong? :frowning: :frowning: :frowning:

#include <pins_arduino.h>   // This is needed for a new pulseIn function for remote


#define REMOTEPIN 10      // Pin for IR receiver (remote control)

#define INTERVAL_SAMPLE 2     // Time interval in SECONDS for refreshing the sample rate
#define INTERVAL_BOUNCE 2     // Time in milliseconds to debounce the rotary encoder
#define INTERVAL_SWITCHBOUNCE 200  // Time in milliseconds to debounce switch
#define INTERVAL_SELECT 4     // Time in sec to exit select mode when no activity


boolean sharp;       // FIR filter mode
boolean jitter;      // Jitter reduction
boolean selectMode;
byte pulse=0;
byte status;

// The following variables for the remote control feature
int duration;         // Duration of the IR pulse
int mask;
int c1;               // Byte 1 of the 32-bit remote command code
int c2;               // Byte 2 of the 32-bit remote command code
int c3;               // Byte 3 of the 32-bit remote command code
int c4;               // Byte 4 of the 32-bit remote command code
int IRkey;            // The unique code (Byte 3) of the remote key
int previousIRkey;    // The previous code (used for repeat)

const int rel1 = 6;
const int rel2 = 7;


unsigned long newpulseIn(uint8_t pin, uint8_t state, unsigned long timeout)
{
  uint8_t bit = digitalPinToBitMask(pin);
  uint8_t port = digitalPinToPort(pin);
  uint8_t stateMask = (state ? bit : 0);
  unsigned long width = 0;

  unsigned long numloops = 0;
  unsigned long maxloops = microsecondsToClockCycles(timeout) / 16;

  // wait for any previous pulse to end
  while ((*portInputRegister(port) & bit) == stateMask)
    if (numloops++ == maxloops)
      return 0;

  // wait for the pulse to start
  while ((*portInputRegister(port) & bit) != stateMask)
    if (numloops++ == maxloops)
      return 0;

  // wait for the pulse to stop
  while ((*portInputRegister(port) & bit) == stateMask){
    if(width++ == maxloops)  // added the check for end of pulse
      return 0;
  }
  return clockCyclesToMicroseconds(width * 20+16); // Recalibrated because of additional code
  // in the width loop
} 

/*
The following function returns the code from the Apple Aluminum remote control. The Apple remote is
 based on the NEC infrared remote protocol. Of the 32 bits (4 bytes) coded in the protocol, only the
 third byte corresponds to the keys. The function also handles errors due to noise (returns 255) and
 the repeat code (returs zero)
 
 The Apple remote returns the following codes:
 
   Up key:     238 135 011 089
   Down key:   238 135 013 089
   Left key:   238 135 008 089
   Right key:  238 135 007 089
   Center key: 238 135 093 089 followed by 238 135 004 089 (don't know why there is two commands)
   Menu key:   238 135 002 089
   Play key:   238 135 094 089 followed by 238 135 004 089 (don't know why there is two commands)
 */

int getIRkey() {
  c1=0;
  c2=0;
  c3=0;
  c4=0;
  duration=1;
  while((duration=newpulseIn(REMOTEPIN, HIGH, 20000)) < 2000 && duration!=0)
  {
    // Wait for start pulse
  }
  if (duration == 0)         // This is an error no start or end of pulse
    return(255);             // Use 255 as Error

  else if (duration<3000)    // This is the repeat
    return (0);              // Use zero as the repeat code

  else if (duration<5000){   // This is the command get the 4 byte
    mask = 1;            
    for (int i = 0; i < 8; i++){               // get 8 bits
      if(newpulseIn(REMOTEPIN, HIGH, 3000)>1000)     // If "1" pulse
        c1 |= mask;                  // Put the "1" in position
      mask <<= 1;            // shift mask to next bit
    }
    mask = 1;           
    for (int i = 0; i < 8; i++){               // get 8 bits
      if(newpulseIn(REMOTEPIN, HIGH, 3000)>1000)     // If "1" pulse
        c2 |= mask;                  // Put the "1" in position
      mask <<= 1;            // shift mask to next bit
    }
    mask = 1;           
    for (int i = 0; i < 8; i++){               // get 8 bits
      if(newpulseIn(REMOTEPIN, HIGH, 3000)>1000)     // If "1" pulse
        c3 |= mask;                  // Put the "1" in position
      mask <<= 1;            // shift mask to next bit
    }
    mask = 1;           
    for (int i = 0; i < 8; i++){               // get 8 bits
      if(newpulseIn(REMOTEPIN, HIGH, 3000)>1000)     // If "1" pulse
        c4 |= mask;                  // Put the "1" in position
      mask <<= 1;            // shift mask to next bit
    }
     //Serial.println(c1, DEC); //For debugging
    //Serial.println(c2, DEC); //For debugging
   // Serial.println(c3, DEC); //For debugging
    //Serial.println(c4, DEC); //For debugging
    return(c3);
  }
}

/************************ MAIN PROGRAM ************************************************************/

void setup() {


  Serial.begin(9600); // This is here for debugging

  // Set up the pin modes
  pinMode(rel1, OUTPUT);       // Button for Encoder pin for volume up
  

  pinMode(rel2, OUTPUT);     // Button for Encoder pin for volume down


  pinMode(REMOTEPIN, INPUT);      // Pin for IR sensor
  digitalWrite(REMOTEPIN, HIGH);  // Enable pull-up resistor

        

}
void loop() {

  
    /*
  The following code is for the remote control. It handles the codes generated by the Apple remote
   control except 0 has been designated for "repeat" and 255 designated as an error code. The current
   Apple remote does not generate these codes.
   */
   
  while(digitalRead(REMOTEPIN)==LOW){
    if((IRkey=getIRkey())==255){
      // Do nothing
    }
    else if(IRkey==1){  // Repeat
      IRkey=previousIRkey;
    }
    else {  // New command
      previousIRkey=IRkey;
    }
    switch(IRkey){
    case 12:  // 12 is the up key, we will use for volume up
      
        Serial.println ("GIU'");      // print text
      
      break;
    case 10:  // 10 is the down key, we will use for volume down
     
        Serial.println ("SU'");   //print text
      
      break;
    }
  }
}

Sorry for my bad English

    case [color=red]12[/color]:  // [color=red]11[/color] is the up key, we will use for volume up
...
    case [color=orange]10[/color]:  // [color=orange]13[/color] is the down key, we will use for volume down

so where is the truth?

not taking into account what is written in the comments, I forgot to change them

Most remotes send one code when a key is pressed, and another when a key is held. That second code is the same, regardless of which key is held. It means “repeat the last unique action”.

Does yours? Or does yours send the same key over and over?

int c1;               // Byte 1 of the 32-bit remote command code
int c2;               // Byte 2 of the 32-bit remote command code
int c3;               // Byte 3 of the 32-bit remote command code
int c4;               // Byte 4 of the 32-bit remote command code
int IRkey;            // The unique code (Byte 3) of the remote key
int previousIRkey;    // The previous code (used for repeat)

NONE of the code my IR sends fit in an int. Bytes are NOT ints.

  while((duration=newpulseIn(REMOTEPIN, HIGH, 20000)) < 2000 && duration!=0)

Isyourspacekeybroken? Bangitonceinawhile!

        // Controls the brightness of LCD

Does it really?

        Serial.println ("SU'");

What is reading the serial data?

my remote if I press once to me by a code each button, if I hold down any button returns to me as a code FFFFFFFF.

tix88:
Up

up what? explain how a println this is supposed to increase the volume. is that connected somewhere else decoding Serial? What do you get ? do you capture properly the remote control code?

help us help you...

Have you looked at Apple Remote - Wikipedia?

The low bit of the third byte is parity, and the function should actually return c3 >> 1 (or at least clear the low bit). Checking the parity would also be a good idea.

   Center key: 238 135 093 089 followed by 238 135 004 089 (don't know why there is two commands)
   Play key:   238 135 094 089 followed by 238 135 004 089 (don't know why there is two commands)

This is what I think is going on:

  • Code 4 (actually 2) = combined Play/Center on the old white remote.
  • The new remote sends both the new code and the old code.
  • Old devices ignore the new codes they don't recognize.
  • New devices ignore the old code if it follows a new code.

Now that everything is functioning I presents a little problem, pressing the button on the remote that selects me of CASE least for 1 second, the CASE are selected perfectly, but when I go to press the button and release it quickly HOUSES are selected automatically without me longer stop until the key is hold, use this statement to the selection of CASE, where am I wrong?

      (My_Receiver.GetResults(&My_Decoder)); {
       My_Decoder.decode();
      irbuttonState =  (My_Decoder.value==0x77E1C0FE)  ;
      if (My_Decoder.value==0x77E1C0FE){
       if (irbuttonState != irlastButtonState ){
      irbuttonPushCounter++;
      delay(50);
      if (irbuttonPushCounter > 3) irbuttonPushCounter = 1;
      switch (irbuttonPushCounter) {
        case 1:
          CD_on();
          break;
        case 2:
          DAC_on();
          break;
        case 3:
          AUX_on();
          break;
       
      
      }
      }
      }

Time to go read Snippets-r-us...

give us full code...for example we don't see where you manage irlastButtonState

:frowning: sorry

selettore_ingressi_ir_prova1.ino (13 KB)

:slight_smile:

I guess my intuition was not too bad... you don't handle irlastButtonState

what's going on with the parenthesis around (My_Receiver.GetResults(&My_Decoder)); {and why are you opening a { bracket afterwards? are you missing the if in front like you had above???

You also understand that you are calling twice My_Receiver.GetResults

Also a good coding practice is to use truth values (true and false) for booleans. Don't doboolean irlastButtonState = 0;but doboolean irlastButtonState = false;

You need to fix the code so that you read ONCE what happens on the buttons and then decide what you want to do with this next. if some buttons need a state machine, then implement a state machine.

Thanks for the reply.
Could you help me do that?

      (My_Receiver.GetResults(&My_Decoder)); {

Littering your code with useless parentheses and curly braces is not a good idea. I, for one, refuse to help fix code that looks like this crap.

PaulS:

      (My_Receiver.GetResults(&My_Decoder)); {

Littering your code with useless parentheses and curly braces is not a good idea. I, for one, refuse to help fix code that looks like this crap.

I'm sorry that my code you do not like, but I'm not a programmer but a hobbyist, and I'm still learning. Thanks anyway for your help

May be start by cleaning the code

For example what does void setVol(float volume_temp); do in the middle of the code?

What does

  if (millis() - previousMillis >= interval) {
    previousMillis = millis();
  }

or

  if (millis() - irpreviousMillis >= irinterval) {
    irpreviousMillis = millis();
  }

bring to you?

Looks like you frantically copied and paste code, removed pieces and expect things to work...

Get a coherent structure that follows a logical pattern - you should be able first to explain in plain English what are the steps in the loop and then start coding...

I cleaned the code by eliminating various pieces of code that I had left in the various tests I had done.

The operation that now I want to get is the same operation that I get through the statement that I make through but with a button on the remote control.

How do I start?

v0.4b.ino (16.1 KB)

The operation that now I want to get is the same operation that I get through the statement that I make through but with a button on the remote control.

How do I start?

You start by taking a deep breath, letting it out slowly, and then re-typing your problem statement, with punctuation and meaning.

I cleaned the code, eliminating several pieces of code that I had left in the various tests done previously.

Now I want to replicate this code, with the remote control

  buttonState = digitalRead(BUTTON);
   delay(10);
  if (buttonState != lastButtonState) {
    if (buttonState == LOW) {
      buttonPushCounter++;
      delay(50);
      if (buttonPushCounter > 3) buttonPushCounter = 1;
      switch (buttonPushCounter) {
        case 1:
          CD_on();
          break;
        case 2:
          DAC_on();
          break;
        case 3:
          AUX_on();
          break;
      } 
    }
  }
  lastButtonState = buttonState;

How do I start?

Sorry for ma bad English :frowning:

How do I start?

With some clear requirements. That code is expecting that there is ONE switch connected to a pin, and that the switch is wired in pullup configuration. It does something different based on how many times the switch has been pressed.

Obviously, your remote has more than one switch, so counting the number of times one switch is pressed doesn't make sense.

Use a different switch for each function.

Prove that you can read the remote control's data. Then, use an if/else if/else if structure to pick which function to call based on which button on the remote was pressed.

With different remote control buttons already I can select functions, but I want to do it with a single button.