01
01
Microcontrollers
02
02
Control systems, open systems
03
03
Electronic world, sites
04
04
Electronic components, parts, etc...

e-micronica

NeuronC y RTC

Imprimir
Escrito por Paikan

En las redes Lonworks es necesario incluir un patrón de hora y puede que no se disponga de conexión a Internet para tomarla de un servidor o que no exista un gateway que pueda realizar esta función. Para ello es muy fácil conectar a una CPU de Echelon (FT3120 o FT3150) mediante el bus I2C un chip del tipo PCF8583 (RTC).

Mediante el código adjunto y la documentación técnica del fabricante del chip podremos dotar a la red de una hora fiable basada en un auténtico reloj / calendario. Esta es la versión base con las funciones mínimas. El código se puede completar con la inclusión de escenas, plug-in de ajuste de hora, conexión de sincronización via GPS, etc.

//----------------------------------------------------
// Software necesario para implementar un RTC en 
// un nodo Lonworks con un chip I2C PCF8583
// Este reloj sería el 'master' de horario
// en ausencia de otras referencias externas
//----------------------------------------------------
// En versiones posteriores se incluye la gestión
// automática del horario verano/invierno
// así como la sincronización via GPS
//-----------------------------------------------------

#define rtc_addr 0x50 // dirección del RTC

network output sd_string("Dia de la Semana")   SNVT_date_day   nvoDiaSema;
network input sd_string("Entrada Ajuste Hora") SNVT_time_stamp nviTimeSet;

// Variables Errores I2C
network output sd_string("Fallos bus I2C")SNVT_count I2CFails;

// Salidas RTC, como suele vincularse a decenas o cientos de nodos, se ajusta como unackd_rpt
network output sd_string("Time Stamp propagado") SNVT_time_stamp bind_info(unackd_rpt) nvoTimeRef;
network output sd_string("Day of Week") SNVT_count nvoDOW;


//////////////////////////////////////////////////////////////////
// Funciones - Timers - Variables - I/O's - etc.
/////////////////////////////////////////////////////////////////
int es_bisi(long ano);
unsigned short dow(unsigned int d, unsigned int m, unsigned long a);

/////////////////////// Timers ///////////////////////////////////
mtimer repeating lectura=250;

////////////////////// I/O Objects //////////////////////////////
IO_8 i2c io_i2c_bus;

////////////////////// Vars ////////////////////////////////////
far unsigned int rtcbuff[18];
far unsigned int rtcset[7];
far unsigned int rtc_cont;
far unsigned long ano;
far unsigned int ano_ant, ano_act, minut;
unsigned int horas_adel;
// Variable interna para mabejo reloj
SNVT_time_stamp  nvoTimeSet;


/////////////////////////////////// Tasks ///////////////////////////////////
// Reset task
// This task is called whenever the node is reset.
when(reset){
  rtc_cont=0;
  // Lectura Inicial RTC
  if (!io_out(io_i2c_bus,&rtc_cont,rtc_addr,1)) I2CFails++;
  if (!io_in(io_i2c_bus,rtcbuff,rtc_addr,18)) I2CFails++;
  // Si se desea se puede manejar la variable I2CFails aquí... 
  // No hay fallos nunca salvo avería directa del chip
  ano_ant=( (rtcbuff[5]&0xC0)>>6);
  ano_act=( (rtcbuff[5]&0xC0)>>6);
  nvoTimeSet.second=(((rtcbuff[2]&0xF0)>>4)*10)+(rtcbuff[2]&0x0F);
  nvoTimeSet.minute=(((rtcbuff[3]&0xF0)>>4)*10)+(rtcbuff[3]&0x0F);
  nvoTimeSet.hour=(((rtcbuff[4]&0x30)>>4)*10)+(rtcbuff[4]&0x0F);
  nvoTimeSet.day=(((rtcbuff[5]&0x30)>>4)*10)+(rtcbuff[5]&0x0F);
  nvoTimeSet.month=(((rtcbuff[6]&0x10)>>4)*10)+(rtcbuff[6]&0x0F);
  ano=(rtcbuff[16]*256)+rtcbuff[17]+ano_act;
  nvoTimeSet.year=ano;
  nvoDiaSema=(rtcbuff[6]&0xE0)>>5;
  nvoTimeRef=nvoTimeSet;
}
/////////////////////////////////////


//***************************************
// Puesta en hora del Reloj desde SNVT's
//***************************************
when (nv_update_occurs(nviTimeSet))
{ unsigned int x, y, t;
  unsigned long z;
  x=dow(nviTimeSet.day,(unsigned int)nviTimeSet.month,nviTimeSet.year);
  nvoDOW=x;
  if (x==7) {y=0;} else {y=x;}
  rtcset[0]=2;
  t=(unsigned int)(nviTimeSet.year % 4);
  ano_act=t;
  ano_ant=t;
  z=nviTimeSet.year-t;
  rtcset[1]=((nviTimeSet.second/10)*16)+(nviTimeSet.second%10);
  rtcset[2]=((nviTimeSet.minute/10)*16)+(nviTimeSet.minute%10);
  rtcset[3]=((nviTimeSet.hour/10)*16)+(nviTimeSet.hour%10);
  rtcset[4]=((nviTimeSet.day/10)*16)+(nviTimeSet.day%10)+(t<<6);
  rtcset[5]=((nviTimeSet.month/10)*16)+(nviTimeSet.month%10)+(y*32);
  if (!io_out(io_i2c_bus,&rtcset,rtc_addr,6)) I2CFails++;
  rtcset[0]=16;
  rtcset[1]=(unsigned int)(z / 256);
  rtcset[2]=(unsigned int)(z % 256);
  if (!io_out(io_i2c_bus,&rtcset,rtc_addr,3)) I2CFails++;
  nvoTimeRef=nviTimeSet;
  nvoTimeSet=nviTimeSet;
  // Nueva hora, propagar salida....
  propagate(nvoTimeRef);
}
//*************************************************************


/////////////////////////////////////////////////////////////////////////////
// I/O event tasks
///////////////////////////////// Functions /////////////////////////////////

//--------------------------------------------------------------------------
// Volver a leer el reloj... para otro ritmo, ajustar timer
//--------------------------------------------------------------------------
when (timer_expires(lectura)){
  unsigned int sumador;
  signed int z;
  rtc_cont=0;
  if (!io_out(io_i2c_bus,&rtc_cont,rtc_addr,1)) I2CFails++;
  if (!io_in(io_i2c_bus,rtcbuff,rtc_addr,18)) I2CFails++;
  // Ver posibilidad de comunicar error en caso de fallo en lectura reloj
  ano_act=( (rtcbuff[5]&0xC0)>>6);
  if ( (ano_act!=ano_ant) && (ano_act==0) ){ sumador=4; } else { sumador=0; }
  ano=(rtcbuff[16]*256)+rtcbuff[17]+ano_act+sumador;
  ano_ant=ano_act;                                                     // Igualar comparadores
  nvoTimeSet.second=(((rtcbuff[2]&0xF0)>>4)*10)+(rtcbuff[2]&0x0F);
  nvoTimeSet.minute=(((rtcbuff[3]&0xF0)>>4)*10)+(rtcbuff[3]&0x0F);
  nvoTimeSet.hour=(((rtcbuff[4]&0x30)>>4)*10)+(rtcbuff[4]&0x0F);
  nvoTimeSet.day=(((rtcbuff[5]&0x30)>>4)*10)+(rtcbuff[5]&0x0F);
  nvoTimeSet.month=(((rtcbuff[6]&0x10)>>4)*10)+(rtcbuff[6]&0x0F);
  nvoTimeSet.year=ano;
  nvoDiaSema=(rtcbuff[6]&0xE0)>>5;
  if (sumador==4) { rtcset[0]=16;   // Escribir a partir de dirección 16
                    rtcset[1]=(unsigned int)(nvoTimeSet.year / 256);
                    rtcset[2]=(unsigned int)(nvoTimeSet.year % 256);
                    if (!io_out(io_i2c_bus,&rtcset,rtc_addr,3)) I2CFails++;
                    sumador=0; }

  //********************************************************************//
  // Para no saturar la red, la hora se propaga cada minuto, suficiente
  // para la mayoría de los sistemas de control
  // Estamos en un nuevo minuto ?
  if ( nvoTimeSet.minute != minut ) {
     nvoTimeRef=nvoTimeSet;
     minut=nvoTimeSet.minute; }
  //-------------------------------------------------------------------- 
}

//***************************//
// Calcula dia de la Semana //
//***************************//
// Lunes=1....Domingo=7
unsigned short dow(unsigned short d, unsigned short m, unsigned long a) {
unsigned int an, dato;
an=(unsigned int)(a-1900);
if (m >= 3) m -= 3;
    else {
        m += 9;
        an--;
    }
    dato=(an + an / 4 + (m * 13 + 2) / 5 + d + 3) % 7 + 1;
    dato--;
    if (dato==0) {dato=7;}
    return (dato);
}
//*****************************


//*************
// Año bisiesto
//*************
// Devuelve '0' si es bisiesto y '1' si no lo es para restar a 29 dias de febrero...
int es_bisi(long ano){
  int a;
  if ((ano % 4)!=0) {a=0;} else {a=1;};
  return a;
}
//*************
hostgator coupon or play poker on party poker
Copyright 2011 NeuronC y RTC.
Joomla Templates by Wordpress themes free