Er zijn een aantal concepten die je kunnen helpen je droom te realiseren. Ik kan niet in de ruimte van dit antwoord precies zeggen hoe je moet implementeren wat je wilt, maar ik kan je de concepten laten zien die je zullen helpen om het te implementeren.
Allereerst is er het concept van de busmaster . Dit is niet noodzakelijkerwijs het apparaat dat communicatie tot stand brengt - in plaats daarvan is dit het apparaat dat de eigenaar is van en de bus bedient.
Wanneer een apparaat dat niet de busmaster is, op de bus wil communiceren, vraagt het eerst toestemming aan de busmaster. De oude Z80 (nou ja, ik zeg "oud", maar ze zijn tegenwoordig nog in veel vormen) gebruikte dit concept om andere chips toe te staan om de data- en adresbussen te gebruiken. Het bestaat uit twee signalen - BUSRQ en BUSACK. Een apparaat kijkt eerst of BUSRQ of BUSACK actief zijn en of geen van beide BUSRQ activeert. Als de busmaster bereid is om de bus op te geven aan het andere apparaat (hij gebruikt het op dat moment niet), activeert het BUSACK en weet het andere apparaat dat het de bus kan gebruiken. Niets anders kan het gebruiken totdat BUSRQ en BUSACK beide zijn vrijgegeven. Mooi en eenvoudig en elegant.
Maar niet perfect. Als twee apparaten beide besluiten om op hetzelfde moment om de bus te vragen, krijg je een botsing . Dit is een veel voorkomend probleem bij gedeelde bussystemen zoals dit, en veroorzaakt onnoemelijke problemen, tenzij je weet hoe je het op de juiste manier moet gebruiken.
Voer het concept luister-terwijl-je-praatje in. Dit betekent dat het apparaat dat de bus verzendt ook luistert naar wat er op de bus wordt verzonden via een afzonderlijke ontvanger. Het kan dan weten of wat het in de bus heeft verzonden, is wat er feitelijk in de bus is terechtgekomen. Als twee apparaten bijvoorbeeld op hetzelfde moment praten en één 10011001
verzendt en de andere 11001100
verzendt, kan het resultaat dat op de bus verschijnt, uiteindelijk iets anders zijn, zoals 11011101
of misschien 10001000
, afhankelijk van hoe de bussignalen zijn gemaakt. Dus als je weet wat je hebt verzonden, kan je er nu iets aan doen.
Volgend concept: back-off . Dit is waar beide afzenders een korte periode wachten en proberen opnieuw te verzenden. Zolang ze beiden een bepaalde tijd uitstellen, zal de eerste die probeert de bus pakken en kunnen communiceren. Maar hoe garandeer je dat ze beide voor verschillende tijden uitgesteld zullen worden? U denkt misschien dat het antwoord eenvoudig is: gebruik een willekeurig getal, zoals rand()
of random()
. Maar dat is ook een probleem:
Another concept: The pseudo random number generator
De Arduino genereert geen willekeurige getallen. Het gebruikt gewoon een complexe wiskundige formule om een reeks getallen te creëren die voor ons willekeurig kijken . Dat zijn ze echter niet. Schrijf een klein programma om 10 willekeurige nummers serieel af te drukken en meerdere keren uit te voeren (druk op de resetknop). U zult steeds dezelfde "willekeurige" nummers in dezelfde volgorde vinden. Probeer het op een andere Arduino en je krijgt dezelfde nummers opnieuw. Altijd hetzelfde.
Dus wat te doen? Het antwoord heet seeding de generator van willekeurige getallen. Het volgende nummer gegenereerd door rand()
et al hangt af van het nummer dat als laatste is gegenereerd. Dus verander het eerste nummer en de rest van de nummers zal veranderen. Je hebt echter een catch-22-situatie. Je hebt een willekeurig nummer nodig om de generator van willekeurige getallen in te zaaien om het willekeurig te maken om een willekeurig getal te kunnen genereren om de toevalsgetalgenerator ... ad infinitum in te zaaien. Zie je waar dat heengaat? Je kunt niet seeden van rand()
omdat rand()
niet willekeurig is totdat je uit een willekeurige bron hebt gezaaid. Dus je moet een willekeurige bron vinden.
En dat is geen gemakkelijke taak. De beste bron van entropy zoals die bekend is, is witte ruis . Dit kan op een aantal manieren worden gegenereerd met een aantal verschillende circuits - van de afbraak van een diodeovergang tot een zeer hoge versterkingsversterking van de thermische fluctuaties in een weerstand.
Ze zijn allemaal behoorlijk ingewikkeld voor wat je echt wilt, maar er is een eenvoudigere, zij het iets minder willekeurige methode: lees een analoge ingang die nergens mee verbonden is. Het zal niet zoveel bereik hebben als een geschikte entropie-generator, maar het moet voldoende willekeur bieden om een redelijke kans te geven dat elk apparaat een ander zaad krijgt.
Een ander nuttig concept is de interrupt.
Dit is goed in een situatie waarin je niet de complexiteit van een multi-masterbus met alle botsingen wilt, enz. Je hebt één master die al het werk op de bus doet en wanneer een slave-apparaat iets belangrijks te zeggen heeft het duwt de meester met een interrupt. De meester gaat dan "Ja? Wat wil je?" waarop de slaaf antwoordt: "Iemand heeft op mijn knop gedrukt".
Op die manier pompt de meester niet constant de slaaf om te zien of de knop is ingedrukt. Het wordt vaak gebruikt in busarrangementen zoals SPI en er zijn veel chips, zoals IO-expanderchips, die een onderbreking kunnen doen gelden wanneer een van hun ingangspinnen van status verandert.
Maar als u 20 apparaten heeft, betekent dit dat u 20 interrupt-pinnen hebt? Niet noodzakelijk. Nieuw concept: bedraad OF .
Het is perfect mogelijk om meerdere verschillende slaves allemaal met dezelfde interrupt-pin te gebruiken. De pin wordt normaal HOOG gehouden met een weerstand (dit kan een interne pullup-weerstand zijn) en elke slave heeft een open drain -uitgang die op die pin is aangesloten. Een open afvoeruitgang, wanneer "uit", is nergens op aangesloten - het is alsof de pin in de invoermodus is (in feite kan deze worden geëmuleerd op chips die geen open afvoer hebben door te schakelen tussen de invoer- en uitvoermodus). Wanneer de uitgang "aan" staat, verbindt deze de pin met de aarde en trekt de IO-pin naar beneden, net als een knop.
Het is dan aan de meester om zijn weg te banen rond de slaven waarvan het weet dat ze gehecht zijn aan die interrupt om te zien wie aandacht nodig heeft. Je kunt natuurlijk een aantal verschillende interrupt-pinnen implementeren met verschillende groepen slaves op elke - misschien een hoge prioriteit met slechts één apparaat, en lagere prioriteit degenen met elk een, bijvoorbeeld, meerdere apparaten.
Hetzelfde concept van bedrade OF en open afvoer kan worden gebruikt om meerdere apparaten dezelfde fysieke draden te laten delen. Dat is precies hoe I2C werkt - de twee buslijnen worden omhoog getrokken door weerstanden en de apparaten erop gebruiken open afvoeroutputs om de lijn laag te trekken om hem weer te hoog te zetten om de verschillende logische niveaus te creëren. Als twee apparaten het samen laag trekken, is het net laag. Zonder de open drain-methode als je had dat een apparaat een 1 en een ander uitvoerde met een 0, zou je in principe een kortsluiting krijgen tussen de twee en zou je uiteindelijk chips beschadigen.
En dan heb je natuurlijk het concept van synchrone versus asynchrone communicatie, maar dat is een heel ander soort vis. Simpel gezegd, protocollen met een klok, zoals SPI en I2C, die een master hebben die die klok genereert, zijn synchroon. Protocollen zoals de UART en RS-232, RS-485, enz. Zijn asynchroon - ze vertrouwen op beide uiteinden afspreken hoe snel gegevens worden verzonden (baudrate), zodat ze weten hoe de signalen te interpreteren als ze aankomen.