I'd like to implement a remotely controlled volume control.
The 'Volume' variable ranges from 0 to 127.
What I'd like to achieve is:
entering the 3-digit value from an IR remote, then store the final value by pressing the 'Enter' button.
As an example:
let's say I need to set the volume to '58', so I would need three button presses,
1st press: button '5',
2nd press: button '8',
3rd press: button 'enter' to store the final composed value.
The problem: unfortunately I have no idea on how to correctly implement this. Could you please help?
Hi guys, much thanks for the replies!
Yes, I'm using the IR lib and TSOP 2438 IR receiver.
If I undestand correctly, I could use a string to accumulate the digits, then use atoi function to get the integer.
I came up with the following code, inspired by other example sketches I've found (as suggested).
Do you think it will work?
#include <IRremote.h>
/*
* Variables
*/
int RECV_PIN = 11;
const int MaxChars = 3;
char strValue[MaxChars + 1]; // String for 3 digits + null char
char ch;
int index = 0;
int accumulVal = 0;
IRrecv irrecv(RECV_PIN);
decode_results results;
void setup()
{
Serial.begin(9600);
// In case the interrupt driver crashes on setup, give a clue
// to the user what's going on.
Serial.println("Enabling IRin");
irrecv.enableIRIn(); // Start the receiver
Serial.println("Enabled IRin");
}
void loop() {
if (irrecv.decode(&results)) {
Serial.println(results.value, DEC);
irrecv.resume(); // Receive the next value
}
delay(100);
if ( results.value == 0x20DFA857 ) // Button '5' on my remote
{
ch = '5'; // assign number '5' to button '5' press
}
if ( results.value == 0x20DF18E7 ) // Button '8' on my remote
{
ch = '8'; // assign number '8' to button '8' press
}
/*
* Accumulation
*/
if ( index < MaxChars){
strValue[index++] = ch; // add the ASCII character to the string
}
else
{
// here when the buffer is full or on the first non digit
strValue[index] = 0; // terminate the string with a 0
accumulVal = atoi(strValue); // use atoi to convert string to an int
index = 0; // reset index to receive other data
}
} // loop end
So a bit of debugging, Serial.print() will do - to help locate the specific issue.
it sounds like you're almost there.
Just stay calm, think logically, and try to understand each line of code as opit executes.
lastchancename:
You press '1' once, and get three ones?
Yes, exactly.
I got the impression that it keeps accumulating, instead it should get
the first press char and store it to the right (LSB), then wait for the second press to pass the first-pressed character to the left, towards the MSB, and replace the LSB value with the new
2nd press char value.
I'm assuming the Index bit order is:
2 1 0 (so MSB to LSB)
Am I misinterpreting here?
Unfortunately I have no clue on how to do this (limited knowledge).
Any help/suggestion highly appreciated.
Updated code:
#include <IRremote.h>
/*
* Variables
*/
int RECV_PIN = 11;
const int MaxChars = 3;
char strValue[MaxChars + 1]; // String for 3 digits + null char
char ch;
int index = 0;
int accumulVal = 0;
IRrecv irrecv(RECV_PIN);
decode_results results;
void setup()
{
Serial.begin(9600);
// In case the interrupt driver crashes on setup, give a clue
// to the user what's going on.
Serial.println("Enabling IRin");
irrecv.enableIRIn(); // Start the receiver
Serial.println("Enabled IRin");
}
void loop() {
if (irrecv.decode(&results)) {
Serial.println(results.value, DEC);
irrecv.resume(); // Receive the next value
}
delay(100);
if ( results.value == 0x20DF8877 ) // Button '1' on my remote
{
ch = '1'; // assign number to button press
}
if ( results.value == 0x20DF48B7 ) // Button '2' on my remote
{
ch = '2'; // assign number to button press
}
if ( results.value == 0x20DFC837 ) // Button '3' on my remote
{
ch = '3'; // assign number to button press
}
if ( results.value == 0x20DF28D7 ) // Button '4' on my remote
{
ch = '4'; // assign number to button press
}
if ( results.value == 0x20DFA857 ) // Button '5' on my remote
{
ch = '5'; // assign number '5' to button '5' press
}
if ( results.value == 0x20DF6897 ) // Button '6' on my remote
{
ch = '6'; // assign number to button press
}
if ( results.value == 0x20DFE817 ) // Button '7' on my remote
{
ch = '7'; // assign number to button press
}
if ( results.value == 0x20DF18E7 ) // Button '8' on my remote
{
ch = '8'; // assign number '8' to button '8' press
}
if ( results.value == 0x20DF9867 ) // Button '9' on my remote
{
ch = '9'; // assign number to button press
}
if ( results.value == 0x20DF08F7 ) // Button '0' on my remote
{
ch = '0'; // assign number to button press
}
/*
* Accumulation
*/
if ( index < MaxChars && isDigit(ch) ){
strValue[index++] = ch; // add the ASCII character to the string
}
else
{
// here when the buffer is full or on the first non digit
strValue[index] = 0; // terminate the string with a 0
accumulVal = atoi(strValue); // use atoi to convert string to an int
index = 0; // reset index to receive other data
}
Serial.print("Accumulated value: ");
Serial.println(accumulVal, DEC);
} // loop end
Two steps
Replace the multiple IF's with a switch() block.
As AWOL suggested, only validate and accumulate your buffer after a new keycode is received... not every time around the loop().
(You /may/ need to detect unwanted, 'non' keys to effectively debounce/ignore any stream of recurring characters.
lastchancename:
Two steps
Replace the multiple IF's with a switch() block.
I should be able to do that, thanks.
lastchancename:
As AWOL suggested, only validate and accumulate your buffer after a new keycode is received... not every time around the loop().
(You /may/ need to detect unwanted, 'non' keys to effectively debounce/ignore any stream of recurring characters.
Once you've implemented the switch() block, test if the character is 'different' than the previous button received before you store the character.
(This could be done before or after the switch()
if (newKey != prevKey) { // check if a key and different than previous key
switch(newKey) {
case AAA:
// save the AAA value
strValue[index++] = AAA;
break;
case BBB:
// save the BBB value
strValue[index++] = BBB;
break;
case CCC:
// save the CCC value
strValue[index++] = CCC;
break;
default;
; // whatever
}
prevKey = newKey; // keep for next comparison
}
/*
Personally I would prefer to use a pointer to accumulate the chars, but you know where you're going - so leave it this way for now.
{
// here when the buffer is full or on the first non digit
strValue[index] = 0; // terminate the string with a 0
accumulVal = atoi(strValue); // use atoi to convert string to an int
index = 0; // reset index to receive other data
}
Serial.print("Accumulated value: ");
Serial.println(accumulVal, DEC);
/*
}
Good luck.
A bit of help - but some thinking for you too!
Unfortunately I couldn't upload the modded sketch.
Error on line 40 (if newKey!=prevKey statement):
exit status 1
expected primary-expression before 'if'
What I do not understand is how you associate each case to the IRrecv decoded number, so I've added newKey=results.value, on line 35.
Further, it's not clear to me why the line
if newKey!=prevKey
since I expect I can enter the value '11', '22', 33' etc., and this would obviously imply 2 presses
with the same key.
I'm a bit confused. :o
The new code (which I cannot upload because of the error) below:
#include <IRremote.h>
/*
* Variables
*/
int RECV_PIN = 11;
const int MaxChars = 3;
char strValue[MaxChars + 1]; // String for 3 digits + null char
char ch;
int index = 0;
int accumulVal = 0;
int newKey = 0;
int prevKey = 0;
IRrecv irrecv(RECV_PIN);
decode_results results;
void setup()
{
Serial.begin(9600);
// In case the interrupt driver crashes on setup, give a clue
// to the user what's going on.
Serial.println("Enabling IRin");
irrecv.enableIRIn(); // Start the receiver
Serial.println("Enabled IRin");
}
void loop() {
if (irrecv.decode(&results)) {
Serial.println(results.value, DEC);
irrecv.resume(); // Receive the next value
}
delay(100);
newKey = results.value;
/* ------------
* -- CASES ---
*/------------
if (newKey != prevKey) { // check if a key and different than previous key
switch(newKey)
{
case 0x20DF8877 : // Button '1' on my remote
strValue[index++] = '1';
break; // assign number to button press
case 0x20DF48B7 : // Button '2' on my remote
strValue[index++] = '2';
break;
case 0x20DFC837 : // Button '3' on my remote
strValue[index++] = '3';
break;
case 0x20DF28D7 : // Button '4' on my remote
strValue[index++] = '4';
break;
case 0x20DFA857 : // Button '5' on my remote
strValue[index++] = '5';
break;
case 0x20DF6897 : // Button '6' on my remote
strValue[index++] = '6';
break;
case 0x20DFE817 : // Button '7' on my remote
strValue[index++] = '7';
break;
case 0x20DF18E7 : // Button '8' on my remote
strValue[index++] = '8';
break;
case 0x20DF9867 : // Button '9' on my remote
strValue[index++] = '9';
break;
case 0x20DF08F7 : // Button '0' on my remote
strValue[index++] = '1';
break;
} // end of cases
prevKey = newKey;
}
/*
* Accumulation
*/
else
{
// here when the buffer is full or on the first non digit
strValue[index] = 0; // terminate the string with a 0
accumulVal = atoi(strValue); // use atoi to convert string to an int
index = 0; // reset index to receive other data
}
Serial.print("Accumulated value: ");
Serial.println(accumulVal, DEC);
} // loop end
The block of code which i offered is called 'pseudo code', the purpose being to get you thinking and asking more questions.
It had some meaningful structures - to help make your code more readable and intuitive. Whether it achieves those goals is dependent on how ready you are to learn, understand, experiment and be guided.
I doubt anyone here is going to finish your project - you can go to the Gigs & Collaborations section for that.
We'll keep watching and helping, but you. need to inject the same effort.