Til hovedinnhold

Se hvordan vi fikk værvarselet inn på lampen

Ved hjelp av åpne data fra YR.no og litt koding laget vi en kjekk værvarslingslampe med Arduino.

Øyvind N. Dahl / Shutterstock

Introduksjon

Tenk deg at du våkner og ser bort på nattbordet ditt. Der står det en liten lampe som lyser rødt. Dette vet du at betyr at det skal bli varmt idag, så du spretter opp av senga for å komme deg ut i det fine været.

Du har bestemt deg for å dra ut og møte noen venner på kvelden. På vei ut kaster du et blikk bort på lampa på bordet og ser at den er blå-grønn. Du vet at dette betyr at det kommer til å bli litt kjølig ikveld, så du tar med deg en jakke før du går.

Dette er ideen bak dagens hjemmebyggerprosjekt – en lampe som forteller deg hvilken temperatur det skal bli de neste timene, ved hjelp av farger. For å få til dette trenger vi følgende komponenter:

  • Arduino
  • RGB lysdiode
  • 3 stk motstander
Arduino. Foto: Shutterstock

Vi deler prosjektet inn i 3 deler:

  1. Koble RGB-lysdioden til Arduinoen
  2. Lage et program som henter værdata
  3. Lage Arduino-program som tar imot data og konverterer til farge

Det kan være greit å ha enn grunnleggende forståelse av hvordan Arduino fungerer dersom du vil bygge dette prosjektet. Vi har tidligere skrevet en guide for å komme igang med Arduino (Ekstra).

RGB-lysdiode

I dette prosjektet skal vi bruke en såkalt RGB-lysdiode. RGB står for fargene rød, grønn og blå, fordi dette er en lysdiode som består av en rød, en grønn og en blå lysdiode i samme pakning. Ved å styre intensiteten til hver av de tre diodene, kan man blande farger og i teorien få hvilken som helst farge. Det første vi skal gjøre er å få RGB-dioden til å fungere.

Test av RGB-dioden

RGB-lysdiode. Foto: oomlout [CC BY-SA 2.0]/Wikimedia Commons

En lysdiode har to sider – anode og katode – og disse må kobles riktig for at lysdioden skal fungere. Anoden kobles til positiv spenning og katoden til jord, men med en motstand koblet imellom for å sørge for at ikke alt for mye strøm går igjennom dioden. RGB-dioden vi skal bruke, er en såkalt «common anode» diode. Det betyr at anodene fra de tre lysdiodene er koblet sammen.

For å styre RGB-dioden fra Arduinoen, skal vi bruke «PWM»-utganger. Disse utgangene er merket med «~» (tilde) på Arduinoen, og kan brukes til å gi ut pulser som vi kan styre lysintensiteten til diodene med.

En enkel måte å teste om vi har koblet opp riktig på, er å skru på en og en diode. Siden vi har koblet felles-anoden til 5 volt, så vil lysdiodene bare lyse når den andre pinnen er koblet til jord. For å koble en pinne til jord, må vi sette den «lav» i Arduinokoden. Vi lager derfor en enkel testkode hvor vi setter én og én pinne lav, samtidig som vi holder de andre høye. Dette burde gi oss et resultat hvor lysdioden først er rød, så grønn og til slutt blå. For å unngå at for mye strøm går igjennom lysdioden, bruker vi tre 100-ohms motstander.

Oppkobling av RGB-lysdiode til Arduino. Foto: Øyvind N. Dahl

int red_pin = 11;
int green_pin = 10;
int blue_pin = 9;

void setup() {
  pinMode(green_pin, OUTPUT);
  pinMode(blue_pin, OUTPUT);
  pinMode(red_pin, OUTPUT);
}

void loop() {
  digitalWrite(red_pin, LOW);
  digitalWrite(green_pin, HIGH);
  digitalWrite(blue_pin, HIGH);
  delay(1000);

  digitalWrite(red_pin, HIGH);
  digitalWrite(green_pin, LOW);
  digitalWrite(blue_pin, HIGH);
  delay(1000);

  digitalWrite(red_pin, HIGH);
  digitalWrite(green_pin, HIGH);
  digitalWrite(blue_pin, LOW);
  delay(1000);
}

Blanding av farger

Det neste vi skal gjøre er å teste ut å blande farger ved å styre lysintensiteten til hver farge i lysdioden. For å gjøre dette skal vi bruke funksjonen «analogWrite()», som sender ut pulser på en pinne. Denne funksjonen tar inn en verdi mellom 0 og 255 som bestemmer bredden på pulsene som sendes ut. Dersom vi bruker verdien 0 vil pinnen alltid være lav, med verdien 128 vil pinnen 50% av tiden være høy, og 50% av tiden være lav – og dersom vi bruker 255 vil pinnen alltid være høy. Så ved å bestemme verdien vi legger med «analogWrite»-funksjonen, vil vi kunne styre intensiteten til en farge i lysdioden.

Siden våre lysdioder er koblet slik at de er PÅ når pinnen er lav, og AV når pinnen er høy, så vil vi få høyest intensitet når vi kaller «analogWrite()» med verdien 0, og ikke noe lys med verdien 255. For å forenkle, lager vi metoden «setColor()» som vi kan bruke til å blande farger.

int red_pin = 11;
int green_pin = 10;
int blue_pin = 9;

void setup() {
   pinMode(green_pin, OUTPUT);
  pinMode(blue_pin, OUTPUT);
  pinMode(red_pin, OUTPUT);
}

void loop() {
  setColor(255, 0, 0);
  delay(1000);

  setColor(0, 255, 0);
  delay(1000);

   setColor(0, 0, 255);
  delay(1000);

  setColor(255, 0, 255);
  delay(1000);

  setColor(0, 255, 255);
  delay(1000);

   setColor(255, 255, 0);
  delay(1000);

  setColor(255, 255, 255);
   delay(1000);

}


void setColor(int red, int green, int blue)
{
  analogWrite(red_pin, 255 - red);
  analogWrite(green_pin, 255 - green);
  analogWrite(blue_pin, 255 - blue);
}

Hente værdata

For å hente værdata, trenger vi å koble oss til Internett. Værmeldingssiden yr.no har en veldig enkel måte for å tilby værdata i XML-format, som vi skal benytte oss av. XML-format er et format som det er lett å lage dataprogrammer som kan lese. Det minner veldig om den måten Ruter.no tilbyr sine data på, som vi så på i artikkelen «Slik lager du din egen Ruter-skjerm med knøttemaskinen Arduino» (Ekstra).

Hvis vi for eksempel vil se været i Oslo, så finner vi det på adressen: http://www.yr.no/place/Norway/Oslo/Oslo/Oslo/

Dersom vi vil få været i Oslo på XML-format, så legger vi på forecast.xml til slutt i adressen: http://www.yr.no/place/Norway/Oslo/Oslo/Oslo/forecast.xml

Hente værdata med Processing

Processing er et utviklingsverktøy for å enkelt programmere egne programmer på en datamaskin. Det ligner veldig på Arduino, både i utseende og i hvordan selve programmeringen foregår. Processing ble utviklet for å gjøre det lett å lære programmering. Derfor er det et veldig fint sted å starte dersom du aldri har programmert før.

XML-fil. Foto: Øyvind N. Dahl

I Arduinoprogrammering, utgjør de to metodene «setup()» og «loop()» den grunnleggende strukturen i programmet, noe vi lærte i denne artikkelen. I Processing har vi istedet «setup()» og «draw()» som fungerer på omtrent samme måte. Det som står inne i «setup()» kjøres én gang ved oppstart, og det som står inne i «draw()» kjøres om og om igjen, helt til programmet avsluttes.

For å hente ut værdata fra yr.no, starter vi med å studere XML-filen. Nettleseren vi bruker er Google Chrome, som gir oss en fin visning av filen. XML-filen er bygd opp av noder, som for eksempel toppnoden:

<weatherdata>....</weatherdata>

Inne i «weatherdata»-noden er det undernoder, som for eksempel «location» og «forecast». Etter å ha studert denne filen en stund, skjønner vi etterhvert hvordan den er bygd opp og hvor informasjon om temperaturen for de neste timene befinner seg.

Processing har et bibliotek som er laget for å jobbe med XML-data. Vi tar utgangspunkt i et eksempel som beskriver funksjonen «parseXML()», og utvider koden slik at den henter temperaturen for de neste timene fra yr.no. Koden vi ender opp med blir:

void setup(){
   int temp = getTemp();
  println(temp);
}

void draw() {}

int getTemp()
{
  println("Getting temperature...");
  XML xml_main = loadXML("http://www.yr.no/place/Germany/Berlin/Berlin/forecast.xml");
  XML xml_forecast = xml_main.getChild("forecast");
  XML xml_tabular = xml_forecast.getChild("tabular");
  XML[] xml_times = xml_tabular.getChildren("time");
  XML xml_temperature = xml_times[0].getChild("temperature");

  int t = xml_temperature.getInt("value");

  return t;
}

Sende data til Arduino

Nå gjenstår det å få konvertert denne temperaturen til en farge på lysdioden, som vil gi oss et inntrykk av hva temperaturen kommer til å bli. Etter å ha hentet temperaturen fra yr.no trenger vi derfor å sende denne over til Arduinoen. Når du kobler Arduinoen til datamaskinen din, opprettes det en virtuell serieport. Denne kan vi bruke til å kommunisere mellom de to.

For å få til dette, trenger vi å vite navnet på serieporten til Arduino. På Windows-maskiner kalles den «COM» med et tall bak, for eksempel «COM7». Siden vi sitter på en Linux-maskin, heter den «/dev/ttyACM0/». For å finne navnet på serieporten, kan du se nederst til venstre i Arduino-vinduet ditt.

Finner navnet til serieporten. Foto: Øyvind N. Dahl

Vi endrer koden vår til å hente temperaturen og sende den over til Arduino hvert 5. minutt.

import processing.serial.*;

Serial myPort; // Create object from Serial class
int temperature = 0;
int last_update = -999999; //Large negative number to trigger first temp-check

void setup(){
  //Connect
  println("Connecting to Arduino...");
  String portName = "/dev/ttyACM0"; //change to match your port
  myPort = new Serial(this, portName, 9600);

  //Arduino will reset when we connect to it, so give it a few seconds
  delay(3000);
}

void draw() {
  //Set canvas size
  size(100, 100);

  //Set background color
  background(128);

  //Update temperature every 5 min
  int m = millis();
  if (m - last_update > 300000) {
    temperature = getTemp();

    //Write temperature as a string to Arduino
     myPort.write(str(temperature)); //send the temperature as a string

     //Save current number of milliseconds since start of program
    last_update = millis();
  }

  //Write text
  text("Temperature", 10, 20);
  text(temperature, 40, 50);

}

int getTemp()
{
  println("Loading XML data");
  XML xml_main = loadXML("http://www.yr.no/place/Germany/Berlin/Berlin/forecast.xml");
  XML xml_forecast = xml_main.getChild("forecast");
  XML xml_tabular = xml_forecast.getChild("tabular");
  XML[] xml_times = xml_tabular.getChildren("time");
  XML xml_temperature = xml_times[0].getChild("temperature");

  int t = xml_temperature.getInt("value");

  return t;
}

Motta data på Arduino

På Arduinoen, trenger vi å lage kode som kan motta en temperatur over serieporten, og deretter sette en farge på RGB-dioden basert på denne temperaturen. Etter å ha søkt litt rundt på nettet og lest hvordan «read()»-funksjonen fungerer, ender vi til slutt på en løsning som ser ut til å fungere ganske bra. Først mottar vi temperaturen som en tekst, deretter konverterer vi dette til et tall som vi kan bruke videre i koden.

Så gjenstår det å vise en farge som representerer temperaturen. Dette kan gjøres på mange forskjellige måter, men for oss virker det fornuftig å ta utgangspunkt i at blå betyr kaldt og at rød betyr varmt. Vi definerer i koden at 0 grader er minimumstemperatur og 30 grader er maksimumstemperatur. Dersom det er 0 grader eller kaldere vises et blått lys, og dersom det er 30 grader eller mer vises et rødt lys. Dersom temperaturen er et sted mellom 0 og 30 grader, så får vi en fargeblanding som regnes ut ifra temperaturen.

Vi ender opp med følgende kode:

int red_pin = 11;
int green_pin = 10;
int blue_pin = 9;

//Maximum and minimum values
const int max_hot = 30;
const int min_cold = 0;

void setup() {
  Serial.begin(9600);

  pinMode(green_pin, OUTPUT);
  pinMode(blue_pin, OUTPUT);
  pinMode(red_pin, OUTPUT);

   setColor(255, 255, 255); //White
}

void loop()
{
  String temperature_string = "";

  if (Serial.available())
  {
    //This while-loop receives a string from the serial port
    while (Serial.available()) {
      char c = Serial.read(); //gets one byte from serial buffer
      temperature_string = temperature_string + c; //adds the character to the string
      delay(10); //delay to allow buffer to fill
    }

    //Quick blink to indicate that temperature was updated
    digitalWrite(red_pin, HIGH);
    digitalWrite(green_pin, HIGH);
    digitalWrite(blue_pin, HIGH);
    delay(100);

    //Now temperature_string will contain something like "23".
    //But since this is text, we need to convert it to an integer
    int temperature = temperature_string.toInt();

    //Now temperature contains the temperature value as an integer

    //Cap temperature at max_hot and min_cold
    if (temperature > max_hot)
      temperature = max_hot;
    else if (temperature < min_cold)
      temperature = min_cold;

    //Calculate the middle temperature and "half range"
    int middle_temp = min_cold + (max_hot-min_cold)/2;
    int half_range = (max_hot-min_cold)/2;


    if (temperature < middle_temp) {
      int r = 0;
      int b = 255 * (middle_temp - temperature) / half_range;
      int g = 255 - 255 * (middle_temp - temperature) / half_range;

      setColor(r, g, b);
    }
    else if (temperature > middle_temp) {
      int r = 255 * (temperature - middle_temp) / half_range;
      int b = 0;
      int g = 255 - 255 * (temperature - middle_temp) / half_range;

      setColor(r, g, b);
    }
    else {
      setColor(0, 255, 0);
    }
  }
}

void setColor(int red, int green, int blue)
{
  analogWrite(red_pin, 255 - red);
  analogWrite(green_pin, 255 - green);
  analogWrite(blue_pin, 255 - blue);
}

For å teste at koden fungerer, bruker vi verktøyet «Serial Monitor» som ligger under «Tools»-menyen i Arduino. Her kan vi skrive inn forskjellige temperaturer og trykke «Send» for å sende til Arduino, og sjekke at fargen på lysdioden blir oppdatert.

Resultat og utvidelser

Etter å ha verifisert at Arduinoprogrammet fungerer, starter vi opp Processingprogrammet og sjekker at dette også fungerer. Alt ser ut til å fungere, så vi lager et selvstendig kjørbart program av koden, ved å velge «Export Application» under «File»-menyen. Nå kan vi for eksempel gjøre slik at dette programmet starter opp automatisk hver gang datamaskinen starter opp.

Utvidelser

For å gjøre det hele litt penere, kan du hente litt inspirasjon ved å sjekke ut hvordan denne brukeren på imgur lagde et veldig stilig «mood light».

Ulempen med oppsettet vårt er at vi er avhengig av å ha Arduinoen koblet til en datamaskin. For å slippe dette kunne vi for eksempel brukt en Raspberry Pi med WiFi dongle tilkoblet. Da kunne vi også kuttet ut å bruke Arduino, og heller brukt GPIO-pinnene til Raspberry Pi for å styre RGB-lysdioden.

En annen løsning for å koble Arduino til Internett, er å bruke den lille, billige WiFi-modulen ESP8266. Dette er en WiFi-modul som ikke koster mer enn rundt $5 og som kan kobles direkte til en Arduino. Denne kan du kjøpe fra flere selgere på for eksempel Ebay.

Er du allerede klar for ditt neste prosjekt? Sjekk ut hvordan du kan bygge din egen ryggesensor med Arduino (Ekstra).

annonse
Tek.no er en del av Schibsted Media. Schibsted Media AS og Schibsted ASA er ansvarlig for dine data på denne siden.Les mer her