Κώδικας:
/*
7-Segment Display Multiplexing Countdown timer
Common cathode displays
max. countdown time 99:59 [min:sec]
Arduino Software (IDE) 1.8.12
Date: 16/06/2020
# kernel panik #
*/
/*
7-Segment Display map
AAA
F B
F B
GGG
E C
E C
DDD
*/
/*------------------------------------------------------------
Includes
------------------------------------------------------------*/
#include <EEPROM.h>
/*------------------------------------------------------------
Defines
------------------------------------------------------------*/
#define pinUP 0 // Button UP Countdown
#define pinDown 1 // Button Down Countdown
#define pinStart 2 // Button Start or STOP
#define PinPause A4 // Button Pause
#define UV_Leds A3 // output
#define Buzzer A2 // Buzzer pin out
#define SpeedSlow 250 // milliseconds
#define SpeedFast 1500 // milliseconds
#define SpeedDwnSec 1 //
#define BeepSec 6 // Beep for the last seconds
#define Debounce_ms 20 // milliseconds
#define EEPRminute 0 // address of the EEPROM
#define EEPRsecond 1 // address of the EEPROM
#define StartTimer TCCR1B = 0x04; // set clock -> start = 0x04; | stop = 0x00;
#define StopTimer TCCR1B = 0x00;
// arduino pins for segments
#define A 7 // arduino pin out
#define B 5
#define C 8
#define D 11
#define E 12
#define F 10
#define G 6
#define DP 9 // Blink led COL. every second
// arduino pins for digits
#define Dig1 3 // arduino pin out
#define Dig2 4
#define Dig3 A1
#define Dig4 A0
// Button debouncing globals
const uint8_t Buttons[] = {pinUP, pinDown, pinStart, PinPause}; // create an array of pins for switch
const uint8_t NumOFbtns = sizeof(Buttons);
unsigned long ButtonTime, SpeedTime;
int Minute, Second, SpeedCount; //
//=== 7 segments leds =============================
// bits representing segments A through G (and decimal point) for numerals 0-9
const uint8_t Numera[21] = {
//ABCDEFG dp
B11111100, // 0
B01100000, // 1
B11011010, // 2
B11110010, // 3
B01100110, // 4
B10110110, // 5
B00111110, // 6
B11100000, // 7
B11111110, // 8
B11100110, // 9
B10110110, // S / 10
B10011110, // E / 11
B00011110, // t / 12
B01101110, // H / 13
B00001000, // i / 14
B11001110, // P / 15
B00000010, // - / 16
B00000000, // 17 - shows nothing
B00101010, // n / 18
B01111010, // d / 19
B00111010, // o / 20
};
const uint8_t segmentPins[] = {DP, G, F, E, D, C, B, A};
const uint8_t nbrDigits = 4; // the number of digits in the LED display
const uint8_t digitPins[nbrDigits] = { Dig1, Dig2, Dig3, Dig4};
/* notes in the melody
http://www.arduino.cc/en/Tutorial/Tone */
// int melody[] = {262, 196, 196, 220, 196, 0, 247, 262};
int melody[] = {4186, 3136, 3136, 3520, 3136, 0, 3951, 4186};
//note durations. 4=quarter note / 8=eighth note
int noteDurations[] = {4, 8, 8, 4, 4, 4, 4, 4};
bool ON = HIGH;
bool OFF = LOW;
bool LastBeep;
/***********************
Timer interrupt
https://www.electronicsblog.net/examples-of-using-arduinoatmega-16-bit-hardware-timer-for-digital-clock/
************************/
ISR(TIMER1_OVF_vect) {
Second --;
LastBeep = true ;
digitalWrite (DP, !digitalRead(DP));
TCNT1 = 0x0BDC ; // 0x0BDC set initial value to remove time error (16bit counter register)
}
enum _buttons {
ButtonUP,
ButtonDOWN,
ButtonSTART,
ButtonPAUSE
};
//=== setup =============================================================
void setup() {
/* make buttons as input */
for ( uint8_t index_BTN = 0; index_BTN < NumOFbtns; index_BTN++) {
pinMode(Buttons[index_BTN], INPUT_PULLUP);
}
for (uint8_t i = 0; i < 8; i++) {
pinMode (segmentPins[i], OUTPUT); // set segment and DP pins to output
for (uint8_t i = 0; i < nbrDigits; i++)
pinMode (digitPins[i], OUTPUT);
}
pinMode (Buzzer, OUTPUT);
pinMode (UV_Leds, OUTPUT);
digitalWrite (Buzzer, OFF);
digitalWrite (UV_Leds, OFF);
for (uint8_t i = 0; i < 50; i++) { // Hi
showDigit (13, 1); // H
showDigit (14, 2); // i
}
TIMSK1 = 0x01; // enabled global and timer overflow interrupt;
TCCR1A = 0x00; // normal operation (mode0);
TCNT1 = 0x0BDC; // 0x0BDC set initial value to remove time error (16bit counter register)
StopTimer;
Minute = EEPROM.read(EEPRminute); // read minute from address of the EEPROM
Second = EEPROM.read(EEPRsecond); // read second from address of the EEPROM
digitalWrite (DP, ON);
Beep_();
}//==Close setup =====
//==== loop ================================================================
void loop() {
UpDown();
//--- Start | EEPROM | Pause | STOP ----
//--- Pause ----
if ((digitalRead(PinPause) == HIGH) && (CheckButton(Buttons[ButtonSTART])) && (!getBtnStableLevel(Buttons[ButtonSTART]))) {
digitalWrite (UV_Leds, OFF);
StopTimer;
Pause();
delay (10);
}
//--- Start ---
if (( digitalRead (PinPause) == LOW) && (CheckButton(Buttons[ButtonSTART])) && (!getBtnStableLevel(Buttons[ButtonSTART]))) {
bool CountDwn = true;
//--- Store EEPROM only if different ---
if ( EEPROM.read (EEPRminute) != Minute || EEPROM.read (EEPRsecond) != Second) {
digitalWrite (DP, OFF);
EEPROM.update (EEPRminute, Minute);
EEPROM.update (EEPRsecond, Second);
for (int i = 0; i < 50; i++) { // Display SEt
showDigit (10, 0); // S
showDigit (11, 1); // E
showDigit (12, 2); // t
}
} //--Close Store EEPROM -----
StartTimer;
digitalWrite (UV_Leds, ON);
Beep_();
//--- Countdown ----
while (CountDwn) {// wait
if (Minute == 0 && Second == 0) {
CountDwn = false;
}
if (Minute == 0 && Second < BeepSec && LastBeep == true) {
Beep_();
LastBeep = false;
}
if (Second < 0) {
Minute --;
Second = 59;
}
//--- Pause ----
if ((CheckButton(Buttons[ButtonPAUSE])) && (getBtnStableLevel(Buttons[ButtonPAUSE]))) {
digitalWrite (UV_Leds, OFF);
StopTimer;
Pause();
StartTimer;
digitalWrite (UV_Leds, ON);
}//--Close Pause ----
//-- STOP ----
if ((CheckButton(Buttons[ButtonSTART])) && (!getBtnStableLevel(Buttons[ButtonSTART]))) {
digitalWrite (UV_Leds, OFF);
StopTimer;
digitalWrite (DP, OFF);
for (int i = 0; i < 100; i++) {
showDigit (10, 0); // S
showDigit (12, 1); // t
showDigit (20, 2); // 0
showDigit (15, 3); // P
}
Minute = 0;
Second = 0;
}//--Close STOP ----
UpdateDisplay();
}//--Close while Countdown ----
digitalWrite (UV_Leds, OFF);
StopTimer;
digitalWrite (DP, OFF);
BuzMelody();
// End
bool _end = true;
do {
showDigit (11, 0); // E
showDigit (18, 1); // n
showDigit (19, 2); // d
if ((CheckButton(Buttons[ButtonSTART])) && (!getBtnStableLevel(Buttons[ButtonSTART]))) {
Minute = EEPROM.read(EEPRminute);
Second = EEPROM.read(EEPRsecond);
_end = false;
}
}
while (_end) ; // End
digitalWrite (DP, ON);
}//--Close Start | EEPROM | Pause | STOP ----
UpdateDisplay();
}//==Close loop =====
//=== Up Down Time ==========================================
void UpDown() {
//-- UP ---
if (CheckButton(Buttons[ButtonUP]) && !getBtnStableLevel(Buttons[ButtonUP])) {
Second ++;
ButtonTime = millis();
SpeedTime = millis();
while ( digitalRead (pinUP) == LOW) {
if (Second > 59) {
Second = 00;
Minute ++;
}
if (Minute >= 100) {
Minute = 00;
}
if (millis() - ButtonTime > SpeedSlow) {
Second ++;
ButtonTime = millis ();
if ( millis () - SpeedTime > SpeedFast) {
Second += 29;
}
}
UpdateDisplay();
}//--Close while ----
}//==Close pinUP ====
//--- Down ----
if (CheckButton(Buttons[ButtonDOWN]) && !getBtnStableLevel(Buttons[ButtonDOWN])) {
if ((Minute == 0) && (Second == 0)) {
Second = 59;
Minute = 99;
}
else {
Second --;
}
if ((Second == -1) || (Second > 60)) {
Second = 59;
Minute --;
}
SpeedCount = SpeedSlow;
ButtonTime = millis();
SpeedTime = millis();
while ( digitalRead (pinDown) == LOW) { //-- while --
if ( millis () - SpeedTime > SpeedFast) {
SpeedCount = SpeedDwnSec;
}
if ( millis () - ButtonTime > SpeedCount) {
if ((Second == 0) && (Minute == 0)) {
Minute = 99;
Second = 59;
}
else {
Second --;
}
if ((Second == -1) || (Second > 60)) {
Second = 59;
Minute --;
}
ButtonTime = millis();
}
UpdateDisplay();
}//--Close while ---
} //== Close Down ===
}//== Close UpDown ===
//=== Pause ==========================================
void Pause() {
digitalWrite (DP, OFF);
//-- Animation P --
while ( digitalRead (PinPause) == HIGH ) { //-- while --
for ( int digit = nbrDigits - 1; digit >= 0; digit--) {
for ( uint8_t i = 0; i < 40; i++) {
showDigit (15, digit); // P
}
}
for ( uint8_t Dig = 1; Dig <= 2; Dig++) {
for ( uint8_t i = 0; i < 40; i++) {
showDigit (15, Dig); // P
}
}
}//--Close while Animation P ---
}//==Close Pause =====
//=== UpdateDisplay ===================================
void UpdateDisplay() { // mmss
showDigit (Minute / 10, 0);
showDigit (Minute % 10, 1);
showDigit (Second / 10, 2);
showDigit (Second % 10, 3);
}//==Close UpdateDisplay ====
//=== showDigit ========================================
// Displays given number on a 7-segment display at the given digit position
void showDigit ( uint8_t number, uint8_t digit) {
digitalWrite (digitPins[digit], HIGH );
for ( uint8_t segment = 1; segment < 8; segment++) {
bool isBitSet = bitRead (Numera[number], segment);
// isBitSet will be true if given bit is 1
/* --- CC or CA Display --- */
// isBitSet = ! isBitSet ; // if (CA) Common Anode Display Remove comment from this line
digitalWrite (segmentPins[segment], isBitSet);
}
delay (3);
digitalWrite (digitPins[digit], LOW );
}//==Close showDigit ====
//--- Buttons -----
//=== CheckButton ====================================
bool stableButtonLevels[20]; //
bool oldButtonLevels[20]; //
bool CheckButton( uint8_t Button_Pin) {
bool previousLevel = stableButtonLevels[Button_Pin];
bool newLevel = getBtnStableLevel(Button_Pin);
return previousLevel != newLevel;
}//== Close CheckButton ===
//=== getBtnStableLevel ====================================
bool getBtnStableLevel( uint8_t Button_Pin) {
unsigned long BtnPressTime;
// Reads a digital pin and filters it, returning the stable button position
bool pinLevel = digitalRead (Button_Pin);
if (pinLevel != oldButtonLevels[Button_Pin]) {
BtnPressTime = millis ();
oldButtonLevels[Button_Pin] = pinLevel;
}
// Once the button has been stable for
if (( millis () - BtnPressTime) > Debounce_ms) { // Debounce
stableButtonLevels[Button_Pin] = pinLevel;
}
return stableButtonLevels[Button_Pin];
}//==Close getBtnStableLevel ======
//--End Buttons ----
/* --- Buzzer Melody ----
http://www.arduino.cc/en/Tutorial/Tone */
//=== BuzMelody ====================================
void BuzMelody() {
//iterate over the notes of the melody
for (int thisNote = 0; thisNote < 8; thisNote++) {
//to calculate the note duration, take one second. Divided by the note type
int noteDuration = 1000 / noteDurations [thisNote];
tone(Buzzer, melody [thisNote], noteDuration);
//to distinguish the notes, set a minimum time between them
int pauseBetweenNotes = noteDuration * 1.30;
delay(pauseBetweenNotes);
//stop the tone playing
noTone(Buzzer);
}
}//==Close BuzMelody ====
//=== Buzzer Beep ====================================
void Beep_() {
tone(Buzzer, 2489, 30);
delay(40);
noTone(Buzzer);
}//==Close Beep_ ======
/*********( END Code )***********/