I²C / TWI
Beschrijving
I²C (wiki) is een protocol dat bedoeld is om chips in een TV met elkaar te kunnen laten praten, veelal op 1 printplaat. Het is ontworpen door Phillips en breed overgenomen door de rest van de industrie. Het leuke is dat het slechts 2 draden (SDA en SDL) kost en dat er theoretisch tot 128 apparaten aan 1 bus kunnen worden gehangen. Voor toepassing in robots is het dus zeer geschikt. De Atmel µcontrollers hebben een hardware voorziening die I²C ondersteunt. Het heet bij Atmel enkel: Two Wire Interface oftewel TWI. Deze 2 begrippen kunnen en zullen vrijelijk door elkaar gebruikt worden. Verder ben ik ook IIC en I-square-C als benaming tegengekomen. Ook Lego NXT gebruikt I²C. Enkele andere voorbeelden zijn CJMCU, GY-521, SRF10 and CMPS03.

Let op: I²C specificeert niets voor de werkspanning van de SDA en SDC lijn. Daardoor is het bijvoorbeeld heel makkelijk om een GY-521 (3.3Vdc) op te blazen met een Arduino (5Vdc). De oplossing in een dergelijk geval is een level-shifter.

Optrekweerstanden
Zowel de SDA lijn alsook de SDL lijn moeten met een zogenaamde optrekweerstand aan de plus worden verbonden. De waarde van deze weerstandjes varieert. Volgens de datasheet van de 24LS512 geheugenchip wordt de bussnelheid bepaald door de optrekweerstanden. De waarde zou 10kΩ moeten zijn voor een snelheid van 110kHz en een waarde van 2kΩ voor de snellere protocollen, zoals 400 kHz of 1mHz. Des te hoger de gekozen bussnelheid, des te lager de waarde van de weerstanden moet zijn. En ook geldt dat des te meer chips er op de bus zijn aangesloten, des te lager de waarde van de optrekweerstand moet zijn. Ik gebruik 2k2Ω (3 keer rood) weerstanden die aan de plus worden gemonteerd.

Arduino bibliotheek
Several different libraries are available. Github.com/elechouse/MLX90614 seems the preferred apprach to me since it contains a more technical approach in which the I²C commands a worked out on the lowest level. Only uses #include i2cmaster.h. So it does not need any higher or special libraries. Sparkfun offers lots of information and the wire.h and the SparkFunMLX90614.h library. Also playground.arduino also needs wire.h, but also several other includes are required. So we stick to the most pure one of elechouse.

Erfenis
Er bestaan van Atmel 2 Application Notes die het toepassen van TWI tamelijk duidelijk uitleggen: AVR315: Using the TWI module as I2C master AVR311: Using the TWI module as I2C slave. Hieruit blijkt onder andere dat TWI bestaat in diverse standaards met verschillende snelheden. Zo lijken voor robot projecten 2 snelheden toepasbaarbaar, namelijk 100 kBs en 400 kBs. De DS1307 klokchip bijvoorbeeld kan maximaal op 100 kBs lopen. De snelheid van de bus wordt bepaald door de master, maar een slave kan het proces vertragen als het hem te snel gaat. De snelheid van de master wordt bepaald door het TWBR en TWPS register. De formule voor het bepalen van de snelheid staat in de datasheet van de ATmega32 op blz. 173 en blijkt precies te kloppen met voorbeeldprogrammas. De prescaler lijkt me uitsluitend nodig voor zeer langzame protocollen of extreem snelle controllers. Voor een microcontroller op 16 mHz kan de prescaler op 0 blijven. Overigens zal het sowieso makkelijk blijken te zijn om de prescaler op 0 te houden, dat voorkomt een hoop maskeren. TWBR is dan 72 voor 100 kBs of 12 voor 400 kBs. Het lijkt er overigens op dat bij twijfel de TWBR beter lager kan worden gesteld dan hoger. De slave kan namelijk de clock lijn laag houden als het hem te snel gaat, maar ik ken geen mechanismes die ervoor zorgen als het te langzaam gaat.

Een eerste kennismaking heb ik gehad met het Futurelec ATmega32 control board. Op dit board bevinden zich een klokchip en een geheugenchip (EEPROM) die zich beiden door middel van TWI laten lezen en schrijven. In een TWI communicatieproces is er altijd 1 master en 1 slave. De ATmega32 functioneert dan als master en bijvoorbeeld de klok functioneert dan als slave. De klok en EEPROM kunnen overigens enkel als slave functioneren. De ATmega32 kan beiden, die kan zowel als slave of als slave opereren. Op 1 bus kunnen zich overigens meerdere masters bevinden en ieder device mag behalve slave ook master zijn. Het protocol kan er zelfs mee uit de voeten indien er 2 masters tegelijkertijd aan het werk willen op de bus.

Meer algemeen bestaan er 4 modi waarin een TWI apparaat kan werken:

  • Master Send Data
  • Master Receive Data
  • Slave Send Data
  • Slave Receive Data

Verder bestaan er ook nog combinaties van verschillende modi. De zin daarvan is dat een master eerst de slave vertelt wat de master wil ontvangen en vervolgens omschakelt dmv een restart naar het ontvangen van de gewenste data. Dit is ook wat er op dit moment gebeurd om een DS1307 uit te lezen, waarbij het probleem is dat de data byte voor byte worden uitgelezen. Dit zou niet nodig hoeven zijn en moet dus nog worden verbeterd. Verder moeten er nog meer status situaties worden afgehandeld, die nu nog tot een fout of vastlopen leiden.

Als volgende stap wordt er een slave receive data geprogrammeerd op de ATmega8 van de LCD. Deze slave zet de data die hij received direct in het video SRAM. Zo kan er worden bekeken wat er nu gebeurd. De ATmega32 op het Futurlecboard zal als master gaan proberen data te schrijven.

 

DEVICE SCL SDA ADRES OPMERKING
ATmega8 PC5 PC4 0x10 niet open voor General Call
ATmega16 PC0 PC1 nvt niet open voor General Call
ATmega32 PC0 PC1 0x20 is master of slave
DS1307 SCL SDA 0xD0 enkel 100 kHz mogelijk
DS1621 SCL SDA 0x90-8 8 verschillenden mogelijk dmv pull-ups
24ls512 SCL SDA 0xA0-8 8 verschillenden mogelijk dmv pull-ups

De gebruikte programmas zijn aan de slave kant: STKmega8test8 en aan de master kant: FutTWImaster. Van beide kanten bestaan er overigens al verbeterde versies en daarom worden ze hier niet getoond.

Bus wordt te klein

Het zat er natuurlijk al aan te komen. Het aantal devices op 1 TWI bus wordt beperkt door de kabels en de capaciteit van 400F. Op dit moment zijn aangesloten op een Futurlec control board een ATmega32, DS1307, 24LS512 en via een kabel ook nog een ATmega8. Dit probleem ontstaat zodra ik probeer nog en device aan te sluiten. Ik heb een parallel stekkertje gemaakt en zodra hier een kabel in wordt gestoken trekt de bus het niet meer, onafhankelijk van het feit of de andere kant van die kabel is aangesloten. Dit betekent dat er een soort versterker zal moeten worden gebruikt. Phillips heeft AN255 over dit onderwerp. Mogelijke oplossingen zijn:

 

  • Kabels vervangen.
    Ik gebruik op dit moment 8 aderige, twisted pair kabel. Diverse plaatsen in de literatuur stellen dat dit zo ongeveer de slechtste kabel is die ik kon verzinnen. Kortom eerst de lange (1 m) kabel vervangen door 10-aderige rechte kabel (30 cm), waarbij de overbodige aders aan de aarde worden gelegd. Overigens bevat deze kabel 1 twisted pair (zwart/paars) die beiden worden geaard. Enkel deze kabel vervangen werkt iets beter, maar nog niet stabiel. Verder wordt de draad tussen de data en de klok leiding ook geaard. Verder lijkt het handig om op de chassisdelen de niet gebruikte pins te aarden en sowieso de data en klok niet in 1 paar te leggen. Dit blijkt op zich overigens niet voldoende om het probleem te verhelpen.
  • Phillips PCA9515 I?C bus repeater ($ 1,14).
    Hiervan kan er slechts 1 worden gebruikt per bus omdat hij speelt met de spanningen om in en/of uit te detecteren.
  • Phillips P82B715 I?C bus extender ($ 3,15).
    Hiervan kan er slechts 1 worden gebruikt per bus omdat hij speelt met de spanningen om in en/of uit te detecteren. Ook volgens een boek van Electuur is deze chip handig hiervoor. Dit boek verwijst hierbij naar AN444 en AN452 van Philips.

Indien de aarde ook wordt aangesloten blijkt de bus nog wel te werken. Als voorbeeld leest de STK500 met een ATmega16 de DS1307 uit. Dit werkt echter alleen indien de software van de Futurlec wordt gewist. Dat wil dus zeggen dat deze sofware niet correct is. Het kan eventueel ook nog de software van de ATmega8 zijnn op de LCD die als slaaf werkt.