Programmera din Arduino 4x4x4 LED-kub för att göra några mer fantastiska saker

Programmera din Arduino 4x4x4 LED-kub för att göra några mer fantastiska saker / Programmering

Förra veckan byggde jag en LED-kub Hur man gör en pulserande Arduino LED-kub som ser ut som den kom från framtiden Hur man gör en pulserande Arduino LED-kub som ser ut som den kom från framtiden Om du har dabbled med några nybörjare Arduino-projekt , men letar efter något lite permanent och på en helt annan nivå av häftigt, då är den ödmjuka 4 x 4 x 4 LED-kuben ... Läs mer - 64 lysdioder att du kan programmera för att göra fantastiska futuristiska ljusprogram - och jag hoppas du gjorde det också, för det är ett bra projekt att motivera dig och utöka din Arduino skillset. Jag lämnade dig med några grundläggande appar för att få dig att tänka, men idag presenterar jag några fler bitar av programvara som jag gjorde för kuben, tillsammans med kodförklaringar. Syftet med detta är att ge dig några fler vackra lightshows att springa, men också för att lära dig om några av begränsningarna att programmera kuben och lära dig några nya programmeringskoncept i processen.

Detta är en ganska avancerad kodning; du behöver verkligen läsa alla mina tidigare Arduino-handledning och vår nybörjares Arduino-guide innan du anpassar koden.

App 1: Mini Snake

I stället för att köra en uppsättning orm-liknande mönster-sekvens, ville jag programmera en orm - en artificiell som skulle göra det egna slumpmässiga val och vara helt oförutsägbar. Den är begränsad till endast 2 segment, vilket jag kommer att förklara senare, och du kan se demoen nedan. Ladda ner hela koden här.

När du arbetar med 3D-utrymme behöver du 3 koordinater för en enda punkt: X, Y, och Z.

I vår kub representeras X och Z-planen av LED-stiften, medan Y är direkt mappad till katodplanen. För att underlätta arbetet med dessa koordinater och räkna ut rörelsen runt kuben skapade jag därför en ny datatyp (med hjälp av struct) att representera en enda punkt på kuben - som jag ringde “xyz”. Den består av bara två heltal: “xz”, och “y”. Med denna struktur kan jag då också representera en riktning, som anges nedan i vårt speciella (xz, y) koordinatsystem:

Y-rörelse (upp ner): (xz, y + 1), (xz, y-1)
Z rörelse (framåt, bakåt): (xz-1, y), (xz + 1, y)
X-rörelse (vänster höger): (xz + 4, y), (xz-4, y)

Till exempel, för att flytta LED-lampan i läge (0,0) en till vänster, vi ansöker (xz + 4, y) och sluta med (0,4).

Det finns vissa gränser som placeras på rörelse - nämligen att Y-koordinater endast kan vara möjliga 0 till 3 (O är bottenskiktet, 3 är toppen) och XZ-koordinater kan endast vara 0 till 15. En ytterligare gräns placeras på Z-rörelsen för att förhindra “hoppning” från baksidan till kubens framsida och vice versa. I det här fallet använder vi modulfunktionen för att testa för multiplar av 4 och förneka det rörelseförsöket. Detta är logiken är representerad i giltig() funktion, som returnerar en sann om den föreslagna riktningen är ett acceptabelt drag och falskt annars. Jag lade till en ytterligare funktion för att leta efter en invers riktning - det vill säga om ormen är på väg i en riktning vill vi inte att den ska gå bakåt på sig själv, även om det annars är en giltig plats att flytta till - och en flytta() funktion, som tar en koordinat, en riktning och returnerar den nya koordinaten.

De XYZ data typ, giltig(), flytta() och omvänd() funktioner kan alla hittas i xyz.h filen i hämtningarna. Om du undrar varför detta sattes i en separat fil i stället för huvudprogramfilen beror det på några komplicerade Arduino-compilerregler som förhindrar funktioner från återvänder anpassade datatyper; De måste placeras i sin egen fil och importeras sedan i början av huvudfilen.

Tillbaka i den huvudsakliga runtime-filen lagras en rad riktningar alla möjliga rörelser som ormen kan göra; vi kan helt enkelt välja en slumpmässig array medlem för att få en ny riktning. Variabler skapas också för att lagra aktuell plats (nu), föregående riktning och tidigare plats. Resten av koden ska vara ganska uppenbar för dig; bara for slingor och släcka och släcka lysdioder. I huvudslingan kontrollerar vi för att se om den föreslagna riktningen är giltig, och om det är så går vi så. Om inte, väljer vi en ny riktning.

Det enda som ska påpekas i huvudslingan är några kontroller för att rätta till en bugg som jag hittade med multiplexing: om den nya platsen var på samma katodplan eller samma anodstift, skulle det leda till att båda utgåvorna stängdes av tidigare LED. Det är också vid denna tidpunkt att jag insåg att gå utöver ett 2-segment orm skulle bli omöjligt med mitt nuvarande genomförande: försök att tända 3 lysdioder i ett hörnarrangemang. Du kan inte, för med 2 lager och 2 LED-stift aktiverade skulle 4 LED-lampor slås på, inte 3. Detta är en inneboende fråga med vår begränsade multiplexade kubdesign, men oroa dig inte: vi behöver helt enkelt använda kraften i persistens av syn att skriva om teckningsmetoden.

Persistens av vision innebär att när ljus når våra ögon i följd - snabbare än vi kan bearbeta det - verkar det vara en enda bild. I vårt fall, i stället för att rita alla fyra skikten samtidigt, borde vi rita den första, avaktivera den, dra den andra och avaktivera den: Snabbare än vi kan berätta några förändringar sker till och med. Det här är principen om vilka meddelandeskrivare som arbetar, som den här:

Ny teckningsmetod som använder persistens av vision

Först då, en ny rita rutin. Jag har skapat en 4 x 16 tvådimensionell array av bitar (sant eller falskt) för att vara en bokstavlig representation av LED-kubens tillstånd. Rita rutinen kommer att genomföra persistens av syn genom att helt enkelt iterera över detta och spola ut varje lager till kuben för ett kort ögonblick. Det fortsätter att rita sig i det nuvarande läget tills uppdateringstiden har gått, vid vilken tidpunkt kommer vi att skicka kontrollen tillbaka till huvudslingan (). Jag har sparat den här delen av koden i den här LED_cube_POV-filen, så om du bara vill hoppa in i programmering dina egna spel och så är du välkommen att använda den här som en bas.

App 2: Livets lek

För nu, låt oss utveckla detta till en grundläggande version av Conways Game of Life. För de av er som är obekanta (försök Googling det för att hitta en fantastisk påskäggs animation), de Livets spel är ett exempel på cellulär automat som skapar ett fascinerande mönster av framväxande beteende som endast ges några enkla regler.

Det här är till exempel hur myror verkar flytta med intelligens och bikopsinne, trots det biologiska faktum att de faktiskt bara följer väldigt grundläggande hormonella regler. Här är fullständig kod för nedladdning: tryck på återställa knappen för att starta om. Om du befinner dig i samma mönster om och om igen, försök hålla ner vilopnappen längre.

Här är spelets livsregler:

  • Alla levande celler med färre än två levande grannar dör, som om de orsakas av underbefolkningen.
  • En levande cell med två eller tre levande grannar lever vidare till nästa generation.
  • Vilken levande cell som helst med mer än tre levande grannar dör, som genom överbeläggning.
  • Varje dödcell med exakt tre levande grannar blir en levande cell, som genom reproduktion.

Kör koden. Du kommer att märka inom 5 till 10 “generationer”, Automaten har förmodligen kommit vila, stabiliserar sig i en viss position; Ibland kommer det här stabila mönstret att byta plats och växla runt ombord. I sällsynta fall kan de till och med ha helt dött ut. Det här är en begränsning att bara ha 4x4x4-lysdioder att arbeta med, men det är en bra inlärningsövning ändå.

Förklara koden:

  • Du kanske inte känner till memcpy () fungera. Jag har använt detta för att spara det tidigare spelstaten, eftersom arrays inte bara kan tilldelas varandra som vanliga variabler - du måste faktiskt kopiera över minnesutrymmet (i detta fall 64 bitar).
  • howManyNeighbours () funktionen ska vara självförklarande, men om det inte är det - den här metoden tar en koordinat och går genom varje eventuell granne (samma uppsättning riktningar som vi tidigare använt i ormapp) för att kontrollera om de är giltiga. Det kontrollerar då om de andra LED-lamporna var "på" i föregående speltillstånd och räknar med hur många som finns.
  • Huvudfunktionen för denna Game of Life-app är progressGame (), vilken applicerar automatreglerna till det aktuella speltillståndet.

förbättringar: Jag har spenderat alltför länge här så länge, men du kanske vill försöka lägga till i en check som automatiskt återställer brädan efter 5 eller så generationer av samma mönster. vänligen meddela mig det! Jag föreslår också att man försöker lägga till POV-metoden till ormspelet för att förhoppningsvis göra en längre orm möjlig.

Det är det från mig idag. Jag kan återkomma några fler Arduino LED-kubprogram på senare tid, men förhoppningsvis bör du kunna ändra min kod och skapa egna spelregler: Låt oss veta vad du kommit med i kommentarerna, så vi kan alla ladda ner dina skapelser! Som alltid kommer jag att vara här för att svara på dina frågor och försvara mina fasansfulla kodningsförmågor.

Bildkredit: Kartesiska koordinater - Wikimedia-användare Sakurambo

Utforska mer om: Arduino.