PDA

View Full Version : Help guys...communication issue, I think?



kevlar129bp
- 12th October 2013, 05:11
Hello all,

I'm back here posting due to some massive brain fry over my latest project. Here's what I've got:

PC to a Trendnet TU-S9 (USB to RS232 adapter).
From there, into a custom board with a MAX232 to a MAX3081 RS422 chip (Rx+, Rx-,Tx+,Tx-,Ground).
From there, into board(s) that have a MAX3081, which are then tied into the USARTs of the MCUs.
All of the RS422 wiring is over Cat5e with RJ-45 connectors.
Each board has 2 RJ-45 connectors, wired in parallel, to facilitate a daisy chain configuration.

At present, I have 2 boards: 1 that does ADC stuff (PIC16F1936), and the other that does strictly outputs (PIC16F887).

I think that gets the hardware out of the way.

As far as the software, I'm running them with Term.exe @ 57600,8,N,1.
Here's where it gets weird :confused:
When I plug either board in by itself, all is good (receive from the PC and transmit back from the MCU)
When I plug both boards in (daisy chained), both boards receive from the PC just fine but
I can only receive a response back from my 887 output board, although I can send commands just fine to both
of them. I verify this by manually switching some outputs on the 1936 board. When I expect a serial response
from the 1936 board, all I seem to receive at the terminal is a carriage return (or so it appears).
I hope that isn't confusing :smile:
Here's the code for the 2 different boards, so maybe one of you fine folks can determine where I'm going astray.
Of course, the following code is clipped for irrelevant content.

Thanks for taking a peek at the code, and for the help.
Chris

*As you will see, I even tried to enable the serial transmit only when it is needed. That got me to the point
of the 887 board responding back to the PC. Previous to that, neither boards would respond.:confused:


1936 code:


'***********************************SERIAL INTERRUPT**************************************
RS232in:
@ INT_DISABLE IOC_INT
@ INT_DISABLE TMR1_INT
@ INT_DISABLE RX_INT
low RxLED 'Rx LED ON
HSERIN 300,Stall,[DEC3 SerialIn]
If SerialIn = 255 then gosub GoodQualifier
Stall:
while PIR1.5
SerialIn = RCREG
wend
high RxLED 'Rx LED OFF
@ INT_ENABLE IOC_INT
@ INT_ENABLE TMR1_INT
@ INT_ENABLE RX_INT
@ INT_RETURN
'************************************************* ****************************************

GoodQualifier:

T1CON = timeroff 'Timer Off

hserin 300,Junk,[str SerBuff\10\"~"]

'Parse ASCII CmdPrefix
CmdPrefix = SerBuff[0]

'Convert Address from ASCII to DECIMAL
for x = 1 to 3
SerBuff[x] = (SerBuff[x]-"0")
next
'Build the DECIMAL address
CmdAddress = SerBuff[1] * 100
CmdAddress = CmdAddress + SerBuff[2] * 10
CmdAddress = CmdAddress + SerBuff[3]

if CmdPrefix = "A" then
'-------------------------Address Module----------------------------
Address = CmdAddress
write 0,Address
LOW TxLED
TXSTA = 36
HSEROUT [CmdPrefix,DEC3 Address,13]
WHILE PIR1.4 = 0 : WEND
TXSTA = 4
HIGH TxLED
read 0,Address
'------------------------------------------------------------------
endif
'--------------------Address Mismatch--------------------------
if CmdAddress = Address then

TXSTA = 36 'Turn ON transmitter

'-------------------------Command Module----------------------------
if CmdPrefix = "O" then 'Oaaaoo (6)
'Convert CmdOutput from ASCII to DECIMAL
for x = 4 to 5
SerBuff[x] = (SerBuff[x]-"0")
next
'Build the DECIMAL address
CmdOutput = SerBuff[4] * 10
CmdOutput = CmdOutput + SerBuff[5]
select case CmdOutput
case 10
OUT1 = 0
case 20
OUT2 = 0
case 30
OUT3 = 0
case 11
OUT1 = 1
case 21
OUT2 = 1
case 31
OUT3 = 1
CASE ELSE
goto Junk
END SELECT
HSEROUT [CmdPrefix,DEC3 Address,dec2 CmdOutput,13]
endif

if CmdPrefix = "Q" then 'Qaaa (4)
low TxLED 'Tx LED ON
HSEROUT [CmdPrefix,DEC3 Address, _
",",DEC VOLTS,",",DEC TempF,",",DEC Amps, _
",",dec PORTA.1,",",DEC PORTA.0,",",DEC PORTA.4,13]
high TxLED 'Tx LED OFF
endif

if CmdPrefix = "P" then 'Paaa (4)
low TxLED 'Tx LED ON
HSEROUT [CmdPrefix,DEC3 Address,DEC1 ModType,13]
high TxLED 'Tx LED OFF
endif

if CmdPrefix = "M" then 'Maaallvvv (9)
'10=LowVolts, 11=HighVolts, 12=LowTemp, 13=HighTemp, 14=LowCurrent, 15=HighCurrent
'M001 Board Address
' 10 EEProm Location (Low Trip)
' 255 Low Trip Value

'Convert eepromloc from ASCII to DECIMAL Maaaeevvv
for x = 4 to 5
SerBuff[x] = (SerBuff[x]-"0")
next
'Build the DECIMAL
eepromloc = SerBuff[4] * 10
eepromloc = eepromloc + SerBuff[5]

if (eepromloc < 10) OR (eepromloc > 15) then
goto Junk
endif

'Convert tripval from ASCII to DECIMAL
for x = 6 to 8
SerBuff[x] = (SerBuff[x]-"0")
next
'Build the DECIMAL
tripval = SerBuff[6] * 100
tripval = tripval + SerBuff[7] * 10
tripval = tripval + SerBuff[8]

write eepromloc,tripval
HSEROUT [CmdPrefix,DEC3 Address,dec2 eepromloc,dec3 tripval,13]
ReReadVals = 1
endif

if CmdPrefix = "C" then '(CONTROL) 'Caaa1
ManualControl = (SerBuff[4]-"0")
HSEROUT [CmdPrefix,DEC3 Address,dec1 ManualControl,13]
endif

WHILE PIR1.4 = 0 : WEND 'If we're still transmitting, wait here
TXSTA = 4 'Turn OFF transmitter

endif
'--------------------------------------------------------------
Junk:
for x = 0 to 9
SerBuff[x] = " "
next
T1CON = timeron 'Timer ON
return


887 code:


'*********************************SERIAL INPUT**********************************
RS232in:
@ INT_DISABLE RX_INT
@ INT_DISABLE TMR1_INT
HSERIN 300,Stall, [DEC3 SerialIn]
If SerialIn = 255 then gosub GoodQualifier
Stall:
while PIR1.5
SerialIn = RCREG
wend
@ INT_ENABLE TMR1_INT
@ INT_ENABLE RX_INT
@ INT_RETURN
'************************************************* ******************************

GoodQualifier:

T1CON = timeroff

hserin 300,Junk,[str SerBuff\10\"~"]

'Parse ASCII CmdPrefix
CmdPrefix = SerBuff[0]

'Convert Address from ASCII to DECIMAL
for x = 1 to 3
SerBuff[x] = (SerBuff[x]-"0")
next
'Build the DECIMAL address
CmdAddress = SerBuff[1] * 100
CmdAddress = CmdAddress + SerBuff[2] * 10
CmdAddress = CmdAddress + SerBuff[3]

'-------------------------Address Module----------------------------
'Aaaa (4)
IF CmdPrefix = "A" THEN
Address = CmdAddress
write 0,Address
TXSTA = 36
HSEROUT [CmdPrefix,DEC3 Address,13]
WHILE PIR1.4 = 0 : WEND
TXSTA = 4
read 0,Address
newaddr = 1
endif
'------------------------------------------------------------------
'--------------------Address Mismatch--------------------------
if CmdAddress = Address then

TXSTA = 36 'Turn ON transmitter

'-------------------------Command Module----------------------------
'Qaaa (4)
IF CmdPrefix = "Q" THEN
HSEROUT [CmdPrefix,DEC3 Address, _
DEC PORTA.4,DEC PORTA.3,DEC PORTA.5,DEC PORTA.2,_
DEC PORTE.0,DEC PORTA.1,DEC PORTC.1,DEC PORTC.0,_
DEC PORTC.2,DEC PORTE.2,DEC PORTC.3,DEC PORTE.1,_
DEC PORTD.2,DEC PORTD.1,DEC PORTD.3,DEC PORTD.0,_
DEC PORTC.4,DEC PORTC.5,DEC PORTD.7,DEC PORTD.6,_
DEC PORTB.0,DEC PORTD.5,DEC PORTB.1,DEC PORTD.4,13]
endif

'Paaa (4)
if CmdPrefix = "P" then '(PING) '$BxxxQ
HSEROUT [CmdPrefix,DEC3 Address,DEC1 ModType,13]
endif

'Oaaarrs (7)
IF CmdPrefix = "O" THEN
'Convert Relay from ASCII to DECIMAL Oaaaoo
for x = 4 to 5
SerBuff[x] = (SerBuff[x]-"0")
next
'Build the DECIMAL address
Relay = SerBuff[4] * 10
Relay = Relay + SerBuff[5]
Stat = (SerBuff[6]-"0")

if Relay = 1 then
if stat = 0 then
OUT1 = 0
else
OUT1 = 1
endif
endif
if Relay = 2 then
if stat = 0 then
OUT2 = 0
else
OUT2 = 1
endif
endif
if Relay = 3 then
if stat = 0 then
OUT3 = 0
else
OUT3 = 1
endif
endif
if Relay = 4 then
if stat = 0 then
OUT4 = 0
else
OUT4 = 1
endif
endif
if Relay = 5 then
if stat = 0 then
OUT5 = 0
else
OUT5 = 1
endif
endif
if Relay = 6 then
if stat = 0 then
OUT6 = 0
else
OUT6 = 1
endif
endif
if Relay = 7 then
if stat = 0 then
OUT7 = 0
else
OUT7 = 1
endif
endif
if Relay = 8 then
if stat = 0 then
OUT8 = 0
else
OUT8 = 1
endif
endif
if Relay = 9 then
if stat = 0 then
OUT9 = 0
else
OUT9 = 1
endif
endif
if Relay = 10 then
if stat = 0 then
OUT10 = 0
else
OUT10 = 1
endif
endif
if Relay = 11 then
if stat = 0 then
OUT11 = 0
else
OUT11 = 1
endif
endif
if Relay = 12 then
if stat = 0 then
OUT12 = 0
else
OUT12 = 1
endif
endif
if Relay = 13 then
if stat = 0 then
OUT13 = 0
else
OUT13 = 1
endif
endif
if Relay = 14 then
if stat = 0 then
OUT14 = 0
else
OUT14 = 1
endif
endif
if Relay = 15 then
if stat = 0 then
OUT15 = 0
else
OUT15 = 1
endif
endif
if Relay = 16 then
if stat = 0 then
OUT16 = 0
else
OUT16 = 1
endif
endif
if Relay = 17 then
if stat = 0 then
OUT17 = 0
else
OUT17 = 1
endif
endif
if Relay = 18 then
if stat = 0 then
OUT18 = 0
else
OUT18 = 1
endif
endif
if Relay = 19 then
if stat = 0 then
OUT19 = 0
else
OUT19 = 1
endif
endif
if Relay = 20 then
if stat = 0 then
OUT20 = 0
else
OUT20 = 1
endif
endif
if Relay = 21 then
if stat = 0 then
OUT21 = 0
else
OUT21 = 1
endif
endif
if Relay = 22 then
if stat = 0 then
OUT22 = 0
else
OUT22 = 1
endif
endif
if Relay = 23 then
if stat = 0 then
OUT23 = 0
else
OUT23 = 1
endif
endif
if Relay = 24 then
if stat = 0 then
OUT24 = 0
else
OUT24 = 1
endif
endif
HSEROUT [CmdPrefix,DEC3 Address,dec2 Relay,dec Stat,13]
endif

WHILE PIR1.4 = 0 : WEND 'If we're still transmitting, wait here
TXSTA = 4 'Turn OFF transmitter

endif
'--------------------------------------------------------------
Junk:
for x = 0 to 9
serbuff[x] = " "
next
T1CON = timeron
return

aratti
- 12th October 2013, 07:17
Read this application note. It should help you to solve the problem.

http://www.analog.com/static/imported-files/application_notes/AN-960.pdf

Cheers

Al

HenrikOlsson
- 12th October 2013, 08:09
Hi,
Yeah, your tranceiver chips doesn't have a way to disable their drivers.
When two or more of those are connected to the same pair of wires they will fight each other. I think you want the MAX3080 - not 3081 - then take your TxLED signal and wire it to the DE-pin (HIGH to enable the driver) so that ONLY the board which is actually going to put data on the bus has its driver enabled, all other boards should have their drivers disabled.

/Henrik.

kevlar129bp
- 12th October 2013, 15:25
Hey Henrik,

Thanks for your reply. I looked at the Analog datasheet and the only thing that jumped out at me was their termination schema. My bus is built exactly like this one: http://datasheets.maximintegrated.com/en/ds/MAX3080-MAX3089.pdf (page 20). Did I miss something in the datasheet, or is the 3081 only intended for point to point comms? :frown: If so, it sure sounds like a board rework is in order huh. bummer.

Thanks again,
Chris

HenrikOlsson
- 12th October 2013, 15:52
Hi Chris,

My bus is built exactly like this one: http://datasheets.maximintegrated.co...80-MAX3089.pdf (page 20)
Yes and no..... The actual bus may be built the same but your tranceiver chips (the MAX3081) doesn't have the DE-pin which you see in the schematic on that page and which you need for multidrop networks so yes, the MAX3081 is basically intended for point-to-point.

If the tranceiver has no way to turn of its driver then it will always drive the bus to one state or the other. Then, when another tranceivers driver is hooked across the same pair of wires and IT too tries to drive the bus to one state or the other there will be a conflict. One tries to drive it high while the other tries to drive it low - for example. On the chips with the DE-pin (Driver Enabled) you can disable the driver outputs all together.

/Henrik.

kevlar129bp
- 12th October 2013, 16:29
Thanks Henrik,

Bummer, I was afraid you were going to tell me that :) I wonder why the 887 board works with both boards on the bus though? That's the part that stumps me. Do you have any insight on that? Just seems that both of them would crash, not just one...

Chris

Demon
- 12th October 2013, 21:19
If you're stuck with those drivers, what if the PIC controls power to the drivers? Do they take time to "boot up"?

Robert

HenrikOlsson
- 13th October 2013, 05:28
Robert,
The chips are tranceivers...if you power them down they won't be able to receive either.
The PIC will never get any queries to send any data because the receiver is powered down, you might as well throw out the tranceiver all together... ;-)

Chris,
Can't say why it appears to work in some situations. Perhaps one driver is slightly "stronger" than the other (don't think so though).

/Henrik.

kevlar129bp
- 13th October 2013, 07:47
Hey guys,

I actually did give the power down thing a thought for a moment, but as Henrik pointed out...1 step forward, two steps back :)

No problem on the mysterious 887 board operation, as I'm reworking the boards now. I do, however, have one more quick question for ya Henrik... I should be ok to still run the MAX3081 on the 232 to 422 master board, correct? My thought is, I shouldn't need to (or wouldn't want to) enable or disable the Rx and Tx lines at the master... Is my thinking correct on that one?

BTW: The new boards will have the MAX3086 on 'em, of course with the sacrifice of my heartbeat led output :frown: Oh well, small price to pay.

Thanks again guys,
Chris

HenrikOlsson
- 13th October 2013, 08:20
Hi Chris,

I should be ok to still run the MAX3081 on the 232 to 422 master board, correct?
Lets stop and think about that for a minute....

Finished thinking?

If ANY one of the drivers on the bus (doesn't matter which one) is enabled it will "occupy" the bus. There can only be ONE enabled driver on the bus at any given time or they will end up fighting each other.

All receivers on all devices shouls be enabled at all times. The transmitter on each device should be enabled when, and only when, that specific device is about to put data onto the bus. If two or more transmitters are enabled at the same time there will be conflicts.

/Henrik.

EDIT: OK, hold on, brainfart on my behalf here. You're running full duplex so please disregard the above. Yes, you can keep the transmitter on the RS232<->RS422 converter enabled all the time. Doh.....

kevlar129bp
- 13th October 2013, 16:52
Cool Henrik,

I have to say that your brainfart wasn't near as big as mine! Doh, I designed, built and stuffed the boards with those 3081's :biggrin: Oh well, ya gotta crack a few eggs to make an omelet right... I'll check back with progress when I get the new boards whipped up.

Thanks a ton,
Chris

Demon
- 13th October 2013, 18:50
Have you read this?

http://www.picbasic.co.uk/forum/showthread.php?t=17282

I was able to have a master PIC talk to multiple slave PICs at 115200. The trick is to have slaves enable usart transmit only when spoken to by the master.

I assigned each slave an ID (used in the data stream). The master would wait for a reply when necessary or keep on working.

A calling-all-slaves ID can be used to have them all do something, but they can't reply.

So no need for any comm IC, just straight PIC to PIC connections.

Robert

kevlar129bp
- 14th October 2013, 00:24
Hey Robert,

I actually did try that trick in my posted code above, but I just revisited it just to make sure and bummer...no love :frown: If you can take a glance at my code above and double check the technique I used, that would be awesome. Heck, maybe I'm not using it correctly?

Thanks again,
Chris

Demon
- 14th October 2013, 00:59
Check the code for slaves in this post:

http://www.picbasic.co.uk/forum/showthread.php?t=17282&p=116809#post116809

That's all I needed to do. Master TX to slave RXs, slave TXs to master RX, I think I had pull-ups at master.

I'm having a hard time with your code (sick, not feeling right).

I'd suggest making a copy of your program and strip everything except USART logic. Then post that stripped code if you have problems.

Keep it simple; talk to slave 1, wait for reply, talk to slave 2, wait for reply.

You can also use a MAX232 and listen in with your PC and see exactly what is sent. That helped me a lot.

Robert

HenrikOlsson
- 14th October 2013, 07:28
Chris,
You can't use Roberts aproach since you DO have the tranceiver chip in between the PIC and the bus. It doesn't matter if you turn of the USART TX in the PIC, the driver in the tranceiver chip will still be enabled and will still "hold" the line.

Since Robert does NOT have any tranceiver chip in between the PIC and the "bus" turning of the USART TX (ie making its pin high impendence) is effectively the same as what you need to do with your tranceiver chip (turning off the transmitter that is).

If your application invloves any sort of distances and/or deployement in the "real world" I'd definitely stick with some kind of bus like you have now. I wouldn't want to expose the PICs inputs/outputs directly to tens or hundreds of metres wires acting as antennas. Of course YMMV.

/Henrik.

kevlar129bp
- 15th October 2013, 02:49
Thanks guys,

I have succumbed to the fact of the board rework. Bummer for sure. 1 more question...I have looked at so many datasheets for transceivers that I have lost track. On some datasheets it shows the termination resistor on both the Tx and Rx endpoints, and on others it shows it only on the Rx endpoints? I suppose that was more of a statement rather than a question, but you guys get where I'm going with it...:smile: I've got my Rx endpoints terminated now...Am I good with that? Don't want to rework twice.

Thanks guys,
Chris

***Little deja vu here http://www.plcforum.it/f/topic/79753-rs422-multidrop-rs422-multidrop/ :frown:

HenrikOlsson
- 15th October 2013, 19:13
Hi Chris,
There's a section specifically covering bus termination in the .pdf linked to earlier, it covers the differences.

/Henrik.