// segment macros
#define A 5
#define B 8
#define C A3
#define D A1
#define E A0
#define F 6
#define G A4
#define DP A2
// common anodes macros
#define GND1 7
#define GND2 9
#define GND3 10
#define GND4 A5
#define DOWN 0
#define UP 1
#define BUZZER 11
int minutes = 0;
int seconds = 0;
volatile boolean TurnUpDetected; //rotary encoder
volatile boolean TurnDownDetected;
unsigned long Watch, _micro;
unsigned int Clock = 0, R_clock;
boolean Reset = false, Stop = true, Paused = false, _type;
volatile boolean timeFlag = false;
unsigned long time;
int timer=0;
boolean timerStart=false;
int i=0;
// functions to display digits
void setup()
{
pinMode(2, INPUT_PULLUP);
pinMode(4, INPUT_PULLUP);
pinMode(3, INPUT);//button
attachInterrupt(digitalPinToInterrupt(2), setState, FALLING);
pinMode(A, OUTPUT);
pinMode(B, OUTPUT);
pinMode(C, OUTPUT);
pinMode(D, OUTPUT);
pinMode(E, OUTPUT);
pinMode(F, OUTPUT);
pinMode(G, OUTPUT);
pinMode(DP, OUTPUT);
pinMode(BUZZER, OUTPUT);
pinMode(GND1, OUTPUT);
pinMode(GND2, OUTPUT);
pinMode(GND3, OUTPUT);
pinMode(GND4, OUTPUT);
digitalWrite(DP, HIGH);
Serial.begin(9600);
}
void digit0 ()
{
digitalWrite(A, LOW);
digitalWrite(B, LOW);
digitalWrite(C, LOW);
digitalWrite(D, LOW);
digitalWrite(E, LOW);
digitalWrite(F, LOW);
digitalWrite(G, HIGH);
}
void digit1 ()
{
digitalWrite(A,HIGH);
digitalWrite(B, LOW);
digitalWrite(C, LOW);
digitalWrite(D, HIGH);
digitalWrite(E, HIGH);
digitalWrite(F, HIGH);
digitalWrite(G, HIGH);
}
void digit2 ()
{
digitalWrite(A,LOW);
digitalWrite(B, LOW);
digitalWrite(C, HIGH);
digitalWrite(D, LOW);
digitalWrite(E, LOW);
digitalWrite(F, HIGH);
digitalWrite(G, LOW);
};
void digit3 ()
{
digitalWrite(A,LOW);
digitalWrite(B, LOW);
digitalWrite(C, LOW);
digitalWrite(D, LOW);
digitalWrite(E, HIGH);
digitalWrite(F, HIGH);
digitalWrite(G, LOW);
}
void digit4 ()
{
digitalWrite(A,HIGH);
digitalWrite(B, LOW);
digitalWrite(C, LOW);
digitalWrite(D, HIGH);
digitalWrite(E, HIGH);
digitalWrite(F, LOW);
digitalWrite(G, LOW);
}
void digit5 ()
{
digitalWrite(A,LOW);
digitalWrite(B, HIGH);
digitalWrite(C, LOW);
digitalWrite(D, LOW);
digitalWrite(E, HIGH);
digitalWrite(F, LOW);
digitalWrite(G, LOW);
}
void digit6 ()
{
digitalWrite(A,LOW);
digitalWrite(B, HIGH);
digitalWrite(C, LOW);
digitalWrite(D, LOW);
digitalWrite(E, LOW);
digitalWrite(F, LOW);
digitalWrite(G, LOW);
}
void digit7 ()
{
digitalWrite(A,LOW);
digitalWrite(B, LOW);
digitalWrite(C, LOW);
digitalWrite(D, HIGH);
digitalWrite(E, HIGH);
digitalWrite(F, HIGH);
digitalWrite(G, HIGH);
}
void digit8 ()
{
digitalWrite(A, LOW);
digitalWrite(B, LOW);
digitalWrite(C, LOW);
digitalWrite(D, LOW);
digitalWrite(E, LOW);
digitalWrite(F, LOW);
digitalWrite(G, LOW);
}
void digit9 ()
{
digitalWrite(A, LOW);
digitalWrite(B, LOW);
digitalWrite(C, LOW);
digitalWrite(D, LOW);
digitalWrite(E, HIGH);
digitalWrite(F, LOW);
digitalWrite(G, LOW);
}
void showdigit (int digit)
{
switch (digit)
{
case 0:
digit0 ();
break;
case 1:
digit1 ();
break;
case 2:
digit2 ();
break;
case 3:
digit3 ();
break;
case 4:
digit4 ();
break;
case 5:
digit5 ();
break;
case 6:
digit6 ();
break;
case 7:
digit7 ();
break;
case 8:
digit8 ();
break;
case 9:
digit9 ();
break;
default:
break;
};
}
// showing 4 digits
void showdigits (int number)
{
// e.g. we have "1234"
showdigit(number/1000); // segments are set to display "1"
digitalWrite(GND1, HIGH); // first digit on,
digitalWrite(GND2, LOW); // other off
digitalWrite(GND3, LOW);
digitalWrite(GND4, LOW);
digitalWrite(DP, HIGH);
delay (1);
number = number%1000; // remainder of 1234/1000 is 234
digitalWrite(GND1, LOW); // first digit is off
showdigit(number/100); //// segments are set to display "2"
digitalWrite(GND2, HIGH); // second digit is on
digitalWrite(DP, LOW);
delay (1); // and so on....
number =number%100;
digitalWrite(GND2, LOW);
showdigit(number/10);
digitalWrite(GND3, HIGH);
digitalWrite(DP, HIGH);
delay (1);
number =number%10;
digitalWrite(GND3, LOW);
showdigit(number);
digitalWrite(GND4, HIGH);
digitalWrite(DP, HIGH);
delay (1);
};
void loop ()
{
if(timerStart)
{
CountUpDownTimer(DOWN);
timer++;
showdigits(i);
if (timer==10)
{
timer = 0;
}
}
if (TimeHasChanged() && timerStart)
{
int screenMinutes = ShowMinutes();
int screenSeconds = ShowSeconds();
i=(screenMinutes*100)+screenSeconds;
if(Clock==0)
{
playAlarm();
timerStart=false;
}
}
if(!timerStart)
{
//Serial.println(minutes);
showCurrentTime();
if(TurnDownDetected)
{
TurnDownDetected = false;
if(seconds>0&&seconds<3600)
seconds=seconds-30;
if(seconds>=3600)
seconds=seconds-60;
SetTimer(0,0,seconds);
}
if(TurnUpDetected)
{
TurnUpDetected = false;
if(seconds>=0&&seconds<3600)
seconds=seconds+30;
if(seconds>=3600)
seconds=seconds+60;
SetTimer(0,0,seconds);
}
if (digitalRead(3)==LOW && Clock!=0)
{
timerStart = true;
time = micros();
StartTimer();
}
}
}
void showCurrentTime()
{
showdigits(i);
int screenMinutes = ShowMinutes();
int screenSeconds = ShowSeconds();
int screenHours = ShowHours();
if(screenMinutes<60)
{
i= (screenMinutes*100)+screenSeconds;
}
if(screenMinutes>=60)
{
i=(screenHours*100)+screenMinutes%60;
}
if (timer==10)
{
timer = 0;
}
}
void setState() //encoder
{
if(digitalRead(4))
{
TurnDownDetected = true;
}
else
{
TurnUpDetected = true;
}
}
void playAlarm() //
{
for(int i=0;i<12;i++)
{
tone(11, 4000); //4kHz pwm sequention
delay(100);
noTone(11);
delay(100);
tone(11, 4001);
delay(100);
noTone(11);
delay(700);
}
}
boolean CountUpDownTimer(boolean Type)
{
_type = Type;
static unsigned long duration = 1000000; // 1 second
timeFlag = false;
if (!Stop && !Paused) // if not Stopped or Paused, run timer
{
// check the time difference and see if 1 second has elapsed
if ((_micro = micros()) - time > duration )
{
_type == UP? Clock++ : Clock--;
timeFlag = true;
if (_type == DOWN && Clock == 0) // check to see if the clock is 0
Stop = true; // If so, stop the timer
// check to see if micros() has rolled over, if not,
// then increment "time" by duration
_micro < time ? time = _micro : time += duration;
}
}
return !Stop; // return the state of the timer
}
void ResetTimer()
{
if(_type)
Clock = 0;
else
SetTimer(R_clock);
Stop = false;
}
void StartTimer()
{
Watch = micros(); // get the initial microseconds at the start of the timer
Stop = false;
Paused = false;
if(_type == UP)
Clock = 0;
}
void StopTimer()
{
Stop = true;
}
void StopTimerAt(unsigned int hours,unsigned int minutes, unsigned int seconds)
{
if (TimeCheck(hours, minutes, seconds) )
Stop = true;
}
void PauseTimer()
{
Paused = true;
}
void ResumeTimer() // You can resume the timer if you ever stop it.
{
Paused = false;
}
void SetTimer(unsigned int hours, unsigned int minutes, unsigned int seconds)
{
// This handles invalid time overflow ie 1(H), 0(M), 120(S) -> 1, 2, 0
unsigned int _S = (seconds / 60), _M = (minutes / 60);
if(_S) minutes += _S;
Clock = (minutes * 60) + (seconds % 60);
R_clock = Clock;
}
void SetTimer(unsigned int seconds)
{
// StartTimer(seconds / 3600, (seconds / 3600) / 60, seconds % 60);
Clock = seconds;
R_clock = Clock;
Stop = false;
}
int ShowMinutes()
{
return Clock / 60;
}
int ShowSeconds()
{
return Clock % 60;
}
int ShowHours()
{
return Clock / 3600;
}
boolean TimeHasChanged()
{
return timeFlag;
}
// output true if timer equals requested time
boolean TimeCheck(unsigned int hours, unsigned int minutes, unsigned int seconds)
{
return (hours == ShowHours() && minutes == ShowMinutes() && seconds == ShowSeconds());
}
Why in English?
@Polisz
What, source code? Seems like good practice.
izolator
Fajny projekt, choć mam parę uwag:
-bałbym się akumulatora “UltraFire” :)
-bardzo staniały małe wyświetlacze OLED na I2C, całkiem fajnie zastępują 7 segmentowe
co do ogniwa to masz racje kupione dobre 3 lata temu byle taniej :) OLED może być ciekawą alternatywą płytka bardzo by się uprościła, i znacząco można obniżyć pobór prądu dodając opcje ciagłego właczenia i np dorobić termometr.
Ja mam słabość do 7 segmentowych i uważam, że nic nie jest tak czytelne jak one. Też zauważyłem, że kod na pierwszy rzut oka bardzo elegancki. Wogóle w tym projekcie nie ma miejsca na bałagan :)
Co innego u mnie: https://youtu.be/yYBa_sB3w4E :) Ale może posłużyć za inspirację do tworzenia obudowy. Sklejka 5mm dobrze się nadaje do montażu elektroniki. Transfer druku na drewno poznałem tu na majsterkowie, ale na you-tube jest bardzo dużo materiału na ten temat. Ja do prostych grafik polecam aceton, wacik i łyżkę stołową.
Dominik bardzo ładna obudowa, odezwij się do mnie na priv po płytkę, może sie przyda do uprzątnięcia projektu. Pozdrawiam
Kurcze :D dobry projekcik !
Płytka sztosik + hehe :) powiedz proszę, gdzie w Chinach zamawiałeś płytki oraz ile miej więcej oczekiwałeś na ich dostarczenie?
I jeszcze na koniec jak z ich jakością ? Pytam dlatego że kiedyś zamawiałem płytki z ebay (nie pamiętam już sprzedawcy) i trochę rozczarowany byłem ich wykonaniem :(
zamawiałem na pcbway i na allpcb jakoś bardzo dobra z powodzeniem wykorzystywana w komercyjnych rozwiązaniach. Po 4 dniach roboczych od wgrania gerberów masz płytki, jęśli to nie jest jakiś wygórowany projekt wielowarstwowy.
Multipleksowanie powinno być w przerwaniu.
Multipleksowanie? Dlaczego? Generalnie reguła jest chyba taka żeby w przerwaniu było jak najmniej. Najlepiej tylko zmiana wartości zmiennej stanu.
Można to zrobić tak: w przerwaniu od timera (co kilkanaście milisekund) ustawiać flagę, w pętli głównej ją sprawdzać, i jeśli jest ustawiona, to multipleksować kolejną cyfrę
Dzięki, tak to brzmi rozsądnie.
Oczywiście, że multipleksowanie można dać do przerwania – jest to bardzo mały ułamek użycia procka, a czasem multipleksowanie jest o tyle kluczowe, że gdy sterujemy większym prądem zwłoka w przełączeniu może spowodować uszkodzenie wyświetlacza.
Ładnie pooptymalizować, ze w przerwaniu tylko wywalimy odpowiednie dane na porty, a ich wcześniejsza obróbka podczas zmiany wyświetlanych rzeczy i gitara
Witam prosiłbym o dopisanie do programu włączanie przekaźnika który byłby włączony na czas odliczania.
chętnie kupię płytkę
ok już nie potrzeba
Masz schemat na arduino i plytke prototypowa?
AREF należy odsprzegnąć kondensatorem 100nF do masy. Całość zyska na stabilności a pamiętając o takich szczegółach w najdrobniejszych nawet projektach wyrabia się dobre nawyki. Pozdrawiam!