Jeg har lenge hatt lyst til å lære meg å bygge med Arduino, og etter nyttår bød plutselig anledningen seg. Jeg gikk til anskaffelse av en startpakke på Kjell & Company, som er min nye favorittsjappe (nei, dette er ikke sponset – jeg har gått i butikk og betalt full pris som alle andre kunder), og har brukt de siste ukene på å sette meg inn i det grunnleggende.
Og la bare det være sagt med én gang: Jeg har enormt stor sans for tanken bak Arduino, et prosjekt med opphav i Italia som har som mål å gi folk flest tilgang til ganske avansert elektronikk. Både programvare og maskinvare er open source, hvilket betyr at man kan komme igang for en billig penge og i stor grad bygge på andres programvareideer.
Samtidig er det ikke til å komme forbi at elektronikk er kompliserte saker, og at det vil være en viss læringsterskel for de aller fleste brukere. Det finnes et utall “kom igang”-guider til Arduino på nettet (denne fra Instructables er f.eks. fin), som stort sett alle krever at du husker det grunnleggende i elektrisitetslæren fra fysikktimene (som Ohms lov) pluss har noe erfaring med å programmere.
Min startpakke baserer seg på Arduino-kretskortet Uno (en ganske populær versjon), som gir tilgang til en mikrokontroller (en programmerbar mikroprosessor) via en rekke input- og output-koblinger eller pinner. Det følger også med et koblingsbrett som gjør det enkelt å legge opp kretser uten å lodde. I tillegg får man hundrevis av ledninger og elektroniske komponenter som motstander, kondensatorer, lysdioder, servoer og sensorer.
Man programmerer Arduino på PC/Mac i et C-lignende språk, og overfører programmet via en USB-kabel til mikrokontrolleren. Så snart programmet er kompilert (og debugget, som regel) og overført, begynner mikrokontrolleren på kortet å utføre instruksjonene, som f.eks. kan være å skru LEDer av og på, kjøre en elektromotor, hente data fra trykknapper eller sensorer osv. Programsnutten nedenfor (fra Wikipedia) får en LED til å blinke:
#define LED_PIN 13
void setup() {
pinMode(LED_PIN, OUTPUT); // Enable pin 13 for digital output
}
void loop() {
digitalWrite(LED_PIN, HIGH); // Turn on the LED
delay(1000); // Wait one second (1000 milliseconds)
digitalWrite(LED_PIN, LOW); // Turn off the LED
delay(1000); // Wait one second
}
For å få Arduinoen til å gjøre mer avanserte ting (og folk får virkelig til det mest utrolige med den lille dingsen) øker kompleksiteten raskt, ikke minst når man samtidig skal debugge et fysisk oppsett og programvaren som skal styre det. Jeg innså at jeg trengte et incentiv for å ta meg tiden som trengs for å bli rimelig god i dette. Det var ikke nok mestringsglede i å få lys til å blinke – jeg trengte et konkret problem å løse.
Og det gikk raskt opp for meg at jeg hadde et problem som lenge har ventet på en løsning. Faste lesere av bloggen har sikkert lagt merke til at jeg har to katter. Generelt er de så snille og veltilpassede som man kan forvente av et halvvilt lite rovdyr, men det siste året har Linus lagt seg til en mildest talt irriterende vane. Mellom 04 og 05 hver morgen vekker han meg for å få mat.
Jeg har prøvd ulike løsninger, som å gi mer mat før leggetid og lukke ham ut av soverommet, men til ingen nytte. Når katter bare gidder, kan de være svært gode problemløsere, og Linus har kommet seg rundt alle mottiltak jeg har satt inn. Jeg kom etterhvert frem til at det som trengtes var en automatisk kattemater – en maskin som på et gitt tidspunkt (f.eks. 04.00) slapp ut litt mat til dyra.
Nå finnes det allerede mange masseproduserte og hjemmelagete kattematere på markedet, men jeg fant ingen som passet våre behov. Matemaskiner flest er bygd av folk med god plass og som kan tenke seg å la katten være alene i dager av gangen. Mitt behov var et annet: Maskinen måtte ta lite plass og behøvde bare å slippe ut én (i høyden to) dose(r) kattemat av gangen. Er vi hjemmefra en hel dag eller mer, sørger vi alltid for at de har tilsyn.
Enkle behov gir gjerne enkel kravspekk: Maskinen måtte levere én dose med tørrfor til to katter, med en tidsforsinkelse på 5-6 timer. Jeg tok en titt på Arduino-startpakken, og blikket mitt falt raskt på den inkluderte servoen. En servo kan programmeres til å vris til en spesifisert vinkel mellom 0 og 180 grader, og er derfor veldig nyttig når man f.eks. skal styre retningen til en robot eller et kjøretøy.
Selv små servoer kan gi ganske mye skyvkraft, og det gav meg en idé: Hva om jeg brukte servoen til å levere kattematen? Et par lyspærer over hodet senere (de dukker gjerne når jeg er ute og går, hvilket er grunnen til at rask gange er min foretrukne form for mosjon) og jeg hadde det grunnleggende designet klart: Jeg ville bruke servoen til å drive fire vinger rundt i et sylindrisk kammer. Kattematen ville ligge mellom vingebladene slik at når servoen ble vridd 90 grader, ville maten skyves over en åpning og slippes ned.
Designet ser ut som det gjør av to årsaker. Den viktigste er at vi har to katter som gjennom årene har vent seg til å få servert hver sin matporsjon. To doser på én gang gir gladere katter og ditto større mulighet for nattero. Den andre årsaken er at servoer normalt bare kan bevege seg mellom 0 og 180 grader. Det finnes riktignok 360-graders-servoer på markedet, men de er noe mer plundrete å programmere, og dette var nå mitt første prosjekt.
Ergo en kattemater med to pelletskamre og to åpninger, altså. Det var nå på tide å skrive programmet eller skissen (“sketch” på Arduino-språk) som skulle drive materen. Jeg satte opp en enkel krets på koblingsbrettet, der servoen fikk strøm via Arduino-kortets pinner merket 5V og GND (jord). Kontroll eller puls-delen av servoen ble koblet til den digitale I/O-pinnen merket 10. Skjematisk så det ut som nedenfor (med unntak av at I/O-pinnen her er nummer 9):
Å få servoen til å vri seg riktig viste seg å være ganske trivielt. I programmet setter jeg først servoen til 0 grader, deretter vrir jeg vingene 90 grader til venstre og lar dem stå slik i ca 10 sekunder. Det gir nok tid til å fylle kattemat i åpningen, før vingene vris tilbake til 0 grader igjen. Deretter går det fem timer før de igjen vris til 90 grader, og maten slippes ut.
Siden Arduino ikke har noen innebygd klokke måtte jeg bruke en litt problematisk fiks: kommandoen delay, som forsinker utførelsen av en sekvens med et gitt antall millisekunder. delay(1000) gir altså en forsinkelse på 1 sekund. Jeg kjørte flere tester for å forsikre meg om at tidsangivelsen var presis, og kom til at delay etter noen timer fremdeles treffer innen et par prosent eller så. Godt nok for meg.
#include <Servo.h> // Kaller et eget servokontroll-bibliotek
float hoursleft1=4.5; // No of hours to wait before first feeding compartment opens
Servo servoMain; // Define Servo
void setup()
{
servoMain.attach(10); // Attaches servo to digital pin 10
}
void loop() // Hovedløkken som kjører programmet
{
delay(1000); // Wait
servoMain.write(0); // Turn Servo Left to 0 degrees
delay(10000); // 10 seconds to put food in compartment
servoMain.write(90); // Turn Servo Right to 90 degrees
delay(hoursleft1*3600000); // Wait for hours defined by hoursleft variable
servoMain.write(0); // Turn Servo Left to 0 degrees
}
Hovedproblemet med denne uelegante (om enn effektive) løsningen er at hele programløkken settes på vent. Hvis jeg ønsker at Arduino skal gjøre flere ting enn å slippe ut mat i løkken, som å blinke med en LED eller hente inn data fra en trykknapp, blir dette også forsinket like lenge som delay-verdien. Min kattemater kan dermed bare gjøre to ting: Laste inn mat, og vente fem timer før den slipper maten ut igjen.
På den annen side: Det enkle er ofte det beste. Og kattemateren er virkelig enkel å bruke. Ingen av-på-knapp, ingen ting å stille inn, bare plugg den i veggen (strømkilden til Arduino frakoblet til PC kan f.eks. være en vanlig 5 Volts mobillader av den typen du sikkert har slengende i en skuff), putt mat i åpningene og vent til vingene har rotert maten ut av syne før du henger materen på plass.
Siste trinn var å bygge selve maskinen. Siden prototypen ikke skulle flytte på mer enn 20-30 gram med tørr kattemat, visste jeg at papp, limpistol og gaffa ville gjøre jobben. Jeg trengte en beholder i plast, for å hindre sultne katter i å gnage seg gjennom til maten der inne. PET-brusflasker har noenlunde riktig form og størrelse, og er gjennomsiktige slik at man kan se LEDene på Arduino-kortet som bekrefter at alt er som det skal være.
Etter litt prøving og feiling kom jeg til at 1,5 liters Olden-flasker hadde riktig form og tykkelse på plasten. Dermed satt jeg igjen med disse komponentene til kattematermaskinen jeg har valgt å kalle PUS-1 (for PET Utility System – hva trodde du egentlig?):
Det eneste som gjensto var en festemekanisme. Jeg ville ha det slik at PUS-1 kunne tas vekk om morgenen, og laget en slags festekrok av en gammel ståltrådhenger som passer over radiatoren som kattene pleier å spise ved. Kattene ble litt nysgjerrige av den nye dingsen til å begynne med, men er stort sett bare opptatt av å se nedover på matskåla når de er her, og sluttet snart å bry seg.
Så til det store spørsmålet: Fungerte den etter hensikten? Svaret er et klart og utvetydig JA. Etter at jeg begynte å bruke PUS-1, er det blitt helt slutt på å bli vekket i grålysningen av en sulten hannkatt som spretter rommet rundt. Siden jeg er fast bruker av en Fitbit Charge HR, som automatisk registrerer søvnmønsteret mitt, kan jeg tilmed dokumentere dette i tall.
På disse grafene fra Fitbit er tidspunkter da jeg er våken om natten markert med rødt. Som man kan se er de røde feltene ved 4-5-tiden borte i de to øverste grafene. Det ser også ut til at jeg har færre faser med rastløshet (markert i lyseblått). Alt i alt vinn-vinn, altså. Kattene er mer tilfredse, og jeg får sove bedre om natten.
Problemet med slike prosjekter er at de fort gir mersmak. Jeg har allerede et par Arduino/Raspberry Pi-relaterte ideer i bakhodet, men først og fremst vil jeg ta med erfaringene fra PUS-1 videre til den oppgraderte, forbedrede PUS-2. Her er noen av forbedringene jeg kan se for meg:
- Et langt penere deksel. Jeg er allerede igang med å designe innmaten til PUS-2 i TinkerCad, med sikte på å 3D-printe den i ikke altfor fjern fremtid.
- Bytte ut store Arduino Uno med et minikort typ Arduino Nano eller tilsvarende. Small is beautiful.
- Seks vinger istedenfor fire på rotasjonsenheten. Da kan jeg ha to separate matinger. Lett å programmere inn med dagens system.
- En mer hensiktsmessig festemekanisme.
Om jeg får tid og lyst, ser jeg også PUS-3 i det fjerne. Den vil bruke en 360 graders rotasjonsløsning, slik at man kan få opptil fem separate matekamre. Det vil også kreve ordentlig tidsinnstillinger, hvilket betyr at jeg må skaffe en såkalt RTC-klokkeenhet og en måte å hente inn ønskede tidspunkter fra brukeren på. Den tid den sorg. I mellomtiden kan man trygt si at Linus er fornøyd med å ha fått mennesket sitt til å gå lengre enn noensinne i å tilfredsstille husguden…
27/01/2016 at 01:07
Nydelig! Bravo! 🙂
Og nydelig kode også. Men hvorfor den første forsinkelsen på ett sekund? Noe kode som bare fulgte med Copy&Paste? 😉
PS: Hvordan ville kattene ha oppført seg hvis du lagde noe som gav dem én pellets f.eks. hvert minutt gjennom hele natten?
27/01/2016 at 08:43
Morsomt prosjekt. Første versjon skal vare litt redneck-style 🙂
Merk at dersom du ikke trenger mer en fem (maks seks) io-pinner til prosjektet ditt kan du vurdere å miniatyrisere prosjektet enda mer med å bruke en ATTINY85 e.l. og hoppe over hele Arduino-kortet. Prosjektet du har her kjører lett med bare den interne klokka og du kan bytte ut hele kretskortet med en liten IC med bare åtte pinner pluss en liten overgang fra usb til 5V strømtilkobling for kretsen.
Det er også ganske enkelt å bruke mikrokontrolleren som står på Arduino-kortet for seg selv, men da er en Ardiono Nano/Mini bare marginalt større.
27/01/2016 at 19:53
@Rune: Det er faktisk for å gi servoen et lite “pusterom”, kommer kommandoene for fort på begynner den å dure og nærmest stotre. Kunne sikkert ha valgt 100 ms, men 1000 ms ble nå stående.
Til spørsmål 2: Har vurdert å gi kattene flere porsjoner, men en pellets per minutt natten gjennom ville jo ha vært sann tortur både for dyr og mennesker. Ville ikke ha gjort noe annet enn å henge rundt på kjøkkenet og vente på den neste. 🙂
@Arne: Takk for tips! Ja, jeg har snust litt på muligheten for å skippe hele kortet, men kommer til å ta det litt piano til å begynne med. Sist jeg holdt på med elektronikk på hobbybasis var mens Oddvar Nordli var statsminister og de fire S’ene var nasjonalhelter. 🙂
22/03/2016 at 11:39
Gennialt! 🙂
22/03/2016 at 11:56
Veldig bra! jeg brukte også Arduino til å styre servoer den første gangen, men fant ut at det er lettere å bruke Raspberry PI med et servoshield fra Adafruit. Da er funksjonene tilgjengelige rett fra Python, og du kan potensielt la kidsa dine styre katteforingen fra Minecraft 🙂 I tillegg har jo Raspberry’en full nettverks-støtte så du kan integrere med alt mulig annet…
01/04/2016 at 17:12
@Simen: Jeg vurderte å bruke Raspberry Pi til dette (er jo utrolig kult at Pi har så mange pinner man kan leke seg med), men syns i grunnen det var overkill i forhold til behovet (maskinen fungerer fremdeles helt prikkfritt, og gjør akkurat den jobben den ble bygd for, som er å gi meg en full natts søvn!)
Men har jo selvsagt tenkt at det kunne være greit f.eks. å kunne sjekke at kattene har det bra ved å ta bilder under spisingen eller gi brukeren mer kontroll – kanskje til og med fjernstyre. Da kan det fort bli krøkkete å implementere funksjonene på Arduino.
Den utvilsomt største fordelen med Arduino er dog at dingsen booter opp så kjapt. Du plugger den bokstavelig talt i veggen og er klar til å kjøre på et par sekunder, akkurat som en hvilken som helst annen hvitevare. For énfunksjonsdingser syns jeg dette er uslåelig. Og velger man sin Arduino-klon med omhu blir også prisen temmelig uslåelig. 🙂