středa 7. ledna 2009

Komunikace po RS485

Konečně se mi podařilo zprovoznit komunikaci mezi moduly. Pro tento účel jsem navrhl jednoduchý komunikační protokol, respektive knihovnu. Zatím funguje v zjednodušené verzi. Mám totiž hotové jen dva moduly, takže mě ještě nic nedonutilo zprovoznit MPCM (Multi-processor Communication mode).

Takto (zatím) vypadá obsluha komunikace v řídicím (master) modulu:

while (1) {

// vytvoření a inicializace pole dat
uint8_t data[30], i;
for(i=0; i<30;i++) data[i] = i*2;

// vytvoření paketu
makePacket(&comm_state.op,&data,30,P_ECHO,10);

// zakázání příjmu
CLEARBIT(UCSR1B,RXEN1);

// přepnutí na vysílání
C_SETBIT(RS485_SEND);

// poslání prvního bytu - ostatní se vysílají automaticky
sendFirstByte(&UDR1,&comm_state);

// čekání na odeslání paketu
while(comm_state.send_state != PS_READY);

// přepnutí na příjem
C_CLEARBIT(RS485_SEND);

// povolení příjmu
SETBIT(UCSR1B,RXEN1);

comm_state.send_state=PS_READY;

// čekání na odpověď
while(comm_state.receive_state != PR_PACKET_RECEIVED && comm_state.receive_state!=PR_TIMEOUT);
comm_state.receive_state = PR_READY;

}

Nejprve se vytvoří pole dat o 30 prvcích. To se potom uloží do paketu, odešle a čeká se na příjem paketu, nebo na timeout. Na lcd se vypisují statistiky komunikace: počet odeslaných paketů, přijatých, paketů s vadných kontrolním součtem, počet chyb rámce, počet timeoutů. Za pomocí těchto údajů jsem provedl test - viz níže. Knihovna bude po doplnění o MPCM ke stažení na stránkách projektu.

Takto vypadá obsluha komunikace v podřízeném (slave) modulu:

while(1) {

// přepnutí na příjem
C_CLEARBIT(RS485_SEND);

// čekání na příjem paketu
while(comm_state.receive_state != PR_PACKET_RECEIVED);

// rozhodnutí podle typu paketu
switch(comm_state.ip.packet_type) {

case P_ECHO: {

C_FLIPBIT(LED);

// vytvoření ECHO paketu
makePacket(&comm_state.op,&comm_state.ip.data,comm_state.ip.len,P_ECHO,0);

// zakázání příjmu
CLEARBIT(UCSRB,RXEN);

// přepnutí na odesílání
C_SETBIT(RS485_SEND);

// odeslání prvního bytu
sendFirstByte(&UDR,&comm_state);

// čekání na odeslání paketu
while(comm_state.send_state != PS_READY);

// přepnutí na příjem
C_CLEARBIT(RS485_SEND);

// povolení příjmu
SETBIT(UCSRB,RXEN);

comm_state.send_state = PS_READY;

} break;

} // switch

comm_state.receive_state = PR_READY;

}

Řídicí modul zatím umí jen posílat a přijímat pakety, bez toho, aby s nimi cokoliv dělal. Slave modul zase reaguje jen na pakety P_ECHO, které pošle zpět. Pro test mi to ale stačilo.
























rychlost přenosuúspěšnost echa [%]Chybovost příjmu [%]
96007514
144007913
38400895
76800972
250000980

Nastavoval jsem různé rychlosti přenosu a měřil úspěšnost echa (přijatých/odeslaných*100) a chybovost příjmu (chyba crc/přijatých*100). Kupodivu se výsledky zlepšovaly se zvyšující se rychlostí. Čekal jsem spíše opačný výsledek.

Graf úspěšnosti echa:


Graf chybovosti příjmu:

4 komentáře:

  1. Ty grafy závislostí jsou hodně zajímavé, obyčejným selským rozumem bych čekal naopak nárust chybovosti :-)

    OdpovědětVymazat
  2. Jo, to já taky. Abych řekl pravdu, tak fakt nevím, proč to tak vyšlo. Chyba v programu by na to snad neměla mít vliv. Nicméně dělal jsem v kódu nějaké změny a tak zkusím měření zopakovat. Nicméně teď používám 250kbps a komunikace je naprosto bezchybná.

    OdpovědětVymazat
  3. Trochu se mi to nezdá. Někde bude asi problém. Používám na svých robotech stejnou komunikaci po RS485 a funguje to na jakékoliv rychlosti absolutně bez problémů. Na podzimní Robotour robot najezdil cca 10km (asi 4 hodiny) a v logu nebyl ani jeden výpadek komunikace. Zkusil bych to ještě překontrolovat. Takové náhodné chyby se dovedou vymstít v nejnevhodnější dobu.

    OdpovědětVymazat
  4. Zdravím. Asi byl vážně nějaký problém v softwaru. Bohužel jsem se ještě nedostal k tomu, abych opět vyzkoušel komunikaci na nějaké nižší rychlosti, ale na 250kbps to chodí naprosto bezchybně.

    OdpovědětVymazat