I2C gebruiken om structuren verzenden en ontvangen

Arduino specifieke Software
Berichten: 15
Geregistreerd: 12 Mei 2017, 21:36

I2C gebruiken om structuren verzenden en ontvangen

Berichtdoor rainman » 12 Mei 2017, 22:05

Hallo,

Ik ben begonnen met een project waarbij ik tussen 3 arduino's wil gaan communiceren met I2C. De afstand tussen deze arduino's is ongeveer 0,5m. Een master en 2 slave.

De master is een Mega en de slaves zijn Uno's. Over deze arduino zijn 8 segmenten verdeeld met ieder zijn eigen hardware en software. De software acteer op de informatie die beschikbaar is voor elk segment

In een segment is een input en een output deel.

In een input (of output) deel zitten analoge en digitale signalen.


In de master zit een hoofdstructuur, zoiets als dit.

Segment[0].IN[0]
Segment[0].IN[1]
....
Segment[0].IN[4]

Segment[0].OUT[0]
Segment[0].OUT[1]
....
Segment[0].OUT[4]


Segment[..]

Segment[8]


Hierin wordt date geschreven en gelezen

Bijvoorbeeld

In een segment 5 zit een potmeter en deze waarde wordt geschreven in Segment[[5].IN[0]

De software doet iets met deze waarde

Daarna wordt een waarde geschreven voor een servo motor in Segment[[5].OUT[0]


Segment 5 zit toevaliige op de slave arduino.

Hoe gaat ik dit aanpakken.

Ik heb nu al een test werkend met een Mega als master en een uno als slave. Op de mega zit een potmeter en op de uno een servo. Dit werkt nu.

Alleen ik wil graag met een structuur werken. Ik kan bijvoorbeeld een analoge waarde voor meer digitale signalen gebruiken

Heeft iemand een goed idee?


Met vriendelijke groet,

Rainman

Advertisement

Gebruikers-avatar
Berichten: 2655
Geregistreerd: 06 Aug 2016, 01:03

Re: I2C gebruiken om structuren verzenden en ontvangen

Berichtdoor Koepel » 13 Mei 2017, 00:02

Als je alle stukjes draad bij elkaar optelt van de SDA of SCL, wat is dan de lengte ?
Gebruik geen flatcable. Het beste is om SDA en SCL als losse draadjes in de lucht te hangen ;)

Bij een class/object kun je een waarde toekennen die je soms opslaat in een variabele en soms doorstuurt via I2C naar een Slave Arduino. Helemaal automatisch. Heb je dat deel al ? Ik weet niet meer hoe dat ging, maar misschien kan ik het opzoeken.
Een object kun je niet over I2C sturen. Dan kom je bij 'struct' en 'union' terecht.
De Wire library heeft een buffer van 32 byte, dus dat is het maximum.

Je vraag is me niet helemaal duidelijk. Als je verschillende soorten variabelen wilt oversturen, dan zou je een 'id' kunnen gebruiken.
Code: Alles selecteren
struct MYSTRUCT
{
  byte id;
  union
  {
    byte b;
    int i;
    long l;
    float f;
  }v;
};

MYSTRUCT myStruct;

myStruct.id = 1;       // 0=byte, 1=int, 2=long, 3=float
myStruct.v.i = 125;

Berichten: 15
Geregistreerd: 12 Mei 2017, 21:36

Re: I2C gebruiken om structuren verzenden en ontvangen

Berichtdoor rainman » 14 Mei 2017, 11:08

Hallo Koepel,

Het wordt een robot, vandaar de segmenten. De totale SDA of SDL is een meter. Er zitten wel één of twee slipringen tussen (ligt nog aan het ontwerp). Een voorbeeld is https://www.adafruit.com/product/1196

Als een andere manier van communiceren beter is, hoor ik het graag. Ik ben niet helemaal thuis in C. Ik kan het meeste wel volgen, maar zelf wat opschrijven is nog wat lastig. Elk segment krijgt een motor (stepper of servo). Elk draaipunt krijgt een pot meter voor de huidige positie. Dus vandaar in input en het output gedeelte. Ik denk dat ik aan intergers genoeg heb. En voor de digitale signalen wil ik ook een interger gebruiken, dan kan ik 8 digitale in of outputs gebruiken, toch?

Dus per segment 3 interger voor input en 3 intergers voor output. De eerste voor analoog (motor/potmeter), de 2e voor de digitale signalen en de 3e is reserve, want je weet maar nooit.

ik heb me verdiept in struct, als ik het goed begrijp zal het dus zo worden:

Code: Alles selecteren
typedef struct
  {
    int Outputs[2]
    int Inputs[2]
  }  record_type;

record_type segment[8];


segment[2].Outputs[1] = 138;





Alleen dan zit ik met het volgende probleem

Een interger is 4 bytes. Met 3x een input en 3x een output is dat al 24 byte. Klopt mijn rekensom?


Aleen dit is nog maar 1 segment en dan al bijna aan de 32.


Ik loop dan al nu al vast.

Gebruikers-avatar
Berichten: 2655
Geregistreerd: 06 Aug 2016, 01:03

Re: I2C gebruiken om structuren verzenden en ontvangen

Berichtdoor Koepel » 14 Mei 2017, 11:54

De Arduino Mega 2560 en de Arduino Uno gebruiken 8-bit ATmega microcontrollers. De compiler heeft de default integer op twee byte gezet, dan is er goed mee te werken.

De I2C kan ontvangen of versturen. Niet allebei. En iedere Slave wordt apart aangeroepen.
Heeft een Arduino Uno drie integers voor uitgangen en drie integers voor ingangen ? Dan gaat er dus maximaal 6 byte data over de I2C bus ? of 3 en 1 ?

Een I2C bus van 1 meter kan. Als je maar onthoudt om SDA en SCL niet naast elkaar in een flatcable te leggen.
Natuurlijk ook niet naast draden die voor de power van motors zorgen.
De I2C is oorspronkelijk bedoeld om binnen in een Philips televisie de instellingen op te slaan en te gebruiken. Dus de I2C is niet bedoeld om de printplaat te verlaten.

De juiste pullup weerstanden is belangrijk.
Wanneer een Master of Slave de SDA of SCL laag trekt, dan kies ik zo'n 1mA voor kleine projecten. Het mag maximaal 3mA zijn (volgens de officiële standaard). Dus je kunt tussen de 2mA en 3mA gaan zitten voor zo sterk mogelijke signalen.
De Arduino Uno heeft 50k pullup intern, en de Mega heeft 50k intern + 10k op het board. Even rekenen... Wanneer je alleen bij de Master pullup weerstanden van 2k2 of 2k7 (van SDA naar 5V en van SCL naar 5V) zet, dat zit je rond het optimum.

De code voor een Arduino als een I2C Slave vereist een specifieke manier om dat te doen. Dat is dus eigenlijk voor iemand die al 'c' en 'c++' kent en ook de Arduino al kent.

De oude vertrouwde RS-485 bus kan gebruikt worden voor grotere afstanden. Dat is een seriële bus, dus heb je seriële poorten nodig. De Arduino Mega 2560 heeft nog drie vrij seriële poorten over. Als je de Arduino Uno vervangt door Arduino Leonardo, dan heb je ook de beschikking over een vrije seriële poort. Dan zul je ook nog zelf een heel protocol moeten gaan schrijven.

Misschien is het nodig om de I2C kloksnelheid terug te brengen naar 50kHz (i.p.v. de standaard 100kHz).
De Wire library wacht totdat een I2C functie klaar is met versturen of ontvangen.
Stel: 50kHz, twee Slaves, elk 6 byte voor uitgangen en 6 byte voor ingangen. Dan kost het totaal zo'n 5ms voor een volledige update van alle gegevens.

Terug naar Arduino software

Wie is er online?

Gebruikers in dit forum: Geen geregistreerde gebruikers en 13 gasten