Как да свържете ADC HX711 с NRF52832

1. Въведение

На дневен ред стоеше задачата да се разработи протокол за комуникация между микроконтролера nrf52832 и два полумостови китайски тензодатчика.

Задачата се оказа не лесна, тъй като се сблъсках с отсъствието на ясна информация. По-вероятно е «коренът на злото» да е в самия SDK от Nordic Semiconductor — постоянно обновяване на версиите, известна излишност и объркване на функционалността. Приличаше, че ще трябва да пиша всичко от нулата.

Мисля, че тази тема е доста актуална, като се има предвид, че този чип притежава BLE стек и цял набор от «вкусни неща» от режима на пестене на енергия. Но аз няма да се задълбочавам в техническите детайли, тъй като по темата са написани много статии.

2. Описание на проекта

Как да свържете ADC HX711 с NRF52832

Хардуер:

  • Adafruit Feather nRF52 Bluefruit LE (това, което се оказа под ръка)
  • ADC HX711
  • Китайски тензодатчици 2 бр. (50х2 кг)
  • Програматор ST-LINK V2

Софт:

  • IDE VSCODE
  • NRF SDK 16
  • OpenOCD
  • Програматор ST-LINK V2

Всичко е в един проект, просто ще трябва да променя Makefile (да посоча местоположението на вашия SDK).

3. Описание на кода

Ще използваме GPIOTE модула за работа с периферията, на базата на свързването на задачи и събития, а също и PPI модула за прехвърляне на данни от една периферия на друга без участието на процесора.

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); //настройваме на изход

Настройваме синхронизационната линия PD_SCL за изход за генериране на импулси с продължителност 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); //включваме таймера
}
 

Настройваме данната линия DOUT за четене на състоянието на готовност HX711; при наличие на ниско ниво се задейства обработчика, в който изключваме прекъсването и стартираме таймера за генериране на синхронизиращи импулси на изхода 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); 

// включаем gpiote

След което инициализираме PPI модула и свързваме нашия таймер с изхода PD_SCL, за генериране на импулси с продължителност 10 мкс при настъпване на събитие на сравнение, а също така активираме GPIOTE модула.


nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG; // по подразбиране
   timer_cfg.frequency = NRF_TIMER_FREQ_1MHz; // такнираме на честота 1MHz
   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); // сработва при сравнение

Инициализираме нулевия таймер и неговия обработчик.

  if(m_counter%2 != 0 && m_counter<=48){
       buffer <<= 1; // променлива на прочетените данни
        c_counter++; // брояч на положителните импулси
           if(nrf_gpio_pin_read(DOUT))buffer++; //считаме състоянието на входа
   }

Най-интересното става в обработчика на таймера. Периода на импулсите е 20 мкс. Интересуват ни нечетните импулси (на възходящ фронт) и при условие, че броят им не надвишава 24, а събитията — 48. При всяко нечетно събитие се извършва прочитане на 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(); // деактивираме 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 Създаване на таймери.
*\/ 
static void create_timers()
{
   ret_code_t err_code;
 
   \/\// Създаване на таймери
   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 (скорост на предаване 115200, TX — 6 пин, RX — 8 пин) всички настройки са в sdk_config.h

Как да свържете ADC HX711 с NRF52832

Изводи

Благодаря на всички за вниманието, надявам се тази статия да бъде полезна и да спести ценно време в търсене на решения за разработчиците. Искам да кажа, че техническият подход, който използва Nordic в своите платформи, е доста интересен от гледна точка на енергийната ефективност.

P.S.

Проектът е все още в процес на разработка, затова, ако тази тема ви интересува, в следващата статия ще се опитам да опиша алгоритъма за калибриране на сензорите за тегло, както и свързването на BLE стека.

Материали

Източник: habr.com

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