├── SevSeg-Lib ├── keywords.txt ├── library.properties ├── examples │ ├── SevSeg_Counter │ │ └── SevSeg_Counter.ino │ └── testWholeDisplay │ │ └── testWholeDisplay.ino ├── SevSeg.h ├── README.md ├── LICENSE.txt └── SevSeg.cpp ├── README.md ├── Traffic-Ligh.ino └── Traffic-Ligh-Other-Code.ino /SevSeg-Lib/keywords.txt: -------------------------------------------------------------------------------- 1 | SevSeg KEYWORD1 2 | setNumber KEYWORD2 3 | refreshDisplay KEYWORD2 4 | setBrightness KEYWORD2 5 | setSegments KEYWORD2 6 | setChars KEYWORD2 7 | blank KEYWORD2 8 | COMMON_CATHODE LITERAL1 9 | COMMON_ANODE LITERAL1 10 | N_TRANSISTORS LITERAL1 11 | P_TRANSISTORS LITERAL1 12 | NP_COMMON_CATHODE LITERAL1 13 | NP_COMMON_ANODE LITERAL1 -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Arduino-Traffic-Ligh 2 | 3 | Membuat Traffic ligh otomatis, dimana ketika keadaan sedang berada pada lampu hijau, dan pada bagian yang sedang menyala lampu hijaunya terdapat antrian yang cukup panjang, maka akan terjadi perpanjangan menyalanya lampu hijau 4 | 5 | Project ini dibuat menggunakan : 6 | 1. arduino Mega 7 | 2. 3 buah seven segment 2 digit 8 | 3. 9 buah Led (Merah 3, Kuning 3, Hijau 3) 9 | 4. 3 buah sensor HCSR 05 (ultra sonic) 10 | -------------------------------------------------------------------------------- /SevSeg-Lib/library.properties: -------------------------------------------------------------------------------- 1 | name=SevSeg 2 | version=3.3.0 3 | author=Dean Reading 4 | maintainer=Dean Reading 5 | sentence=Turns your Arduino into a seven segment display controller! 6 | paragraph=Use it to easily display numbers on your seven segment display without any additional hardware. Supports common cathode and common anode displays, the use of switching transistors, decimal numbers, hexadecimal numbers, and alphanumeric characters. 7 | category=Display 8 | url=https://github.com/DeanIsMe/SevSeg 9 | architectures=* 10 | includes=SevSeg.h 11 | -------------------------------------------------------------------------------- /SevSeg-Lib/examples/SevSeg_Counter/SevSeg_Counter.ino: -------------------------------------------------------------------------------- 1 | /* SevSeg Counter Example 2 | 3 | Copyright 2017 Dean Reading 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | 17 | This example demonstrates a very simple use of the SevSeg library with a 4 18 | digit display. It displays a counter that counts up, showing deci-seconds. 19 | */ 20 | 21 | #include "SevSeg.h" 22 | SevSeg sevseg; //Instantiate a seven segment controller object 23 | 24 | void setup() { 25 | byte numDigits = 4; 26 | byte digitPins[] = {2, 3, 4, 5}; 27 | byte segmentPins[] = {6, 7, 8, 9, 10, 11, 12, 13}; 28 | bool resistorsOnSegments = false; // 'false' means resistors are on digit pins 29 | byte hardwareConfig = COMMON_ANODE; // See README.md for options 30 | bool updateWithDelays = false; // Default. Recommended 31 | bool leadingZeros = false; // Use 'true' if you'd like to keep the leading zeros 32 | 33 | sevseg.begin(hardwareConfig, numDigits, digitPins, segmentPins, resistorsOnSegments, updateWithDelays, leadingZeros); 34 | sevseg.setBrightness(90); 35 | } 36 | 37 | void loop() { 38 | static unsigned long timer = millis(); 39 | static int deciSeconds = 0; 40 | 41 | if (millis() - timer >= 100) { 42 | timer += 100; 43 | deciSeconds++; // 100 milliSeconds is equal to 1 deciSecond 44 | 45 | if (deciSeconds == 10000) { // Reset to 0 after counting for 1000 seconds. 46 | deciSeconds=0; 47 | } 48 | sevseg.setNumber(deciSeconds, 1); 49 | } 50 | 51 | sevseg.refreshDisplay(); // Must run repeatedly 52 | } 53 | 54 | /// END /// 55 | -------------------------------------------------------------------------------- /SevSeg-Lib/SevSeg.h: -------------------------------------------------------------------------------- 1 | /* SevSeg Library 2 | 3 | Copyright 2017 Dean Reading 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | 17 | This library allows an Arduino to easily display numbers in decimal format on 18 | a 7-segment display without a separate 7-segment display controller. 19 | 20 | Direct any questions or suggestions to deanreading@hotmail.com 21 | See the included readme for instructions. 22 | */ 23 | 24 | #ifndef MAXNUMDIGITS 25 | #define MAXNUMDIGITS 8 // Can be increased, but the max number is 2^31 26 | #endif 27 | 28 | #ifndef SevSeg_h 29 | #define SevSeg_h 30 | 31 | #if defined(ARDUINO) && ARDUINO >= 100 32 | #include "Arduino.h" 33 | #else 34 | #include "WProgram.h" 35 | #endif 36 | 37 | // Use defines to link the hardware configurations to the correct numbers 38 | #define COMMON_CATHODE 0 39 | #define COMMON_ANODE 1 40 | #define N_TRANSISTORS 2 41 | #define P_TRANSISTORS 3 42 | #define NP_COMMON_CATHODE 1 43 | #define NP_COMMON_ANODE 0 44 | 45 | 46 | class SevSeg 47 | { 48 | public: 49 | SevSeg(); 50 | 51 | void refreshDisplay(); 52 | void begin(byte hardwareConfig, byte numDigitsIn, byte digitPinsIn[], 53 | byte segmentPinsIn[], bool resOnSegmentsIn=0, 54 | bool updateWithDelaysIn=0, bool leadingZerosIn=0); 55 | void setBrightness(int brightnessIn); // A number from 0..100 56 | 57 | void setNumber(long numToShow, char decPlaces=-1, bool hex=0); 58 | void setNumber(unsigned long numToShow, char decPlaces=-1, bool hex=0); 59 | void setNumber(int numToShow, char decPlaces=-1, bool hex=0); 60 | void setNumber(unsigned int numToShow, char decPlaces=-1, bool hex=0); 61 | void setNumber(char numToShow, char decPlaces=-1, bool hex=0); 62 | void setNumber(byte numToShow, char decPlaces=-1, bool hex=0); 63 | void setNumber(float numToShow, char decPlaces=-1, bool hex=0); 64 | 65 | void setSegments(byte segs[]); 66 | void setChars(char str[]); 67 | void blank(void); 68 | 69 | private: 70 | void setNewNum(long numToShow, char decPlaces, bool hex=0); 71 | void findDigits(long numToShow, char decPlaces, bool hex, byte digits[]); 72 | void setDigitCodes(byte nums[], char decPlaces); 73 | 74 | bool digitOn,digitOff,segmentOn,segmentOff; 75 | bool resOnSegments, updateWithDelays, leadingZeros; 76 | byte digitPins[MAXNUMDIGITS]; 77 | byte segmentPins[8]; 78 | byte numDigits; 79 | byte prevUpdateIdx; 80 | byte digitCodes[MAXNUMDIGITS]; 81 | int ledOnTime; 82 | unsigned long prevUpdateTime; 83 | }; 84 | 85 | #endif //SevSeg_h 86 | /// END /// 87 | -------------------------------------------------------------------------------- /SevSeg-Lib/examples/testWholeDisplay/testWholeDisplay.ino: -------------------------------------------------------------------------------- 1 | /* 2 | testWholeDisplay.ino 3 | -test each segment in the display 4 | -a simple example using Dean Reading's SevSeg library to light up all 4 digits plus the 4 decimal points on a 4 digit display 5 | -the purpose of this example is to ensure you have the wires all hooked up right for every segment and digit, and to troubleshoot the display and wiring 6 | to ensure *every* segment and period lights up 7 | 8 | By Gabriel Staples 9 | Website: http://www.ElectricRCAircraftGuy.com 10 | My contact info is available by clicking the "Contact Me" tab at the top of my website. 11 | Written: 1 Oct. 2015 12 | Last Updated: 1 Oct. 2015 13 | */ 14 | 15 | /* 16 | LICENSING: 17 | -this *example file* only is modified from Dean Reading's original example, and is in the public domain. 18 | 19 | Dean Reading's SevSeg library is as follows: 20 | Copyright 2014 Dean Reading 21 | 22 | Licensed under the Apache License, Version 2.0 (the "License"); 23 | you may not use this file except in compliance with the License. 24 | You may obtain a copy of the License at 25 | http://www.apache.org/licenses/LICENSE-2.0 26 | 27 | Unless required by applicable law or agreed to in writing, software 28 | distributed under the License is distributed on an "AS IS" BASIS, 29 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 30 | See the License for the specific language governing permissions and 31 | limitations under the License. 32 | */ 33 | 34 | #include 35 | 36 | SevSeg sevseg; //Instantiate a seven segment controller object 37 | 38 | void setup() 39 | { 40 | byte numDigits = 4; 41 | byte digitPins[] = {2, 3, 4, 5}; //Digits: 1,2,3,4 <--put one resistor (ex: 220 Ohms, or 330 Ohms, etc, on each digit pin) 42 | byte segmentPins[] = {6, 7, 8, 9, 10, 11, 12, 13}; //Segments: A,B,C,D,E,F,G,Period 43 | 44 | sevseg.begin(COMMON_ANODE, numDigits, digitPins, segmentPins); 45 | sevseg.setBrightness(10); //Note: 100 brightness simply corresponds to a delay of 2000us after lighting each segment. A brightness of 0 46 | //is a delay of 1us; it doesn't really affect brightness as much as it affects update rate (frequency). 47 | //Therefore, for a 4-digit 7-segment + pd, COMMON_ANODE display, the max update rate for a "brightness" of 100 is 1/(2000us*8) = 62.5Hz. 48 | //I am choosing a "brightness" of 10 because it increases the max update rate to approx. 1/(200us*8) = 625Hz. 49 | //This is preferable, as it decreases aliasing when recording the display with a video camera....I think. 50 | } 51 | 52 | void loop() 53 | { 54 | //local vars 55 | static byte decPlace = 0; 56 | 57 | sevseg.setNumber(8888,decPlace); 58 | decPlace++; 59 | decPlace %= 4; //rollover back to 0 once variable gets to 4; To anyone wondering: the % is called the "modulo" operator; see here for explanation & example: https://www.arduino.cc/en/Reference/Modulo 60 | 61 | sevseg.refreshDisplay(); // Must run repeatedly; don't use blocking code (ex: delay()) in the loop() function or this won't work right 62 | } 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /Traffic-Ligh.ino: -------------------------------------------------------------------------------- 1 | 2 | #include "SevSeg.h" 3 | #define ECHOPIN 2 4 | #define TRIGPIN 3 5 | #define ECHOPIND 4 6 | #define TRIGPIND 5 7 | #define ECHOPINT 6 8 | #define TRIGPINT 7 9 | 10 | SevSeg sevseg,sevseg1,sevseg2; 11 | byte numDigits = 2; 12 | byte digitPins[] = {8,9}; 13 | byte digitPins1[] = {10,11}; 14 | byte digitPins2[] = {12,13}; 15 | byte segmentPins[] = {22,23,24,25,26,27,28,29}; 16 | byte segmentPins1[] = {30,31,32,33,34,35,36,37}; 17 | byte segmentPins2[] = {38,39,40,41,42,43,44,45}; 18 | bool resistorsOnSegments = false; 19 | byte hardwareConfig = COMMON_ANODE; 20 | bool updateWithDelays = false; 21 | bool leadingZeros = true; 22 | int waktuS,waktuD,waktuT; 23 | int senS,senD,senT; 24 | bool Status1 = false,Status2 = false,Status3 = false; 25 | 26 | 27 | void setup() { 28 | pinMode(ECHOPIN, INPUT); 29 | pinMode(TRIGPIN, OUTPUT); 30 | pinMode(ECHOPIND, INPUT); 31 | pinMode(TRIGPIND, OUTPUT); 32 | pinMode(ECHOPINT, INPUT); 33 | pinMode(TRIGPINT, OUTPUT); 34 | for(int i = 46; i<= 53; i++){ 35 | pinMode(i, OUTPUT); 36 | } 37 | pinMode(A15, OUTPUT); 38 | 39 | sevseg.begin(hardwareConfig, numDigits, digitPins, segmentPins,resistorsOnSegments, updateWithDelays, leadingZeros); 40 | sevseg1.begin(hardwareConfig, numDigits, digitPins1, segmentPins1,resistorsOnSegments, updateWithDelays, leadingZeros); 41 | sevseg2.begin(hardwareConfig, numDigits, digitPins2, segmentPins2,resistorsOnSegments, updateWithDelays, leadingZeros); 42 | Serial.begin(9600); 43 | } 44 | int sensor1(){ 45 | digitalWrite(TRIGPIN, LOW); 46 | digitalWrite(TRIGPIN, HIGH); 47 | digitalWrite(TRIGPIN, LOW); 48 | int distance = pulseIn(ECHOPIN, HIGH); 49 | distance= distance/58; 50 | if(distance <= 5){ 51 | return true; 52 | } 53 | else{ 54 | return false; 55 | } 56 | } 57 | int sensor2(){ 58 | digitalWrite(TRIGPIND, LOW); 59 | digitalWrite(TRIGPIND, HIGH); 60 | digitalWrite(TRIGPIND, LOW); 61 | int distance = pulseIn(ECHOPIND, HIGH); 62 | distance= distance/58; 63 | if(distance <= 5){ 64 | return true; 65 | } 66 | else{ 67 | return false; 68 | } 69 | } 70 | int sensor3(){ 71 | digitalWrite(TRIGPINT, LOW); 72 | digitalWrite(TRIGPINT, HIGH); 73 | digitalWrite(TRIGPINT, LOW); 74 | int distance = pulseIn(ECHOPINT, HIGH); 75 | distance= distance/58; 76 | if(distance <= 5){ 77 | return true; 78 | } 79 | else{ 80 | return false; 81 | } 82 | } 83 | void loop() { 84 | static unsigned long timer = millis(); 85 | if (millis() - timer >= 1000) { 86 | if(sensor1()){ 87 | senS++; 88 | 89 | if(senS >= 5){ // 5 detik 90 | senS = 0; 91 | } 92 | } 93 | else{ 94 | senS = 0; 95 | } 96 | if(sensor2()){ 97 | senD++; 98 | if(senD >= 5){ // 5 detik 99 | senD = 0; 100 | } 101 | } 102 | else{ 103 | senD = 0; 104 | } 105 | if(sensor3()){ 106 | senT++; 107 | if(senT >= 5){ // 5 detik 108 | senT = 0; 109 | } 110 | } 111 | else{ 112 | senT = 0; 113 | } 114 | normal(); 115 | 116 | timer += 1000; 117 | waktuS--; 118 | waktuD--; 119 | waktuT--; 120 | } 121 | sevseg.refreshDisplay(); 122 | sevseg1.refreshDisplay(); 123 | sevseg2.refreshDisplay(); 124 | LampNormal(); 125 | } 126 | void LampNormal(){ 127 | if(waktuS != 0){ 128 | if(waktuS >= 5){ 129 | digitalWrite(46,HIGH); 130 | digitalWrite(47,LOW); 131 | digitalWrite(48,LOW); 132 | } 133 | else if(waktuS ==4 || waktuS ==3 || waktuS ==2 || waktuS == 1){ 134 | digitalWrite(46,LOW); 135 | digitalWrite(47,HIGH); 136 | digitalWrite(48,LOW); 137 | } 138 | else{ 139 | if(waktuD ==4 || waktuD ==3 || waktuD ==2 || waktuD == 1|| waktuD == 0){ 140 | digitalWrite(46,HIGH); 141 | digitalWrite(47,LOW); 142 | digitalWrite(48,LOW); 143 | } 144 | else{ 145 | digitalWrite(46,LOW); 146 | digitalWrite(47,LOW); 147 | digitalWrite(48,HIGH); 148 | if(!Status1){ // kalau false 149 | Serial.print(senS); 150 | if(senS >=4){ 151 | waktuD =waktuD + 5; 152 | waktuT =waktuT + 5; 153 | Status1 = true; 154 | Status2 = false; 155 | Status3 = false; 156 | } 157 | } 158 | } 159 | } 160 | } 161 | if(waktuD != 0){ 162 | if(waktuD >= 5){ 163 | digitalWrite(49,HIGH); 164 | digitalWrite(50,LOW); 165 | digitalWrite(51,LOW); 166 | } 167 | else if(waktuD ==4 || waktuD ==3 || waktuD ==2 || waktuD == 1){ 168 | digitalWrite(49,LOW); 169 | digitalWrite(50,HIGH); 170 | digitalWrite(51,LOW); 171 | } 172 | else{ 173 | if(waktuT ==4 || waktuT ==3 || waktuT ==2 || waktuT == 1 || waktuT == 0){ 174 | digitalWrite(49,HIGH); 175 | digitalWrite(50,LOW); 176 | digitalWrite(51,LOW); 177 | } 178 | else{ 179 | digitalWrite(49,LOW); 180 | digitalWrite(50,LOW); 181 | digitalWrite(51,HIGH); 182 | if(!Status2){ // kalau false 183 | Serial.print(senD); 184 | if(senD >=4){ 185 | waktuS =waktuS + 5; 186 | waktuT =waktuT + 5; 187 | Status2 = true; 188 | Status1 = false; 189 | Status3 = false; 190 | } 191 | } 192 | } 193 | } 194 | } 195 | if(waktuT != 0){ 196 | if(waktuT >= 5){ 197 | digitalWrite(52,HIGH); 198 | digitalWrite(53,LOW); 199 | digitalWrite(A15,LOW); 200 | } 201 | else if(waktuT ==4 || waktuT ==3 || waktuT ==2 || waktuT == 1){ 202 | digitalWrite(52,LOW); 203 | digitalWrite(53,HIGH); 204 | digitalWrite(A15,LOW); 205 | } 206 | else{ 207 | if(waktuS ==4 || waktuS ==3 || waktuS ==2 || waktuS == 1|| waktuS == 0 ){ 208 | digitalWrite(52,HIGH); 209 | digitalWrite(53,LOW); 210 | digitalWrite(A15,LOW); 211 | } 212 | else{ 213 | digitalWrite(52,LOW); 214 | digitalWrite(53,LOW); 215 | digitalWrite(A15,HIGH); 216 | if(!Status3){ // kalau false 217 | Serial.print(senT); 218 | if(senT >=4){ 219 | waktuD =waktuD + 5; 220 | waktuS =waktuS + 5; 221 | Status3 = true; 222 | Status2 = false; 223 | Status1 = false; 224 | } 225 | } 226 | } 227 | } 228 | } 229 | } 230 | void normal(){ 231 | if(waktuS == 0){ 232 | waktuD = 15; 233 | waktuT = 30; 234 | }else if(waktuD == 0){ 235 | waktuT = 15; 236 | waktuS = 30; 237 | }else if(waktuT == 0){ 238 | waktuS = 15; 239 | waktuD = 30; 240 | } 241 | if(waktuS != 0){ 242 | if(waktuS > 0){ 243 | sevseg.setNumber(waktuS); 244 | } 245 | else{ 246 | sevseg.setNumber(00); 247 | } 248 | } 249 | if(waktuD != 0){ 250 | if(waktuD > 0){ 251 | sevseg1.setNumber(waktuD); 252 | } 253 | else{ 254 | sevseg1.setNumber(00); 255 | } 256 | } 257 | if(waktuT != 0){ 258 | if(waktuT > 0){ 259 | sevseg2.setNumber(waktuT); 260 | } 261 | else{ 262 | sevseg2.setNumber(00); 263 | } 264 | } 265 | } 266 | -------------------------------------------------------------------------------- /Traffic-Ligh-Other-Code.ino: -------------------------------------------------------------------------------- 1 | #include "SevSeg.h" 2 | #define ECHOPIN 2 3 | #define TRIGPIN 3 4 | #define ECHOPIND 4 5 | #define TRIGPIND 5 6 | #define ECHOPINT 6 7 | #define TRIGPINT 7 8 | 9 | SevSeg sevseg,sevseg1,sevseg2; 10 | byte numDigits = 2; 11 | byte digitPins[] = {8,9}; 12 | byte digitPins1[] = {10,11}; 13 | byte digitPins2[] = {12,13}; 14 | byte segmentPins[] = {22,23,24,25,26,27,28,29}; 15 | byte segmentPins1[] = {30,31,32,33,34,35,36,37}; 16 | byte segmentPins2[] = {38,39,40,41,42,43,44,45}; 17 | bool resistorsOnSegments = false; 18 | byte hardwareConfig = COMMON_ANODE; 19 | bool updateWithDelays = false; 20 | bool leadingZeros = true; 21 | int waktuS,waktuD,waktuT; 22 | int senS,senD,senT; 23 | bool Status1 = false,Status2 = false,Status3 = false; 24 | 25 | 26 | void setup() { 27 | pinMode(ECHOPIN, INPUT); 28 | pinMode(TRIGPIN, OUTPUT); 29 | pinMode(ECHOPIND, INPUT); 30 | pinMode(TRIGPIND, OUTPUT); 31 | pinMode(ECHOPINT, INPUT); 32 | pinMode(TRIGPINT, OUTPUT); 33 | for(int i = 46; i<= 53; i++){ 34 | pinMode(i, OUTPUT); 35 | } 36 | pinMode(A15, OUTPUT); 37 | 38 | sevseg.begin(hardwareConfig, numDigits, digitPins, segmentPins,resistorsOnSegments, updateWithDelays, leadingZeros); 39 | sevseg1.begin(hardwareConfig, numDigits, digitPins1, segmentPins1,resistorsOnSegments, updateWithDelays, leadingZeros); 40 | sevseg2.begin(hardwareConfig, numDigits, digitPins2, segmentPins2,resistorsOnSegments, updateWithDelays, leadingZeros); 41 | Serial.begin(9600); 42 | } 43 | int sensor1(){ 44 | digitalWrite(TRIGPIN, LOW); 45 | digitalWrite(TRIGPIN, HIGH); 46 | digitalWrite(TRIGPIN, LOW); 47 | int distance = pulseIn(ECHOPIN, HIGH); 48 | distance= distance/58; 49 | if(distance <= 5){ 50 | return true; 51 | } 52 | else{ 53 | return false; 54 | } 55 | } 56 | int sensor2(){ 57 | digitalWrite(TRIGPIND, LOW); 58 | digitalWrite(TRIGPIND, HIGH); 59 | digitalWrite(TRIGPIND, LOW); 60 | int distance = pulseIn(ECHOPIND, HIGH); 61 | distance= distance/58; 62 | if(distance <= 5){ 63 | return true; 64 | } 65 | else{ 66 | return false; 67 | } 68 | } 69 | int sensor3(){ 70 | digitalWrite(TRIGPINT, LOW); 71 | digitalWrite(TRIGPINT, HIGH); 72 | digitalWrite(TRIGPINT, LOW); 73 | int distance = pulseIn(ECHOPINT, HIGH); 74 | distance= distance/58; 75 | if(distance <= 5){ 76 | return true; 77 | } 78 | else{ 79 | return false; 80 | } 81 | } 82 | void loop() { 83 | static unsigned long timer = millis(); 84 | if (millis() - timer >= 1000) { 85 | if(sensor1()){ 86 | senS++; 87 | 88 | if(senS >= 4){ // 5 detik 89 | senS = 0; 90 | } 91 | } 92 | else{ 93 | senS = 0; 94 | } 95 | if(sensor2()){ 96 | senD++; 97 | if(senD >= 4){ // 5 detik 98 | senD = 0; 99 | } 100 | } 101 | else{ 102 | senD = 0; 103 | } 104 | if(sensor3()){ 105 | senT++; 106 | if(senT >= 4){ // 5 detik 107 | senT = 0; 108 | } 109 | } 110 | else{ 111 | senT = 0; 112 | } 113 | 114 | normal(); 115 | 116 | timer += 1000; 117 | waktuS--; 118 | waktuD--; 119 | waktuT--; 120 | } 121 | sevseg.refreshDisplay(); 122 | sevseg1.refreshDisplay(); 123 | sevseg2.refreshDisplay(); 124 | LampNormal(); 125 | } 126 | 127 | 128 | void LampNormal(){ 129 | if(waktuS != 0){ 130 | if(waktuS >= 5){ 131 | Lampu(1,1); 132 | } 133 | else if(waktuS ==4 || waktuS ==3 || waktuS ==2 || waktuS == 1){ 134 | Lampu(1,2); 135 | } 136 | else if(waktuD ==4 || waktuD ==3 ){ 137 | Lampu(1,2); 138 | } 139 | else if(waktuD ==2 || waktuD ==1 || waktuD ==0 ){ 140 | Lampu(1,1); 141 | } 142 | else{ 143 | Lampu(1,3); 144 | if(!Status1){ 145 | if(senS >=3){ 146 | waktuD =waktuD + 5; 147 | waktuT =waktuT + 5; 148 | Status1 = true; 149 | Status2 = false; 150 | Status3 = false; 151 | } 152 | } 153 | } 154 | } 155 | if(waktuD != 0){ 156 | if(waktuD >= 5){ 157 | Lampu(2,1); 158 | } 159 | else if(waktuD ==4 || waktuD ==3 || waktuD ==2 || waktuD == 1){ 160 | Lampu(2,2); 161 | } 162 | else if(waktuT ==4 || waktuT ==3 ){ 163 | Lampu(2,2); 164 | } 165 | else if(waktuT == 2 || waktuT == 1 || waktuT == 0 ){ 166 | Lampu(2,1); 167 | } 168 | else{ 169 | Lampu(2,3); 170 | if(!Status2){ 171 | if(senD >=3){ 172 | waktuS =waktuS + 5; 173 | waktuT =waktuT + 5; 174 | Status2 = true; 175 | Status1 = false; 176 | Status3 = false; 177 | } 178 | } 179 | } 180 | } 181 | if(waktuT != 0){ 182 | if(waktuT >= 5){ 183 | Lampu(3,1);// 184 | } 185 | else if(waktuT ==4 || waktuT ==3 || waktuT ==2 || waktuT == 1){ 186 | Lampu(3,2); 187 | } 188 | else if(waktuS ==4 || waktuS ==3){ 189 | Lampu(3,2); 190 | } 191 | else if(waktuS == 2 ||waktuS == 1 || waktuS == 0){ 192 | Lampu(3,1); 193 | } 194 | else{ 195 | Lampu(3,3); 196 | if(!Status3){ // kalau false 197 | if(senT >=3){ // ketika sensor terhalang 4 detik 198 | waktuD =waktuD + 5; // penambahan waktu 5 detik 199 | waktuS =waktuS + 5; 200 | Status3 = true; 201 | Status2 = false; 202 | Status1 = false; 203 | } 204 | } 205 | } 206 | } 207 | } 208 | void Lampu (int simpang, int warna){ 209 | // warna 1: merah, 2:kuning, 3 : hijau 210 | if(simpang == 1 && warna == 1){ 211 | digitalWrite(46,HIGH); 212 | digitalWrite(47,LOW); 213 | digitalWrite(48,LOW); 214 | } 215 | else if(simpang == 1 && warna == 2){ 216 | digitalWrite(46,LOW); 217 | digitalWrite(47,HIGH); 218 | digitalWrite(48,LOW); 219 | } 220 | else if(simpang == 1 && warna == 3){ 221 | digitalWrite(46,LOW); 222 | digitalWrite(47,LOW); 223 | digitalWrite(48,HIGH); 224 | } 225 | else if(simpang == 2 && warna == 1){ 226 | digitalWrite(49,HIGH); 227 | digitalWrite(50,LOW); 228 | digitalWrite(51,LOW); 229 | } 230 | else if(simpang == 2 && warna == 2){ 231 | digitalWrite(49,LOW); 232 | digitalWrite(50,HIGH); 233 | digitalWrite(51,LOW); 234 | } 235 | else if(simpang == 2 && warna == 3){ 236 | digitalWrite(49,LOW); 237 | digitalWrite(50,LOW); 238 | digitalWrite(51,HIGH); 239 | } 240 | else if(simpang == 3 && warna == 1){ 241 | digitalWrite(52,HIGH); 242 | digitalWrite(53,LOW); 243 | digitalWrite(A15,LOW); 244 | } 245 | else if(simpang == 3 && warna == 2){ 246 | digitalWrite(52,LOW); 247 | digitalWrite(53,HIGH); 248 | digitalWrite(A15,LOW); 249 | } 250 | else if(simpang == 3 && warna == 3){ 251 | digitalWrite(52,LOW); 252 | digitalWrite(53,LOW); 253 | digitalWrite(A15,HIGH); 254 | } 255 | 256 | } 257 | void normal(){ 258 | if(waktuS == 0){ 259 | waktuD = 15; 260 | waktuT = 30; 261 | }else if(waktuD == 0){ 262 | waktuT = 15; 263 | waktuS = 30; 264 | }else if(waktuT == 0){ 265 | waktuS = 15; 266 | waktuD = 30; 267 | } 268 | if(waktuS != 0){ 269 | if(waktuS > 0){ 270 | sevseg.setNumber(waktuS); 271 | } 272 | else{ 273 | sevseg.setNumber(waktuD); 274 | } 275 | } 276 | if(waktuD != 0){ 277 | if(waktuD > 0){ 278 | sevseg1.setNumber(waktuD); 279 | } 280 | else{ 281 | sevseg1.setNumber(waktuT); 282 | } 283 | } 284 | if(waktuT != 0){ 285 | if(waktuT > 0){ 286 | sevseg2.setNumber(waktuT); 287 | } 288 | else{ 289 | sevseg2.setNumber(waktuS); 290 | } 291 | } 292 | } 293 | -------------------------------------------------------------------------------- /SevSeg-Lib/README.md: -------------------------------------------------------------------------------- 1 | SevSeg 2 | ====== 3 | Copyright 2016 Dean Reading 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | * * * 16 | 17 | This library turns your Arduino into a seven segment display controller! Use it to easily display numbers on your seven segment display without any additional controllers. 18 | 19 | It supports common cathode and common anode displays, and the use of switching transistors. Numbers can be displayed in decimal or hexadecimal representation, with decimal places. Characters can be displayed (as accurately as possible). It also supports multiple displays, of varying dimensions. Shift registers and similar devices are NOT supported. 20 | 21 | [Download it from GitHub][1]. 22 | 23 | Direct any questions or suggestions to deanreading@hotmail.com. If I have the time, I'm happy to help you get things working. 24 | 25 | #### Update Version 3.3.0 (February 2017) 26 | 27 | Added the ability to keep leading zeros. This is now an extra 28 | parameter in the begin() function. 29 | 30 | #### Update Version 3.2.0 (December 2016) 31 | 32 | Backwards compatible with version 3.1 33 | Updated to Arduino 1.5 Library Specification 34 | New display function - no longer consumes processor time with delay() 35 | Now supports hexadecimal number printing 36 | The decimal point can now be omitted with a negative decPlaces 37 | Alphanumeric strings can be displayed (inaccurately) with setChars 38 | Removed #define RESISTORS_ON_SEGMENTS. Now a begin() input 39 | Can now blank() the display 40 | Now 'heavier' - uses more PROGMEM and RAM 41 | 42 | 43 | * * * 44 | 45 | ### HARDWARE 46 | 47 | #### Seven Segment Display Pins 48 | 49 | Your display should have: 50 | **Digit Pins** \- One for each digit. These are the 'common pins'. They will be cathodes (negative pins) for common cathode displays, or anodes (positive pins) for common anode displays. 51 | **8 Segment Pins** \- One for each of the seven segments plus the decimal point. 52 | 53 | 54 | #### Arduino Connections 55 | 56 | All digit pins and segment pins can be connected to any of the Arduino's digital or analog pins; just make sure you take note of your connections! 57 | 58 | 59 | #### Current-limiting Resistors 60 | 61 | Don't forget that the display uses LEDs, so you should use current-limiting resistors in series with the *digit pins*. 330 ohms is a safe value if you're unsure. If you use current-limiting resistors on the *segment pins* instead, then set resistorsOnSegments to true (see the example SevSeg_Counter.ino). 62 | 63 | #### Hardware Configuration 64 | 65 | You have to specify your hardware configuration to the library as the first argument in sevseg.begin. The options are detailed below. 66 | 67 | ##### Simple, Low Power Displays 68 | These displays are powered directly through the Arduino output pins. 69 | * **COMMON_CATHODE** \- For common cathode displays without switches. These displays require a low voltage at the digit pin to illuminate the digit. 70 | * **COMMON_ANODE** \- For common anode displays without switches. These displays require a high voltage at the digit pin to illuminate the digit. 71 | 72 | ##### Displays with Switches 73 | Some displays (mostly bigger ones) use switching transistors, but most people won't have to worry about the configurations below. 74 | * **N_TRANSISTORS** \- If you use N-type transistors to sink current (or any other active-high, low-side switches). 75 | * **P_TRANSISTORS** \- If you use P-type transistors to supply current (or any other active-low, high-side switches). 76 | * **NP_COMMMON_CATHODE** \- If your setup uses N-type AND P-type transistors with a common cathode display. 77 | * **NP_COMMMON_ANODE** \- If your setup uses N-type AND P-type transistors with a common anode display. 78 | Note that use of active-high, high-side switches will have no impact on the configuration chosen. There are usually called high-side switches. 79 | 80 | #### Example Pinout 81 | 82 | In the below pinout, digits are numbered 1, 2, 3, 4. 83 | Segments are numbered A through G plus Decimal Point (DP), according to [this picture][4]. 84 | Pins are ordered as looking at the front of the display. 85 | 86 | [Cheap, 4-digit, 12-pin display from Ebay][5] (labelled HS410561k-32 on bottom edge): 87 | 4-digit common anode display, with 2 rows of 6 pins. 88 | ``` 89 | Top Row: 1 A F 2 3 B 90 | Bottom Row: E D DP C G 4 91 | ``` 92 | 93 | * * * 94 | 95 | ### SOFTWARE 96 | 97 | To install, copy the SevSeg folder into your arduino sketchbook\-libraries folder. More detailed instructions are [here][3]. 98 | The Library Manager can be used from arduino version 1.6.2. 99 | 100 | 101 | #### Setting Up 102 | 103 | 104 | #include "SevSeg.h" 105 | SevSeg sevseg; //Instantiate a seven segment object 106 | 107 | void setup() { 108 | byte numDigits = 4; 109 | byte digitPins[] = {2, 3, 4, 5}; 110 | byte segmentPins[] = {6, 7, 8, 9, 10, 11, 12, 13}; 111 | bool resistorsOnSegments = false; // 'false' means resistors are on digit pins 112 | byte hardwareConfig = COMMON_ANODE; // See README.md for options 113 | sevseg.begin(hardwareConfig, numDigits, digitPins, segmentPins, resistorsOnSegments); 114 | ... 115 | 116 | 117 | digitPins is an array that stores the arduino pin numbers that the digits are connected to. Order them from left to right. 118 | segmentPins is an array that stores the arduino pin numbers that the segments are connected to. Order them from segment a to g , then the decimal place. 119 | If you wish to use more than 8 digits, increase MAXNUMDIGITS in SevSeg.h. 120 | 121 | 122 | #### Setting a Number 123 | 124 | 125 | sevseg.setNumber(3141,3); // Displays '3.141' 126 | 127 | 128 | The first argument is the number to display. The second argument indicates where the decimal place should be, counted from the least significant digit. E.g. to display an integer, the second argument is 0. 129 | Floats are supported. In this case, the second argument indicates how many decimal places of precision you want to display. E.g: 130 | 131 | 132 | sevseg.setNumber(3.14159f,3); //Displays '3.141' 133 | 134 | 135 | Out of range numbers are shown as '----'. 136 | 137 | If the second argument is -1 or omitted, there will be no decimal place. 138 | 139 | Enter 'true' as the third agument to display the number in hexadecimal representation. 140 | 141 | #### Setting a Character String 142 | 143 | 144 | sevseg.setChars("abcd"); 145 | 146 | Character arrays can be displayed - as accurately as possible on a seven segment display. See SevSeg.cpp digitCodeMap[] to notes on each character. Only alphanumeric characters, plus ' ' and '-' are supported. The character array should be NULL terminated. 147 | 148 | 149 | #### Displaying 150 | 151 | 152 | sevseg.refreshDisplay(); 153 | 154 | 155 | Your program must run the refreshDisplay() function repeatedly to display the number. Note that any delays introduced by other functions will produce undesirable effects on the display. 156 | 157 | To blank the display, call: 158 | 159 | sevseg.blank(); 160 | 161 | 162 | 163 | #### Setting the Brightness 164 | 165 | 166 | sevseg.setBrightness(90); 167 | 168 | 169 | The brightness can be adjusted using a value between 0 and 100. 170 | Note that a 0 does not correspond to no brightness. If your display has noticeable flickering, reducing the brightness level may correct it. 171 | 172 | [1]: https://github.com/DeanIsMe/SevSeg 173 | [2]: https://docs.google.com/file/d/0Bwrp4uluZCpNdE9oWTY0M3BncTA/edit?usp=sharing 174 | [3]: http://arduino.cc/en/Guide/Libraries 175 | [4]: https://en.wikipedia.org/wiki/File:7_segment_display_labeled.svg 176 | [5]: http://www.ebay.com/sch/i.html?LH_BIN=1&_from=R40&_sacat=0&_nkw=7+segment+display+4+digit+2+pcs&_sop=15 177 | 178 | -------------------------------------------------------------------------------- /SevSeg-Lib/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | 203 | -------------------------------------------------------------------------------- /SevSeg-Lib/SevSeg.cpp: -------------------------------------------------------------------------------- 1 | /* SevSeg Library 2 | 3 | Copyright 2017 Dean Reading 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | 17 | This library allows an Arduino to easily display numbers in decimal format on 18 | a 7-segment display without a separate 7-segment display controller. 19 | 20 | Direct any questions or suggestions to deanreading@hotmail.com 21 | See the included readme for instructions. 22 | https://github.com/DeanIsMe/SevSeg 23 | 24 | CHANGELOG 25 | Version 3.3.0 - February 2017 26 | Added the ability to keep leading zeros. This is now an extra 27 | parameter in the begin() function. 28 | 29 | Version 3.2.0 - December 2016 30 | Updated to Arduino 1.5 Library Specification 31 | New display function - no longer consumes processor time with delay() 32 | Now supports hexadecimal number printing 33 | The decimal point can now be omitted with a negative decPlaces 34 | decPlaces is now optional in setNumber 35 | Alphanumeric strings can be displayed (inaccurately) with setChars() 36 | Removed #define RESISTORS_ON_SEGMENTS. Now a begin() input 37 | Can now blank() the display 38 | 39 | Version 3.1 - September 2016 40 | Bug Fixes. No longer uses dynamic memory allocation. 41 | Version 3.0 - November 2014 42 | Library re-design. A display with any number of digits can be used. 43 | Floats are supported. Support for using transistors for switching. 44 | Much more user friendly. No backwards compatibility. 45 | Uploaded to GitHub to simplify any further development. 46 | Version 2.3; Allows for brightness control. 47 | Version 2.2; Allows 1, 2 or 3 digit displays to be used. 48 | Version 2.1; Includes a bug fix. 49 | Version 2.0; Now works for any digital pin arrangement. 50 | Supports both common anode and common cathode displays. 51 | */ 52 | 53 | #include "SevSeg.h" 54 | 55 | #define BLANK_IDX 36 // Must match with 'digitCodeMap' 56 | #define DASH_IDX 37 57 | 58 | static const long powersOf10[] = { 59 | 1, // 10^0 60 | 10, 61 | 100, 62 | 1000, 63 | 10000, 64 | 100000, 65 | 1000000, 66 | 10000000, 67 | 100000000, 68 | 1000000000 69 | }; // 10^9 70 | 71 | static const long powersOf16[] = { 72 | 0x1, // 16^0 73 | 0x10, 74 | 0x100, 75 | 0x1000, 76 | 0x10000, 77 | 0x100000, 78 | 0x1000000, 79 | 0x10000000 80 | }; // 16^7 81 | 82 | // The codes below indicate which segments must be illuminated to display 83 | // each number. 84 | static const byte digitCodeMap[] = { 85 | // GFEDCBA Segments 7-segment map: 86 | B00111111, // 0 "0" AAA 87 | B00000110, // 1 "1" F B 88 | B01011011, // 2 "2" F B 89 | B01001111, // 3 "3" GGG 90 | B01100110, // 4 "4" E C 91 | B01101101, // 5 "5" E C 92 | B01111101, // 6 "6" DDD 93 | B00000111, // 7 "7" 94 | B01111111, // 8 "8" 95 | B01101111, // 9 "9" 96 | B01110111, // 65 'A' 97 | B01111100, // 66 'b' 98 | B00111001, // 67 'C' 99 | B01011110, // 68 'd' 100 | B01111001, // 69 'E' 101 | B01110001, // 70 'F' 102 | B00111101, // 71 'G' 103 | B01110110, // 72 'H' 104 | B00000110, // 73 'I' 105 | B00001110, // 74 'J' 106 | B01110110, // 75 'K' Same as 'H' 107 | B00111000, // 76 'L' 108 | B00000000, // 77 'M' NO DISPLAY 109 | B01010100, // 78 'n' 110 | B00111111, // 79 'O' 111 | B01110011, // 80 'P' 112 | B01100111, // 81 'q' 113 | B01010000, // 82 'r' 114 | B01101101, // 83 'S' 115 | B01111000, // 84 't' 116 | B00111110, // 85 'U' 117 | B00111110, // 86 'V' Same as 'U' 118 | B00000000, // 87 'W' NO DISPLAY 119 | B01110110, // 88 'X' Same as 'H' 120 | B01101110, // 89 'y' 121 | B01011011, // 90 'Z' Same as '2' 122 | B00000000, // 32 ' ' BLANK 123 | B01000000, // 45 '-' DASH 124 | }; 125 | 126 | // Constant pointers to constant data 127 | const byte * const numeralCodes = digitCodeMap; 128 | const byte * const alphaCodes = digitCodeMap + 10; 129 | 130 | // SevSeg Constructor 131 | /******************************************************************************/ 132 | SevSeg::SevSeg() 133 | { 134 | // Initial value 135 | ledOnTime = 2000; // Corresponds to a brightness of 100 136 | numDigits = 0; 137 | prevUpdateIdx = 0; 138 | prevUpdateTime = 0; 139 | resOnSegments = 0; 140 | updateWithDelays = 0; 141 | } 142 | 143 | 144 | // begin 145 | /******************************************************************************/ 146 | // Saves the input pin numbers to the class and sets up the pins to be used. 147 | // If you use current-limiting resistors on your segment pins instead of the 148 | // digit pins, then set resOnSegments as true. 149 | // Set updateWithDelays to true if you want to use the 'pre-2017' update method 150 | // That method occupies the processor with delay functions. 151 | void SevSeg::begin(byte hardwareConfig, byte numDigitsIn, byte digitPinsIn[], 152 | byte segmentPinsIn[], bool resOnSegmentsIn, 153 | bool updateWithDelaysIn, bool leadingZerosIn) { 154 | 155 | resOnSegments = resOnSegmentsIn; 156 | updateWithDelays = updateWithDelaysIn; 157 | leadingZeros = leadingZerosIn; 158 | 159 | numDigits = numDigitsIn; 160 | //Limit the max number of digits to prevent overflowing 161 | if (numDigits > MAXNUMDIGITS) numDigits = MAXNUMDIGITS; 162 | 163 | switch (hardwareConfig) { 164 | 165 | case 0: // Common cathode 166 | digitOn = LOW; 167 | segmentOn = HIGH; 168 | break; 169 | 170 | case 1: // Common anode 171 | digitOn = HIGH; 172 | segmentOn = LOW; 173 | break; 174 | 175 | case 2: // With active-high, low-side switches (most commonly N-type FETs) 176 | digitOn = HIGH; 177 | segmentOn = HIGH; 178 | break; 179 | 180 | case 3: // With active low, high side switches (most commonly P-type FETs) 181 | digitOn = LOW; 182 | segmentOn = LOW; 183 | break; 184 | } 185 | 186 | digitOff = !digitOn; 187 | segmentOff = !segmentOn; 188 | 189 | // Save the input pin numbers to library variables 190 | for (byte segmentNum = 0 ; segmentNum < 8 ; segmentNum++) { 191 | segmentPins[segmentNum] = segmentPinsIn[segmentNum]; 192 | } 193 | 194 | for (byte digitNum = 0 ; digitNum < numDigits ; digitNum++) { 195 | digitPins[digitNum] = digitPinsIn[digitNum]; 196 | } 197 | 198 | // Set the pins as outputs, and turn them off 199 | for (byte digit = 0 ; digit < numDigits ; digit++) { 200 | pinMode(digitPins[digit], OUTPUT); 201 | digitalWrite(digitPins[digit], digitOff); 202 | } 203 | 204 | for (byte segmentNum = 0 ; segmentNum < 8 ; segmentNum++) { 205 | pinMode(segmentPins[segmentNum], OUTPUT); 206 | digitalWrite(segmentPins[segmentNum], segmentOff); 207 | } 208 | 209 | setNewNum(0, 0); // Initialise the number displayed to 0 210 | } 211 | 212 | 213 | // refreshDisplay 214 | /******************************************************************************/ 215 | // Turns on the segments specified in 'digitCodes[]' 216 | // There are 4 versions of this function, with the choice depending on the 217 | // location of the current-limiting resistors, and whether or not you wish to 218 | // use 'update delays' (the standard method until 2017). 219 | // For resistors on *digits* we will cycle through all 8 segments (7 + period), 220 | // turning on the *digits* as appropriate for a given segment, before moving on 221 | // to the next segment. 222 | // For resistors on *segments* we will cycle through all __ # of digits, 223 | // turning on the *segments* as appropriate for a given digit, before moving on 224 | // to the next digit. 225 | // If using update delays, refreshDisplay has a delay between each digit/segment 226 | // as it cycles through. It exits with all LEDs off. 227 | // If not using updateDelays, refreshDisplay exits with a single digit/segment 228 | // on. It will move to the next digit/segment after being called again (if 229 | // enough time has passed). 230 | 231 | void SevSeg::refreshDisplay() { 232 | 233 | if (!updateWithDelays) { 234 | 235 | // Exit if it's not time for the next display change 236 | if (micros() - prevUpdateTime < ledOnTime) return; 237 | prevUpdateTime = micros(); 238 | 239 | if (!resOnSegments) { 240 | /**********************************************/ 241 | // RESISTORS ON DIGITS, UPDATE WITHOUT DELAYS 242 | 243 | 244 | // Turn all lights off for the previous segment 245 | for (byte digitNum = 0 ; digitNum < numDigits ; digitNum++) { 246 | digitalWrite(digitPins[digitNum], digitOff); 247 | } 248 | digitalWrite(segmentPins[prevUpdateIdx], segmentOff); 249 | 250 | prevUpdateIdx++; 251 | if (prevUpdateIdx >= 8) prevUpdateIdx = 0; 252 | 253 | byte segmentNum = prevUpdateIdx; 254 | 255 | // Illuminate the required digits for the new segment 256 | digitalWrite(segmentPins[segmentNum], segmentOn); 257 | for (byte digitNum = 0 ; digitNum < numDigits ; digitNum++) { 258 | if (digitCodes[digitNum] & (1 << segmentNum)) { // Check a single bit 259 | digitalWrite(digitPins[digitNum], digitOn); 260 | } 261 | } 262 | } 263 | else { 264 | /**********************************************/ 265 | // RESISTORS ON SEGMENTS, UPDATE WITHOUT DELAYS 266 | 267 | 268 | // Turn all lights off for the previous digit 269 | for (byte segmentNum = 0 ; segmentNum < 8 ; segmentNum++) { 270 | digitalWrite(segmentPins[segmentNum], segmentOff); 271 | } 272 | digitalWrite(digitPins[prevUpdateIdx], digitOff); 273 | 274 | prevUpdateIdx++; 275 | if (prevUpdateIdx >= numDigits) prevUpdateIdx = 0; 276 | 277 | byte digitNum = prevUpdateIdx; 278 | 279 | // Illuminate the required segments for the new digit 280 | digitalWrite(digitPins[digitNum], digitOn); 281 | for (byte segmentNum = 0 ; segmentNum < 8 ; segmentNum++) { 282 | if (digitCodes[digitNum] & (1 << segmentNum)) { // Check a single bit 283 | digitalWrite(segmentPins[segmentNum], segmentOn); 284 | } 285 | } 286 | } 287 | } 288 | 289 | else { 290 | if (!resOnSegments) { 291 | /**********************************************/ 292 | // RESISTORS ON DIGITS, UPDATE WITH DELAYS 293 | for (byte segmentNum = 0 ; segmentNum < 8 ; segmentNum++) { 294 | 295 | // Illuminate the required digits for this segment 296 | digitalWrite(segmentPins[segmentNum], segmentOn); 297 | for (byte digitNum = 0 ; digitNum < numDigits ; digitNum++) { 298 | if (digitCodes[digitNum] & (1 << segmentNum)) { // Check a single bit 299 | digitalWrite(digitPins[digitNum], digitOn); 300 | } 301 | } 302 | 303 | //Wait with lights on (to increase brightness) 304 | delayMicroseconds(ledOnTime); 305 | 306 | //Turn all lights off 307 | for (byte digitNum = 0 ; digitNum < numDigits ; digitNum++) { 308 | digitalWrite(digitPins[digitNum], digitOff); 309 | } 310 | digitalWrite(segmentPins[segmentNum], segmentOff); 311 | } 312 | } 313 | else { 314 | /**********************************************/ 315 | // RESISTORS ON SEGMENTS, UPDATE WITH DELAYS 316 | for (byte digitNum = 0 ; digitNum < numDigits ; digitNum++) { 317 | 318 | // Illuminate the required segments for this digit 319 | digitalWrite(digitPins[digitNum], digitOn); 320 | for (byte segmentNum = 0 ; segmentNum < 8 ; segmentNum++) { 321 | if (digitCodes[digitNum] & (1 << segmentNum)) { // Check a single bit 322 | digitalWrite(segmentPins[segmentNum], segmentOn); 323 | } 324 | } 325 | 326 | //Wait with lights on (to increase brightness) 327 | delayMicroseconds(ledOnTime); 328 | 329 | //Turn all lights off 330 | for (byte segmentNum = 0 ; segmentNum < 8 ; segmentNum++) { 331 | digitalWrite(segmentPins[segmentNum], segmentOff); 332 | } 333 | digitalWrite(digitPins[digitNum], digitOff); 334 | } 335 | } 336 | } 337 | } 338 | 339 | // setBrightness 340 | /******************************************************************************/ 341 | 342 | void SevSeg::setBrightness(int brightness) { 343 | brightness = constrain(brightness, 0, 100); 344 | ledOnTime = map(brightness, 0, 100, 1, 2000); 345 | } 346 | 347 | 348 | // setNumber 349 | /******************************************************************************/ 350 | // This function only receives the input and passes it to 'setNewNum'. 351 | // It is overloaded for all number data types, so that floats can be handled 352 | // correctly. 353 | 354 | void SevSeg::setNumber(long numToShow, char decPlaces, bool hex) //long 355 | { 356 | setNewNum(numToShow, decPlaces, hex); 357 | } 358 | 359 | void SevSeg::setNumber(unsigned long numToShow, char decPlaces, bool hex) //unsigned long 360 | { 361 | setNewNum(numToShow, decPlaces, hex); 362 | } 363 | 364 | void SevSeg::setNumber(int numToShow, char decPlaces, bool hex) //int 365 | { 366 | setNewNum(numToShow, decPlaces, hex); 367 | } 368 | 369 | void SevSeg::setNumber(unsigned int numToShow, char decPlaces, bool hex) //unsigned int 370 | { 371 | setNewNum(numToShow, decPlaces, hex); 372 | } 373 | 374 | void SevSeg::setNumber(char numToShow, char decPlaces, bool hex) //char 375 | { 376 | setNewNum(numToShow, decPlaces, hex); 377 | } 378 | 379 | void SevSeg::setNumber(byte numToShow, char decPlaces, bool hex) //byte 380 | { 381 | setNewNum(numToShow, decPlaces, hex); 382 | } 383 | 384 | void SevSeg::setNumber(float numToShow, char decPlaces, bool hex) //float 385 | { 386 | char decPlacesPos = constrain(decPlaces, 0, MAXNUMDIGITS); 387 | if (hex) { 388 | numToShow = numToShow * powersOf16[decPlacesPos]; 389 | } 390 | else { 391 | numToShow = numToShow * powersOf10[decPlacesPos]; 392 | } 393 | // Modify the number so that it is rounded to an integer correctly 394 | numToShow += (numToShow >= 0) ? 0.5f : -0.5f; 395 | setNewNum(numToShow, decPlaces, hex); 396 | } 397 | 398 | 399 | // setNewNum 400 | /******************************************************************************/ 401 | // Changes the number that will be displayed. 402 | 403 | void SevSeg::setNewNum(long numToShow, char decPlaces, bool hex) { 404 | byte digits[numDigits]; 405 | findDigits(numToShow, decPlaces, hex, digits); 406 | setDigitCodes(digits, decPlaces); 407 | } 408 | 409 | 410 | // setSegments 411 | /******************************************************************************/ 412 | // Sets the 'digitCodes' that are required to display the desired segments. 413 | // Using this function, one can display any arbitrary set of segments (like 414 | // letters, symbols or animated cursors). See setDigitCodes() for common 415 | // numeric examples. 416 | // 417 | // Bit-segment mapping: 0bHGFEDCBA 418 | // Visual mapping: 419 | // AAAA 0000 420 | // F B 5 1 421 | // F B 5 1 422 | // GGGG 6666 423 | // E C 4 2 424 | // E C 4 2 (Segment H is often called 425 | // DDDD H 3333 7 DP, for Decimal Point) 426 | 427 | void SevSeg::setSegments(byte segs[]) 428 | { 429 | for (byte digit = 0; digit < numDigits; digit++) { 430 | digitCodes[digit] = segs[digit]; 431 | } 432 | } 433 | 434 | // setChars 435 | /******************************************************************************/ 436 | // Displays the string on the display, as best as possible. 437 | // Only alphanumeric characters plus '-' and ' ' are supported 438 | void SevSeg::setChars(char str[]) 439 | { 440 | for (byte digit = 0; digit < numDigits; digit++) { 441 | digitCodes[digit] = 0; 442 | } 443 | 444 | for (byte digitNum = 0; digitNum < numDigits; digitNum++) { 445 | char ch = str[digitNum]; 446 | if (ch == '\0') break; // NULL string terminator 447 | if (ch >= '0' && ch <= '9') { // Numerical 448 | digitCodes[digitNum] = numeralCodes[ch - '0']; 449 | } 450 | else if (ch >= 'A' && ch <= 'Z') { 451 | digitCodes[digitNum] = alphaCodes[ch - 'A']; 452 | } 453 | else if (ch >= 'a' && ch <= 'z') { 454 | digitCodes[digitNum] = alphaCodes[ch - 'a']; 455 | } 456 | else if (ch == ' ') { 457 | digitCodes[digitNum] = digitCodeMap[BLANK_IDX]; 458 | } 459 | else { 460 | // Every unknown character is shown as a dash 461 | digitCodes[digitNum] = digitCodeMap[DASH_IDX]; 462 | } 463 | } 464 | } 465 | 466 | // blank 467 | /******************************************************************************/ 468 | void SevSeg::blank(void) { 469 | for (byte digitNum = 0 ; digitNum < numDigits ; digitNum++) { 470 | digitCodes[digitNum] = digitCodeMap[BLANK_IDX]; 471 | } 472 | refreshDisplay(); 473 | } 474 | 475 | // findDigits 476 | /******************************************************************************/ 477 | // Decides what each digit will display. 478 | // Enforces the upper and lower limits on the number to be displayed. 479 | 480 | void SevSeg::findDigits(long numToShow, char decPlaces, bool hex, byte digits[]) { 481 | const long * powersOfBase = hex ? powersOf16 : powersOf10; 482 | const long maxNum = powersOfBase[numDigits] - 1; 483 | const long minNum = -(powersOfBase[numDigits - 1] - 1); 484 | 485 | // If the number is out of range, just display dashes 486 | if (numToShow > maxNum || numToShow < minNum) { 487 | for (byte digitNum = 0 ; digitNum < numDigits ; digitNum++) { 488 | digits[digitNum] = DASH_IDX; 489 | } 490 | } 491 | else { 492 | byte digitNum = 0; 493 | 494 | // Convert all number to positive values 495 | if (numToShow < 0) { 496 | digits[0] = DASH_IDX; 497 | digitNum = 1; // Skip the first iteration 498 | numToShow = -numToShow; 499 | } 500 | 501 | // Find all digits for base's representation, starting with the most 502 | // significant digit 503 | for ( ; digitNum < numDigits ; digitNum++) { 504 | long factor = powersOfBase[numDigits - 1 - digitNum]; 505 | digits[digitNum] = numToShow / factor; 506 | numToShow -= digits[digitNum] * factor; 507 | } 508 | 509 | // Find unnnecessary leading zeros and set them to BLANK 510 | if (decPlaces < 0) decPlaces = 0; 511 | if (!leadingZeros) { 512 | for (digitNum = 0 ; digitNum < (numDigits - 1 - decPlaces) ; digitNum++) { 513 | if (digits[digitNum] == 0) { 514 | digits[digitNum] = BLANK_IDX; 515 | } 516 | // Exit once the first non-zero number is encountered 517 | else if (digits[digitNum] <= 9) { 518 | break; 519 | } 520 | } 521 | } 522 | 523 | } 524 | } 525 | 526 | 527 | // setDigitCodes 528 | /******************************************************************************/ 529 | // Sets the 'digitCodes' that are required to display the input numbers 530 | 531 | void SevSeg::setDigitCodes(byte digits[], char decPlaces) { 532 | 533 | // Set the digitCode for each digit in the display 534 | for (byte digitNum = 0 ; digitNum < numDigits ; digitNum++) { 535 | digitCodes[digitNum] = digitCodeMap[digits[digitNum]]; 536 | // Set the decimal place segment 537 | if (decPlaces >= 0) { 538 | if (digitNum == numDigits - 1 - decPlaces) { 539 | digitCodes[digitNum] |= B10000000; 540 | } 541 | } 542 | } 543 | } 544 | 545 | /// END /// 546 | --------------------------------------------------------------------------------