|
|
View previous topic :: View next topic |
Author |
Message |
Salfer
Joined: 20 Mar 2014 Posts: 15
|
Protocol for MAX485 |
Posted: Thu May 08, 2014 4:43 am |
|
|
Hi everyone! I have a doubt using MAX485. I Use three pics with three MAX485. Each pic use a MAX485.
Mi protocol is:
-The first pic request a answer of the other two pics (Pin RE/DE high and, later, RE/DE low for transmit data and, later, listen the response).
-The pic two and pic three initially are listen. If the direcction sent by pic one coincide with their direcction (pic two or pic three), the pic answer (Pin RE/DE high and, later, RE/DE low for transmit data and, later, listen)
My problem is: When initially I connect this network only a pic answer, the other pic don't answer (for example pic two). If I disconnect the power supply and later I connect the power supply the pic three answer and the pic two don't answer.
Is the problem about the protocol of MAX485 that I am using?
Thanks! |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9244 Location: Greensville,Ontario
|
|
Posted: Thu May 08, 2014 5:10 am |
|
|
Since your hardware seems to work( master and one slave is OK), then probably it is your software that has problems. You should post the code for both master and slaves for others to test.
CCS does supply working RS-485 code , it's located in the examples folder.
One possible hardware issue is the biasing of the network. Be sure to have the correct resistors.
It's very,very difficult to say exactly what is wrong without seeing code or schematics.
hth
jay |
|
|
Salfer
Joined: 20 Mar 2014 Posts: 15
|
|
Posted: Thu May 08, 2014 5:26 am |
|
|
temtronic wrote: | Since your hardware seems to work( master and one slave is OK), then probably it is your software that has problems. You should post the code for both master and slaves for others to test.
CCS does supply working RS-485 code , it's located in the examples folder.
One possible hardware issue is the biasing of the network. Be sure to have the correct resistors.
It's very,very difficult to say exactly what is wrong without seeing code or schematics.
hth
jay |
I don't use resistors (120ohms) because the distance is very short between MAX485 (I am using a protoboard for test this network)
The part of the code in the pic two and three for send the response is it (inicially PIN_B0 is LOW waiting a answer). Each pic have a function that can detect the answer and ONLY response if the direcction coincide. The pic two and three use the same code for send the response:
Code: | output_high(PIN_B0);// RE/DE high (write)
delay_ms(3);
printf("RESPONSEx"); //The pic send the response x=2 for PIC2 and X=3 for PIC3
delay_ms(3);
output_low(PIN_B0);// RE/DE low (listen) |
In the pic one the code is it for send a answer (initially PIN_B0 is low):
Code: | output_high(PIN_B0);// RE/DE high (write)
delay_ms(3);
printf("ANSWERx"); //The pic one send a ansewer x=2 for PIC2 and X=3 for PIC3
delay_ms(3);
output_low(PIN_B0);// RE/DE low (listen) |
|
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9244 Location: Greensville,Ontario
|
|
Posted: Thu May 08, 2014 6:05 am |
|
|
For correct RS-485 network you need the 120R PLUS a pullup (on A)and pulldown(on B) resistor ,usually 4K7, though that depends on the make/model of RS-485 interface chip. If you don't follow the specs..you'll get into 'weird' issues...
I don't understand the B0 operation. If you specify the 'control' pin in the #use rs232(...options...), I'm pretty sure CCS handles the RE/*DE pin.This is where a picture is worth 1000 words.
Have to admit I do not use RS-485 as I use another method that works far better for me.I'm sure others here will offer help that do use it daily, I'm just going on stuff I did 15+ years ago.
jay |
|
|
Salfer
Joined: 20 Mar 2014 Posts: 15
|
|
Posted: Thu May 08, 2014 6:23 am |
|
|
temtronic wrote: | For correct RS-485 network you need the 120R PLUS a pullup (on A)and pulldown(on B) resistor ,usually 4K7, though that depends on the make/model of RS-485 interface chip. If you don't follow the specs..you'll get into 'weird' issues...
I don't understand the B0 operation. If you specify the 'control' pin in the #use rs232(...options...), I'm pretty sure CCS handles the RE/*DE pin.This is where a picture is worth 1000 words.
Have to admit I do not use RS-485 as I use another method that works far better for me.I'm sure others here will offer help that do use it daily, I'm just going on stuff I did 15+ years ago.
jay |
Pin_B0 is the control. If I connect the resistances the problem is the same. I don't know how can I upload an image.
[/img] |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9244 Location: Greensville,Ontario
|
|
Posted: Thu May 08, 2014 6:54 am |
|
|
re: image
You need to save on a 'picture saving site', then insert the 'link' to it.... |
|
|
ezflyr
Joined: 25 Oct 2010 Posts: 1019 Location: Tewksbury, MA
|
|
Posted: Thu May 08, 2014 7:04 am |
|
|
Hi Salfer,
To share an image, you need to upload it to a free hosting site and then post the link.
Creating a 'micro' RS485 network on a breadboard should be pretty trivial even if you completely ignore the network biasing issues (which can't be ignored in a larger network). You appear to be using a simple addressing 'protocol' to uniquely query each PIC, but your protocol is seriously lacking and is definitely making your life harder.
You showed us this as your addressing scheme:
Code: |
printf("ANSWERx"); //The pic one send a ansewer x=2 for PIC2 and X=3 for PIC3
|
May I suggest that you do something like this instead:
Code: |
printf("#ANSWERx\r"); //The pic one send a ansewer x=2 for PIC2 and X=3 for PIC3
|
The differences are subtle, yet very important. The addition of the '#' character is a 'start' character for your communications message, and the <CR> is a 'stop' character. This should make your data packet receiving routine much simpler, and more robust. Simply ignore all incoming data until the '#' is received, and then keep receiving data until the <CR> is received. When a complete message is obtained, you can then parse it to determine the unique 'address' received.
Also, be sure you have 'Errors' defined in your #use rs232 declaration.
John |
|
|
Salfer
Joined: 20 Mar 2014 Posts: 15
|
|
Posted: Thu May 08, 2014 7:37 am |
|
|
ezflyr wrote: | Hi Salfer,
To share an image, you need to upload it to a free hosting site and then post the link.
Creating a 'micro' RS485 network on a breadboard should be pretty trivial even if you completely ignore the network biasing issues (which can't be ignored in a larger network). You appear to be using a simple addressing 'protocol' to uniquely query each PIC, but your protocol is seriously lacking and is definitely making your life harder.
You showed us this as your addressing scheme:
Code: |
printf("ANSWERx"); //The pic one send a ansewer x=2 for PIC2 and X=3 for PIC3
|
May I suggest that you do something like this instead:
Code: |
printf("#ANSWERx\r"); //The pic one send a ansewer x=2 for PIC2 and X=3 for PIC3
|
The differences are subtle, yet very important. The addition of the '#' character is a 'start' character for your communications message, and the <CR> is a 'stop' character. This should make your data packet receiving routine much simpler, and more robust. Simply ignore all incoming data until the '#' is received, and then keep receiving data until the <CR> is received. When a complete message is obtained, you can then parse it to determine the unique 'address' received.
Also, be sure you have 'Errors' defined in your #use rs232 declaration.
John |
My complete code is it (for PIC2 and PIC3). The code in these pics are the same but a different adress. I use this method. Thecode that I posted was an example of my real code.
Code: | #include <16f88.h>
#device ADC=10
#fuses NOWDT, NOLVP, NOBROWNOUT, NOPROTECT, PUT, INTRC_IO
#use delay (internal=8MHz)
#use rs232(baud=9600, xmit=PIN_B5, rcv=PIN_B2, ERRORS) //CONFIGURO PUERTO SERIE
//#use RS232(UART1, ERRORS)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
//**VARIABLES PARA GESTIONAR LA TRAMA RECIBIDA Y LA TRAMA A ENVIAR POR PUERTO SERIE**//
long valor_adc=0; //Variable de 16 bits para lectura ADC
int P_W=0; //indice escritura
int P_R=0; //indice lectura
int i=0;
int j=0;
int inicio=0;
int final=0;
char string_valor_adc[5]="0000";//Cadena de caracteres para guardar valor ADC en Carcteres
char trama_entrada[91]={0}; //String para guardar el dato de entrada por UART
char direccion_pic[4]="P01";
char tipo_dato[5]="$ADQ";
char canal[4]="CH0";
char dato[14]="$ADQ,P01,CH0\r";
char miretorno[2]="\r";
char misimbolo[2]="$";
short flag_final=0;
short flag_permiso=0;
short flag_tst=0;
short flag_envio=0;
//FUNCIÓN PARA LEER LOS DATOS PROCEDENTES DEL PUERTO SERIE//
void lectura(){
for(P_R=0; P_R<91; P_R++){
if(trama_entrada[P_R]==misimbolo[0]){
inicio=P_R;
for(P_R=inicio; P_R<91; P_R++){
if(trama_entrada[P_R]==miretorno[0]){
P_W=0;
final=P_R;
flag_permiso=1;
break;
}
}
break;
}
}
}
//FUNCIÓN PARA COPIAR EL DATO PROCEDENTE DEL BUFFER DEL PUERTO SERIE//
void escritura(){
for(i=inicio; i<=final; i++){
dato[j]=trama_entrada[i];
j++;}
i=0;
j=0;
memset(trama_entrada, 0, sizeof(trama_entrada));
return;
}
//FUNCIÓN PARA PROCESAMIENTO DEL DATO PROCEDENTE DEL PUERTO SERIE//
void procesamiento(){
//Se copia la dirección de la solicitud para saber a qué pic va dirigido//
//Éste pic tiene la dirección "P01"//
for(i=0; i<3; i++){
direccion_pic[i]=dato[i+5];}
direccion_pic[3]='\0';
//Se compara la dirección obtenida con la de éste pic//
if(strcmp(direccion_pic, (char*)"P01")==0){
memset(direccion_pic, 0, sizeof(direccion_pic));
//Se copia el tipo de dato que puede ser "$ADQ" o "$TST"//
for(i=0; i<4; i++){
tipo_dato[i]=dato[i];}
tipo_dato[4]='\0';
//Se compara el tipo de dato con "$ADQ" que es para obtener medidas del ADC//
if(strcmp(tipo_dato, (char*)"$ADQ")==0){
memset(tipo_dato, 0, sizeof(tipo_dato));
flag_tst=0;//flag para el case de la función enviar
//Se copia el canal para ver qué canal se quiere escoger "CH0" o "CH1"//
for(i=0; i<3; i++){
canal[i]=dato[i+9];}
canal[3]='\0';
//Se compara el canal//
if(strcmp(canal,(char*)"CH0")==0){
set_adc_channel(0);}
else if(strcmp(canal,(char*)"CH1")==0){
set_adc_channel(1);}
//Lectura del ADC//
delay_us(20);//retardo para leer ADC
valor_adc=read_adc();//lectura ADC
sprintf(string_valor_adc,"%04ld",valor_adc);
}
//Se compara el tipo de dato con "$TST" que es para que éste pic responda con "$TST,P01\r"//
else if(strcmp(tipo_dato,(char*)"$TST")==0){
memset(tipo_dato, 0, sizeof(tipo_dato));
flag_tst=1;
}
//Se da permiso para enviar dato//
flag_envio=1;//flag para el case de la función enviar
}
return;
}
void enviar(){
switch(flag_tst){
case 0:
output_high(PIN_B0);
delay_ms(3);
printf("$ADQ,P01,%s,%s\r", canal,string_valor_adc);
delay_ms(3);
output_low(PIN_B0);
break;
case 1:
output_high(PIN_B0);
delay_ms(3);
printf("$TST,P01\r");
delay_ms(3);
output_low(PIN_B0);
flag_tst=0;
break;
}
return;
}
void main(){
output_low(PIN_B0);
disable_interrupts(INT_RDA);
enable_interrupts(GLOBAL); //HABIlLITO TODAS LAS INTERRUPCIONES GLOBALES
enable_interrupts(INT_RDA); //HABILITO LA INTERRUPCIÓN UART
setup_adc_ports(sAN0|sAN1); //INDICO EL PIN A0/A1/A2/A3/A4/A5 COMO ENTRADA ANALÓGICA
setup_adc(ADC_CLOCK_INTERNAL); //CLOCK INTERNO PARA CONVERSIÓN ADC
while(1){
if(flag_final==1){
flag_final=0;
lectura();
if(flag_permiso==1){
flag_permiso=0;
escritura();
procesamiento();
if(flag_envio==1){
flag_envio=0;
enviar();
//reset_cpu();
}
}
}
}
}
#INT_RDA
void INT_UART(void) {
trama_entrada[P_W]=getc();
if(trama_entrada[P_W]=='\r'){
P_W=0;
flag_final=1;
}
else{
P_W++;
if(P_W >=91 ){
P_W=0;
}
}
}
|
|
|
|
ezflyr
Joined: 25 Oct 2010 Posts: 1019 Location: Tewksbury, MA
|
|
Posted: Thu May 08, 2014 9:12 am |
|
|
Hi,
I don't really have time to dig into your code right now, but one thing did catch my eye. You appear to be attempting to control the MAX485 'direction' control (Tx or Rx) manually by explicitly manipulating Pin_B0. In some instances there may be a good reason for this, but I don't see it in this case, and unless it's done carefully, there are a lot of pitfalls. Instead, let the compiler handle the 'Enable' for you by doing the following:
Code: |
#use rs232(baud=9600, xmit=PIN_B5, rcv=PIN_B2, Enable=Pin_B0, ERRORS) //CONFIGURO PUERTO SERIE
|
Then, remove all the code that manipulated Pin B0 directly.
John |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Thu May 08, 2014 12:03 pm |
|
|
a google visit to search:
MODBUS 485
might profitably guide your thoughts
also see MODBUS_xxx drivers in the CCS folder |
|
|
Salfer
Joined: 20 Mar 2014 Posts: 15
|
|
Posted: Fri May 09, 2014 1:50 am |
|
|
asmboy wrote: | a google visit to search:
MODBUS 485
might profitably guide your thoughts
also see MODBUS_xxx drivers in the CCS folder |
I think that the problem is my code but I follow the code like says the datasheet (max485)... I don't know |
|
|
Humberto
Joined: 08 Sep 2003 Posts: 1215 Location: Buenos Aires, La Reina del Plata
|
|
Posted: Sat May 10, 2014 11:30 am |
|
|
asmboy wrote:
Quote: |
a google visit to search:
MODBUS 485
|
Agree. The ANSI Standard RS485 (managed by Telecommunications Industry Association under TIA-485-A.222.) refers only to the
hardware layer, without any mention it about software layer protocol.
There are many serial communications protocols, Modbus RTU is one of the most used widely and it is the best starting point to refer.
Doing a bit bang protocol, it is difficult to manage in a multi-slave node without handling the procedures in another upper layer level.
regards _________________ Humber |
|
|
Salfer
Joined: 20 Mar 2014 Posts: 15
|
|
Posted: Thu May 15, 2014 5:31 pm |
|
|
I think that the PROBLEM is the INTERFERENCES between transmissions. If I connect only a Master and slave the sistem works OK but If I connect other slave the sistems works rarely. The protocol that I use with the MAX485 is correct. Each PIC have an individual ID. The sistem is connected in form of bus.
I connected the 120ohms resistor in the start of the bus and the end of the bus.
If I connect ONLY Arduino and one slave the sistem works ok but if I connect ther slave the sistem works rarely (sometimes only respond the first slave that I called)
My sistem is: (the PIC2 is connect down: -----)
ARDUINO-MAX485-(R=120)---------------(R=120)-MAX485-PIC1(id=p01)
|
|
MAX485
|
PIC2(id=p02)
I dont know how I can solve this problem :( I need help please. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9244 Location: Greensville,Ontario
|
|
Posted: Thu May 15, 2014 6:50 pm |
|
|
You really should have proper pullup/pulldown bias resistors as well as one 120r across A-B. There's some great info on Maxim's site about using their RS-485 chips. Though it's been years, I did have 251 devices on one network and never had any problems.Since then I've gone to a more reliable(robust),hackerproof topography.
Others who use PICs with RS-485 can comment abut your code, though I recall thet CCS does supply an example in the examples folder?
hth
jay |
|
|
ezflyr
Joined: 25 Oct 2010 Posts: 1019 Location: Tewksbury, MA
|
|
Posted: Thu May 15, 2014 9:24 pm |
|
|
Salfer,
There seems to be an explosion of people coming here to the forum, pleading for help, and then summarily ignoring the advise and help that is offered to them.
A week ago, I told you to stop trying to manipulate the direction control on your RS485 network manually, and to let the compiler handle this for you. Using your method is a sure way to mess up the required network timing, and to introduce problems like you are seeing. Did you ever do this???
Frankly, creating a multi-drop RS485 network using MAX485 IC's, the CCS compiler, and a simple networking protocol is a pretty TRIVIAL exercise.
John |
|
|
|
|
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
|