|
|
View previous topic :: View next topic |
Author |
Message |
WILLEY_85
Joined: 06 Jul 2009 Posts: 3
|
rs485 communication problem |
Posted: Tue Aug 11, 2009 1:01 am |
|
|
Hi all,
I am new to PIC. I currently want to build a small system (school project). In this project, I would like to make 2 microcontrollers communicate with each other via rs485. However, the method I used is not working. Therefore, I hope the experts here would help me to solve my problems.
The system is:
1. using ccs provided rs485.c driver
2. using sn75176BP
3. using PIC18F4620
My question is -- is the built-in #use rs232 capable to interpret the signal sent by sn75176B? Because the PIC keep on receiving rubbish from the data line. Any suggestion? Thanks |
|
|
Ttelmah Guest
|
|
Posted: Tue Aug 11, 2009 4:36 am |
|
|
Hopefully, you mean you have a pair of 75176's.
The sequence should be:
TTL serial (PIC)
75176 to RS485
RS485 back to TTL serial with another 75176
TTL serial into PIC.
You may though be experiencing the other common problem with RS485. Line biasing.
If you turn off the transmitter, when not sending (as is required if you are intending to use the line bidirecionally), what happens to the bus?. What generally happens, is that it floats, and you receive garbage. To get round this, you need to ensure that your line termination, also 'biases' the bus to the 'off' state. So, instead of terminating the bus with 100R at each end, you use a little 'network', comprising a 1.2KR to +5v, to the first line (A), a 120R between the lines (A-B), and a 1.2KR to the GND. This gives the required 100R (electrically the three resistors are seen as in parallel), but also applies a small voltage to the bus to keep it from floating.
Some RS485 line receivers, are designed to ensure that an 'undriven' bus, gives the required 5v out on the TTL connection. Also some companies do line terminators that apply this same bias.
Without this bias, your chips will continually receive garbage when not sending, and the system is not likely to work....
Best Wishes |
|
|
mkuang
Joined: 14 Dec 2007 Posts: 257
|
|
Posted: Tue Aug 11, 2009 8:30 am |
|
|
You also need to make sure you are enabling the transmitter and receiver at the proper time on the 75176. The receiver is active low and the transmitter is active high. Your PIC has to control this device properly when you when to transmit and receive. |
|
|
WILLEY_85
Joined: 06 Jul 2009 Posts: 3
|
|
Posted: Tue Aug 11, 2009 10:52 pm |
|
|
Thanks for the immediate reply.
I used a pair of sn75176 to transmit signal.
Quote: | If you turn off the transmitter, when not sending (as is required if you are intending to use the line bidirecionally), what happens to the bus?. |
I have tried this, when turned of the transmitter, the receiver will received 0 all the time. Is this mean the communication is free of noise?
I will try to add in the resistor.
But, I have another question.
I have connected the transmitter to receiver (via rs485) and then the receiver will display the input to computer (rs232). This is for me to see what is going on the the rs485 communication. The coding is as follow
For transmitter
Code: |
#include <18F4620.h>
#device *=16
#fuses HS, NOWDT, NOLVP, NOBROWNOUT, NOPROTECT, PUT
#use delay(clock=4000000)
// Define the destination's RS485 ID
#define RS485_ID 0x10
#define RS485_RX_PIN pin_a4 //define the pin connection
#define RS485_TX_PIN pin_c5
#define RS485_Enable_pin pin_b5
#define RS485_Rx_Enable pin_b5
#use rs232(baud=9600, xmit=RS485_TX_PIN, rcv=RS485_RX_PIN, enable=RS485_ENABLE_PIN, force_sw, errors, stream=RS485)
#use rs232(baud=9600, xmit=RS485_TX_PIN, rcv=RS485_RX_PIN, enable=RS485_ENABLE_PIN, force_sw, multi_master, errors, stream=RS485_CD)
#define RCV_OFF () {disable_interrupts(INT_EXT);}
void main ()
{
int i,x;
char value;
while(1)
{
fputs("~021", RS485_CD); // send the string to rs485
fputs("#020+08.000", RS485_CD);
}
}
|
for receiver
Code: |
#include <18F4620.h>
#device *=16
#fuses HS, NOWDT, NOLVP, NOBROWNOUT, NOPROTECT, PUT
#use delay(clock=4000000)
// Define the destination's RS485 ID
#define RS485_ID 0x11
#define RS485_RX_PIN pin_a4 //define the pin connection
#define RS485_TX_PIN pin_c5
#define RS485_Enable_pin pin_b5
#define RS485_Rx_Enable pin_b5
#use rs232(baud=9600, xmit=RS485_TX_PIN, rcv=RS485_RX_PIN, enable=RS485_ENABLE_PIN, force_sw, errors, stream=RS485)
#define RCV_OFF () {disable_interrupts(INT_EXT);}
void main ()
{
char value[5];
int i=0;
int x;
set_tris_A(0xff);
#use rs232 (baud=9600, xmit=pin_c6, parity=N, rcv=pin_c7,bits=8)
putc('\n'); // put character on PC
puts("waiting ");
putc('\n');
while(1)
{
while(kbhit(rs485)) // when a character is available
{
value[i]= fgetc(rs485); // receive character from rs485
#use rs232 (baud=9600, xmit=pin_c6, parity=N, rcv=pin_c7,bits=8)
printf(" %c the value \n",value[i]); // print to PC
i++;
}
#use rs232 (baud=9600, xmit=pin_c6, parity=N, rcv=pin_c7,bits=8)
printf(" ------------");
}
}
|
Above is my simple code. My problem face in the system is:
1. When transmitter is off. The PC will display <0>.
2. When I transmit the data. The PC will display garbage.
Hope this may give you an idea what i am facing.
For enabling the transmitter and receiver. I think the #use rs232 will push the pin high to transmit. Is it anything wrong with my code? Or is it just because of noise? |
|
|
arunb
Joined: 08 Sep 2003 Posts: 492 Location: India
|
RE: |
Posted: Wed Aug 12, 2009 1:13 am |
|
|
Why don't you use hardware usart instead of software??? |
|
|
mkuang
Joined: 14 Dec 2007 Posts: 257
|
|
Posted: Wed Aug 12, 2009 8:38 am |
|
|
Sorry, I didn't see the ENABLE option before in your #use rs232 statements.
Those are not simple test programs, they are messy to say the least. You should not declare a #use rs232 statement inside the main loop multiple times like that. Actually you should not declare it anywhere but the top of the program.
I recommend you take arunb's advice and use hardware UART to keep things as simple as possible.
One more thing about RS485 transceiver chips, like anything else you get what you pay for. I would pay more for something decent like a MAX487 which work splendidly without any need for any bias resistors. |
|
|
WILLEY_85
Joined: 06 Jul 2009 Posts: 3
|
|
Posted: Thu Aug 13, 2009 5:32 am |
|
|
Thanks for the advice. That is really a good suggestion to use hardware uart. Now, after some testing, the problem is really due to the line terminator. Thanks. |
|
|
SherpaDoug
Joined: 07 Sep 2003 Posts: 1640 Location: Cape Cod Mass USA
|
|
Posted: Thu Aug 13, 2009 7:16 am |
|
|
WILLEY_85 wrote: |
Quote: | If you turn off the transmitter, when not sending (as is required if you are intending to use the line bidirecionally), what happens to the bus?. |
I have tried this, when turned of the transmitter, the receiver will received 0 all the time. Is this mean the communication is free of noise?
|
This sounds like when the line is idle (transmitter off) it sits at Start bit level (data 0). It should sit at Stop bit level and a getc() should wait forever. You should have a string of Stop bits, until data is sent when you get a Start bit, 8 data bits, and one or more Stop bits till the next byte is ready (which could be milliseconds or months).
The idle state is best set by the terminating resistors. Some manufacturers chips interpret 0.0V as a valid Stop bit, but that is NOT in the 485 spec. _________________ The search for better is endless. Instead simply find very good and get the job done. |
|
|
a3ka2000
Joined: 26 Feb 2010 Posts: 11
|
Re: RE: |
Posted: Thu Mar 11, 2010 11:07 pm |
|
|
arunb wrote: | Why don't you use hardware usart instead of software??? |
Hi hi, is there any reason to use hardware USART? I'm working with RS485 from normal I/O pins of PIC16F84A (simple primitive PIC). It doesn't have dedicated RS485 pins.
I'm facing a problem actually. If I connect more than 2 devices (with PIC on board) to the master, I somehow experienced intermittent when I execute "printf" statement from the PIC back to the PC.
I guarantee that the device is working one by one. No issue on hardware assignment, etc. But I doubt whether need to put 120 ohms resistor, but my cable length is less than 2 m. |
|
|
arunb
Joined: 08 Sep 2003 Posts: 492 Location: India
|
RE: |
Posted: Fri Mar 12, 2010 1:15 am |
|
|
With a dedicated USART port you can make use of interrupts, this makes the software more efficient.
For example the RDA interrupt can be enabled to receive data.
thanks
arunb |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
Re: RE: |
Posted: Fri Mar 12, 2010 8:05 am |
|
|
a3ka2000 wrote: | arunb wrote: | Why don't you use hardware usart instead of software??? |
Hi hi, is there any reason to use hardware USART? I'm working with RS485 from normal I/O pins of PIC16F84A (simple primitive PIC). It doesn't have dedicated RS485 pins.
I'm facing a problem actually. If I connect more than 2 devices (with PIC on board) to the master, I somehow experienced intermittent when I execute "printf" statement from the PIC back to the PC.
I guarantee that the device is working one by one. No issue on hardware assignment, etc. But I doubt whether need to put 120 ohms resistor, but my cable length is less than 2 m. |
You don't need termination assuming your data rate is reasonably low.
The 'rule of thumb', is that termination is not needed, if the propogation delay is less than 0.5 bit time. At low rates like 9600bps, you don't even need termination really out at lengths like a mile!....
However you will still need biasing.
This is a 'key' difference between RS232, and RS485. On RS232, a line floating at 0v, is defined as giving the 'idle state. On RS485, a signal below +/-200mV, will (normally - some receiver chips deliberately break this to avoid the problem....), leave the receiver giving the last bit value received.
With an unterminated network, with only a few nodes, something like 10KR, from signal A to ground, and the same from signal B to +5v, will be comfortably enough.
It is difficult to know what your problem may be, since you don't really describe the network well enough. PC is master?. It addresses slaves?. They monitor the line looking for what?. Are you sure your data format cannot contain a devices address?.
Best Wishes |
|
|
a3ka2000
Joined: 26 Feb 2010 Posts: 11
|
|
Posted: Wed Mar 24, 2010 1:09 am |
|
|
Hi thanks Ttelmah for the reply.
My master is PC. From one of its serial COM port, I used RS232-RS485 converter. From the converter output, I connect in chain 6-7 RS-485 devices or boards. Each boards contain pic16f84A and is assigned slave addresses, e.g. '02'.
From my PC, I broadcast a command based on the particular board I want to control, e.g. to board '02' I send certain command and expecting readback.
The boards have MAX483 that (I assume) take care the RS-485 hardware requirement, e.g. pull-up, etc.
thanks!
Code: | void main() {
//printf("Communication via RS-485\r\n");
output_b (0x00); // Initialize
output_high(PIN_A0); // Set MAX-483 as a driver to transmit to PC
output_high(PIN_A1);
while(1) {
output_low(PIN_A0); // Disable back DE, enable RE, then MAX-483 is a receiver!
gets(text); // Get the text from UART bus
output_high(PIN_A0); // Enable DE, disable RE, to set MAX-483 chip back as a driver!
rec_data();
}
} // end of main |
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
Posted: Wed Mar 24, 2010 3:30 am |
|
|
The MAX483, _does not bias the bus_. You _must_ do this somewhere.
Second, how have you got the enable pin connected.
There are two ways of doing this:
1) The PIC enable pin connects to the chip's 'DE' pin only. Whenever you send anything, the PIC will receive this.
2) The PIC enable pin connects to both the 'DE', and the '/RE' pin. You then need a pll up resistor (perhaps 10K), from the RO pin to +5v. Your PIC will then not receive what it sends.
Best Wishes |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|