Sida 1 av 2

Deltids-väckarklocka

Postat: 19 februari 2016, 10:49:41
av BjörnO
Om ett par veckor har jag nått mitt bäst-före-datum. Jag kommer att vara kvar på jobbet, men bara tre dagar i veckan. Mina helger kommer därför att vara fyra dagar långa :)
Min gamla väckarklocka har hittills väckt mig varje dag klockan 6, vardag som helg. Så vill jag inte ha det i fortsättningen. Klockan 6 är OK tre dagar i veckan men annars ska det vara tyst.
Visst, jag kan lösa det med mobilen, men jag vill ha en dedicerad väckarklocka. Jag har en Arduino och en display kvar från ett tidigare projekt, resten kan jag säkert hitta i mina gömmor.

Re: Deltids-väckarklocka

Postat: 19 februari 2016, 10:57:53
av BjörnO
Efter några veckors labbande började det arta sig.
En plastbox där jag samlade diverse visitkort fick bli sjäva skalet. Ena högtalaren från hörlurar som jag tror härrör från en flygning får bli det som väcker mig. Det ska bara vara en knapp att trycka på, oavsett om man ska snooza, stänga av ringsignalen eller ställa in väckningstid.

Re: Deltids-väckarklocka

Postat: 19 februari 2016, 11:05:30
av BjörnO
Förutom Arduinon och displayen blev det en timerkrets med batteribackup, en lysdiod för att indikera att klckan är i snooze-mod och en transistorkrets som får driva högtalaren.
Knappen ska reagera på:
- klick, för att stänga av ringsignalen och för att stega fram när man ställer in väckningstiden
- dubbelklick för att stänga av ringsignalen och snooze
- lång klick (ett par sekunder) för att växla till nästa läge när man ställer in väckningstiden
- längre klick (>5 sekunder) för att växla mellan vanlig tidvisning och inställning av väckningstid

Re: Deltids-väckarklocka

Postat: 19 februari 2016, 11:08:30
av BjörnO
Den är färdig i en första fungerande version. Har använt den under veckan med min gamla väckarklocka som backup.

Re: Deltids-väckarklocka

Postat: 19 februari 2016, 12:10:36
av Icecap
Kul! "Man tager vad man haver..." Ett princip jag starkt gillar!

Re: Deltids-väckarklocka

Postat: 19 februari 2016, 16:08:12
av MiaM
Batteribackup/batteridrift?

En bekant påpekade att Arduino dumt nog använder några pinnar på "fel" sätt för att gå ned i maximal djupsömn. Men det är väl ändå så låg strömförbrukning (med släckt backlight på displayen) att ett batteri räcker några timmar?

P.S. om backlighten ska vara igång vid normaldrift så vill du nog ha röd, och en fotocell/fototransistor som känner av rummets ljusstyrka och styr displayens ljusstyrka.

Re: Deltids-väckarklocka

Postat: 19 februari 2016, 16:17:22
av Icecap
Jag läste "timerkrets med batteribackup" som "RTC med batteribackup" och tror att det nog rör sig om den standard DS1307 som finns i drösvis här och där.

Re: Deltids-väckarklocka

Postat: 19 februari 2016, 17:27:50
av MicaelKarlsson
BjörnO: Tjusig klocka!
Icecap skrev:Kul! "Man tager vad man haver..." Ett princip jag starkt gillar!
Kan bara instämma!!
MiaM skrev:En bekant påpekade att Arduino dumt nog använder några pinnar på "fel" sätt för att gå ned i maximal djupsömn. Men det är väl ändå så låg strömförbrukning (med släckt backlight på displayen) att ett batteri räcker några timmar?
Detta kanske kan vara intressant: , http://www.kevindarrah.com/download/ard ... rVideo.ino

Re: Deltids-väckarklocka

Postat: 19 februari 2016, 22:52:09
av BjörnO
Just det, där sitter en DS1307. Än så länge strömförsörjs min klocka med USB-laddare.
Nu när hårdvaran är klar blir det dags att vidareutveckla programmet. Displayen lyste för starkt så den får i alla fall sova. Ett tryck på knappen och den tänds en liten stund.
Klockan håller tiden även när övrigt är avstängt, men inställd tid försvinner. Alltså dags att lära sig hantera minnet i DS1307:an.

Re: Deltids-väckarklocka

Postat: 21 februari 2016, 01:46:45
av MiaM
Men DS1307 verkar inte ha någon alarm-utgång. Därmed försover man sig minst till strömavbrottets slut (eller man vaknar av sig själv) om det är strömavbrott vid ordinarie väckningstid.

En fulvariant är förstås att istället ordna så att väckning går igång på batteri direkt vid strömavbrott, så får man vakna till och ställa någon annan klocka på väckning. Osmidigt men fungerar.

Re: Deltids-väckarklocka

Postat: 22 februari 2016, 15:16:48
av BjörnO
Du har alldeles rätt. Det får fortsätta vara en nätdriven klocka, eventuellt med batteri-backup som håller den igång tills strömmen återkommit. Det får plats rätt mycket i lådan så det blir inget problem.
Ett problem däremot är hur man skriver/läser till minnesarean i DS1307. Jag förstår inte riktigt hur man ska göra det. Kan någon peka på kod som jag kan kopiera och klistra in i min kod så :D

Re: Deltids-väckarklocka

Postat: 22 februari 2016, 15:47:32
av BjörnO
Om någon är nyfiken på koden:

Jag använder dessa bibliotek:

Kod: Markera allt

#include <LiquidCrystal_I2C.h>
#include <DS1302RTC.h>
#include <Time.h>
#include <Wire.h>
#include <TimeAlarms.h>
Detta är min huvudrutin:

Kod: Markera allt

void loop() // Huvudflöde
{
    timeNow = millis();    // läs tiden varje varv
    if (status == 0)
    {
        visaTid();    // visa klockan
        keyAlarm();    // tangentrutin för snooze och stäng av
    }
    if (status == 1)
    {
        visaAlarm();    // visa väckningstid
        keySetting();    // tangentrutin för ställa in väckning
    }

    if ((alarm == 0) && (hh == hhSet && mm == mmSet && ss == 0) && (setdag != 0)) // larm på tid
    {
        delay (1000);    // setdag; avstängd = 0, vecka = 1, vardagar = 2, tredagars = 3
        if(setdag == 1) alarm = 2;
        if((setdag == 2) && (dd > 1) && (dd < 7)) alarm = 2;
        if((setdag == 3) && (dd > 2) && (dd < 6)) alarm = 2;
    }

    larmrutin(); // hantera larm

    if (timeNow > (timeKey + 60000)) lcd.noBacklight();
}
Vanlig tidvisning:

Kod: Markera allt

void visaTid() // rutin
{
    if (timeNow > (timeDisp + 1000)) // har det gått 1 s?
    {
        timeDisp = timeNow;
        // Display time centered on the upper line
        lcd.setCursor(1, 0);
        lcd.print("Time: ");
        print2digits(hour());
        lcd.print(":");
        print2digits(minute());
        lcd.print(":");
        print2digits(second());
        // Display abbreviated Day-of-Week in the lower left corner
        lcd.setCursor(0, 1);
        lcd.print(dayShortStr(weekday()));
        // Display date in the lower right corner
        lcd.setCursor(5, 1);
        lcd.print(" ");
        lcd.print(year());
        lcd.print("-");
        print2digits(month());
        lcd.print("-");
        print2digits(day());

        // Read and save time (weekday, hour, minute)
        dd = weekday(); // 1=söndag, 7=lördag
        hh = hour();
        mm = minute();
        ss = second();
    }
}

void print2digits(int number) // Output leading zero
{
    if (number >= 0 && number < 10)
    {
        lcd.write('0');
    }
    lcd.print(number);
}
Larmrutinen:

Kod: Markera allt

void larmrutin()
{
    if (alarm == 2)
    {
        digitalWrite(alarmPin, HIGH); // alarm
        if (timeNow > (beepTime + 5000))
        {
            tone(tonePin , 800, 1000); // pin, frequency, duration
            beepTime = timeNow;
        }

    }
    if (alarm == 1)      // snooze
    {
        if (timeNow > (snooze + 300000))
        {
            alarm = 2;
            digitalWrite (alarmPin, LOW);
        }
        else digitalWrite (alarmPin, HIGH);
    }
    if (alarm == 0) digitalWrite (alarmPin, LOW);       // off
}
Avkoda knapptryck:

Kod: Markera allt

void keyAlarm()
{
    buttonState = digitalRead(buttonPin);
    if (buttonState == LOW) // knapp tryckt
    {
        delay (10);
        lcd.backlight();
        if (timeread == 0)
        {
            timeKey = timeNow;
            timeread = 1;
        }
    }
    if (timeread == 1)
    {
        if (buttonState == HIGH) // knapp uppe
        {
            delay (10);
            timeread = 0;
            if (timeNow > (timeKey + 5000)) // väckningstid
            {
                status = 1;
//                timeread = 0;
                lcd.clear();
            }
            else if (alarm > 0)
            {
                if (timeNow > (timeKey + 100)) // klick = snooze, dubbelklick = off
                {
                    alarm = alarm - 1;
//                    timeread = 0;
                    snooze = timeNow;
                }
            }
        }
    }
}
Visa väckningstid på display:

Kod: Markera allt

void visaAlarm()
{
    lcd.setCursor(0, 0);
    lcd.print("Alarm: ");
    lcd.print(hhSet);
    lcd.print(":");
    lcd.print(mmSet);
    lcd.print(":");
    lcd.print("00");
    lcd.print(" ");
    lcd.print(setdag);

    lcd.setCursor(0, 1);
    lcd.print("Change");
    lcd.print(":");
}
Ställa in väckningstid:

Kod: Markera allt

void keySetting()
{
    buttonState = digitalRead(buttonPin);
    if (buttonState == LOW) // knapp tryckt
    {
        delay (10);
        lcd.backlight();
        if (timeread == 0)
        {
            timeKey = timeNow;
            timeread = 1;
        }
    }
    if (timeread == 1)
    {
        if (buttonState == HIGH) // knapp uppe
        {
            delay (10);
            if (timeNow > (timeKey + 5000)) // normal tidvisning
            {
                status = 0;
                timeread = 0;
                lcd.clear();
            }
            else if (timeNow > (timeKey + 2000)) // nästa pos
            {
                timeread = 0;
                setpos++;
                if (setpos >= 3) setpos = 0;
                // Display what to set
                lcd.setCursor(9, 1);
                if (setpos == 0) lcd.print("Day    ");
                if (setpos == 1) lcd.print("Hour    ");
                if (setpos == 2) lcd.print("Minute  ");
            }
            else if (timeNow > (timeKey + 100)) // bläddra
            {
                timeread = 0;
                if (setpos == 0) selectDay();
                if (setpos == 1) selectHour();
                if (setpos == 2) selectMinute();
            }
        }
    }
}


void selectHour()
{
    hhSet++;
    if (hhSet >= 25) hhSet = 1;
}

void selectMinute()
{
    mmSet = mmSet + 10;
    if (mmSet >= 60) mmSet = 00;
}
void selectDay()
{
    setdag;
    lcd.print(setdag);
    setdag ++;
    if (setdag >= 4) setdag = 0;
    lcd.setCursor(9, 1); // avstängd = 0, vecka = 1, vardagar = 2, tredagars = 3
    if (setdag == 0) lcd.print("Off     ");
    if (setdag == 1) lcd.print("Alldays ");
    if (setdag == 2) lcd.print("Weekdays");
    if (setdag == 3) lcd.print("Midweek ");
}

Re: Deltids-väckarklocka

Postat: 23 februari 2016, 00:32:08
av qx5
Om MCU:n sätts i "sleepmode" när det är elavbrott och t.ex väcks varje minut i några millisekunder så kan den aktivera alarmet även på batteri. Så mycket energi går det inte åt till det. Om man t.ex använder 10 W under 5 minuter för alarmljud så har man gjort av med 3 kJ. Ett standard R6 NiMH batteri på 2200 mAh rymmer 8,6 kJ. Med en liten blyackumulator får man kanske 25 kJ.

Så vid elavbrott släck bakgrundsbelysningen för det är den som förbrukar den största mängden energi och låt processorn gå i "sleepmode". Initiera uppväckning av processorn varje minut som varar i några millisekunder där den kontrollerar om larmet skall aktiveras den närmsta minuten. Om så är fallet så kvarstår den i aktivt läge och kanske förbrukar 16 mW i ström de minutrarna som larmet varar.

På detta sätt får du både väckning och batteritid oavsett om det finns elnät som fungerar.

Re: Deltids-väckarklocka

Postat: 23 februari 2016, 07:59:00
av Icecap
DS1307 kan ge ut en puls varje sekund.

Den kan användas som aktivering och µC'n kan då dels räkna upp tiden internt utan att behöva "prata" med RTC'n och dels kolla larm innan den går i sleep igen.

Detta kan bli en mycket strömsnål lösning och lägger man till lite koll av back-up spänning kan man även styra att displayen släcks ner helt osv.

Re: Deltids-väckarklocka

Postat: 23 februari 2016, 12:27:42
av Swech
Det går att göra det hela lite mer läsbart

Kod: Markera allt

if (timeread == 1)
Om du istället definierar
off = 0
on = 1

så blir det

Kod: Markera allt

if (timeread == on)
Koden blir lättare att läsa / underhålla

Swech