/* EPOCH PROJECT#12: MULTIPLEXING THE 4-DIGIT 7-SEGMENT DISPLAY! IN THIS PROJECT, WE'LL CONTROL ONE DIGIT OF THE DISPLAY, AND TURN IT ON AND OFF WITHOUT THE USE OF A LIBRARY. THIS IS SO THAT YOU CAN UNDERSTAND HOW THE DISPLAY WORKS. CONNECTIONS: MAKE ALL OF THE FOLLOWING CONNECTIONS TO CHIP-A CONNECT GPIO PINS 2/3/4/5/6/7/8/9 TO QUAD 7-SEGMENT DISPLAY PINS A/B/C/D/E/F/G/DOT RESPECTIVELY CONNECT GPIO PIN 10 TO QUAD 7-SEGMENT CHANNEL 1 DISPLAY PIN 10 CONNECT GPIO PIN 10 TO QUAD 7-SEGMENT CHANNEL 2 DISPLAY PIN 11 CONNECT GPIO PIN 10 TO QUAD 7-SEGMENT CHANNEL 3 DISPLAY PIN 12 CONNECT GPIO PIN 10 TO QUAD 7-SEGMENT CHANNEL 4 DISPLAY PIN 13 */ #define PRG 2 #define pina 9 // THESE PINS CONTROL SEGMENTS 1A-G, AND DOT #define pinb 8 #define pinc 7 #define pind 6 #define pine 5 #define pinf 10 #define pinG 11 #define pindot 12 #define control1 13 // This pin will be used to turn display 1 on and off //#define control2 11 // This pin will be used to turn display 2 on and off //#define control3 12 // This pin will be used to turn display 3 on and off //#define control4 13 // This pin will be used to turn display 4 on and off int seg1 = 0; // THIS IS THE NUMBER THAT THE SEGMENT IS HOLDING IN THE COUNTDOWN SEQUENCE. SEGMENT 1 IS THE RIGHT MOST DIGIT, AND SEGMENT 4 IS THE LEFT MOST // IF THE TIMER IS 05:00, SEG1, SEG2, AND SEG 4 ARE 0, AND SEG5 = 5; int seg2 = 0; int seg3 = 0; int seg4 = 0; int seg1save = 0; int seg2save = 0; int seg3save = 0; int seg4save = 0; int segnum = 0; // THIS IS USED IN THE DECODER FUNCTION, AND TELLS THE PROGRAM WHICH SEGMENT TO LOOK AT int counter = 0; // THIS IS USED FOR MULTIPLEXING int hold = 0; // THIS INTEGER HOLDS DATA TEMPORARILY int hold2 = 0; // SAME AS ABOVE int trigger = 0; // THIS INTEGER IS USED TO TELL THE PROGRAM WHEN TIME HAS RUN OUT 00:00 int pindecide = 0; int modeval = 0; int manualprogramming = 0; int numberhold = 0; // numberhold determines whether or not we stop timer values from exceeding a 'second value of 59. For timer modes, this will be set to 5. For point mode, 9. // #define inval 4 // inval IS OUR RECEIVER LINE, WHICH IS DEDICATED TO GPIO PIN #4 #define OUTSIG 3 // THIS OUTPUT TELLS THE PROGRAMMER THAT THE TIMER HAS BEEN COUNTED DOWN TO 0, OR TO A CLOCKED TIME int val = 0; // val IS TE INTEGER THAT HOLDS THE INCOMING DATA int state = 0; // state IS AN INTEGER THAT CONTROLS WHEN A MAIN WHILE LOOP IN THE incoming() FUNCTON ENDS int state2 = 0; // HOLDS YOU IN A PROGRAM int timer = 0; // timer IS AN INTEGER THAT HOLDS TIMING DATA IN THE incoming() FUNCTION. IT LETS US KNOW WHEN THE TRANSMITTER HAS STOPPED SENDING PULSES. // /* BELOW IS A DIAGRAM OF THE SEGMENTS AND THE DOT ON THE LOWER RIGHT SIDE. pina CONTROLS THE "A" SEGMENT. WHEN THE pina GPIO PIN IS SET LOW (0V) THE "A" SEGMENT WILL TURN ON A ---- F| |B | G | ---- E| |C | D | ---- O DOT */ void setup() { Serial.begin(9600); pinMode(pina,OUTPUT); // DECLARE ALL PINS AS OUTPUTS pinMode(pinb,OUTPUT); pinMode(pinc,OUTPUT); pinMode(pind,OUTPUT); pinMode(pine,OUTPUT); pinMode(pinf,OUTPUT); pinMode(pinG,OUTPUT); pinMode(pindot,OUTPUT); pinMode(control1,OUTPUT); pinMode(A0,OUTPUT); pinMode(A1,OUTPUT); pinMode(A2,OUTPUT); pinMode(A3,OUTPUT); pinMode(A4,OUTPUT); pinMode(inval,INPUT); pinMode(OUTSIG,OUTPUT); pinMode(PRG,INPUT); pinMode(A5,INPUT); seg4 = 4; // LEFT MOST SEGMENT DATA (10 MINITE DIGIT DATA seg3 = 5; // SECOND FROM THE LEFT SEGMENT DATA SET TO 5 MINUTES seg2 = 0; // 10 SECOND DIGIT DATA seg1 = 0; // 1 SECOND DIGIT DATA //digitalWrite(A3,HIGH); //delay(1000); //digitalWrite(A3,LOW); } void loop(){ if(digitalRead(PRG) == LOW){ digitalmenu(); } else { manualprogramming = 1; // SETTING THIS INTEGER TO 1 WILL ALLOW FOR US TO REUSE MANY DIGITAL FUNCTIONS, ONLY THE PROGRAM WILL LOOK FOR A PUSH BUTTON PRESS, VERSUS A DIGITAL INCOMING SIGNAL. manualmenu(); } } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void digitalmenu(){ pindecide = 1; Serial.println("Digital Menu..."); Serial.println("Please Select Mode (1 = COUNTDOWN MODE // 2 = COUNT UP MODE // 3 = POINT ACCUMULCATION MODE) Awaiting command..."); state = 0; //seg4mode(); while(state == 0){ { digitalWrite(A2,HIGH); // TURNS ON LEFT MOST DIGIT seg4 = 10; seg3 = 11; seg2 = 11; seg1 = 0; incoming(); delay(5); if(val > 0 && val < 4){ modeval = val; seg1 = val; //for(int i = 0;i < 12; i++){ // holdit(); //} state = 1; } } } selectprogram(); } void selectprogram(){ if(val == 1){ countdowntimer(); } else if(val == 2){ numberhold = 5; clocktimer(); } else{ numberhold = 9; pointaccumulator(); } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void manualmenu(){ pindecide = 1; Serial.println("Manual Menu..."); Serial.println("Please Select Mode (1 = COUNTDOWN MODE // 2 = COUNT UP MODE // 3 = POINT ACCUMULCATION MODE) Awaiting command..."); state = 0; //seg4mode(); while(state == 0){ { //digitalWrite(A2,HIGH); // TURNS ON LEFT MOST DIGIT seg4 = 10; seg3 = 11; seg2 = 11; seg1 = 0; selmode(); delay(5); //if(val > 0 && val <4){ modeval = val; seg1 = val; state = 1; } } selectprogram2(); } void selectprogram2(){ if(val == 1){ countdowntimer(); } else if(val == 2){ numberhold = 5; clocktimer(); } else{ numberhold = 9; manualpointaccumulator(); } } void selmode(){ state = 0; digitalWrite(control1,HIGH); while(state == 0){ { holdit(); if(digitalRead(A5) == LOW){ seg1 = 1; decoder(); Serial.println("1"); for(int i = 0; i < 30 ; i++){ holdit(); } if(digitalRead(A5) == HIGH){ val = 1; printit(); state = 1; Serial.println("2"); } else{ seg1 = 2; decoder(); Serial.println("3"); for(int i = 0; i < 30 ; i++){ holdit(); } if(digitalRead(A5) == HIGH){ val = 2; printit(); state = 1; Serial.println("4"); } else{ seg1 = 3; decoder(); Serial.println("5"); for(int i = 0; i < 30 ; i++){ holdit(); } if(digitalRead(A5) == HIGH){ val = 3; printit(); state = 1; Serial.println("6"); } } } } } } } void printit(){ for(int i = 0; i < 3 ; i++){ dispoff(); delay(100); dispon(); } off(); } void dispon(){ for(int i = 0 ; i < 15; i++){ holdit(); } } void dispoff(){ digitalWrite(control1,LOW); digitalWrite(A0,LOW); digitalWrite(A1,LOW); digitalWrite(A2,LOW); } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void printresult(){ if(hold == 1){ Serial.print("COUNTDOWN MODE Selected!"); } else if(hold == 2){ Serial.print("COUNT UP MODE Selected!"); } else{ Serial.print("POINT ACCUMULATION MODE Selected!"); } Serial.println("Please Select TIME OR POINTS"); } void holdit(){ digitalWrite(control1,HIGH); // TURN ON THE RIGHT MOST SEGMENT segnum = 1; // THE VALUE IN signum TELLS THE PROGRAM WHICH SEGMENT TO ACTIVATE IN THE UPCOMING "decoder()" FUNCTION. 1 = RIGHT MOST SEGMENT, AND 4 IS LEFT MOST SEGMENT decoder(); // CALL THE DECODER FUNCTION. LOOK BELOW TO SEE HOW THIS FUNCTION WORKS delay(5); // 5ms DELAY digitalWrite(control1,LOW); // TURN THIS SEGMENT OFF digitalWrite(A0,HIGH); // TURN THE NEXT SEGMENT ON segnum = 2; // THE BELOW CODE IS THE SAME AS ABOVE, ONLY WE'RE CONTROLLING DIFFERENT SEGMENTS decoder(); delay(5); digitalWrite(A0,LOW); digitalWrite(A1,HIGH); segnum = 3; decoder(); delay(5); digitalWrite(A1,LOW); digitalWrite(A2,HIGH); segnum = 4; decoder(); delay(5); digitalWrite(A2,LOW); } // MANUAL MENU /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void manualpointaccumulator(){ state2 = 0; manualtiming(); clearsegments; while(state2 == 0){ { triggerwait(); // WAIT FOR A BUTTON PRESS increment(); // INCREMENT IT } } } void manualtiming(){ // THIS FUNCTION USES THE SW1 BUTTON TO PROGRAM THE POINTS OR SECONDS state = 0; // SET STATE TO 0. WHEN IT IS SET TO ONE, THIS FUNCTION WILL END. seg1 = 0; seg2 = 0; seg3 = 0; seg4 = 0; hold = 0; decoder(); while(state == 0){ digitalWrite(control1,HIGH); segnum = 1; pulsewait(); seg1save = seg1; digitalWrite(control1,LOW); zero(); digitalWrite(A0,HIGH); segnum = 2; pulsewait(); seg2save = seg2; if(modeval == 2 && seg2 > 5){ // IF MODEVAL EQUALS 2 (COUNTUP/CLOCK MODE) AND seg2 IS GREATER THAN 5, THEN SET seg2 TO 5 SO THAT MINUTES CANNOT BE GREATER THAN :59 SECONDS. seg2 = 5; seg2save = 5; seg1 = 9; seg1save = 9; } digitalWrite(A0,LOW); zero(); digitalWrite(A1,HIGH); segnum = 3; pulsewait(); seg3save = seg3; digitalWrite(A1,LOW); zero(); digitalWrite(A2,HIGH); segnum = 4; pulsewait(); seg4save = seg4; digitalWrite(A2,LOW); delay(200); off(); triggerwait(); // WAIT FOR A BUTTON PRESS TO END THE TIME PROGRAMMING FUNCTION if(val != 1){ seg1 = 0; seg2 = 0; seg3 = 0; seg4 = 0; } hold = 0; } } void triggerwait(){ // IN THIS FUNTCTION WE SIMPLY WAIT FOR A PUSH BUTTON PRESS while(digitalRead(A5) == HIGH){ { holdit(); } } for(int i = 0 ; i < 5 ; i++){ holdit(); } while(digitalRead(A5) == LOW){ { holdit(); } } delay(20); } void pulsewait(){ state = 0; hold = 0; while(state == 0){ { while(digitalRead(A5) == HIGH){ { //holdit(); } } delay(250); if(digitalRead(A5) == HIGH){ manualincrement(); //state = 0; delay(100); } else{ state = 1; while(digitalRead(A5) == LOW){ { //holdit(); } } } delay(50); } } } void manualincrement() // THIS FUNCTION ACTS TO INCREMENT THE VALUE IN 'hold" TO RETURN A VALUE FROM 0 THROUGH 9. { if(hold < 9) // IF HOLD IS LESS THAN 9, ADD ONE TO HOLD. OTHERWISE, RESET HOLD TO A VALUE OF 0 { hold = hold + 1; // INCREMENT HOLD BY 1 programsegment(); } else // OTHERWISE, SET HOLD BACK TO 0 { hold = 0; // SEG hold TO 9 programsegment(); } } void programsegment(){ if(segnum == 1){ seg1 = hold; seg1save = hold; } if(segnum == 2){ seg2 = hold; seg2save = hold; } if(segnum == 3){ seg3 = hold; seg3save = hold; } if(segnum == 4){ seg4 = hold; seg4save = hold; } decoder(); } // DIGITAL MEMU /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void pointaccumulator(){ // IN THIS PRIGRAM, YOU CAN ACCUMULATE POINTS BY SENDING A 5V PULSE TO THE inval PIN. THE PULSES MUST BE AT LEAST 100uS ON AND 1MS OFF. state2 = 0; programtimer(); clearsegments(); while(state2 == 0){ { state = 0; while(state == 0){ { waitforpulse(); increment(); } } } } } void waitforpulse(){ while(digitalRead(inval) == LOW){ { holdit(); } } delay(5); while(digitalRead(inval) == HIGH){ {} } delay(5); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void clocktimer(){ state2 = 0; // SET STATE2 TO 0 SO THAT THE FOLLOWING CODE LOOPS UNTIL state2 CHANGES TO 1 pindecide = 0; // SET pinddecide BACK TO 0, SO THAT THE MINUTE/SECOND "DOT" WILL BE ACTIVATED if(manualprogramming == 0){ programtimer(); // PROGRAM THE TIMER } else{ manualtiming(); } clearsegments(); // THIS IS ONLY USED FOR COUNTUP while(state2 == 0){ // LOOP THE FOLLOWING: { clocktime(); // CALL THE clocktime() FUNCTION } } } void clocktime(){ counter = 45; // WE WILL PERFORM THE FOLLOWING 50 TIMES. THIS TEAMS THAT WE'LL BE TURNING ALL FOUR SEGMENTS ON AND OFF ONE AT A TIME. 50 X (5ms x 4 SEGMENTS (20ms) = 1000ms = 1 SECOND). THIS MEANS WE'LL COUNT DOWN THE TIMER ONE SECOND AT A TIME. while(counter > 0){ // PERFORM THE FOLLOWING CODE OVER AND OVER UNTIL THE VALUE IN "counter" EQUALS 50 { digitalWrite(control1,HIGH); // TURN ON THE RIGHT MOST SEGMENT segnum = 1; // THE VALUE IN signum TELLS THE PROGRAM WHICH SEGMENT TO ACTIVATE IN THE UPCOMING "decoder()" FUNCTION. 1 = RIGHT MOST SEGMENT, AND 4 IS LEFT MOST SEGMENT decoder(); // CALL THE DECODER FUNCTION. LOOK BELOW TO SEE HOW THIS FUNCTION WORKS delay(5); // 5ms DELAY digitalWrite(control1,LOW); // TURN THIS SEGMENT OFF digitalWrite(A0,HIGH); // TURN THE NEXT SEGMENT ON segnum = 2; // THE BELOW CODE IS THE SAME AS ABOVE, ONLY WE'RE CONTROLLING DIFFERENT SEGMENTS decoder(); delay(5); digitalWrite(A0,LOW); digitalWrite(A1,HIGH); segnum = 3; decoder(); delay(5); digitalWrite(A1,LOW); digitalWrite(A2,HIGH); segnum = 4; decoder(); delay(5); digitalWrite(A2,LOW); counter = counter - 1; // ONCE ALL FOUR SEGMENTS HAVE BEEN TURNED ON AND OFF 25 TIMES, "counter" WILL EQUAL 0. WHEN THIS HAPPENS, WE'LL CALL THE "decrement()" FUNTION, WHICH DEGREMENTS THE COUNTDOWN TIMER } } increment(); // CALL THE DECREMENT FUNCTION } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void countdowntimer(){ // THIS PROGRAM ALLOWS FOR YOU TO PROGRAM A COUNTDOWN TIMER DIGITALLY state2 = 0; // SET STATE2 TO 0 SO THAT THE FOLLOWING CODE LOOPS UNTIL state2 CHANGES TO 1 pindecide = 0; // SET pinddecide BACK TO 0, SO THAT THE MINUTE/SECOND "DOT" WILL BE ACTIVATED if(manualprogramming == 0){ programtimer(); // PROGRAM THE TIMER } else{ manualtiming(); } while(state2 == 0){ // LOOP THE FOLLOWING: countdown(); // START THE COUNTDOWN TIMER } } void programtimer(){ // DIGITAL PROGRAM THE CLOCK OR COUNTDOWN TIMER TIME clearsegments(); // SET ALL VALUES TO 0 incoming(); // WAIT FOR AN INCOMING VALUE TO BE SENT seg1 = val; // TAKE THE RECEIVED VALUE AND SET THE RIGHT MOST SEGMENT WITH THAT VALUE. THE REST OF THIS FUNCTION IS THE SAME. PROGRAM HE VALUE FOR ALL FOUR SEGMENTS SEPARATELY. seg1save = val; incoming(); seg2 = val; // If modeval = 2, then numberhold should equal 5. If modeval = 3, modeval should equal 9. seg2save = val; incoming(); seg3 = val; seg3save = val; incoming(); seg4 = val; seg4save = val; if(modeval == 2 && seg2 > 5){ // IF MODEVAL EQUALS 2 (COUNTUP/CLOCK MODE) AND seg2 IS GREATER THAN 5, THEN SET seg2 TO 5 SO THAT MINUTES CANNOT BE GREATER THAN :59 SECONDS. seg2 = 5; seg2save = 5; seg1 = 9; seg1save = 9; } incoming(); // SENT ANY NUMBER TO END THIS FUNCTION AND START THE COUNTDOWN TIMER. THERE IS NO NEED TO WORRY ABOUT WHAT VALUE IS SENT. JUST SEND ANY VALUE TO START THE TTIMER. } void clearsegments(){ seg1 = 0; seg2 = 0; seg3 = 0; seg4 = 0; } void countdown() { counter = 45; // WE WILL PERFORM THE FOLLOWING 50 TIMES. THIS TEAMS THAT WE'LL BE TURNING ALL FOUR SEGMENTS ON AND OFF ONE AT A TIME. 50 X (5ms x 4 SEGMENTS (20ms) = 1000ms = 1 SECOND). THIS MEANS WE'LL COUNT DOWN THE TIMER ONE SECOND AT A TIME. while(counter > 0){ // PERFORM THE FOLLOWING CODE OVER AND OVER UNTIL THE VALUE IN "counter" EQUALS 50 { digitalWrite(control1,HIGH); // TURN ON THE RIGHT MOST SEGMENT segnum = 1; // THE VALUE IN signum TELLS THE PROGRAM WHICH SEGMENT TO ACTIVATE IN THE UPCOMING "decoder()" FUNCTION. 1 = RIGHT MOST SEGMENT, AND 4 IS LEFT MOST SEGMENT decoder(); // CALL THE DECODER FUNCTION. LOOK BELOW TO SEE HOW THIS FUNCTION WORKS delay(5); // 5ms DELAY digitalWrite(control1,LOW); // TURN THIS SEGMENT OFF digitalWrite(A0,HIGH); // TURN THE NEXT SEGMENT ON segnum = 2; // THE BELOW CODE IS THE SAME AS ABOVE, ONLY WE'RE CONTROLLING DIFFERENT SEGMENTS decoder(); delay(5); digitalWrite(A0,LOW); digitalWrite(A1,HIGH); segnum = 3; decoder(); delay(5); digitalWrite(A1,LOW); digitalWrite(A2,HIGH); segnum = 4; decoder(); delay(5); digitalWrite(A2,LOW); counter = counter - 1; // ONCE ALL FOUR SEGMENTS HAVE BEEN TURNED ON AND OFF 25 TIMES, "counter" WILL EQUAL 0. WHEN THIS HAPPENS, WE'LL CALL THE "decrement()" FUNTION, WHICH DEGREMENTS THE COUNTDOWN TIMER } } decrement(); // CALL THE DECREMENT FUNCTION } void decoder() // IN THIS FUNCTION, WE'LL DECREMENT THE COUNTDOWN TIMER { if(segnum == 1) // IF segnum EQUALS 1, THEN MAKE CHANGES TO THE LEFT MOST SEGMENT. IF signum IS ANY NUMBER OTHER THAN 1, THEN THE FOLLOWING CODE WILL BE IGNORED. { hold = seg1; // PLACE THE CONTENTS IN THE seg1 INTEGER, AND PLACE IT IN THE hold INTEGER. number(); // CALL THE number FUNCTION. THIS FUNCTION TURNS THE RELATIVE A-G AND DOT SEGMENTS TO TURN ON } else if(segnum == 2) // IF segnum EQUALS 1, THEN MAKE CHANGES TO THE LEFT MOST SEGMENT. THE REST OF THIS FUNCTION IS THE SAME AS ABOVE, ONLY DIFFERENT SEGMENTS ARE CONTROLLED. { hold = seg2; number(); } else if(segnum == 3) { hold = seg3; number(); if(pindecide == 0){ digitalWrite(pindot,LOW); // ADD A DECIMAL POINT TO SEPARATE MINUTES FROM SECONDS. } } else { hold = seg4; number(); } } void number() // ANOTHER DECODING FUNCTION. REMEMBER WHEN WE PLACED THE seg1-4 VALUES INTO THE hold INTEGER? WE'LL USE THAT NUMBER TO CALL THE RIGHT SEGMENT DATA. { if(hold == 0) // IF hold EQUALS 0, THEN CALL THE zero() FUNCTION. THE REST OF THIS FUNCTION SHOULD BE PRETTY CLEAR. IF hold = 5, THEN WE'LL CALL "five()" { zero(); } if(hold == 1) { one(); } if(hold == 2) { two(); } if(hold == 3) { three(); } if(hold == 4) { four(); } if(hold == 5) { five(); } if(hold == 6) { six(); } if(hold == 7) { seven(); } if(hold == 8) { eight(); } if(hold == 9) { nine(); } if(hold == 10) { calld(); } if(hold == 11) { off(); } } void decrement() // ONE LAST DECODING FUNCTION. FIRST WE'LL CALL ANOTHER FUNCTION THAT CHECKS TO SEE IF seg1 THROUGH seg4 DATA ARE ALL ZEROs. IF THEY ARE, THEN "trigger" CHANGES FROM 0 TO 1, AND THE TIMER IS RESTARTED { allzeros(); // CALL THE allzeros(); FUNCTION. IF seg1 THROUGH seg4 DATA ARE ALL ZEROS, RESTART THE TIMER AND SET IT TO 5 MINUTES. YOU CAN PLAY WITH THESE TIMES IF YOU'D LIKE. if(seg1 > 0) // THIS IS A SOMEWHAT COMPLICATED DECODER SEQUENCE. TRY TO FOLLOW ALONG. EXECUTE THE FOLLOWING IF THE seg1 INTEGER HOLDS A VALUE HIGHER THAN 0 { seg1 = seg1 - 1; // SUBTRACT (DECREMENT) A VALUE OF 1 FROM THE seg1 INTEGER. IF THIS HAPPENS, THEN THE CODE RETURNS FROMHERE. THE REST OF THE CODE IS NOT EXECUTED. } else // IF seg1 DID HOLD A VALUE OF 0, THEN WE'LL DECREMENT A VALUE OF 1 FROM seg2 (THE TENS DIGIT), AND WE'LL SET seg1 BACK TO 9 { seg1 = 9; // SEG seg1 TO 9 if(seg2 > 0) // BEFORE WE REMOVE 1 FROM seg2, WE NEED TO SEE IF IT IS ALREADY 0. IF seg2 IS HIGHER THAN 0, THEN SIMPLY SUBTRACT 1 FROM seg2, AND WE'LL BE DONE WITH THIS FUNCTION. IF seg2 IS IN FACT 0, THEN WE HAVE MORE TO DO. { seg2 = seg2 - 1; // SUBTRACT 1 FROM seg2. IF THIS HAPPENS, THEN THE CODE RETURNS FROMHERE. THE REST OF THE CODE IS NOT EXECUTED. } else // IF seg2 WAS IN FACT 0, THEN DO THE FOLLOWING { seg2 = 5; // SET seg2 TO 5. WHY? BECAUSE THE TENS DIGIT IS NEVER HIGHER THAN 5. FOR INSTANCE: 29:59. IF WE'RE COUNTING DOWN IN MINUTES, THEN THIS DIGIT NEEDS TO NEVER BE HIGHER THAN 5. (SEGMENT FROM THE RIGHT = seg2) if(seg3 > 0) // WE NOW NEED TO SEE IF seg3 IS HIGHER THAN 0. IF IT IS, SUBRTACT 1 FROM seg3, AND WE'RE DONE WITH THIS FUNCTION. { seg3 = seg3 - 1; // SUBTRACT 1 FROM seg3. IF THIS HAPPENS, THEN THE CODE RETURNS FROMHERE. THE REST OF THE CODE IS NOT EXECUTED. } else // IF seg3 WAS IN FACT 0, THEN SET seg3 TO 9, AND REMOVE 1 FROM seg4. { seg3 = 9; // SET seg3 TO 9. seg4 = seg4 - 1; // SUBTRACT 1 FROM seg4. WE DON'T NEED TO SEE IF SEG4 IS 0 BECAUSE THAT IS LOOKED AFTER DURING THE allzeros(); FUNCTION ABOVE. IF seg4 WAS JUST SUBTRACTED DOWN TO 0, THEN seg1-4 WILL BE 0000 WHEN THIS FUNCTION IS NEXT CALLED, // AND THE allzeros() FUNCTION WILL SEE THAT. } } } } void increment() // ONE LAST DECODING FUNCTION. FIRST WE'LL CALL ANOTHER FUNCTION THAT CHECKS TO SEE IF seg1 THROUGH seg4 DATA ARE ALL ZEROs. IF THEY ARE, THEN "trigger" CHANGES FROM 0 TO 1, AND THE TIMER IS RESTARTED { if(manualprogramming == 1){ decoder(); holdit(); } //clockdone(); // CALL THE allzeros(); FUNCTION. IF seg1 THROUGH seg4 DATA ARE ALL ZEROS, RESTART THE TIMER AND SET IT TO 5 MINUTES. YOU CAN PLAY WITH THESE TIMES IF YOU'D LIKE. if(seg1 < 9) // THIS IS A SOMEWHAT COMPLICATED DECODER SEQUENCE. TRY TO FOLLOW ALONG. EXECUTE THE FOLLOWING IF THE seg1 INTEGER HOLDS A VALUE HIGHER THAN 0 { seg1 = seg1 + 1; // SUBTRACT (DECREMENT) A VALUE OF 1 FROM THE seg1 INTEGER. IF THIS HAPPENS, THEN THE CODE RETURNS FROMHERE. THE REST OF THE CODE IS NOT EXECUTED. } else // IF seg1 DID HOLD A VALUE OF 0, THEN WE'LL DECREMENT A VALUE OF 1 FROM seg2 (THE TENS DIGIT), AND WE'LL SET seg1 BACK TO 9 { seg1 = 0; // SEG seg1 TO 9 if(seg2 < numberhold) // numberhold is a value that is either 5 or 9. For timer apps, 99:59 is the highest time. For point accumulation, 9999 is the highest time. { seg2 = seg2 + 1; // SUBTRACT 1 FROM seg2. IF THIS HAPPENS, THEN THE CODE RETURNS FROMHERE. THE REST OF THE CODE IS NOT EXECUTED. } else // IF seg2 WAS IN FACT 0, THEN DO THE FOLLOWING { seg2 = 0; // SET seg2 TO 5. WHY? BECAUSE THE TENS DIGIT IS NEVER HIGHER THAN 5. FOR INSTANCE: 29:59. IF WE'RE COUNTING DOWN IN MINUTES, THEN THIS DIGIT NEEDS TO NEVER BE HIGHER THAN 5. (SEGMENT FROM THE RIGHT = seg2) if(seg3 < 9) // WE NOW NEED TO SEE IF seg3 IS HIGHER THAN 0. IF IT IS, SUBRTACT 1 FROM seg3, AND WE'RE DONE WITH THIS FUNCTION. { seg3 = seg3 + 1; // SUBTRACT 1 FROM seg3. IF THIS HAPPENS, THEN THE CODE RETURNS FROMHERE. THE REST OF THE CODE IS NOT EXECUTED. } else // IF seg3 WAS IN FACT 0, THEN SET seg3 TO 9, AND REMOVE 1 FROM seg4. { seg3 = 0; // SET seg3 TO 9. seg4 = seg4 - 1; // SUBTRACT 1 FROM seg4. WE DON'T NEED TO SEE IF SEG4 IS 0 BECAUSE THAT IS LOOKED AFTER DURING THE allzeros(); FUNCTION ABOVE. IF seg4 WAS JUST SUBTRACTED DOWN TO 0, THEN seg1-4 WILL BE 0000 WHEN THIS FUNCTION IS NEXT CALLED, // AND THE allzeros() FUNCTION WILL SEE THAT. } } } clockdone(); // CALL THE allzeros(); FUNCTION. IF seg1 THROUGH seg4 DATA ARE ALL ZEROS, RESTART THE TIMER AND SET IT TO 5 MINUTES. YOU CAN PLAY WITH THESE TIMES IF YOU'D LIKE. } void clockdone(){ state2 = 0; // SET trigger TO 0 if(seg1 == seg1save) // CHECK ALL INTEGERS (seg1 THROUGH seg4). IF THEY ALL REQUAL THE CLOCK VALUES, TURN ON THE BUZZER AND THE RELAY. THIS WILL INDICATE TO THE SOFTWARE THAT TIME HAS RUN OUT. { if(seg2 == seg2save) { if(seg3 == seg3save) { if(seg4 == seg4save) { for(int i = 0 ; i < 20 ; i++){ holdit(); } off(); // TURN THE SEGMENTS OFF IF ALL SEGs = 0 digitalWrite(OUTSIG,HIGH); // SET THE OUTPUT PINE HIGH //digitalWrite(A3,HIGH); // YOU NEED TO ADD THE RELAY HERE. delay(1000); // WAIT ONE SECOND digitalWrite(A3,LOW); // TURN THE BUZZER OFF digitalWrite(A4,HIGH); // TURN THE RELAY ON while(state2 == 0){ { if(manualprogramming == 0){ scroll(); // SCROLL THE DISPLAY IN A COOL WAY WHILE WAITING FOR A SIGNAL ON THE inval LINE TO STOP } else{ scroll2(); } } } state2 = 0; digitalWrite(A4,LOW); // TURN THE RELAY OFF digitalWrite(OUTSIG,LOW); // TURN THE OUTPUT SIGNAL OFF if(manualprogramming == 0){ incoming(); if(val == 5){ // IF THE VALUE RECEIVED WAS 5, SET state2 TO 1, WHICN WILL SEND YOU BACK TO THE MAIN MENU state2 = 1; state = 1; } else{ programtimer(); // PROGRAM THE TIMER clearsegments(); } } else{ hold = 0; longpush(); if(hold == 0){ manualtiming(); // PROGRAM THE TIMER //clearsegments(); } else{ state2 = 1; state = 1; } } } } } } } void longpush(){ // A short press of SW1 will have you reprogram new points. A long press (longer than 0.35 seconds, will send you back to the main menu hold = 0; hold2 = 0; while(hold2 == 0){ { if(digitalRead(A5) == LOW){ delay(350); if(digitalRead(A5) == LOW){ hold2 = 1; hold = 1; } else{ hold2 = 1; } } } } while(digitalRead(A5) == LOW){ {} } delay(50); } void allzeros() // THIS FUNCTION DETERMINES IF TIME HAS RUN OUT { state2 = 0; // SET state2 TO 0 if(seg1 == 0) // CHECK ALL INTEGERS (seg1 THROUGH seg4). IF THEY'RE ALL 0, SET trigger TO 1. THIS WILL INDICATE TO THE SOFTWARE THAT TIME HAS RUN OUT. { if(seg2 == 0) { if(seg3 == 0) { if(seg4 == 0) { for(int i = 0 ; i < 20 ; i++){ holdit(); } off(); // TURN THE SEGMENTS OFF IF ALL SEGs = 0 //digitalWrite(A3,HIGH); // YOU NEED TO ADD THE RELAY HERE. digitalWrite(OUTSIG,HIGH); delay(1000); // WAIT ONE SECOND digitalWrite(A3,LOW); // TURN THE BUZZER OFF digitalWrite(A4,HIGH); // TURN THE RELAY ON while(state2 == 0){ { if(manualprogramming == 0){ scroll(); // SCROLL THE DISPLAY IN A COOL WAY WHILE WAITING FOR A SIGNAL ON THE inval LINE TO STOP } else{ scroll2(); } } } state2 = 0; digitalWrite(A4,LOW); // TURN THE RELAY OFF digitalWrite(OUTSIG,LOW); // TURN THE OUTPUT SIGNAL OFF if(manualprogramming == 0){ incoming(); if(val == 5){ // IF THE VALUE RECEIVED WAS 5, SET state2 TO 1, WHICN WILL SEND YOU BACK TO THE MAIN MENU state2 = 1; state = 1; } else{ programtimer(); // PROGRAM THE TIMER //clearsegments(); } } else{ hold = 0; longpush(); if(hold == 0){ manualtiming(); // PROGRAM THE TIMER //clearsegments(); } else{ state2 = 1; state = 1; //clearsegments(); } } } } } } } void scroll(){ // Digital off(); Serial.println("Scroller1"); while(digitalRead(inval) == LOW){ { scroller(); off(); delay(5); } } // while(digitalRead(inval) == HIGH){ //{} //} state2 = 1; //delay(5); } void scroll2(){ // Manual off(); Serial.println("Scroller2"); while(digitalRead(A5) == HIGH){ { scroller(); off(); delay(5); } } delay(100); Serial.println("halfdone"); while(digitalRead(A5) == LOW){ {} } delay(5); state2 = 1; Serial.println("done"); } void scroller(){ digitalWrite(pina,LOW); movescroll(); digitalWrite(pina,HIGH); digitalWrite(pinb,LOW); movescroll(); digitalWrite(pinb,HIGH); digitalWrite(pinG,LOW); movescroll(); digitalWrite(pinG,HIGH); digitalWrite(pine,LOW); movescroll(); digitalWrite(pine,HIGH); digitalWrite(pind,LOW); movescroll(); digitalWrite(pind,HIGH); digitalWrite(pinc,LOW); movescroll(); digitalWrite(pinc,HIGH); digitalWrite(pinG,LOW); movescroll(); digitalWrite(pinG,HIGH); digitalWrite(pinf,LOW); movescroll(); digitalWrite(pinf,HIGH); } void movescroll(){ digitalWrite(control1,HIGH); delay(10); digitalWrite(control1,LOW); digitalWrite(A0,HIGH); delay(10); digitalWrite(A0,LOW); digitalWrite(A1,HIGH); delay(10); digitalWrite(A1,LOW); digitalWrite(A2,HIGH); delay(10); digitalWrite(A2,LOW); } // THE FOLLOWING FUNCTIONS ACT TO DISPLAY A NUMBER ON A DISPLAY THAT IS TURNED ON. void calld() // SHOWS A "d" { off(); // CALL THE "off()" FUNCTION WHICH YOU CAN FIND BELOW. IT TURNS ALL OF THE SEGMENTS OFF. digitalWrite(pina,HIGH); digitalWrite(pinb,LOW); digitalWrite(pinc,LOW); digitalWrite(pind,LOW); digitalWrite(pine,LOW); digitalWrite(pinf,HIGH); digitalWrite(pinG,LOW); // BY SETTING A SEGMENT PIN LOW, YOU TURN IT ON. BY SETTING IT HIGH, YOU TURN SAID SEGMENT OFF. digitalWrite(pindot,HIGH); // dot IS THE DECIMAL SEGMENT } void zero() { off(); // CALL THE "off()" FUNCTION WHICH YOU CAN FIND BELOW. IT TURNS ALL OF THE SEGMENTS OFF. digitalWrite(pina,LOW); digitalWrite(pinb,LOW); digitalWrite(pinc,LOW); digitalWrite(pind,LOW); digitalWrite(pine,LOW); digitalWrite(pinf,LOW); digitalWrite(pinG,HIGH); // BY SETTING A SEGMENT PIN LOW, YOU TURN IT ON. BY SETTING IT HIGH, YOU TURN SAID SEGMENT OFF. digitalWrite(pindot,HIGH); // dot IS THE DECIMAL SEGMENT } void one() { off(); digitalWrite(pina,HIGH); digitalWrite(pinb,LOW); digitalWrite(pinc,LOW); digitalWrite(pind,HIGH); digitalWrite(pine,HIGH); digitalWrite(pinf,HIGH); digitalWrite(pinG,HIGH); digitalWrite(pindot,HIGH); } void two() { off(); digitalWrite(pina,LOW); digitalWrite(pinb,LOW); digitalWrite(pinc,HIGH); digitalWrite(pind,LOW); digitalWrite(pine,LOW); digitalWrite(pinf,HIGH); digitalWrite(pinG,LOW); digitalWrite(pindot,HIGH); } void three() { off(); digitalWrite(pina,LOW); digitalWrite(pinb,LOW); digitalWrite(pinc,LOW); digitalWrite(pind,LOW); digitalWrite(pine,HIGH); digitalWrite(pinf,HIGH); digitalWrite(pinG,LOW); digitalWrite(pindot,HIGH); } void four() { off(); digitalWrite(pina,HIGH); digitalWrite(pinb,LOW); digitalWrite(pinc,LOW); digitalWrite(pind,HIGH); digitalWrite(pine,HIGH); digitalWrite(pinf,LOW); digitalWrite(pinG,LOW); digitalWrite(pindot,HIGH); } void five() { off(); digitalWrite(pina,LOW); digitalWrite(pinb,HIGH); digitalWrite(pinc,LOW); digitalWrite(pind,LOW); digitalWrite(pine,HIGH); digitalWrite(pinf,LOW); digitalWrite(pinG,LOW); digitalWrite(pindot,HIGH); } void six() { off(); digitalWrite(pina,LOW); digitalWrite(pinb,HIGH); digitalWrite(pinc,LOW); digitalWrite(pind,LOW); digitalWrite(pine,LOW); digitalWrite(pinf,LOW); digitalWrite(pinG,LOW); digitalWrite(pindot,HIGH); } void seven() { off(); digitalWrite(pina,LOW); digitalWrite(pinb,LOW); digitalWrite(pinc,LOW); digitalWrite(pind,HIGH); digitalWrite(pine,HIGH); digitalWrite(pinf,HIGH); digitalWrite(pinG,HIGH); digitalWrite(pindot,HIGH); } void eight () { off(); digitalWrite(pina,LOW); digitalWrite(pinb,LOW); digitalWrite(pinc,LOW); digitalWrite(pind,LOW); digitalWrite(pine,LOW); digitalWrite(pinf,LOW); digitalWrite(pinG,LOW); digitalWrite(pindot,HIGH); } void nine() { off(); digitalWrite(pina,LOW); digitalWrite(pinb,LOW); digitalWrite(pinc,LOW); digitalWrite(pind,HIGH); digitalWrite(pine,HIGH); digitalWrite(pinf,LOW); digitalWrite(pinG,LOW); digitalWrite(pindot,HIGH); } void off() // BY SETTING ALL PINS TO HIGH, ALL SEGMENTS ARE TURNED OFF { digitalWrite(pina,HIGH); digitalWrite(pinb,HIGH); digitalWrite(pinc,HIGH); digitalWrite(pind,HIGH); digitalWrite(pine,HIGH); digitalWrite(pinf,HIGH); digitalWrite(pinG,HIGH); digitalWrite(pindot,HIGH); } void on() // THIS FUNCTION TURNS ALL OF THE SEGMENTS ON. WE DON'T USE THIS FUNCTION IN THE ABOVE CODE. IT IS HERE IN CASE WE WANT IT. { off(); digitalWrite(pina,LOW); digitalWrite(pinb,LOW); digitalWrite(pinc,LOW); digitalWrite(pind,LOW); digitalWrite(pine,LOW); digitalWrite(pinf,LOW); digitalWrite(pinG,LOW); digitalWrite(pindot,LOW); } void incoming() // THIS FUNCTION ACTS TO WAIT FOR AN INSTRUCTION, AND WAIT FOR A SET OF PULSES, WHICH WILL EQUAL THE INSTRUCTION NUMBER. { val = 0; // Set int 'val' to 0. state = 0; // Set int 'state' state to 0 while(digitalRead(inval) == LOW){ // Wait until data on A1 line goes from 0v to 5v. Once there, this while loop will end. { holdit(); } } while(state == 0){ // This new while loop will execute until 'state' not equal 0. ESSENTIALLY THE REST OF THIS FUNCTION IS IN THIS WHILE LOOP. { while(digitalRead(inval) == HIGH){ // This new while loop will wait until the 'inval' input line goes back to 0v from 1v. {} } val = val + 1; // Add 1 to the 'val' integer timer = 0; // 'timer' integer set to 0; while(digitalRead(inval) == LOW){ // This while loop is a timer. It waits for the 'inval' input line to go from 0v to 5v again. It counts pulses from the transmitter. { delay(1); // Wait 1ms timer = timer + 1; // Add 1 to 'timer' integer if(timer > 7) // If 'timer' value is higher than 7 (7 ms has elapsed), then to do the following { Serial.print("val#"); // Then write "val#" to the serial monitor Serial.println(val); // Write 'val', which is the instruction value if(val == 11){ // If a value of 11 was received, then this value should be interpretted as a 0. val = 0; } delay(5); state = 1; // state is changed to 1, which means that this function will end break; // EXIT } } } } } }