Arduino Projekten

Fri 19-Apr-24
12:26:40


KerstLicht

Datum: Thu 20 December 2018
Samenvatting: Een 4-kanaals Looplicht voor Kerstverlichting, met 2-staps Timer.


Al een paar jaar heb ik een dennestruik in de tuin staan en doe ik daar lichtjes in. Dit zijn van die standaard lichtsnoeren die op batterijen werken en die een timer in zich hebben. De lichtjes worden aangestuurd vanuit een kastje, waar de electronica in zit en waar de batterijen in gaan (bij mijn snoeren zijn dat 3 AA batterijen per snoer). En ik heb twee van die lichtsnoeren in de struik hangen. Ondertussen zijn de nadelen, die ik in die lichtsnoeren zie, groter dan het gemak die ik erin zag, zoals:
  • De manier waarop de batterijen erin gedaan moeten worden. Dit gaat met schroefjes en na enkele jaren raak je ze kwijt (ze vallen en je vind ze niet meer terug in de tuin-aarde).
  • Het timer-systeem op zich werkt wel leuk, het kent maar 1 periode (van 6 uren lang) van activiteit. Daarna gaat het lichtsnoer uit en 18 uur later wordt het weer aktief. Dit wordt elke 24-uur herhaald.
  • De timer-cyclus wordt pas gestart wanneer je op de startknop duwt.
  • Het minst wegend nadeel is dat ik ze altijd in plastic zakjes doe, om weersinvloeden (regen, sneeuw) zo weinig mogelijk invloed erop te hebben. Maar ... het weer slaat wel toe in de besturingen (o.a. de schroefjes worden roestig).
  • PLUS als de batterijen leeg zijn, moeten de kastjes weer worden opengeschroefd, om de batterijen te verversen. Daarna moeten de timers weer opnieuw worden geactiveerd.

Batterijen eruit, Netvoeding "erin".

Tegenwoordig zijn er van die adapters (3V en 4.5V) te koop, met opvulstukjes, die in de plaats van de batterijen gaan. Maar de praktijk leert dat de tussenliggende kabel tussen de adapter en de opvulstukken te kort is voor naar de tuin. De oplossing die ik zag, was het verlengen van de kabel.

En dan kom je erachter dat de kabel zelf te dun is om de twee lichtsnoeren van voldoende energie te voldoen. Ik kan 1 lichtsnoer aan laten gaan, maar zodra ik het tweede lichtsnoer activeer, gaat er zoveel stroom door de kabel heen, dat de spanningsval over de kabel te groot wordt om beide lichtsnoeren voldoende spanning te kunnen geven. Resultaat: de beide lichtsnoeren gaan uit - of te wel, dit werkt niet.

Volgende oplossing was een losse tuin-transformator (12V) en deze via een lange kabel naar een losse 5V-stabilisator te laten gaan. De trafo gaat binnenshuis in het stopkontakt, de 5V stabilisator komt bij de lichtsnoeren in de buurt te hangen.

Op zich voldoet deze oplossing wel, MAAR er zit iets niet lekker in het geheel. Een paar dagen doen de timers het goed en opeens worden ze niet meer geactiveerd. En dan moet je weer naar buiten om op het knopje van de aanstuurkastjes te drukken.

Of te wel, ook dit idee werkt niet.

Een eigen aansturing maken.

Dan komt de volgende oplossing. Zelf een aansturing bouwen - bijvoorbeeld met een Arduino. Hiermee kan ik dan meteen enkele andere nadelen van de eerder gekochte lichtsnoeren oplossen.

Zodra de Arduino van stroom wordt voorzien, wordt deze meteen geaktiveerd. Als er dan een timer-storing zou zijn, is het voldoende om de stroom er even af te halen en weer op te zetten ... En de boel knippert weer.

De aktiviteits-periode.

Hebben de gekochte lichtsnoeren maar 1 aktiviteitsperiode, nu bouw ik er twee in. Want wanneer zijn de lichtjes aan? Bij de gekochte snoeren is dat op het moment dat je op het knopje duwt, meestal rond 16:30hr wanneer de duisternis eind van de middag invalt. 6 uur later, rond 22:30hr zijn ze weer donker. Ga je de volgende ochtend weg, dan is de boel ook donker. Dus worden er 2 periodes van aktiviteit mee programmeren.

Het aantal kanalen aan lichtjes.

Mijn lichtsnoeren hebben maar 2 kanalen aan lichtjes, terwijl er vroeger systemen waren met 4 kanalen. Met tegenwoordig de miniarisatie in allerlei micro besturingen, zijn er te weinig pinnen om meer dan 2 kanalen aan te sluiten. Ik programmeer er 4 kanalen op. In de toekomst moet dit uit te breiden zijn naar 8 kanalen. Er zitten pinnen zat op, op de Arduino.

En dan de lichtjes zelf. Een idee is om zelf alle Leds in snoeren te solderen. Een klus dat veel werk is en waarbij alle Led-solderingen spatwater-dicht moeten worden gemaakt.

Echter vooral vlak voor (en na) de kerstdagen wordt kerstverlichting met grote kortingen verkocht (tot 35%). De winkeliers willen toch van de handel af. Wat is er dan makkelijker om in die periode 4 lichtsnoeren te kopen (gevoed door batterijen (plus eventueel een timer)) en dan het batterij gedeelte af te knippen. Via een transistor (of een MosFet) moeten de nieuwe lichtsnoeren aan te sturen zijn met een Arduino. En TaRaaa, een eigen lichtsnoer is gemaakt.

Weersinvloeden.

Alleen met een goede behuizing en (siliconen)kit moet de boel aardig (spat)water dicht te maken zijn. Dan zijn er vast nog plastic zakjes nodig, maar dan moet het ook werken vanuit een adapter (of tuin-trafo).

Het programma - De Eisen.

In het kort zijn de eisen dus:

  • 4 lichtkanalen - dus 4 losse LedSnoeren.
  • Timer-funktie met 2 periodes van activiteit.
  • Een Patronen-deel die gemakkelijk is uit te breiden.

Er is begonnen met een eenvoudig looplicht. 4 keer 2 Leds in serie, die keurig in een rijtje staan van [12341234]. Dit rijtje werd eerst als binaire teller aangestuurd. Je moet ergens mee beginnen.

Het Programma - De Timer.

Daarna werd de timer geprogrammeerd. De Arduino heeft een (zogenoemde) timer in zich, die op vaste tijdstippen een interrupt kan geven. Om het eenvoudig te houden, is gekozen om elke seconde een interrupt te laten geven. Via de interrupt-routine wordt software-matig een teller opgehoogd - er worden dus secondes geteld.

De Arduino werkt zelf op een frequentie van 16MHz. Door de voor-deler (pre-scaler) op 1024 te zetten (%101 in het register TCCR1B, op de bitjes CS12, CS11 en CS10)) en de teller-startwaarde op "15625" (OCR1A) (met de functie InitIrq()), worden de interrupts keurig met 1 Hz opgewekt.

In de loop van dit project heeft de Seconde-Teller enkele constantes gekregen om de boel te initialiseren en te regelen. De Teller houdt secondes bij, dus alle constantes moeten ook in secondes worden opgegeven. In plaats van constantes om te rekenen naar secondes, wordt in het programma het aantal uren opgegeven vermenigvuldigd met 3600 (het aantal secondes in een uur). Deze vermenigvuldigingen zijn boven in het programma duidelijk te zien. De constante-benamingen zijn:

  1. TimerSecondes: Dit is de eigenlijke seconde-teller.
  2. TimerInit: Deze waarde wordt in de Teller geladen op het moment van aanzetten. In het programma staat deze op 16*3600, of te wel we doen net alsof hij om 16:00hr begint.
  3. TimerStart: Deze heeft de waarde 0 (hoe kan dat ook anders) en deze waarde wordt in de Teller geladen op het moment dat hij het maximum bereikt.
  4. TimerReset: Zodra de Teller deze waarde bereikt, wordt hij terug gezet naar de Start-waarde van 0. De Reset-waarde is 24*3600, of te wel 24-uren aan secondes.
  5. TimerTrig1 .. TimerTrig4: Dit betreft 4 afzonderlijke Trigger waardes, die elk op een "tijdstip" staan. In het eerste programma zijn dit de waardes (1) 5*3600 = Aan, (2) 9*3600 = Uit, (3) 16*3600 = Aan en (4) 23*3600 = Uit. De uur-waardes zijn er nu eenvoudig uit te halen.

Als voorlopige extra laat ik de Teller gaan naar de 16-Leds die ik op de voorkant van mijn Arduino experimenteer-kastje heb zitten. Eerst in Binair-formaat, maar nu als Bcd laat ik hier de inhoud van de Teller zien in Uren en Minuten (met de functies Timer2Bcd() en ShiftLeds()) (zie schema, linker helft).

Voor test-doeleindes kan ik de interrupt-frequentie verhogen door een extra deling op de teller-startwaarde (OCR1A) te verrichten. Dit verklaart de deling in de regel "15625 / 1".

Het Programma - Aktiviteit-periode.

Door de Teller-waarde te vergelijken met de 4 Trigger-waardes, is vast te stellen of het Looplicht aktief moet zijn, of niet. Een meervoudige If-Then-Else Statement gaat deze toestand af in de functie CheckActive(). Hierbij is het wel zaak dat de laagste Trigger variabele ook echt de laagste waarde heeft.

Als extra wordt de ingebouwde Led op Pin 13 gebruikt om de toestand van de activiteit aan te geven. Aktief is Aan, Niet-Aktief is Uit. Op mijn experimenteer-kastje heb ik ook de grote blauwe Led op deze Pin 13 gezet.

Het Programma - De Lampen, c.q. LedSnoeren.

De pinnen die de Lampen/ LedSnoeren moeten aansturen, worden door de functie LampOutput() bediend. 4 losse If-Then statements testen de afzonderlijne bits en sturen hiermee de 4 losse pinnen aan.

Deze functie is uit te breiden dat er 8 pinnen aangestuurd kunnen worden - en dus 8 kanalen kunnen worden bediend.

Wanneer dan hele LedSnoeren aan elkaar bevestigd zijn, met de Leds keurig achter elkaar, dan ontstaat er echt een heel snoer met de volgorde [12341234123412341234123412341234].

Het Programma - De Patronen in een eigen Library.

Om het programma zelf overzichtelijk te houden, zijn de LoopLicht patronen in een grote Array gezet en in een eigen Library geplaatst, genaamd "Patterns.cpp" en "Pattern.h".

Het array zelf verandert niet qua inhoud, daarom is hier gekozen om het array in het programma geheugen te zetten. Dit is te herkennen aan de term "PROGMEM" in de Library. Een tweede reden hiervoor is ook, dat het programma-geheugen meer plaats heeft (32kB) dan het variabele geheugen (2kB). Een gevolg hiervan is het gebruik van de funktie "pgm_read_byte_near()" in het "loop()" gedeelte van het hoofdprogramma.

Ook is het array een recht-toe recht-aan 2-dimensionaal Array. De patronen hebben allemaal het zelfde aantal stappen en elke regel (in de Library) bevat 1 patroon. Hiermee is al een behoorlijk aantal patronen aan te brengen, zoals:

  • Een Lamp aanzetten en deze echt alle 4 de kanalen af laten gaan. Het echt schuif-register looplicht, binair: [---x] [--x-] [-x--] [x---].
  • De lampen wisselend aan en uit laten gaan, binair: [-x-x] [x-x-] of [xx--] [--xx].
  • Diverse variaties hierop, al of niet met extra pauzes dat alles uit is (binair [----]).

Het Programma - De Init() en de Loop().

De initialisatie zet diverse indexen (Idx) op nul, zet de diverse pinnen op output en initialiseert de interrupt funktie InitIrq().

Na het testen met binaire waardes op de Looplicht-Leds wordt het tijd om de patronen uit een tabel te halen en aar de Leds te sturen. De Loop() zorgt hiervoor, inclusief het controleren of het LoopLicht aktief moet wezen en de vertraging tussen de LoopLicht stappen.

De patronen worden een aantal keren herhaal, voordat er een ander patroon wordt gekozen. Dit kiezen gaat via een Random()-functie ... hoewel het afwachten is hoe Random het Random is. Maar een voorbijganger buiten zal hier vast geen enkele aandacht aan besteden.

Patroon-uitbreiding.

Ondertussen is ook het aantal patronen uitgebreidt tot 24 stuks, inclusief binair tellen en gray-codes - bij elkaar zijn dit (maar) 384 bits. Wat wel prettig is om te weten, is dat er nog zo'n 29-duizend stappen bij kunnen (75 keer zoveel als nu gebruikt wordt). Er is dus ruimte genoeg voor creativiteit.

  • Toekomst idee 1) zou kunnen zijn om patronen van een wisselende lengte te kunnen gebruiken, waarbij een tweede array de indexen kan bevatten waar elk patroon begint (en dus het vorige patroon eindigt). Er zou dan zelfs de woorden "Vrolijk Kerst" in morse geknipperd kunnen worden.

  • Toekomst idee 2) zou kunnen zijn om de patronen in een 16-bits array te zetten, waarbij een tijdsduur ingegeven kan worden. Het aantal patroon-stappen wordt dan ongeveer maximaal 14.000 stuks.

  • Toekomst idee 3) zou kunnen zijn om de patronen in een 32-bits array te zetten, waarbij de bits (per kanaal) een helderheid aangeven om dan de LedSnoeren (bijvoorbeeld) via Binaire Modulatie aan sturen. Dit laatste vereist wel een uitbreiding van de interrupt routine. Het aantal patroon-stappen wordt dan ongeveer maximaal 7.000 stuks.

    De LedSnoer aansturing.

    Om een LedSnoer aan te kunnen sturen, is er eerst onderzoek nodig op het LedSnoer om te weten hoeveel stroom een LedSnoer verbruikt en wat voor spanning er over staat. Op de doos stond niets over knipperen, dus werd het een questie van batterijen erin doen en de multimeter erbij pakken. Het stroomverbruik is (bij 100Leds) 45mA, terwijl er een spanningsval van 2.8V is. Tevens blijkt dat alle Leds in het Snoer parallel staan. Er waren geen derde-draden in het snoer te zien, wat er zou moeten zijn bij serie-schakeling van de Leds.

    Als aansturing is er eerst gedacht om een MosFet te gebruiken om een snoer aan en uit te schakelen. Maar met een stroom van maar 50mA (iets minder) is een standaard TUN (BC547) ook te gebruiken. Weerstanden erom (bij T1 is dat R1 en R2) en testen maar. En het voldoet. Nog iets aanpassen van een weerstand (R2) en dit deel is klaar. Er is zelfs nog een handige controle-Led erbij gekomen (D1).

    En toen bedacht ik me dat er alleen maar een AC-voedingslijn aanwezig was (want het is de tuin-trafo). Dus moet er nog een (brug)gelijkrichter met een afvlak elko op de print komen. Deze moet de Arduino dan rechtstreeks voeden op de adapter konnector.

    Daarna was het zoeken naar een behuizing ... tot ik mij bedacht dat het wellicht in een (buiten-)lasdoos zou passen. Met twee-componenten lijm werden twee schroeven vastgelijmd en (na het uitharden) de Arduino werd er in geschroefd.

    De LedSnoeren Tie-wrappen en aansluiten.

    Dan komt het saaiste gedeelte van dit project. Dat is niet het losknippen van een snoer met de oorspronkelijke besturing geweest, maar het samen binden van de 4 LedSnoeren. Elk snoer is 7.5meter lang en heeft 100 Leds. Na 3 uren is ook deze klus geklaard en zijn er zo'n 200 Tie-wraps gebruikt.

    Er werd uitgezocht welke draden van dit nieuwe LedSnoer voor welke Leds zijn, of te wel het bepalen van Lamp 1 t/m Lamp 4. De draden van het nieuwe LedSnoer werden aangesloten op de besturingsprint en de Arduino werd opgestart. Et voila ... wat een mooi effect, 400 vrolijk knipperende Leds.

    De laatste afwerking.

    Als laatste moet het doorvoergat van de lasdoos, waar de draden door naar buiten gaan, worden dichtgekit. Ophangen in de dennestruik en activeren, net op tijd om de kerstdagen knipperend door te komen.

    Van een afstand is aan de lijn-van-licht echt de vorm van het snoer te zien. Ook zijn de knipper-effecten spectaculairder dan van de oude twee losse snoertjes. 4 kanalen geeft immers meer mogelijkheden dan 2 x 2 kanalen (die vlak na elkaar hetzelfde patroon afspelen)..

    Op de foto's is te zien dat de oude verlichting nog in de struik hangt. Deze zijn als eerste in de struik geplaatst en de rest "ligt" er bovenop.

    En na ruim 2 weken werkt het nog steeds zoals gepland, ook de ochtend cyclus.

    Programma werking.

    De afgelopen jaren is de volgorde nu als volgt. Eerst slinger ik de lichtjes door de bomen in de tuin. Vervolgens sluit ik, via een lang stuk 220V tweeling-snoer de tuin-trafo binnens huis aan. Met een standaard kroonsteen sluit ik de kerstverlichting aan op het tweeling-snoer. Rond 16:00 uur trek ik de tuin-trafo even uit het stopkontakt en doe hem er weer in. Op dat moment start de Arduino besturing de tijd-telling, te beginnen bij 1600 uur (constante TimerInit).

    Bij de telling van 2300 uur (constante TimerTrig4) dooft de verlichting, maar de tijd-telling gaat verder. Zodra deze het tijdstip 2400 uur (constante TimerReset) heeft bereikt, gaat de tijd-telling naar 0000 uur (middernacht) (constante TimerStart). Om 0500 uur (constante TimerTrig1) beginnen de lichtjes weer te knipperen, leuk als je met ochtend-dienst de deur uitgaat. Heeft de tijd-telling de stand van 0900 uur (constante TimerTrig2) bereikt, dan stopt het knipperen weer. Er is dan meestal alweer daglicht. En om 1600 uur (constante TimerTrig3) begint dit weer van voren af aan.

    Wanneer de Arduino pas om 16:30hr spanning krijgt, ook dan denkt de Arduino dat het 16:00hr is. De bovengenoemde tijdstippen zullen dan ook een half uur later (in echte tijd) plaats vinden.

    De werking na enkele jaren.

    In het najaar is de dennenstruik uit de tuin gegaan en is er op die plaats een (langzaam groeiende) kerstboomje gepland. Met kerst 2019, 2020 heeft deze kerstverlichting ook gewerkt.

    En met kerst 2021 werkt het nog steeds. Zonder enige verandering aan de verlichting en besturing ... en zonder herprogrammering.


    Broncode: [1: KerstLicht] [2: De Patroon Library (.CPP)] [3: De Patroon Library (.H)]

    1: De broncode van KerstLicht

    (Thu 20 December 2018) Het Hoofdprogramma "KerstLicht.Ino"

    Deze broncode heeft 242 regels met programma-code.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    // -----------------------------------------------------------------------------
    // KerstLicht
    //
    // A Christmas Light Controller for 4 Lamps with 2 Periods of Activity
    //
    // -----------------------------------------------------------------------------

    //--------[ Needed Include Files ] -------------------------------------------

    // Include the Lamp Patterns
    #include "e:\arduino\KerstLicht\Patterns.h"

    // Next line is needed for PROGMEM and pgm_read_byte_near-function
    #include <avr/pgmspace.h>

    //==============================================================================
    // Some Seconde Timing Values
    const long TimerInit  = 16L * 3600L; // Initialize Value for the TimerSecondes
    const long TimerTrig1 =  5L * 3600L; // Trigger 3 Value for the TimerSecondes
    const long TimerTrig2 =  9L * 3600L; // Trigger 4 Value for the TimerSecondes
    const long TimerTrig3 = 16L * 3600L; // Trigger 1 Value for the TimerSecondes
    const long TimerTrig4 = 23L * 3600L; // Trigger 2 Value for the TimerSecondes
    const long TimerStart =  0L;         // Start Value for the TimerSecondes
    const long TimerReset = 24L * 3600L; // Reset Value for the TimerSecondes ( 86'400sec/day)
    long volatile TimerSecondes    =  0L;         // Seconde Teller, which increases by Interupt (per seconde).

    // Idxxes to the patterns
    word IdxPattern        =  0; // Idx for the Pattern to show
    word IdxTimes          =  0; // Number of Times to repeat the Pattern
    word IdxStep           =  0; // Step Number in the Pattern
    // Some Lamp Output vars
    byte LampValue         =  0; // Temp Var for the Lamp Value
    const byte Lamp1       =  9; // Lamp 1
    const byte Lamp2       = 10; // Lamp 2
    const byte Lamp3       = 11; // Lamp 3
    const byte Lamp4       = 12; // Lamp 4

    // Some Led-Shift
    byte DataPin  =  2; // Data  (74HC595)
    byte ClockPin =  3; // Clock (74HC595)
    byte LatchPin  = 4; // Latch (74HC595)

    //==============================================================================
    //== Setup and Loop                                                           ==
    //==============================================================================

    void setup()
    { // Serial.begin(115200);              //////////////////////////////////////////
      // Set the Pattern Index to the begin
      IdxPattern = 0;
      IdxStep    = 0;
      // Set A1 to Input, because the signal will be used
      // to seed the Random(), for selecting a new Pattern.
      pinMode(A1, INPUT);
      randomSeed(analogRead(0));
      IdxPattern = random(0, MaxPattern);

      // Set Lamp-Pins to Output
      pinMode(Lamp1, OUTPUT);
      pinMode(Lamp2, OUTPUT);
      pinMode(Lamp3, OUTPUT);
      pinMode(Lamp4, OUTPUT);

      // Set Led-Shift to Output
      pinMode(DataPin , OUTPUT);
      pinMode(ClockPin, OUTPUT);
      pinMode(LatchPin, OUTPUT);

      // Set Activity Led to Output
      pinMode(13, OUTPUT);
      TimerSecondes = TimerInit;
      InitIrq();
    }

    void loop()
    { // Output the value of TimerSecondes
      ShiftLeds( Timer2Bcd(TimerSecondes) );
      // Check if the Lights must be active.
      if (CheckActive() != 0)
         { // Active => Do Some Lamp Stuff
           LampValue = pgm_read_byte_near( &LampPatterns[IdxPattern][IdxStep] );
           LampOutput(LampValue);
           // Increase IdxStep
           IdxStep    = IdxStep    + 1;
           if (IdxStep    == MaxStep   )
              { // If Max, Then Reset
                IdxStep    = 0;
                // Do it One more time
                IdxTimes = IdxTimes + 1;
                if ( IdxTimes == MaxTimes)
                   { // Reset Number of Times
                     IdxTimes = 0;
                     // Select the next IdxPattern
                     IdxPattern = random(0, MaxPattern);
                   }
              }
         }
      else
      { // Not Active => No Lamps, No Patterns
        LampOutput(0x00);
      }
      delay(213);

    }

    //==============================================================================
    // Some Functions to handle stuff
    //==============================================================================

    void LampOutput (byte LampOut)
    { // Do Lamp 1
      if ((LampOut & 0x01) == 0)
         { digitalWrite(Lamp1, LOW);
         }
      else
         { digitalWrite(Lamp1, HIGH);
         }
      // Do Lamp 2
      if ((LampOut & 0x02) == 0)
         { digitalWrite(Lamp2, LOW);
         }
      else
         { digitalWrite(Lamp2, HIGH);
         }
      // Do Lamp 3
      if ((LampOut & 0x04) == 0)
         { digitalWrite(Lamp3, LOW);
        }
      else
         { digitalWrite(Lamp3, HIGH);
         }
      // Do Lamp 4
      if ((LampOut & 0x08) == 0)
         { digitalWrite(Lamp4, LOW);
         }
      else
         { digitalWrite(Lamp4, HIGH);
         }
    }

    //==============================================================================

    void ShiftLeds (word value)
    { // Show Value of a word
      digitalWrite(LatchPin, LOW );  // Latch = Low, to Freeze the Value
      shiftOut    (DataPin, ClockPin, MSBFIRST, value >> 8);     // Sent the Value
      shiftOut    (DataPin, ClockPin, MSBFIRST, value & 0x00FF); // Sent the Value
      digitalWrite(LatchPin, HIGH);  // Latch = High, to Send the Value thru
    }

    //==============================================================================

    byte CheckActive ()
    { // Show if Active, or not (on pin 13)
      byte BeActive = 0;
      if (TimerSecondes < TimerTrig1)
         { // Periode 1 = Not Active
           BeActive = 0;
         }
      else if (TimerSecondes < TimerTrig2)
         { // Periode 2 = Active
           BeActive = 1;
         }
      else if (TimerSecondes < TimerTrig3)
         { // Periode 3 = Not Active
           BeActive = 0;
         }
      else if (TimerSecondes < TimerTrig4)
         { // Periode 4 = Active
           BeActive = 1;
         }
      else
         { // Periode 5 = Not Active
           BeActive = 0;
         }

      if (BeActive == 0)
         { digitalWrite(13, LOW);
         }
      else
         { digitalWrite(13, HIGH);
         }
      return BeActive;
    }

    //==============================================================================

    word Timer2Bcd (long daytime)
    { word hrs  = 0;
      word mins = 0;
      word b0 = 0;
      word b1 = 0;
      word b2 = 0;
      word b3 = 0;

      // Split Daytime into Hours and Minutes
      hrs  = daytime / 3600;
      mins = daytime % 3600;
      mins = mins / 60;
      // Convert Hours into BCD
      b0 = hrs / 10;
      b1 = hrs % 10;
      // Convert Minutes into BCD
      b2 = mins / 10;
      b3 = mins % 10;

      return ((((b0 << 4) + b1) << 4) + b2) << 4) + b3;
    }

    //==============================================================================
    //==  Interupt Init                                                           ==
    //==============================================================================

    void InitIrq()
    { // Initialize Timer1 in the Arduino
      cli();                        // Disable Interrupts
      // Timer Counter Control Registers 1A & 1B
      TCCR1A = 0;                   // Make all bits of this register to 0
      TCCR1B = 0;                   // Make all bits of this register to 0

      OCR1A = 15625 / 1;                // set Output Compare Register 1 to the desired timer count
      TCCR1B = TCCR1B | B00001000;  // turn on CTC mode (WGM12 = bit 3 - Waveform Generation Mode)
      TCCR1B = TCCR1B | B00000101;  // Set the Prescaler (CS12 CS11 CS10 = bit 2..0 - Clock Select)

      TIMSK1 = TIMSK1 | B00000010;  // set Timer Interupt MaSK 1 to compare interrupt
      // (OCIE1A = bit 1 - Output Compare match Interrupt Enable 1A)
      sei();                        // Enable Interrupts
    }

    //==============================================================================
    //==  [ The Interupt Function ]                                               ==
    //==============================================================================

    ISR(TIMER1_COMPA_vect)
    // De Interrupt Service Routine
    // The main interupt-routine. Do one count ...
    { TimerSecondes = (TimerSecondes + 1L);
      if (TimerSecondes == TimerReset)
         { TimerSecondes = TimerStart;
         }
    }


    Broncode: [1: KerstLicht] [2: De Patroon Library (.CPP)] [3: De Patroon Library (.H)]

    2: De broncode van De Patroon Library (.CPP)

    (Thu 20 December 2018) De bijbehorende "Pattern.Cpp"-file is leeg, de library bevat geen eigen functies.

    Deze broncode heeft 19 regels met programma-code.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    //------------------------------------------------------------------------------
    // KerstLicht
    //
    // The Lamp Patterns
    //------------------------------------------------------------------------------

    #ifndef PATTERNS_CPP
    #define PATTERNS_CPP

    // Include some Libraries
    //#include "Arduino.h"
    #include "Patterns.h"
    // #include "e:\arduino\KerstLicht\Patterns.h"

    //==============================================================================
    // This Library contains only array's.
    // All array's are in the Header-file.
    //==============================================================================


    Broncode: [1: KerstLicht] [2: De Patroon Library (.CPP)] [3: De Patroon Library (.H)]

    3: De broncode van De Patroon Library (.H)

    (Thu 20 December 2018) De Patroon Library "Pattern.H" bevat alle patronen van het Kerstlicht. Geen ingewikkelde berekeningen, maar een uitgebredie verzameling van eenvoudige Bit"map" patronen van 4-bits breed.

    Deze broncode heeft 51 regels met programma-code.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    //------------------------------------------------------------------------------
    // KerstLicht
    //
    // The Lamp Patterns
    //------------------------------------------------------------------------------

    #ifndef PATTERNS_H
    #define PATTERNS_H

    #include "Arduino.h"
    // Next 2 lines are needed for PROGMEM and pgm_read_byte_near-function
    #include <avr/io.h>
    #include <avr/pgmspace.h>

    //==============================================================================
    // Lamp Patterns
    //==============================================================================

    const word MaxTimes   =  8 ; // Max number of Times to repeat a Pattern
    const word MaxPattern = 24 ; // Max Number of Patterns in the Array
    const word MaxStep    = 16 ; // Max Number of Steps in a Pattern (in the Array)
    static const byte LampPatterns [MaxPattern][MaxStep] PROGMEM = // = [000..max][00..max]
                 { //  0    1    2    3      4    5    6    7      8    9    A    B      C    D    E    F        Pattern
                   { 0x01,0x02,0x04,0x08 , 0x01,0x02,0x04,0x08 , 0x01,0x02,0x04,0x08 , 0x01,0x02,0x04,0x08 } , //  01
                   { 0x05,0x00,0x0A,0x00 , 0x05,0x00,0x0A,0x00 , 0x05,0x00,0x0A,0x00 , 0x05,0x00,0x0A,0x00 } , //  02
                   { 0x03,0x00,0x0C,0x00 , 0x03,0x00,0x0C,0x00 , 0x03,0x00,0x0C,0x00 , 0x03,0x00,0x0C,0x00 } , //  03
                   { 0x01,0x03,0x07,0x0F , 0x0E,0x0C,0x08,0x00 , 0x01,0x03,0x07,0x0F , 0x0E,0x0C,0x08,0x00 } , //  04
                   { 0x00,0x01,0x02,0x04 , 0x08,0x09,0x0A,0x0C , 0x09,0x03,0x05,0x09 , 0x01,0x02,0x04,0x08 } , //  05
                   { 0x09,0x03,0x06,0x0C , 0x09,0x03,0x06,0x0C , 0x09,0x03,0x06,0x0C , 0x09,0x03,0x06,0x0C } , //  06
                   { 0x0F,0x00,0x0F,0x00 , 0x0F,0x00,0x0F,0x00 , 0x0F,0x00,0x0F,0x00 , 0x0F,0x00,0x0F,0x00 } , //  07
                   { 0x05,0x0A,0x05,0x0A , 0x05,0x0A,0x05,0x0A , 0x05,0x0A,0x05,0x0A , 0x05,0x0A,0x05,0x0A } , //  08
                   { 0x03,0x0C,0x03,0x0C , 0x03,0x0C,0x03,0x0C , 0x03,0x0C,0x03,0x0C , 0x03,0x0C,0x03,0x0C } , //  09
                   { 0x0E,0x0D,0x0B,0x07 , 0x0E,0x0D,0x0B,0x07 , 0x0E,0x0D,0x0B,0x07 , 0x0E,0x0D,0x0B,0x07 } , //  10
                   { 0x00,0x0F,0x00,0x0F , 0x00,0x0F,0x00,0x0F , 0x00,0x0F,0x00,0x0F , 0x00,0x0F,0x00,0x0F } , //  11
                   { 0x00,0x0F,0x00,0x0F , 0x00,0x00,0x0F,0x0F , 0x0F,0x0F,0x0F,0x0F , 0x00,0x00,0x00,0x00 } , //  12
                   { 0x03,0x0C,0x00,0x00 , 0x0C,0x03,0x00,0x00 , 0x03,0x0C,0x00,0x00 , 0x0C,0x03,0x00,0x00 } , //  13
                   { 0x09,0x00,0x06,0x00 , 0x09,0x00,0x06,0x00 , 0x09,0x00,0x06,0x00 , 0x09,0x00,0x06,0x00 } , //  14
                   { 0x09,0x06,0x09,0x06 , 0x09,0x06,0x09,0x06 , 0x09,0x06,0x09,0x06 , 0x09,0x06,0x09,0x06 } , //  15
                   { 0x08,0x04,0x02,0x01 , 0x08,0x04,0x02,0x01 , 0x08,0x04,0x02,0x01 , 0x08,0x04,0x02,0x01 } , //  16
                   { 0x00,0x01,0x03,0x05 , 0x06,0x0A,0x0C,0x08 , 0x00,0x01,0x03,0x05 , 0x06,0x0A,0x0C,0x08 } , //  17
                   { 0x01,0x02,0x04,0x08 , 0x08,0x04,0x02,0x01 , 0x01,0x02,0x04,0x08 , 0x08,0x04,0x02,0x01 } , //  18
                   { 0x01,0x02,0x05,0x0A , 0x04,0x08,0x00,0x00 , 0x01,0x02,0x05,0x0A , 0x04,0x08,0x00,0x00 } , //  19
                   { 0x01,0x02,0x04,0x09 , 0x02,0x04,0x08,0x00 , 0x01,0x02,0x04,0x09 , 0x02,0x04,0x08,0x00 } , //  20
                   { 0x05,0x00,0x05,0x00 , 0x0A,0x00,0x0A,0x00 , 0x05,0x00,0x05,0x00 , 0x0A,0x00,0x0A,0x00 } , //  21
                   { 0x00,0x01,0x02,0x03 , 0x04,0x05,0x06,0x07 , 0x08,0x09,0x0A,0x0B , 0x0C,0x0D,0x0E,0x0F } , //  22
                   { 0x00,0x01,0x03,0x02 , 0x06,0x07,0x05,0x04 , 0x0C,0x0D,0x0F,0x0E , 0x0A,0x0B,0x09,0x08 } , //  23
                   { 0x00,0x00,0x00,0x00 , 0x0F,0x0F,0x0F,0x0F , 0x00,0x00,0x00,0x00 , 0x0F,0x0F,0x0F,0x0F }   // Last
                 };

    //==============================================================================


    Broncode: [1: KerstLicht] [2: De Patroon Library (.CPP)] [3: De Patroon Library (.H)]
  • Afbeeldingen

    kerstlicht_01-lichtsnoer.jpg
    1/33: kerstlicht_01-lichtsnoer.jpg.
    kerstlicht_02-lichtsnoer.jpg
    2/33: kerstlicht_02-lichtsnoer.jpg.
    kerstlicht_03-lichtsnoer.jpg
    3/33: kerstlicht_03-lichtsnoer.jpg.
    kerstlicht_04-stabilisator-schema.jpg
    4/33: kerstlicht_04-stabilisator-schema.jpg.
    kerstlicht_05-stabilisator-print.jpg
    5/33: kerstlicht_05-stabilisator-print.jpg.
    kerstlicht_06-print-gebouwd.jpg
    6/33: kerstlicht_06-print-gebouwd.jpg.
    kerstlicht_07-print-in-plastic.jpg
    7/33: kerstlicht_07-print-in-plastic.jpg.
    kerstlicht_08-aansturingen.jpg
    8/33: kerstlicht_08-aansturingen.jpg.
    kerstlicht_09-struik_in_duisternis.jpg
    9/33: kerstlicht_09-struik_in_duisternis.jpg.
    kerstlicht_10-controle-leds.jpg
    10/33: kerstlicht_10-controle-leds.jpg.
    kerstlicht_11-looplicht.jpg
    11/33: kerstlicht_11-looplicht.jpg.
    kerstlicht_12-looplicht.jpg
    12/33: kerstlicht_12-looplicht.jpg.
    kerstlicht_13-metingen.jpg
    13/33: kerstlicht_13-metingen.jpg.
    kerstlicht_14-schema.jpg
    14/33: kerstlicht_14-schema.jpg.
    kerstlicht_15-print.jpg
    15/33: kerstlicht_15-print.jpg.
    kerstlicht_16-soldeer.jpg
    16/33: kerstlicht_16-soldeer.jpg.
    kerstlicht_17-gebouwd.jpg
    17/33: kerstlicht_17-gebouwd.jpg.
    kerstlicht_18-soldeer.jpg
    18/33: kerstlicht_18-soldeer.jpg.
    kerstlicht_19-op-arduino.jpg
    19/33: kerstlicht_19-op-arduino.jpg.
    kerstlicht_20-behuizing.jpg
    20/33: kerstlicht_20-behuizing.jpg.
    kerstlicht_21-behuizing.jpg
    21/33: kerstlicht_21-behuizing.jpg.
    kerstlicht_22-vier-snoeren.jpg
    22/33: kerstlicht_22-vier-snoeren.jpg.
    kerstlicht_23-tie-wraps.jpg
    23/33: kerstlicht_23-tie-wraps.jpg.
    kerstlicht_24-tie-wraps.jpg
    24/33: kerstlicht_24-tie-wraps.jpg.
    kerstlicht_25-werkend.jpg
    25/33: kerstlicht_25-werkend.jpg.
    kerstlicht_26-werkend.jpg
    26/33: kerstlicht_26-werkend.jpg.
    kerstlicht_27-klaar.jpg
    27/33: kerstlicht_27-klaar.jpg.
    kerstlicht_28-in-struik.jpg
    28/33: kerstlicht_28-in-struik.jpg.
    kerstlicht_29-in-struik.jpg
    29/33: kerstlicht_29-in-struik.jpg.
    kerstlicht_30-in-struik.jpg
    30/33: kerstlicht_30-in-struik.jpg.
    kerstlicht_31-kerst-2019.jpg
    31/33: kerstlicht_31-kerst-2019.jpg.
    kerstlicht_32-kerst-2020.jpg
    32/33: kerstlicht_32-kerst-2020.jpg.
    kerstlicht_33-kerst-2021.jpg
    33/33: kerstlicht_33-kerst-2021.jpg.

    De aansluitingen van KerstLicht

    Een 4-kanaals Looplicht voor Kerstverlichting, met 2-staps Timer.

    Arduino Uno

    Pwr USB ?
     
    ?
    aref
    gnd Gnd's (4x)
    ? d13 Activiteit Led
    ioreff d12 MosFet Lamp 4
    reset d11 MosFet Lamp 3
    +3.3v d10 MosFet Lamp 2
    +5V (voor 74HCT595) +5v d9 MosFet Lamp 1
    Gnd's (4x) gnd d8
    Gnd's (4x) gnd
    Vin d7
    d6
    a0 d5
    a1 d4 Latch (74HCT595)
    a2 d3 Clock (74HCT595)
    a3 d2 Data (74HCT595)
    a4 d1 Txd (standaard)
    a5 d0 Rxd (standaard)