Система распределенного сбора агрометеорологических данных

Появилась задача создания системы распределенного сбора агрометеорологических данных, состоящей из базовой станции, передающей по GSM данные на сервер, и небольших автономных датчиков температуры.

Станция должна обеспечить сбор данных с 20-30 датчиков на площади 10га – для этого станция и датчики будут общаться с помощью LoRa.

 Пока едут комплектующие для базовой станции, решено было заняться разработкой датчиков температуры. В качестве контроллера выбран CH32V003- китайский RISC-V контроллер с 16кб FLASH и 2кБ RAM, стоимостью 20 рублей. При такой стоимости он имеет достаточно богатую периферию: SPI, I2C, USART, DMA, два таймера.

 Для начала решил проверить энергопотребление в режиме сна – для автономного устройства, питаемого от небольшой солнечной панели это очень критично.

Что интересно, режим Standby – более экономный режим чем Sleep, хотя обычно наоборот.

Для выхода из режима Standby может применяться встроенный низкочастотный таймер – AWU. Он тактируется от низкочастотного встроенного источника – LSI (128kHz).

Из доступных настроек – делитель частоты до 61440 раз, и регистр-счетчик с максимальным значением 63.

Для запуска режима сна нужно запустить тактирование AWU, настроить делитель и задать регистр-счетчик. Каждый тик таймера из регистра вычитается 1, и при достижении 0 генерируется пробуждающее событие.

После этого при вызове функции PWR_EnterSTANDBYMode(PWR_STANDBYEntry_WFE)

Контроллер уходит в сон, а спустя заданное время – просыпается и продолжает выполнение программы.

Но! Что-то странное происходило при отправке в сон контроллера.

Вместо ожидаемых 0.01мА контроллер потребляет целых 1.5мА – почти как при работе.

Оказалось, что после прошивки нужно отключить питание и подключить снова – тогда сон работает нормально.

Видимо, модуль, отвечающий за прошивку контроллера, оставался активным несмотря на сон. Кнопка Reset также не влияла на энергопотребление.

Когда проблема со сном была решена, можно было переходить к следующему этапу – работа с модулем LoRa sx1276. Тут тоже не обошлось без приключений. Для начала необходимо было портировать библиотеку для этого модуля. В качестве основы я взял библиотеку для STM32 HAL

(https://github.com/belyalov/stm32-hal-libraries/blob/master/doc/lora.md )

По большей части портирование заключалось в переписывании 4 функций, отвечающих за взаимодействие с шиной SPI.

И тут начались приключения.

SPI включает в себя 4 сигнала – SCK(тактирование), MISO (данные от слейва к мастеру) ,MOSI (данные от мастера к слейву), NSS (выбор слейва). Все эти сигналы выведены на пины контроллера —  SCK(PC5), MISO(PC7), MOSI(PC6), NSS (PC1). И, если на первый взгляд с линиями SCK, MOSI , MISO всё было в порядке, то с ногой NSS что-то было явно не так – она не выставлялась в 0 при начале передачи данных, и не возвращалась в 1 при окончании.

Решено было использовать другую ногу контроллера для управления линией NSS. Для этого после каждой передачи данных в регистр SPI проверяется флаг окончания работы SPI SPI_I2S_FLAG_BSY, когда флаг становится равным 0 – можно отключать NSS.

Далее возникла проблема с приемом данных. Для чтения из устройства SPI контроллер должен отправить какие-то данные, чтобы прочитать ответ – но, из-за того, что для SPI используется всего один регистр DATAR для чтения и отправки, контроллер читал данные, которые он же и отправил. Пришлось сделать костыль – после отправки читать регистр в пустоту.

Таким образом результирующие функции для работы с SPI выглядят так:

А функции работы с регистрами модуля так:

Аналогично необходимо подкорректировать функции для работы с FIFO модуля:

После корректировок модуль заработал, и успешно обменивался данными с другим модулем:

Теперь можно было приступать к работе с термодатчиком – в качестве которого был выбран DS18B20 – довольно распространённый цифровой датчик,  работающий по шине OneWire.

Шина OneWire(https://www.engineersgarage.com/what-is-the-1-wire-protocol/)  – однопроводная двунаправленная шина, позволяющая подключить несколько подобных устройств всего одним сигнальным проводом ( и одна земля).

Данные на шине кодируются длительностью низкого уровня:

Для работы с датчиком была найдена библиотека (https://github.com/Montecri/DS18B20_CH32V/tree/main )

Однако, она не заработала – для работы с шиной необходимо быстро переключать GPIO контроллера из режима выхода в режим входа  и наоборот, а для управления этим процессом использовалась готовые блоки кода, стандартные для CH32V003:

Внутри такой функции – ещё более 70 строк кода!

Такой вариант управления никак не годится для интерфейса, где требуются задержки в буквально несколько тактов процессора. Поэтому, решено было использовать прямое обращение к регистрам GPIO

Я не стал переделывать функцию, чтобы она была универсальная для любого пина, а просто рассчитал значения для используемого у меня пина PD0. Первые четыре бита – относятся к пину 0:

Функции стали гораздо компактнее, и значительно быстрее:

Вот так выглядит передача данных на шине:

А до модификации логический анализатор не мог даже распознать данные

Также подверглись модификации функции чтения и записи данных на выход:

После модификаций датчик успешно выходит на связь и передает данные:

Добавить комментарий