Help changing code for bluetooth door lock?

Hi guys, I have been reading an instructable writeup on how to make an Arduino bluetooth door lock which I would like to make. So far, I have assembled the entire device, but I need help in editing the code. See, instead of unlocking for just a few seconds when a serial code is sent via bluetooth from an Android powered device, I want it to stay unlocked. Then, I would like it to lock when I send the serial code again. It is going on my bedroom door, where I don't want it to be locked all the time by default, but instead only when I want it to be locked.

Here is the code that I have been using, if anyone is able to show me how I can change it to fit my needs, it would be much appreciated. I have been reading and searching left and right, even attending a lesson on Arduino code today at a local place, but it was very much aimed at the complete beginner and the instructor there was of no real help.

int lock = 9;          //pin 9 on Arduino
char final[4];         //Characters the Arduino will receive
char correct[4] = {'A','B','C','D'};    //User-Defined Password
int pass_correct = 0;          //Does Password match, 0=false 1=true

void setup()
{
pinMode(lock, OUTPUT);
Serial.begin(9600);
digitalWrite(lock, HIGH);  //By default, lock is active(locked)
}

void loop()
{
while(Serial.available()) 
{
  for(int i=0; i<4; i++)   //While data is available read 4 bytes
  {
   final[i] = Serial.read();  //Read 4 bytes into the array labled "final"
  }

  for(int i=0; i<4; i++)
  {
   if(final[i]==correct[i]) //Compare each char received to each car in our password in order
   {
    pass_correct = 1;   //If we compare two chars and they match, set the pass_correct variable to true(1)
   }
   else
   {
    pass_correct = 0;  //if the two compared chars do NOT match, set pass_correct variable to false(0)
    break;   //End loop and stop comparing chars
   }
  }
}

if(pass_correct==1)  //If all chars compared match, deactivate(unlock) the lock for 5 seconds
{
  Serial.println("Unlocked");
  digitalWrite(lock, LOW);
  delay(5000);
  Serial.println("Locked");
  pass_correct = 0;
}
else
{
digitalWrite(lock, HIGH); //Else if there was not a complete match, keep the lock high(locked)
}

/* FOR TESTING
Serial.print(final[0]);Serial.print(final[1]);Serial.print(final[2]);Serial.print(final[3]);
Serial.print(" | ");
Serial.print(correct[0]);Serial.print(correct[1]);Serial.print(correct[2]);Serial.print(correct[3]);
Serial.print(" ");
Serial.print(pass_correct);
Serial.println("");
*/
delay(500);


}

If there is any additional information needed to help on this project, please let me know so I can get back to you as soon as I can.

Thanks in advance, guys! (and gals!)

Once again, proof that Instructables == crap.

while(Serial.available()) 
{
  for(int i=0; i<4; i++)   //While data is available read 4 bytes
  {
   final[i] = Serial.read();  //Read 4 bytes into the array labled "final"
  }

When there is at least one byte to read, read all 4 of them. Nope. Doesn't work that way.

if(pass_correct==1)  //If all chars compared match, deactivate(unlock) the lock for 5 seconds
{
  Serial.println("Unlocked");
  digitalWrite(lock, LOW);
  delay(5000);
  Serial.println("Locked");
  pass_correct = 0;
}
else
{
digitalWrite(lock, HIGH); //Else if there was not a complete match, keep the lock high(locked)
}

This is the code that unlocks the door, waits 5 seconds, and then locks it again.

Add a global boolean variable to keep track of whether the door is locked or unlocked. If it is locked, unlock it. If it is unlocked, lock it.

boolean locked = true; // Set initial state as appropriate
if(pass_correct==1)  //If all chars compared match, deactivate(unlock) the lock for 5 seconds
{
  if(locked)
  {
    Serial.println("Unlocking");
    digitalWrite(lock, LOW);
    locked = false;
  else
  {
    Serial.println("Locking");
    digitalWrite(lock, HIGH);
    locked = true;
  }
  pass_correct = 0;
}
else
{
  digitalWrite(lock, HIGH); //Else if there was not a complete match, keep the lock high(locked)
}

Please, pardon my ignorance, how should I put this all together? Are you saying that there are additional changes to the 4-byte reading process that must be made in order for this project to function?

Thanks much.

Simplest solution for a novice would be to just change to this:

while(Serial.available() >= 4) 
{
  for(int i=0; i<4; i++)   //While data is available read 4 bytes
  {
   final[i] = Serial.read();  //Read 4 bytes into the array labled "final"
  }

Wait, and this would ameliorate the entire thing?

Wait, and this would ameliorate the entire thing?

Did you try the changes suggested?

Okay, I have integrated all of these suggestions (from both of your posts). I am testing with an LED instead of a door lock for the time being, which should not cause any issues, I don't believe. Correct me if I am wrong. Here is what happens now:

  • LED starts on (i.e. door starts locked).
  • Send ABCD, LED goes off for less than 1 second, prints "unlocking".
  • Send ABCD again, prints "locking" but nothing happens with the actual device.
  • Send ABCD again, repeats step 2.
  • Send ABCD again, repeats step 3.

Then repeats over and over again. So, this has something to do with the Boolean re-reading itself as soon as it changes itself, right? I can see the light at the end of the tunnel, just need to get this last part working.

Thanks guys.

Then repeats over and over again. So, this has something to do with the Boolean re-reading itself as soon as it changes itself, right? I can see the light at the end of the tunnel, just need to get this last part working.

So, you made some code changes. You did not post the modified code. Still, you want us to help you figure out what is wrong with it. It seems that there is something you need to do, if I could just figure out what it was...

Whoops, I'm sorry. Here is the code which is modified with all of the suggest changes that were listed.

int lock = 9;          //pin 9 on Arduino
char final[4];         //Characters the Arduino will receive
char correct[4] = {'A','B','C','D'};    //User-Defined Password
int pass_correct = 0;          //Does Password match, 0=false 1=true
boolean locked = true;

void setup()
{
pinMode(lock, OUTPUT);
Serial.begin(9600);
digitalWrite(lock, HIGH);  //By default, lock is active(locked)
}

void loop()
{
while(Serial.available() >= 4) 
{
  for(int i=0; i<4; i++)   //While data is available read 4 bytes
  {
   final[i] = Serial.read();  //Read 4 bytes into the array labled "final"
  }

  for(int i=0; i<4; i++)
  {
   if(final[i]==correct[i]) //Compare each char received to each car in our password in order
   {
    pass_correct = 1;   //If we compare two chars and they match, set the pass_correct variable to true(1)
   }
   else
   {
    pass_correct = 0;  //if the two compared chars do NOT match, set pass_correct variable to false(0)
    break;   //End loop and stop comparing chars
   }
  }
}

if(pass_correct==1)  //If all chars compared match, deactivate(unlock) the lock for 5 seconds
{
  if(locked)
  {
    Serial.println("Unlocking");
    digitalWrite(lock, LOW);
    locked = false;
  }
  else
  {
    Serial.println("Locking");
    digitalWrite(lock, HIGH);
    locked = true;
  }
  /*Serial.println("Unlocked");
  digitalWrite(lock, LOW);
  delay(5000);
  Serial.println("Locked");*/
  pass_correct = 0;
}
else
{
digitalWrite(lock, HIGH); //Else if there was not a complete match, keep the lock high(locked)
}

/* FOR TESTING
Serial.print(final[0]);Serial.print(final[1]);Serial.print(final[2]);Serial.print(final[3]);
Serial.print(" | ");
Serial.print(correct[0]);Serial.print(correct[1]);Serial.print(correct[2]);Serial.print(correct[3]);
Serial.print(" ");
Serial.print(pass_correct);
Serial.println("");
*/
delay(500);


}

Thanks for helping :slight_smile:

You don't want that final else clause. pass_correct gets set back to 0 after one pass through the loop, and after that the final else clause will forever write the pin high, until pass_correct is set to 1 again by receiving a message.

Perhaps you need to remove this line:

  pass_correct = 0;

I'm not sure why pass_correct is an int. It only holds two values - 0 and 1. Could be a byte, but, really it would make more sense as a boolean, containing true or false.

WizenedEE and PaulS -- thanks very much. WizenedEE's last suggestion took care of it in addition to Paul's previous changes.

Thanks for putting up with my noob-ness!