Tilgjengeligheten til billige steppermotorer og drivere i disse dager gir god mulighet til å eksperimentere utenfor de dyrere og kompliserte 2D / 3D kutt- og trykkprosjektene.
For dette prosjektet tar jeg OpenBuilds-kameraets glidebryter (referer til bygningsvideoen i å bygge en grunnleggende videoregler med Open Source CNC-deler) og motoriser den. Jeg skal også lage et selvstendig system for styring av motoren.
Denne opplæringen dekker spesielt å sette sammen maskinvaren, men bygger først og fremst en rudimentær 16x2 LCD-GUI ved hjelp av LiquidCrystal-biblioteket og et enkelt menysystem for visning, etterfulgt av arbeidet med A4988-stappedriveren og hvordan man styrer det med Arduino.
Dette prosjektet er tungt på løkker og trinn, og i mellomtiden er prosjektet mer mellomliggende, jeg har forsøkt å forklare det på en slik måte at nybegynnere kan kjøre seg relativt raskt.
Jeg vil dekke å legge til motor og remskiver til glidebryteren, stramme beltet rundt og feste det hele opp. Det er en enkel modifikasjon.
Deretter skal jeg dekke hvordan du kan sette sammen et Pololu A4988 Black Edition-sett og hvordan du kobler det opp på et brettbrett sammen med alle de andre eksterne brettene, samt en enkel kryssfinérhylling jeg banket sammen om noen minutter for min 12V strøm forsyning (oppført ovenfor) for å forhindre støt når ledningsklemmene blir utsatt.
Menyen tillater innspilling av avstand til reise, tid til å reise, Antall trinn for å reise inn og kjøreretning. På slutten av hvert trinn pause skyveknappen mens kameraet utløses.
OpenBuilds V-Slot Aktuator End Mount har NEMA 17 dimensjon hull i den, så fire 30mm M3 cap hode skruer er alt som kreves for å montere motoren til den.
Kontroller at 20-tommers GT2-remskiven er inne i festet før du slår inn motorakselen, da monteringen ikke er bred nok til å legge den på etterpå. Når motoren er skrudd på bunnen, festes skruene med en av dem mot den flate delen av motorakselen, slik at tennene er direkte i linje med midten av hele ekstruderingsenheten.
Rulleskiven settes sammen, akkurat som et hjulsett, og slår inn i motsatt ende. Aktuatormontering:
Før beltet gjennom midten av V-sporet i tråd med remskiven, slik at tennene vender opp.
Deretter mate den opp og over de to remskiver og ta den tilbake i midten til dolly-byggeplaten.
Her vikler du den ene siden gjennom beltesporet og klemmer, eller glidelås den, og bruk den for å stramme hele beltet gjennom hele systemet før du kobler den andre siden. Ikke for tett for at motoren skal snu, men ikke løs nok til å hoppe over tennene på drivhjulet!
Pololu A4988 Black Edition Stepper Motor Driver (teknisk A4988 bæreplate - A4988 er selve brikken) kommer vanligvis i settform, noe som ganske enkelt betyr at hodene må loddes på. Siden dette er en kraftkomponent, selv om den ikke kjører enheten med maksimal kapasitet, er det en god ide å legge til en heatsink for å forbedre levetiden.
Bryt toppraden i halv for å ha to rader med åtte. Slå disse inn i de forgylte hullene i brettet, og sper dette forsiktig inn i brødbrettet. Løsn pinnene på plass mens breadboard holder alt godt og vinkelrett.
Når dette er ferdig, kutt av hjørnet av en liten selvklebende heatsink ved hjelp av en hacksaw eller rullesag (forsiktig, i en klemme!) For å montere til A4988 IC.
Nå må alt monteres på breadboards slik at det kan kobles sammen til en fungerende cicuit. Jeg bruker separate plater for hver del for å få klarhet i bildene, men vær så snill å passe det hele inn i et enkelt bord hvis du ønsker det.
LCD-tastaturet skjerm kan ikke monteres på et bord, takket være Arduinos merkelige valg å holde seg til en designfeil i stedet for å oppfylle standarder. Dette vil bli holdt skilt, skjønt å skru det til et tre eller noe å beskytte pinnene, er kanskje ikke en dårlig ide.
Kamerautløserkretsen er på sin mest enkle måte bestående av en motstand, en transistor og en 2,5 mm TRS sub-miniprop. Jeg har lagt til en lysdiode som vil blinke når utløserstiften er høy og en 3,5 mm TRS mini-jack for å tillate fleksibilitet.
Hvis du kjøper komponenter til denne konstruksjonen, ville en 3,5 mm sokkel utformet for 0,1 "pitch boards være en god ide, men min er fra scavenged haugen, så jeg har loddet en kontakt til den i stedet.
Legg alt ut, klar til å koble det hele opp.
Tid til å ta tak i alle jumperkablene. Å ha nok til å holde tingene fargekodede, vil gjøre livet enklere når du feilsøker. Se kretsdiagrammet øverst hvis følgende beskrivelse forvirrer deg når som helst.
Først skru opp LCD-skjermen. Ta 10 kvinnelige hoppere og koble dem til følgende skjoldstifter: Digitale pinner 4-9, strømbøssestifter tilbakestilles (hvis du vil bruke LCD-reset-knappen), 5V og en av GNDs.
Hvis du har joggesko, kan du legge den der. Hvis ikke, kobler du mannlige hoppere til den andre enden av hunnene - for å koble dem til de tilhørende Arduino-koplingsstikkene. Hvis du har et LCD-tastaturskjold som har passerende kvinnelige hoder installert på toppen, kan du hoppe over dette trinnet, siden skjoldet ditt ikke blokkerer noe.
Deretter, Pololu A4988 bordet. Dette trenger åtte hoppere på den ene siden, jeg har brukt svart og rødt for logikk / motorkraft ved letthet, og rød / grønn / blå / gul i midten fire for å matche opp med stepperens servo-ledninger.
Den logiske kraftpinnen går til 3,3V på arduino, da LCD-skjermen ovenfor bruker 5V-pin. Motorens strømledninger går til 12V strømforsyningen. På den andre siden, nær A4988-brikken, bruker jeg blå og oransje for STP og DIR henholdsvis til kontrast med de relativt ensartede fargene overalt. De går til henholdsvis Arduino pins 11 og 12, med mindre du endrer koden. Så kort RST og SLP sammen for å holde styret aktivert; Jeg har brukt den hvite ledelsen her.
Til slutt kobler du kamerautløserbryterkretsen. Her er de svarte ledningene jordet - A-ledningen til Arduino, C-ledningen til 3,5 mm-kontakten. Den gule går til Arduino pin 13 (så det er en LED-indikator på bordet, så vel som på bryteren!), Og den røde ledningen går til den andre siden av 3,5 mm-kontakten (eller 2,5 mm pluggen hvis du skal den ruten).
Plugg stepper motoren i de fargede ledningene i henhold til A4988 brettdiagrammet og stappers datablad. For meg var det slik:
Forsiktighet: Husk at ledningene som gir strøm til motoren, sannsynligvis vil trekke 1-2A ved valgt spenning, så sørg for at ledningene som brukes er vurdert for det. A4988-brikken og brettet rundt det kan bli varmt! Potentiometeret som er innebygd i brettet gir nåværende begrensning for å beskytte både A4988 og motoren, så sørg for at du setter det riktig før du bruker et multimeter.
Når komponentene er satt sammen, kan du flytte til kodingen. Last ned postkortet som følger med denne opplæringen, eller sjekk dette GitHub respository hvis du foretrekker det. Jeg vil beskrive hvordan jeg legger den sammen slik at du kan forstå den generelle programflyten og hvordan modulene fungerer sammen.
Det eneste som er nødvendig for dette var LCD-skrivbiblioteket LiquidCrystal.h
. Dette gir tilgang til lcd.xxxx ()
funksjoner. Det er en pulver ()
i programmet, og jeg fant det med C ++-biblioteket math.h
er ikke nødvendig da noen av de mest nyttige funksjonene er inkludert i lager Arduino miljøet, inkludert pulver ()
.
#inkludereLiquidCrystal lcd (8, 9, 4, 5, 6, 7); // sett LCD utgangsstifter // definer stepper driver pins const int stp = 11; // kan ikke bruke pin 10 med SS LCD som det er bakgrunnsbelysningskontrollen. // hvis det går lavt, slås bakgrunnsbelysningen av! const int dir = 12; // definere trigger pin const int trig = 13; // KNAPPER // definere knappverdier const int btnUp = 0; const int btnDn = 1; const int btnL = 2; const int btnR = 3; const int btnSel = 4; const int btnNone = 5; // definere knappavlesningsvariabler int btnVal = 5; int adcIn = 0;
Jeg setter LCD-utgangspinnene, stapperdriverens utgangspinner og kamerautløseren. Når selve maskinvaregrensesnittet er satt opp, la jeg til variabler for knapphendelser etterfulgt av knappavlesingsfunksjonen, som jeg tilpasset fra DFRobot-wiki på deres identiske LCD-tastaturskjerm. Legg merke til at SainSmart gir ingen dokumentasjon.
Dette er super straightfoward. Initialiser LCD-skjermen og relevante utgangsstifter, etterfulgt av en grunnleggende velkomstskjerm, og slipp deretter til startskjermbildet: menyalternativ 1 med verdier nullstillet.
ugyldig oppsett () lcd.begin (16, 2); // initialiser LCD lib fullskjerm lcd.setCursor (0,0); // sett markørposisjon pinMode (stp, OUTPUT); // initialiser stepper pins pinMode (dir, OUTPUT); pinMode (trig, OUTPUT); // initialiser utløserknappen digitalWrite (trig, LOW); // sørg for at utløseren er slått av lcd.print ("Welcome to"); // velkomstskjerm lcd.setCursor (0,1); lcd.print ("SliderCam v0.2!"); forsinkelse (1000); lcd.clear (); lcd.print (menuItemsTop [0]); forsinkelse (100); lcd.setCursor (0,1); for (int i = 0; i < 4; i++) lcd.setCursor(i, 1); lcd.print(currentDistance[i]); lcd.setCursor(4,1); lcd.print("mm(max 1300)");
Fordelen her er kodende, at utstyret ikke trenger å gjøre noe i det hele tatt uten brukerinngang. Det betyr at det aller første kan bare være en evig knappestikksløyfe. Ringer på readLcdButtons ()
Fungerer om og om igjen til verdiendringer ikke påvirker programytelsen negativt, og du trenger ikke å bekymre deg for å forlate avbruddsnåler.
void loop () do btnVal = readLcdButtons (); // leser kontinuerlig knappene ... mens (btnVal == 5); // ... til noe er trykket
// erklære knappavstemmingsfunksjon int readLcdButtons () forsinkelse (90); // debounce forsinkelse, innstilt eksperimentelt. forsinkelse er bra som program skal ikke gjøre noe annet // på dette tidspunktet uansett adcIn = analogRead (0); // les verdien fra pin A0 / * terskelverdier bekreftet ved eksperimentering med knappkalibreringskisse, retur følgende ADC-lesverdier: høyre: 0 opp: 143 ned: 328 venstre: 504 velg: 741 * / hvis (adcIn> 1000) returnerer btnNone ; hvis (adcIn < 50) return btnR; if (adcIn < 250) return btnUp; if (adcIn < 450) return btnDn; if (adcIn < 650) return btnL; if (adcIn < 850) return btnSel; return btnNone; //if it can't detect anything, return no button pressed
ReadLcdButtons ()
har en forsinkelse på 90ms for å kunne debounce knappene. I virkeligheten er dette ikke en debounce, da den ikke gjenopptar ADC-måling etter et bestemt tidsrom, men snarere velger knappene sjelden nok til sjelden å registrere mer enn ett enkelt klikk.
Den oppnår det samme fra en praktisk UX-visning. Det er mer av en meningsmåling knappene hver 90m i stedet for hele tiden, det er derfor bruk av utsette()
er generelt ikke ansett som god praksis for debouncing formål, men det løste problemet (bare hver ende av menyene var tilgjengelig).
Når enheten kan reagere på inngang, må det være en måte for den å vise disse reaksjonene.
Etter å ha prøvd oppdateringsoppdateringer, bestemte jeg meg for at konsistent skjermoppdatering som et ekte operativsystem var lettere å håndtere i forsøkene på en modulær oppgraderbar struktur. Å gjøre dette er like enkelt som å rydde skjermen, og deretter gjenoppbygge basert på kjente nåværende parametere.
Dette høres komplisert, men i praksis gjør livet mye lettere. Den fjerner et stort antall LCD-kommandoer fra andre steder i programmet, og oppretter en variabeltype-agnostisk sone som minimeres av programoppdateringer utenfor den.
Den faktiske forfriskende delen utviklet seg til å bestå av fire forskjellige trinn:
Tilbakestill parametere ...
// SKRIV NYE SKJERMVARUER btnVal = btnNone; lcd.clear ();
... skriv ut topplinjen ...
lcd.setCursor (0, 0); lcd.print (menuItemsTop [currentMenuItem]); // Skriv ut toppnivå menyelement
... skrive ut bunnlinjen, som jeg vil forklare litt senere ...
lcd.setCursor (0,1); bytte (currentMenuItem) tilfelle 0: for (int i = 0; i < 4; i++) lcd.setCursor(i, 1); lcd.print(currentDistance[i]); break; case 1: for (int i = 0; i < 6; i++) lcd.setCursor(i, 1); lcd.print(currentDuration[i]); break; case 2: for (int i = 0; i < 4; i++) lcd.setCursor(i, 1); lcd.print(currentSteps[i]); break; case 3: if (travelDir == 0) lcd.print("From Motor"); else lcd.print("To Motor"); break; case 4: lcd.print("Stop!"); break; //end switch
... og legg til skjermspesifikke kommandoer over toppen av det som allerede er skrevet ut.
hvis (currentMenuItem == 0) lcd.setCursor (4,1); lcd.print ("mm (maks 1300)"); // Sett inn maksimal transport på glidebryteren brukt hvis (currentMenuItem == 1) lcd.setCursor (6,1); lcd.print ( "s (3600 / hr)"); hvis (currentMenuLevel == 1) lcd.setCursor (currentCursorPos, 1); lcd.blink (); annet lcd.noBlink ();
Naturligvis skriver den eksakte skjermoppdateringsseksjonen seg ikke, og vi må vite hvilken meny den skriver til å skjerme før den kan fullføres. Hovedoverskriftene er enkle, siden de ikke endres, avhengig av brukerinngang. Dette betyr at det bare kan være en strengmatrise - teknisk en char pointer array, eller en rekke arrays:
// MENU GUI // definere toppnivå menyelement strenger for numerisk navigering char * menuItemsTop [] = "01 Avstand>", "< 02 Duration >","< 03 Steps > ","< 04 Direction >","< 05 Go!"; int currentMenuLevel = 0; //top menu or submenu int currentMenuItem = 0; //x-axis position of menu selection int currentCursorPos = 0; //current lcd cursor position int currentDistance[4] = 0, 0, 0, 0; int currentDuration[6] = 0, 0, 0, 0, 0, 0; int currentSteps[4] = 0, 0, 0, 1;
Dette betyr at dette menuItemsTop
array kan navigeres ganske enkelt ved å endre tallet inne i firkantede parentes på skjermoppdateringstidspunktet. Det som bare skjer, siden alt er nullindeksert, sporer identisk med heltallet currentMenuItem
.
manipulering currentMenuItem
På knapphendelser tillater vi endimensjonal navigasjon, så når du ser menuItemsTop [currentMenuItem]
det er åpenbart nåværende menyoverskrift.
hvis (currentMenuLevel == 0) switch (btnVal) tilfelle btnL: hvis (nåværendeMenuItem == 0) bryte; // kan ikke gå til venstre herfra nåværendeMenuItem--; gå i stykker; tilfelle btnR: hvis (currentMenuItem == 4) pause; // kan ikke gå rett fra her annet nåværendeMenuItem ++; gå i stykker; tilfelle btnSel: currentMenuLevel ++; hvis (currentCursorPos> 3 && (currentMenuItem == 0 || currentMenuItem == 2)) currentCursorPos = 3; // Ikke gå av slutten av tallene for de firesifrede tallene hvis (currentCursorPos> 0 && (currentMenuItem> 2)) currentCursorPos = 0; // sett blinkende markør til venstre for tekstbaserte alternativer hvis (currentMenuItem == 4) motion = 1; bevegelseskontroll(); gå i stykker; // slutten av bryteren // slutten av nivå 0
Så du kan flytte til venstre og høyre, og gå inn i en meny, eller i tilfelle av Gå! så er bevegelseskontroll aktivert. Det er alt som kreves her.
Undermeny-systemet tok litt mer, takket være den interne kompleksiteten. De tre første oppføringene, Avstand, Varighet og Steps, Teknisk bestå av en underundermeny, som hver tillater navigering av den flersifrede verdien, så vel som hver enkelt karakter.
Dette er dekket ved å gjøre hver undermenyoppføring et byttesystem i sin egen rett. Selv om dette var langt, er det en enkel og konsistent metode for å tillate slike navigasjoner på lavt nivå. Siden jeg egentlig bare skjønte ut Avstand undermenyen og kopierte den over til de andre undermenyene, her er en titt på den.
ellers // dvs. "annet hvis currentMenuLevel = 1" if (currentMenuItem == 0) // 01 DISTANCE-bryteren (btnVal) case btnUp: currentChar = currentDistance [currentCursorPos]; adjustDigit (currentChar, 1); currentDistance [currentCursorPos] = currentChar; gå i stykker; tilfelle btnDn: currentChar = currentDistance [currentCursorPos]; adjustDigit (currentChar, 0); currentDistance [currentCursorPos] = currentChar; gå i stykker; tilfelle btnL: hvis (currentCursorPos == 0) pause; // kan ikke gå til venstre herfra nåværendeCursorPos--; gå i stykker; tilfelle btnR: hvis (currentCursorPos == 3) pause; // kan ikke gå til venstre herfra nåværendeCursorPos ++; gå i stykker; tilfelle btnSel: parseArrayDistance (); currentMenuLevel--; // sluttbryter / / slutt DISTANCE
Venstre og høyre er i det vesentlige det samme som toppmenyen, bare å flytte frem og tilbake langs tallet på samme måte, ved å ha Nummer faktisk være et sett med siffer i en int array og gjeldende plassering lagret i en int-kalt currentCursorPos
som gjør det mulig å blinke som vist i skjermoppdateringsmodulen ovenfor.
Hvis du skriver ut disse arrays langs den nederste LCD-raden, er det for loops for i skjermoppdateringsdelen; Jeg
fra 0 til 3, LCD-kolonne
fra 0 til 3, currentDistance []
fra 0 til 3.
int adjustDigit (int x, int dir) // sifferjusteringsfunksjon hvis (dir == 0 && x> 0) x--; // trekke fra siffer på btnDn hvis (dir == 1 && x < 9) x++; // add to digit on btnUp lcd.setCursor(currentCursorPos, 1); lcd.print(x); currentChar = x; return currentChar; //return new digit
Å øke og redusere tallet oppnås ved å lagre det nåværende sifferet i variabelen currentChar
, som deretter sendes til adjustDigit ()
funksjon sammen med en boolsk verdi indikatorretning; å øke eller redusere motoren.
Dette justerer bare sifferet i henhold til den boolske verdien og lagrer resultatet, hvoretter strømmen vender tilbake til hovedløkken, der gjeldendeChar-verdien lagres tilbake til den riktige posisjonen til originalen currentDistance []
array og det nye justerte sifferet skrives ut på skjermoppdatering.
Når Select velges fra en av tallrissens undermenyer, utløser den den relevante parsing-funksjonen - i dette tilfellet parseArrayDistance ()
. Du må analysere arrayet som brukes til å vise og redigere det, til et heltall som er nyttig for faktiske bevegelsesberegninger. Jeg valgte å gjøre dette nå heller enn på Gå! for å holde UX følelsen snappy.
int adjustDigit (int x, int dir) // sifferjusteringsfunksjon hvis (dir == 0 && x> 0) x--; // trekke fra siffer på btnDn hvis (dir == 1 && x < 9) x++; // add to digit on btnUp lcd.setCursor(currentCursorPos, 1); lcd.print(x); currentChar = x; return currentChar; //return new digit
Jeg kom opp med denne funksjonen fra den en nyttige passerende kommentaren jeg fant etter å ha slitt ut Google, og lette etter standard array-to-int-funksjoner, kom opp tom og slettet med rotet av array-to-char-to-int-funksjoner som var en ineffektiv løsning. Det virker ganske kort og lett gitt at det er bokstavelig talt basert på grunnlaget for desimal matematikk, men hvis du vet en bedre metode, er jeg alle ører.
Alle verdiene er satt og du treffer Gå! Hva skjer etterpå? Du må beregne nøyaktig hva tallene som er oppgitt til det skal gjøre for å kunne kjøre den endelige bevegelsen. Denne delen er funksjonell, men et arbeid pågår; Jeg føler at det må være flere alternativer for ulike typer bevegelse.
int motionControl () totalMotorSteps = currentDistanceInt * 5; // beregne totale trinn (0.2mm = 20-tannhjul på 2mm båndbelte, 40mm per omdreining, 200 trinn per omdreining, ergo 1/5 mm per trinn) pulseDelay = (1000L * (currentDurationInt - (currentStepsInt * shutterDuration))) / totalMotorSteps; // hvor lang tid å pause i ms mellom STP-pulser til motordriveren intervalDistance = totalMotorSteps / currentStepsInt;
Hva som skjer i denne funksjonen er ganske tydelig fra kommentaren, tror jeg. Jeg har satt en shutterDuration
av 2 sekunder i programvaren, hovedsakelig for å fortsette å teste ganske raskt. Hvis du skyter om natten, ved lavere ISO, må dette kanskje være mer som 25-35 sekunder avhengig av nøyaktig lukkerhastighet.
De pulseDelay
multipliseres med 1000
på slutten å konvertere fra sekunder til millisekunder, selvfølgelig. De L
å konvertere den konstante int til en lang er mer som jeg går på side av forsiktighet enn faktisk er strengt nødvendig. Siden det er en relativt liten skisse, er jeg ikke så bekymret for variabel minnebruk.
Disse beregningene antar at sløyfen selv krever en ubetydelig tid til å løpe i forhold til pulseDelay
Tid, som, når jeg tok ut knappevalget, ser ut til å være sant.
// en gang per samlet kjøre hvis (travelDir == 0) digitalWrite (dir, LOW); ellers hvis (travelDir == 1) digitalWrite (dir, HIGH); //Serial.begin(9600); //Serial.println(pulseDelay); // trinnsløyfe gjør digitalWrite (stp, HIGH); // brannmotorstyreforsinkelse (pulseDelay); digitalWrite (stp, LOW); // Tilbakestill driver // btnVal = readLcdButtons (); // Sjekk at det ikke er noen stopp - dette tar for lang tid og senker motoren betydelig; bruk tilbakestill for stopp! currentStep ++; // ved slutten av hvert trinn hvis (currentStep% intervalDistance == 0) // hvis nåværende antall motorstrinn er delbart med antall motorstrinn i et kamerasteg, brann kameraet digitalWrite (trig, HIGH); // utløseren for kamerautløseren (80); digitalWrite (trig, LOW); // Tilbakestill utløserknappforsinkelse ((shutterDuration * 1000) -80); // forsinkelse må skiftes til timer slik at stoppknappen kan polles mens (currentStep < totalMotorSteps); //end motion control
Til slutt noter du currentSteps
verdi satt til 1. Jeg har ikke opprettet en feilkontrollfunksjon for dette, men enkel sunn fornuft sier Trinnstørrelse
blir uendelig hvis currentStepsInt == 0
, så det er best å holde det på en hvis kontinuerlig bevegelse er ønsket. Jeg har allerede lagt til en forbedringsoppføring for dette.
For noe som kjører på kode som er skrevet mer eller mindre fra bunnen av to dager og feilfri over to, virker det som en drøm! Beviset er i pudding, skjønt. Får det faktisk verdig timelapseopptak, og fungerer kontrollenheten virkelig bra i feltet?
I mine tester synes svaret å være en helhjertet ja. Nedenfor er en to-timers 650-timelapse-tidsplan, den aller første testen. Skyvekontrollen fullførte også en 9 timers 720 rammeprøve feilfritt, men dessverre gjorde kameraets batteri ikke så bra etter 2 timer i ... som jeg ikke fant ut før 8,5 timers markering, naturlig.
Hvis jeg setter tid og trinn på riktig måte, kan bevegelsen være kontinuerlig for sakte dolly-bevegelser i live-actionvideo, selv om de jerky endene må redigere ut eller hastighetsrampe.
Lyd kan være et problem med mindre stepper er veldig stille, men for å legge til produksjonsverdi for selvopptak, er det et alternativ.
Som med noe, er det mulige forbedringer som skal gjøres. Jeg har listet disse på toppen av .ino
fil, men selvsagt uten særlig omhu over gjennomførbarhet eller bestilt av noen form for betydning.
Noen av disse vurderte jeg å fikse før jeg slettet denne veiledningen med v0.2, men jeg føler at de i seg selv er en lærerfaring å se på når det gjelder å demontere brukbarheten av et program.
FORBEDRINGER OG HENSYN TIL V1.0: 1) Effektivitet av undermeny-knappens svarkode for de første tre menyhodene 2) Bruk av pæreutløsertid som et ekstra menyalternativ, bestått til shutterDuration int 3) Lukkerens varighet bør være tidsbestemt pause, ikke forsinkelse ) - kan ikke stoppe stoppknappen! 4) Bruk EEPROM-biblioteksfunksjonene til å lagre mengder, og dermed forenkle bevegelsestyringsdelen og bruk Tilbakestill som "stopp" 5) Fjern bryteren fra "Gå" undermenyen, erstatt med mer hensiktsmessig logisk setning 6) Ville det være bedre å koble kameraet heller enn total reise? "varighet" er mer som 15 sek eller 2 min enn 30 min eller 4 timer? 7) Vil du være bedre som #definer eller ints bedre som boolsk? Knapt kjører mot grensene for SRAM plass på 8kB, skjønt. 8) Tweening / lettelse for akselerasjonskurver, spesielt for videobruk 9) Feilkontroll for null trinnstørrelse, eller bare legg til en til intervalDistance hvis verdien er null før beregninger - annen ende av Avstanden er fortsatt 1 trinn 10) Ville sub-16ms forsinkelse () s være bedre som delayMicroseconds ()? Hvor mye ødelegger avbrudd timingen? 11) Bruk av søvn på A4988 for å redusere strømforbruket i feltet? 12) Feilkontroll for currentDurationInt <= currentStepsInt*shutterDuration, allowing no time for movement or even negative pulseDelay! */
Dette er bare de forbedringene jeg har tenkt på så langt, i et forsøk på å lede kodebasen fra en rudimentær, men funksjonell v0.2 til en mer optimalisert og mer standby-versjon v1.0. Du kan legge merke til mer. Du er velkommen til å legge dem i kommentarene under eller på GitHub.
Hvis du har fulgt fra begynnelse til slutt, inkludert Photography Tuts + -delen av bygningen, er du nå den stolte eieren av en høykvalitets motorisert skyveknapp som kan produsere timelapsopptak og subtile dollybevegelser. Hvis du bruker koden for et annet prosjekt, vil jeg gjerne se det.
I denne opplæringen har jeg sett på forskjellige former for loopbasert flytkontroll, opprettet en rudimentær GUI og oppdaterer en LCD basert på brukerinngang. Jeg så også på samtidig styring av flere eksterne mekaniske enheter via breakout boards.
Du har sett flyt og enkel programmering av modulær kode, samt å se ideer for hvordan du kan forbedre koden som er funksjonell, men ikke optimalisert, både fra UX og prosessor effektivitet standpoints. Disse verktøyene skal tjene deg godt for en rekke kommunikasjons- og interaksjonsbaserte prosjekter i fremtiden.
Vennligst legg inn eventuelle spørsmål eller kommentarer kommentaren nedenfor!