Doel:€250.00
Donaties:€90.00

Per saldo:€-160.00

Steun ons nu!

Laatst bijgewerkt
op 18-11-2019
Algemeen

De stichting

Recente berichten

BNLS trammodule: 'Den Zoedel Tramt' door arnaudns
Vandaag om 11:04:57
BNLS trammodule: Haagse Trams int noorden door arnaudns
Vandaag om 11:04:12
Fleischmann 1306 probeersels door NS1220
Vandaag om 11:00:56
DIGSIGHT decoder 5313 door Ben
Vandaag om 10:58:18
DDM-1 afscheid door Rick
Vandaag om 10:52:51
Frans loodsje door Zilte
Vandaag om 10:47:29
Roco v60 lichtgeleiders schilderen door Remunj
Vandaag om 10:27:43
Raadplaatje door wimk
Vandaag om 10:18:10
Piko 2019 door mardig23
Vandaag om 10:09:25
DDM-1 & DD-AR; de laatste loodjes. Fotodraadje. door Jamie
Vandaag om 09:37:22
Mat 54 in Schaal 0 door Mitchell
Vandaag om 09:11:11
MARDEC, de Multifunctionele ARduino dcc DECoder. door Duikeend
Vandaag om 08:55:17
NS modelbaan Hoekdam H0 door Ronald1974
Vandaag om 08:51:22
Mijn eerste H0-modeltreinbaan in aanbouw door Wim Vink
Vandaag om 08:43:22
Ermehuizen anno 1974 door mikeya
Vandaag om 08:43:20
Toon hier je nieuwe (model-) spooraanwinst(en)... door Bob R.
Vandaag om 08:11:47
Schwarzburg-Neuffen-Bahn door Patrick1975
Vandaag om 07:02:20
Update: baan in de tropen door Hans Grasmaijer
Vandaag om 05:56:56
"Litter Bin" voor Brits spoor en Britse modelspoorprojecten door jandejager
Vandaag om 02:44:04
Veerboten door Modellbahnwagen
Vandaag om 01:20:32
Verlichting e.d. eerst handmatig, later automatisch aansturen mogelijk en hoe? door Reinout van Rees
Vandaag om 01:09:32
LS Models 2019 door Rondje_HO
Vandaag om 00:27:44
Roco BR 80 wel of geen antislipbandjes? door Reinout van Rees
Vandaag om 00:04:42
Projekt 083-338 door Noordernet
21 november 2019, 23:49:09
Goede plantenspuit door Modellbahnwagen
21 november 2019, 23:30:50
Spoorwegkanon Leopold Krupp K5 (E) door Hans Reints
21 november 2019, 23:03:39
Heen, En en Weer door DE-II
21 november 2019, 22:56:47
Saint Tourbière, een Franse enkelsporige lijn door de Ardeche door hansb58
21 november 2019, 22:46:27
Baanplan voor herbeginner met een Fleischman H0 door Wim Hesselink
21 november 2019, 21:48:44
Onlangs gespot - gefotografeerd, de foto's door Kronefan
21 november 2019, 21:44:05
  

Auteur Topic: De CanBus komt naar Kranenberg, Arduino's en de CanBus  (gelezen 4341 keer)

meino

  • Offline Offline
  • Berichten: 555
De CanBus komt naar Kranenberg, Arduino's en de CanBus
« Gepost op: 11 oktober 2019, 13:07:40 »
Ik heb ooit een draadje gestart rond Automatisering voor Kranenberg. Destijds had ik nog geen kennis en ervaring met de CanBus, dat kwam later tijdens de discussies in dat draadje. Momenteel ben ik zover dat ik een goed werkende CanBus implementatie aan de gang heb. Ik had verder kunnen gaan in het oorspronkelijke draadje, maar het leek me beter om met een schone lei te beginnen en een nieuw draadje te starten gewijd aan de combinatie van Arduino's met een CanBus.

Groet Meino

A clean desk is a sign of an empty mind

Kranenberg

Martin Hornis

  • Offline Offline
  • Berichten: 956
Re: De CanBus komt naar Kranenberg, Arduino's en de CanBus
« Reactie #1 Gepost op: 11 oktober 2019, 15:42:56 »
We gaan het beleven. Je hebt een mooie spreuk in jouw onderschrift staan.
Märklin K-rails met boogstralen > 500 mm; NS-lichtseinen met cijferbak: 4, 6 en 8 in één bak; iTrain; Intellibox I; OC32; eigen treindetectiesysteem aangesloten op OC32; controleprogramma's voor iTrain en OC32.

meino

  • Offline Offline
  • Berichten: 555
Re: De CanBus komt naar Kranenberg, Arduino's en de CanBus
« Reactie #2 Gepost op: 11 oktober 2019, 15:56:29 »
Ok laten we eens beginnen.

Het is begonnen met een idee. Oorspronkelijk had ik allerlei Arduino systemen aangesloten, via DCC en via S88. Sommige daarvan had ik met de I2C bus aan elkaar geknoopt. Ook door de wirwar van de bedrading die hierdoor ontstaan was, beviel me dat niet.  Conclusie; ik heb een bus nodig. Daar is veel keuze in, na wat discussies in het oorspronkelijke draadje, heb ik besloten om met de CanBus te gaan werken. Voor de geinterresseerden: https://en.wikipedia.org/wiki/CAN_bus

Het systeem dat ik uitgerold heb voor Kranenberg is gebaseerd op het volgende schema:

Er zijn twee koppellingen tussen de klassieke DCC omgeving van de DCC Centrale, de DCC-Interface en de S88-Interface. De DCC-interface zet de ontvangen DCC commando'(op dit moment aleen de wissel/sein commando's) om in specifieke Canbus berichten. De S88-interface zet alle ontvangen bezetmeldingen om in een S88 shiftregister welke door de Centrale periodiek wordt uitgelezen. De S88-interface combineert meerdere 16 bit banks, het aantal daarvan is flexibel. Daardoor is er slechts een aansluiting nodig voor alle S88 bezetmelders met de centrale, dus geen noodzaak om zaken door te lussen.
   De Wissel-, Sein- en Draaischijf-controller, luisteren op de Canbus naar Wissel/sein commando's en bij ontvangst wordt het betreffende commando uitgevoerd, ten minste als het een wissel/sein betreft dat door een specifieke controller wordt bediend. Er kunnen n.l. meerdere van deze controllers aan de bus hangen, ieder met zijn eigen groep van seinen en wissels.
   De Bezetmelder-controllers monitoren hun bezetmelders en bij een wijziging wordt voor de betreffende bezetmelder een bezetmelder bericht op de bus gezet. Ook de Wissel-controller zal bij een wijziging van de wisselstand dit doorgeven in een bezetmelding (Hierdoor kan ik in Koploper bepaalde zaken regelen).

Een puntje van aandacht, ik heb tot nu toe geen behoefte gehad om al deze controllers dynamisch te kunnen configureren. Zo vaak wijzig ik de topologie van de baan niet, dus alles is gecodeerd in de Arduino schets en als er iets mocht wijzigen, dan pas ik de schets aan en laad ik de betreffende arduino's opnieuw. Wel is het zo dat ik bijvoorbeeld voor de wissel-, sein- en bezetmelder controllers slechts drie schetsen onderhoud, waarbij ik iedere specifieke Arduino zijn eigen systeem identificatie geef (Via jumpers op 4 pinnen), zodat hij weet welk gedeelte van de gemeenschappelijke configuratie voor hem geldt.

Tot zover even deze korte inleiding.

Groet Meino




« Laatst bewerkt op: 11 oktober 2019, 16:00:30 door meino »
A clean desk is a sign of an empty mind

Kranenberg

meino

  • Offline Offline
  • Berichten: 555
Re: De CanBus komt naar Kranenberg, Arduino's en de CanBus
« Reactie #3 Gepost op: 11 oktober 2019, 16:31:49 »
We gaan het beleven. Je hebt een mooie spreuk in jouw onderschrift staan.

Mijn werkplek  ;)



Groet Meino
A clean desk is a sign of an empty mind

Kranenberg

AlbertG

  • Offline Offline
  • Berichten: 224
Re: De CanBus komt naar Kranenberg, Arduino's en de CanBus
« Reactie #4 Gepost op: 11 oktober 2019, 16:45:09 »
Hoi Meino,
Interessant onderwerp.
Bestaan CAN-bus, de interfaces en controllers uit Arduino's met schetches of moet er elektronica gesoldeerd worden?
In het eerste geval blijf ik aangesloten, in het laatste geval haak ik (waarschijnlijk) af.
Ik heb een werkende DCC++ centrale, en ben vooral geïnteresseerd in de S88 interface.

Succes met de ontwikkeling.
Albert.

44

  • Team forummoderators
  • Offline Offline
  • Berichten: 13409
Re: De CanBus komt naar Kranenberg, Arduino's en de CanBus
« Reactie #5 Gepost op: 11 oktober 2019, 17:12:12 »
If a dirty desk means a dirty mind, what does an empty desk mean?

meino

  • Offline Offline
  • Berichten: 555
Re: De CanBus komt naar Kranenberg, Arduino's en de CanBus
« Reactie #6 Gepost op: 11 oktober 2019, 17:30:11 »
Dag Albert

Er moet wel wat simpel soldeerwerk gedaan worden. Ik heb de S88 interface met een UTP patchkabel (ethernet) op de Centrale aangesloten. Daarvoor heb ik een connector op een bordje gesoldeerd. Verder de connector aan wat pinnen gesoldeerd, zodat de handel met jumpercables aan de Arduino is verbonden. Uiteindelijk gaat het er om dat de S88 signalen op een aantal pinnen van de Arduino uitkomen, daar zit verder geen electronica tussen.
Voor de DCC interface is er wel een klein schakelingetje met wat weerstanden en een opto isolator op een stukje stripboard gesoldeerd om de DCC-controller fysiek met de DCC te verbinden.

Dit is het schema dat ik daarvoor gebruikt heb.


Groet Meino
A clean desk is a sign of an empty mind

Kranenberg

meino

  • Offline Offline
  • Berichten: 555
Re: De CanBus komt naar Kranenberg, Arduino's en de CanBus
« Reactie #7 Gepost op: 11 oktober 2019, 17:32:34 »
@44

 :D dat was het originele antwoord dat Albert Einstein gaf toen iemand het nodig vond om een opmerking over de chaos op zijn bureau te geven.
Overigens was dit motto al jaren in gebruik als weerwoord op baasjes die iedere keer probeerden om een "clean desk" policy in te voeren. Let wel we praten over een tijd voordat internet en google gemeen goed waren en ik samen werkte in een groep hackers die soms wedstrijden hielden wie de hoogste stapel op zijn bureau kon bouwen.

Groet Meino
« Laatst bewerkt op: 11 oktober 2019, 23:45:47 door meino »
A clean desk is a sign of an empty mind

Kranenberg

meino

  • Offline Offline
  • Berichten: 555
Re: De CanBus komt naar Kranenberg, Arduino's en de CanBus
« Reactie #8 Gepost op: 11 oktober 2019, 20:08:00 »
Grappig, dat motto heb ik al een hele tijd, en nu valt het een aantal mensen opeens op :D

Maar goed, terug naar het onderwerp van dit draadje.

Ik gebruik voor de fysieke interface naar de Can bus het volgende kaartje:



Dit  is een MCP2515 met TJA1050 receiver, deze kaartjes zijn voor minder dan 2 euro te koop op Aliexpress of Ebay. Overigens zijn ze vrij beperkt voor wat betreft de prestaties. Voor een deel wordt dat waarschijnlijk veroorzaakt doordat ze op 8Mhz draaien. Ik ben van plan om nog eens de 8Mhz oscilator te vervangen door 16 of 20Mhz om te kijken wat dat voor invloed heeft. In ieder geval bij juist gebruik is de prestatie voldoende voor mijn toepassing.
    Voor de aansluiting aan de arduino verwijs ik naar het internet, daar zijn genoeg schema's te vinden, alhoewel het eigenlijk simpel is, de communicatie tussen Arduino en het kaartje vindt plaats d.m.v. de SPI bus. Alleen de CS pin (voor de selectie van het actieve SPI device) is vrij. Ik gebruik daar meestal pin 9, 10 (op de UNO) of 53,54 (op de Mega) voor.

Voor het testen van mijn CanBus bibliotheek heb ik ook een Testsysteem opgezet, bestaande uit 2 Arduinos en 4 MCP2515 kaartjes.



Logisch schema van de test.


De test is in principe vrij simpel, beide UNO's zenden in een continue stroom berichten naar de andere kant. Tegelijkertijd ontvangen beide UNO's ook de berichten van de andere kant. Door in de berichten tellers en andere identificatie op te nemen wordt bij ontvangst gecontroleerd of alles correct ontvangen is. De timing tussen de berichten is tijdens de test gevarieerd. Uit deze stresstest blijft het goed werken tot het moment dat beide UNO's 250 berichten/sec verzenden, Dus een totaal 500 berichten/sec is mogelijk. Dat is in mijn optiek voldoende voor ons gebruik, het is meer dan wat er via DCC verzonden kan worden (200-220/sec)

Een aantal observaties gedaan tijdens het testen.
- De bus snelheid die gebruikt wordt is 500Kb/sec, Theoretisch zou de MCP2515 chip ook 1Mb/sec aan kunnen, maar gebruik van die snelheid kan het kaartje niet echt aan, want dan stort de betrouwbaarheid in. Ook bij lagere snelheden neemt de prestatie weer sterk af. Dus 500Kb is optimaal.

- Een kaartje gebruiken voor gecombineerd ontvangen en zenden is zeer slecht voor de prestaties. In dat geval valt de prestatie met 80-90% terug. Vandaar dat voor systemen die zowel berichten ontvangen als wel berichten moeten zenden, er twee MCP2515 kaartjes gekoppeld worden, een voor zenden en een voor ontvangen. Dat is ook op het testsysteem gedaan.

- Het MCP2515 kaartje behoort niet tot de meest snelle systemen. Uit veel berichten op Internet blijkt dat vooral het gebruik van de SPI interface om data uit de kaarten en data naar de kaart te sturen veel tijd kost.

- Het gebruik van de interrupt pin met interrupt handlers in de Arduino verslechtert de prestaties aanmerkelijk, Vermoedelijk heeft dat te maken met de hoeveelheid interrupts die de Arduino dan voor zijn kiezen krijgt en de bijbehorende context switches welke in de Arduino code afgehandeld moet worden. De beste prestaties krijg je als je de MCP2515 kaart polt

- Volgens de specificaties heeft de MCP2515 3 transmit buffers en 2 receive buffers. Zonder in de specs te duiken, was mijn aanname dat de kaart dus 2 berichten kan opnemen voordat er een overrun plaats vindt. Dat is dus niet zo. De eerste buffer wordt gebruikt voor z.g. "High priority" berichten en de tweede buffer voor z.g. "Low Priority" Berichten. Wat High of Low is wordt bepaald door de mask en filter setting. Er zijn twee masker registers en 6 filter registers. 2 van de filter registers horen bij de eerste mask register, de andere 4 horen bij de tweede mask register. Een High priority bericht is een bericht dat geaccepteerd wordt door de eerste mask en filter registers. Een bericht dat pas door de tweede mask en filters wordt geaccepteerd is een low priority bericht. In de praktijk houdt dat dan ook in dat er eigenlijk maar een receive buffer gebruikt wordt. Overigens heb ik helaas moeten constateren dat het gebruik van de tweede mask en bijbehorende filters veel overhead op het MCP2515 kaartje tot gevolg heeft met de bijbehorende negatieve invloed op de prestaties. Ik gebruik dan voor de filtering maximaal 2 filters. Bij meer filters, zet ik de filtering in de kaart af en ga over naar filtering in de arduino code.

Tot zover. In de volgende bijdrage ga ik wat dieper in op de Bibliotheek die ik ontwikkeld heb om de hardware aan te sturen.

Met vriendelijk groet
Meino





A clean desk is a sign of an empty mind

Kranenberg

meino

  • Offline Offline
  • Berichten: 555
Re: De CanBus komt naar Kranenberg, Arduino's en de CanBus
« Reactie #9 Gepost op: 14 oktober 2019, 00:09:20 »
Tijd om weer verder te gaan.

Essentieel om Can-Bus te begrijpen is het feit dat je berichten niet naar een ander systeem stuurt. Op de Canbus publiceer je een bericht, en dat gepubliceerde bericht kan in principe door alle aangesloten systemen gelezen worden. Het is dan aan de andere systemen om te beslissen of ze een bericht moeten verwerken. De zender weet dan ook niet of er iemand is die er wat mee doet, het enige dat hij kan zien is dat het bericht met succes is gepubliceerd.
Om dit in goede banen te leiden begint ieder bericht met een ID (identificatie) veld. De inhoud van het ID veld moet uniek zijn voor ieder systeem dat aan de bus hangt. Er zijn 2 mogelijk groottes voor het ID veld, in std mode is het ID veld 11 bits, in extended mode is het 29 bits groot. Momenteel gebruik ik alleen de std mode, dus 11bit ID's.
In dit syteem zijn de ID's als volgt: bit 1-7 (LSB 0) bevat een uniek systeem nr dat gekoppeld is aan ieder specifiek systeem aan de Can-bus. Hierdoor kan ik maximaal 127 systemen koppelen. Om enige ordening te krijgen heb ik dit gekoppeld aan het systeemtype (DCC-Interface, S88-Interface, Bezetmelder-controller, Sein-controller en Wissel-controller) d.m.v Enum definities in de bibliotheek. Momenteel is daarvoor het volgende gedefinieerd:
-   DCC-Interface                 127
-   S88-Interface                  126
-   Bezetmelder-controller    1-16
-   Wissel-controller             17-32
-   Sein-controller                 33-48
Voor ieder type controller is er nu ruimte voor 16 exemplaren, dat is voor mij nu voldoende. Overigens is er nog genoeg ruimte omdat uit te breiden. Ook is er nog ruimte voor toekomstige uitbreidingen. Ieder type interface komt slechts 1 keer voor. Verder gebruiken de controllers pin a0-a3 om een digitaal nummer te zetten dat tijdens setup gelezen kan worden en gebruikt wordt om de type enum op te hogen zodat het echte systeemnr ontstaat dat in de ID kan worden gezet. Hoe dat in de code er uitziet daar zal ik later nog wel laten zien.
Bit 8-11 (4bits ook LSB 0) bevatten het berichttype. Op dit moment zijn er 3 berichttypes gedefinieerd.
-   OCC_DT_MSG       1         Berichten met de status van een bezetmelder
-   DCC_ACC_MSG     2         DCC wissel/sein commando
-   DCC_LOC_MSG     3         DCC lokomotief commando (nog niet in gebruik)

Ter verduidelijking, LSB 0 betekent Least Significant Bit heeft index 0. Dat betekend dat de bit nummering in het ID veld van rechts naar links gaat (analoog aan de bitSet() functie in een Arduino schets).

Groet Meino
« Laatst bewerkt op: 14 oktober 2019, 00:31:27 door meino »
A clean desk is a sign of an empty mind

Kranenberg

meino

  • Offline Offline
  • Berichten: 555
Re: De CanBus komt naar Kranenberg, Arduino's en de CanBus
« Reactie #10 Gepost op: 14 oktober 2019, 16:34:01 »
Door deze indeling ondersteun ik maximaal 15 berichttypes (0 wordt niet gebruikt omdat die waarde niet goed te filteren was op de MCP2515 kaart). Dat leek mij voldoende ook voor de toekomst.
   Een eigenschap van de CanBus is dat berichten met een lagere ID waarde automatisch een hogere prioriteit krijgen. Dat is de achtergrond voor de type keuzes. Hoogste prioriteit hebben de berichten van de bezetmelders, die zenden een status wijziging slechts 1 maal uit. De DCC accessory (wissel-seinen) commando's worden door de meeste centrales een aantal keren na elkaar verzonden, en de lokcommando's worden nog vaker herhaald.

Data in een Canbus bericht kan 1 tot 8 bytes lang zijn.

In het bezetmelder bericht, type OCC_DT_MSG, worden twee bytes als data verstuurd. De eerste byte bevat het nr van de bezetmelder en het tweede byte zijn status.
    Overigens de waarde van het bezetmeldernr volgt een andere conventie dan vaak gebruikt wordt in besturingsprogramma's. In Koploper heeft de eerste bezetmelder van de eerste groep van 16 bezetmelders het adres 1.01. Het bijbehorende nr in het bericht is echter 0x00. Bezetmelder 1.02 wordt 0x01, 1.15 wordt 0x0F, 2.03 wordt 0x12 etc. In totaal kunnen dus 256 bezetmelders ondersteund worden.
De tweede byte bevat de status, 0 is niet bezet, 1 is bezet.

In het Accessory (wissel/sein) bericht, type DCC_ACC_MSG, bevat de eerste byte het adres van het wissel of sein zoals dat in het treinbesturings programma is vastgelegd. Op dit moment ondersteunt de bibliotheek slechts 255 adressen en niet de maximale 2044 die volgens de DCC normen mogelijk zouden zijn. Dat is voor later en heeft ook te maken met de gebruikte centrale. De wissel/sein stand wordt bepaald door de waarde in het tweede byte. 0 betekend rechtdoor of onveilig wissel. en 1 betekend afbuigend/veilig.
Overigens dit hangt af van de centrale en hoe het treinbesturings programma zich gedraagt of hoe seinen en wissels zijn geconfigureerd. Dit is wat ik zelf krijg in mijn combinatie van Koploper met de MDRRC II centrale.

Groet Meino
A clean desk is a sign of an empty mind

Kranenberg

meino

  • Offline Offline
  • Berichten: 555
Re: De CanBus komt naar Kranenberg, Arduino's en de CanBus
« Reactie #11 Gepost op: 16 oktober 2019, 23:38:21 »
Nog even een kleine update, tot nu toe had ik een maximum van 255 wissels/seinen en bezetmelders ingebouwd. Alhoewel dat voor mijn toepassing, Kranenberg meer dan voldoende is, leek het met toch bij nader inziens om wat binnen de DCC normen mogelijk is in te bouwen. Dus heb ik het adres veld in de berichten uitgebreid van 1 byte naar 2 bytes (een unsigned short) zodat ik nu 2044 wissels/seinen en 512 of meer bezetmelders kan ondersteunen. Dus de lengte van een OCC_DT_MSG en DCC_ACC_MSG is nu 3 bytes lang.

Groet Meino
A clean desk is a sign of an empty mind

Kranenberg

meino

  • Offline Offline
  • Berichten: 555
Re: De CanBus komt naar Kranenberg, Arduino's en de CanBus
« Reactie #12 Gepost op: 24 oktober 2019, 13:21:38 »
Na de voorgaande introductie, is het tijd om wat dieper in te gaan op de code.
Er zijn twee bibliotheken gebruikt. Een bibliotheek https://github.com/autowp/arduino-mcp2515 komt van Github, deze is er om het gebruikte MCP2515 kaartje direct via SPI en zijn hardware registers aan te sturen. Omdat ik zelf er niet van hou om iedere keer weer een soms,complexe serie commando's uit te voeren, heb ik zelf een bibliotheek gemaakt die dit in een aantal simpele methods (functie aanroepen) regelt. Dit is de KB_CanBus bibliotheek. Voor hen die zelf hiermee aan de slag willen, neem contact met mij op via een PB en ik maak dan wel een zip bestand met beide bibliotheken.

Wat doen we om de toegang naar de Canbus te activeren. Daarvoor zijn er twee klassen gedefinieerd in de KB_CanBus bibliotheek. N.l. de mcp2515 en de CanBus. Een mcp2515 object representeerd een fysiek Mcp2515 kaartje. De creatie van dit object kent slechts een parameter, n.l. de digitale pin op de Arduino waarmee de CS  pin (SPI device selectie) van het betreffende kaartje is verbonden.

Voorbeeld:
mcp2515 *sender = new mcp2515(10);

Dit object hoeven we verder niet in de code van de schets aan te spreken, het wordt slechts gebruikt om aan de echte interface door te geven. Deze inteface die we aanspreken is een Object van het type CanBus. Tijdens de creatie van dit object geven we het als parameters een unieke systeemidentificatie en  het adres van een of twee mcp2515 objecten mee.

Voorbeeld:
//
// Ieder systeem heeft een uniek nummertje nodig op de Canbus. Hoe we aan dat nummer komen
// laten we hier nog even open.
//
int systemId = .......;

//
// Canbus interface die alleen berichten moet ontvangen
//
CanBus *messageReceiver = new CanBus( systemId, nullptr, new mcp2515(9));

//
// Canbus interface die alleen berichten moet zenden
//
CanBus *messageSender = new CanBus(systemId, new mcp2515(10), nullptr);

//
// Canbus interface die berichten moet ontvangen en zenden (er zijn 2 mcp2515 kaartjes)
//
CanBus *cbSenderReceiver = new CanBus(systemId, new mcp2515(10), new mcp2515(9);

Groet Meino
A clean desk is a sign of an empty mind

Kranenberg

meino

  • Offline Offline
  • Berichten: 555
Re: De CanBus komt naar Kranenberg, Arduino's en de CanBus
« Reactie #13 Gepost op: 24 oktober 2019, 17:54:54 »
Even iets over de systemId die gebruikt wordt om het CanBus object te maken.
Iedere systeem dat berichten op de Canbus zet moet zorgen dat het ID (identificatie) veld van het bericht uniek is ten opzichte van de berichten die door andere producenten worden geproduceert. In voorgaande posts heb ik het daar al over gehad, deze bibliotheek maakt gebruik van standaard berichten, dus een ID veld van 11 bits. 4 bits bevatten het berichttype (DCC_ACC, OCC_DT etc) de overige 7 bits worden gevuld met het systemId zoals dat tijdens de creatie van het CanBus object wordt doorgegeven. Het is dus van belang dat iedere Arduino aan de Canbus zijn eigen unieke systemId krijgt.
Daarom zijn in CanBus.h een aantal type producenten gedefinieerd.

Een stukje uit CanBus.h
//
// Id's of the different types of controllers on the CanBus
//      Maximum nr of ID's is 127!!!
//
#define BEZETMELDER_CONTROLLER_ID 1   //  16 Bezetmelder controllers supported
#define WISSEL_CONTROLLER_ID 17       //  16 Wissel controllers supported
#define SEIN_CONTROLLER_ID 33         //  16 Sein controllers supported
#define DCC_INTERFACE_ID 126          //   1 DCC Interface system supported
#define S88_INTERFACE_ID 127          //   1 S88 Interface system supported

De beide interface systemen komen slechts een maal voor, dus die hebben een vast systemId. Voor de huidige controllers heb ik ruimte voor maximaal 16 stuks van een type gereserveerd (dat kan natuurlijk aangepast worden door de waarden in CanBus.h aan te passen).
Voor de controllers gebruik ik deze definities als start die ik daarna ophoog met een vaste waarde voor iedere controller. Dat kun je doen door in de EPROM van iedere Arduino een eigen nummer te zetten, wat tijdens setup uitgelzen wordt. of zoals ik het doe, d.m.v. jumpers naar aarde op pinnen A0,A1,A2 en A3 waarmee ik als het ware een digitaal (4bits) getal maak.

Een klein voorbeeld uit de setup method van de DCC Interface
//
//  The CanBus
//
CanBus *canBus;

void setup()
{


  //

  //  Start the CanBus communication
  //
  canBus = new CanBus(DCC_INTERFACE_ID, new Mcp2515(10), nullptr); // Only a sender
  canBus->setSendWaitTime(4); // Set minimum delay between messages
  canBus->begin();        // Make the CanBus interface active


}// End of setup

In deze twee voorbeelden zien we naast de creatie van de CanBus objecten ook het gebruik van twee methods (functies) van het gecreerde object. de begin method, zorgt er voor dat de interface start, dit is een

En een stukje uit de setup van de Bezetmelder Controller
void setup()
{
  //
  //  Based on which pin is connected to ground, the controller ID is established
  //
  pinMode(A0, INPUT_PULLUP);
  pinMode(A1, INPUT_PULLUP);
  pinMode(A2, INPUT_PULLUP);
  pinMode(A3, INPUT_PULLUP);

  systemId = 0;
  if (!digitalRead(A0)) systemId = systemId+1;
  if (!digitalRead(A1)) systemId = systemId+2;
  if (!digitalRead(A2)) systemId = systemId+4;
  if (!digitalRead(A3)) systemId = systemId+8;

  //
  //  Start the CanBus communication
  //
  canBus = new CanBus(BEZETMELDER_CONTROLLER_ID+systemId, new Mcp2515(10), nullptr); // Only a sender
  canBus->begin();      // Make the CanBus interface active
}

We zien dat we na de creatie van het CanBus object er ook een aantal methods (functies) van het object uitgevoerd wordt. Wat altijd moet gebeuren is de begin() method, deze initializeerd en activeerd de inteface naar de Canbus. Maar voordat je dit doet, is er de mogelijkheid om een aantal parameters van het gecreerde object aan te passen. Bijv. setSendWaitTime(4) dat bij de DCC Interface wordt gebruikt, veranderd de minimale wachttijd tussen 2 op een volgende berichten die deze Arduino op de Canbus zet. Standaard is die 10ms (max 100berichten/sec). In dit geval wordt dit op 4ms gezet (250berichten/sec).
De reden achter dit is, dat het MCP2515 kaartje niet al te snel is, en dat als er teveel berichten te snel aangeboden worden, de kans op verloren berichten vrij groot is. Hiermee wordt gezorgd dat een enkel systeem niet de bus kan verzadigen.

groet Meino
« Laatst bewerkt op: 24 oktober 2019, 17:59:24 door meino »
A clean desk is a sign of an empty mind

Kranenberg

meino

  • Offline Offline
  • Berichten: 555
Re: De CanBus komt naar Kranenberg, Arduino's en de CanBus
« Reactie #14 Gepost op: 24 oktober 2019, 23:56:43 »
We hebben nu een CanBus object geinitialiseerd en klaar voor gebruik, maar verder doet hij nog niet veel. Om een receiver actief te laten luisteren naar berichten en een zender aangeboden berichten op de bus te laten zetten, moet in de loop() functie van een schets, constant de heartBeat() method van de CanBus object aangeroepen worden.

void loop()
{
  //
  //  Monitor the canBus
  //
  canBus->heartBeat();

  // Andere code

}

Deze heartBeat() method verzorgt een aantal zaken, Als het CanBus object een mcp2515 object als zender heeft, worden berichten die in de send queue staan in het tempo dat is gedefinieerd door de sendWaitTime eigenschap (zie setSendWaitTime()) eigenschap op de bus gezet.
Als het CanBus object een mcp2515 object als ontvanger heeft, dan wordt bij het betreffende MCP2515 kaartje geinformeerd of er een bericht is ontvangen, als dat het geval is, wordt het bericht van de kaart gelezen en aangeboden aan een geregistreerde call back routine voor het type van de ontvangen bericht.

We hebben het nu over het zenden en ontvangen van berichten.
Voordat we daar verder op ingaan eerst even iets over de berichten zelf. Op dit moment zijn er twee typen berichten die gebruikt worden, de derde is wel al gedefinieerd, maar wordt in de huidige systemen nog niet gebruikt.

Een klein stukje uit CanBus.h
//
//  There are several types of messages, each is identified by an unique number
//  the lowest id's have the highest priority
//
//  DCC_ACC   defines a DCC Accesory command
//  OCC_DT    defines an Occupance detector that triggered
//  DCC_LOC   defines a DCC locomotive command
//

enum messageId {
    OCC_DT = 1, DCC_ACC = 2, DCC_LOC = 3
};

typedef struct
{
    unsigned short    address;
    byte              state;
} OCC_DT_MSG;

typedef struct
{
    unsigned short    address;
    byte              direction;
} DCC_ACC_MSG;


Berichten die de status van een bezetmelder bevatten zijn van het type OCC_DT en hun inhoud is de struct OCC_DT_MSG. Berichten die een actie voor een DCC Accessory decoder aansturen zijn van het type DCC_ACC en de berichtdata staat in een struct DCC_ACC_MSG. DCC_LOC is een type voor een toekomstige uitbreiding en wordt nu nog niet gebruikt.

Een klein voorbeeld van het zenden van een bericht.
      //
      //  Send the new state to the S88 Interface
      //
      OCC_DT_MSG buf;
      buf.address = ((s88Bank-1)*16)+(s88Id-1);
      if (occupied)
        buf.state = 1;
      else
        buf.state = 0;

      //
      //  Repeat the message, to cover the occasional mishap
      //
      canBus->sendMsg(OCC_DT, sizeof(OCC_DT_MSG), &buf);
      canBus->sendMsg(OCC_DT, sizeof(OCC_DT_MSG), &buf);
Wat belangrijk is, dat sendMsg() het bericht niet direct op de bus zet, maar dat het bericht slechts op de interne send queue geplaatst wordt. Daarna is het de verantwoordelijkheid van de heartBeat() method om het bericht op de bus te zetten.
Tot zover het zenden van berichten, nu hoe ontvangen we een bericht, dat doen we door een z.g. Call back routine bij het CanBus object te registreren. Dit moet gebeuren in de setup() van de schets.
void setup()
{

  canBus->setMsgReceiver(OCC_DT, occDtReceiver);
 
}
De Call Back routine occDtReceiver wordt vanuit het CanBus object aangeroepen op het moment dat er een OCC_DT_MSG ontvangen is.
en voorbeeld van deze Call back routine:
/
//  A function that executes whenever a message is received from the Canbus
//  It's purpose is to analyze the received event Occupancy detector and
//  update the proper element in the semaphore table or turnout table.
//
void occDtReceiver(unsigned char aMsgLen, OCC_DT_MSG *msgData)
{
  if (msgData->address < nrOfOccDetectors)
  { 
    pendingStates[msgData->address] = msgData->state;

Dit is in grote lijnen hoe de CanBus bibliotheek gebruikt kan worden.

Groet Meino
A clean desk is a sign of an empty mind

Kranenberg