Programmering for begyndere Brug af Arduino Programmeringskursus Brug af digitale ind og udgange
Oversigt over aftenen Digitale ind- og udgange Det er der ikke så meget i: Digitale indgange kan tænde og slukke lysdioder Digitale udgange kan aflæse kontakts stilling (Åben / lukket) Det skal vi lige prøve det har vi ikke gjort før i projektet Jeg pakke det ind i programmer og eksempler Vi har i det mindste følgende udfordringer: Hvordan blinker man med en diode uden alt går istå? Hvordan undgår man at vente på langsom hardware?
Digital indgang Prel fra en kontakt? Funktionen aflæser en kontakt og returnere tilstanden når den er stabil boolean kontakt(int pin) boolean tilstand; boolean tidligeretilstand; tidligeretilstand = digitalread(pin); for(int counter=0; counter <preltid; counter++) delay(1); tilstand = digitalread(pin); if( tilstand!= tidligeretilstand) counter = 0; tidligeretilstand = tilstand; return tilstand; Globale variable: int preltid Hvis preltid = 10 skal kontaktes tilstand være stabil i 10 ms.
Overskrifter for i aften Derfor bliver aftens hovedemner Blink med en diode uden brug af delay Blik med to dioder!... (mere) Pointere Det er varianter over emnet: Har andet at lave end at vente på hardware
Hvad er lang ventetid? Om det er rimelig ikke at vente afhænger af om vi kan lave noget andet i mellemtiden. Eller: Hvor hurtig er processoren egentlig? Hurtig oplag giver om Arduino: Krystalfrekvens: 16 MHz krystal Regnehastighed: 16 MIPS 63 ns/instruktion
Hvad er lang ventetid? Eksempel på maskinsprog 11: c = a + b; 0C4 0E02 MOVLW 0x2 0C6 CFDB MOVFF 0xfdb, 0x2 0C8 F002 NOP 0CA 0E03 MOVLW 0x3 0CC CFDB MOVFF 0xfdb, 0x3 0CE F003 NOP 0D0 50DE MOVF 0xfde, W, ACCESS 0D2 2402 ADDWF 0x2, W, ACCESS 0D4 6E00 MOVWF 0, ACCESS 0D6 50DD MOVF 0xfdd, W, ACCESS 0D8 2003 ADDWFC 0x3, W, ACCESS 0DA 6E01 MOVWF 0x1, ACCESS 0DC 0E04 MOVLW 0x4 0DE C000 MOVFF 0, 0xfdb 0E0 FFDB NOP 0E2 0E05 MOVLW 0x5 0E4 C001 MOVFF 0x1, 0xfdb 0E6 FFDB NOP c = a + b 19 instruktioner á Varighed : 19 * 63 ns = 1,2 μs 840 additioner på 1ms
Undgå at vente i programmet Blink med diode uden brug af delay()
Blink uden brug af delay() void loop() // hentet fra www.arduino.com Her kan indsættes kode som ikke må vente unsigned long currentmillis = millis(); if(currentmillis - previousmillis > interval) previousmillis = currentmillis; // gemmer sidste skift af LED if (ledstate == LOW) // hvis LED er OFF ændres til ON og omvendt ledstate = HIGH; else ledstate = LOW; digitalwrite(ledpin, ledstate); // skriver til LED:
Blink uden af delay() ON OFF Programmeringskursus nej LED OFF? ja ON OFF nej tid ja ja tid nej gået gået?? Gem tidspunkt Gem tidspunkt Sluk LED Tænd LED
Blink uden af delay() ON OFF Programmeringskursus void loop() if (ledstate == LOW ) if((tid - skifttid) > OFFTID) skifttid = Tid; // Gemmer tiden for skift ledstate = HIGH; // Skifter tilstand for LED digitalwrite(ledpin, ledstate); else if((tid - skifttid) > ONTID) skifttid = Tid; // Gemmer tiden for skift ledstate = OFF; // Skifter tilstand for LED digitalwrite(ledpin, ledstate); // loop() Her kan indsættes en mase kode, som ikke behøver at vente på at der blinkes med dioden.
Blink med to dioder (ON OFF) Programmeringskursus Med en diode har vi variablerne: ONTID OFFTID ledstate skifttid Med to dioder kunne vi lave variablerne: ONTID1 OFFTID1 ledstate1 skifttid1 ONTID2 OFFTID2 ledstate2 skifttid2 Så kunne vi jo skrive noget kode to gange
Blink med to dioder ON OFF Programmeringskursus void loop() if (ledstate == LOW ) if((tid - skifttid) > OFFTID) skifttid = Tid; // Gemmer tiden for skift ledstate = HIGH; // Skifter tilstand for LED digitalwrite(ledpin, ledstate); else if((tid - skifttid) > ONTID) skifttid = Tid; // Gemmer tiden for skift ledstate = OFF; // Skifter tilstand for LED digitalwrite(ledpin, ledstate); // loop() At skrive koden to gange koster plads og er vanskelig at vedligeholde. Disse variable skal der laves to udgaver af
Vi tager nu to skridt: Jeg præsenterer en variabeltype hvor man ligesom kan sætte et nummer på. Dernæst vil jeg flytte det hele ind i en funktion, som kan bruges med hhv. diode 1 og diode 2 Altså noget i retning af: skift(int diode) som så kaldes med diode nummeret Altså noget i retning af skift(1) eller skift(2) skift(n) skal så undersøge om det er tid til at skifte den pågældende diode og så gøre det. Først den med variabeltypen.
Lidt teori - Array Array Det stod vist på en overhead tidligere uden at der blev uddybet. Et array er et måde at ordne data på. I virkeligheden er det meget lig strenge, der er en ordnet samling af karakterer. Et array defineres f.eks. således: int MineData[4]; //det er en samling af fire heltal Disse fire heltal ligger på række i hukommelsen Forsættes
Lidt teori - Array Grafisk kunne det se således ud når der er data i dem: MineData 0 1 2 3 1234 22 98 1086 Man gemmer data i Minedata således: f.eks. MineData[3] = 1086; Indholdet i MineData får man fat på således: w = MineData[2]; hvorefter w er 98.
Lidt teori - Array Data i et array er nummereret fra 0. Man definere et array således int MineData[4] Husk det nu Jeg har dummet mig! og dermed findes: MineData[0], MineData[1], MineData[2], MineData[3], Det fylder det samme som fire heltal (int).
Lidt teori - Array Med programvariable kan vi adressere de forskellige elementer i et array. void loop() int MineData[10]; for (n = 0; n < 10; n = n + 1); MineData[n] = n * n; Efter dette program vil: MineData[0] 0 MineData[1] 1 MineData[2] 4 MineData[3] 9 MineData[4] 16 MineData[5] 25 MineData[6] 36 MineData[7] 49 MineData[8] 64 MineData[9] 81
Blink med to dioder (ON OFF) Programmeringskursus Vi ønskede jo at lave følgende variable: ONTID1 OFFTID1 ledstate1 skifttid1 ONTID2 OFFTID2 ledstate2 skifttid2 Disse variable gemmer vi i følgende arrays: ONTID[2] OFFTID[2] ledstate[2] skifttid[2]
Blink med to dioder Mere formelt ser definitionerne således ud: long OFFTID[2]; //Off tid for LED1 og LED2 long ONTID[2]; // On tid for LED1 og LED2 int ledstad[2]; // Tilstand for LED1 og LED2 : LOW eller HIGH long skifttid[2]; // Tidspunkt hvor dioder sidst er skiftet Dermed har vi bl.a. oprettet følgende pladser: OFFTID[0] OFFTID[1] ONTID[0] ONTID[1] til LED1 til LED2 Det fylder det samme som at oprette variable af typen long!
Blink med to dioder ON OFF Programmeringskursus void loop() if (ledstate == LOW ) if((tid - skifttid) > OFFTID) skifttid = Tid; // Gemmer tiden for skift ledstate = HIGH; // Skifter tilstand for LED digitalwrite(ledpin, ledstate); else if((tid - skifttid) > ONTID) skifttid = Tid; // Gemmer tiden for skift ledstate = OFF; // Skifter tilstand for LED digitalwrite(ledpin, ledstate); // loop() Vi havde denne kode som skulle bruges to gange Disse variable skulle der laves to udgaver af. I stedet erstatter vi dem med arrays.
Blink med to dioder ON OFF Programmeringskursus void loop() if (ledstate[diode] == LOW ) if((tid - skifttid[diode]) > OFFTID[diode]) skifttid[diode] = Tid; // Gemmer tiden for skift ledstate[diode] = HIGH; // Skifter tilstand for LED digitalwrite(ledpin, ledstate); else if((tid - skifttid[diode]) > ONTID[diode]) skifttid[diode] = Tid; // Gemmer tiden for skift ledstate[diode] = OFF; // Skifter tilstand for LED digitalwrite(ledpin, ledstate); Her har vi erstattet de variable vi skal bruge to gange med arrays. Dette går dog ikke fordi det skal puttes ind i en funktion Og hvad med digitalwrite()
Blink med to dioder ON OFF Programmeringskursus void skift(int diode, long Tid) if (ledstate[diode] == LOW ) if((tid - skifttid[diode]) > OFFTID[diode]) skifttid[diode] = Tid; // Gemmer tiden for skift ledstate[diode] = HIGH; // Skifter tilstand for LED digitalwrite(ledpin, ledstate); else if((tid - skifttid[diode]) > ONTID[diode]) skifttid[diode] = Tid; // Gemmer tiden for skift ledstate[diode] = OFF; // Skifter tilstand for LED digitalwrite(ledpin, ledstate); Først det med at lave en funktion ud af det. Jeg tager lige det i kassen ud til undersøgelse Og hvad med digitalwrite()
Blink med to dioder ON OFF Programmeringskursus Der er jo et problem med værdien af diode Koden fra kassen på sidste OH er her: if((tid - skifttid[diode]) > OFFTID[diode]) skifttid[diode] = Tid; ledstate[diode] = HIGH; digitalwrite(ledpin, ledstate); Diode vil naturligt antage værdierne 1 og 2. Men f.eks. OFFTID[2] er jo ikke lovlig! Den variabel var defineret ved: long OFFTID[2]; og dermed findes kun OFFTID[0] og OFFTID[1]
Blink med to dioder ON OFF Programmeringskursus void skift(int diode, long Tid) diode = diode -1; if (ledstate[diode] == LOW ) if((tid - skifttid[diode]) > OFFTID[diode]) skifttid[diode] = Tid; // Gemmer tiden for skift ledstate[diode] = HIGH; // Skifter tilstand for LED digitalwrite(ledpin, letstade); else if((tid - skifttid[diode]) > ONTID[diode]) skifttid[diode] = Tid; // Gemmer tiden for skift ledstate[diode] = OFF; // Skifter tilstand for LED digitalwrite(ledpin, ledstate); Problemet med værdien af diode løses f.eks. således. Og hvad med digitalwrite()? Et (dårligt?) forslag er at flytte det ud af funktionen
Blink med to dioder ON OFF Programmeringskursus Dermed kunne hovedprogrammet være : void loop() // Her er al den kode som skal køre hele tiden // funktionen skift() checker om det er tid til skift af LED unsigned long TidNu = millis(); skift(1, TidNu); skift(2, TidNu); // set the LED with the ledstate of the variable: digitalwrite(ledpin1, ledstate[0]); digitalwrite(ledpin2, ledstate[1]); Forstsætter
Blink med to dioder ON OFF Programmeringskursus Og funktionen skift() kunne se således ud: void skift(int diode, long Tid) diode = diode -1; if (ledstate[diode] == LOW ) if((tid - skifttid[diode]) > OFFTID[diode]) skifttid[diode] = Tid; // Gemmer tiden for skift ledstate[diode] = HIGH; // Skifter tilstand for LED else if((tid - skifttid[diode]) > ONTID[diode]) skifttid[diode] = Tid; // Gemmer tiden for skift ledstate[diode] = OFF; // Skifter tilstand for LED
Blink med to dioder ON OFF Løsningen er bestemt ikke ideel fordi: Der skrives til udgangen i hvert gennemløb uanset om det er nødvendigt! (Bør ændres så skift returner oplysning om ændring er sket) Hvad sker der når der er overløb i variablen Tid eller TidNu?? Tid har største værdi 2.147.483.647-2,147,483,648 Overløb efter ca. 27 dage! (Derefter vil den vist aldrig mere blinke!) Formålet var: Vise at man kan blinke med to LED uden brug af delay() Mere generelt at undgå at vente på sløvt hardware. Introducere variabel typen array. Vise hvordan man kan flytte kode til en funktion.
Digitale ind og udgange Generelt er ikke problemet ligger i styring af udgangene. Problemet er nok i højere grad at: Få styr på hvad hardwaren egentlig skal Få det programmeret hensigtsmæssigt Dermed ender det hele (måske) ikke op i programmering!
Digitale Udgange Stepmotor ved hjælp af EasyDriver
Stepmotor ved hjælp af EasyDriver
Stepmotor ved hjælp af EasyDriver Opstilling principielt Programmeringskursus
Stepmotor ved hjælp af EasyDriver Vigtigste indgange: Step / trin Direction / retning Ground / stel Udgange Motor spole A (to terminaler) Motor spole B (to terminaler)
Stepmotor ved hjælp af EasyDriver Stepmotor Opløsning MS1 MS2 Helt trin LOW LOW Halvt trin HIGH LOW Kvart trin LOW HIGH Ottendedel trin HIGH HIGH
Stepmotor ved hjælp af EasyDriver Det centrale i et program til styring af EasyDriver: while(steps > 0) digitalwrite(steppin,high); delaymicroseconds(1); digitalwrite(steppin,low); delay(stepdelay); // steps = steps -1; // tæller steps ned Størrelsen af forsinkelsen er bl.a. afhængig af motoren. Typisk 10ms?
Stepmotor ved hjælp af EasyDriver Forinden skal man bestemme hvilken vej motoren skal kører. Det kan f.eks. gøres således: if (steps > 0) digitalwrite(dirpin, HIGH); // Motoren kører til venstre if (steps < 0) digitalwrite(dirpin, LOW); // motoren kører til højre steps= -steps;
Stepmotor ved hjælp af EasyDriver Samlet kan det komme til at se således ud: void loop() int steps, speed, stepdelay;... // Her nogle forudsætninger // hvor hastighed og retning // bestemmes stepdelay = 1000 / speed; if (steps > 0) digitalwrite(dirpin, HIGH); if (steps < 0) digitalwrite(dirpin, LOW); steps= -steps; while(steps > 0) digitalwrite(steppin,high); delaymicroseconds(1); digitalwrite(steppin,low); delay(stepdelay); Her eller i setup() skal laves forudsætninger om hvilke udgange der bruges til hvad. steps = steps -1; (Ide fra Arduino Cookbook) Dette delay overvejes næste side
Stepmotor ved hjælp af EasyDriver Kommentar til programmet: Kan det betale sig at lave programmet så man ikke venter på at stepmotoren flytter sig? Det er noget i størrelsesordnen 0,3 1 ms. Det er en vurderingssag. Overvej: Når motoren kører er der så andet som er vigtigt? Hvordan er beskeden til at motoren kører et bestemt antal step dannet?
Digitale Udgange Vente på display
Vente på display Sidst blev det nævnt at udskrivning til display kunne give problemer med tid til at gøre andet. Det vil jeg godt se lidt på, fordi udskrift til display er noget vi ofte får brug for! Hvad er det vi er oppe imod?
Vente på display Fra datablad for driver
Vente på display Hvad er det så for et program vi har. Et eksempel: #include <LiquidCrystal.h> LiquidCrystal lcd(12, 11, 6, 5, 4, 3); void setup() lcd.begin(16, 2); void loop()? lcd.clear(); lcd.setcursor(0, 1); lcd.print("resultatet >"); lcd.setcursor(14,1); lcd.print("77"); 1,5ms 12 * 36 μs = 432 μs
Vente på display Konklusion (min): Man skal i det mindste ikke skrive for meget tekst til display, hvis det sker i en løkke, der styrer noget andet, f.eks. en stepmotor. Man skal slet ikke foretage clear af display i en sådan løkke! Er der kommentarer fra jer der har prøvet??
Arduino - C-programmering Programmeringskursus Pointere
Pointere Kort præsentation En pointer er en pegepind eller en pil. Når vi opretter en variabel, f.eks. int a; Så opretter vi en adresse i hukommelsen. En pointer er en pegepind til adressen for variablen. Det skriver man således: ptr = &a; Det kikker vi lige lidt mere på
Pointere Antag at vi har lavet følgende: a = 98; Variablen er jo gemt på en eller anden adresse. Det er det som pointeren fortæller om. Det betyder at (f.eks.) ptr = &a så er prt = FE04HEX Det er vi jo ofte temmelig ligeglade med. Det er jo det som vi har sat C-compileren til at holde styr på.
Pointere Vi skal naturligvis bruge det til noget. Det vigtigste er nok at kunne bruge pointere I funktioner Til arbejde på store datamængder (arrays) En funktion som: boolean kontakt(int pin); Vi kunne godt tilføje flere argumenter her Kan vi få en værdi tilbage. Om vi ønsker det kan vi godt have flere argumenter (dem i parentesen)
Pointere Hvad nu hvis vi har brug for at få mere end en værdi tilbage? Vi kan naturligvis operere på en global variabel. (Dårlig stil, men heller ikke altid godt nok) Vi kan også bruge pointere i et funktionskald: void modtag(int *tabel)... // henter data fra en indgang Se næste
Pointere Dele af et program: int tabel1[20]; int tabel2[20]... void modtag(int *tabel)... tabel[3] = 77; tabel[3] = 634;... Jeg har ikke (endnu) fundet eksempler til Arduino med dette. Det vil jeg gerne gøre til en af de følgende gange.
Digital ind- og udgang Det var det jeg havde til i aften Der er lige et par ting vi skal (begynde) at tale om: Hvad skal jeg genere jer med de to sidste aftener? Hvordan skal vi bruge Arduino i foråret?