debounce not working / handling arrays

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.

tell me if it would work theoretically

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... :confused:

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...

Shall I then just subtract 4 instead of 2?

No

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)

This method will work for an array of any type

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:

if(PIN[0] == PINx[0] && PIN[1] == PINx[1] && PIN[2] == PINx[2]
{
  Serial.print ("arrays equal")
}

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

Fresco00:
I only want to compare the content of the arrays every loop, so that no button for confirmation needs to be pressed.

Redeclare your arrays as type byte and use my new favorite function - memcmp(). This'll save a small bit of RAM as well.

Fresco00:
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...

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...

Can you post your code to show what you did?

dougp:
Redeclare your arrays as type byteand use my new favorite function - memcmp(). This'll save a small bit of RAM as well.

I tried implementing it like this:

for (int k = sizeof(PIN) - 2; k >= 0; k--)//shifting the Items of the array
      {
        PIN[k+1] = PIN[k];
      }
      n = memcmp (PIN, PINx, sizeof(PIN)); //comparing arrays
      if (n == 0)
      {
        Serial.println("arrays equal");
      }
    }
    codeMillis = aktMillis;
    irrecv.resume();

With the arrays re-declared as byte and n as an int, but it never gives me "arrays equal"

darrob:
Can you post your code to show what you did?

before I fixed it, the brackets of the if-statement for the debounce included "codeMillis = aktMillis;"

So this is the whole code now, after tidying everything up a bit

#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;
const uint16_t SCHWELLE = 130;
uint32_t aktMillis, codeMillis;
byte PIN[]={0,0,0};
byte PINx[]={1,2,3};
int n;

void  setup ( )
{
  Serial.begin(9600);   
  irrecv.enableIRIn();
  #define lock 8 
}

void  loop ( )
{
  aktMillis = millis();
  decode_results  results;        
  
  if (irrecv.decode(&results)) 
  {  
    if (aktMillis - codeMillis > SCHWELLE)
    {
      switch (results.value)
      {
        case TASTE1:
        case TASTE1_1:
          PIN[0]=1;
          break;
        case TASTE2:
        case TASTE2_1:
          PIN[0]=2;
          break;
        case TASTE3:
        case TASTE3_1:
          PIN[0]=3;
          break;
      }
      for (int i = 0; i < 3; i++){
        Serial.print(PIN[i]);}  //debugging
        Serial.println();
      n = memcmp (PIN, PINx, sizeof(PIN)); //comparing arrays
      if (n == 0)
      {
        Serial.println("arrays equal");
      }
      for (int k = sizeof(PIN) - 2; k >= 0; k--)//shifting the Items of the array
      {
        PIN[k+1] = PIN[k];
      }
     }
    codeMillis = aktMillis;
    irrecv.resume();              
  }
}
byte PIN[] = {0, 0, 0};

PIN is an array of 3 bytes so sizeof(PIN) will be 3

for (int k = sizeof(PIN) - 2; k >= 0; k--)//shifting the Items of the array

is equivalent to

for (int k = 1; k >= 0; k--)//shifting the Items of the array
     {
        PIN[k + 1] = PIN[k];
      }

How many array entries will be shifted ?
How many should be shifted ?

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();

...seems correct

my intention is to shift the first two entries one index up,

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];

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 :roll_eyes: . 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.