Using a password to start a servo

So, I finally got my 2 pieces of code to work as one, but I am still having difficulty using an actual key-code to start my servo. i want to enter the key-code "1234" for example on my keypad that is using a one-wire voltage divider input. I then want it to rotate the servo, wait 5 seconds, and then rotate the servo back.

Here is what I have thus far:

#include <Servo.h>
String keys="123A456B789C*0#D";
int key;
boolean key_lockout=false;
int button1 = 4;
int press1 = 0;
int pos = 90;
Servo servo1;
void setup()
{
  Serial.begin(9600);

  pinMode(button1, INPUT);
  servo1.attach(13);
  digitalWrite(4, HIGH);
}

void loop(){

  key=getKeypad();
  if(key!=-1)
      Serial.println(keys[key]);
   delay(10);
  press1 = digitalRead(button1);
  if (press1 == LOW)
  {
    servo1.write(0);
    delay(5000);
    servo1.write(90);
  }
}

int getKeypad(){
  int ret=-1;
  boolean reset_lockout=false;
  if(analogRead(A0)==0)
    key_lockout=false;
  else if(!key_lockout){
    delay(20);
    ret=15-(log((analogRead(A0)-183.9)/58.24)/0.1623)+0.5;
    key_lockout=true;
  }
  return ret;
}

This compiles, but I'm certain that the keypad part is only outputting the keystrokes to the serial monitor. I need help using a set code to start this process. Any help please???

jrugg8028:
This compiles, but I'm certain that the keypad part is only outputting the keystrokes to the serial monitor.

Of course it does, because that's all you do with it. You then make a digitalRead of an entirely different button to decide how to procede.

To save us the pain of reverse engineering your getKeypad function. Can you tell us what gets printed in the serial monitor when you press "1234".

KenF:
To save us the pain of reverse engineering your getKeypad function. Can you tell us what gets printed in the serial monitor when you press "1234".

You just see 1234, but it is vertical, it never goes side-by-side. Can you even input passcode like that?

What you need to do is save each keypress in a separate string. You also need to have a method of keeping track of where your are in the string.

I'd also suggest you use one of the other characters (such as the # symbol) to mark the end of the users input.

See if this gets you any closer. You'll probably have to debug it as it's totally untested.

#include <Servo.h>
String keys="123A456B789C*0#D";
int key;
boolean key_lockout=false;
int button1 = 4;
int press1 = 0;
int pos = 90;
Servo servo1;
void setup()
{
  Serial.begin(9600);

  pinMode(button1, INPUT);
  servo1.attach(13);
  digitalWrite(4, HIGH);
}

char password[]={"1234"};
char enteredString[5]={""};
int stringPos=0;


void loop(){

  key=getKeypad();
  if( (key>-1) && (keys[key]!='*') && (keys[key]!='#') )
  {
   //save current char
   enteredString[stringPos++]=keys[key];
   //terminate string
   enteredString[stringPos]=0;
   //prevent writing past end of string
   stringPos -= (stringPos > 3);
   Serial.print(keys[key]);
   delay(10);
  }
  
 
  if (keys[key] =='#')
  {//reset ready for next attempt
    Serial.println("");
    stringPos=0;
    if ( strcmp(enteredString, password)==0) 
      {Serial.println("Quick, it's open");
       servo1.write(0);
       delay(5000);
       servo1.write(90);
      }
    else
      Serial.println("GO AWAY!");
    }
}

int getKeypad(){
  int ret=-1;
  boolean reset_lockout=false;
  if(analogRead(A0)==0)
    key_lockout=false;
  else if(!key_lockout){
    delay(20);
    ret=15-(log((analogRead(A0)-183.9)/58.24)/0.1623)+0.5;
    key_lockout=true;
  }
  return ret;
}

BTW println introduces the new line. If you don't want a new line you shoud use Serial.print("without a new line");

KenF:
What you need to do is save each keypress in a separate string. You also need to have a method of keeping track of where your are in the string.

I'd also suggest you use one of the other characters (such as the # symbol) to mark the end of the users input.

See if this gets you any closer. You'll probably have to debug it as it's totally untested.

It compiled the first try, but it prints a "1" in the monitor every 6 seconds or so. Also, when i input 1234 and press #, it says go away. Any idea what that could be?

Also, thank you so much for how fast you replied! Kudos to your skill set.

Well the 1 popping up every few seconds is likely a slight bug in your getKeypad() function. I notice you're using some pretty complex maths in there.

The more normal approach is to have an array of thresholds. Then a for loop that checks the current analog value against each until it finds one that is high enough. Then the loop counter tells you which button is being held. If it gets to the end of the array, then no key is being pressed.

Since analogRead is so sensitive, it's likely that your getKeypad is detecting some slight RF signal or something.

To get a better idea of why your entered string is not working, you could try adding
Serial.println(enteredString); just after the "Go Away" line.

KenF:
Well the 1 popping up every few seconds is likely a slight bug in your getKeypad() function. I notice you're using some pretty complex maths in there.

The more normal approach is to have an array of thresholds. Then a for loop that checks the current analog value against each until it finds one that is high enough. Then the loop counter tells you which button is being held. If it gets to the end of the array, then no key is being pressed.

Since analogRead is so sensitive, it's likely that your getKeypad is detecting some slight RF signal or something.

To get a better idea of why your entered string is not working, you could try adding
Serial.println(enteredString); just after the "Go Away" line.

Yes that makes a lot of sense. Thank you again for all your help. i edited your code so that my push button works, and it does very well. I am almost complete. I am now working on adding a 16x2 lcd to view these inputs away from a computer. Do you have any advice on that? The tutorial has the standard way of input using 8 pins, and as you know i am using one.

16x2 LCDs come in many forms. Some use the SPI lines, others use I2C. One issue you may face is cable length. Neither of these methods are very suitable for long connections. But adding length to your keypad may also cause problems.

Maybe your keypad and door lock mechanism could be managed by an ATtiny You could then use something like RS232 to communicate with a separate controller that has the LCD and a user interface for administrative functions.

BTW one omission on my part is that when someone enters, it doesn't clear the enteredString. So anyone following could just press # to gain entry. So besides resetting stringPos to 0 you should also write enteredString[0]=0;

KenF:
BTW one omission on my part is that when someone enters, it doesn't clear the enteredString. So anyone following could just press # to gain entry. So besides resetting stringPos to 0 you should also write enteredString[0]=0;

That sounds like a good idea, but my knowledge of that is very limited. This is only for a school project (Electrical Engineering).

Where exactly would I add that piece into the code? Below is your code with modifications for my pushbutton to work. Also, how can I make a longer password? I tried to change "enteredString" to one number above the new code, but it didn't work past 4 characters.

Here is the code:

#include <LiquidCrystal.h>
#include <Servo.h>
String keys="123A456B789C*0#D";
int key;
boolean key_lockout=false;
int button1 = 7;
int press1 = 0;
int pos = 90;
int led = 8;
int led2 = 9;

Servo servo1;
void setup()
{
  Serial.begin(9600);

  
  pinMode(button1, INPUT);
  pinMode(led, OUTPUT);
  pinMode(led, OUTPUT);
  servo1.attach(13);
  digitalWrite(7, HIGH);
  digitalWrite(8, LOW);
  digitalWrite(9, LOW);
}

char password[]={"1234"};
char enteredString[5]={""};
int stringPos=0;


void loop(){

  key=getKeypad();
  if( (key>-1) && (keys[key]!='*') && (keys[key]!='#') )
  {
   //save current char
   enteredString[stringPos++]=keys[key];
   //terminate string
   enteredString[stringPos]=0;
   //prevent writing past end of string
   stringPos -= (stringPos > 3);
   Serial.print(keys[key]);
   delay(10);
  }
  
 
  if (keys[key] =='#')
  {//reset ready for next attempt
    Serial.println("");
    stringPos=0;
    if ( strcmp(enteredString, password)==0) 
      {digitalWrite(led, HIGH);
        Serial.println("Quick, it's open");
       servo1.write(0);
       delay(5000);
       servo1.write(90);
       digitalWrite(led, LOW);
       digitalWrite(led2, HIGH);
    delay(1000);
    digitalWrite(led2, LOW);
      }
    else
    digitalWrite(led2, HIGH);
      Serial.println("GO AWAY!");
      delay(1000);
      digitalWrite(led2, LOW);
    }
    press1 = digitalRead(button1);
    if (press1==LOW)
    {
    digitalWrite(led, HIGH);
    servo1.write(0);
    delay(5000);
    servo1.write(90);
    digitalWrite(led, LOW);
    digitalWrite(led2, HIGH);
    delay(1000);
    digitalWrite(led2, LOW);
  }
      
}

int getKeypad(){
  int ret=-1;
  boolean reset_lockout=false;
  if(analogRead(A0)==0)
    key_lockout=false;
  else if(!key_lockout){
    delay(20);
    ret=15-(log((analogRead(A0)-183.9)/58.24)/0.1623)+0.5;
    key_lockout=true;
  }
  return ret;
}

And again, I cannot thank you enough.

Ken,

Can you take a look as to why this would be printing a 1 every so often? It makes it impossible to enter a correct password. when i try my original code, it never throws the one. Any ideas?

String keys="123A456B789C*0#D";

Why are you pissing away resources on the String class to hold a fixed size string? Use a string!

  pinMode(button1, INPUT);

How IS this switch wired? What are you NOT using the internal pullup resistor, instead of an external resistor? You are using an external resistor, right?

  pinMode(led, OUTPUT);
  pinMode(led, OUTPUT);

Maybe you need to do this a couple more times.

  if( (key>-1) && (keys[key]!='*') && (keys[key]!='#') )

Why are you using key as an index into the array?

   //prevent writing past end of string
   stringPos -= (stringPos > 3);

There are ways of doing this that make more sense than subtracting true or false from the index.

   delay(10);

Useless.

   Serial.print(keys[key]);

Anonymous prints are stupid. Clearly identify WHAT you are printing, or don't bother printing.

Also, how can I make a longer password? I tried to change "enteredString" to one number above the new code, but it didn't work past 4 characters.

Did you change the value of password, too? Did you change the > 3 in the convoluted code?

PaulS:

String keys="123A456B789C*0#D";

Why are you pissing away resources on the String class to hold a fixed size string? Use a string!

  pinMode(button1, INPUT);

How IS this switch wired? What are you NOT using the internal pullup resistor, instead of an external resistor? You are using an external resistor, right?

  pinMode(led, OUTPUT);

pinMode(led, OUTPUT);



Maybe you need to do this a couple more times.



if( (key>-1) && (keys[key]!='*') && (keys[key]!='#') )



Why are you using key as an index into the array?



//prevent writing past end of string
  stringPos -= (stringPos > 3);



There are ways of doing this that make more sense than subtracting true or false from the index.



delay(10);



Useless.



Serial.print(keys[key]);



Anonymous prints are stupid. Clearly identify WHAT you are printing, or don't bother printing.
Did you change the value of password, too? Did you change the > 3 in the convoluted code?

I appreciate your help, but I am a novice, so i have almost no idea what you are saying. I did manage to figure everything out on my own though. If you can be of more help, I just posted another question.