verlichting huisjes aansturen met Arduino - hoe kan het anders/beter/...

Gestart door Dirky, 04 maart 2021, 11:55:03 AM

Alberke

Citaat van: Havoc op 16 maart 2021, 22:13:35 PM
Citaat van: Karel A.J. op 16 maart 2021, 21:53:07 PM
CiteerOverigens kost het geen moeite om dingen ineens goed te coderen.

Patrick sorry hoor, maar dat klinkt toch een beetje elitair, al zal het zo wel niet bedoeld geworden geweest zijn.

Waarschijnlijk niet, en ik kan Patrick geen ongelijk geven. Maar toch wel enkele bedenkingen:
- om op dat detail te gaan programmeren moet je al verdomd veel weten over de hardware. Meer dan 75% van diegenen die een arduino of andere processor als bijzaak in hun hobby gaan gebruiken weten dat niet. En hebben er ook geen interesse of noodzaak aan.
- alhoewel het principe ongetwijfeld correct is, blijft de vraag hoe belangrijk het is voor een LED sturing van huisjes op een treinbaan... Moesten we hier nu over iets bezig zijn zoals een machinesturing, medisch toestel, een raket... ja, dan ongetwijfeld. Maar de vraag is of er iemand ooit iets van zal merken als dit niet 100% is. en zelfs dan of er ooit iemand meer zal zeggen dan "dat is raar....".
- laat ons niet het doel uit het oog verliezen. Ergens is er een "return on investment". Ik kan begrijpen dat mensen die professioneel met software bezig zijn dit correct willen. Maar er zijn er ook die alleen wat lichtjes in een huisje willen zien aan en uit gaan.
En daarom opnieuw mijn vraag over dat item van Modelbouwled dat intussen spoorloos is. Met die post is het hele gedoe hier begonnen. Het ding kost minder dan een Arduino en doet wat het moet: het licht willekeurig laten aangaan, op acht verschillende plaatsen. Al wat je moet kunnen is stekkertjes versteken.
Ja, ik ben de plezantste thuis, als de vuilbak buiten staat! ;D

svvander

Sven Vandersmissen Aan het afbouwen om iets anders op te bouwen. Elk einde is een nieuw begin.

Alberke

Citaat van: svvander op 17 maart 2021, 08:33:05 AM
Minder dan €7?
Hangt er vanaf waar ge uwe Arduino koopt hé. Als ge de Chinese industrie wil steunen komt ge er soms zelfs goedkoper vanaf.
Ja, ik ben de plezantste thuis, als de vuilbak buiten staat! ;D

Alberke

Ja, ik ben de plezantste thuis, als de vuilbak buiten staat! ;D

deevie

Citaat van: Karel A.J. op 16 maart 2021, 21:53:07 PM
CiteerOverigens kost het geen moeite om dingen ineens goed te coderen.

Patrick sorry hoor, maar dat klinkt toch een beetje elitair, al zal het zo wel niet bedoeld geworden geweest zijn.

Het kost iedereen moeite om voor zichzelf uit te maken wat goed is. Dan mag het over coderen gaan of over het lasersnijden van styreenplaat of over het spuiten van de make-up van een hoerke in de Aarschotstraat of over het 3d-printen van een TGV-koppeling.

Maar wat men ook voor zichzelf vastlegt als goed het zal altijd moeite kosten om te bereiken.
Ik vind het alvast héél hautain overkomen. Mensen willen een positieve bijdrage leveren met zo weinig mogelijk code om begrijpbaar te zijn voor iedereen en die in praktijk eigenlijk perfect werkt voor het doel. Ik vind ook als je kritiek hebt ivm goed coderen dat je bvb zelf steeds het goede voorbeeld moet geven en dus de moeite moet doen om bij voorbeeld te kijken of de digitalWrite-functie boolean-waarden accepteert. Dat gedrocht met die zetuitgang-functie is dus absoluut not done.

patrick smout

Bedankt voor de constructieve bijdrage.
Ik neem het mee in mijn volgend progamma voorbeeld.
Met vriendelijke groeten,

Patrick Smout

Havoc

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.
Met vakantie voor onbepaalde duur.

Havoc

Oh ja, nog een late bedenking: door het gebruik van die timer_ticks kunnen we de algemene "klok" van onze modelwereld sneller of trager laten lopen zonder overal tijden (in milliseconden) te moeten gaan aanpassen.

Pas op met #define, die vervangt letterlijk overal tekst. Dus als je schrijft "#define a 5", dan wordt "int aantal" vervangen door "int 55nt5l". Verschiet niet als je dan rare dingen krijgt. Daarom dat normaliter bij een #define de te vervangen tekst in hoofdletters geschreven wordt. Maar ik ben tegenwoordig te lui.... Dus eerder "#define AANT_LICHTPTN 6". Kwestie van de aandacht erop te trekken dat dit een tekst is die vervangen zal worden.

En ik haat die lower camelcase die ze gebruiken voor hun voor gedefinieerde functies!
Met vakantie voor onbepaalde duur.

deevie

Die toggle functie heb je eigenlijk niet nodig. Als je een pin als output definieert kan je de status ervan inlezen via digitalRead. Daarnaast zijn de outputs altijd low wanneer de Atmel van stroom voorzien wordt, dus eigenlijk niet nodig om die LOW te schrijven.

Havoc

Citaat van: deevie op 21 maart 2021, 22:10:58 PM
Die toggle functie heb je eigenlijk niet nodig. Als je een pin als output definieert kan je de status ervan inlezen via digitalRead. Daarnaast zijn de outputs altijd low wanneer de Atmel van stroom voorzien wordt, dus eigenlijk niet nodig om die LOW te schrijven.

Heb het snel eens geprobeerd. Als ik de status_lamp array weglaat, de toggle functie weglaat en vervang door digitalWrite(x,!digitalRead(x)) dan gebruik ik 12 bytes minder geheugen voor variabelen (de array die weg is). Maar wel 28 bytes meer programma geheugen (de functie digitalRead moet erbij komen).

Het meer bijzondere is als je de digitalWrite(x,LOW) weglaat in de setup. Dan worden er plots 86 bytes minder programma geheugen gebruikt! Dit is heel eigenaardig want de digitalWrite wordt verderop nog gebruikt dus de functie moet in het eindprogramma zitten. Kennelijk is die setup niet zo efficiënt. Zelf heb ik de neiging om die er te laten staan. In princiepe kan je dan de setup zelf aanroepen om de boel ergens in je programma te resetten.

Nu ja, allemaal nogal accademisch, Elke variant gebruikt maar 4% van het programma geheugen en 0% van het dynamisch geheugen (voor variabelen). Leesbaarheid en onderhoudbaarheid hebben ook belang vind ik.
Met vakantie voor onbepaalde duur.