Arduino med Atmel studio 6.x (6.1) Etter å ha sett meg grenseløs lei av Arduinos IDE har jeg i lenge tid brukt Atmels eget AS6.1 Tenkte derfor lage en liten hvordan sette den opp til å virke med arduino. 1. Hvorfor? I arduinos IDE så vil det fort bli mye kode som du etterhvert kjenner og da ofte må bla deg gjennom, as6 kan "gjemme" disse mens de fremdeles er lett tilgjengelig. I arduino må du huske alle forkortelser og akronymer selv, det er ingen feilretting eller forslag som kommer opp mens du skriver. det gjør as6. (prøv det, du blir hekta) Arduinos skrive og lese funksjoner er veldig trege da de inneholder tester for ditt og datt, riktignok er dette for å forhindre at du gjør ting feil men som oftest er de bare til forsinkelse. UTFORDRING! - det er mange ting arduinos IDE fikser for deg slik at du ikke trenger å tenke så veldig på hva som egentlig foregår i bakgrunn, dette må du nå ordne selv. 2.Hvordan? -Last ned Atmel Studio fra http://www.atmel.com/tools/atmelstudio.aspx -Installer. Ok, hva nå. Jo nå må du fikse slik at as6 kan bruke avrdude til å laste inn.hex fila til arduinon, her bruker vi da 'Tools' - 'External Tools...' Åpne menyen og velg 'Add' Mitt oppsett ser slik ut: Title: "UNOR3 COM9" Command: "C:\WinAVR-20100110\bin\avrdude.exe" Arguments: "-c arduino -p atmega328p -carduino -P\\.\COM9 -b115200 -D - Uflash:w:"$(ProjectDir)Debug\$(ItemFileName).hex":i" Initial directory: "$(SolutionDir)" So far so good! Nå må du kansje redigere littegranne om dette ikke fungerer, det kan hende avrdude hos deg ikke ligger samme sted som hos meg så du må finne avrdude.exe og legge inn riktig bane i Command. Hos meg så bruker min arduino COM9, dette sjekker du i arduinos ide (som du sikkert har fra før) og bare forandrer nummeret i Arguments til riktig COM port. Kryss av 'Use Output window" for å se hva avrdude gjør, dette BØR være med slik at du ser om noe går galt! Yes, da burde vi være klare til å sette i gang :)
Da lager vi oss et prosjekt!: 'File' - 'New' - 'Project' -> GCC C++ Executable Project. Gi prosjektet et navn og OK. Så får vi et merkelig valg "Device Selection" hva er det? JO atmel har MANGE forskjellige microcontrollere, på en UNO så heter microkontrolleren ATmega328P og vi finner den i lista og trykker OK. Da er vi i gang.. for vårt første prosjekt så skal vi blinke led lampa på arduino kortet vårt :) Menneh, hvor er setup() og loop()? Jo, nå skal du høre, dette er en av de tingene arduinos IDE jukser litt med, siden et program egentlig er en fra a-b ting så må vi her ordne disse selv, vanskelig? NEI. // Her plasserer du alt som har med setup å gjøre //Her plasserer du alt som skal i loop() //TODO:: Please write your application code Og da er alt i sjønneste orden og det bare er å skrive som du gjorde i arduinos IDE? Nei -tingen er den at i den virkelige mikrokontrollerverdenen så finnes det ikke en enkelt in og ut pinne, alt samlet i PORTer og registre. hva betyr dette, kan jeg ikke bare slå LED av og på lenger? Joda, men vi må gjøre dette på en annen måte. Først, i arduinos IDE så heter LED bare pinne 13, i den virkelige Mc verdenen heter denne PortB5, og siden vi valgte ATmega328P tidligere så vet as6 hvor denne er. Den vet også hvordan vi skal sette porten som utgang. Åh, hvordan gjør vi det da? I den virkelige Mc verdenen så styres dette av et register som heter Data Direction Register, i dette tilfellet DDRB (PortB remember), så vi må begynne med litt setup() for den.
Nå skal vi gjøre noe morsomt, vi skal skrive vår første linje med kode i den virkelige Mc verdenen: Hva betyr dette da? Jo, litt bakvendt kansje men i dette registeret betyr 1 at den respektive porten skal være en utgang. "0b.." betyr at vi skriver i binært, bruker dette her for å kansje forenkle ting. Ok, vi fortsetter, da har vi satt PortB5 som utgang. Vi begynner med å slå LED på, og på samme måte som vi satte DDRB skal vi nå sette PortB5 høy. Sånn nå har vi laget et program som får LED til å lyse! burde se slik ut: //TODO:: Please write your application code Hvordan får vi den over til UNOn da? Litt flere tastetrykk enn arduinos IDE men alikevel, først trykker vi F7 (Build solution), vi får en output nederst på siden med informasjon om hvordan det gikk (se bare helt nederst om det står Build Succeeded) og da har vi laget filene avrdude trenger for å laste opp programmet til UNOn, så da trykker vi på 'Tools' - 'UNOR3 COM9' (som den heter i mitt tilfelle) og lampene på UNOn burde blinke litt for så å la LED lyse.
Alright!! den lyser <happy joy joy> Hva nå? Jo, vi skulle jo ha den til å blinke så vi får slå den av igjen: last opp og sjekk! Øh, lampa lyser jo fremdeles, men svakere? Helt riktig, dette fordi den nå slås av og på et par millioner ganger i sekundet, vi må forsinke dette litt og her begynner ting å bli noe mer anderledes enn fra arduinos ide, vi må nemlig legge til et bibliotek i programmet vårt, i dette tilfelle et som heter delay.h og det gjør vi slik: Aha, så nå kan jeg bruke delay(100); som fra arduino? Nei, her heter den jo selvfølgelig noe annet. her heter den _delay_ms(); husk understreken forran!, den fungerer på samme måte som delay(); og vi setter den inn i programmet vårt: //TODO:: Please write your application code Trykk F7 og se!
Nå blinker den! men skrev ikke vi at den skulle blinke med et sekund mellomrom? den blinker mye raskere enn det! Yes! Når du trykket F7 så fikk du sikkert opp #warning "F_CPU not defined for <util/delay.h>" [-Wcpp] Dette er bare en advarsel som as6 spytter ut fordi at vi ikke har fortalt programmet hvilken hastighet prosessoren arbeider med. Mikrokontrollere kan ha forskjellige hastigheter nemlig og siden alle UNOer har samme frekvens så er dette også noe arduinos ide fikser for deg, så vi må fortelle programmet hvilken hastighet vi har slik: #define F_CPU 16e6 // 16e6 betyr det samme som 16000000 som er 16Megahertz Sånn og da har vi laget et veldig kort program som blinker LED dvs. pin 13 dvs. PORTB5 av og på en gang i sekundet. Hva med litt input! Nå skal vi legge til en knapp som skal styre denne blinkinga, målet er at det skal bare blinke når knappen holdes nede! Og vi ser ovenfor på programmet vi har laget så langt. Vi velger å bruker PORTB4, arduino pinne 12 som inngang til knappen vår og for å gjøre ting enklere så bruker vi den innebygde pull-up motstanden i Microkontrolleren. Åssen gjør vi det da? Enkelt, PORTB4 er i DDRB alerede satt til 0 som betyr at vi skal bruke den som inngang så her trenger vi ikke forandre noe, men for å aktivere pull-up motstanden så skal vi alikevel skrive porten høy i setup området slik:
Okei, så nå er den en inngang, hvordan bruker vi den da da? Enkelt, alt vi trenger å gjøre nå er å sjekke om den er høy eller lav. Kansje ikke fullt så enkelt alikevel, vi har jo LED på samme porten som både kan være av eller på, så vi må maskere bort alt utenom PORTB4, for de av dere som har lakkert før vet hva det vil si å maskere, for dere andre så er det rett og slett en måte å fjerne alt vi ikke trenger eller vil ha i en byte, og her så er vi jo bare interesert i knappen vår som er på PORTB4 alså skal vi tvinge alle andre bit enn PORTB4 til lav, og det gjør vi ved å AND (og) hele PINB med en maske slik: (PINB & 0b00010000) Legg spesielt merke til at det bare er et & tegn, dette betyr at alle bittene i begge argumentene blir behandlet hver for seg! Såh, dersom vi nå legger dette inn i programmet vårt som en enkel IF statement vil det se sånn ca slik ut : #define F_CPU 16e6 if(pinb & 0b00010000) Menneh, måtte ikke PORTB4 være høy for at vi skulle bruke pull-up motstanden i Mc'en? Helt riktig, dette programmet vil kansje bare virke 1 gang, så vi får forandre litt på PORTB slik at PORTB4 fortsetter å være pulled-up :) slik : PORTB = 0b00110000;
Menneh du, nå blinker det hele tiden, skulle ikke den bare blinke når vi holdt knappen inne? BINGO!, siden vi har en knapp som drar pinnen til jord og en pull-up motstand så er pinnen høy hele tiden, helt til vi trykker på knappen hvor den går lav, vi kan da velge om vi kansje må bytte om på kretsen finne frem motstand og ordne en pull-down krets, den må i så fall lage selv siden Mc bare har pull-up innebygd. Men vi kan jo bare snu hele greia i programmet vårt! Vi mekker inn en NOT i IF'en vår slik: if(!(pinb & 0b00010000)) Og da burde vi ende opp med et noe slikt program: #define F_CPU 16e6 if(!(pinb & 0b00010000)) PORTB = 0b00110000; Og Voila, vi har en knappestyrt blinkende LED