Programarea Arduino 4x4x4 LED Cube pentru a face unele lucruri mai minunat
Săptămâna trecută, am construit un cub LED Cum să faci un pulsatoriu Arduino LED Cube care pare că a venit de la viitor Cum să faci un pulsatoriu Arduino LED Cube care pare că a venit de la viitor Dacă ai dabbled cu unele proiecte Arduino începător , dar căutați ceva puțin permanent și pe un alt nivel de minunat, atunci cubul umil 4 x 4 x 4 LED este ... Citește mai mult - 64 de LED-uri pe care le puteți programa pentru a face spectacole fantastice de lumină futuriste - și sper că ați făcut și voi, pentru că este un proiect minunat de a vă motiva și de a vă extinde abilitățile Arduino. Ți-am lăsat câteva aplicații de bază pentru a te gândi, dar astăzi voi prezenta mai multe bucăți de software pe care le-am făcut pentru cub, împreună cu explicațiile codului. Scopul acestui lucru este atât să vă dați câteva lumini frumoase pentru a alerga, cât și să învățați despre unele dintre limitările de programare a cubului și să învățați câteva noi concepte de programare în acest proces.
Aceasta este o codificare destul de avansată; trebuie să fi citit toate tutorialele mele Arduino anterioare și ghidul nostru Arduino începător înainte de personalizarea codului.
Aplicația 1: Mini Snake
Mai degrabă decât să rulez o șarjă de șarpe, mi-am dorit să programez un șarpe - unul artifical care ar face alegeri aleatorii proprii și să fie complet imprevizibil. Este limitat doar la 2 segmente, pe care le voi explica mai târziu, și puteți vedea demo-ul de mai jos. Descărcați codul complet aici.
Atunci când se ocupă de spațiul 3D, aveți nevoie de 3 coordonate pentru un singur punct: X, Y, și Z.
Cu toate acestea, în cubul nostru, avioanele X și Z sunt reprezentate de pinii LED, în timp ce Y este cartografiat direct pe planurile catodice. Pentru a facilita lucrul cu aceste coordonate și pentru a imagina mișcarea în jurul cubului, am creat un nou tip de date (folosind struct) pentru a reprezenta un singur punct pe cub - pe care l-am sunat “xyz”. Se compune din două numere întregi: “XZ”, și “y”. Cu această structură, aș putea apoi să reprezint o direcție, indicată mai jos în sistemul nostru special de coordonate (xz, y):
Y mișcare (sus jos): (xz, y + 1), (xz, y-1)
Z circulaţie (înainte, înapoi): (xz-1, y), (xz + 1, y)
X mișcare (stanga dreapta): (xz + 4, y), (xz-4, y)
De exemplu, pentru a muta LED-ul în poziție (0,0) unul la stânga, aplicăm (xz + 4, y) și se încheie cu (0,4).
Există anumite limite care se pun pe mișcare - și anume faptul că coordonatele Y nu pot fi decât posibile 0 până la 3 (0 fiind stratul inferior, 3 este partea de sus), iar coordonatele XZ ar putea fi doar 0 până la 15. O altă limită este pusă pe mișcarea Z pentru a preveni “jumping” de la spate la partea frontală a cubului și invers. În acest caz, folosim funcția modulului pentru a testa multiplii de 4 și neagă încercarea de mișcare. Aceasta este logica este reprezentată în valabil() funcția, care returnează un adevărat dacă direcția propusă este o mișcare acceptabilă și altfel falsă. Am adăugat o funcție suplimentară pentru a verifica un inversă - adică, dacă șarpele se îndreaptă într-o direcție, nu vrem să se ducă înapoi în sine, chiar dacă este altfel o locație valabilă pentru a trece la - și o mișcare() funcția, care ia o coordonate, o direcție și returnează noua coordonată.
XYZ datatype, valabil(), mișcare() și invers() toate funcțiile pot fi găsite în xyz.h fișier în descărcări. Dacă vă întrebați de ce acest lucru a fost pus într-un fișier separat în loc de fișierul principal al programului, se datorează unor reguli complicate ale compilatorului Arduino care împiedică funcțiile returnați tipuri de date personalizate; acestea trebuie să fie plasate în fișierul propriu, apoi importate la începutul fișierului principal.
Înapoi în fișierul principal de execuție, o serie de instrucțiuni stochează toate mișcările posibile pe care șarpele le poate face; putem alege pur și simplu un membru aleatoriu pentru a obține o nouă direcție. De asemenea, sunt create variabile pentru a stoca locația curentă (acum), cea anterioară direcţie și anterioare Locație. Restul codului ar trebui să fie destul de evident pentru dvs.; doar for bucle și activarea și dezactivarea LED-urilor. În bucla principală, verificăm dacă direcția propusă este valabilă și dacă este atunci mergem așa. Dacă nu, alegem o nouă direcție.
Singurul lucru pe care trebuie să-l subliniez în bucla principală sunt câteva verificări pentru a corecta un bug pe care l-am găsit implicând multiplexarea: dacă noua locație se afla pe același plan catodic sau pe același anod, oprirea LED-ului precedent ar duce la ieșirea ambelor. De asemenea, în acest moment mi-am dat seama că depășirea unui șarpe de 2 segmente va fi imposibilă cu implementarea mea actuală: încercați să aprindeți 3 LED-uri într-un aranjament de colț. Nu puteți, deoarece cu 2 straturi și 2 LEDuri activate, 4 LED-uri se vor aprinde, nu 3. Aceasta este o problemă inerentă cu designul cubului limitat, dar nu pentru a ne face griji: pur și simplu trebuie să folosim puterea persistența vederii să rescrieți metoda de tragere.
Persistența viziunii înseamnă că atunci când lumina ajunge la ochii noștri secvențial - mai repede decât putem procesa - pare să fie o singură imagine. În cazul nostru, în loc să desenăm toate cele patru straturi în același timp, ar trebui să desenați primul, să îl dezactivați, să desenați al doilea și să-l dezactivați: mai repede decât putem spune că orice schimbare se întâmplă. Acesta este principiul în care scriitorii de mesaje lucrează, ca acesta:
Noua metodă de tragere folosind persistența viziunii
În primul rând, o nouă rutină de tragere. Am creat o 4 x 16 matrice bidimensională de biți (adevărat sau fals) pentru a fi o reprezentare literală a stării cubului LED. Rutina de tragere va implementa persistența viziunii prin simpla iterare a acesteia și eliminarea fiecărui strat de cub pentru un moment scurt. Se va continua să se tragă în starea actuală până la trecerea timpului de reîmprospătare, moment în care vom trece controlul înapoi la bucla principală (). Am salvat această secțiune a codului în acest fișier LED_cube_POV, așa că dacă doriți doar să sarăți în programarea propriilor jocuri și astfel, atunci nu ezitați să utilizați acest lucru ca bază.
Aplicația 2: Jocul vieții
Pentru moment, să dezvoltăm acest lucru într-o versiune de bază a jocului de viață al lui Conway. Pentru cei care nu sunteți familiarizați (încercați Googling-ul să găsească o animație minunată de ouă de Paște), Jocul Vieții este un exemplu de automate celulare care creează un model fascinant de comportament emergent, dat fiind doar câteva reguli simple.
Acesta este, de exemplu, modul în care furnicile par să se miște cu inteligență și o minte de stup, în ciuda faptului biologic că aceștia urmează doar reguli hormonale de bază. Iată codul complet pentru descărcare: apăsați pe restabili pentru a reporni. Dacă vă aflați prin faptul că obțineți același tipar mereu și repede, încercați să țineți apăsat butonul de odihnă mai mult timp.
Iată regulile jocului vieții:
- Orice celula viu cu mai putin de doi vecini vii moare, ca si cum ar fi cauzata de sub-populatie.
- Orice celulă viu cu doi sau trei vecini trăiește în următoarea generație.
- Orice celula viu cu mai mult de trei vecini vii moare, ca si cum ar fi prin supraaglomerare.
- Orice celulă moartă cu exact trei vecini vii devine o celulă vie, ca și cum ar fi prin reproducere.
Rulați codul. Veți observa între 5 și 10 “generații”, automatele au venit probabil să se odihnească, stabilizându-se pe o anumită poziție; uneori acest model stabil va schimba locația și va schimba în jurul bordului. În cazuri rare, s-ar putea chiar să fi dispărut complet. Aceasta este o limitare a funcționării doar a LED-urilor cu 4x4x4, dar este oricum un exercițiu bun de învățare.
Pentru a explica codul:
- S-ar putea să nu fiți familiarizați cu memcpy () funcţie. Am folosit acest lucru pentru a salva starea anterioară a jocului, deoarece nu pot fi alocate unul altuia ca variabile normale - trebuie să copiați spațiul de memorie (în acest caz, 64 de biți).
- howManyNeighbours () funcția ar trebui să fie explicativă, dar în caz că nu este - această metodă are o singură coordonată și trece prin fiecare posibil vecin (aceeași gamă de direcții pe care am folosit-o anterior în aplicația șarpe), pentru a verifica dacă acestea sunt valide. Apoi verifică dacă LED-urile vecine au fost "pornite" în starea anterioară a jocului și contează cât de multe sunt acolo.
- Funcția principală a acestei aplicații Game of Life este progressGame (), care aplică regulile automate la starea actuală a jocului.
îmbunătăţiri: Am petrecut mult prea mult pe această temă până acum, dar ați putea încerca să adăugați un cec care resetează automat tabla după 5 sau mai multe generații de același model. atunci vă rog să-mi spuneți! Aș sugera, de asemenea, încercarea de a adăuga metodologia POV la jocul de șarpe pentru a speria că va fi posibil un șarpe mai lung.
Asta e de la mine azi. S-ar putea să revizuiesc mai multe aplicații Arduino LED cube într-un moment mai târziu, dar sperăm că ar trebui să fii în poziția de a-mi modifica codul și de a-ți crea propriile reguli de joc: să ne spui ce ai venit în comentarii, creatiile tale! Ca întotdeauna, voi fi aici pentru a răspunde la întrebările dvs. și pentru a-mi apăra abilitățile mele de codare groaznice.
Credit de imagine: coordonate cartesian - Utilizator Wikimedia Sakurambo
Explorați mai multe despre: Arduino.