[Беспроводные технологии, Программирование микроконтроллеров] Как подключить АЦП HX711 к NRF52832
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
1. Введение
На повестке дня стояла задача разработать протокол общения микроконтролера nrf52832 с двумя полумостовыми китайскими тензодатчиками.
Задача оказалась не простой, так как столкнулся с отсутствием какой — либо внятной информации. Вероятнее, что «корень зла» находится в самом SDK от Nordic Semiconductor — это постоянное обновления версий, некоторая избыточность и запутанность функционала. Пришлось писать все с нуля.
Я думаю эта тема довольно актуальна исходя из того, что данный чип обладает BLE стеком и целым набором “вкусняшек” режима энергосбережения. Но в техническую часть я сильно углубляться не буду, так как на эту тему написано немало статей.
2. Описание проекта
Железо:
- Adafruit Feather nRF52 Bluefruit LE (то что оказалось под рукой)
- АЦП 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 мкс.
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;// тактируем на частоте 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);// срабатывает по сравнению
Инициализируем нулевой таймер и его обработчик.
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();//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
Выводы
Спасибо всем за внимание, надеюсь эта статья будет полезной и сократит драгоценное время на поиск решения для разработчиков. Хочу сказать, что технический подход который использует Nordic в своих платформах довольно интересен с точки зрения энергоэффективности.
P.S.
Проект еще в процессе разработки, поэтому если будет интересна эта тема в следующей статье я постараюсь описать алгоритм калибровки датчиков веса, а также подключения BLE стека.
Материалы
===========
Источник:
habr.com
===========
Похожие новости:
- [C, JavaScript, Интернет вещей, Программирование микроконтроллеров, Разработка для интернета вещей] Термостат на ThingJS (beta)
- [Беспроводные технологии, Космонавтика, Разработка систем связи, Транспорт] Военные США разрешили SpaceX повторно запустить Falcon 9 с GPS-спутником
- [Системное программирование, Программирование микроконтроллеров, Компьютерное железо] Моделирование прошивки в среде ModelSim с использованием моделей на языке SystemC
- [Гаджеты, Информационная безопасность, Программирование микроконтроллеров, Умный дом] Исследователь в рамках теста заразил умную кофеварку вымогателем и запустил на ней майнинг криптовалюты
- [Open source, Интернет вещей, Облачные сервисы, Разработка для интернета вещей] Знакомство с Node-RED и потоковое программирование в Yandex IoT Core
- [3D-принтеры, DIY или Сделай сам, Программирование микроконтроллеров] Как управлять CNC-роутером, не привлекая внимания…
- [Интернет вещей, Программирование микроконтроллеров, Разработка для интернета вещей, Разработка систем связи] MQTTv5.0: Обзор новых функций. Часть 2
- [DIY или Сделай сам, Космонавтика, Научно-популярное, Программирование микроконтроллеров] Per aspera ad astra, или как я строил ракету. Часть 2. Собираем альтиметр на STM32 и BMP280
- [C, Программирование микроконтроллеров, 3D-принтеры] Прошивка для фотополимерного LCD 3D-принтера своими руками. Часть 3
- [3D-принтеры, C, Программирование микроконтроллеров] Прошивка для фотополимерного LCD 3D-принтера своими руками. Часть 2
Теги для поиска: #_besprovodnye_tehnologii (Беспроводные технологии), #_programmirovanie_mikrokontrollerov (Программирование микроконтроллеров), #_atsp_hx711 (ацп hx711), #_nrf52832, #_elektronnye_vesy (электронные весы), #_tenzodatchiki (тензодатчики), #_internet_veschej (интернет вещей), #_cortexm4, #_besprovodnye_tehnologii (
Беспроводные технологии
), #_programmirovanie_mikrokontrollerov (
Программирование микроконтроллеров
)
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 08:46
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
1. Введение На повестке дня стояла задача разработать протокол общения микроконтролера nrf52832 с двумя полумостовыми китайскими тензодатчиками. Задача оказалась не простой, так как столкнулся с отсутствием какой — либо внятной информации. Вероятнее, что «корень зла» находится в самом SDK от Nordic Semiconductor — это постоянное обновления версий, некоторая избыточность и запутанность функционала. Пришлось писать все с нуля. Я думаю эта тема довольно актуальна исходя из того, что данный чип обладает BLE стеком и целым набором “вкусняшек” режима энергосбережения. Но в техническую часть я сильно углубляться не буду, так как на эту тему написано немало статей. 2. Описание проекта Железо:
Софт:
Все находится в одном проекте, придется только подшаманить 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 мкс. 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); После чего инициализируем PPI модуль и коммутируем наш таймер к выходу PD_SCL, для генерирования импульсов длительность 10мкс при наступление события сравнения, а также включаем 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);// срабатывает по сравнению Инициализируем нулевой таймер и его обработчик. 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();//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 Выводы Спасибо всем за внимание, надеюсь эта статья будет полезной и сократит драгоценное время на поиск решения для разработчиков. Хочу сказать, что технический подход который использует Nordic в своих платформах довольно интересен с точки зрения энергоэффективности. P.S. Проект еще в процессе разработки, поэтому если будет интересна эта тема в следующей статье я постараюсь описать алгоритм калибровки датчиков веса, а также подключения BLE стека. Материалы =========== Источник: habr.com =========== Похожие новости:
Беспроводные технологии ), #_programmirovanie_mikrokontrollerov ( Программирование микроконтроллеров ) |
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 08:46
Часовой пояс: UTC + 5