RPi, Arduino ja Gambas

[size=150]Alkusanat[/size]

Tässä artikkelissa opetetaan kuinka tehdään Raspberryyn graafinen ohjelma, jolla luetaan ja lähetetään tietoa Arduinolle. Grafiikkapuolta hoitaa Gambas3 joka muistuttaa hyvin pitkälti Visual Basic 6:sta. Gambasia ei ole saatavilla Windowsille, joten ne joilla ei ole omalla koneella Linuxia, joutuvat ohjelmoimaan suoraan Raspberryssä. Artikkelissa rikotaan vain jäävuoren huippua, mutta toivottavasti tästä on jollekkin hyötyä. Arduino sekä Gambas3 ohjelmat kirjoitan PC:llä sekä ohjelmoin Arduinon. Nämä toki voi suorittaa RPI:lläkin mutta tässä artikkelissa ei käsitellä Arduino Iden asentamista RPI:lle.

Artikkelilin ymmärtämiseksi on hyvä että osaat vähän ohjelmoinnin perusteita. Osaat ajaa ohjelman Arduinolle, sekä osaat käynnistää Raspberryn. Toki kaiken voi suorittaa ilman RPI:tä, mikäli tietokoneellasi on Linuxin käyttöjärjestelmä.

Tässä liitetiedosto, josta löytyy kyseiset sorsat:tiedostot.zip (11.7 KB)
[size=150]Laitteisto[/size]

-Raspberry Pi (minun tapauksessa 256Mb)
-jokin näyttö
-Arduino Uno ja USB kaapeli
-2x Potikka 10K
-Vastus ja ledi
-Hyppyjohtoja
-USB näppis ja hiiri

[size=150]Aloitus[/size]

Gambas3 löytyy Debianin paketeista RPI:stä suoraan, mutta mitä olen intternettiä lukenut, niin siinä on jotain ongelmia kansioiden sijoittelussa tai jotain. No ei siitä sen enempää. Netistä löytyy suoraan käännetty versio jossa on Gambas3 valmiiksi asennettuna, joten käytämme sitä.

http://dl.dropbox.com/u/97096067/2012-07-15-wheezy-gambas3.zip

Asennamme imagen muistikortille ohjeet löytyy Ruuvipenkistä http://www.ruuvipenkki.fi/foorumi/viewtopic.php?f=15&t=682
Nyt meillä pitäisi olla toimiva versio jossa on Gambas3 valmiiksi asennettuna. Ensimmäisellä käynnistyskerralla kirjaudutaan sisään (pi, raspberry) ja käynnistetään x

startx

[size=150]Arduino[/size]

Teemme Arduinoon yksinkertaisen kytkennän, johon lisäämme kaksi potentiometriä, sekä yhden ledin. Näin ollen pystymme fyysisesti toteamaan ohjelman toiminnallisuuden.

[code]void setup()
{

Serial.begin(9600); // serialin asetukset
pinMode(2, OUTPUT); // Ledin pinni outputiks
digitalWrite(2, LOW); // Ledi alas

}

void loop()
{
int data; // data muuttuja serialille

if (Serial.available()) { // jos seriali on saatavilla
data=Serial.read(); // data muuttujaan serialilta tieto

if (data==49){ // jos saapuva data on 1 keyascii 49
digitalWrite(2, HIGH); // Ledi päälle
}
if (data==48){ // jos saapuva data on 0 keyascii 48
digitalWrite(2, LOW); // Ledi pois päältä
}

data=0; // kun seriali on lukenut data=0

}

Serial.print(“POT1A”); // lähetetään serialiin “POT1A”
Serial.print(analogRead(0)); // lähetetään serialiin A0:n arvo
Serial.print(“F”); // lähetetään serialiin lopetus “F”
Serial.print(“POT2A”); // lähetetään serialiin “POT2A”
Serial.print(analogRead(1)); // lähetetään serialiin A1:n arvo
Serial.print(“F”); // lähetetään serialiin lopetus “F”

delay(100); // viive jotta seriali pysyy perässä

}[/code]

Tutkitaan hieman koodia:
if (data==49){
Mistä tämä 49 oikeen muodostuu? Se on KeyAsciita. Eli Gambas lähettää numeron 1 joka muutetaan KeyAscii muotoon ja siitä tulee 49. Kaikki merkit löytyvät osoitteesta: asciitable.com/
Serial.print(“POT1A”);
Miksi lopussa iso “A”? No tämä voisi olla vai “x” tai mikä tahansa merkki. Tämä kuitenkin siksi että se helpottaa Gambas koodia. Seriaalista tuleva tieto on kirjoitettu yhteen pötköön, niin Gambas tietää että kun tulee iso “A” niin seuraavaksi tulee anturin arvo.
Serialissa liikkuu tämännäköistä tietoa: POT1A453FPOT2A678FPOT1A443FPOT2A578F…
Serial.print(“F”);
“F” lähetetään Serialiin niin Gambas tietää milloin anturin arvo on luettu loppuun asti.

käännetään ohjelma ja ajetaan se Arduinoon PC:n avulla.

[size=150]Gambas[/size]

Käynnistämme Gambasin, jonka jälkeen vasemmalta “New project…” avautuu seuraavanlainen näkymä


Valitaan “Qt graphical application” ja painetaan “Next”, valitaan kansio johon ohjelma luodaan ja painetaan “Next”, lopuksi annetaan ohjelmalle nimi ja vielä “Ok”

Tässä on kuvattu tärkeimpiä kohteita ohjelmasta. Tässä artikkelissa ei opeteta Gambas ohjelmointia muutakuin vaadittavan verran, jotta esimerkin pystyy toteuttamaan.
[b]

  1. Seriali kirjaston lisääminen[/b]

Ensimmäiseksi tarvitsemme kirjaston jolla käsitellään Serialia. Tässä kirjastossa on muutakin, mutta tarvitsemme vain sarjaporttia. Tämä löytyy yläpalkista “Project -> Properties…”


Selataan listaa ja laitetaan ruksi kohtaan gb.net. Nyt meillä on kirjasto käytössä.

2. Graafinen käyttöliittymä

Formia voi venytellä haluamansa kokoiseksi, samoin yleensä kaikkia komponenttejä. Lisätään Formille kolme Buttonia eli nappia sekä kaksi LCDNumberia. Komponenttien lisääminen tapahtuu ihan hiirellä vetämällä ja pudottamalla Formille. Clikataan Ensimmäistä LCDNumberia ja muutetaan sen arvoa “Digits” ja annetaan arvoksi 4, koska Arduinolta saatava potentiometrin tilatieto on maksimissaan neljä numeroa eli 1023. Tehdään sama toiselle LCDNumberille. Buttoneiden tekstejä voi muuttaa klickaamalla haluttua nappia ja muuttamalla arvoa “Text”.


Lopuksi lisäämme Formille “SerialPort1”:n.

Nyt käyttöliittymä on valmis.
3. Ohjelmakoodi

Ohjelmakoodi on alla. Sen voi kirjoittaa Gambasiin kun tuplaclikkaa jotain komponenttia formilla, tai painaa formin yläpuolella olevaa valkoista nappia, jossa lukee “Code” kun hiiren cursorin vie sen päälle. Pyyhi valmiiksi tullut koodi ja kopio koodi alapuolelta. En rupea Iden käyttöä käymään tässä läpi tarkemmin. En tiedä onko Gambasista kirjoitettu mitään suomenkielistä opasta, mutta Visual Basic 6 löytyy ainakin ja niillä pääsee aika pitkälti alkuun. Muutamia eroavaisuuksia toki on mutta niistä lukee ohjelman kotisivuilla.

[code]’ Gambas class file

Public Luettu As String 'Muuttuja

Public Sub SerialPort1_Read() 'Kun Serialportti lukee se suorittaa kyseisen function

Dim Kirjain As String 'Luettu kirjain Serialista
Dim Katkottu As New String[] 'Taulu johon kirjaimet luetaan, tauluja on niin monta kuin Arduino lähettää

Read #SerialPort1, Kirjain, 1 'Luetaan kunnes ei ole mitään luettavaa
If Kirjain <> “F” Then 'niin kauan kunnes tulee F joka tarkoitti että tulee seuraavan anturin tieto
Luettu &= Kirjain 'lisätään Luettu muuttujaan Kirjain muuttujan arvo
Else
Katkottu = Split(Luettu, “A”) 'katkotaan Luettu A:n kohdalta

If Katkottu[0] = "POT1" Then ' jos kyseessä on POT1
  
  LCDNumber1.Value = Val(Katkottu[1]) 'Asetetaan LCDNumber1 valueksi arvo joka saatiin arduinolta
  
Endif

 If Katkottu[0] = "POT2" Then
  
  LCDNumber2.Value = Val(Katkottu[1])
  
Endif

Luettu = "" 'Tyhjennetään Luettu

Endif

End

Public Sub Yhdista()
'tämä functio hoitaa Arduinon yhdistämisen

If SerialPort1.Status = Net.Active Then 'Mikäli yhteys on jo muodostettu
Close SerialPort1 'suljetaan yhteys
Else 'muuten hoidetaan yhteys kuntoon
SerialPort1.portname = “/dev/ttyACM0” ’ osoite jossa Arduino sijaitsee
SerialPort1.Speed = 9600
SerialPort1.parity = SerialPort.none
SerialPort1.databits = SerialPort.Bits8
SerialPort1.StopBits = SerialPort.Bits1
SerialPort1.FlowControl = SerialPort.none
Try SerialPort1.Open() 'yritetään avata yhteys
If Error Then Message.Error(“Ongelmia yhdistäessä laitteistoon”) 'jos ei onnistu annetaan virhe
Endif

End

Public Sub Arduino(viesti As String)
'Tällä functiolla lähetetään tietoa Arduinolle
Try Print #SerialPort1, viesti 'lähetetään tietoa serialille
If Error Then 'jos virhe
Message.Error(“Viestin lähettäminen ei onnistunut”) 'tulostetaan virhe
Endif

End

Public Sub Button1_Click()
'kun Button1 clicataan, niin tämä koodi suoritetaan
Arduino(“1”) 'kutsutaan functiota Arduino ja lähetetään viesti 1
'joka Arduinonkoodissa tarkoittaa että sytytetään led

End

Public Sub Button2_Click()
'kun Button2 clicataan, niin tämä koodi suoritetaan
Arduino(“0”) 'kutsutaan functiota Arduino ja lähetetään viesti 0
'joka Arduinonkoodissa tarkoittaa että sammutetaan led

End

Public Sub Button3_Click()
Yhdista 'suljetaan yhteys
Quit 'suljetaan ohjelma
End

Public Sub Form_Open()
'tämä koodi suoritetaan kun formi käynnistyy
Sleep 1 'odotetaan sekuntti
Yhdista 'yhdistetään seriali

End

Public Sub Form_Close()
'tämä koodi suoritetaan kun ohjelma suljetaan ruksista
Yhdista 'suljetaan jos yhteys on päällä

End[/code]
Olen kommentoinut ohjelmakoodia parhaani mukaan.

4. Ohjelman kääntäminen

Ohjelmaa voi ajaa yläpalkissa olevalla vihreällä nuolella. Seuraavaksi käännämme ohjelman yhdeksi ajettavaksi tiedostoksi. Tämän jälkeen ohjelman voi käynnistää suoraan päättestä.
Ylävalikosta “Project -> Make -> Executable…” Nimi ja ok. Nyt meillä on tiedosto jota voi ajaa ettei Gambasia tarvitse käynnistää.

5. Kopio

Kopioidaan kansio, jonka alussa loimme uuden Gambas projektin luomisen yhteydessä ja liitämme kansion Raspberrylle. Tämän voi suorittaa USB muistitikulla tai vaihtoehtoisesti siirtämällä kansio suoraan muistikortille, omaan kotikansioon. Kytketään Arduino USB-kaapelilla Raspberryyn. Ohjelman ajaminen tapahtuu kohdekansiossa päätteellä ./Ohjelmannimi.gambas tai tiedostojenhallinnassa tuplaclikkaamalla Ohjelmannimi.gambas tiedostoa.
kuva6.png
[size=150]Loppusanat[/size]

Mitä tällä voi tehdä? Mahdollisuudet ovat tietysti rajattomat. Gambas tuntuu olevan vielä aika vieras monelle, joten halusin luoda arttikkelin jossa hiukan raapaistaan pintaa ja saisi harrastelijat huomaamaan että graafisen käyttöliittymän tekeminen ei vaadi ihmeitä ja kymmenien rivien kirjoittamista, että saa muutaman napin näytölle. Joten raja on nyt laskettu niin alas kuin mahdollista -> nyt koodaamaan!

Hyvä artikkeli. Laitan raspberryn pian tilaukseen, pitää tätäkin kokeilla.

Tarkoittaako tämä sitä, että jos asennan kortille tuon zipin, saan rpi:hin sekä sen perus käyttiksen ja Gambas3sen? Eli siis rasberryn käyttöön riittää, kun asennan tuon paketillisen muistikortille?

Kyllä tarkoittaa. Paketissa on Raspbian “wheezy” sekä valmiiksi asennettu Gambas3. :sunglasses:

Miten voisin käyttää gambasin sijasta suoraan python.koodia? Tarkoitus olisi ohjata webiopi ohjelmalla arduinoa.

jotenkin näin:

import serial ser=serial.Serial('/dev/ttyACM0',9600 teksti=1 #tai 0 ser.write(teksti)

No mahtavaa, kiitos hyvästä ohjeesta !

Sujui helposti yksi ongelmanratkaisu, kun RasPi ja Arduino Uno oli jo omaan projektiini varattu. Vielä pitäisi saada säännöllisesti siirrettyä vähän tietoa Arduinolta RPin kautta nettiin…
Ai niin sattuiko seuraava artikkelisi olemaan… :mrgreen:

Ftp, PHP $_POST, Database vai miten halusit?

Tässä tiedon janoaville pythonia. Eli ohjelma lukee Arduinolta 2 analogiatietoa, tekee niistä tiedoston ja lähettää sen ftp:llä palvelimelle. Ohjelma on allekkirjoittaneen käsialaa, enkä ole laittanut siihen minkäänlaista virheenkäsittelyä. Luo samaan kansioon missä ohjelmaa ajat tiedot.txt

[code]import serial
import time
import datetime
from ftplib import FTP
#muuta seuraavan muuttujan arvoa sen mukaan montako anturia luetaan
antureita=2

alku = time.time() #muuttuja tietokoneen aika
anturiarvot=[]
aika = datetime.datetime.now()#kello ja päivämäärä joka tulostetaan tiedostoon
aika=aika.strftime("%d.%m.%Y %H:%M:%S") #muutetaan luettavampaan muotoon

#FTP(“palvelin” , “käyttäjätunnus”, “salasana”)
ftp = FTP(“192.168.0.1”, “kayttaja”, “salasana”)

#lisätään antureita listaan
for i in range(antureita):
anturiarvot.append(“0”)

odotus_aika = int(raw_input(“Anna viive sekunneissa:”))
odotus_aika2=odotus_aika+alku
lopeta=""
#tätä joudut muuttamaan serialportin mukaan!!!
ser=serial.Serial("/dev/ttyACM0",115200)
if (ser):
print(“Yhteys Arduinoon muodostettu.”)

#ohjelma pyörii luupissa, kunnes käyttäjä kirjoittaa x ja painaa enter
while lopeta<>“x”:
#luetaan serialia size= montako bittiä luetaan. yksi kirjain tai numero 1 bitti
ser_tiedot=ser.read(size=antureita7)
lopeta = raw_input(“Lopeta ohjelma kirjoittamalla x ja painamalla Enter”)
#etsitään oikea aloituskohta eli “A0”, koska ohjelma alkaa sattumanvaraiselta paikalta
#lukemaan serialia
for i in range(len(ser_tiedot)):
loppu = i + len(“A0”)
if ser_tiedot[i:loppu] == “A0”:
#asetetaan serialin tulos oikeaan muotoon (leikkaa liitä)
#
uusi=ser_tiedot[i:antureita*7] + ser_tiedot[0:i]
for u in range(antureita):
#pilkotaan vain anturien arvot pötköstä
anturiarvot[u]=uusi[2+(7
u):6+(7*u)]
#mikäli aika on suurempi, mitä odotusaikamme
if odotus_aika2<time.time():
#muutetaan seuraava odotusaika
odotus_aika2=odotus_aika2+odotus_aika
#avataan tiedosto lisäys muodossa
tiedot = open(“tiedot.txt”, “a”)
#kirjoitetaan tiedostoon
tiedot.write(aika + " Anturi0:"+anturiarvot[0]+" Anturi1:"+anturiarvot[1]+"\n")
#suljetaan tiedoston kahva
tiedot.close()
#lähetetään tiedosto ftp:lle
ftp.storbinary(‘STOR tiedot.txt’, open(‘tiedot.txt’, ‘rb’))
#suljetaan ohjelman lopussa ftp
ftp.close()
[/code]

Arduinoon seuraavanlainen koodi:

[code]void setup() {

Serial.begin(115200);
}

void loop() {

Serial.print(“A0”);
Serial.print(analogRead(A0)+1000);
Serial.print(“X”);

Serial.print(“A1”);
Serial.print(analogRead(A1)+1000);
Serial.print(“X”);

delay(10);
}[/code]

Eipä tuo mennytkään ihan heittämällä:
Latasin koko paketin + ohjelmakoodin RasPille, ajoin Gambasilla ja tulee herja:
“gb.qt4: warning: unable to load Qt translation: en_GB.UTF-8”

Ja hetken päästä aukeaa ikkuna jossa otsikkona ohjelman nimi,
ikkunassa tikkarin kuva ja “ongelmia yhdistettäessä laitteistoon” sekä ok-painike
(Arduinossakaan ei kyllä ole kytkentöjä, mutta ainakin PC:llä kokeillessa tuli konsoliin tekstiä ok)

Mitä itse sain kaiveltua niin:
Eka kohta liittynee käytössä olevaan kieleen, ei kai pitäisi haitata (?)
Eli pitäisi ehkä kieleksi valita englanti, vain näppis suomeksi ?

Toinen kohta liitty kai usbiportin nimeen, RasPin lsdev ei sisällä tuollaista “/dev/ttyACM0” laitetta. Lähimmäs osuu “/dev/ttyAMA0” mutta ei toimi sillä. Millä tuohon oikean nimen löytäisi ?

EDIT: Kelpuuttaakohan Google sites FTP siirtoa ? (tullut joskus tuonne domaini parkkeerattua)

tuo herja on joku automaattisen käännöksen herja tai jotain vastaavaa. siitä ei tarvi välittää. simun kohdalla ongelma on ainoastaan tuon oikean seriaalin löytäminen… eli usb arduinosta irti ja rasbilla terminaaliin ja kirjota
$ cd /dev
$ ls tty*
saat listan… pluggaa usb arduinoon paikalleen ja
$ls tty*
se mikä sinne tulee lisää niin se on se oikea :sunglasses:

No niin, kuso kulkee :smiley: Piti vaan buutata RasPi välillä että sai “ttyUSB0”:n erottumaan joukosta. Kiitos vinkistä !

Hienoa homma!

onnistuko tuon imagen asennus ihan ongelmitta?

Itellä toimii uusin versio raspbianista mutta tuota en saa toimimaan?
myöskään asennus ei onnistu… kolmella eri tavalla oon kokeillu ja ensimmäisellä ei lisäosat onnistunu lisätä, tuli vaan liuta erroreita…

sen jälkeen kaks eri asennuskertaa muuten onnistu ihan hyvin mutta kun yrittää käynnistää ohjelman nin suoritinkäyttö hyppää 100% eikä ohjelma vaan käynnisty ikinä…

sama ongelma ollu monella muullakin ja käsittääkseni just tuo image jossa gamabas asennettuna on juurikin sitä varten tehty jos ei se asennus onnistu…

sitten yritin tietysti tuota imagee ajaa kortille mutta ei etes yritä lähtee käynnistymäään… (merkkivaloista palaa ainoastaan punanen)… ajoin tietysti sen uusimman uudelleen ja testasin niin se toimii taas ihan hyvin… pari kertaa kokeilin jopa eri korteilla mutta en sitä saanu käynnistymään?? teinkö jotain väärin?

ohjeita? vinkkejä?
linux ei ole ennestään kovin tuttu niin ei ole noista arkkitehtuureista tms paketeista kokemusta että mitä pitää olla asennettuna…