RS485, MAX485 furcsa nullák

Processing/Wiring (illetve C) nyelvű programozási fogások, tippek. (AVR-Duino, Arduino, EthDuino, Diecimila, Severino, Nano, LilyPad)
Válasz küldése
Avatar
sytex
DrótVégénSzéndarab
Hozzászólások: 36
Csatlakozott: 2010. június 10. csütörtök, 6:00

RS485, MAX485 furcsa nullák

Hozzászólás Szerző: sytex »

Sziasztok!

Először is elnézést ha rossz topikba nyitottam, de nem találtam hardverspecifikus fórumot, majd robert átteszi a megfelelő helyére ha itt nem jó.
A képeken az angol feliratért elnézést, de próbálkoztam a nagy arduino forumon is, de feladtam a harcot mikor folyton a forráskódomat szerették volna elkérni mikor hardver a problémám alapja.

Szóval:
RS485-ön szeretnék MODBUS kommunikációt megvalósítani. Környezet: 1.0.6. RS485 illesztés ezzel:
Kép
Kép

A "hálózat"
Master: Mega2560, ethernet shield, RS485: Serial1
Slave: Nano, RS485: SoftwareSerial

Amit tapasztalok, SLAVE oldalon kiiratom a vett frame-ket:
Kép

Logikai analizerrel nézve:
Kép

Kicsit bezoomolva:
Kép

A MODBUS specifikáció miatt, az egyes frame-ek adása után a MAX485 DE lábát még 3.5 karakter hosszúságig adásban kell tartani. Viszont ha a buszon bármely MAX485 DE lába aktív akkor az összes RO (ReceiverOutput) láb magas állapotot vesz fel. Ezek az RO lábak vannak összekötve a kontrollerek RX lábaival, és erre a magas állapotra a serial.available true-t ad vissza, és nullákat olvas be a buszról.
A soros monitoron látszódó szimpla nullák oka pedig szerintem az, hogy amikor a slave ad, akkor az ő RX lába is magas állapotra kerül a MAX485 által, az adást befejezi, majd a 3,5 karakter "kitartás" miatt, nulla (néha nullák) kerülnek a vételi bufferbe, a loop következő lépcsőjében pedig ezt visszaolvassuk, erről kép:
Kép

Mint látszik oda-vissza megvannak ezek a plusz nullák, mindkét eszközön, ezért kizárnám, hogy a SoftwareSerial okozza a galibát, hisz a megán hardveres soros portot használok.
A kódban semmi trükk nincs, csak annyi hogy:
MASTER:

Kód: Egész kijelölése

void waiting_for_reply()
{
	if ((*ModbusPort).available()) // is there something to check?
	{
		unsigned char overflowFlag = 0;
		buffer = 0;
		while ((*ModbusPort).available())
		{
			// The maximum number of bytes is limited to the serial buffer size 
      // of BUFFER_SIZE. If more bytes is received than the BUFFER_SIZE the 
      // overflow flag will be set and the serial buffer will be read until
      // all the data is cleared from the receive buffer, while the slave is 
      // still responding.
			if (overflowFlag) 
				(*ModbusPort).read();
			else
			{
				if (buffer == BUFFER_SIZE)
					overflowFlag = 1;
			
				frame[buffer] = (*ModbusPort).read();
				buffer++;
			}
			// This is not 100% correct but it will suffice.
			// worst case scenario is if more than one character time expires
			// while reading from the buffer then the buffer is most likely empty
			// If there are more bytes after such a delay it is not supposed to
			// be received and thus will force a frame_error.
			delayMicroseconds(T1_5); // inter character time out
		}
		  
		// The minimum buffer size from a slave can be an exception response of
    // 5 bytes. If the buffer was partially filled set a frame_error.
		// The maximum number of bytes in a modbus packet is 256 bytes.
		// The serial buffer limits this to 64 bytes.
	
		if ((buffer < 5) || overflowFlag)
			processError();       
      
		// Modbus over serial line datasheet states that if an unexpected slave 
    // responded the master must do nothing and continue with the time out.
		// This seems silly cause if an incorrect slave responded you would want to
    // have a quick turnaround and poll the right one again. If an unexpected 
    // slave responded it will most likely be a frame error in any event
		else if (frame[0] != packet->id) // check id returned
			processError();
		else
			processReply();
	}
	else if ((millis() - delayStart) > timeout) // check timeout
	{
		processError();
		state = IDLE; //state change, override processError() state
	}
}
SLAVE:

Kód: Egész kijelölése

  while (mySerial.available())
  {
    // The maximum number of bytes is limited to the serial buffer size of 128 bytes
    // If more bytes is received than the BUFFER_SIZE the overflow flag will be set and the 
    // serial buffer will be red untill all the data is cleared from the receive buffer.
    if (overflow) 
      mySerial.read();
    else
    {
      if (buffer == BUFFER_SIZE)
	  {
        overflow = 1;
	  }	
      frame[buffer] = mySerial.read();
      buffer++;
    }
    delayMicroseconds(T1_5); // inter character time out
  }
Tehát lényegében annyi, hogy ha valami vár a soros porton akkor olvassuk ki és tegyük bele a frame[] tömbbe.
A serial monitoron látszódó kép a beérkezés után egyből kiiratott frame[] tömb.

A delayMicroseconds(T1_5) pedig szintén a MODBUS szabvány miatti 1,5 karakter szünet a karakterek között miatt kell.

Valaki futott már bele ilyen hibába? Ötlet, hogy hogyan lehetne ezt az "RX láb fel van húzva amikor adás van a buszon" dolgot kiküszöbölni?
Azt már próbáltam, hogy levettem a MAX485 panelről a felhúzóellenállást, és lehúztam 1K-val, nem segített, a MAX485 erősebb volt :-)
Avatar
Robert
Elektronbűvölő
Hozzászólások: 10213
Csatlakozott: 2005. december 9. péntek, 7:00

Re: RS485, MAX485 furcsa nullák

Hozzászólás Szerző: Robert »

Az A, B össze van kötve, nem szakadt valamelyik?
Sima soros átvitel megy?

A modulon a lezárások hibásak (gyárilag!):
- 120Ohm lezárás (ez OK).
- 2x 20k szétfeszítő (na ez a hibás).

Próbáld meg simán, hogy sorosan adsz, veszel az ASCII kódtáblával.
Monitorozd mindkét oldalon a DE/RE lábakat is. Látsz benne majd csuda dolgokat! (pl. Modbusz protokolod hibás)
Igaz a DE/RE is be van kötve? És összekötve?
Avatar
sytex
DrótVégénSzéndarab
Hozzászólások: 36
Csatlakozott: 2010. június 10. csütörtök, 6:00

Re: RS485, MAX485 furcsa nullák

Hozzászólás Szerző: sytex »

Szia!

A-B összekötve (hisz akkor ez az adat se menne át).

Mennyi szétfeszítés kell neki?
Amúgy a 120ohm-ot minden eszközhöz be kell tenni (ha több eszkör kerül majd a buszra), vagy csak a két szélsőhöz?

DE/!RE lábak összekötve egymással (persze csak az egyazon modulon lévők :) ), és vezérli is őket az adott kontroller.
Kötöttem azt is analizerre (screenshot nincs róla), és ott láttam, hogy amig DE magas (bármelyik), addig mindkét MAX485 RO is magas (tehát a kontrollerek RX lábát magasan tartja), mikrosec-re pontosan.
Miből gondolod, hogy a modbus protokollom hibás, mit látsz benne amit én nem :) ?

Tehát a kommunikáció átmegy, sőt ha módosítom a programot, hogy ne foglalkozzon ezekkel a plusz megjelenő "lezáró" nullákkal akkor kommunikál is egymással. De akkor is zavar!
Főleg, hogy nem csak arduino alapú Slave-ek lesznek, tehát a Masteren nem mondhatom, hogy buffer = buffer-1 azt' csókolom...
Avatar
Robert
Elektronbűvölő
Hozzászólások: 10213
Csatlakozott: 2005. december 9. péntek, 7:00

Re: RS485, MAX485 furcsa nullák

Hozzászólás Szerző: Robert »

A 120 R lezárás csak a 2 végen lehet! Közben nem!
Szétfeszítés csak az egyik végen (célszerűen a Master). A szétfeszítés: 680R - 120R - 680R.

Ha túl gyorsan kapcsol a MAX IC, akkor nem megy ki az utolsó bit/nem fogadja az első bitet. Sőt, az Arduino belül buffereni a sorosportot : a bufferbe beérkezés alatt kapcsol a MAX, nem a feldolgozás végén!

Az analizátort tedd:
- Tx/Rx lábak,
- DE/RE lábak

Ezt az adó és a vevő oldalon is tedd meg!
Én beraknék még egy plusz 485-s eszközt, állandó vételen. Ennek Rx lábán is legyen ott az analizátor.
Válasz küldése