Fråga:
Hur kan jag köra två öglor samtidigt på en Arduino Uno?
Daniel T.
2014-09-29 02:54:06 UTC
view on stackexchange narkive permalink

Jag är ny på Arduino och jag har två enheter som jag försöker kontrollera:

  1. En RGB LED-ljusremsa som kan ändra färger
  2. Ett ljus sensor som kan upptäcka den omgivande ljusnivån

Vad jag skulle vilja göra är att LED-remsan kontinuerligt cyklar genom en regnbågsfärg och ljussensorn justerar ljusstyrkan på LED remsa baserat på den omgivande ljusnivån. Här är de två koderna i sig, som jag har testat isolerat och bekräftat att de fungerar korrekt:

LED-remsa:

  j = (j + 1 256%; // aktuell iteration av ljuscykeln // ställer in stripfärgen för (int i = 0; i< strip.numPixels (); i ++) {strip.setPixelColor (i, Wheel (((i * 256 / strip.numPixels ()) + j) & 255));} // visa de nya färgerna och vänta 20 ms innan nästa cykelstrip.show (); fördröjning (20);  

Ljussensor:

  sensors_event_t händelse; tsl.getEvent (&event); // få en ljusmätstrip.setBrightness (event.light); // ställ in ljusstyrkan på LED-remsan  

Problemet är att ljussensorn tar allt från 100ms till 600ms för att få en läsning, och tsl.getEvent (&event) är ett blockerande samtal, så slutresultatet är att LED-remsan uppdateras alldeles för långsamt. Jag skulle behöva köra de två sida vid sida så att ljussensoravläsningen inte blockerar uppdateringen av LED-remsan. Någon aning om hur jag kan åstadkomma detta?

vilket bibliotek kommer "tsl" från?
100 till 600 ms är överdrivet. Är det bara för en LDR ansluten till en analog ingång?
@BrettM Jag tror att han använder TSL2561 I2C ljussensor.
Sex svar:
Gerben
2014-09-29 18:02:07 UTC
view on stackexchange narkive permalink

Du kan få sensorn att returnera data snabbare genom att sänka dess noggrannhet.

  tsl.setIntegrationTime (TSL2561_INTEGRATIONTIME_13MS); / * snabb men låg upplösning * /  

Du kan också ändra biblioteket så att sensorn inte stängs av efter varje avläsning. Öppna bara TSL2561.cpp , hitta getFullLuminosity -funktionen och kommentera radavläsningen inaktivera (); och de 12 raderna som läser switch (_integration) {...}

En annan lösning är att pixlarna uppdateras var 20: e sekund med en timer. Du kan ha timern, avbryta huvudslingan var 20: e ms och uppdatera pixelvärdena.

(Jag kan inte riktigt hjälpa dig med timers, eftersom jag själv ställer in register för mina timers och ISRs direkt, vilket inte är för nybörjare. Men det finns förmodligen bibliotek för det, för att göra det mer användarvänlig.)

http://playground.arduino.cc/code/timer1 detta bibliotek skulle hjälpa till att göra timers enklare
Se min redigering ovan för att förneka behovet av fördröjning, genom att lämna tsl2561 på hela tiden.
Duncan C
2014-09-29 04:42:33 UTC
view on stackexchange narkive permalink

Arduino är inte en multitrådad eller multitasking enhet. Du måste skriva dina olika funktioner för att "spela trevligt" med varandra. Blockeringskod är dödsfall för denna typ av multitasking. Du kan behöva skriva om din kod som läser ljussensorn så att den inte blockerar.

Om du kan få den koden att inte blockeras är Visual Micros inlägg vägen att gå.

Visual Micro
2014-09-29 04:30:45 UTC
view on stackexchange narkive permalink

Ställ in en "statsserver" i din slinga (). Enkelt uttryckt innebär detta att hålla reda på nästa kommando för varje uppgift och sedan göra en sak i varje uppgift per slinga ().

Om en uppgift behöver köras snabbare än en annan uppgift kan du använda en timer i din slinga för att bestämma vad du ska göra nästa.

Om en uppgift behöver en paus, spara sedan "Last Run" millis () till en global variabel och ignorera uppgiften tills rätt tid har gått . Använd inte en fördröjning (), låt alltid slingan () springa.

Tanken är att slingan () körs så ofta som möjligt men du gör en sak varje gång den körs.

Det tar en stund att få tag på detta sätt att arbeta men det gör att Arduino-processorn kan bearbeta alla jobb jämnt.

  int task1Status = 0; int task2Status = 0; ogiltig slinga () {doOneThingOfTask1 (); doOneThingOfTask2 ();} // 10 saker för att tända lamporna, men gör bara onevoid doOneThingOfTask1 () {if (task1Status == 10) task1Status = 0; växla (task1Status) {fall 0: // börja göra ett nytt processfall 1: // göra något fall 9: // göra det sista}}  
Jag skulle lägga upp något liknande, då märkte jag att OP sa att koden för att göra ljusmätningar blockerar kod.
@Duncan C Åh! Bra poäng. Jag lämnar svaret eftersom jag tror att det beskriver ett sätt att arbeta som undviker samma problem någon annanstans i koden. Det kan också vara att genom att undersöka bibliotekssamtalet till getEvent () kan samma lösning tillämpas för att minska förseningen. Uppenbarligen betyder det att du ändrar bibliotekskoden men man kan kopiera biblioteket till skissmappen och hacka den som lokal källa. en Lib-förändring skulle säkert hjälpa men lokal källa och lite hacking kan ge en lösning. Tack :)
JRobert
2014-09-29 22:10:02 UTC
view on stackexchange narkive permalink

Ditt första, största problem är

ljussensorn tar allt från 100ms till 600ms för att få en avläsning, och tsl.getEvent (&event) är ett blockerande samtal,

Du behöver icke-blockerande åtkomst till ljussensorn. Titta på bibliotekets kod för att se vad den gör när den blockeras. Chansen är stor att den väntar på att sensorn ställer in en 'klar' bit. Om så är fallet måste du ändra biblioteket antingen genom att

  1. lägga till en boolesk .isDone () -funktion som testar den färdiga biten och inte låta ditt huvudprogram kräver en avläsning tills isDone () == TRUE; eller
  2. gör .getEvent () till ett icke-blockerande så att det omedelbart returnerar en uppenbart ogiltig avläsning (som -1) istället för att blockera om sensorn inte är redo än.
  3. ol>

    Det gör att ditt huvudprogram är fritt att betjäna allt som behöver göras och är redo att göra utan att hålla upp allt för den långsamma sensorn.

ForestPhoenix
2014-10-24 18:46:08 UTC
view on stackexchange narkive permalink

Det finns bibliotek som tillåter multitasking, till exempel mitt bibliotek arduOS.

Detta ska fungera:

  #include <arduos16.h> # inkluderar <arduos_core.h> # inkluderar <roundscheduler.h>SYS_enable_preemptive; // glöm INTE detta !!! void setup () {auto sched = new SYS :: RoundScheduler (2); sched->add (&loop1); // dessa 2 är funktioner. sched->add (&loop2); SYS :: start ();}  

Men kom ihåg att faktisk multitasking kan vara ganska knepigt med mycket obskyra buggar. (men du hittar dem).

Detta operativsystem ser lättare att använda än ditt genomsnittliga arduino-operativsystem
lxx
2015-01-01 13:34:27 UTC
view on stackexchange narkive permalink

1. Använd två arduino och låt dem prata med varandra via serie eller i2c. Troligen det enklaste alternativet (men inte det billigaste - även om du kan få klon-arduinos från 4 USD).

2. Hitta en ljussensor som uppdateras snabbare. Försökte en ldr (ljusberoende motstånd) / fotocell? Då kan man använda analog läsning.

Kan också byta från att använda arduino till c, men det är mycket mer arbete och du kommer fortfarande att träffa liknande problem.

Att byta till C skulle egentligen inte göra något för den här frågan.


Denna fråga och svar översattes automatiskt från det engelska språket.Det ursprungliga innehållet finns tillgängligt på stackexchange, vilket vi tackar för cc by-sa 3.0-licensen som det distribueras under.
Loading...