Het project is op dit moment opgesplitst in twee aandachtpunten: De camera en de focus. Beide apparaten werken via een I2C bus, en hier komen we bij de oorzaak van de moeilijkheden waar we vooral maandag en dinsdag mee hebben gekampt. Er was namelijk geen overeenkomstig apparaat voor de I2C bus in de /dev map in Linux.
Dit was ons al opgevallen vlak voor de verlofweek, en we hebben het gemeld aan de ontwikkelaars van de versie van Linux die op de target draait. In het begin van de week hadden ze dan ook een patch geschreven die gebruikt moest worden bij het recompileren van de kernel (op de target). Echter zonder directe betering. Na lang zoeken was er al sprake van een nieuwe versie van de camera te bestellen, die beter zou functioneren met de bestaande drivers. Toen bleek dat het een bepaalde module was die het probleem veroorzaakte, GPIO. Toen we deze optie uitschakelden voor het recompileren van de kernel hadden we enkele nieuwe devices; enerzijds voor de camera: /dev/video0, en (door het aanvinken van alle compilatie-opties die met I2C te maken hadden) 2 I2C apparaten; /dev/i2c-0 en /dev/i2c-1.
Hierna kwam er terug vaart in de situatie. Er kon geëxperimenteerd worden met de broncodes die werden gevonden voor de communicatie met de camera. Hier werd duidelijk waarvoor die GPIO module eigenlijk nodig was. Zonder deze module kunnen we enkel pure rood – groen – blauw waarden schrijven naar de camera. Dus complexere beelden afbeelden wordt niet evident.
Er waren nog enkele andere problemen, kortom, zoals eerder vermeld, deze driver werkt simpelweg niet goed met ons type camera. Daardoor is, samen met opdrachtgevend bedrijf Dioptik, de beslissing genomen een nieuwe camera te bestellen die beter samenwerkt met de driver. Voorlopig zit het op dat vlak dus even vast, maar er is nog altijd de focus ook om ons op te concentreren.
Ook deze wordt gecontroleerd door een I2C bus, die dus dankzij de patch beschikbaar is geworden.
Al vrij snel hadden we een stukje voorbeeldcode te pakken, die aantoont hoe de device geopend dient te worden en een correct adres dient te krijgen.
#define DEVICE “/dev/i2c-0”De ioctl() functie wijst de addr variabele toe aan I2C_SLAVE, zodat gecommuniceerd kan worden met de slave, in dit geval dus de focus. Natuurlijk, zoals zo vaak in deze situaties, lukte dit niet zomaar. Het bleek hem om een banale syntax fout te gaan.
#define addr 0x40
fd = open(DEVICE, 0_RDWR);
if(fd<0)
{
printf(“\Erreur, impossible d’ouvrir %s”, DEVICE);
exit(1);
}
if(ioctl(fd,I2C_SLAVE,addr) < 0);
{
printf(“\Erreur, impossible de sélectionner le composant i2c a l’adresse 0x%x: %s”, addr, strerror(errno));
exit(1);
}
if(ioctl(fd,I2C_SLAVE,addr) < 0);
Hier staat er een ‘;’ te veel. Syntaxfouten komen wel meer voor, maar ik vermeld dit gewoon even om een markant verschil met Java te illustreren. Deze fout zou in Java direct opgevallen zijn, maar aangezien de C compiler zeer toelatend is ging het er zonder problemen door, met als gevolg dat hij het als een statement beschouwde, en de inhoud tussen de haakjes sowieso uitvoerde. Hierdoor leek de ioctl() functie steeds te falen.
Zodra dat recht gezet was, konden we beginnen testen met het schrijven naar de I2C bus.
char trame[3]; trame[0]=0x04; trame[1]=0x99; trame[2]=0x01;Dit gaf als resultaat "failed to write : remote I/O error"
If (write(fd, trame, 3) < 0)
{
fprintf(stderr, “failed to write : %m\n”)
}
We waren echter niet zeker of het adres dat we toewezen aan de I2C_SLAVE wel het juiste was. Dit hadden we weliswaar afgeleid uit de handleiding van de lens, maar het was niet zeer duidelijk. Dus besloten we een klein algoritme te schrijven dat via een for-lus alle adressen nagaat en verifieert op welk adres de functie write() geen -1 oplevert.
Echter geen succes. Geen enkel adres werd gevonden.
De oplossing zat hem in de manier waarop de connectoren van de lens waren bevestigd op de i2c poort. Er zijn namelijk verschillende connectoren die moeten verbonden worden met de pinnen van de i2c bus (Zie afbeeldingen). We hadden alles aangesloten gebruik makend van een tabel in de handleiding van het ontwikkelingsbord, waarvan hier de relevante lijnen:
PIN # SIGNAL NAME DESCRIPITION
1A VCC_CAM_EXT External Power supply
2A VCC_3V3 Power supply
3B CAM1_SDA SDA Quick Capture
4A CAM1_SCL SCL Quick Capture
5B GND Ground
Maar de VCC connector van de focus zat op pin 1A, een configuratie die gebruikt dient te worden als het om een apparaat gaat dat zelf een stroomtoevoer heeft, vandaar “external power supply”. Bij ons is dit niet het geval, de lens gebruikt de stroomtoevoer van het bord. Vandaar dat de VCC connector op pin 2A moet zitten, iets waar we eerst geen rekening mee hadden gehouden, en achteraf niet meer bij stil gestaan.
Dat verklaarde waarom hij geen adres vond. Bij het opnieuw runnen van onze code om het adres uit te vissen, kregen we deze keer wel resultaat, namelijk drie verschillende locaties: 0x0, 0x21 en 0x7E. Schrijven (via write()) naar deze locaties lukte, maar enkel schrijven naar adres 0x21 gaf een int 3 als return waarde, wat bleek te wijzen op het feit dat er 3 bytes succesvol waren weggeschreven. Dit was dus het enige juiste adres.
Via een oscilloscoop konden we de signalen die werden doorgestuurd verifiëren en concluderen dat het inderdaad was hetgene we bedoelden (zie afbeelding).
Een anekdote: de stagementor hier, Mr. Halluin, had er plezier in dat wij, software programmeurs in opleiding, ons aan het scheel staren waren op de kleine hardware componentjes!
Nu we weten dat de juiste elektronische signalen worden doorgestuurd naar de i2c poort, is de volgende stap de spanning controleren die doorkomt op de focus. Want het is namelijk een apparaatje dat elektronische signalen omzet naar spanning, en de lens verandert zijn focus op basis van deze spanning.
Meer hierover volgende week!
De i2c poort waarop de focus wordt aangesloten
De connectoren van de focus, die dus op de pinnen van de i2c poort moeten

Focus geconnecteerd, op de correcte manier

Opstelling, verbonden met een oscilloscoop, om te meten welke elektronische signalen worden doorgegeven

De output van de oscilloscoop (het onderste signaal is de klok). Hierop is te zien dat we eerst de waarde van het adres doorsturen (0x21, dus 0010 0001), gevolgd door een acknowledgement (kleine uitstulpsel naar onderen toe). Hierna volgt de informatie van de trame variabele: 0x04, 0x99, 0x01.
Groeten vanuit Brive.
Dieter Walckiers
Hannes Claerhout
Geen opmerkingen:
Een reactie posten