Hi everyone,
I'm a beginner so it's possible that I'm making pretty trivial mistakes and ask fairly basic questions.
My current project is about designing a lock that opens when the correct PIN is entered via an IR-remote control.
#include <IRremote.h>
int recvPin = 11;
IRrecv irrecv(recvPin);
const uint32_t TASTE1 = 0x401, TASTE1_1 = 0x10401, TASTE2 = 0x10402, TASTE2_1 = 0x402, TASTE3 = 0x403, TASTE3_1 = 0x10403; // every button has two codes
const uint16_t SCHWELLE = 140;
uint32_t aktMillis, codeMillis;
int PINx[]={0,0,0};
int PIN[]={1,2,3};
#define lock 8
void setup ( )
{
Serial.begin(9600);
irrecv.enableIRIn();
pinMode(8, OUTPUT);
}
void loop ( )
{
aktMillis = millis();
decode_results results;
if (irrecv.decode(&results))
if (aktMillis - codeMillis > SCHWELLE){ //for debouncing
switch (results.value)
{
case TASTE1:
case TASTE1_1:
PINx[0]=1;
break;
case TASTE2:
case TASTE2_1:
PINx[0]=2;
break;
case TASTE3:
case TASTE3_1:
PINx[0]=3;
break;
}
Serial.println(PINx[0]); // for debugging, this is where the codes repeated when I held the button pressed
for (int k = sizeof(PINx) - 2; k >= 0; k--){ // here I try to move the array-entries
PINx[k+1] = PINx[k];
}
codeMillis = aktMillis;
irrecv.resume(); // Prepare for the next value
}
if (PINx == PIN){
digitalWrite(lock, HIGH);
delay(500);
digitalWrite(lock, LOW);
}
}
I want there to be no key that has to be pressed in order to confirm the code, therefore I had to look into arrays a bit and attempted to make it so that it would replace the first number of the array, while moving the previous entries one index up and deleting the last one. The problem is that I didn't have the possibility to try my code out in practice, so I would be very grateful if someone could tell me if it would work theoretically and/or what could be done better.
Also, for some reason my debounce seems to not be working and the IR-code gets printed out multiple times. I had to include it because the remote control i use sends the code for one button as long as you press it, which would lead to false PIN-attempts.
P.S. English isn't my mother tongue, so I'm sorry for any mistakes.
Try making SCHWELLE much bigger, like 1000 or 3000. Does it debounce properly?
Do you want to allow codes with the same number repeated? Like "911" has two "1". If you can exclude codes like that, then check that the new digit is different to the previous. Then you don't need the SCHWELLE debounce at all.
No. Run the little sketch below and examine the results.
int PINx[]={0,0,0};
void setup() {
Serial.begin(9600);
Serial.println(sizeof(PINx));
Serial.println(sizeof(PINx[0]));
// put your setup code here, to run once:
}
void loop() {
// put your main code here, to run repeatedly:
}
OK, so sizeof(PINx) gives me 6 and sizeof(PINx[0]) gives me 2.
I looked up the reference again and saw that I didn't take into account that it gives you the number of bytes instead of the number of variables stored.
Shall I then just subtract 4 instead of 2?
MorganS:
Do you want to allow codes with the same number repeated? Like "911" has two "1". If you can exclude codes like that, then check that the new digit is different to the previous. Then you don't need the SCHWELLE debounce at all.
My remote seems to be using the RC-5 protocol, in which the code is sent as long as the button is pressed. The code switches every time the button is pressed so that the TV would know if you just held it pressed or pressed it multiple times. Do you mean that I should try to ignore codes that are the same as the previously received one by storing it as an int and compare it? And I didn't really understand what that has to do with repeating numbers in the code...
MorganS:
Try making SCHWELLE much bigger, like 1000 or 3000. Does it debounce properly?
I tried that and it didn't change anything. The codes are sent only about 110 ms apart, so the value shouldn't have to be that big...
The fact that the key changes code each time it is pressed is useful. That means that instead of using a time based debounce to check for keycode repeat, you could store the last key that was pressed (last_key_pressed).
If this keypress (this_key_pressed) is the same as the last keypressed, (that is, the key is being held down) ignore it (do this check before entering the switch).
If this keypress is different to the last key pressed, store it in your array. Then set last_last_key_pressed to this_key_pressed.
Once you have all three and no other key is pressed for a while, you can then check against the PIN.
If there is no key pressed for a period (5sec, 10sec whatever) and there are not enough number for the PIN, clear your array, reset your counters and start again.
darrob:
The fact that the key changes code each time it is pressed is useful. That means that instead of using a time based debounce to check for keycode repeat, you could store the last key that was pressed (last_key_pressed).
If this keypress (this_key_pressed) is the same as the last keypressed, (that is, the key is being held down) ignore it (do this check before entering the switch).
If this keypress is different to the last key pressed, store it in your array. Then set last_last_key_pressed to this_key_pressed.
So something like this?
decode_results results;
if (irrecv.decode(&results)){
if (a != results.value){
switch (results.value)
{
case TASTE1:
...
case TASTE3_1:
PINx[0]=3;
break;
}
a = results.value;
Serial.println(PINx[0]);
I tried that and somehow that didn't work either. There must be some stupid mistake I'm making the whole time...
If you want to determine the number of elements in an array then divide the total number of bytes used by the array (you know how to determine this) by the size of one of the array elements (you know how to determine this)
Fresco00:
I tried that and it didn't change anything. The codes are sent only about 110 ms apart, so the value shouldn't have to be that big...
Yes, your original code will ignore the repeat at 110ms. But if you held the button down, you will get a repeat at 220ms too. That is treated as valid.
Thanks for everyones help!
I finally figured out what the problem was.
It actually was a bracked in the wrong place, which caused the millis to not function correctly and after following UKHeliBob's advice everything seemed to work...
except now I have another problem, of which I never thought it could be one: comparing the arrays.
I tried to do it like this:
Aaand it didn't work. But I can't think of the solution being too fancy, so maybe somebody could help me out with this one too. I only want to compare the content of the arrays every loop, so that no button for confirmation needs to be pressed.
But I can't think of the solution being too fancy,
Brute force method. Set a boolean to true. Use a for loop to iterate through the arrays and compare the levels in the two arrays. If a level is found not to be equal set the boolean to false and break out of the for loop. Use the value of the boolean to indicate whether or not the arrays were the same
if (irrecv.decode(&results)){
if (a != results.value){
switch (results.value)
{
case TASTE1:
...
case TASTE3_1:
PINx[0]=3;
break;
}
a = results.value;
Serial.println(PINx[0]);
I tried that and somehow that didn't work either. There must be some stupid mistake I'm making the whole time...
Exactly like that. Of course, a needs to be declared as uint32_t first.
Fresco00:
Thanks for everyones help!
I finally figured out what the problem was.
It actually was a bracked in the wrong place, which caused the millis to not function correctly and after following UKHeliBob's advice everything seemed to work...
UKHeliBob:
How many array entries will be shifted ?
How many should be shifted ?
I don't know if I really got what you wanted to tell me, but my intention is to shift the first two entries one index up, so that the last one simply gets overwritten.
Doesn't the code move PIN[1] to PIN[2] and after that PIN[0] to PIN[1]?
The stuff I get from...
for (int i = 0; i < 3; i++){
Serial.print(PIN[i]);} //debugging
Serial.println();
It seems like I just shut my brain down before inserting the array-comparison.
I looked at it again and saw that I had put the comparison after the shifting of the items . I edited the code and now everything seems fine and working. Also fixed it in post #13, if anyone ever wants to do something similar.
And again, thanks for all the help!
UKHeliBob:
In that case your for loop will work, but if you only want to move 2 entries then it is simpler to do
PIN[2] = PIN[1];
PIN[1] = PIN[0];
Yeah, but I wanted to expand the array eventually and this solution seemed more elegant.