TrainPi osa 3: Annetaan palautetta

Tässä osassa siirrytään jo vähän edistyneempiin asioihin ja ruvetaan liittämään Raspberry Pi -tietokonetta ulkomaailmaan.

Kun rakennetaan tietokoneasetinlaitetta, olisi hyvä saada radasta tieto onko jokin raideosuus varattuna vai vapaana – eli palaute. Se tuodaan tietokoneelle palauteväylää pitkin. Eräs suosittu palauteväylä on Märklinin kehittämä s88, joka on hyvin yksinkertainen käyttää. Sen haittapuolena on herkkyys ympäristön sähköisille häiriöille.  Tässä esitellään s88-väylän liittäminen Raspberry Pi -tietokoneeseen. Samalla käsitellään hieman Raspberry Pin liitäntöjä ja ohjelmointia.

Palautetta voidaan käyttää muuhunkin kuin raideosuuksien tilan ilmaisemiseen. Palauteväylään voidaan kytkeä painikkeita, joilla saadaan aikaan erilaisia toimintoja, kuten vaihteen kääntyminen tai kulkutien turvautuminen.

Perusasioita

Muutamia perusasioita kannattaa kerrata tässä välissä. Raspberry Pin käyttöjärjestelmänä toimii tässä kehitysvaiheessa Raspbian-niminen Linux-versio. Koneeseen voi liittää näytön, näppäimistön ja hiiren, mutta yhtä hyvin siihen voi ottaa verkon kautta ssh-yhteyden. Tämän projektin kannalta kumpikin käy. Itse käytän rajallisen työpöytätilan takia jälkimmäistä tapaa. Verkkoyhteys tarvitaan joka tapauksessa ohjelmiston päivittämiseen ja muutamien uusien ohjelmien asentamiseen. Raspberry Pin tarkalla mallilla ei liene kovin paljoa väliä, mutta uudemmissa on tietysti enemmän kapasiteettia tehdä useita asioita yhtäaikaa.

Koeluontoiset kytkennät kannattaa tehdä koekytkentäalustalle tai reikälevylle ja Raspberry Pi liittää siihen nauhakaapelilla ja piikkirimalla. Näin kytkentöjen rakentelu ja mittailu on helppoa itse tietokoneen pysyessä suojassa. Myös erityistä prototyyppien rakenteluun tarkoitettua lisälevyä voi käyttää. Sellainen kiinnitetään suoraan Raspberry Pin laajennusliittimeen.

Jonkin verran huomiota ansaitsee komponenttien suojaaminen staattiselta sähköltä. Se on erityisen tärkeää käsiteltäessä irtonaisia CMOS-piirejä ja MOSFET-transistoreita. Niissä on ohuita eristekerroksia, jotka vaurioituvat herkästi. Jalalliset piirit toimitetaan useimmiten joko muoviputkessa tai johtavaan vaahtomuovinkappaleeseen työnnettynä. Ne kannattaa pitää kotelossaan käyttöhetkeen asti. Parasta olisi, jos työskentelyalustana olisi pöydälle levitettävä antistaattinen matto. Jos sellaista ei ole, kannattaa kuitenkin ainakin valita sellaiset vaatteet, joissa ei saa sähköiskuja ovenkahvoista. Ammattimaisesti elektroniikkaa valmistettaessa pitää olla ESD-sertifioitu työpiste, jossa on määritelty lattian, jalkineiden, työvaatteiden, työtasojen ja välineiden sähkönjohtavuus (ei liikaa eikä liian vähän, luokkaa megaohmeja), ja niitä myös testataan säännöllisesti. Harrastustoiminnassa se taitaa tulla liian kalliiksi.

s88-väylä

s88-palauteväylä on teknisesti sarja yhteenkytkettyjä siirtorekistereitä. Siirtorekisteri on periaatteessa muisti. Siinä on sarja yhden bitin muistisoluja, ja kellopulssin tullessa jokainen bitti siirtyy yhden paikan verran eteenpäin. Bitit siis liikkuvat sarjassa eli marssivat kellon tahdissa kuin elefantit jonossa. s88-väylässä käytetään toistakin toimintoa, jossa kaikkiin muistipaikkoihin ladataan sisältö yhtäaikaa eli rinnakkain.

s88-kaapelissa on kuusi johtoa, joiden toiminnot on esitetty kuvassa 1. Johtojen jännitetasot vastaavat CMOS-logiikkaa, eli looginen 0 on lähes 0 V ja looginen 1 on lähes 5 V.

Kuva 1. S88-väylän johtimet toimintoineen

Kuva 1. S88-väylän johtimet toimintoineen

Kuvassa on esimerkkinä Viessmann 5217 -palautemoduuli, mutta kaikki s88-palautemoduulit toimivat periaatteessa samalla tavalla. Moduulissa on yleensä 16 tuloa ja jokaisessa kiikku. Toisin sanoen kun johonkin tuloon kytkettyä nappia painetaan, painallus jää muistiin kunnes se luetaan. Luku tapahtuu seuraavasti:

  1. PS-johto nostetaan ylös (vaihtuu 0:sta 1:ksi). Tämä vaihtaa siirtorekisterin tilan rinnakkaismuotoiseksi.
  2. CLK-johtoon annetaan pulssi (0-1-0). Kiikkuihin tallentuneet tulojen tilat luetaan siirtorekisteriin. DATA-johdossa näkyy aina ensimmäisen muistipaikan tila.
  3. RESET-johtoon annetaan pulssi. Kiikkujen tilat nollataan, ja moduuli on valmiina ottamaan seuraavat syötteet vastaan.
  4. PS-johto pudotetaan nollaksi. Siirtorekisteri toimii nyt sarjamuotoisena.
  5. CLK-johtoon annetaan pulssi jokaista tuloa kohden. Aina siirron tapahduttua DATA-johdossa näkyy uuden tulon tila.

Tapahtumasarjaa kuvaa oheinen animaatio. Palautemoduuleja voi ketjuttaa niin, että seuraavan moduulin DATA-johto on yhdistetty edellisen siirtorekisteriin. Yleensä yhden 16-tuloisen moduulin sisällä on jo valmiiksi kaksi ketjutettua 8-bittistä siirtorekisteriä. Tällöin seuraavasta moduulista tuleva DATA-johto menee jälkimmäiseen. PS-, CLK-, RESET- ja käyttöjännitejohdot menevät suoraan läpi moduulista toiseen.

Liitettäessä s88-väylää Raspberry Pin liittimeen joudutaan huomioimaan jännitetasot. Raspberry Pi on 3,3 voltin laite, kun taas s88 on 5 voltin väylä.

Raspberry Pi pystyisi periaatteessa syöttämään 5 voltin logiikkaa, mutta loogisen ykkösen jännite jää alhaiseksi, mikä altistaa häiriöille. Toisin sanoen jännitteen ei tarvitse paljoakaan pudota jäädäkseen epämääräiseksi. Tarvitaan siis jonkinlainen liitäntäpiiri. Vaihtoehtoja on useita. 5 voltin käyttöjännite olisi saatavissa Raspberry Pin virtalähteestä, joten periaatteessa riittäisi yksinkertainen transistorikytkentä. Tässä tapauksessa kokeiltiin kuitenkin asentaa optoerotin (U1, U2, U3) lähtevien signaalien väliin, vaikkei galvaaninen erotus (toisistaan täysin erilliset virtapiirit) ollutkaan tavoitteena. Se olisi kuitenkin mahdollinen saavuttaa optojen avulla, jos 5 voltin käyttöjännite olisi erillinen. Kytkentä on siis tämän kirjoitushetkellä kuvan 2 mukainen. Myös datalinja olisi tarvittaessa kytkettävissä optoerottimen kautta, mutta tässä tapauksessa on tehty yksinkertainen vastusjako (R4, R5) jännitteen pudottamiseksi sopivalle tasolle. Raspberry Pin GPIO-linjoihin ei saa tuoda yli 3,3 voltin jännitteitä, muuten on vaarana koko laitteen vaurioituminen.

Kuva 2. S88-väylän kytkentä Raspberry Pin 40-nastaiseen laajennusliittimeen

Kuva 2. s88-väylän kytkentä Raspberry Pin 40-nastaiseen laajennusliittimeen

Kuvassa 2 on esitetty kytkennät 40-nastaiseen laajennusliittimeen. Nastojen nimet ja toiminnot voi helposti tarkistaa kartasta.

Väylän toimintaa ja ajoituksia testattiin lyhyellä Python-ohjelmalla, joka on listattuna kokonaan tämän artikkelin lopussa. Se esittää kuvan 3 mukaisesti komentorivillä annetun määrän tuloja ja niiden tilat. s88-väylän ominaisuuksista on huomattava, että mikään ohjelma ei voi tietää montako palautemoduulia väylään on liitettynä. Siksi luettavien tulojen (eli annettavien kellopulssien) määrä on ilmoitettava aina erikseen. Jos ilmoitettu määrä on liian pieni, osa tuloista jää huomioimatta; jos liian suuri, ylimääräiset näyttävät pysyvästi nollaa – tai jos järjestelmään kytkeytyy häiriöitä, jotakin satunnaista arvoa.

S88-väylän testiohjelma käynnissä. Tulo nro 12 on aktiivinen.

Kuva 3. s88-väylän testiohjelma käynnissä. Tulo nro 12 on aktiivinen. Moduulissa se on nro 13, koska numerointi alkaa ykkösestä.

Ohjelma hyödyntää pigpio-ohjelmistoa. Siihen kuuluu palvelin pigpiod sekä eri ohjelmointikieliin liittyviä kirjastoja, joilla voidaan käsitellä GPIO-nastoja. Raspberry Pin liittimen nastojen tilaa voidaan tarkastella piscope-ohjelmalla, joka kytkeytyy pigpiod-palvelimeen verkon välityksellä. Se ei korvaa oskilloskooppia, mutta on kuitenkin hyödyllinen apuväline ohjelmiston toimintaa selvitettäessä.

Kuva 4. S88-väylän signaalit piscope-ohjelmassa

Kuva 4. S88-väylän signaalit piscope-ohjelmassa. 22: RESET, 23: CLK, 24: DATA, 27: PS. 22, 23 ja 27 käänteisiä.

Pigpio-ohjelmistolla päästäisiin paljonkin nopeampaan ja tarkemmin ajoitettuun signaaliin. Pulssit voisivat olla kymmenen kertaa nopeampia. Silloin kuitenkin käy niin, ettei palautemoduuli pysy perässä!

Kuvan 4 piscopen näyttökuvassa on huomioitava, että kytkentä invertoi eli kääntää lähtevät signaalit. Toisin sanoen nollasta tulee ykkönen ja päinvastoin. Sen takia Raspberry Pin liittimessä signaalin lepotila on looginen ykkönen.

Kun lukee palautemoduulien komponenttien datalehtiä, jää siihen käsitykseen, että siirtorekisteri palauttaisi seuraavan bitin välittömästi kellopulssin nousevalla reunalla. Näyttökuvassa se tarkoittaisi sitä, että rivillä 24 pitäisi viivan nousta samaan aikaan kun rivillä 23 laskee. Todellisuudessahan näin ei ole, vaan signaali tekee monta mutkaa matkan varrella. Käytännössä tämä ilmenee niin, että Raspberry Pin lähettämän kellopulssin reunasta vastauksena saapuvan datapulssin reunaan kuluu lähes millisekunti, mikä tietokoneen mittakaavassa on pitkä aika. Prosessori ehtii sinä aikana suorittaa lähes miljoona käskyä.

Edellinen osa: Pysähdytäänpä hetkeksi

Ohjelmalistaus:

#!/usr/bin/env python
import time
import sys
import pigpio
import signal
import atexit

CK=23 #kellopulssin GPIO - käytetään BCM-numeroita, ks. http://pinout.xyz
PS=27 #PS/LOAD-nastan GPIO
RS=22 #RESET-nastan GPIO
DI=24 #DATA-nastan GPIO
CX=16 #oletusarvo montako tuloa näytetään jollei komentorivillä muuta määrätä
DELAY=0.0005 #pulssien sisäinen ja välinen viive sekuntia; käytännössä 0,5 ms eli 0.0005 on lyhyin joka toimii luotettavasti Viessmannin 5217-moduulilla ja TLP621-optoilla
fstart=[]
floop=[]

if(len(sys.argv) > 1):
 CX=int(sys.argv[1])

pi = pigpio.pi()
x = 0
def cleanup():
 pi.write(CK, 1)
 pi.write(RS, 1)
 pi.write(PS, 1)
 pi.wave_clear()
 signal.setitimer(signal.ITIMER_REAL, 0, 0)
 pi.stop()
 print("")

atexit.register(cleanup)

pi.set_mode(CK, pigpio.OUTPUT)
pi.set_mode(PS, pigpio.OUTPUT)
pi.set_mode(RS, pigpio.OUTPUT)
pi.set_mode(DI, pigpio.INPUT)
pi.set_pull_up_down(DI, pigpio.PUD_OFF)

#kytkentä on invertoiva, siksi ykkönen ja nolla ovat nurinpäin
pi.write(CK, 1) 
pi.write(RS, 1)
pi.write(PS, 1)
pi.wave_clear()
sys.stdout.write("\033[1;36;40m") #värit ANSI-koodeilla
for x in xrange(0, CX):
 sys.stdout.write("%2d " % x)
 sys.stdout.write("\n")

def qs88(signum, frame):
 pi.write(PS,0)
 time.sleep(DELAY)
 pi.write(CK,0)
 time.sleep(DELAY)
 pi.write(CK,1)
 x = pi.read(DI)
 y = x+40
 z = x+30
 sys.stdout.write("\033[1;%d;%dm%2d " % (z, y, x))
 time.sleep(DELAY)
 pi.write(RS,0)
 time.sleep(DELAY)
 pi.write(RS,1)
 time.sleep(DELAY)
 pi.write(PS,1)
 for n in xrange(1, CX):
 time.sleep(DELAY)
 pi.write(CK,0)
 time.sleep(DELAY)
 pi.write(CK,1)
 z = x+30
 sys.stdout.write("\033[1;%d;%dm%2d " % (z, y, x))
 time.sleep(DELAY)
 pi.write(RS,0)
 time.sleep(DELAY)
 pi.write(RS,1)
 time.sleep(DELAY)
 pi.write(PS,1)
 for n in xrange(1, CX):
 time.sleep(DELAY)
 pi.write(CK,0)
 time.sleep(DELAY)
 pi.write(CK,1)
 x = pi.read(DI)
 y = x+40
 z = x+30
 sys.stdout.write("\033[1;%d;%dm%2d " % (z, y, x))
 sys.stdout.write("\r") #toimii jos näyttö on riittävän leveä; tulostaa koko ajan rivin päälle

signal.signal(signal.SIGALRM, qs88)

#määritellään päivitystiheys
signal.setitimer(signal.ITIMER_REAL, 0.1, 0.1)

#lopettaa Enteriä painamalla
raw_input("")


Merkitty: , , , ,
0 comments on “TrainPi osa 3: Annetaan palautetta
1 Yhteydet/Seurannat varten "TrainPi osa 3: Annetaan palautetta"