Autor Tema: El RS485, un Relé en la lejanía: Hardware y Software  (Leído 43502 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado RedPic

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 5395
    • Picmania by Redraven
El RS485, un Relé en la lejanía: Hardware y Software
« en: 23 de Octubre de 2007, 18:15:53 »
Introducción:

Venimos hablando desde hace tiempo del RS485, de cómo montarlo con los PIC's y de cómo implementar algún algoritmo fácil para que varios dispositivos contesten cuando se les pregunte, y solo entonces. Rescato aquí un pequeño proyecto de hace unos meses en el que hicimos exactamente eso: Un PIC 16F628A que habla con el PC mediante RS485 y es capaz de comandar un sencillo Relé. Poca cosa para algunos pero todo un logro para muchos.  :mrgreen:

Con este proyecto podemos aprender todas las técnicas básicas para implementar una red RS485 con dispositivos diferenciados hablando con un PC que va a actuar como MASTER.

1ª Parte: El Hardware.

El esquema:

Este pequeño proyecto tiene pocas cosas, un PIC 16F628A sin cristal externo, vamos a usar el oscilador interno a 4Mhz, un Relé de 5V que vamos a activar con un simple transistor y una pequeña fuente alrededor de un 7805 para poder utilizar 12V, y por supuesto, un SN75176 que es uno de los muchos chips idénticos al MAX485 pero mas baratos.



El PCB que me salió es este :



Que con sus componentes aparece así:



Una vez construido y dándole la "primera luz" mostraba este aspecto:



Continuará ...
« Última modificación: 18 de Septiembre de 2012, 16:20:27 por RedPic »
Contra la estupidez los propios dioses luchan en vano. Schiller
Mi Güeb : Picmania

Desconectado RedPic

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 5395
    • Picmania by Redraven
Re: El RS485, un Relé en la lejanía: Hardware y Software
« Respuesta #1 en: 23 de Octubre de 2007, 18:16:58 »
2ª Parte: El Software.

El dispositivo que vamos a montar es un SLAVE, esclavo, de una Red RS485.

Este firmware tiene la característica de tener que conmutar de Low un Pin del PIC para recibir desde la USART, que es el estado por defecto, a High para poder transmitir, son las funciones USART_activa_rx() y USART_activa_tx().

La recepción se realiza sobre un buffer, carácter a carácter, de forma que sólo al recibir un carácter especial de finalización podemos pasar a procesar lo recibido. Para ello usamos la interrupción de la USART y la funcione USART_add_to_buffer(). El carácter de finalización de una trama lo tenemos definido con un define const char end_of_transmit = '!' con vistas a facilitar su cambio según las necesidades. Yo he utilizado el carácter '!' para indicar el fin de la trama, podéis coger el que queráis.

Como la transmisión de un mensaje del MASTER es broadcast, todos lo oyen, es imprescindible que cada PIC lleve un identificador único en la red RS485, para que se sienta aludido, responda, sólo cuando dicho identificador único aparezca en la trama enviada por el MASTER. Para ello he implementado un define const char WhoAmI = '1'; que ha de ser único para cada PIC, así a uno le pondremos '1', a otro '2' ... etc.

Como además podemos tener en la misma red varios tipos de dispositivos, que no sean éste Relé en la Lejanía, le he colocado otro define que me dice a qué tipo de dispositivo vamos a responder. En nuestro caso vamos a usar const char WhatAmI = 'R';

Y por último necesitamos al menos una orden directa para ejecutar una función específica. La única orden que he implementado es const char Command_Execute = 'X'; que va a producir una conmutación del Relé de un segundo de tiempo.
 
Todo esto significa que el PC MASTER va a transmitir un frame del estilo de "R1X!" cuyo significado sería: Mensaje a los Dispositivos de Tipo 'R', al concreto dispositivo '1' para que ejecute el Comando 'X', fin de transmisión.

Todos los PIC escucharán este mensaje pero sólo el PIC que sea de Tipo 'R', que tenga el identificador concreto '1' ejecutará el comando 'X'.

Y por último, para comprobar que la orden ha sido recibida correctamente este mismo PIC que sí va a ejecutar la orden recibida responderá con una trama del estilo de "R1A!" significando que el Relé 1 ha actuado correctamente.

Fijaos que todos los demás oirán ese "R1A!" pero no harán nada porque no son el '1' ni 'A' es un comando válido.

El código completo es:

Código: C++
  1. /** \file firmware_iRELE485-628.c
  2.  * \brief Este fichero contiene el cuerpo principal del Firmware del\n
  3.  * dispositivo auxiliar satélite de la iACD V1.0.4. denominado iRELE485-628
  4.  *
  5.  * Integra todos los subsistemas y funciones implementados.\n
  6.  * Source para el compilador CCS C v.3.242
  7.  *
  8.  * Microprocesador : <b>16F628A</b> (18 pines PDIP) \n\n
  9.  * Fuses utilizados: \n
  10.  * \li <b>INTRC</b> Internal RC Osc
  11.  * \li <b>MCLR</b> Master Clear pin enabled
  12.  * \li <b>NOWDT</b> No Watch Dog Timer
  13.  * \li <b>NOPROTECT</b> Code not protected from reading
  14.  * \li <b>NOPUT</b> No Power Up Timer
  15.  * \li <b>NOBROWNOUT</b> No brownout reset
  16.  * \li <b>NOLVP</b> No low voltage prgming, B3(PIC16)
  17.  * \li <b>NOCPD</b> No EE protection
  18.  *
  19.  * \author Diego Márquez García-Cuervo \n
  20.  * <http://picmania.garcia-cuervo.net>
  21.  *
  22.  * \version 1.0.0.A
  23.  */
  24.  
  25. ///////////////////////////////////////////////////////////////////////////////////////////////////
  26. //
  27. // Definiciones estándar del 16F628A
  28. //
  29. ///////////////////////////////////////////////////////////////////////////////////////////////////
  30.  
  31. #include <16F628A.h>
  32.  
  33. ///////////////////////////////////////////////////////////////////////////////////////////////////
  34. //
  35. // Fuses y ajuste de Clock
  36. //
  37. ///////////////////////////////////////////////////////////////////////////////////////////////////
  38.  
  39. #fuses INTRC,MCLR,NOWDT,NOPROTECT,NOPUT,NOBROWNOUT,NOLVP,NOCPD
  40. #use delay(clock=4000000)
  41.  
  42. ///////////////////////////////////////////////////////////////////////////////////////////////////
  43. //
  44. // Defines y Constantes
  45. //
  46. ///////////////////////////////////////////////////////////////////////////////////////////////////
  47.  
  48. /*! \def DRIVER_RELE
  49.  *   Pin accionador del Relé número 1 \li HIGH : Relé ON.
  50.  */
  51. #define DRIVER_RELE PIN_B4
  52.  
  53. /*! \def TX_485_ENABLE
  54.  *  Pin que habilita la transmisión por el canal RS485
  55.  * \li LOW Habilita recepción RS485
  56.  * \li HIGH Habilita transmisión RS485.
  57.  */
  58. #define TX_485_ENABLE PIN_B5
  59.  
  60. /*! \def bytes_for_USART_buffer
  61.  *  \brief Establece el número de bytes de longitud del buffer de la USART.
  62.  */
  63. #define bytes_for_USART_buffer 12
  64.  
  65. /*! \var const char VERSION
  66.  *  \brief Versión del Firmware.
  67.  */
  68. const char VERSION[]="1.0.0\0";
  69.  
  70. /*! \var const char WhatAmI
  71.  *  \brief Identificador de tipo de dispositivo: 'R' Relé.
  72.  */
  73. const char WhatAmI = 'R';
  74.  
  75. /*! \var const char WhoAmI
  76.  *  \brief Identificador de dispositivo.
  77.  */
  78. const char WhoAmI = '1';
  79.  
  80. /*! \var const char Command_Execute
  81.  *  \brief Comando que indica ejecución de acción : Activar Relé
  82.  */
  83. const char Command_Execute = 'X';
  84.  
  85. /*! \var const char end_of_transmit
  86.  *  \brief Carácter que indica fin de transmisión (no buffereable)
  87.  */
  88. const char end_of_transmit = '!';
  89.  
  90. ///////////////////////////////////////////////////////////////////////////////////////////////////
  91. //
  92. // Canal de Comunicación
  93. //
  94. ///////////////////////////////////////////////////////////////////////////////////////////////////
  95.  
  96. #use rs232(baud=9600,xmit=PIN_B2,rcv=PIN_B1)
  97.  
  98. ///////////////////////////////////////////////////////////////////////////////////////////////////
  99. //
  100. // Prototipos de Funciones
  101. //
  102. ///////////////////////////////////////////////////////////////////////////////////////////////////
  103.  
  104. void USART_activa_tx(void);
  105. void USART_activa_rx(void);
  106. void USART_add_to_buffer(char c);
  107.  
  108. ///////////////////////////////////////////////////////////////////////////////////////////////////
  109. //
  110. // R A M : Variables Globales Estáticas
  111. //
  112. ///////////////////////////////////////////////////////////////////////////////////////////////////
  113.  
  114. /*! \var USART_buffer
  115.  *  \brief Buffer de la USART
  116.  */
  117. static char USART_buffer[bytes_for_USART_buffer];
  118.  
  119. /*! \var USART_nextRec
  120.  *  \brief Indice del Buffer de la USART
  121.  */
  122. static int8 USART_nextRec;
  123.  
  124. /** \var Command
  125.   * \brief Comando válido para ejecutar.
  126.   */
  127. int8 Command;
  128.  
  129. ///////////////////////////////////////////////////////////////////////////////////////////////////
  130. //
  131. // Funciones
  132. //
  133. ///////////////////////////////////////////////////////////////////////////////////////////////////
  134.  
  135. /** \brief Abre el canal RS485 para transmitir.
  136.   * \return void
  137.   */
  138. void USART_activa_tx(void){
  139.   output_high(TX_485_ENABLE);
  140.   delay_ms(5);
  141. }
  142.  
  143. /** \brief Abre el canal RS485 para recibir.
  144.   * \return void
  145.   */
  146. void USART_activa_rx(void){
  147.   delay_ms(5);
  148.   output_low(TX_485_ENABLE);
  149.   delay_ms(1);
  150. }
  151.  
  152. /** \brief Inicializa el Buffer de la USART
  153.   *
  154.   * Recoge el último carácter recibido desde la USART sobre USART_buffer
  155.   * e incrementa en 1 el índice USART_nextRec.\n\n
  156.   * Si el carácter recibido es Retorno de carro '\\r' ó 0x0D comprueba identidad de dispositivo y comando recibido
  157.   *
  158.   * \return void
  159.   */
  160. void USART_add_to_buffer(char c){
  161.  
  162.    USART_buffer[USART_nextRec++]=c;
  163.    if(USART_nextRec==bytes_for_USART_buffer){
  164.       USART_nextRec=0;
  165.    }
  166.  
  167.    if(c==end_of_transmit){
  168.       --USART_nextRec;
  169.       if(USART_buffer[USART_nextRec-3]==WhatAmI){
  170.          if(USART_buffer[USART_nextRec-2]==WhoAmI){
  171.            if(USART_buffer[USART_nextRec-1]==Command_Execute){
  172.               Command=0x01;
  173.            }
  174.          }
  175.       }
  176.       USART_nextRec = 0;
  177.    }
  178. }
  179.  
  180. ///////////////////////////////////////////////////////////////////////////////////////////////////
  181. //
  182. // Rutinas de Servicio de Interrupciones
  183. //
  184. ///////////////////////////////////////////////////////////////////////////////////////////////////
  185.  
  186. #int_rda
  187. /** \brief Interrupción por : Recepción del Canal Serie.
  188.   *
  189.   */
  190. void interrupt_service_rutine_rda(void) {
  191.  
  192.    char USART_nextChar;
  193.  
  194.    USART_nextChar='\0';
  195.    if(kbhit()){
  196.       USART_nextChar=getc();
  197.       USART_add_to_buffer(USART_nextChar);
  198.    }
  199. }
  200.  
  201. ///////////////////////////////////////////////////////////////////////////////////////////////////
  202. //
  203. // M A I N
  204. //
  205. ///////////////////////////////////////////////////////////////////////////////////////////////////
  206.  
  207. /** \brief Constituye el núcleo principal del sistema
  208.   *
  209.   * \return void.
  210.   */
  211. void main(void) {
  212.  
  213.    setup_oscillator(OSC_4MHZ);
  214.    setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
  215.    setup_timer_1(T1_INTERNAL|T1_DIV_BY_4);
  216.    setup_timer_2(T2_DISABLED,0,1);
  217.    setup_comparator(NC_NC_NC_NC);
  218.    setup_vref(FALSE);
  219.    port_b_pullups(False);
  220.    set_tris_b(0b00000010);
  221.    output_low(DRIVER_RELE);
  222.    delay_ms(100);
  223.  
  224.    USART_nextRec = 0;
  225.    Command = 0x00;
  226.  
  227.    USART_activa_rx();
  228.    delay_ms(333);
  229.  
  230.    enable_interrupts(global);
  231.    enable_interrupts(int_rda);
  232.  
  233.    USART_activa_tx();
  234.    printf("[iRELE485-628] v.%s\r\n",version);
  235.    USART_activa_rx();
  236.  
  237.    do{
  238.  
  239.       if(Command==0x01){
  240.          Command =0x00;
  241.  
  242.          USART_activa_tx();
  243.          printf("R%cA%c\r\n",WhoAmI,end_of_transmit);
  244.          USART_activa_rx();
  245.  
  246.          output_high(DRIVER_RELE);
  247.          delay_ms(2000);
  248.          output_low(DRIVER_RELE);
  249.        }
  250.  
  251.    } while(true);
  252. }
  253.  
  254. ///////////////////////////////////////////////////////////////////////////////////////////////////
  255. //
  256. // End of firmware
  257. //
  258. ///////////////////////////////////////////////////////////////////////////////////////////////////
  259.  

Ea, mañana más.  :mrgreen:

« Última modificación: 23 de Octubre de 2007, 18:48:19 por RedPic »
Contra la estupidez los propios dioses luchan en vano. Schiller
Mi Güeb : Picmania

Desconectado ema

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1078
Re: El RS485, un Relé en la lejanía: Hardware y Software
« Respuesta #2 en: 23 de Octubre de 2007, 18:50:46 »
El proyecto parece bueno pero no estan las imagenes.

Saludos

Desconectado Azicuetano

  • Moderadores
  • PIC24H
  • *****
  • Mensajes: 1020
    • Aplicaciones Electrónicas en Alicante.
Re: El RS485, un Relé en la lejanía: Hardware y Software
« Respuesta #3 en: 23 de Octubre de 2007, 19:08:45 »
OOhhh... que grande Diego.

Yo tengo ya medio acabada mi comunicación RS485 utilizando las funciones que nos dan los señores de CCS (trama=origen, destino, datos, checksum). La verdad es que me ha costado un poco entenderlas, pero bueno, en cuanto el programa pase mi bataría de pruebas, lo cuelgo en este hilo para que esté toda la documentación al respecto más conglomerada  :D


Un saludo desde Alicante.

Desconectado RedPic

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 5395
    • Picmania by Redraven
Re: El RS485, un Relé en la lejanía: Hardware y Software
« Respuesta #4 en: 23 de Octubre de 2007, 19:08:48 »
Acabo de reiniciar el servidor. Tened paciencia porque es un servidor casero y hay veces que el tráfico le viene largo, alto y ancho.  :mrgreen:
Contra la estupidez los propios dioses luchan en vano. Schiller
Mi Güeb : Picmania

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 17493
    • MicroPIC
Re: El RS485, un Relé en la lejanía: Hardware y Software
« Respuesta #5 en: 24 de Octubre de 2007, 01:27:23 »
Muy instructiva la práctica; gracias maestro.
Un saludo desde Sevilla, España.
Visita MicroPIC                                                                                        ɔ!doɹɔ!ɯ ɐʇ!s!ʌ

Desconectado Mario

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 873
Re: El RS485, un Relé en la lejanía: Hardware y Software
« Respuesta #6 en: 24 de Octubre de 2007, 03:11:38 »
Muy interesante.

Se intentará realizar algo parecido pero con BASIC; esta información será de gran utilidad.





PD: ¡¡¡Necesito meterme a CCS pero ya!!!  :D
La buena administración es utilizar el sentido común y la regla de oro; aunque el sentido común no es tan común como quisiéramos que fuera y, quien tiene el oro, hace las reglas.
George Terry

"A loser will defeat a genius with hard work"
Rock Lee

Desconectado ema

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1078
Re: El RS485, un Relé en la lejanía: Hardware y Software
« Respuesta #7 en: 29 de Octubre de 2007, 17:43:33 »
La verdad que muy bueno lo tuyo.
Felicitaciones y gracias por compartirlo tan explicitamente.

En alguna otra vida tu has sido profesor!!!!!!!

Saludos

Desconectado zonadjarn

  • PIC10
  • *
  • Mensajes: 45
Re: El RS485, un Relé en la lejanía: Hardware y Software
« Respuesta #8 en: 30 de Octubre de 2007, 14:56:51 »
Muy interesante, gracias por informarme de este hilo que estas creando, permaneceré atento para poder ver como hacer mi trabajo relacionado con esto....Saludos
En los Albores de la Electronica, "THE GOD IS PIO LAZARO"

Desconectado stk500

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 4780
Re: El RS485, un Relé en la lejanía: Hardware y Software
« Respuesta #9 en: 11 de Noviembre de 2007, 08:44:53 »
Hola Redpic!
Una pregunta porque estoy luchando con DMXPack?
yo uso de driver el SN75176, quizas tu ha visto el esquema, me sucede que dandole Señal DMX en su entrada me sale en la salida pin 1
Ocilaciones de corriente continua, cosa que no estoy seguro si debe ser asi, lastima no estoy en mi trabajo para comprobarlo, y claro el dimmer no me funciona como debe ser :x las lucces me hace detellos pero no regula :?
claro esta que si TX trasmite RX recibe la señal detectada debe dar una corriente que es la que me gustaria saber!
 :mrgreen:
« Última modificación: 11 de Noviembre de 2007, 08:48:58 por stk500 »

Desconectado xrom

  • PIC10
  • *
  • Mensajes: 10
Re: El RS485, un Relé en la lejanía: Hardware y Software
« Respuesta #10 en: 12 de Noviembre de 2007, 19:54:04 »
Magnífico ejemplo Redpic sobre el Bus 485. Me he tomado la libertad de crear la simulación en Proteus para su mejor comprensión. Un saludo y felicidades por el foro.


Desconectado RedPic

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 5395
    • Picmania by Redraven
Re: El RS485, un Relé en la lejanía: Hardware y Software
« Respuesta #11 en: 13 de Noviembre de 2007, 02:53:39 »
Muchas gracias xrom por tu aporte, los amigos del Foro y yo te lo agradecemos.  :mrgreen:
Contra la estupidez los propios dioses luchan en vano. Schiller
Mi Güeb : Picmania

Desconectado valdorre

  • Colaborador
  • PIC18
  • *****
  • Mensajes: 346
Re: El RS485, un Relé en la lejanía: Hardware y Software
« Respuesta #12 en: 22 de Noviembre de 2007, 19:08:08 »
hola, estoy haciendo pruebas con rs485 y me estan dando bastante batalla.
generaba errores en la comunicacion de los datos, como si tubiera interferencias.
paso a comentar algunos cambios que hice con los que logre que se comunicara un 877 con la pc. use sn75176.
 #use rs232(baud=38400,xmit=PIN_C6,rcv=PIN_C7, enable=PIN_C5).
 puse resistencias de 10k a positivo en tx, rx y enable.   
 en la salida del sn75176 puse una resistencia de 120 ohms entre las patas 6 y 7 y de 1k de la pata 7 a vss y de la pata 6 a vdd.

Diego, hay alguna otra cosa que pueda hacer?? la velocidad de comunicacion es bastante alta, sera por eso??  :?
saludos

Osvaldo

Osvaldo

Desconectado MGLSOFT

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 7787
Re: El RS485, un Relé en la lejanía: Hardware y Software
« Respuesta #13 en: 22 de Noviembre de 2007, 23:13:57 »
Que cableado utilizas para unir los nodos??? :shock:
Todos los dias aprendo algo nuevo, el ultimo día de mi vida aprenderé a morir....
Mi Abuelo.

Desconectado RedPic

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 5395
    • Picmania by Redraven
Re: El RS485, un Relé en la lejanía: Hardware y Software
« Respuesta #14 en: 23 de Noviembre de 2007, 02:24:21 »
Según la norma las resistencias de 120 Ohms deben ir en ambos extremos de la red RS485, cerrando entre sí los dos hilos tanto junto al SN751766 como junto al PC. Yo normalmente o no pongo ninguna o pongo las dos.
Contra la estupidez los propios dioses luchan en vano. Schiller
Mi Güeb : Picmania