Vraag:
Meerdere onafhankelijke LED-patronen
Nickos
2014-07-11 00:03:42 UTC
view on stackexchange narkive permalink

Ik heb een probleem, waarvan ik in eerste instantie dacht (en omdat ik nieuw was bij Arduino) dat ik dacht dat het een perfecte applicatie was voor een Arduino. Maar nadat ik het geprobeerd heb en het niet heb geïmplementeerd, twijfel ik aan mezelf!

Gewoon - ik moet veel LED's onafhankelijk bedienen, waarvan er vele hun eigen individuele patronen hebben - bijvoorbeeld "5 seconden op - 5 seconden uit". "continue flitsen" - of sequenties zoals "2 flitsen, pauze, 1 flits". Het is duidelijk dat ik zonder de luxe van draden een beetje loskom. Wees goed om te horen of a) Arduino de beste keuze is en b) zo ja - hoe kan ik dit aanpakken!

Bij voorbaat dank :)

Heb je [protothreads] (http://dunkels.com/adam/pt/) bekeken? Er zijn een aantal Arduino-bibliotheken waarmee u eenvoudig protothreads in uw project kunt opnemen.
Drie antwoorden:
Peter Bloomfield
2014-07-11 00:42:02 UTC
view on stackexchange narkive permalink

Meerdere patronen tegelijk behandelen is zeker mogelijk met een platform als Arduino, en er zijn een aantal manieren waarop je dit kunt aanpakken.

Een methode die ik zou overwegen, is het schrijven van functies die effectief elk patroon wiskundig. U geeft het gewoon de totale tijd die tot nu toe in uw programma is verstreken door, en het zal de juiste actie voor dat specifieke moment in de tijd uitvoeren. Het zal onmiddellijk daarna terugkeren (geen vertragingen of zoiets).

Om dat te doen, moet je eerst weten hoe lang een enkele cyclus van het patroon duurt. U kunt vervolgens de modulo-operator gebruiken om erachter te komen hoe ver u door de huidige cyclus bent. Van daaruit hoeft u alleen maar een paar if -voorwaarden te hebben om te bepalen wat u op een bepaald moment moet doen.

Hier is hoe het eruit zou kunnen zien voor uw "5 seconden op, 5 seconden uit "pattern:

  function pattern5on5off (unsigned long totalTime) {// Bereken hoe ver we door de huidige cyclus heen zijn const unsigned long cycleTime = totalTime% 10000; // Als we in de eerste 5 seconden van de cyclus zitten, doe dan het licht aan. // Schakel het anders uit. if (cycleTime < 5000) digitalWrite (3, HIGH); else digitalWrite (3, LOW);}  

Toegegeven, constant digitalWrite () aanroepen als je dat technisch niet nodig hebt, is niet erg efficiënt. Het mag echter geen schade aanrichten en is vrij eenvoudig te optimaliseren indien nodig.

Om het bovenstaande voorbeeld in een sketch te gebruiken, hoef je het alleen maar aan te roepen in loop () , en geef het nummer door dat u krijgt van millis () ; bijv .:

  void loop () {const unsigned long totalTime = millis (); pattern5on5off (totalTime); // roep hier andere patronen aan ...}  

Andere patronen zullen complexer zijn, maar volgen hetzelfde principe. Je zou gewoon de juiste if -instructies moeten gebruiken om je logica uit te drukken.

Het belangrijkste om te onthouden is dat de functie een specifiek moment in de tijd vertegenwoordigt. Het mag het programma nooit pauzeren of vertragen, anders zal het voorkomen dat de andere patronen worden uitgevoerd.

Bewerken: timing op de eerste cyclus
Zoals jfpoilpret opgemerkt in de commentaren, de allereerste cyclus begint op een willekeurig punt. Dit komt doordat de eerste keer dat u millis () aanroept in loop () , het niet start bij 0 (het apparaat heeft al een korte tijd gedraaid loop () wordt aangeroepen). Het is echter gemakkelijk op te lossen, indien nodig.

Je zou het doen door de totalTime -waarde te compenseren met de waarde die je de allereerste keer kreeg rond loop () . Bijvoorbeeld:

  unsigned long g_startTime = 0; void loop () {unsigned long totalTime = 0; if (g_startTime == 0) {// Dit is de eerste cyclus. // Sla de starttijd op zodat we later kunnen compenseren. g_startTime = millis (); } else {// Dit is niet de eerste cyclus. // Compenseer de starttijd. totalTime = millis () - g_startTime; } pattern5on5off (totalTime); // etc ..}  
Heel erg bedankt - is volkomen logisch! Ik heb absoluut met mijn hoofd tegen een muur gestoten met de verkeerde benadering ... :)
Het probleem met de `%` benadering is dat de timing niet de allereerste keer correct zal zijn, aangezien deze in het begin gewoon willekeurig zal zijn.
@jfpoilpret Dat is waar. Het is echter gemakkelijk op te lossen, dus ik heb het aan mijn antwoord toegevoegd. :)
Een andere optie zou zijn, in plaats van 'millis' eenmaal in de lus uit te voeren en de waarde ervan als parameter door te geven aan elke led-functie, om elke functie als parameterloze functie te hebben en millis binnen elke functie uit te voeren. Dat zou elke functie in staat stellen om een ​​nauwkeurigere waarde te krijgen, die al dan niet belangrijk kan zijn, afhankelijk van hoeveel tijd elke functie in de lus nodig heeft om uit te voeren, en ook van de timing-correctheidseisen van de toepassing.
user2973
2014-07-11 01:31:22 UTC
view on stackexchange narkive permalink

Arduino is een prima keuze voor de taak - gemakkelijk om mee te beginnen. De sleutel is om niet-blokkerende code te schrijven. Je zou het BlinkWithoutDelay-voorbeeld kunnen bekijken.

Ik heb een suggestie gedaan voor je taak:

  // Timing-suquenties voor de LED's in milliseconden // Eerste waarde is aan tijd, tweede waarde is uit tijd, // derde waarde aan tijd enzovoort (tot 10 waarden) // Eén rij voor elke LEDunsigned int led_timing [] [10] = {{5000, 5000}, {100, 1000} , {100, 100, 100, 1500, 100, 1500}}; // De pinnen waarmee de LED's zijn verbonden byte led_pins [] = {11, 12, 13}; // Houd de timingsequentie bij // Array-grootte overgenomen van led_pinsunsigned long last_change [sizeof (led_pins) / sizeof (led_pins [0])]; byte timing_i [sizeof (led_pins) / sizeof (led_pins [0])]; void setup () {// Initialiseer LED's als uitvoer voor (byte i = 0; i < sizeof (led_pins) / sizeof (led_pins [0]); i ++) {pinMode (led_pins [i], OUTPUT); digitalWrite (led_pins [i], HIGH); }} void loop () {// Huidige tijdstempel niet ondertekend lang nu = millis (); // Houd de volgorde bij voor elke LED voor (byte i = 0; i < sizeof (led_pins) / sizeof (led_pins [0]); i ++) {if (now - last_change [i] > = led_timing [i] [timing_i [i]]) {digitalWrite (led_pins [i],! digitalRead (led_pins [i])); timing_i [i] ++; // Begin opnieuw aan het einde van de timingreeks timing_i [i]% = sizeof (led_timing [i]) / sizeof (led_timing [i] [0]); last_change [i] = nu; }}}  
TommyL
2017-04-18 16:07:49 UTC
view on stackexchange narkive permalink

Ik weet dat het bericht oud is, maar ik heb het voorbeeld gecontroleerd met de array-gebaseerde benadering en naar mijn mening:

  sizeof (led_timing [i]) / sizeof (led_timing [i] [ 0])  

zal altijd de toegewezen grootte (aantal elementen) van de array opleveren - in dit geval 10. Dus de timing zal niet herstarten totdat je het "einde" van de array, met behulp van ongedefinieerde elementen. Voor LED "0":

  int led_timing [0] [10]: 5000,5000, <undefined>, <undefined>, <undefined>, <undefined>, <undefined>, <undefined>, <undefined>, <undefined>  

Groeten Tommy



Deze Q&A is automatisch vertaald vanuit de Engelse taal.De originele inhoud is beschikbaar op stackexchange, waarvoor we bedanken voor de cc by-sa 3.0-licentie waaronder het wordt gedistribueerd.
Loading...