Wie man den ADC HX711 mit dem NRF52832 verbindet

1. Einleitung

Auf der Agenda stand die Entwicklung eines Kommunikationsprotokolls für den Mikrocontroller nrf52832 zur Anbindung an zwei halbbrückige chinesische Dehnungssensoren.

Die Aufgabe erwies sich als schwierig, da ich auf das Fehlen klarer Informationen stieß. Wahrscheinlich liegt das „Ursache des Übels“ im SDK von Nordic Semiconductor — regelmäßige Versionsupdates, eine gewisse Überladung und die Verwirrung des Funktionsumfangs. Ich musste alles von Grund auf neu schreiben.

Ich denke, dieses Thema ist ziemlich aktuell, da dieser Chip über einen BLE-Stack und eine ganze Reihe von „Leckerbissen“ im Energiesparmodus verfügt. Ich werde jedoch nicht zu tief in die technischen Einzelheiten eintauchen, da zu diesem Thema bereits viele Artikel geschrieben wurden.

2. Projektbeschreibung

Wie man den ADC HX711 mit dem NRF52832 verbindet

Hardware:

  • Adafruit Feather nRF52 Bluefruit LE (das, was zur Hand war)
  • ADC HX711
  • Chinesische Dehnungssensoren 2 Stk. (50x2 kg)
  • Programmierer ST-LINK V2

Software:

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

Alles befindet sich in einem einzigen Projekt; ich muss nur das Makefile anpassen (den Standort Ihres SDK angeben).

3. Beschreibung des Codes

Wir werden das GPIOTE-Modul verwenden, um mit Peripheriegeräten basierend auf Aufgaben- und Ereignisbindungen zu arbeiten, sowie das PPI-Modul, um Daten von einer Peripherie zur anderen ohne CPU-Intervention zu übertragen.

ret_code_t err_code;
   err_code = nrf_drv_gpiote_out_init(PD_SCK, &config); //wir konfigurieren als Ausgang
   nrf_drv_gpiote_out_config_t config = GPIOTE_CONFIG_OUT_TASK_TOGGLE(false); //wir werden den Pin für Pulsaktionen umschalten
   err_code = nrf_drv_gpiote_out_init(PD_SCK, &config); //wir konfigurieren als Ausgang

Wir konfigurieren die Synchronisationsleitung PD_SCL als Ausgang zur Generierung von Impulsen mit einer Dauer von 10 µs.

   nrf_drv_gpiote_in_config_t gpiote_config = GPIOTE_CONFIG_IN_SENSE_HITOLO(false); // Übergang des Pegels von hoch auf niedrig
   nrf_gpio_cfg_input(DOUT, NRF_GPIO_PIN_NOPULL); // als Eingang ohne 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); //wir deaktivieren die Unterbrechung
    nrf_drv_timer_enable(&m_timer0); //wir aktivieren den Timer
}
 

Wir konfigurieren die Datenleitung DOUT zum Lesen des Bereitstellungsstatus des HX711, bei niedrigem Pegel aktiviert sich der Handler, der die Unterbrechung deaktiviert und den Timer für die Generierung synchronisierender Impulse am Ausgang PD_SCL startet.

 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)); // verbinden Sie den Timer mit dem Ausgang
   APP_ERROR_CHECK(err_code);
   err_code = nrf_drv_ppi_channel_enable(m_ppi_channel1); // aktivieren Sie den Kanal
   APP_ERROR_CHECK(err_code);
   nrf_drv_gpiote_out_task_enable(PD_SCK); 

// включаем gpiote

Danach initialisieren wir das PPI-Modul und verbinden unseren Timer mit dem Ausgang PD_SCL, um Impulse mit einer Dauer von 10 µs bei Eintritt des Vergleichsereignisses zu erzeugen, und aktivieren auch das GPIOTE-Modul.


nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG; // Standardkonfiguration
   timer_cfg.frequency = NRF_TIMER_FREQ_1MHz; // Taktfrequenz von 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); // wird bei Vergleich ausgelöst

Wir initialisieren den Null-Timer und seinen Handler.

  if(m_counter%2 != 0 && m_counter<=48){
       buffer <<= 1; // Variable für gelesene Daten
        c_counter++; // Zähler für positive Impulse
           if(nrf_gpio_pin_read(DOUT))buffer++; // Zustand des Eingangs lesen
   }

Das Interessanteste geschieht im Timer-Handler. Die Periode der Impulse beträgt 20 µs. Uns interessieren die ungeraden Impulse (bei steigendem Flankenwechsel) und unter der Bedingung, dass ihre Anzahl nicht mehr als 24 beträgt, und die Ereignisse – 48. Bei jedem ungeraden Ereignis erfolgt das Auslesen von DOUT.

Aus dem Datenblatt geht hervor, dass die Anzahl der Impulse mindestens 25 betragen sollte, was einem Verstärkungsfaktor von 128 entspricht (im Code habe ich 25 Impulse verwendet). Dies entspricht 50 Timerereignissen, die das Ende des Datenrahmens anzeigen.

 ++m_counter; // Zähler für Ereignisse
if(m_counter==50){
      nrf_drv_timer_disable(&m_timer0); // Timer deaktivieren
       m_simple_timer_state = SIMPLE_TIMER_STATE_STOPPED; //
       buffer = buffer ^ 0x800000;
       hx711_stop(); // hx711 ausschalten
       }
   

Nach diesem deaktivieren wir den Timer und verarbeiten die Daten (laut Datenblatt) und versetzen den HX711 in den Energiesparmodus.


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

Wir warten auf ein Ereignis vom RTC-Timer mit einem Intervall von 10 Sekunden (dies liegt bereits in Ihrem Ermessen); im Handler starten wir HX711, indem wir einen Interrupt über die DOUT-Leitung auslösen.

Ein weiterer Punkt ist, dass die Logs über UART ausgegeben werden (Baudrate 115200, TX — Pin 6, RX — Pin 8), alle Einstellungen befinden sich in sdk_config.h.

Wie man den ADC HX711 mit dem NRF52832 verbindet

Fazit

Vielen Dank für eure Aufmerksamkeit, ich hoffe, dieser Artikel wird nützlich sein und wertvolle Zeit für die Entwickler beim Finden von Lösungen sparen. Ich möchte erwähnen, dass der technische Ansatz, den Nordic in seinen Plattformen verwendet, aus Sicht der Energieeffizienz ziemlich interessant ist.

P.S.

Das Projekt befindet sich noch in der Entwicklungsphase, daher werde ich, falls dieses Thema von Interesse ist, im nächsten Artikel versuchen, den Algorithmus zur Kalibrierung der Gewichtssensoren sowie die Verbindung zum BLE-Stack zu beschreiben.

Materialien

Quelle: habr.com

Купить надежный хостинг для сайтов с защитой от DDoS, VPS VDS серверы 🔥 Купить надежный хостинг для сайтов с защитой от DDoS, VPS VDS серверы | ProHoster