Come collegare l'ADC HX711 al NRF52832

1. Introduzione

Era necessario sviluppare un protocollo di comunicazione tra il microcontrollore nrf52832 e due sensori di peso cinesi a ponte parziale.

La task si è rivelata complessa a causa della mancanza di informazioni chiare. È probabile che il problema risieda nel SDK di Nordic Semiconductor — gli aggiornamenti costanti delle versioni, alcune ridondanze e la confusione nelle funzionalità hanno complicato il tutto. Ho dovuto riscrivere tutto da zero.

Penso che questo argomento sia piuttosto attuale, considerando che questo chip dispone di uno stack BLE e un intero insieme di funzionalità avanzate per la modalità di risparmio energetico. Tuttavia, non mi addentrerò troppo nella parte tecnica, poiché sono già stati scritti molti articoli su questo tema.

2. Descrizione del progetto

Come collegare l'ADC HX711 al NRF52832

Hardware:

  • Adafruit Feather nRF52 Bluefruit LE (ciò che avevo a disposizione)
  • ADC HX711
  • Sensori di peso cinesi 2 pezzi (50x2 kg)
  • Programmatore ST-LINK V2

Software:

  • IDE VSCODE
  • NRF SDK 16
  • OpenOCD
  • Programmatore ST-LINK V2

Tutto è contenuto in un unico progetto, dovrò solo sistemare il Makefile (specificare la posizione del proprio SDK).

3. Descrizione del codice

Utilizzeremo il modulo GPIOTE per interagire con le periferiche in base all'associazione di compiti ed eventi, e il modulo PPI per trasferire dati da una periferica all'altra senza coinvolgere il processore.

ret_code_t err_code;
   err_code = nrf_drv_gpiote_out_init(PD_SCK, &config); //configuriamo l'uscita
   nrf_drv_gpiote_out_config_t config = GPIOTE_CONFIG_OUT_TASK_TOGGLE(false); //ingaggeremo il pin per un impulso
   err_code = nrf_drv_gpiote_out_init(PD_SCK, &config); //configuriamo l'uscita

Configuriamo la linea di sincronizzazione PD_SCL come uscita per generare impulsi della durata di 10 µs.

   nrf_drv_gpiote_in_config_t gpiote_config = GPIOTE_CONFIG_IN_SENSE_HITOLO(false); // passaggio del livello da alto a basso
   nrf_gpio_cfg_input(DOUT, NRF_GPIO_PIN_NOPULL); // ingresso senza pull-up
   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); //disattiviamo l'interruzione
    nrf_drv_timer_enable(&m_timer0); //attiviamo il timer
}
 

Configuriamo la linea dati DOUT per leggere lo stato di prontezza dell'HX711; quando è presente un livello basso, si attiva il gestore che disattiva l'interruzione e avvia il timer per generare impulsi di sincronizzazione in uscita su 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));// collegare il timer all'uscita
   APP_ERROR_CHECK(err_code);
   err_code = nrf_drv_ppi_channel_enable(m_ppi_channel1);// attiviamo il canale
   APP_ERROR_CHECK(err_code);
   nrf_drv_gpiote_out_task_enable(PD_SCK); 

// включаем gpiote

Dopo di che inizializziamo il modulo PPI e commutiamo il nostro timer all'uscita PD_SCL, per generare impulsi di durata 10µs all'attivarsi dell'evento di confronto, e attiviamo anche il modulo GPIOTE.


nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;// di default
   timer_cfg.frequency = NRF_TIMER_FREQ_1MHz;// impostiamo a una frequenza di 1 MHz
   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);// scatta al confronto

Inizializziamo il timer zero e il suo gestore.

  if(m_counter%2 != 0 && m_counter<=48){
       buffer <<= 1; // variabile dei dati letti
        c_counter++; // contatore degli impulsi positivi
           if(nrf_gpio_pin_read(DOUT)) buffer++; // leggiamo lo stato dell'ingresso
   }

Le cose più interessanti succedono nell'handler del timer. Il periodo degli impulsi è di 20 µs. Siamo interessati agli impulsi dispari (sul fronte ascendente) e a condizione che il loro numero non superi 24, e gli eventi 48. Ad ogni evento dispari si legge DOUT.

Dal datasheet si evince che il numero di impulsi deve essere almeno 25, corrispondente a un guadagno di 128 (nel codice ho usato 25 impulsi), equivalente a 50 eventi del timer, il che indica la fine del frame di dati.

 ++m_counter; // contatore eventi
if(m_counter==50){
      nrf_drv_timer_disable(&m_timer0); // disattiva il timer
       m_simple_timer_state = SIMPLE_TIMER_STATE_STOPPED; //
       buffer = buffer ^ 0x800000;
       hx711_stop(); // disattiva hx711
       }
   

Dopo di che, disattiviamo il timer e elaboriamo i dati (secondo il datasheet) e mettiamo HX711 in modalità a basso consumo energetico.


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();// attiviamo hx711
       nrf_drv_gpiote_out_toggle(LED_1);
       m_simple_timer_state = SIMPLE_TIMER_STATE_STARTED;
   }
  
}
/**@brief Crea timer.
*/
static void create_timers()
{
   ret_code_t err_code;
 
   // Crea timer
   err_code = app_timer_create(&m_repeated_timer_id,
                               APP_TIMER_MODE_REPEATED,
                               repeated_timer_handler);
   APP_ERROR_CHECK(err_code);
}

Aspettiamo un evento dal timer RTC con un intervallo di 10 secondi (questo è a vostra discrezione) e nell'handler avviamo l'HX711, attivando l'interruzione sulla linea DOUT.

C'è un altro punto, i log vengono emessi tramite UART (baud rate 115200, TX — pin 6, RX — pin 8) tutte le impostazioni si trovano in sdk_config.h.

Come collegare l'ADC HX711 al NRF52832

Conclusioni

Grazie a tutti per l'attenzione, spero che questo articolo sarà utile e ridurrà il tempo prezioso nella ricerca di soluzioni per gli sviluppatori. Voglio dire che l'approccio tecnico utilizzato da Nordic nelle proprie piattaforme è piuttosto interessante dal punto di vista dell'efficienza energetica.

P.S.

Il progetto è ancora in fase di sviluppo, quindi se questo argomento vi interessa, nel prossimo articolo cercherò di descrivere l'algoritmo di calibrazione dei sensori di peso, nonché il collegamento dello stack BLE.

Materiali

Fonte: habr.com

Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server 🔥 Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server | ProHoster