zaterdag 7 maart 2020

Software - De list (3: TM1637)

Het dashboard van de Burton wordt volledig custom en digitaal. Geen analoge meters dus. Met de precieze lay-out en het design ben ik nog niet klaar, maar er komen in ieder geval grote 7-segmentdisplays in.


https://en.wikipedia.org/wiki/Seven-segment_display


En daar gaan we weer. Een 7-segmentdisplay zou zomaar - de naam verraad het al - zeven uitgangen van de microcontroller kunnen bezetten. Elk segment moet namelijk onafhankelijk aangestuurd kunnen worden. Om de snelheid van de Burton weer te kunnen geven zijn minimaal drie cijfers en dus drie van die 7-segmentdisplays nodig. Da's alleen al 21 uitgangen. Zoveel uitgangen heeft de ESP32 helemaal niet vrij, dus dat moet anders kunnen. En gelukkig kan dat ook anders. Met een I²C-bus I/O-expander bijvoorbeeld. Zou kunnen, maar in de praktijk worden vaak andere IC's gebruikt. Bijvoorbeeld de TM1637 van Titan Micro Electronics. Een speciaal IC waarmee tot zes 7-segmentdisplays aangestuurd kunnen worden.

TM1637, display driver.

Dit IC is nog tot meer in staat, maar daar maak ik geen gebruik van. Net als de I²C-bus wordt dit IC aangestuurd met een klok- en een datasignaal. Ook het communicatieprotocol lijkt erg veel op het I²C-protocol, met het verschil dat de TM1637 niet geadresseerd hoeft te worden. Je kunt maar één zo'n IC aanspreken.

Bij de NeoPixels uit het vorige bericht was de grootste uitdaging de timing van de bits die verstuurd moeten worden. Bij deze TM1637 is de timing veel minder kritisch. Zolang het klok- en datasignaal maar netjes op elkaar afgestemd zijn. In de figuur hieronder wordt dit weergegeven:


Timing van de TM1637

Elke bericht naar de TM1637 begint altijd met een start-conditie en eindigt altijd met een stop-conditie. Bij de start wordt het datalijntje (DIO) laag gemaakt terwijl de kloklijn (CLK) hoog is. Bij de stop wordt de DIO juist hoog gemaakt terwijl de CLK hoog is. Dit zijn de enige twee condities waarbij de DIO van niveau wijzigt terwijl CLK hoog is. De TM1637 kan hierdoor deze twee belangrijke condities herkennen.

Een commando of data (tussen start- en stop-conditie) wordt verstuurd in een groepje van acht bits. Ná elk zo'n byte volgt nog een Acknowledge (ACK) waarbij de TM1637 de kans krijgt om het ontvangen byte te bevestigen. De acht bits worden door de TM1637 één voor één 'ingeklokt' op het moment dat het kloksignaal van laag naar hoog beweegt. Easy peasy.

In de software worden bovenstaande condities op de volgende manier geprogrammeerd (voorbeeld van de start-conditie):

TM1637 Start-conditie

Omdat de absolute timing niet zo kritisch is kan ik gewoon gebruik maken van de eenvoudige pauzefunctie vTaskDelay(1). Hiermee wordt steeds 1 tick, ofwel 10 ms gewacht tussen de bitwisselingen. Een eeuwigheid als je het vergelijkt met de timing van de eerder genoemde NeoPixels. Een prima oplossing voor dit doeleind. Bovendien krijgen andere taken gedurende deze pauzes de tijd om hun ding te doen. Uiteindelijk gebruikt dit protocol bijzonder weinig processortijd.

Voordat de 7-segmentdisplays aangestuurd kunnen worden moet de TM1637 eerst geconfigureerd worden. Hierbij wordt een keuze gemaakt of de TM1637 gebruikt wordt voor het aansturen van een display of het uitlezen van een keyboard (het K-bit) en of de (maximaal) zes 7-segmentdisplays afzonderlijk of automatisch ná elkaar geadresseerd worden (het F-bit).

Bit:  7 6 5 4 3 2 1 0
Data: 0 1 0 0 0 F K 0

In mijn geval wordt zowel het K-bit (bit 1) als het F-bit (bit 2) laag gehouden. Dus:

Bit:  7 6 5 4 3 2 1 0
Data: 0 1 0 0 0 0 0 0

In de software ziet dit er als volgt uit:

TM1637 Configuratiebericht


Daarna wordt het display aangezet met een bepaalde helderheid:

Bit:  7 6 5 4 3 2 1 0
Data: 1 0 0 0 S A B C

Het S-bit zet het display aan. De drie bits A, B en C bepalen de helderheid van het display. De helderheid (brightness) loopt van 000 naar 111 en heeft dus acht verschillende standen. In de software gebruik ik hiervoor een eenvoudige functie:


TM1637 Brightness

Nu de TM1637 geconfigureerd is, kunnen de 7-segmentdisplays aangestuurd worden. De TM1637 wil eerst weten welke van de (maximaal) zes displays gewijzigd moet worden. We starten altijd bij display 0. Het adres wordt na het eerste cijfer automatisch opgehoogd, dat is met het F-bit (zie hierboven) zo geconfigureerd. In geval van zes cijfers worden achtereenvolgend de volgende commando's naar de TM1637 gestuurd:

  1. Start
  2. Adres ( = 0 )
  3. Ackn
  4. Cijfer 1
  5. Ackn
  6. Cijfer 2
  7. Ackn
  8. Cijfer 3
  9. Ackn
  10. Cijfer 4
  11. Ackn
  12. Cijfer 5
  13. Ackn
  14. Cijfer 6
  15. Ackn
  16. Stop

Dat is alles. Hoewel... De cijfers bestaan uit 7 segmenten. Bij elk cijfer moet een andere combinatie van segmenten oplichten. Het cijfer moet hiervoor omgezet worden naar een bitpatroon. Hiervoor is de software voorzien van een constant array met tien posities:


Van decimaal naar 7-segment

De bitpatronen weerspiegelen de op te lichten segmenten. De positie in het array bepaalt het cijfer dat gepresenteerd moet worden. Bij het achtste element (overeenkomstig het cijfer 8) is goed te zien dat alle zeven segmenten op moeten lichten.

Alle puzzelstukje bij elkaar ziet de functie om een getal (number) met al zijn cijfers (digits) te presenteren er als volgt uit:


Getal presenteren op het display


Met deze derde 'list' is het gelukt om maximaal zes cijfers op een display te tonen en hier maar twee digitale uitgangen van de microcontroller voor te gebruiken. Samen met list 1 en list 2 ben ik nu in staat om behoorlijk wat knoppen en lampjes aan te sluiten. Maar ik wil nog meer... Binnenkort list nummer vier!

vrijdag 6 maart 2020

Software - De list (2: NeoPixels)

Een tweede list voor het minieme aantal ingangen en uitgangen van de ESP32 wordt bedacht voor de aansturing van alle indicatie- en storingslampjes. De dashboardlampjes zouden aangestuurd kunnen worden met de I/O-expanders uit het vorige bericht. Maar dat zou te gemakkelijk zijn ;-). Het idee is om hiervoor NeoPixels te gaan gebruiken.


https://www.adafruit.com/


NeoPixels zijn RGB-leds die via één digitale uitgang van de ESP32 aan te sturen zijn. Over die digitale uitgang wordt een patroon van bits naar de NeoPixel gestuurd. Precies 24 bits; voor elke kleur - rood, groen en blauw - acht bits. Met die acht bits wordt de intensiteit van elke kleur ingesteld (0..255) en kunnen dus 256 x 256 x 256 = ruim 16 miljoen kleuren gekozen worden. Mooi, één digitale uitgang voor 16 miljoen kleuren! Maar het wordt nog mooier, want NeoPixels kunnen in een string achter elkaar geschakeld worden; en ook dan is er nog steeds maar één digitale uitgang nodig. Zijn er twee NeoPixels achter elkaar geschakeld, dan worden niet 24, maar 48 bits naar buiten gestuurd. De eerste 24 bits worden door de eerste NeoPixel 'gebruikt', de resterende bits worden doorgestuurd naar de tweede NeoPixel. Zo kunnen er honderden achter elkaar geschakeld worden waarbij elke NeoPixel telkens 24 bits van het treintje bits afsnoept en de rest doorgeeft. Ik wil (o.a.) gebruik maken van een stick met acht NeoPixels:


https://www.adafruit.com/


Voldoende voor alle indicatielampjes en nog voor andere creatieve uitingen. Zo kan zo'n balkje ledjes ook gebruikt worden ter indicatie van het toerental.

Tot nu toe klinkt het allemaal positief. Maar er zit een addertje onder het gras. De NeoPixels zijn behoorlijk kritisch als het gaat om de timing van de pulsjes die ontvangen worden. Dit komt omdat er maar één pin gebruikt wordt voor het bitpatroon en daarnaast niet net als bij I²C-bus een separaat kloksignaal aanwezig is. Een digitale 0 wordt gevormd door de uitgang van de ESP32 eerst gedurende 300 ns (jawel nanoseconde) hoog te maken en vervolgens 800 ns laag. Een digitale 1 wordt herkend als de uitgang 800 ns hoog en 325 ns laag wordt gemaakt.


WS2812-timing

Als de uitgang enkele tientallen microseconden laag blijft (Treset), dan worden de nieuw ontvangen RGB-waarden van alle NeoPixels gebruikt om gelijktijdig alle leds aan te sturen. De leds houden die kleur totdat er een nieuw treintje met kleurenbits is langsgekomen. Omdat de tijdwaarden zo kort zijn, gaat dit allemaal razendsnel. Dit protocol is vastgelegd in de WS2812-specificatie. Er zijn inmiddels enkele verschillende versies van dit protocol waarbij vooral de timing anders is. En omdat juist die timing een beetje kritisch is, is het belangrijk om te weten welke versie van de WS2812-specificatie bij de gebruikte NeoPixels hoort.

De ESP32 werkt - zoals in het vorige bericht vermeld - met een multitasking besturingssysteem genaamd FreeRTOS. De verschillende taken die hierin draaien moeten zo nu en dan wat tijd gunnen aan de andere taken. Normaliter gebeurt dit door een taak even zogenaamd te pauzeren. In een microcontroller zónder multitasking besturingssysteem (bijvoorbeeld een Arduino UNO) zal een delay-functie de processor eventjes bezig houden (blocking) en vervolgens weer met het programma verder gaan. In een multitasking besturingssysteem is dit uit den boze. Het pauzeren van een taak zal de processor niet blokkeren, maar juist de tijd geven wat aandacht aan een andere taak te geven. In een FreeRTOS-taak wordt hiervoor de functie vTaskDelay() gebruikt. Deze functie accepteert een aantal ticks als argument. Eén tick is de kleinste tijdsduur die te gebruiken is om een taak te pauzeren. De lengte van een tick is afhankelijk van de snelheid waarmee FreeRTOS tussen taken schakelt. En dat doet 'hij' standaard 100 keer per seconde. Zo'n tick is hierdoor ongeveer 10 ms. Je ziet direct dat dit véél te lang is om de WS2812-timing voor elkaar te krijgen. Dit moet dus op een andere manier aangepakt worden.

Bij de I²C-bus hadden we dit probleem niet, omdat de timing en afhandeling van die bus in de hardware van de ESP32 wordt uitgevoerd. Voor het WS2812-protocol is echter geen hardware in de ESP32 aanwezig. Of misschien toch wel...

Zoekende op internet en in de documentatie van Espressif (de maker van de ESP32) kwam ik de Remote Control-hardware (RMT) tegen. Net als de CAN-bus en de I²C-bus een stukje hardware in de ESP32 waarmee het bitpatroon van een afstandsbediening gerealiseerd kan worden. De meeste afstandsbedieningen werken met een infrarood-led. Deze led zendt afhankelijk van de ingedrukte knop op de afstandsbediening (en het merk) een ander treintje bitjes naar de ontvanger (bijv. de tv). Ook dit bitpatroon volgt een strikt tijdschema.

Een klein deel van het RMT-blokschema (Espressif)

De RMT-hardware is net als de CAN-bus en de I²C-hardware vooraf te voorzien van een reeks commando's - hier een serie getalletjes waarmee de tijd van het hoog en laag worden van de digitale uitgang bepaald wordt. Vervolgens krijgt de RMT-hardware vanuit de software de opdracht zijn ding te doen. Daar is de software dan niet meer bij betrokken. De precieze timing wordt volledig afgehandeld door de RMT-hardware zelf. Deze heeft een tijdresolutie overeenkomstig de interne klok van de microcontroller. Die draait op 80 MHz, wat overeenkomt met een tijdresolutie van 12.5 ns. Aangezien de timing van de WS2812 in de grootteorde van 100 ns ligt, is dit nauwkeurig genoeg.

Timing-data

De timing-data wordt aangeboden in een array van 32-bits woorden. Die 32-bits wordt gevuld met twee keer een tijdsduur van 15 bits en de resterende twee bitjes om het niveau van het signaal aan te geven. Als ik het niet zou weten, zou ik denken dat het bedacht is voor het WS2812-protocol. Voor elk bit heb je in dit protocol namelijk een Hoog- en een Laag-tijdsduur (zie hierboven) nodig. Om één NeoPixel aan te sturen zijn precies 24 (3 x 8 voor R, G en B) bits nodig; voor de RMT-hardware komt dit neer op een array van 24 x 32-bits woorden. Voor een stick van acht NeoPixels komt dit uit op 8 x 24 x 32 bits. Da's ruim 6000 bits. Voor een doorsnee computer een druppel op een gloeiende plaat, voor een microcontroller best wel wat geheugen. Gelukkig heeft de ESP32 aardig wat geheugen aan boord, dus dat levert hier geen beperkingen op.

Naast de taken die eerder beschreven zijn (CAN-bus en I²C-bus) is er nu weer een belangrijke taak bijgekomen. Het aansturen van NeoPixels via de RMT-hardware. Drie onafhankelijke taken die netjes door FreeRTOS afgehandeld worden. Er komen er nog meer...

zondag 1 maart 2020

Software - De list (1: I²C)

In het vorige bericht werd duidelijk dat het aantal vrije in- en uitgangen (19 stuks) van de microcontroller (ESP32) niet toereikend is voor alle dashboardfuncties van de Burton. Zeker niet omdat ik méér mogelijkheden wil introduceren dan dat er standaard in de eend zitten. Dit vraagt om een list, zou Burton-bouwer Anton Folkeringa zeggen. Zoek op het internet naar "i/o expander" en je komt al snel de PCF8574 van NXP (voorheen Philips) tegen.

https://pmdway.com/products/pcf8574-8-bit-i2c-i-o-expander-dip-5-pack

Dit is een relatief eenvoudig IC waarmee het aantal ingangen en/of uitgangen van de microcontroller uitgebreid kan worden. De PCF8574 wordt met de microcontroller verbonden via een tweedraads I²C-bus (Inter-IC-bus). De ESP32 heeft standaard twee I²C-bussen aan boord, dus daar kunnen we er wel eentje van gebruiken. Van de 19 vrije in- en uitgangen worden er twee gebruikt voor deze tweedraads bus. Eentje voor de klok (SCL) en eentje voor de data (SDA). Eén PCF8574 bevat acht digitale poorten. Ze kunnen als ingang of als uitgang gebruikt worden. De I²C-bus is - zoals de naam al doet vermoeden - een bussysteem waar - net als bij de CAN-bus - meerdere apparaten op aangesloten kunnen worden. Anders dan bij de CAN-bus gaat het bij de I²C-bus echter over het verbinden van IC's en hele korte afstanden, meestal op dezelfde printplaat. Er kunnen dus ook meerdere PCF8574-IC's aan dezelfde bus gekoppeld worden. Drie van de pinnen van het IC worden gebruikt om een digitaal adres in te stellen, van binair 000 tot 111 zijn dit acht verschillende adressen. Uiteindelijk kunnen er van hetzelfde IC dus acht verbonden worden met de microcontroller, resulterend in 8 x 8 = 64 in- of uitgangen. En alsof dat nog niet genoeg is, is er nog de PCF8574A (zie foto hierboven) waarmee nog eens acht IC's aan de bus toe te voegen zijn. Méér dan voldoende dus!

Op internet zijn mooie compacte modules te vinden met handige pinnen voor het aansluiten van de acht in- of uitgangen, de twee lijnen van de I²C-bus, de voeding en het instellen van het 3-bits-adres.

Twee varianten van een PCF8574-module

Voor de ESP32 is een handige bibliotheek beschikbaar waarmee de I²C-hardware van de microcontroller aangestuurd kan worden. De berichten voor op de bus worden eerst voorbereid en netjes op een rij in het geheugen gezet, waarna de I²C-hardware de opdracht krijgt om onafhankelijk van de afloop van het programma de I²C-communicatie af te handelen. De timing op de bus wordt door de hardware van de controller geregeld en is dus niet afhankelijk van de software. Da's mooi, want dan hoeven we ons daar geen zorgen om te maken.


https://www.freertos.org/


De ESP32 bevat twee processor-cores en wordt standaard voorzien van het FreeRTOS realtime operating system. Dat klinkt ingewikkeld, maar is het juist niet. FreeRTOS geeft namelijk de mogelijkheid om met parallel draaiende taken te werken (Multi Tasking). Erg handig als je gelijktijdig meerdere taken af moet handelen. Een van de taken is natuurlijk de communicatie over de CAN-bus. Nu hebben we er een belangrijke taak bij: de afhandeling van de I²C-communicatie. En wacht maar, er komen nog aardig wat taken bij...

dinsdag 28 januari 2020

Software - Who am I

Waarom één microcontroller gebruiken als het er ook méér kunnen zijn. Da's natuurlijk geen doel op zich, maar wel een resultaat van de gemaakte keuzes. Elke node op de CAN-bus wordt gevormd door een gelijke DevKit voorzien van een microcontroller van het type ESP32:

ESP32 DevKit

De pinnen van de node worden gebruikt voor het aansluiten van Inputs en Outputs (I/O). Eenvoudige I/O van het type GPIO (General Purpose Inputs/Outputs), maar ook I/O voor de CAN-bus en pinnen voor de stroomvoorziening. Veel van de pinnen hebben speciale functies die deels te configureren zijn, maar ook deels ongewijzigd moeten blijven. Nader onderzoek resulteert in het volgende schema:

Fysieke I/O

Van de 30 pinnen blijven er relatief weinig over om vrij te gebruiken. In de kolommen met de naam Functie staat <spare> vermeld als de pin vrij is. Enkele pinnen hebben al een vaste functie gekregen die voor élke node gelijk is:
  • PIN34, PIN35, PIN36 en PIN39 zijn pinnen die alleen als Input te gebruiken zijn. Drie van deze pinnen worden ingezet om de node te identificeren. Hierover zometeen meer.
  • PIN04, PIN05, PIN12 en PIN15 zijn zogenaamde strapping-IO's en hebben tijdens het opstarten een speciale functie. Er wordt geadviseerd om ze met rust te laten (floating).
  • GND (2x), VIN en 3V3 dienen voor de voeding.
  • PIN01 en PIN03 (resp. TXD0 en RXD0) zijn in gebruik voor het programmeren van de node.
  • PIN16 en PIN17 worden ingezet voor de koppeling met de CAN-bus.
  • PIN02 is intern verbonden met de blauwe LED op de DevKit. Deze zal gebruikt worden om activiteit op de CAN-bus te signaleren.
Uiteindelijk blijven er dertien pinnen over om ingezet te worden voor diverse functies zoals het uitlezen van schakelaars of het aansturen van lampen. Dat lijkt best nog veel, maar zeker bij het dashboard red je het daar niet (zomaar) mee. Denk maar eens aan alle schakelaars en indicatielampjes en je gaat al snel over de dertien heen. Dat betekent dat een list bedacht moet worden of dat er een node bijgeplaatst moet worden. In een later bericht meer over dit dilemma.

Hierboven werden al de drie identificatiepinnen (PIN34, PIN36 en PIN39) genoemd. Die worden gebruikt om de node te identificeren. Alle nodes zijn namelijk gelijk. Niet alleen hardwarematig, maar ook softwarematig wil ik ze gelijk houden. Alle nodes krijgen dus dezelfde software, maar moeten wel verschillende functies uitvoeren. Bij het opstarten worden de drie pinnen uitgelezen en op basis hiervan worden sommige functies in de software wel of niet geactiveerd. De drie pinnen kunnen elk aan 0 volt of 3.3 volt gekoppeld worden en zo ontstaan er acht verschillende identificatiecodes (binair: 000, 001, 010, 011, 100, 101, 110 en 111). Dat betekent dus dat er op deze manier maximaal acht nodes mogelijk zijn. Lijkt me genoeg voor een Burton.

Voor de liefhebbers een stukje C-code waarmee de drie identificatiepinnen uitgelezen worden:

Functie "whoAmI".

De software wordt ontwikkeld in Visual Studio Code met de plug-in PlatformIO. Een prachtige combinatie waarmee vrij eenvoudig software voor diverse microcontrollers ontwikkeld kan worden. Voor diegene die al eens met de Arduino IDE gewerkt hebben, stap gerust over op PlatformIO. Daar ga je geen spijt van krijgen. Om de softwarefuncties te testen zijn twee nodes op een breadboard geplaatst. Hieronder een testopstelling met de verlichtingsschakelaar aan de ene node en de lampen (hier blauwe LED's) aan de andere node. Lijkt al snel een onoverzichtelijke spaghetti op zo'n breadboard.


Testopstelling. Het geel/oranje kabeltje is de CAN-bus.

Inmiddels is er al heel wat meer software geschreven waarover nog wel wat berichtjes gaan volgen. De basisopzet is gereed maar het is nog lang niet klaar. Morgen komt - als het goed is - de hoge voorruit binnen. Fijn, want die heeft wel even op zich laten wachten.

donderdag 9 januari 2020

CAN-bus - Deel 2

Mijn enthousiasme voor de CAN-bus heb ik in het vorige blogbericht niet onder stoelen of banken geschoven. De conclusie is dat het hier om een efficiënte en zeer betrouwbare communicatieverbinding gaat. Maar hoe gaat deze bus ingezet worden in mijn Burton. Hiervoor zijn in ieder geval twee belangrijke vragen te beantwoorden:
  1. Wat voor berichten ga ik versturen?
  2. Wat voor apparatuur ga ik toepassen?
De eerste vraag heeft natuurlijk alles te maken met de onderdelen binnen de Burton die via de CAN-bus aangestuurd gaan worden. In eerste instantie denk ik dan aan de verlichting en de bediening hiervan. Er zijn dus CAN-berichten nodig om alle lampen aan en uit te schakelen en hier misschien nog wel wat andere dingen mee uit te halen (spoiler alert).

Een CAN-bericht bevat naast de zaken uitgelegd in het vorige blogbericht o.a. nog een datablok. Hierin kan maximaal 8 bytes aan data verstuurd worden. Hoeveel data-bytes in het uiteindelijke bericht zitten wordt bepaald door de controle-bits. Met vier van de vijf controle-bits (het vijfde bit wordt niet gebruikt) wordt de lengte van het datablok (in aantal bytes) bepaald.


Het volledig standaard CAN-bericht op schaal (klik op het plaatje om het te vergroten).

Wat duidelijk wordt is dat het datablok het grootste deel van het CAN-bericht uitmaakt. Maar zoals in het plaatje aangegeven wordt, kan het datablok ook lengte 0 hebben. Da's fijn want om lampen aan en uit te zetten is niet zoveel data nodig. Maar hoe gebruiken autofabrikanten de CAN-berichten? Er zijn aardig wat pogingen ondernomen om de CAN-berichten van diverse automerken te reverse engineeren, omdat die fabrikanten hier niet mee te koop lopen. Wat mij daarbij steeds weer opvalt is dat er niet zo heel veel structuur zit in die berichten. Vaak worden maar relatief weinig berichten (lees: identificatiecodes) ingezet, maar wel met grote datablokken. Dit terwijl er méér dan 2000 identificatiecodes mogelijk zijn. In die datablokken worden veel bits gebruikt om zaken aan en uit te zetten of te monitoren. Zou ik dezelfde strategie volgen, dan heb ik met slechts één CAN-bericht de beschikking over 8 x 8 = 64 bits; méér dan genoeg bits om alle lampen van een Burton aan en uit te schakelen.

Ik moet dus een keuze maken: weinig berichten met relatief veel data, of relatief veel berichten met weinig data. Voorbeeld: het aansturen van het groot licht. Ik kan hiervoor één berichtidentificatie reserveren. Laten we zeggen berichtnummer 100. Dit bericht krijgt één databyte waarvan het eerste bit gebruikt wordt om de lamp aan (bit = 1) of uit (bit = 0) te schakelen. De alternatieve opzet zou zijn om gebruik te maken van twéé berichtnummers - 100 en 101 - beide zonder databytes. Berichtnummer 100 schakelt het groot licht aan en berichtnummer 101 schakelt het groot licht uit. Dat is toch om het even zou je zeggen, en dat is natuurlijk ook zo. Ik neig er trouwens naar om voor de alternatieve opzet te kiezen. Elke 'discrete opdracht' (lees: aan/uit) krijgt zijn eigen berichtnummer zonder datablok. Alleen als iets analoog aangestuurd of uitgelezen wordt, zal het bericht ook één of meerdere bytes bevatten voor de gewenste of actuele waarde.

Nu deze principiële keuze gemaakt is kan ik een lijst met berichtindentificatienummers (3 x woordwaarde) en bijbehorende functies gaan maken, rekening houdend met het feit dat lage nummers voorrang hebben op hoge nummers. Spreadsheetje vullen dus:

Eerste berichten in de lijst.

Het lijstje hierboven is nog heel prematuur. De 16 laagste berichtnummers heb ik nog even open gelaten. Verder zijn er nog wat nummers die niet gebruikt mogen worden:
  • 2032..2047: beginnen binair allemaal met zeven enen (111 1111 xxxx). Heeft vast iets te maken met de zeven recessieve stopbits.
  • 2015..2031: OBD (On Board Diagnostics) requests en responses. Heb ik niet echt mee te maken, maar toch maar vrij houden.
Blijven er nog ruim 2000 berichtnummers over. Méééér dan genoeg.


De tweede vraag (wat voor apparatuur ga ik toepassen) sluit wel een beetje aan op het vorige. Een van de hoofddoelen van CAN-bus is het reduceren van de hoeveelheid koperdraad in de auto. Het lijkt erop dat vooral de verlichting aangestuurd gaat worden en die zit zo'n beetje op elke hoek van de auto. Verder zitten er veel knoppen en lampjes e.d. bij het dashboard. Een mooie centrale plek. Dus op de volgende locaties komen CAN-nodes:
  • Vóórin, onder de motorkap. Misschien eentje rechts en eentje links, of is dat overkill?
  • Achterin, in de achterbak. Misschien ook wel eentje rechts en eentje links.
  • Centraal, achter het dashboard.
  • Mogelijk nog eentje bij het schutbord, onder de motorkap.
Maximaal zes nodes op de bus. En dan een mooi kabeltje daartussen. Bijvoorbeeld de speciale buskabel van Lapp:

Buskabel, maar dan tweedraads.


Doorsnede van de buskabel.

En dan de nodes zelf. Die spreken natuurlijk het meest tot de verbeelding. Een microcontroller is hier op zijn plek. Liefst eentje met een CAN-interface aan boord. Zo is er de PIC18F26K83 van Microchip, een 8-bits controller. Of - aan de andere kant van het spectrum - de ESP32 van Espressif. Zoals de naam al doet vermoeden, een 32-bits controller.

Een van de ESP32-modules.

Deze module wordt aangeboden in veel verschillende varianten en is voor de zelfbouw-hobbyist beschikbaar op een ontwikkelbord. De ESP32 heeft aardig wat mogelijkheden onder de motorkap. Zo is deze microcontroller standaard voorzien van bijvoorbeeld wifi, bluetooth, CAN-bus, I2C, een groot aantal GPIO's en nog enkele interfaces. Het is een dual-core processor met een real-time besturingssyteem (FreeRTOS) aan boord. Multi threaded programmeren wordt zo wel heel 'gemakkelijk'. Hoewel ook hier weer het woord overkill op zijn plaats is, wordt dit 'm. In de volgende variant:

ESP32 DevKit

Zo, de hoofdonderdelen van het CAN-bus-systeem zijn bepaald. In volgende blogberichten komen nog de software en bijbehorende tools aan bod. En misschien ook nog wel wat over de bouw van de Burton zelf, want die is nog lang niet klaar ;-).

dinsdag 7 januari 2020

CAN-bus - Deel 1

Een tijdje terug heb ik mezelf voorgenomen om de Burton te gaan voorzien van een CAN-bus. Niet omdat het moet, maar omdat het can dus... Zo, de eerste foute woordgrap is alweer gemaakt dit nieuwe jaar.

Nee, niet zo'n bus (bron: www.volkswagen.nl).

CAN staat voor Controller Area Network en is door Bosch ontwikkeld om elektronische systemen in een voertuig aan elkaar te koppelen en de hoeveelheid bedrading te verminderen. CAN maakt gebruik van een tweedraads bus-systeem en is als eerste door Mercedes gebruikt in een productie-auto. In de automobielindustrie is de CAN-bus niet meer weg te denken, maar inmiddels heeft de CAN-bus zich ook bewezen in de industriële automatisering, medische apparatuur, elektrische fietsen en volgens een enkele website ook in het elektronische schakelsysteem van Shimano.

Een CAN-bus is vooral nuttig als de complexiteit van de elektronische systemen toeneemt. Bij een Burton is dat toch niet echt (euh, echt niet) het geval hoor ik je denken... En dat is natuurlijk ook zo. Voor de eenvoudige systemen in een Burton is een CAN-bus behoorlijk overkill. Maar omdat de Burton voor mij het ultieme over-the-top hobbyproject is, kan de elektronica natuurlijk niet achter blijven. Dat moet iets speciaals worden. Bovendien: adel verplicht!

Een auto is voor elektronica zo'n beetje de meest vuile omgeving die je je kunt voorstellen. Dus het wordt een hele uitdaging om hier op een goede manier mee om te gaan. De betrouwbaarheid van het geheel moet natuurlijk hoog worden. Iets waar in het ontwerp vanaf het begin rekening gehouden moet worden. De CAN-bus heeft het in zich om zich in zo'n vuile omgeving goed staande te houden. Op verschillende manieren wordt de foutgevoeligheid van het systeem gereduceerd. Enkele elektrische eigenschappen waardoor storingen worden voorkomen:
  • De bus bestaat uit twee draden - CAN-H en CAN-L. De digitale nullen en enen van het protocol worden vertaald naar een spanningsverschil tussen de twee draden. Een storingspuls die opgepikt wordt door de ene draad, wordt naar alle waarschijnlijkheid óók opgepikt door de tweede draad. Het spanningsverschil tussen de draden blijft nu gelijk hetgeen een storing op de bus voorkomt.
  • De twee draden worden getwist (twisted-pair) waardoor magnetische invloeden (en de resulterende stroompjes) zichzelf uitdoven.
  • De bus wordt aan twee zijden afgesloten met een weerstand (afsluitweerstand) van 120 ohm, passend bij de impedantie van de (juist gekozen!) kabel. De kabel wordt nu schijnbaar oneindig lang wat reflecties van signalen aan het eind van de kabel voorkomt.

Schematische voorstelling CAN-bus.


Niet alleen elektrisch worden storingen voorkomen, ook het protocol zelf heeft enkele mooie foutcontroles en foutreducerende eigenschappen aan boord. Het CAN-busprotocol is trouwens anders dan heel veel andere communicatieprotocollen niet gebaseerd op berichtverkeer tussen een specifieke zender en een geadresseerde ontvanger. Nee, op de CAN-bus heeft een node géén adres. Elke node kan in principe berichten op de bus plaatsen. Alle node's luisteren naar de berichten die langs komen en doen hier iets mee als zij ze interessant vinden. Maar wat nu als twee nodes tegelijkertijd een bericht gaan plaatsen? Dan gebeurt er iets wat in mijn ogen het meest geniale is van het hele protocol. Er wordt een prioriteitsgevecht gehouden. De node die dit gevecht wint, mag zijn bericht afmaken; de node die het gevecht verliest moet even zijn mond houden.

Om te begrijpen hoe dit gevecht in zijn werk gaat moet je weten dat elk bericht een identificatiecode heeft. Een getal van 11 bits *) waarmee het bericht geïdentificeerd wordt. De node die het bericht met getalsmatig de laagste identificatiecode op de bus probeert te zetten wint het gevecht van een node die een bericht met een hogere identificatiecode probeert te versturen. Maar dan zonder dat ze beide de identificatiecode eerst in zijn geheel kenbaar maken. Hoe dat kan heeft te maken met de manier waarop bits (nullen en enen) op de bus geplaatst worden:
  • Als een node een 1 (één) wil plaatsen laat hij de CAN-H en CAN-L als het waren vrij zweven. De spanning op de twee draden zal dan ergens in het midden tussen de 0 volt en 5 volt gaan hangen. Op zowel de CAN-H- als de CAN-L-draad staat dan een ongeveer gelijke spanning. De spanning tussen CAN-H en CAN-L is dan nagenoeg 0 volt.
  • Als een node een 0 (nul) wil plaatsen zal hij de CAN-H (via een weerstand) aan de 5 volt, en de CAN-L (via een weerstand) aan de 0 volt hangen. Er ontstaat een spanning tussen de CAN-L- en CAN-H-draad van ongeveer 2 volt.

Dominante en recessieve bits op de CAN-bus.


Stel dat twee CAN-nodes (node A en node B) gelijktijdig beginnen met het plaatsen van een eigen bericht op de bus. Dan zijn er in principe bij elke achtereenvolgend bit vier mogelijkheden:
  • Als node A een 0 plaatst en node B een 0, dan zal er een resulterende 0 op de bus verschijnen. 
  • Als node A een 1 plaatst en node B een 1, dan zal dit resulteren in een 1 op de bus. Tot dusver niets vreemds.
  • Als node A een 1 plaatst en node B een 0, dan gebeurt er iets anders. Node A zal met de 1 de bus vrij laten zweven, maar node B trekt met de 0 de twee buslijnen uit elkaar. Resulterend in een 0 op de bus. De 0 overheerst over de 1. In mooie woorden: de 0 van node B is dominant, de 1 van node A is recessief
  • Als node A een 0 plaatst en node B een 1, gebeurt precies het omgekeerde.
Als beide nodes dus gelijktijdig een eigen bericht met nullen en enen op de bus proberen te plaatsen, zal er een moment aanbreken waarbij het bericht van één van beide nodes niet meer gelijk zal zijn aan wat er daadwerkelijk op de bus verschijnt. Nu is het zo dat een node elk bit dat er op de bus verschijnt ook gelijktijdig terugleest. En nu komt het geniale: op het moment dat een node ziet dat het bit op de bus anders is dan hij zelf wilde plaatsen, dan stopt die node met 'praten' en heeft als het ware het gevecht verloren. De winnende node gaat gewoon verder met het plaatsen van de rest van zijn bericht op de bus. En het mooie is, er wordt geen moment tijd verloren.

Samenvattend:
  • Er zal altijd maar één node op een bepaald moment een volledig bericht op de bus plaatsen.
  • Berichten met een lage identificatiecode hebben voorrang op berichten met een hogere identificatiecode (een 0 is namelijk dominant t.o.v. een 1).
Omdat er geen geldende afspraken zijn vastgelegd over de identificatiecodes (elk automerk heeft zo zijn eigen indeling), kun je zelf een indeling maken. Hierover in een volgend blogbericht meer. Een CAN-bericht bestaat trouwens uit méér dan alleen een identificatiecode. Zo bevat het bericht ook een CRC (Cyclic Redundancy Checksum) van 15 bits (plus één afsluitend bit) die door de zender berekend wordt op basis van alle voorgaande bits in het bericht. De ontvangende node doet hetzelfde en vergelijkt zijn resultaat met de CRC die berekend is door de zender. Zijn ze gelijk, dan wordt het bericht geaccepteerd. Is er ergens een bit veranderd tijdens het versturen, dan zullen de CRC's van zender en ontvanger niet gelijk zijn en wordt het bericht niet geaccepteerd door de ontvanger.

Aansluitend aan de CRC zet de zender een 1 op de bus. Het acknowledge-bit. Als er een ontvangende node aanwezig is die het bericht tot en met de CRC correct heeft ontvangen, zal deze het recessieve bit naar 0 veranderen. Zo vertelt hij de zendende node dat het bericht (in ieder geval bij één node) succesvol is gearriveerd. Blijft het acknowledge-bit 1, dan weet de zendende node dat het bericht herhaald moet worden. Samen met nog wat methodes voor het afhandelen van error's maakt dit van CAN-bus een van de meest betrouwbare en meest elegante bussystemen op de markt.

Een volledig CAN-bericht bevat nog wat overige bits en bytes. In een volgend blogbericht ga ik in op het gebruik van de CAN-berichten voor de Burton. Dan komen de control bits en de data bytes aan bod.

Een volledig standaard CAN-bericht.



*) De specificatie CAN 2.0 Part A maakt gebruik van het standaard frame met een 11-bits identificatiecode. Part B van de specificatie maakt gebruik van het extended frame met een 29-bits identificatiecode.

zondag 5 januari 2020

Lichtschakelaar

Het dashboard van de Burton is waarschijnlijk voor veel bouwers het onderwerp waar de meeste creativiteit bij komt kijken. Klokjes, schakelaars, lampjes, elektronica, enz... Klassieke of moderne look? En heb je al gekozen voor de onderdelen, dan moet er nog een keuze gemaakt worden voor de indeling. Misschien moet het dashboard wel houten of aluminium elementen gaan bevatten. Allemaal keuzes die door mij ook nog niet (definitief) gemaakt zijn. Ik zit er wel aan te denken om enkele elementen uit de Eend te gaan hergebruiken.

Zo wil ik ook graag op een-of-andere manier de lichtschakelaar gaan inzetten. Een multifunctioneel apparaat waar alle (standaard) verlichting én de claxon mee bediend wordt. Mooi, want ik wil eigenlijk niet zo heel veel knoppen op het dashboard. De schakelaar ziet er een beetje vermoeid uit, dus die heeft een opfrisbeurt nodig.


De lichtschakelaar.


De schakelaar is vrij gemakkelijk uit elkaar te halen. Wel mooi hoe de schakelaar drie bewegingen combineert:
  1. Draaibeweging: 0 (uit), V (Ville, binnen bebouwde kom) en R (Route, buiten bebouwde kom).
  2. Omhoog en omlaag (of naar voren en naar achteren): wisselen tussen stadslicht en dimlicht (in stand V) of wisselen tussen groot licht en dimlicht (in stand R).
  3. Op de knop drukken: claxon.

Enkele boutjes missen nog op de foto...

Het tonnetje linksonder op bovenstaande foto bevat een patroon van geleidende strookjes/vlakjes waarmee de boordspanning van 12 volt geschakeld wordt. Ik ben van mening dat de schakelaar niet juist in elkaar zit. Het ringetje links van het tonnetje zit op de verkeerde plek. Lees vooral verder...

De contacten.


De twee contacten links op de foto schakelen de claxon. Het middelste contact zet 12 volt op het tonnetje. De drie contacten rechts schakelen het stadslicht, het dimlicht en het groot licht.


Opgefrist.


Het stangetje heb ik in de accuboormachine geklemd en met een schuurpapiertje en daarna met wat polijstmiddel bewerkt. Ziet er weer glimmend uit, maar da's geen chroom meer. Dus ik moet nog iets bedenken om het staal te beschermen. Ook het tonnetje heb ik in de boormachine geklemd en met een scotch brite bewerkt.


Daar hoort het ringetje te zitten.

Op bovenstaande foto zit het ringetje (naar mijn bescheiden mening) wél op de juiste plek. Tussen het palletje en de twee bladveertjes. Het palletje blijft zo niet meer 'haken' achter de bladveertjes. Nu snap ik pas waarom de schakelaar in sommige standen altijd een beetje hakerig draaide. En wat draait hij nu lekker soepel zeg! Die wil ik hoe dan ook in de Burton terug zien. Tenzij ik weer op andere gedachten kom, natuurlijk...


Ziet er weer bruikbaar uit.


De schakelaar wordt aangesloten via de kant die naar het dashboard gericht is. Normaliter wordt het volledige vermogen van de verlichting (en de claxon) geschakeld. Beetje off-topic, maar onderschat niet hoe veel dit is. Een snel rekensommetje als het groot licht aan staat:
  • Groot licht: 2 x 60 watt
  • Stadslicht: 2 x 5 watt
  • Achterlicht: 2 x 5 watt
  • Dashboard, kentekenplaat enz: ~10 watt
Da's in totaal al snel 150 watt wat overeen komt met ruim 12 ampère. En dan ben ik vast nog wat vergeten. Aanhanger of zo... Al die amps gaan door de contacten heen. Geen wonder dat die schakelaar wat warm kan worden. Zeker als de contacten niet meer helemaal schoon zijn en een overgangsweerstand naar het tonnetje hebben. Bij mijn installatie zal het allemaal niet zo'n vaart lopen. De schakelaars worden aangesloten op een microcontroller, dus daar loopt geen noemenswaardige stroom meer door.

Op onderstaande foto is te zien hoe de lichtschakelaar aangesloten wordt. Een beetje typisch, maar daar staat Citroën om bekend.


Aansluitingen.

  • A: Boordspanning, 12 volt.
  • B: Claxon.
  • C: Stadslicht.
  • D: Groot licht.
  • E: Dimlicht.

Er zijn meldingen van auto's waarbij D en E omgewisseld zijn. Klinkt eigenlijk wel logisch, want dan schakel je na één keer draaien tussen stadslicht en groot licht en na twee keer draaien tussen dimlicht en groot licht. Voelt intuïtiever aan, maar is niet volgens de oorspronkelijke gedachte van Citroën. De vraag is of dat belangrijk is voor een Burton-bouwer?