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?
#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;
}
}
}
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
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.
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?
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;
}
}
}
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.
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.
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.
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.