Design Project Report Merged
Design Project Report Merged
Purpose:
The purpose of this project was to design a digital security lock with behavior based off of a simple combination lock.
Parameters:
The combination is stored in the embedded system as a sequence of three numbers between 0 and 99. The user enters the combination via a rotary encoder. The number to be encoded is displayed on a 7-segment display. The first number chosen by turning the knob on the encoder to change the value of the number displayed. Pressing the knob locks in the number, and the next two numbers are encoded in the same way. After entering the correct combination, the device changes from locked to unlocked. Two LEDs indicate the state of the lock. A red LED is illuminated while the device is in a locked state. A green LED is illuminated while the device is in an unlocked state. The display also reads two dashes, - -, when unlocked. Pressing the knob when the device is unlocked re-locks it.
Implementation:
Software:
At its core, the software in this embedded system uses a state machine to determine when the encoder knob has moved, and in which direction. This allows the value painted on the display to be incremented or decremented. This value is taken and stored when the knob is pressed. When three values have been stored, they are compared to symbolic constants that define the combination. If the values are in the correct sequence, a red LED is turned off and a green LED is lit. The Appendix pages contain flow charts and a state diagram demonstrating the operation of the code.
Hardware:
Parts: Arduino Uno 4-Digit 7-Segment Display (YSD-439AK2B-35) Green LED Red LED 2 x 300 Ohm Resistors 1 x 10k Ohm Resistor 12-position Rotary Encoder w/ Push Button
Discussion:
In essence, the purpose of this design project has been fulfilled by this implementation. The encoder knob will change the displayed value and encode three numbers for the combination. When locked, the red LED is illuminated. When unlocked, the green LED is illuminated. This is a working digital combination lock. However, some features do not work correctly. After the third number has been encoded, the lock will either unlock or remain locked, based on whether or not the correct combination has been entered. At this stage, pressing the encoder knob again will not reset the system. (However, the desired effect can essentially be achieved by pressing the reset button on the development board.) The display also does not display two dashes, - -, in an unlocked state. Please see the Appendix for source code from this project.
Appendix:
void setup() { pinMode (A0, OUTPUT); //Digit 1 Annode pinMode (A1, OUTPUT); //Digit 2 Annode //7-Seg display segments pinMode (2, OUTPUT); pinMode (3, OUTPUT); pinMode (4, OUTPUT); pinMode (5, OUTPUT); pinMode (6, OUTPUT); pinMode (7, OUTPUT); pinMode (8, OUTPUT); pinMode (9, OUTPUT); //Green LED pinMode (10, OUTPUT); //Red LED pinMode (11, INPUT); //Encoder Pin A pinMode (12, INPUT); //Encoder Pin B pinMode (A2, INPUT); //Encoder PushButton } //symbolic constants for state machine in RotaryRead() #define IDLE 0 #define CW1 1 #define CW2 2 #define CW3 3 #define CCW1 4 #define CCW2 5 #define CCW3 6 //symbolic constants to assign display segments to pins in digitDisplay() #define SEG_A 2 #define SEG_B 3 #define SEG_C 4 #define SEG_D 5 #define SEG_E 6 #define SEG_F 7 #define SEG_G 8 //symbolic constants for TwoDigDisplay() #define DIGIT_ONE A0 #define DIGIT_TWO A1 //symbolic constants to set combonation #define COMBO_ONE 2 #define COMBO_TWO 8 #define COMBO_THREE 9
#define NUM1 0 #define NUM2 1 #define NUM3 2 #define NUM4 3 void loop() { static char storageArray[3]; TwoDigDisplay (EncodeReturn () ); Lock (storageArray); if ( (storageArray[0] == COMBO_ONE) && (storageArray[1] == COMBO_TWO) && (storageArray[2] == COMBO_THREE) ) { digitalWrite (9,HIGH); digitalWrite (10,LOW); } else { digitalWrite (9,LOW); digitalWrite (10,HIGH); } }
void Lock (char arrayInput[] ) { //declares chars = -1 static char storage1 = -1; static char storage2 = -1; static char storage3 = -1; //declares char p = value of pushbutton char p = digitalRead (A2); //executes if first number has not been encoded if (storage1 == -1) { //waits for pushbutton release and encodes first number while (p == 0) { storage1 = EncodeReturn(); p = digitalRead (A2); } //paints display with current value of number to be encoded TwoDigDisplay (EncodeReturn() ); }
//executes if second number has not been encoded if (storage2 == -1) { //waits for pushbutton release and encodes second number while (p==0) { storage2 = EncodeReturn(); p = digitalRead (A2); } //paints display with current value of number to be encoded TwoDigDisplay (EncodeReturn() ); } //Executes if third number has not been encoded if (storage3 == -1) { //waits for pushbutton release and encodes third number while (p == 0) { storage3 = EncodeReturn(); p = digitalRead (A2); } //paints display with current value of number to be encoded TwoDigDisplay (EncodeReturn() ); }
arrayInput[0] = storage1; //sets the first element of arrayInput equal to storage1 arrayInput[1] = storage2; //sets the second element of arrayInput equal to storage2 arrayInput[2] = storage3; //sets the third element of arrayInput equal to storage3
} //function returns a char 0 thru 99 to be encoded into the lock combonation char EncodeReturn (void) { char encoderTurn = RotaryRead(); //declares encoderTurn = the return of RotaryRead() static char code = 0; //declares a static char code = 0 //executes if knob is turned CW if (encoderTurn==1) { ++code; //increments code //if statement to reset code to 0 at >99 if(code>99)
{ code=0; } } //executes if knob is turned CCW if (encoderTurn==2) { --code; //decrements code //if statement resets code to 99 at <0 if (code<0) { code=99; } } return code; //returns value of code } //function returns "0" when encoder does not move, //returns "1" when encoder turns clockwise, //returns "2" when encoder turns counter-clockwise. char RotaryRead() { char turn = 0; static char state = 0; //declares chars A and B char A; char B; //declares A and B equal to value of encoder pins A and B A = digitalRead(11); B = digitalRead(12); //state machine for rotary encoder switch (state) { //case for when encoder is in idle position case IDLE: if ( (A == 0) && (B == 1) ) { state = CW1; //changes state to CW1 when knob begins to turn CW } if ( (A == 1) && (B == 0) ) { state = CCW1; //changes state to CCW1 when knob begins to turn CCW }
break; //case for 1/4 of a CW turn case CW1: if ( (A == 0) && (B == 0) ) { state = CW2; //changes state to CW2 when knob one half of a CW turn } if ( (A == 1) && (B == 1) ) { state = IDLE; //changes state to IDLE if encoder returns to idle position } break; //case for 1/2 of CW turn case CW2: if ( (A == 1) && (B == 0) ) { state = CW3; //sets state to CW3 if encoder is 3/4 through CW turn } if ( (A == 1) && (B == 1) ) { state = IDLE; //sets state to IDLE if encoder returns to idle position } break; //case for 3/4 of CW turn case CW3: if ( (A == 1) && (B==1) ) { state = IDLE; //returns state to IDLE upon completing CW turn turn = 1; //sets char turn = 1 to indicate completed CW turn } break; //case for 1/4 of CCW turn case CCW1: if ( (A == 0) && (B == 0) ) { state = CCW2; //sets state to CCW2 if encoder is 1/4 thru CCW turn } if ( (A == 1) && (B == 1) ) { state = IDLE; //sets state to IDLE if encoder returns to idle position } break; //case for 1/2 of CCW turn
case CCW2: if ( (A == 0) && (B == 1) ) { state = CCW3; //sets state to CCW3 if encoder is 1/2 thru CCW turn } if ( (A == 1) && (B == 1) ) { state = IDLE; //sets state to IDLE if encoder returns to idle position } break; //case for 3/4 of CCW Click case CCW3: if ( (A == 1) && (B == 1) ) { state = IDLE; //returns state to IDLE upon completing CCW turn turn = 2; //sets char turn = 2 to indicate completed CCW turn } break; //default statement does nothing default: break; } //returns value of turn return turn; } //displays the two-digit unsigned char passed to the function void TwoDigDisplay (unsigned char twoDigitValue) { //creates unsigned chars "tens" and "ones" unsigned char tens; unsigned char ones; //splits a two-digit number passed into the function //into positional tens and ones values, stores in //"tens" and "ones", respectively tens = (twoDigitValue / 10); ones = (twoDigitValue % 10); //executes if twoDigitValue passed to function is < 10, //displays the value on two 7-segment displays if (twoDigitValue < 10) { //displays ones position digit digitalWrite (DIGIT_ONE, HIGH); digitDisplay (ones);
delayMicroseconds (200); //displays a "0" in position of tens digit clearLED (); digitalWrite (DIGIT_ONE, LOW); digitalWrite (DIGIT_TWO, HIGH); digitDisplay (0); delayMicroseconds (200); //clears display and deactivates tens digit clearLED (); digitalWrite (DIGIT_TWO, LOW); } //executes if twoDigitValue passed to function is >= 10, //displays the value on two 7-segment displays if (twoDigitValue >= 10) { //displays value of char "ones" to ones postion digit digitalWrite (DIGIT_TWO, LOW); digitDisplay (ones); delayMicroseconds (200); //displays value of char "tens" to tens position digit clearLED (); digitalWrite (DIGIT_TWO, HIGH); digitalWrite (DIGIT_ONE, LOW); digitDisplay (tens); delayMicroseconds (200); //clears display and deactivates tens digit clearLED (); digitalWrite (DIGIT_ONE, HIGH); } } //pulls cathodes of 7-segment display LOW/HIGH to display a digit //accepts a single-digit unsigned char value void digitDisplay (unsigned char digit) { //switch based on digit passed to function switch (digit) { //displays a 0 case 0: digitalWrite(SEG_A, LOW); digitalWrite(SEG_B, LOW); digitalWrite(SEG_C, LOW);
digitalWrite(SEG_D, LOW); digitalWrite(SEG_E, LOW); digitalWrite(SEG_F, LOW); digitalWrite(SEG_G, HIGH); break; //displays a 1 case 1: digitalWrite(SEG_A, HIGH); digitalWrite(SEG_B, LOW); digitalWrite(SEG_C, LOW); digitalWrite(SEG_D, HIGH); digitalWrite(SEG_E, HIGH); digitalWrite(SEG_F, HIGH); digitalWrite(SEG_G, HIGH); break; //displays a 2 case 2: digitalWrite(SEG_A, LOW); digitalWrite(SEG_B, LOW); digitalWrite(SEG_C, HIGH); digitalWrite(SEG_D, LOW); digitalWrite(SEG_E, LOW); digitalWrite(SEG_F, HIGH); digitalWrite(SEG_G, LOW); break; //displays a 3 case 3: digitalWrite(SEG_A, LOW); digitalWrite(SEG_B, LOW); digitalWrite(SEG_C, LOW); digitalWrite(SEG_D, LOW); digitalWrite(SEG_E, HIGH); digitalWrite(SEG_F, HIGH); digitalWrite(SEG_G, LOW); break; //displays a 4 case 4: digitalWrite(SEG_A, HIGH); digitalWrite(SEG_B, LOW); digitalWrite(SEG_C, LOW); digitalWrite(SEG_D, HIGH); digitalWrite(SEG_E, HIGH); digitalWrite(SEG_F, LOW); digitalWrite(SEG_G, LOW); break; //displays a 5
case 5: digitalWrite(SEG_A, LOW); digitalWrite(SEG_B, HIGH); digitalWrite(SEG_C, LOW); digitalWrite(SEG_D, LOW); digitalWrite(SEG_E, HIGH); digitalWrite(SEG_F, LOW); digitalWrite(SEG_G, LOW); break; //displays a 6 case 6: digitalWrite(SEG_A, LOW); digitalWrite(SEG_B, HIGH); digitalWrite(SEG_C, LOW); digitalWrite(SEG_D, LOW); digitalWrite(SEG_E, LOW); digitalWrite(SEG_F, LOW); digitalWrite(SEG_G, LOW); break; //displays a 7 case 7: digitalWrite(SEG_A, LOW); digitalWrite(SEG_B, LOW); digitalWrite(SEG_C, LOW); digitalWrite(SEG_D, HIGH); digitalWrite(SEG_E, HIGH); digitalWrite(SEG_F, HIGH); digitalWrite(SEG_G, HIGH); break; //displays a 8 case 8: digitalWrite(SEG_A, LOW); digitalWrite(SEG_B, LOW); digitalWrite(SEG_C, LOW); digitalWrite(SEG_D, LOW); digitalWrite(SEG_E, LOW); digitalWrite(SEG_F, LOW); digitalWrite(SEG_G, LOW); break; //displays a 9 case 9: digitalWrite(SEG_A, LOW); digitalWrite(SEG_B, LOW); digitalWrite(SEG_C, LOW); digitalWrite(SEG_D, HIGH); digitalWrite(SEG_E, HIGH); digitalWrite(SEG_F, LOW);
digitalWrite(SEG_G, LOW); break; //defaults to displaying a "-" default: digitalWrite(SEG_A, HIGH); digitalWrite(SEG_B, HIGH); digitalWrite(SEG_C, HIGH); digitalWrite(SEG_D, HIGH); digitalWrite(SEG_E, HIGH); digitalWrite(SEG_F, HIGH); digitalWrite(SEG_G, LOW); break; } } //void function clears a common-annode 7-segment display void clearLED (void) { //declares char led char led; //cycles thru pins 2 to 9, pulling each high to turn off segment for (led = 2; led < 9; led++) { digitalWrite (led, HIGH); } return; }
twoDigDisplay(encodeReturn());
Lock(storageArray);
digitalWrite(9,HIGH); digitalWrite(10,LOW);
digitalWrite(9,HIGH); digitalWrite(10,LOW);
LOOP
Char P = digitalRead(A2);
Storage1 == -1 ?
P == 0 ?
twoDigDisplay(encodeReturn()); Storage2 == -1 ? Y
Storage1 = encodeReturn();
P = digitalRead(A2);
N N
P == 0 ? Y
twoDigDisplay(encodeReturn()); Storage2=encodeReturn();
P=digitalRead(A2); Storage3 == -1 ?
N N
P == 0 ?
twoDigDisplay(encodeReturn());
Storage3=encodeReturn();
P=digitalRead(A2);
BEGIN
TwoDigitValue
digitDisplay(ones);
delayMicroseconds(200);
digitDisplay(ones);
clearLED();
delayMicroseconds(200);
clearLED();
displayDigit(tens);
delayMicroseconds(200);
clearLED();
END
BEGIN
Digit = 0?
Y N N N N N N N
Displays 0
Y Digit = 4? Displays 1 Y
Digit = 6?
Digit = 8?
Display E
END
BEGIN
encoderTurn = rotaryRead();
encoderTurn == 1?
Y ++code;
Code > 99 ?
Y Code = 0;
encoderTurn == 2 ?
--code;
Return code;
END
CCW1
(1,1) (1,1)