PicManía by RedRaven
 

Búsqueda personalizada

 

PROYECTOS : RELE485-628

 

 

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.

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.

.gif

El PCB:

Como veis el ruteado es razonablemente simple dada la escasez de componentes que calza este dispositivo.
 
.gif

Los componentes:

Y esta es la misma imagen pero con la capa de componentes visible.

.gif

El producto montado:

Aquí tenéis el cacharro ya montado y con la corriente dada.



 

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:
 

  Titulo  
 
/** \file firmware_irele485-628.c
* \brief Este fichero contiene el cuerpo principal del Firmware del\n
* dispositivo auxiliar satélite de la iACD V1.0.4. denominado iRELE485-628
*
* Integra todos los subsistemas y funciones implementados.\n
* Source para el compilador CCS C v.3.242
*
* Microprocesador : <b>16F628A</b> (18 pines PDIP) \n\n
* Fuses utilizados: \n
* \li <b>INTRC</b> Internal RC Osc
* \li <b>MCLR</b> Master Clear pin enabled
* \li <b>NOWDT</b> No Watch Dog Timer
* \li <b>NOPROTECT</b> Code not protected from reading
* \li <b>NOPUT</b> No Power Up Timer
* \li <b>NOBROWNOUT</b> No brownout reset
* \li <b>NOLVP</b> No low voltage prgming, B3(PIC16)
* \li <b>NOCPD</b> No EE protection
*
* \author Diego Márquez García-Cuervo \n
* <http://picmania.garcia-cuervo.net>
*
* \version 1.0.0.A
*/

///////////////////////////////////////////////////////////
//
// Definiciones estándar del 16F628A
//
///////////////////////////////////////////////////////////
#include <16F628A.h>

///////////////////////////////////////////////////////////
//
// Fuses y ajuste de Clock
//
///////////////////////////////////////////////////////////
#fuses INTRC,MCLR,NOWDT,NOPROTECT,NOPUT,NOBROWNOUT,NOLVP,NOCPD
#use delay(clock=4000000)

///////////////////////////////////////////////////////////
//
// Defines y Constantes
//
///////////////////////////////////////////////////////////
/*! \def DRIVER_RELE
* Pin accionador del Relé número 1 \li HIGH : Relé ON.
*/
#define DRIVER_RELE PIN_B4

/*! \def TX_485_ENABLE
* Pin que habilita la transmisión por el canal RS485
* \li LOW Habilita recepción RS485
* \li HIGH Habilita transmisión RS485.
*/
#define TX_485_ENABLE PIN_B5

/*! \def bytes_for_USART_buffer
* \brief Establece el número de bytes de longitud del buffer de la USART.
*/
#define bytes_for_USART_buffer 12

/*! \var const char VERSION
* \brief Versión del Firmware.
*/
const char VERSION[]="1.0.0\0";

/*! \var const char WhatAmI
* \brief Identificador de tipo de dispositivo: 'R' Relé.
*/
const char WhatAmI = 'R';

/*! \var const char WhoAmI
* \brief Identificador de dispositivo.
*/
const char WhoAmI = '1';

/*! \var const char Command_Execute
* \brief Comando que indica ejecución de acción : Activar Relé
*/
const char Command_Execute = 'X';

/*! \var const char end_of_transmit
* \brief Carácter que indica fin de transmisión (no buffereable)
*/
const char end_of_transmit = '!';

///////////////////////////////////////////////////////////
//
// Canal de Comunicación
//
///////////////////////////////////////////////////////////
#use rs232(baud=9600,xmit=PIN_B2,rcv=PIN_B1)

///////////////////////////////////////////////////////////
//
// Prototipos de Funciones
//
///////////////////////////////////////////////////////////
void USART_activa_tx(void);
void USART_activa_rx(void);
void USART_add_to_buffer(char c);

///////////////////////////////////////////////////////////
//
// R A M : Variables Globales Estáticas
//
///////////////////////////////////////////////////////////
/*! \var USART_buffer
* \brief Buffer de la USART
*/
static char USART_buffer[bytes_for_USART_buffer];

/*! \var USART_nextRec
* \brief Indice del Buffer de la USART
*/
static int8 USART_nextRec;

/** \var Command
* \brief Comando válido para ejecutar.
*/
int8 Command;

///////////////////////////////////////////////////////////
//
// Funciones
//
///////////////////////////////////////////////////////////
/** \brief Abre el canal RS485 para transmitir.
* \return void
*/
void USART_activa_tx(void){
  output_high(TX_485_ENABLE);
  delay_ms(5);
}

/** \brief Abre el canal RS485 para recibir.
* \return void
*/
void USART_activa_rx(void){
  delay_ms(5);
  output_low(TX_485_ENABLE);
  delay_ms(1);
}

/** \brief Inicializa el Buffer de la USART
*
* Recoge el último carácter recibido desde la USART sobre USART_buffer
* e incrementa en 1 el índice USART_nextRec.\n\n
* Si el carácter recibido es Retorno de carro '\\r' ó 0x0D comprueba identidad de dispositivo y comando recibido
*
* \return void
*/
void USART_add_to_buffer(char c){

USART_buffer[USART_nextRec++]=c;
  if(USART_nextRec==bytes_for_USART_buffer){
    USART_nextRec=0;
  }

  if(c==end_of_transmit){
    --USART_nextRec;
    if(USART_buffer[USART_nextRec-3]==WhatAmI){
      if(USART_buffer[USART_nextRec-2]==WhoAmI){
        if(USART_buffer[USART_nextRec-1]==Command_Execute){
          Command=0x01;
        }
      }
    }
    USART_nextRec = 0;
  }
}

///////////////////////////////////////////////////////////
//
// Rutinas de Servicio de Interrupciones
//
///////////////////////////////////////////////////////////
#int_rda
/** \brief Interrupción por : Recepción del Canal Serie.
*
*/
void interrupt_service_rutine_rda(void) {

  char USART_nextChar;

  USART_nextChar='\0';
  if(kbhit()){
    USART_nextChar=getc();
    USART_add_to_buffer(USART_nextChar);
  }
}

///////////////////////////////////////////////////////////
//
// M A I N
//
///////////////////////////////////////////////////////////
/** \brief Constituye el núcleo principal del sistema
*
* \return void.
*/
void main(void) {

  setup_oscillator(OSC_4MHZ);
  setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
  setup_timer_1(T1_INTERNAL|T1_DIV_BY_4);
  setup_timer_2(T2_DISABLED,0,1);
  setup_comparator(NC_NC_NC_NC);
  setup_vref(FALSE);
  port_b_pullups(False);
  set_tris_b(0b00000010);
  output_low(DRIVER_RELE);
  delay_ms(100);

  USART_nextRec = 0;
  Command = 0x00;

  USART_activa_rx();
  delay_ms(333);

  enable_interrupts(global);
  enable_interrupts(int_rda);

  USART_activa_tx();
  printf("[iRELE485-628] v.%s\r\n",version);
  USART_activa_rx();

  do{

    if(Command==0x01){
      Command =0x00;

      USART_activa_tx();
      printf("R%cA%c\r\n",WhoAmI,end_of_transmit);
      USART_activa_rx();

      output_high(DRIVER_RELE);
      delay_ms(2000);
      output_low(DRIVER_RELE);
    }

  } while(true);
}

///////////////////////////////////////////////////////////
//
// End of firmware
//
///////////////////////////////////////////////////////////
nte
   
 
 

 

 

 

 


Esta página usa la letra Ñ

Nota pública importante sobre las consultas al Webmaster de PicManía.


Sugerencias a Picmanía... (que serán leídas pero seguramente no podrán ser contestadas)

Esta página pertenece al grupo de páginas de Diego RedRaven

 

 



Nota: Esta página Web esta repleta de imágenes, textos, logotipos y demás material extraídos de los mas variados medios de los que no soy ni autor ni depositario de los correspondientes derechos de autor, uso y/o reproducción. Si Ud. es depositario de dichos derechos y desea que el material correspondiente sea eliminado de esta Web no dude en ponerse en contacto conmigo mediante e-mail y será inmediatamente retirado. Gracias.
 
Visitas
Totales : 21335 Hoy: 1 Activas: 1 Vistas: 21335

Esta página fue modificada el 07-08-2010 15:42:20

           
 DmSoft WAMP Escribir Unreal