Autor Tema: Calibrar el rtc por "smooth calibration"  (Leído 6344 veces)

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

Desconectado Picuino

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 5610
    • Picuino
Re:Calibrar el rtc por "smooth calibration"
« Respuesta #30 en: 23 de Enero de 2020, 18:21:14 »
Tiene un pin de 1PPS.

En la tercera foto se puede ver, en la serigrafia del bottom.

El módulo es estándar. Busca «neo6 datasheet u-blox» en google y te aparece el datasheet.

El error de la señal es de 60ns cada segundo (mejor que 0,1ppm).
Se sincroniza con el flanco de subida.

Saludos.
« Última modificación: 23 de Enero de 2020, 18:24:12 por Picuino »

Desconectado juaperser1

  • Colaborador
  • DsPIC30
  • *****
  • Mensajes: 2901
Re:Calibrar el rtc por "smooth calibration"
« Respuesta #31 en: 29 de Enero de 2020, 04:30:30 »
Tiene un pin de 1PPS.

En la tercera foto se puede ver, en la serigrafia del bottom.

El módulo es estándar. Busca «neo6 datasheet u-blox» en google y te aparece el datasheet.

El error de la señal es de 60ns cada segundo (mejor que 0,1ppm).
Se sincroniza con el flanco de subida.

Saludos.

Ok pues me comprare un gps de estos y lo calibraré con esto. Pero estoy teniendo problemas para comprender el ejemplo de aplicación del smooth calibration (https://www.st.com/en/embedded-software/x-cube-rtc.html)

La verdad es que nunca he utilizado un timer como contador o capturador o como lo este esando en el ejemplo, a ver si alguien me lo puede aclarar, dejo los codigos:

inicializacion de los timer:

Código: [Seleccionar]
/* TIM2 init function */
void MX_TIM2_Init(void)
{
  TIM_ClockConfigTypeDef s_clock_source_config;
  TIM_SlaveConfigTypeDef s_slave_config;
  TIM_MasterConfigTypeDef s_master_config;
  TIM_IC_InitTypeDef s_config_ic;
  TIM_OC_InitTypeDef s_config_oc;

  hTim2.Instance = TIM2;
  hTim2.Init.Prescaler = 0;
  hTim2.Init.CounterMode = TIM_COUNTERMODE_UP;
  hTim2.Init.Period = 0xFFFFFFFF;
  hTim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;

  if (HAL_TIM_Base_Init(&hTim2) != HAL_OK)
  {
    Error_Handler();
  }

  s_clock_source_config.ClockSource = TIM_CLOCKSOURCE_ETRMODE2;
  s_clock_source_config.ClockPolarity = TIM_CLOCKPOLARITY_NONINVERTED;
  s_clock_source_config.ClockPrescaler = TIM_CLOCKPRESCALER_DIV1;
  s_clock_source_config.ClockFilter = 0;
  if (HAL_TIM_ConfigClockSource(&hTim2, &s_clock_source_config) != HAL_OK)
  {
    Error_Handler();
  }

  if (HAL_TIM_IC_Init(&hTim2) != HAL_OK)
  {
    Error_Handler();
  }

  if (HAL_TIM_OC_Init(&hTim2) != HAL_OK)
  {
    Error_Handler();
  }

  s_slave_config.SlaveMode = TIM_SLAVEMODE_RESET;
  s_slave_config.InputTrigger = TIM_TS_ITR2;
  if (HAL_TIM_SlaveConfigSynchronization(&hTim2, &s_slave_config) != HAL_OK)
  {
    Error_Handler();
  }

  s_master_config.MasterOutputTrigger = TIM_TRGO_RESET;
  s_master_config.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&hTim2, &s_master_config) != HAL_OK)
  {
    Error_Handler();
  }

  if (HAL_TIMEx_RemapConfig(&hTim2, TIM_TIM2_ETR_LSE) != HAL_OK)
  {
    Error_Handler();
  }

  s_config_ic.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING;
  s_config_ic.ICSelection = TIM_ICSELECTION_TRC;
  s_config_ic.ICPrescaler = TIM_ICPSC_DIV1;
  s_config_ic.ICFilter = 0;
  if (HAL_TIM_IC_ConfigChannel(&hTim2, &s_config_ic, TIM_CHANNEL_1) != HAL_OK)
  {
    Error_Handler();
  }

  s_config_oc.OCMode = TIM_OCMODE_TOGGLE;
  s_config_oc.Pulse = 0;
  s_config_oc.OCPolarity = TIM_OCPOLARITY_HIGH;
  s_config_oc.OCFastMode = TIM_OCFAST_DISABLE;
  if (HAL_TIM_OC_ConfigChannel(&hTim2, &s_config_oc, TIM_CHANNEL_2) != HAL_OK)
  {
    Error_Handler();
  }

  HAL_TIM_MspPostInit(&hTim2);

}
/* TIM3 init function */
void MX_TIM3_Init(void)
{
  TIM_ClockConfigTypeDef s_clock_source_config;
  TIM_MasterConfigTypeDef s_master_config;
  TIM_OC_InitTypeDef s_config_oc;

  hTim3.Instance = TIM3;
  hTim3.Init.Prescaler = 0;
  hTim3.Init.CounterMode = TIM_COUNTERMODE_UP;
  hTim3.Init.Period = 15;
  hTim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  if (HAL_TIM_Base_Init(&hTim3) != HAL_OK)
  {
    Error_Handler();
  }

  s_clock_source_config.ClockSource = TIM_CLOCKSOURCE_ETRMODE2;
  s_clock_source_config.ClockPolarity = TIM_CLOCKPOLARITY_NONINVERTED;
  s_clock_source_config.ClockPrescaler = TIM_CLOCKPRESCALER_DIV1;
  s_clock_source_config.ClockFilter = 0;
  if (HAL_TIM_ConfigClockSource(&hTim3, &s_clock_source_config) != HAL_OK)
  {
    Error_Handler();
  }

  if (HAL_TIM_OC_Init(&hTim3) != HAL_OK)
  {
    Error_Handler();
  }

  s_master_config.MasterOutputTrigger = TIM_TRGO_RESET;
  s_master_config.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&hTim3, &s_master_config) != HAL_OK)
  {
    Error_Handler();
  }

  s_config_oc.OCMode = TIM_OCMODE_TOGGLE;
  s_config_oc.Pulse = 0;
  s_config_oc.OCPolarity = TIM_OCPOLARITY_HIGH;
  s_config_oc.OCFastMode = TIM_OCFAST_DISABLE;
  if (HAL_TIM_OC_ConfigChannel(&hTim3, &s_config_oc, TIM_CHANNEL_1) != HAL_OK)
  {
    Error_Handler();
  }

  HAL_TIM_MspPostInit(&hTim3);

}

el main:

Código: [Seleccionar]
int main(void)
{
  /* MCU Configuration----------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* Configure the system clock */
  SystemClock_Config();

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_TIM3_Init();
  MX_RTC_Init();
  MX_TIM2_Init();

  if (HAL_TIM_Base_Start_IT(&hTim3) != HAL_OK)
  {
    /* Starting Error */
    Error_Handler();
  }
  /* Start channel 1 in Output compare mode */
  if (HAL_TIM_OC_Start_IT(&hTim3, TIM_CHANNEL_1) != HAL_OK)
  {
    /* Starting Error */
    Error_Handler();
  }

  /*##-1- Start TIM2 generation in interrupt mode ####################*/
  if (HAL_TIM_Base_Start_IT(&hTim2) != HAL_OK)
  {
    /* Starting Error */
    Error_Handler();
  }

  /* Start channel 1 in Input capture mode */
  if (HAL_TIM_IC_Start_IT(&hTim2, TIM_CHANNEL_1) != HAL_OK)
  {
    /* Starting Error */
    Error_Handler();
  }

  /* Start channel 2 in Output compare mode */
  if (HAL_TIM_OC_Start_IT(&hTim2, TIM_CHANNEL_2) != HAL_OK)
  {
    /* Starting Error */
    Error_Handler();
  }
  /*##-2- Start TIM2 generation in interrupt mode ####################*/

  /* Infinite loop */
  while (1)
  {
    if (CalibrationStatus == SET)
    {
      calibrate();
      CalibrationStatus  = RESET;
    }
  }
}

la funcion de calibracion:

Código: [Seleccionar]
static void calibrate(void)
{
  const int32_t cycles_expected = 0x100000; /* expected number of RTCCLK cycles during 32-seconds */
  int32_t smooth_calib_plus_pulses = RTC_SMOOTHCALIB_PLUSPULSES_RESET;
  int32_t smooth_calib_minus_pulses_value = 0x0;

  if (Calibration1stITDone == RESET)
  {
    Calibration1stITDone = SET;
  }
  else
  {
    /* update RTC_Calib */
    if ( (uint32_t) (TIM2->CCR1 >= cycles_expected))
    {
      smooth_calib_plus_pulses = RTC_SMOOTHCALIB_PLUSPULSES_RESET;
      smooth_calib_minus_pulses_value = (uint32_t) (TIM2->CCR1 - cycles_expected );
    }
    else
    {
      smooth_calib_plus_pulses = RTC_SMOOTHCALIB_PLUSPULSES_SET;
      smooth_calib_minus_pulses_value = (uint32_t) ((RTC_SMOOTH_CALIB_MINUS_MASK) - (cycles_expected - TIM2->CCR1 ));
    }
    if (smooth_calib_minus_pulses_value > RTC_SMOOTH_CALIB_MINUS_MASK)
    {
      smooth_calib_minus_pulses_value = (uint32_t) (RTC_SMOOTH_CALIB_MINUS_MASK);
    }

    HAL_RTCEx_SetSmoothCalib(&hrtc, RTC_SMOOTHCALIB_PERIOD_32SEC, smooth_calib_plus_pulses, smooth_calib_minus_pulses_value);
  }
}

y las interrupciones:

Código: [Seleccionar]
void TIM2_IRQHandler(void)
{
  TIM_HandleTypeDef *htim = &hTim2;
  if (__HAL_TIM_GET_FLAG(htim, TIM_FLAG_CC1) != RESET)
  {
    if (__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_CC1) != RESET)
    {
      if ((htim->Instance->CCMR1 & TIM_CCMR1_CC1S) != 0x00)
      {
        CalibrationStatus = SET;
      }
    }
  }
  HAL_TIM_IRQHandler(&hTim2);

}

/**
* @brief This function handles TIM3 global interrupt.
*/
void TIM3_IRQHandler(void)
{

  HAL_TIM_IRQHandler(&hTim3);

}
« Última modificación: 29 de Enero de 2020, 05:13:36 por juaperser1 »
Visita mi canal para aprender sobre electrónica y programación:

https://www.youtube.com/channel/UCxOYHcAMLCVEtZEvGgPQ6Vw

Desconectado juaperser1

  • Colaborador
  • DsPIC30
  • *****
  • Mensajes: 2901
Re:Calibrar el rtc por "smooth calibration"
« Respuesta #32 en: 29 de Enero de 2020, 05:19:37 »
Por lo que yo entiendo a ver si esta bien.

aunque en el ejemplo pone los canales de input y output de los timer en pines, esto no es necesario y se puede hacer de manera interna.

la fuente de reloj del timer 3 es el reloj de 1Hz conectado a PD2.

¿Pero usar el CH1 del timer 3 como comparador en modo toggle? esto que es?

luego el timer 2:

Este tiene como fuente de reloj el reloj LSE, el CH1 como input capture del TRC, y el CH2 como output compare de nuevo como togle on match.

y resulta que es esclavo en modo reset.

Por favor que alguien me explique como esta trabajando esto.

un saludo y gracias.
Visita mi canal para aprender sobre electrónica y programación:

https://www.youtube.com/channel/UCxOYHcAMLCVEtZEvGgPQ6Vw

Desconectado Picuino

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 5610
    • Picuino
Re:Calibrar el rtc por "smooth calibration"
« Respuesta #33 en: 29 de Enero de 2020, 13:17:55 »
Yo no puedo ayudarte con la configuración concreta de ese micro de 32bits, pero si puedo darte las líneas generales de cómo lo he programado en otros microcontroladores de 8 y de 16bits.

En principio puedes dejar a los contadores correr libremente (sin capturas ni nada). Un contador para contar pulsos de reloj de alta frecuencia (64MHz en tu caso) y otro contador para contar los pulsos de la frecuencia que quieres medir (32kHz internos o bien 1Hz externo).

Hasta ahí no deberías tener mayor problema. Los contadores trabajan de forma libre sin interrupciones ni paradas ni reseteos.

Después debes leer los valores de los contadores cuando venga un flanco de subida de la señal que estás midiendo en frecuencia (32kHz o bien 1Hz).  Esto tampoco debería ser un problema.

Por último restas de la última lectura realizada, la penúltima lectura realizada. Así tendrás las diferencias de pulsos entre un flanco y el siguiente (tanto de reloj como de pulsos de la señal a medir).

Esas diferencias son las que se utilizan en la fórmula para calcular la frecuencia. La ventaja de este método (llamdo continuous counting) es que los pequeños errores se compensan de una medición a la siguiente.

Si no sabes implementarlo en tu micro de 32 bits, pásate a uno de 8 bit y te ayudo a implementarlo.

Un saludo.

Desconectado juaperser1

  • Colaborador
  • DsPIC30
  • *****
  • Mensajes: 2901
Re:Calibrar el rtc por "smooth calibration"
« Respuesta #34 en: 03 de Febrero de 2020, 03:13:29 »
Yo no puedo ayudarte con la configuración concreta de ese micro de 32bits, pero si puedo darte las líneas generales de cómo lo he programado en otros microcontroladores de 8 y de 16bits.

En principio puedes dejar a los contadores correr libremente (sin capturas ni nada). Un contador para contar pulsos de reloj de alta frecuencia (64MHz en tu caso) y otro contador para contar los pulsos de la frecuencia que quieres medir (32kHz internos o bien 1Hz externo).

Hasta ahí no deberías tener mayor problema. Los contadores trabajan de forma libre sin interrupciones ni paradas ni reseteos.

Después debes leer los valores de los contadores cuando venga un flanco de subida de la señal que estás midiendo en frecuencia (32kHz o bien 1Hz).  Esto tampoco debería ser un problema.

Por último restas de la última lectura realizada, la penúltima lectura realizada. Así tendrás las diferencias de pulsos entre un flanco y el siguiente (tanto de reloj como de pulsos de la señal a medir).

Esas diferencias son las que se utilizan en la fórmula para calcular la frecuencia. La ventaja de este método (llamdo continuous counting) es que los pequeños errores se compensan de una medición a la siguiente.

Si no sabes implementarlo en tu micro de 32 bits, pásate a uno de 8 bit y te ayudo a implementarlo.

Un saludo.

Perfecto pues así lo voy a hacer, mucho mas simple que la manera enrevesada del ejemplo del stm32, además que en el micro que estoy usando, no puedo configurar un timer con la entrada LSE y que se dispare por el ITR, ya que es con el timer 2 y este micro no lo tiene, tiene el 1 y el 3 pero no el 2.

Por cierto, cuantas veces debería realizar la resta para dar una calibración decente?

un saludo
Visita mi canal para aprender sobre electrónica y programación:

https://www.youtube.com/channel/UCxOYHcAMLCVEtZEvGgPQ6Vw

Desconectado Picuino

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 5610
    • Picuino
Re:Calibrar el rtc por "smooth calibration"
« Respuesta #35 en: 03 de Febrero de 2020, 03:38:13 »
Con una medición de un segundo tendrás suficiente.

Desconectado juaperser1

  • Colaborador
  • DsPIC30
  • *****
  • Mensajes: 2901
Re:Calibrar el rtc por "smooth calibration"
« Respuesta #36 en: 03 de Febrero de 2020, 05:25:57 »
Con una medición de un segundo tendrás suficiente.

Pues de tu solución, a la que ofrece st con el smooth calibration, que tarda 64 segundos... anda que no hay diferencia la verdad.

voy ha hacer el hardware para capturar la señal de 1Hz y ya comentaré cuando lo tenga acabado o lo pruebe.

un saludo y gracias.
Visita mi canal para aprender sobre electrónica y programación:

https://www.youtube.com/channel/UCxOYHcAMLCVEtZEvGgPQ6Vw

Desconectado Picuino

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 5610
    • Picuino
Re:Calibrar el rtc por "smooth calibration"
« Respuesta #37 en: 03 de Febrero de 2020, 12:11:24 »
Puedes comenzar por hacer la medición de frecuencia de 32kHz.

La medición de 1Hz es para corregir el error del oscilador de alta frecuencia.

Desconectado juaperser1

  • Colaborador
  • DsPIC30
  • *****
  • Mensajes: 2901
Re:Calibrar el rtc por "smooth calibration"
« Respuesta #38 en: 04 de Febrero de 2020, 10:27:28 »
Voy ha hacer un pedido a mouser y rs, el modulito que me indicaste no esta en ninguno de los dos.

¿Conoces alguno que pueda comprar por uno de estos dos sitios? Las funciones que tenga me dan igual siempre que tenga el reloj de 1PPS.


un saludo.

son muy caros voy a comprar el de ebay y ya esta, por cierto este modulito es darle alimentación y tener disponible el 1PPS o hay que programarlo?
« Última modificación: 04 de Febrero de 2020, 10:31:57 por juaperser1 »
Visita mi canal para aprender sobre electrónica y programación:

https://www.youtube.com/channel/UCxOYHcAMLCVEtZEvGgPQ6Vw

Desconectado Picuino

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 5610
    • Picuino
Re:Calibrar el rtc por "smooth calibration"
« Respuesta #39 en: 04 de Febrero de 2020, 10:37:00 »
Hay que darle alimentación y acceso a los satélites. Con eso es suficiente.

Si no te funciona en interior, tendrás que sacar la antena por la ventana o salir fuera del edificio.

Desconectado Picuino

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 5610
    • Picuino
Re:Calibrar el rtc por "smooth calibration"
« Respuesta #40 en: 04 de Febrero de 2020, 10:39:56 »
Prueba con el GPS del teléfono móvil. Es similar.

Desconectado juaperser1

  • Colaborador
  • DsPIC30
  • *****
  • Mensajes: 2901
Re:Calibrar el rtc por "smooth calibration"
« Respuesta #41 en: 05 de Febrero de 2020, 03:54:50 »
Ok, he probado en mi taller con el GPS de 3 moviles y parece que no hay ningun problema, por lo que supongo que tampoco debe de existir con el modulito este.

Para medir la señal de 32,768 KHz, en este prototipo que no tengo conexión externa seria colocar el TIM17 en modo captura del LSE, para saber cuando me llega un flango del cristal de 32KHz, por ejemplo?

un saludo.
Visita mi canal para aprender sobre electrónica y programación:

https://www.youtube.com/channel/UCxOYHcAMLCVEtZEvGgPQ6Vw

Desconectado Picuino

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 5610
    • Picuino
Re:Calibrar el rtc por "smooth calibration"
« Respuesta #42 en: 05 de Febrero de 2020, 06:34:30 »
Tienes que configurar un contador para que cuente los pulsos del cristal de 32kHz.

Luego por interrupciones o por polling tienes que detectar el flanco de la señal de 32kHz para sincronizar la lectura de los contadores justo después del flanco.
« Última modificación: 07 de Febrero de 2020, 13:00:28 por Picuino, Razón: corregir polling »

Desconectado juaperser1

  • Colaborador
  • DsPIC30
  • *****
  • Mensajes: 2901
Re:Calibrar el rtc por "smooth calibration"
« Respuesta #43 en: 06 de Febrero de 2020, 03:57:05 »
Tienes que configurar un contador para que cuente los pulsos del cristal de 32kHz.

Luego por interrupciones o por pooling tienes que detectar el flanco de la señal de 32kHz para sincronizar la lectura de los contadores justo después del flanco.

Vale, he puesto el TIMER17 como input capture mapeado al pin MCO configurado en LSE, capturando asi los flancos de subida, he puesto que me haga toggle de un pin cada vez que tenga un flanco ascendente y veo en el osciloscopio que ese pin tiene una frecuencia de ~16,34 que es la mitad de los 32,678 al solo detectar el flanco de subida.

¿Con esto sirve o necesito controlar los dos flancos, de subida y de bajada?
Visita mi canal para aprender sobre electrónica y programación:

https://www.youtube.com/channel/UCxOYHcAMLCVEtZEvGgPQ6Vw

Desconectado Picuino

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 5610
    • Picuino
Re:Calibrar el rtc por "smooth calibration"
« Respuesta #44 en: 06 de Febrero de 2020, 08:44:49 »
Con eso sirve.
Ahora tienes que configurar otro contador para que cuente los pulsos de alta frecuencia del oscilador principal.

Los dos contadores deben funcionar a la vez.
« Última modificación: 06 de Febrero de 2020, 08:48:22 por Picuino »