Ok... ik ben verder aan het prullen om licht in mijn station te krijgen. En vermits de manier waarop ik mijn baan wil aansturen nog lang niet af is EN ik voor een ander projectje een arduino wil gebruiken heb ik iets ineen geprutst om wat random licht te hebben.
Omwille van wat ik nodig heb voor het andere (niet-trein) projectje ben ik vertrokken met een Arduino Nano Every. Die heeft maximaal 20 uitgangen. Dus heb ik er iets van gemaakt dat gewoon die 20 uitgangen aan en uit zet in een relatief random patroon. Het is al wat ingewikkelder dan de allereerste simpele sketch maar nog wel begrijpelijk denk ik. Er is ook overvloedig commentaar in gezet. Hier is de hele zooi:
// geef aan hoeveel uitgangen gebruikt worden, er wordt verondersteld in volgorde gebruikt worden
#define aant_lichtptn 6
// stel in hoelang een timer_tick is in milliseconden
#define timer_tick 1000
// de maximale aantal ticks dat een timer kan lopen
#define max_ticks 30
// de minimale aantal ticks dat een teller kan lopen
#define min_ticks 5
/*
gebruik van de uitgangen:
D2= bureau_chef
D2= bureau;
D4= wachtzaal;
D5= gang
D6= dortoir
D7= badkamer
*/
int x; //teller voor alle werk
int lichtpunten[] = {2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21}; //alle 20 bruikbare IO uitgangen van de Audiono Nano Every
int status_lamp[aant_lichtptn]; //houdt bij of de lamp aan (=1) of uit (=0) is
int timer[aant_lichtptn]; //voor elke lamp loopt een timer (in timer_ticks)
void setup() {
// put your setup code here, to run once:
for(x=0;x<aant_lichtptn;x++){ //zet alle gebruikte uitgangen in een gekende begintoestand
pinMode(lichtpunten[x],OUTPUT); //zet de pin als uitgang
digitalWrite(lichtpunten[x],LOW); //zet de lamp uit
status_lamp[x]=0; //zet de staus van de lamp op uit (=0)
timer[x]=random(1,max_ticks); //geef de lamp een starttimer tussen 1 en max_tick timer ticks
}
}
void toggle(int lamp){ //bedien de lampschakelaar
if(status_lamp[lamp]==0){ //als de lamp uit is
digitalWrite(lichtpunten[lamp],HIGH); //zet ze aan
status_lamp[lamp]=1; //zet de status op 1 (=aan)
}
else{ //als de lamp niet uit is (dus is ze aan)
digitalWrite(lichtpunten[lamp],LOW); //zet de lamp uit
status_lamp[lamp]=0; //zet de status op 0 (=uit)
}
}
void loop() {
// put your main code here, to run repeatedly:
delay(timer_tick); //wacht 1 timer_tick en handel de timers af
for(x=0;x<aant_lichtptn;x++){
timer[x]=timer[x]-1; //verlaag de timer voor de lamp met 1 tick
if(timer[x]<0){ //test of de teller is afgelopen
toggle(x); //als de timer afgelopen is, schakel de lamp om
timer[x]=random(min_ticks,max_ticks); //en stel een nieuwe teller in tussen min en max aantal ticks
}
}
}
Wat bijkomende uitleg:
- "#define aant_lichtptn 6": een #define is eigenlijk iets dat de compiler vertelt dat vòòr de compilatie moet beginnen alles waar de tekst "aant_lichtptn" voorkomt dit moet vervangen worden door de tekst "6". Daarom ook dat er geen commentaar achter staat want al wat er achter komt wordt er vervangen. Dus voor de veiligheid, niets erachter maar de commentaar erboven. Ik ga maar 6 van de 20 uitgangen gebruiken. Maar ze zijn wel allemaal gedefinieerd. Je zou dat ook kunnen doen door een variabele te definiëren en die de waarde 6 te geven. Maar deze manier gebruikt gaan geheugen voor die variabele op te moeten slaan.
- ik werk met "timer_ticks". Elke keer dat de hoofdlus van het programma doorlopen wordt is 1 timer tick. Dit vermiijdt het probleem van de milliseconden teller die "overloopt". Door nu te zeggen hoelang een timer_tick duurt en hoelang een timer maximaal en minimaal mag zijn kan je de werking aan je smaak aanpassen. In mijn geval is dat om de seconde is er 1 tick (1000 milliseconden). En een timer moet minimaal 5 ticks zijn en maximaal 30 ticks. Dus een lamp moet minimaal 5x1000 milliseconden aan of uit zijn en kan maximaal 30x1000 milliseconden aan of uit zijn.
- er is een blok commentaar dat me er aan herinnert welke uitgang waar naartoe moet.
- alle 20 uitgangen zijn te gebruiken, je moet maar zeggen hoeveel je er echt gebruikt. Hoeft eigenlijk niet, die cpu is snel genoeg maar voor de volledigheid toch maar gedaan.
- de functie "toggle" heeft als enige doel te kijken of een lamp aan of uit staat en die dan uit of aan te zetten. Hij "togglet" de lamp. Net zoals je een schakelaar bedient: als de lamp uit is en je bedient de schakelaar, dan is de lamp uit. En omgekeerd. En tegelijk zet je in de lijst "status_lamp" of de lamp nu aan of uit is.
- de tellers van de for-lus lopen van 0 tot (aantal_lichtptn-1). Dit is een gevolg van het gebruik van arrays in de de programmeertaal C. Arrays beginnen altijd te tellen bij 0.
De werking is simpel:
- in een lijst (array "status_lamp") houden we bij of de lamp aan of uit is.
- in een andere lijst (array "timer") houden we voor elke lamp een teller bij. De rest van de uitleg is voor 1 teller/timer maar alle uitgangen werken op hetzelfde principe
- bij het begin zetten we alle lampen uit en we zetten voor elke lamp een timer in met een waarde ergens tussen het 1 en maximum. Waarom 1 en niet het minimum (5 in het voorbeeld)? Wel, dan kunnen we hebben dat er misschien lampen direct aangaan, anders moeten we steeds het minimum wachten.
- vermits de cpu toch niets anders te doen heeft laten we die gewoon wachten tot er een nieuwe timer_tick is.
- we verlagen de teller en kijken of die af gelopen is
- als die afgelopen is dan zetten we de schakelaar om (roepen de functie "toggle" aan voor die lamp) en stellen een random nieuwe timer in
Bekijk het als een hele reeks schakelaars (array "staus_lamp") waar boven elke schakelaar een keukentimer staat. Alle schakelaars staan uit en we geven aan elke keukentimer een draai. En dan wachten we.... telkens als een timer afloopt, dan zetten we de schakelaar om en geven een nieuwe draai aan de keukentimer.