RT-Linux III

ArticleCategory:

Hardware

AuthorImage:

[Foto van de Auteur]

TranslationInfo:

original in es Ismael Ripoll & Elisa Acosta

es to en Georges Tarbouriech

en to nl Tom Uijldert

AboutTheAuthor:

Ismael Ripoll, afgestudeerd aan de Polytechnische Universiteit van Valencia in 1996. Professor in operating systemen aan de afdeling DISCA. Onderzoeksgebieden omvatten onder andere real- time scheduling en operating systemen. Linux gebruiker vanaf 1994. Hobby's: Trektochten door de Pyreneeën, skiën en hobby-electronica.

Elisa Acosta is een computer ingenieur aan de polytechnische school van Valencia. Op dit moment werkt ze voor Indra (een communicatiebedrijf) aan jaar-1900 problemen :-)

Dit artikel is gebaseerd op het werk van Elisa Acosta tijdens haar afstudeeropdracht.

Abstract:

Met behulp van een eenvoudige elektrische schakeling kunnen we RT-Linux opdrachten geven via een infrarode afstandsbediening.

ArticleIllustration:

[Illustratie]

ArticleBody:

Inleiding

Je hoeft geen elektronica- of hardwarekennis te hebben voor het begrijpen van dit artikel, hoewel we het zullen hebben over een kleine hardware component die we gebruiken voor de infrarode afstandsbediening.

Er was een project met de naam "lirc" (Linux Infra-red Remote Control) gestart door Ralph J.K. Metzler (http://fsinfo.cs.uni-sb.de/~columbus/lirc/) waarbij een infrarode ontvanger werd ontwikkeld met gebruikmaking van de standaard Linux hulpmiddelen. Met "standaard" wordt bedoeld dat het geen gebruik maakte van de RT-Linux real time uitbreidingen. In dit artikel starten we met hetzelfde onderwerp maar gaan we in op oplossingen met behulp van RT-Linux.

Beschrijving

In het eerste deel van ons project bekijken we de hardware die nodig is voor het aansluiten van een infrarood ontvanger op de computer. In het tweede deel zullen we zien hoe we de signalen van de infrarood ontvanger kunnen interpreteren met behulp van Real-Time Linux. We hebben slechts weinig hardware nodig: een Sharp (IS1U60) infrarood ontvanger en een paar kabels en pluggen.

De ISU1U60 infrarood ontvanger is een elektronisch wonder; met een 3-pins connector (twee voor voeding en één voor aarde) is het in staat om praktisch alle ontvangst- en conversie werk te doen, waarbij een TTL-signaal wordt aangeboden op de seriële aansluitpin.


Overzicht van het systeem en de elektrische aansluitingen.
PC's hebben een hoop connectoren om allerlei soorten digitale randapparatuur aan te sluiten (modems, printers, SCSI, toetsenbord, monitor enz.) maar niets waarmee we eenvoudige elektronische apparatuur aan kunnen sluiten. Oftewel, een standaard PC heeft geen data- aquisitie kaart. Een kaart die je in staat zou stellen om de elektrische spanning van een kabel af te lezen.

Toevallig is de parallelle poort (en ook de seriële poort) te gebruiken als algemene invoer en uitvoer poort. Een hoop randapparaten gebruiken dit om met de PC te communiceren zoals bijvoorbeeld een Iomega ZIP drive.

We zullen de parallelle poort gebruiken voor het ontvangen van de gegevens van de infrarood ontvanger. We hebben hierbij slechts één pin nodig van deze poort omdat de ontvanger ook slechts één data-pin heeft.

De infrarood ontvanger

Zoals reeds eerder vermeld is de IS1U60 een infrarood ontvanger, speciaal voor toepassing in huishoudelijke apparatuur.

Het signaal van de afstandsbediening is heel complex omdat het diverse coderingen en modulaties combineert. Laten we dit signaal eens nader bekijken.

Het medium voor het signaal van de afstandsbediening zijn de lichtgolven in het infrarood spectrum. Dit soort licht is volkomen onschadelijk, in tegenstelling tot ultraviolet licht. Infrarood is niet zichtbaar voor het menselijk oog maar wel voor elektronische halfgeleiders. Infrarode lichtbronnen zijn onder andere: de zon, gloeilampen, LED-diodes enz. Een infrarode LED wordt door de afstandsbediening gebruikt voor het uitzenden van het signaal.
Infra-red light Visible ultraviolet light
Halfgeleiders zijn gevoelig voor licht (welke kleur/frequentie dan ook). Daarom worden de meeste halfgeleiders verpakt in zwart plastic om ze zo tegen het licht te beschermen. Een infrarood sensor is voornamelijk een halfgeleider diode voorzien van een glasscherm wat alleen infrarood licht door laat.

Een op die manier geconstrueerde detector is in staat om alle infrarood te detecteren, ongeacht de bron van het licht. Ontwerpers van afstandsbedieningen moesten een codering aan het licht toevoegen om het zo te kunnen onderscheiden van andere lichtbronnen. Het uitgezonden signaal van een afstandsbediening wordt gemoduleerd met frequenties tussen de 32 en 40 KHz, afhankelijk van fabrikant en type. Laten we even aannemen dat de frequentie 38 KHz is omdat dit de meest gebruikte is. Meer als 90% van de apparaten gebruiken deze frequentie of iets wat er veel op lijkt.
De infrarood ontvanger.
We moeten niet vergeten dat alles wat er gedaan wordt om het signaal te transporteren ook weer ongedaan moet worden gemaakt na ontvangst. Als we infrarood uitzenden dan moeten we het ontvangen; als deze wordt gemoduleerd met een 38 KHz carrier (= basisfrequentie waarop het signaal wordt getransporteerd) dan moet deze carrier ook weer ongedaan worden gemaakt (gefilterd). Het demoduleren gebeurd analoog met een enkelbands frequentiefilter (om alle frequenties die ver van de uitzendfrequentie zitten eruit te filteren) en met een rectifier/integral filter.

Het gemoduleerde infrarode licht op 38 KHz is het communicatiemedium wat wordt gebruikt tussen de zender (afstandsbediening) en ontvanger (TV, video enz.). Nu moeten we nog bepalen hoe de informatie wordt verzonden oftewel, welke bits komen overeen met welke ingedrukte toets op de afstandsbediening.

De codering van die informatie is afhankelijk van de fabrikant maar gelukkig hoeven we dat in dit project niet te weten, we hoeven de coderingen alleen maar te vergelijken.

Afgaand op de modulatie van het signaal mag het duidelijk zijn dat de informatie serieel wordt verzonden. Bit voor bit en dus hebben we slechts één stroom data aan de ontvangende kant.

De volgende informatie is afkomstig van de technische specificaties van sensor IS1U60 (http://ns14.sharp.co.jp/ecg/unit/is1u60/is1u60-fea.html) en geeft de interne structuur weer. De twee linkerpijlen geven het ontvangen infrarode licht weer wat om wordt gezet in een elektrische stroom via de LED. Het signaal wordt versterkt en het directe signaalgedeelte wordt geëlimineerd, het wordt gefilterd om alleen frequenties vlakbij de 38 KHz door te laten en vervolgens wordt het gecorrigeerd (demodulator plus integrator), en tenslotte wordt het omgezet naar een TTL-signaal.

De parallelle poort

De parallelle poort is van origine ontworpen voor printercommunicatie maar van lieverlee (en omdat er niks vergelijkbaars op de PC was te verkrijgen) werd het gebruikt voor het aansluiten van allerlei randapparaten.

Op dit moment zijn er op zijn minst twee variaties (ECP, EPP) om de parallelle poort om te toveren tot een algemeen bruikbare communicatiepoort. Ons project heeft slechts bescheiden functionele eisen voor het gebruik van de parallelle poort, daarom zal iedere versie voldoen. Feitelijk hebben we maar één IN datastroom nodig.
State register
Detailering statusregister
De PC bestuurt de poort met drie 8-bit registers. Dit zijn het dataregister (0x378), het statusregister (0x379) en een stuurregister (0x37A). De waarden tussen haakjes geven de gebruikelijke registeradressen weer van de eerste parallelle poort.

Schrijven in het stuurregister programmeert de poort. Van de 8 bits in het register wordt alleen bit 4 gebruikt. Een "1" in dit bit laat de hardware van de poort een interrupt genereren (meestal nummer 7) indien de ACK datastroom veranderd van hoge spanning (5 volt) naar lage spanning (0 volt).

Het dataregister is de deur die openstaat naar de pinnen van de connector. Data die naar deze poort wordt geschreven verschijnt op pin 2 tot en met 9 van de parallelle connector. Dit is alleen een OUT poort. Omdat we alleen gedetecteerd infrarood moeten aflezen is deze poort niet bruikbaar voor ons. We hebben een invoerpoort nodig. De statuspoort geeft de status van de printer weer. Deze draden worden door de printer aangestuurd (of door een extern apparaat) en de computer leest dit af. Dit zijn dus IN draden. Ook al is het een 8-bit register, alleen de 5 hoogste bits hiervan worden aangesloten en gebruikt, de rest staat altijd op nul. De draden zijn vernoemd naar de functionaliteit die ze hebben wanneer een printer is aangesloten maar feitelijk zijn het gewone digitale draden die je voor van alles kan gebruiken.

Van deze draden is vooral die op pin 10 interessant (bit 6 van het register), omdat het gebruikt wordt als een digitale invoerlijn. Maar hij kan ook worden gebruikt voor het geven van interrupts als de spanning op de lijn wijzigt (van 5 naar 0), zoals boven vermeld.

Verbinden aan de computer

Schema van chip en verbindingen

De infrarode ontvanger heeft tussen de 4,7 en 5,3 volt aan spanning nodig. Als de spanning beneden de 4,7 valt dan stopt de ontvanger met functioneren. Deze voeding kan op verschillende manieren worden verkregen:

  1. Met batterijen. In dat geval is het het beste om een 4V5 batterij te gebruiken in serie met een kleine (oude) 1V5 batterij. Het zo verkregen voltage zal geen 6 volt zijn maar 5,5 omdat de kleine 1V5 batterij geen vol vermogen levert.
  2. Met een transformator-voeding (die wisselstroom omzet in gelijkstroom). Ook al is dit simpel te maken, het valt buiten dit artikel. Dergelijke voedingen kun je kopen in dezelfde winkels als waar je elektronische componenten haalt.
  3. De 5 volt aftappen van je computer. Een computer bevat twee typen kabels: platte kabels (flat cables) voor het transporteren van data en dikke rode, zwarte en gele kabels voor de voeding. De rode kabel is de +5 volt en de zwarte is de nuldraad oftewel 0 volt.
Om de ontvanger te voeden sluiten we de zwarte kabel aan op pin 2 en de rode (5V) op pin 3.

Verbinden aan de parallelle poort is een kwestie van het aansluiten van ontvanger pin 1 aan poort pin 10 en ontvanger pin 2 aan poort pin 18. Merk op dat de pin GND (ground) op twee plaatsen moet worden aangesloten, de aarde van de voeding en de aarde van de poort.

Voor het maken van deze verbindingen kun je willekeurige kabel gebruiken.

De real-time taak

REAL-TIME module
#define PERIOD 100
#define SIZE 8192
#define FIFO_ZERO 0
#define LP0 0x378 /*Address /dev/lp0*/
#define STS LP0+1

RT_TASK task;

//---------- Real time task
void Real_Time_Task(){	
  unsigned short data1, data2=0;
  unsigned long  cont = 0L;
  
  while(1){
    // Read the port value
    data1=inb(STS) & 0x40;
    	
    // If no change.. 
    if ( data2 == data1) {
      // Increment the counter.
      cont++;
    } else {
      
      // Send the counter value.
      rtf_put(FIFO_ZERO, 
              (char *) &cont, 
	    sizeof(cont));
      cont = 0L;
      data2 = data1;
	
    }
    rt_task_wait();
  }   
}   

//------------- Main program
int init_module(){
  RTIME now = rt_get_time();

  // Create communication FIFO with Linux.
  rtf_create(FIFO_ZERO,SIZE);

  // Create the real time task.
  rt_task_init(&task,Real_Time_Task,1,3000,4);

  // Make it periodic.
  rt_task_make_periodic(&task,now+3000,PERIOD);

  return 0;  // Everything worked.
} 

//------------- To unload the module
void cleanup_module(){
  rt_task_delete(&task);
  rtf_destroy(FIFO_ZERO);
}  
De eenvoudigste manier om de waarde van de ACK pin van de parallelle poort af te lezen is met het maken van een periodieke taak die de bitstatus (pin) steeds afleest. Als een verandering wordt gedetecteerd terwijl de pin dezelfde waarde blijft houden wordt er een teller opgehoogd. Daarmee geven we met iedere tel de tijd aan waarin het bit op hetzelfde niveau bleef. Als nu een verandering optreedt dan sturen we de waarde van de teller naar een normaal Linux proces via een FIFO. Er moet dus een Linux proces actief zijn dat wacht op de FIFO om hem uit te kunnen lezen. De gelezen waarden komen overeen met de periode dat het signaal laag was en vervolgens hoog.

Het is belangrijk om een precieze meting te krijgen van het signaal van de ontvanger. Sterker nog, het is dé reden voor het inzetten van een real-time systeem. Het interpreteren van de rij metingen die van de real-time taak af komen om te ontdekken welke toets er is ingedrukt is niet tijdsafhankelijk en kan dus worden gedaan door een normaal Linux proces.

Een andere mogelijkheid om metingen te verrichten is het installeren van een interrupt afhandelprogramma voor interrupt 7. Je hebt dan de periodieke taak niet nodig en ook geen nieuwe schedule.

De functie init_module start de taak. Je hoeft alleen de communicatie-FIFO voor de taak te creëren, de taak zelf en tenslotte deze omzetten naar een periodieke taak. De waarde van de periode (100 RT-tikken is ongeveer 90 micro seconden) is voor testen en foutafhandeling. Hoe korter de periode, des te preciezer de meting maar dit zal meer CPU-tijd verbruiken.

Het volgende programmaatje stuurt de waarden die het afleest van apparaat /dev/rtf0 door naar de standaard uitvoer. Met dit eenvoudige programma kunnen we "zien" wat voor frame er wordt verstuurd van de infrarode zender als een toets wordt ingedrukt.
Programma
#include 
#include 
#include 			
#include 
#include 
int main(){
  int fd;
  unsigned long cont;
  fd=open("/dev/rtf0",O_RDONLY);
  while(1) {
      read(fd,&cont,sizeof(cont));
      if ( cont > 700) printf("\n");
      printf("%d ",cont);
      fflush(stdout);
    }
  return 0;
}
      
De waarde 700 in dit programma is een geschatte waarde en geeft de minimale tijd weer die verstrijkt tussen de ontvangst van twee opeenvolgende frames.

Hoewel de meeste afstandbedieningen een zelfde infrarood signaal gebruiken, hoeft dat zeker niet zo te zijn voor de codering van de toetsen. Het herkennen van toetsen is echter een kwestie van vormanalyse en geen real-time probleem. De beste manier om een programma te maken die concrete commando's herkend is het bekijken van de uitvoer van dit programma om een idee te krijgen hoe de afstandsbediening zijn data verstuurt.

Simpel gesteld, als een toets op de afstandsbediening wordt ingedrukt zal een bepaalde sequentie worden uitgezonden die we op het scherm als een rij nummers zien. Als we de toets ingedrukt houden zal dezelfde sequentie periodiek worden verstuurd (SONY afstandsbedieningen vormen hierop een uitzondering).

Laten we dit eens bekijken (vergeet niet de real-time modules te installeren: FIFO en scheduler):


  # modprobe rt_fifo_new
  # modprobe rt_prio_sched
  # insmod ir
  # ir_get
  0
  126509 13 6 23 7 13 7 12 7 12 7 12 7 12 8 11 8 11 8 11 8 11 8 11 19 11
  1081 13 6 23 7 12 7 12 8 11 8 11 8 11 8 12 7 12 8 11 8 11 8 11 19 11
  1080 14 6 23 7 12 7 12 7 12 7 12 8 11 8 11 8 11 9 11 7 12 8 11 19 11
  1080 13 6 24 6 13 7 12 7 12 7 12 7 12 7 12 8 11 8 11 8 11 8 11 19 11
  
We kunnen zien dat de toets steeds dezelfde sequentie herhaalt als hij ingedrukt blijft. Een ander interessant detail is de meetfout. De getallen van de verschillende frames hebben een variatie van 1, dit is de kwantificatiefout.

Voor het programmeren van herkenningssoftware hoef je alleen een array aan te houden met daarin ieder frame wat door de afstandsbediening kan worden uitgezonden. Wanneer nu een frame is ontvangen kan deze worden vergeleken met de waarden in de array (een verschil van +/- 1 is acceptabel). Dit programma mag de lezer als oefening zelf schrijven.

Sommige afstandsbedieningen zenden steeds een ander frame uit wanneer een toets in wordt gedrukt, zelfs als we steeds dezelfde indrukken. Ze doen dit als volgt: als we een toets indrukken zendt het apparaat een frame die we "frameA" zullen noemen. Als we hem loslaten en wederom indrukken wordt "frameB" uitgezonden. De volgende toetsindruk zend weer frameA enzovoorts. Als we de toets ingedrukt houden zal hetzelfde frame meerdere keren worden verstuurd. Op deze manier kan de ontvanger onderscheidt maken tussen een lange toetsindruk en twee korte. Hoe denk je dat de volgorde 1 1 (elf) wordt gemaakt op nieuwe afstandsbedieningen?

Referenties