Arduino persistentie van visie weergeven


een persistentie van vision (PoV) display is een rij van LED's die flash kolommen van een bericht.  Als de matrix van LED's wordt verplaatst, net als wanneer gemonteerd op een fietswiel, kan het bericht worden gelezen alsof het veel LED's wide, in plaats van een enkele rij.

De installatie van de hardware voor een PoV display is vrij eenvoudig, maar dit instructable bevat code waar de display kan worden gecontroleerd en geprogrammeerd gemakkelijk via de seriële verbinding, en weergave-instellingen kunnen worden opgeslagen, zodat ze automatisch worden geladen en uitgevoerd wanneer ingeschakeld van een accu.

Wil je een Arduino AVR microcontroller board, zoals een Uno, Nano of mini.  Ongeveer 10 LED's, en 10 weerstanden van ongeveer 100 naar 220 Ohm.

Voor ons voorbeeld zullen we veronderstellen dat een 10 LED-display.  Draad van de LED's in serie met een weerstand aan digitale I/O pinnen 3-10, en schik ze in een rechte rij.

Laden van de bijgevoegde schets.

Typ vanaf de seriële monitor (of terminal emulator), h om het helpmenu.  Dit zal verscheidene opdrachten weergeven.

Mijn klas seriële lezer comprimeert witruimte, zodat u zult willen gebruiken. om te vertegenwoordigen "off" in de regel-instellingen.  Zie de bijgevoegde Quelab.dat monster lijn instelling input file.  De regels van dit bestand kunnen worden geknipt en geplakt in een terminal emulator om in te stellen van het PoV-bericht.

Zodra het gewenste beeldscherm is geladen, gebruiken de s) opdracht EEPROM te worden gebruikt bij volgende reset zijn instellingen opslaan.

 int dummy=0; // this is to force sketch to put arduino include here #define MODE_UNKNOWN 0 #define MODE_PoV 1 #define MODE_RANDOM 2 #define MODE_CYLON 3 #define MAX_COLS 96 #define SERIAL_BUF_LEN (MAX_COLS+15) #include SerialLineBuffer LineBuf; struct { short nCols; // no. columns in buffer short spaceCols; // no. columns "space" time before repeat or reverse short mode; // MODE_ code from above short cylonCols; // no. cols of time for each cylon flash int colTime; // milliseconds/column int misc[3]; // reserved for future use short disp[MAX_COLS]; // display flags } State; // These are the DI/O pins used for the display #define NPINS 10 int ledPins[NPINS] = {12,11,10,9,8,7,6,5,4,3}; #include void loadState() { int n = sizeof(State); byte *bp = (byte *)(&State); for(int i=0; i < n; i++, bp++) *bp = EEPROM.read(i); if (!validState()) initState(); } void saveState() { int n = sizeof(State); byte *bp = (byte *)(&State); for(int i=0; i < n; i++, bp++) EEPROM.write(i,*bp); } // set state to a reasonable default void initState() { State.nCols = 2; State.spaceCols = 1; State.cylonCols = 10; State.mode = MODE_PoV; State.colTime = 10; // ms for (int i=0; i < MAX_COLS; i++) State.disp[i] = (i&1)?0x5555:0x2aaa; saveState(); } void setup() { int i; for (i=0;i { pinMode(ledPins[i],OUTPUT); } pinMode(13,OUTPUT); // use on-board LED // restore state from EEPROM loadState(); Serial.begin(9600); } void loop() { checkCommand(); int i,dt,k; dt = State.colTime; switch (State.mode) { case MODE_CYLON: dt *= State.cylonCols; for (i=0; i < NPINS; i++) { digitalWrite(ledPins[i],HIGH); delay(dt); digitalWrite(ledPins[(i+NPINS-1)%NPINS],LOW); delay(dt); } for (i=NPINS-2; i >= 0; i--) { digitalWrite(ledPins[i],HIGH); delay(dt); digitalWrite(ledPins[(i+1)%NPINS],LOW); delay(dt); } break; case MODE_PoV: for (i=0; i < State.nCols; i++) { short mask=1; for (k=0; k < NPINS; k++, mask <<= 1) digitalWrite(ledPins[k],(mask & State.disp[i])?HIGH:LOW); } for (k=0; k < NPINS; k++) digitalWrite(ledPins[k],LOW); delay(State.spaceCols*dt); break; default: // random default { dt *= 10; k = random(100); int lvl = (k<50)?LOW:HIGH; int j = random(NPINS); digitalWrite(ledPins[j],lvl); delay(dt); } } digitalWrite(13,digitalRead(13)?LOW:HIGH); // toggle heartbeat } // poll for commands from serial port void checkCommand() { short mask; if (!LineBuf.isComplete()) return; char key = lowCase(*(LineBuf.get())); switch(key) { //short mask; //int k; //char *b; case 'h' : Serial.println(" h) help (print this message)"); Serial.println(" s) save state"); Serial.println(" r) random lights mode"); Serial.println(" c) cylon mode"); Serial.println(" p) PoV sign mode"); Serial.println(" n) no. cols to display"); Serial.println(" t) col time, ms"); Serial.println(" b) blank cols between repeat"); Serial.println(" i) re-Initialize state"); Serial.print( " Lx) Set pattern for line x, 0<=x<="); Serial.println(NPINS); break; case 's' : saveState(); break; case 'r' : State.mode = MODE_RANDOM; break; case 'p' : State.mode = MODE_PoV; break; case 'c' : State.mode = MODE_CYLON; break; case 'i' : initState(); break; case 'n' : State.nCols =nextInt(LineBuf.get()+1); break; case 't' : State.colTime =nextInt(LineBuf.get()+1); break; case 'b' : State.spaceCols=nextInt(LineBuf.get()+1); break; case 'l' : { char *b = LineBuf.get()+1; int k = ((int)(*b)) - ((int)'0'); if ((k<0) || (k > 15)) break; b++; short mask = (short)(1< for (int i=0; i < State.nCols; i++, b++) { if (isOn(*b)) State.disp[i] |= mask; else State.disp[i] &= ~mask; } break; } default : Serial.print("Unrecognized Command : <"); Serial.print(LineBuf.get()); Serial.println(">"); Serial.println("Send command h for help."); } printState(); printMsg(); } void printState() { Serial.print(State.nCols); Serial.print(" Columns "); Serial.print(State.spaceCols); Serial.print(" "); Serial.print(State.colTime); Serial.println("ms/col"); Serial.flush(); } void printMsg() { int i,k; Serial.println(); for (i=0; i < State.nCols; i++) Serial.print("-"); short mask=1; for(k=0; k < NPINS; k++, mask <= 1) { for (i=0; i < State.nCols; i++) Serial.print(State.disp[k]&mask?"X":" "); Serial.println("|"); } Serial.println(); for (i=0; i < State.nCols; i++) Serial.print("-"); Serial.println(); Serial.flush(); } // parse next int from a string int nextInt(const char *s) { const char *c = s; int val = 0; for(;;) { int k = ((int)(*c)) - ((int)'0'); if ((k<0)||(k>9)) return val; val *= 10; val += k; c++; } } bool isOn(const char c) { if ((c=='0') || (c=='.') || (c==' ') || (c==0)) return false; //if ((c=='1')||(lowCase(c)=='x')) return true; return true; } bool validState() { // check for silly state, set to default if inconsistent if ((State.mode <= 0) || (State.mode > 3) || (State.nCols< 1) || (State.nCols>MAX_COLS)) return false; if ((State.spaceCols < 1) || (State.spaceCols > 10*MAX_COLS)) return false; if ((State.colTime < 1) || (State.colTime > 10000)) return false; if ((State.cylonCols < 1) || (State.cylonCols > 10000)) return false; return true; } 

---ioUtil.h

 class SerialLineBufferPrivates; class SerialLineBuffer { public: SerialLineBuffer(); //~SerialLineBuffer(); bool isComplete(); // reads from serial, return true if 0 or EOLN void clear(); void begin(); int length() const; int maxLength() const; char *get(); // retrieve current buffer and clear char buf[SERIAL_BUF_LEN+1]; protected: int _maxLength, _len; bool _complete; private: //class SerialLineBufferPrivates *Priv; }; char lowCase(const char a); int caseCmp(const char a0, const char b0); char *extractKey(char *cmdStr, char **val); bool keyMatch(const char *key, const char *key1); 

---ioUtil.cpp

 #include #define NULL 0 // don't want to depend on ctype.h, just for this! bool isBlank(int c) { if(c == 7) return(false); // bell return( (c <= ' ') || (c > '~') ); } #if defined(ARDUINO) && ARDUINO >= 100 #include #warning ARDUINO #else #error ARDUINO not >= 100 #include #endif void SerialLineBuffer::begin() { _maxLength = SERIAL_BUF_LEN; // AVR dynamic mem is tricky _len = 0; _complete = false; } SerialLineBuffer::SerialLineBuffer() { begin(); } bool isTerminator(int c) { if (c == 0) return(true); if (c == ';') return(true); // sending \n to serial is tricky. accept this too. //if ((c=='\n') || (c=='\r') || (c=='\m')) return(true); if ((c>=10) && (c<=13)) return(true); // \r, \n, form feed, vert tab return(false); } /// read from serial, return true if 0 or EOLN bool SerialLineBuffer::isComplete() { if (_complete) return(true); // don't read more until this line is consumed // add characters from serial while(Serial.available() > 0) { int nextByte = Serial.read(); //Serial.print("Got ");Serial.println(nextByte); if ((nextByte < 0) || (nextByte >= 256)) return(_complete); if (isTerminator(nextByte)) { //Serial.print("terminator ");Serial.println(nextByte); buf[_len] = 0; _complete = (_len > 0); return(_complete); } if (isBlank(nextByte)) { //Serial.print("blank ");Serial.println(nextByte); if (_len > 0) // ignore leading whitespace { if (buf[_len-1] != ' ') // compact space to 1 space { buf[_len++] = ' '; // convert all space to ' ' } } } else { buf[_len++] = (char)nextByte; } // don't allow overflow if (_len >= _maxLength) { Serial.println("\nOverflow. truncating command string"); _complete = true; } } return(_complete); } void SerialLineBuffer::clear() { _len = 0; _complete = false; } int SerialLineBuffer::length() const { return(_len); } int SerialLineBuffer::maxLength() const { return(_maxLength); } /// retrieve current buffer and clear char *SerialLineBuffer::get() { buf[_len]=0; clear(); return(buf); } //----------------------------------------------------------- /// split a keyword-value pair string into a key string and value string const char nullChar = 0; // static is scary on AVR char *extractKey(char *cmdStr, char **val) { *val = (char *)&nullChar; if (cmdStr == NULL) return(NULL); char *key = cmdStr; while (*key) // process comments { if (*key == '#') *key=0; // comment else key++; } key = cmdStr; while(*key && isBlank(*key)) key++; // trim leading space *val = key; while(**val && !isBlank(**val)) *val += 1; // skip key **val = 0; *val += 1; while(**val && isBlank(**val)) *val += 1; // skip whitespace return(key); } char lowCase(const char a) { if ((a >= 'A') && (a <= 'Z')) { int sft = ((int)'a') - ((int)'A'); int b = (int)a + sft; return((char)b); } return(a); } int caseCmp(const char a0, const char b0) { char a = lowCase(a0); char b = lowCase(b0); if (a < b) return(-1); return((a>b)?1:0); } bool keyMatch(const char *key0, const char *key1) { //Serial.print("keyMatch(");Serial.print(key0);Serial.print(",");Serial.print(key1);Serial.print(")="); while(*key0 || *key1) { if (caseCmp(*key0, *key1)) { //Serial.println("false"); return(false); } if (*key0) key0++; if (*key1) key1++; } //Serial.println("true"); return(true); } 

---Invoergegevens voorbeeld

 L0..Q.............l......b.... L1.QQQ............l......b.... L2Q...Q...........l......b.... L3Q...Q.u..u..ee..l..a.a.b.b.. L4Q...Q.u..u.e..e.l.a.aa.bb.b. L5Q...Q.u..u.e..e.l.a..a.b..b. L6Q.Q.Q.u..u.eeee.l.a..a.b..b. L7Q..Q..u..u.e....l.a..a.b..b. L8.Q.Q..u..u.e..e.l.a.aa.bb.b. L9.QQ.Q..uu...ee..l..a.a.b.b.. 

Gerelateerde Artikelen

MAKE Controller persistentie van visie Effect met LEDs

MAKE Controller persistentie van visie Effect met LEDs

Hallo, dit is mijn eerste instructable en ik hoop dat het u bevalt. Het is een eenvoudig project, met behulp van MAKE Controller (een handig controller van www.makezine.com), dat een persistentie-van-visie-effect maakt met behulp van LEDs. Wanneer u
Ultra lage kosten zonne-oplaadbare persistentie van visie display

Ultra lage kosten zonne-oplaadbare persistentie van visie display

dit apparaat produceert een heldere en oog springende weergeven als u wilt schrijven tekst en kleine afbeeldingen door de lucht. Het gebruikt onder £2 (circa 3,20 dollar op het moment van schrijven) van onderdelen, en is een mooie kleine weekend proj
Een LED persistentie van visie naambadge

Een LED persistentie van visie naambadge

dit Instructable toont een naambadge die ik heb gebouwd voor mijn dochter.Ik heb gezien de badges voor Defcon, en dacht dat ze waren cool. Waarom cant mijn kinderen hebben een zo goed - maar speciaal gebouwd voor hen?Zo hier gaat u - een eenvoudige b
Persistentie van de visie weergeven (POV)

Persistentie van de visie weergeven (POV)

Hi guys! Dit is mijn eerste Instructable zo als een gewoon geen fouten maakt me vertellen. OK laten we aan de slag!WAT U NODIG ZULT HEBBEN-Arduino uno-vaste kern draad of lint kabel-9v batterij module-6v motor (ik heb de mijne uit een CD-speler)-rest
Persistentie van de visie

Persistentie van de visie

Persistentie van de visie is een optische illusie, het werkt op een eenvoudige fenomeen de werking van onze dag tot dag televisie. MIJN eerste pov was zes maanden vóór met arduino uno en met buitenboordmotor. Maar het is best om een klein en draagbaa
Persistentie van de visie Bauble. POV decoratie.

Persistentie van de visie Bauble. POV decoratie.

Persistentie van de visie Bauble. POV decoratieHet is de tijd van het jaar de boom opstaan en decoreren met alle prachtige verlichting, klatergoud en kerstballen. En dit project gaat over kerstballen, wanneer ik decoraties op een boom ik kan niet hel
(POV) Persistentie van de visie Globe

(POV) Persistentie van de visie Globe

! Update! Ik heb een excel-programma dat maakt het veel gemakkelijker om te tekenen en code van nieuwe beelden toegevoegd!Een eenvoudige persistentie van de visie globe. VIDEO afspelenDit is een project dat ik heb in gedachten had voor heel wat tijd
Bol van de persistentie van de visie

Bol van de persistentie van de visie

Hallo iedereen,Deze tutorial toont je hoe te bouwen uw eigen bol van de persistentie van de visie.Ten eerste, wat is een bol van de persistentie van de visie? Het idee is om het draaien van een kolom met LEDs snel genoeg voor de indruk van een hele w
Hard Drive persistentie van de visie (HDPOV)

Hard Drive persistentie van de visie (HDPOV)

de schaal van een harde schijf draaiingen ruim zestig keer per seconde. Als een smalle sleuf werd gesneden in de schotel om LEDs te schitteren door, kunnen we bereiken flikkeren fusion en Truc van het oog in het zien van een stabiel beeld. Dit fenome
Pulse Arduino uitvoer van Android mobiele. Geen programmeerkennis vereist

Pulse Arduino uitvoer van Android mobiele. Geen programmeerkennis vereist

IntroductieDit Instructable toont u hoe u met de gratis app, pfodDesigner, een menu op uw Androïde mobiele dat zal een uitvoer op je Arduino board pulse zonder dat u code te schrijven helemaal ontwerpen. De pfodDesigner genereert de code van de Ardui
Elektronische muziekdoos aangedreven door Arduino (soort van)

Elektronische muziekdoos aangedreven door Arduino (soort van)

muziek is de meest universele middel van expressie. Ongeacht culturele taal of leeftijd die het idee wel muziek overgebracht zou niet veel verschillen. Het is veilig om te zeggen dat iedereen houdt van muziek, één type of een ander. Wanneer iemands f
Arduino controle van uw iOS-apparaat en uw Apple Watch

Arduino controle van uw iOS-apparaat en uw Apple Watch

Deze eenvoudige instructable is over Arduino Manager, een krachtige General-Purpose iOS App die het mogelijk maakt om te controleren elke Arduino (of Arduino compatibel) bestuur door middel van 30 verschillende Widgets.Enkele van de beschikbare Widge
Crowder van vis, vers gevangen!

Crowder van vis, vers gevangen!

Mijn vis chowder recept is een familie favoriete tijdens de wintermaanden. Dit Instructable toont mijn methode, genieten!Stap 1: Vis Prep Voor meer informatie over het vangen en fileren van vis check mijn vissen instructable (hoe te vangen schoon en
Maken van vis artefacten voor Parade in Kanda Festival met ambacht & 3D

Maken van vis artefacten voor Parade in Kanda Festival met ambacht & 3D

In Japan hebben we een traditie van het maken van een verscheidenheid van fantasierijke artefacten voor paraderen in festivals. Voor dit jaar Kanda Festival van Kanda heiligdom (ward Chiyoda, Tokio), we geroepen vis artefacten met handwerk en 3D-tech