Cómo conectar HX711 ADC a NRF52832

1. Introducción



En la agenda estaba la tarea de desarrollar un protocolo de comunicación para el microcontrolador nrf52832 con dos galgas extensométricas chinas de medio puente.



La tarea resultó no ser fácil, ya que me enfrenté a la ausencia de información inteligible. Es más probable que la "raíz del mal" esté en el propio SDK de Nordic Semiconductor: se trata de actualizaciones de versión constantes, algo de redundancia y confusión de funciones. Tuve que escribir todo desde cero.



Creo que este tema es bastante relevante considerando que este chip tiene una pila BLE y un conjunto completo de "dulces" del modo de ahorro de energía. Pero no profundizaré en la parte técnica, ya que se han escrito muchos artículos sobre este tema.



2. Descripción del proyecto



imagen



Planchar:



  • Adafruit Feather nRF52 Bluefruit LE (lo que pasó a estar a mano)
  • ADC HX711
  • Galgas extensométricas chinas 2 uds. (50x2 kg)
  • Programador ST-LINK V2


Software:



  • IDE VSCODE
  • SDK 16 de NRF
  • OpenOCD
  • Programador ST-LINK V2




Todo está en un proyecto, solo tienes que chamanar Makefile (especifica la ubicación de tu SDK).



3. Descripción del código



Usaremos el módulo GPIOTE para trabajar con periféricos basado en la vinculación de tareas y eventos, así como el módulo PPI para transferir datos de un periférico a otro sin la participación del procesador.





ret_code_t err_code;
   err_code = nrf_drv_gpiote_out_init(PD_SCK, &config);//  
   nrf_drv_gpiote_out_config_t config = GPIOTE_CONFIG_OUT_TASK_TOGGLE(false);//    
   err_code = nrf_drv_gpiote_out_init(PD_SCK, &config);//  


Configuramos la línea de sincronización PD_SCL a la salida para generar pulsos con una duración de 10 μs.



   nrf_drv_gpiote_in_config_t  gpiote_config = GPIOTE_CONFIG_IN_SENSE_HITOLO(false);//      
   nrf_gpio_cfg_input(DOUT, NRF_GPIO_PIN_NOPULL);//    
   err_code = nrf_drv_gpiote_in_init(DOUT, &gpiote_config, gpiote_evt_handler); 


static void gpiote_evt_handler(nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t action)
{
    nrf_drv_gpiote_in_event_disable(DOUT);// 
    nrf_drv_timer_enable(&m_timer0);// 
}
 


Configuramos la línea de datos DOUT para leer el estado listo del HX711, si hay un nivel bajo, se dispara el manejador en el que deshabilitamos la interrupción e iniciamos el temporizador para generar pulsos de reloj en la salida PD_SCL.



 err_code = nrf_drv_ppi_channel_alloc(&m_ppi_channel1);
   APP_ERROR_CHECK(err_code);
   err_code = nrf_drv_ppi_channel_assign(m_ppi_channel1,                                         nrf_drv_timer_event_address_get(&m_timer0, NRF_TIMER_EVENT_COMPARE0),                                           nrf_drv_gpiote_out_task_addr_get(PD_SCK));//    
   APP_ERROR_CHECK(err_code);
   err_code = nrf_drv_ppi_channel_enable(m_ppi_channel1);//  
   APP_ERROR_CHECK(err_code);
   nrf_drv_gpiote_out_task_enable(PD_SCK); 
// habilitar gpiote

Después de eso, inicializamos el módulo PPI y cambiamos nuestro temporizador a la salida PD_SCL, para generar pulsos con una duración de 10 μs cuando ocurre el evento de comparación, y también encendemos el módulo GPIOTE.




nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;//  
   timer_cfg.frequency = NRF_TIMER_FREQ_1MHz;//    1
   ret_code_t err_code = nrf_drv_timer_init(&m_timer0, &timer_cfg, timer0_event_handler);
   APP_ERROR_CHECK(err_code);
   nrf_drv_timer_extended_compare(&m_timer0,
                                  NRF_TIMER_CC_CHANNEL0,
                                  nrf_drv_timer_us_to_ticks(&m_timer0,
                                                            10),
                                  NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK,
                                  true);//   


Inicializamos el temporizador cero y su controlador.





  if(m_counter%2 != 0 && m_counter<=48){
       buffer <<= 1;//   
        c_counter++;//    
           if(nrf_gpio_pin_read(DOUT))buffer++;//  
   }


Lo más interesante sucede en el controlador del temporizador. El período de pulso es de 20 μs. Nos interesan los pulsos impares (en el flanco ascendente) y siempre que su número no sea superior a 24 y haya 48 eventos. Para cada evento impar, se lee DOUT



, 25, 128 ( 25 ), 50 , .



 ++m_counter;//  
if(m_counter==50){
      nrf_drv_timer_disable(&m_timer0);//  
       m_simple_timer_state = SIMPLE_TIMER_STATE_STOPPED;//
       buffer = buffer ^ 0x800000;
       hx711_stop();//j hx711
       }
   


( ) HX711 .




static void repeated_timer_handler(void * p_context)
{
   nrf_drv_gpiote_out_toggle(LED_2);
   if(m_simple_timer_state == SIMPLE_TIMER_STATE_STOPPED){
      	hx711_start();//  hx711
       nrf_drv_gpiote_out_toggle(LED_1);
       m_simple_timer_state = SIMPLE_TIMER_STATE_STARTED;
   }
  
}
/**@brief Create timers.
*/
static void create_timers()
{
   ret_code_t err_code;
 
   // Create timers
   err_code = app_timer_create(&m_repeated_timer_id,
                               APP_TIMER_MODE_REPEATED,
                               repeated_timer_handler);
   APP_ERROR_CHECK(err_code);
}


RTC 10 ( ) HX711, DOUT.



, UART (baud rate 115200, TX — 6 , RX — 8 ) sdk_config.h



imagen





Gracias a todos por su atención, espero que este artículo sea de utilidad y ahorre un tiempo valioso para los desarrolladores que buscan una solución. Quiero decir que el enfoque técnico que utiliza Nordic en sus plataformas es bastante interesante en términos de eficiencia energética.



PD



El proyecto aún está en desarrollo, por lo que si este tema es interesante en el próximo artículo intentaré describir el algoritmo para calibrar los sensores de peso, así como conectar la pila BLE.



Materiales






All Articles