ChipCraft

ChipCraft

На Пикабу
249 рейтинг 10 подписчиков 11 подписок 10 постов 1 в горячем
Награды:
Удача в кармане
51

Энкодер на базе HEDR и STM32

Всем привет!

В данной статье я хочу Вам рассказать про датчик HEDR(от компании avago technologies) - это двухканальный инкрементальный оптический датчик, предназначен для измерения пройденного пути, линейной скорости, угловой скорости и направлении вращения вала.
С помощью данного датчика будет реализован энкодер на базе микроконтроллера STM32, который будет производить вычисление пройденного пути.

В данной статье будет рассмотрено:

  • Принцип работы датчика HEDR-5420-ES214;

  • Схема подключения к микроконтроллеру STM32;

  • Программная реализация (расчет пройденного пути и вывод информации на дисплей).

Технические характеристики датчика HEDR-5420-ES214

Документация на датчик

  • Напряжение питания [ 4.5 - 5.5В ];

  • Тип выхода [ квадратурный ];

  • Диаметр вала [ 5 мм ];

  • Разрешение [ 200 отсчетов на оборот ];

  • Рабочая температура [ от -10°C до +85°C ].

Принцип работы датчика HEDR-5420-ES214

Устройство состоит из трех основных компонентов:

  • Источник света (светодиод, формирующий поток света);

  • Оптическая система (линза, обеспечивает фокусировку и отражение света);

  • Фотодетектор.

Линза фокусирует излучаемый свет на кодовое колесо (диск с чередующимися отражающими и неотражающими участками), при вращении диска, отраженный свет проходит обратно через оптическую систему и попадает на фотодиоды, таким образом на их поверхности формируется чередующийся рисунок света и тени, соответствующий узору кодового диска.

Эти изменения интенсивности света преобразуются в внутренние сигналы А и В, которые проходят через компараторы в составе обработки сигналов, на выходе формируются два цифровых прямоугольных сигнала - канал А и В, находящиеся в квадратурной фазе на 90°, что позволяет микроконтроллеру определять направление вращения вала, к примеру:

  • если канал А опережает канал B - вращение происходит в одну сторону;

  • если канал B опережает канал А - вращение происходит в противоположную сторону.

Для своей задачи применяется следующая последовательность, если канал А опережает канал B - движение энкодера считается положительным, если на оборот, то движение будет отрицательным.

Осциллограмма данных полученных с датчика HEDR-5420-ES214

Осциллограмма данных полученных с датчика HEDR-5420-ES214

Схема подключения к микроконтроллеру STM32

Схема подключения HEDR и дисплея к микроконтроллеру STM32F030CCT6

Схема подключения HEDR и дисплея к микроконтроллеру STM32F030CCT6

 Макет STM32F030CCTx и HEDR

Макет STM32F030CCTx и HEDR

В данной схеме используются преобразователь напряжения DA1 (+12V +5V) и стабилизатор напряжения DA2, дисплей подключается к выводам МК 21_SCL_I2C2 и 22_SDA_I2C2, датчик HEDR подключается к выводам МК 29_CH.A и 30_CH.B, данные сигналы сначала проходят через делители, R17-R18-[CH.A] и R15-R16-[CH.B], так как датчик работает от +5V, сигналы соответственно тоже у него +5V, я всегда стараюсь дополнительно защитить МК, после делителя амплитуда сигналов снизится до +3.3V, копипастить информацию по описанию узлов преобразователя, стабилизатора, узла обвязки напряжения питания и резонатора для МК не особо хочется, поэтому кому интересно можно почитать статью [Модуль обработки и коммутации данных, с внешними управляющими устройствами по RS-485 на STM32]
Настройка микроконтроллера STM32F030CCTx в CubeIDE

Настройка RCC и SYS (в RCC выбираю Crystal/Ceramic Resonator, так как у меня внешний кварц на 8 МГц)

Настройка дисплея

Взаимодействие дисплея с МК будет через I2C2

Настройка выводов узла подключения датчика HEDR

  • TIM1_CH1 (к данному выводу будет подключаться сигнал CH.A);

  • TIM1_CH2 (к данному выводу будет подключаться сигнал CH.B).

Таймер используется в режиме Encoder mode - это специальный аппаратный режим, который позволяет микроконтроллеру автоматически подсчитывать импульсы от инкрементального датчика и определять направление вращения, данная конфигурация освобождает МК от необходимости программно обрабатывать прерывания по каждому импульсу.

Encoder Mode TI1 and TI2 данный параметр указывает, что используется оба канала датчика (A и B), это дает разрешение X4 - т.е. счетчик будет увеличиваться на 4 шага за один полный оборот.

Описание режимов

TI1 - подсчет ведется по фронту одного канала А, направление определяется по уровню В, разрешение 1.8 градусов;

TI2 - аналогично логике TI1, но базируется на канале В;

TI1 and TI2 - подсчет ведется на каждом фронте обоих каналов (А+, А-, В+, В-), направление определяется автоматически, т.е. количеством импульсов на оборот 200, я получаю 800 шагов на оборот, разрешение будет 0.45 градусов.

Input Filter - включает цифровую фильтрацию входного сигнала, помогает убрать дребезг и шум, значения от 0 до 15, чем выше значение, тем надежнее фильтрация, но будет повышаться задержка.

Polarity (Rising Edge) - счетчик реагирует на восходящие фронты сигнала.

Настройка Clock

Программная реализация ведомого устройства

Ссылка на скачивание исходного кода [ https://t.me/ChipCraft В закрепленном сообщении [ #исскуствомк_исходный_код — Исходный код для Encoder_HEDR_5420_STM32F030CCTx].

Модуль process_Encoder

Данный модуль реализует считывание сигналов с инкрементального датчика HEDR и вычисляет:

  • Количество импульсов на оборот;

  • Пройденную дистанцию;

  • Отображение данных на дисплее.

#define ENCODER_MODE_X4 4

Данный параметр отражает режим подсчета импульсов, привожу формулу

Этот режим обеспечивает максимальную точность - 0.45 на один шаг.

#define WHEEL_DIAMETR_M 0.230f // 230 мм
#define WHEEL_RADIUS_M (WHEEL_DIAMETR_M / 2.0f)

Здесь я задаю геометрические размеры колеса, на валу которого установлен датчик%

Диаметр колеса 230 мм (0.230м);

Радиус вычисляется так:

#define STEPS_PER_REV (ENCODER_PPR * ENCODER_MODE_X4)

Максимальное количество шагов за один оборот

#define CIRCUMFERENCE_M (2.0f *M_PI * WHEEL_RADIUS_M)

Длина окружности колеса - это путь, который проходит колесо за один оборот

т.е. при моем радиусе 0.115, получится за один полный оборот 0.72 м.

Функция display_init() - инициализация дисплея

  • Инициализируется драйвер дисплея;

  • Выполняется заливка экрана черным цветом;

  • На дисплее на 2 секунды отображается стартовый экран с надписью ''ChipCraft";

  • После задержки экран очищается для дальнейшей работы.

библиотеку для работы с дисплеем я взял с [https://github.com/afiskon/stm32-ssd1306/tree/master]

Функция display_update()

Отвечает за визуализацию информации на дисплее:

  • Экран предварительно очищается с помощью ssd1306_Fill(Black);

  • В верхней части по центру отображается надпись «Encoder»;

  • Ниже последовательно выводятся:

    • количество импульсов;

    • дистанция;

  • Буфер графики передается на дисплей вызовом ssd1306_UpdateScreen()

Функция encoder_Handler()

Логика работы:

  • считывание текущего значения таймера;

  • определение разницы (delta) между текущим и предыдущим значениями;

  • накопление общего счетчика enocoder_position;

  • вызов функций для вычисления дистанции и обновление дисплея.

Функция get_distance_m() - вычисление пройденной дистанции

Переводит количество импульсов датчика в физическую длину пути в (метрах).

process_Encoder.c

#include "./Project/process_Encoder.h"
#include "./Project/shared.h"
#include "./Project/ssd1306.h"
#include "./Project/ssd1306_fonts.h"
#include "main.h"
#include <stdlib.h>//abs
#include <string.h>//memset
#include <stdio.h>
#include <stdint.h>
#include <math.h>

#define ENCODER_PPR 200 // импульсов на оборот
#define ENCODER_MODE_X4 4

#define WHEEL_DIAMETR_M 0.230f // 230 мм
#define WHEEL_RADIUS_M (WHEEL_DIAMETR_M / 2.0f)

#define STEPS_PER_REV (ENCODER_PPR * ENCODER_MODE_X4)
#define CIRCUMFERENCE_M (2.0f *M_PI * WHEEL_RADIUS_M)

uint16_t current_count= 0;
int16_t delta = 0;
float distance = 0.0f;
int32_t encoder_position = 0;

uint8_t ssd1306_buffer[SSD1306_BUFFER_SIZE];


void display_init(void) {
ssd1306_Init();

ssd1306_Fill(Black);
ssd1306_SetCursor(20, 25);
ssd1306_WriteString("ChipCraft", Font_11x18, White);
ssd1306_UpdateScreen();

HAL_Delay(2000);

ssd1306_Fill(Black);
ssd1306_UpdateScreen();
}

void encoder_Handler(void) {

static uint16_t last_count = 0;
current_count = __HAL_TIM_GET_COUNTER(&htim1);

delta = (int16_t)(current_count - last_count);
encoder_position += delta;

last_count = current_count;

get_distance_m();

display_update(encoder_position, distance);

}
void display_update(int32_t pulses, float distance) {

char buf[32];

ssd1306_Fill(Black);

ssd1306_SetCursor(25, 2);
ssd1306_WriteString("Encoder" ,Font_11x18, White);

sprintf(buf, "Pulses: %ld", pulses);
ssd1306_SetCursor(2, 22);
ssd1306_WriteString(buf, Font_7x10, White);

sprintf(buf, "Dist: %.2f m", distance);
ssd1306_SetCursor(2, 36);
ssd1306_WriteString(buf, Font_7x10, White);

ssd1306_UpdateScreen();
}

float get_distance_m(void){

distance = ((float) encoder_position / STEPS_PER_REV) * CIRCUMFERENCE_M;

return distance;
}

Модуль proj_main() - главный метод

  • Выполняется инициализация дисплея;

  • Запуск таймера;

  • Запуск функции encoder_Handler().

proj_main.c

#include "./Project/shared.h"
#include "./Project/proj_main.h"
#include "./Project/process_Encoder.h"
#include "./Project/process_Encoder.h"

void proj_main()
{
volatile const char *ch = ";V-F-BIN;ver: "VER_PROG(VER_a,VER_b,VER_c);(void)ch;//0x8008b00

display_init();

HAL_TIM_Encoder_Start(&htim1, TIM_CHANNEL_ALL);

while (1){

//хэндлеры
encoder_Handler();

}//while (1)
}


Если статья показалась Вам интересной, буду рад выпустить для Вас еще множество статей исследований по всевозможным видам устройств, так что, если не хотите их пропустить — буду благодарен за подписку на мой ТГ-канал.

Показать полностью 13 1
23

Модуль обработки и коммутации данных, с внешними управляющими устройствами по RS-485 на STM32

В данной статье будет рассматриваться разработка коммутатора, для приема, обработки и передачи потока данных от GNSS-приемника и энкодера, осуществляться передача ведущему устройству будет по интерфейсу RS-485.

Интерфейс RS-485 - представляет собой промышленный стандарт физического уровня передачи данных, широко применяемый в распределенных системах управления, телеметрии и автоматизации, его ключевая особенность - использование дифференциального сигнала, что обеспечивает высокую помехоустойчивость и надежность передачи данных на значительные расстояния (до 1200 метров).

В основе работы лежит двухпроводная линия (выводы А и В), по которой передается информация в виде разности потенциалов:

  • Логическая "1" фиксируется при условии, что напряжение на линии А ниже, чем на линии B;

  • Логический "0" соответствует ситуации, когда потенциал линии А выше потенциала линии В.

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

В стандартных трансиверах интерфейса RS-485 передатчик и приемник интегрированы в одном корпусе и подключены к общей двухпроводной линии, направление выбирается выводом микроконтроллера, уровень на которой определяет в каком режиме микросхема, в приеме или в передаче.

Подробную информацию по теме интерфейса RS-485, можно изучить вот здесь [https://easyelectronics.ru/interfejs-rs-485.html].

Верхняя схема соединения устройств

Принцип взаимодействия устройств

Данная схема реализует архитектуру «ведущий-ведомый» (Master-Slave). Процесс взаимодействия можно разделить на два ключевых этапа:

  1. Этап опроса и обнаружения устройств
    При инициализации системы ведущее устройство отправляет ведомому устройству (коммутатору) запрос на получение списка активных подключенных устройств. В данном примере запрашивается статус энкодера и приемника GNSS.

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

  2. Этап сбора данных
    После успешного обнаружения активных устройств ведущее устройство инициирует цикл опроса для сбора данных. Последовательно отправляются запросы на получение данных: дистанции с энкодера и навигационной информации с приемника GNSS.

    Ведомое устройство агрегирует запрашиваемые параметры, формирует пакет данных и передает его ведущему устройству для последующей обработки.

Таким образом, коммутатор в данной системе обеспечивает централизованный сбор и передачу данных от периферийных устройств к управляющему ведущему устройству по запросу.

В данной схеме используется GNSS-приемник работающий по RS-232, о том как с ним работать я писал статью [Прием и парсинг NMEA-данных от GPS-приемника], в этой статье коммутатор будет принимать данные от GNSS приемника, собирать их в пакет и отправлять ведущему устройству по RS-485.

Для взаимодействия приема и передачи данных, коммутатор и ведущее устройство работают по внутреннему протоколу по аналогии MODBUS ASCII - являющийся одним из вариантов широко распространенного промышленного протокола Modbus, предназначаемого для организации обмена между ведущим и ведомым устройствами по последовательным линиям связи (RS-232/RS-422/RS-485).

Минимальный пример формата кадра MODBUS ASCII

  • Символ начала сообщения - ( : );

  • Адрес устройства - указывает, какому устройству предназначен кадр;

  • Код функции - определяет тип выполняемой операции (чтение, запись, диагностика);

  • Данные - содержат полезную нагрузку (адреса регистров, значения, количество слов);

  • Контрольная сумма - обеспечивает контроль целостности передачи данных;

  • Символы конца строки - (\r\n) - фиксация завершения кадра.

Подробную информацию на тему протокола Modbus, можно изучить вот здесь [https://habr.com/ru/articles/682292/], [https://habr.com/ru/articles/281430/].

Реализация протокола связи по RS-485, описывающая форматы пакетов для приема и передачи данных между ведущим и ведомым устройством.

Краткое объяснение пакетов:

Ведущее устройство (Master) формирует и отправляет запрос:

0xAB, 0xBA, <длина команды>, 0x09, <тип энкодера>, <тип GNSS>, <режим GNSS>, '>'

Этот пакет служит командой запроса статуса:

  • Байты 0xAB и 0xBA образуют преамбулу, по которой ведомое устройство синхронизирует начало кадра;

  • Поле «Длина команды» содержит длину в байтах начиная с поля 4 и заканчивая полем с символом 0x3E (‘>’) включительно.

  • Байт 0x09 - является кодом команды (в данном примере, запрос статуса);

  • Поля <тип энкодера>, <тип GNSS> задают конфигурацию активных модулей;

  • Символ '>' (0x3E)обозначает конец пакета.

Ведомое устройство (Slave) приняв пакет, формирует ответ:

0x5A, 0xA5, <длина команды>, 0x09, <установленный энкодер>, <установленный GNSS>, <тип GNSS>, '>' Здесь преамбула от ведомого устройства будет такая 0x5A, 0xA5.

Если параметр команды «Установка активного экодера» равен 1 и энкодер физически не подключен, то значение текущего типа энкодера «Установленный энкодер» становится равным -1.

Если в ответе на команду[9] параметр «Установленный GNSS » равен -1, значит GNSS не подключен, если 1 – то подключен.

Тип GNSS: 1 – одиночный режим, 4 – режим с дифференциальной коррекцией, 5 – режим дифференциальной коррекции с плавающим решением.

Cхема электрическая принципиальная

Объяснение по схеме

DD2 Микроконтроллер STM32F030CCT6 выполняет функции центрального управляющего узла коммутатора данных.

Характеристики МК

  • Ядро: ARM Cortex-M0, тактовая частота до 48 МГц;

  • Память: 256 КБ Flash для хранения ПО, 32 КБ SRAM для оперативных данных;

  • Периферия:

    • 6 универсальных синхронно-асинхронных приемопередатчиков (UART);

    • Интерфейсы: I2C, SPI;

    • 12-битный АЦП (16 каналов);

    • таймеры общего назначения и ШИМ-модули;

    • системные таймеры (SysTick, watchdog).

Ссылка на техническую документацию МК [https://static.chipdip.ru/lib/915/DOC012915875.pdf]

В микроконтроллере будет задействовано сразу 3 UART-порта:

  • UART_1 - предназначен для работы с GNSS-приемником;

  • UART_2 - предназначен для работы с энкодером;

  • UART_3 - предназначен для работы с ведущим устройством.

Выводы NRST и BOOT0

Вывод NRST(reset) используется для аппаратного сброса МК, подключается через резистор R16(10кОм) к питанию +3В — подтягивает NRST к логической «1», конденсатор С19(0,1мкФ), формирует RC-цепочку, используется для подавления помех и автосброса при включении питания, данный пример схемы гарантирует корректный старт МК после подачи питания, защищает от ложных срабатываний при скачках напряжения.

Вывод BOOT0 определяет, откуда МК будет загружать программу после сброса:

  • BOOT0 = 0 — загрузка из Flash‑памяти(основной режим работы);

  • BOOT0 = 1 — загрузка из системной памяти (встроенный загрузчик через UART, I2C, SPI).

В схеме вывод подтянут резистором R13(10кОм) к земле (логический «0»), это обеспечивает автоматическую загрузку программы из flash‑памяти после старта, если потребуется использовать встроенный загрузчик, можно временно подать «1» на BOOT0.

Обвязка питания VCC и VA

МК имеет несколько выводов питания:

  • VCC — основное цифровое питание (3.3В);

  • VA — питание аналоговой части (АЦП, компараторы и т. д.).

На выводах VCC и VA уставлен конденсатор С18 (0.1мкФ), он фильтрует высокочастотные помехи, возникающие при переключении логики, конденсатор ставиться как можно ближе к выводам МК, также дополнительно установлен танталовый конденсатор С20 (4.7мкФ), он сглаживает низкочастотные колебания и стабилизирует питание аналоговой части.

Узел кварцевого резонатора BQ

Кварцевый резонатор подключается к выводам МК (5 и 6), также добавляются нагрузочные конденсаторы С13 и С14 (12пФ), они обеспечивают корректный запуск и устойчивую работу генератора, формируя необходимую нагрузочную емкость.

После подачи напр.питания МК запускает внутренний RC-генератор, но при активации внешнего кварцевого генератора на выводах (5 и 6) начинает работать схема усилителя с положительной обратной связью, при которой:

  • Кварцевый резонатор задает стабильную резонансную частоту колебаний;

  • Нагрузочные конденсаторы формируют требуемую емкость, обеспечивая корректное возбуждение и работу генератора;

  • Полученная частота передается во внутреннюю систему тактирования МК.

Узел RS-485

В данной схеме я использую MAX14841 - это дифференциальный трансивер RS-485/RS-422, предназначенный для передачи данных в промышленных и встраиваемых системах, техническая документация [https://www.alldatasheet.com/datasheet-pdf/pdf/332495/MAXIM/MAX14841EASA%2B.html].

На выводы 6(А) и 7(В) микросхемы DA3, поступают данные от энкодера, выводы подключены через согласующие резисторы:

  • Резистор R5(120 Ом) - предотвращает отражение сигналов в линии;

  • Резисторы R3 и R6(1,5 кОм) - подтягивающие, обеспечивающие корректное определение логических уровней на линии.

Резисторы R11 и R12(10 кОм) - устанавливают стабильный логический уровень на управляющих выводах RE и DE, таким образом они предотвращают ложные переключения при старте системы.

Подключение выводов к МК:

  • RO(выход приемника) - подключается к PA3;

  • DI(вход) - подключается к PA2;

  • DE и RE - подключаются PA1;

  • выводы А и B - подключаются к энкодеру.

Микросхема DA4, используется для приема и передачи данных ведущему устройству, схема подключения резисторов точно такая же как и у DA3,

Подключение выводов к МК:

  • RO(выход приемника) - подключается к PB11;

  • DI(вход) - подключается к PB10;

  • DE и RE - подключаются PB1.

  • выводы А и B - подключаются к ведущему устройству.

Узел подключения GNSS-приемника

Микроконтроллеры STM32, работают с логическими уровнями TTL/CMOS - обычно это 3.3В или 5В, интерфейс RS-232, напротив, использует более высокие и отрицательные напряжения ( от ±3В до ±12В), что делает их напрямую несовместимыми.

Если подключить напрямую модуль-GPS (RS-232) к выводам МК-STM32, это может не только привести к искажению данных, но и физически повредить выводы. ADM3202 решает эту задачу, переводя сигналы из одного уровня в другой, в обоих направлениях.

ADM3202 - это двухканальный приемопередатчик уровней RS-232 - TTL, выполняет сразу две задачи:

  • Преобразование входящих RS-232 сигналов в безопасные TTL-уровни(RX-канал);

  • Преобразование исходящих TTL-сигналов микроконтроллера в RS-232(TX-канал).

Для формирования требуемых амплитуд RS-232, внутри микросхемы используется помповый преобразователь напряжения(chage pump) с четырьмя внешними конденсаторами, это позволяет работать от одного источника питания (от 3В до 5.5В).

Техническая документация ADM3202 [https://www.alldatasheet.com/datasheet-pdf/pdf/48731/AD/ADM3202.html]

Вид осциллограммы передаваемых данных модуля-gnss(rs-232) до преобразования ADM3202

Осциллограмма амплитуды данных от модуля-gps(rs-232) до преобразования ADM3202

Показатель амплитуды данных от модуля gps(rs-232) до преобразования = delta [ 10.6V ], нельзя подключать к микроконтроллеру STM32.

Вид осциллограммы передаваемых данных модуля-gnss(rs-232) после преобразования ADM3202

Осциллограмма амплитуды данных от модуля-gnss(rs-232) после преобразования ADM3202

Осциллограмма амплитуды данных от модуля-gnss(rs-232) после преобразования ADM3202

Показатель амплитуды данных от модуля gnss(rs-232) после преобразования = delta [ 3.6V ], можно подключать к микроконтроллеру STM32.

Узел преобразователя и стабилизатора напряжения

Микросхема DA1 - MP2315 представляет собой синхронный понижающий DC-DC преобразователь с интегрированными силовыми MOSFET-ключами. Высокая частота переключения (до 2.2 МГц), компактный корпус и широкий диапазон входных напряжений (от 4.5 В до 24 В), ссылка на техническую документацию MP2315 [https://www.alldatasheet.com/datasheet-pdf/pdf/1035056/MPS/MP2315.html].

Микросхема DA2 — LP2985 представляет собой малошумящий стабилизатор, предназначен для преобразования входного напряжения +5В в стабильное напряжение +3В, используемое МК и периферийными узлами, ссылка на техническую документацию LP2985 [https://www.alldatasheet.com/datasheet-pdf/pdf/99706/TI/LP2985.html].

Модель печатной платы коммутатора

Слой TOP (верхний слой) и слой BOTTOM(нижний слой) подключены к GND

Прикладываю схему и модель печатной платы cсылка на скачивание Commutator_STM32(.sch/.pcb) [ https://t.me/ChipCraft В закрепленном сообщении [ #исскуствомк_Схема_Commutator_STM32]

Прикладываю также программу для открытия P-CAD Viewer, да... она очень и очень древняя, но я данную программу по построению схем и печатных плат полюбил очень давно, и в основном проектирую только в ней, cсылка на скачивание P-CAD Viewer [ https://t.me/ChipCraft В закрепленном сообщении [ #исскуствомк_проектирование_sch/pcb — Программа для просмотра схем и печатных плат]

Краткая инструкция по открытию файлов

Для того чтобы открыть схему, необходимо открыть программу SCHView(располагается в папке P-CAD 2006 Viewer) и в ней уже открыть файл, для того чтобы открыть печатную плату, необходимо открыть программу PCBView и в ней уже открыть файл.

Настройка микроконтроллера STM32F030CCTx в CubeIDE (Ведомое устройство)

Настройка RCC и SYS (в RCC выбираю Crystal/Ceramic Resonator, так как у меня внешний кварц)

Настройка выводов узла подключения энкодера

Вывод PA1 предназначен для управления DA3 (MAX14841), он подключен к DE и RE, для приема и передачи данных энкодера, необходимо поднимать и опускать вывод МК, работа схемы:

  • На выводе МК = 1 (высокий уровень, "поднят"):

    • DE = 1 — драйвер включен (выходы A и B активны и передают данные из DI).

    • RE = 1 — приемник выключен (выход RO отключен).

    • Микросхема находится в режиме передачи.

  • На выводе МК = 0 (низкий уровень, "опущен"):

    • DE = 0 — драйвер выключен (выходы A и B в высокоимпедансном состоянии).

    • RE = 0 — приемник включен (данные с A и B передаются на RO).

    • Микросхема находится в режиме приема.

Настройка USART2

Энкодер передает данные на скорости [230400], в Baud Rate выставляю скорость, остальные параметры без изменений

Заходим во вкладку NVIC Settings и включаем прерывания

Заходим во вкладку DMA Settings и подключаем DMA

Настройка выводов узла приема и передачи данных с ведущим устройством

Вывод PB1 предназначен для управления DA4 (MAX14841), он подключен к DE и RE, для приема и передачи данных с ведущим устройством, необходимо поднимать и опускать вывод МК, работа схемы:

  • На выводе МК = 1 (высокий уровень, "поднят"):

    • DE = 1 — драйвер включен (выходы A и B активны и передают данные из DI).

    • RE = 1 — приемник выключен (выход RO отключен).

    • Микросхема находится в режиме передачи.

  • На выводе МК = 0 (низкий уровень, "опущен"):

    • DE = 0 — драйвер выключен (выходы A и B в высокоимпедансном состоянии).

    • RE = 0 — приемник включен (данные с A и B передаются на RO).

    • Микросхема находится в режиме приема.

Настройка USART3

Ведущее устройство передает и принимает данные на скорости [230400], в Baud Rate выставляю скорость, остальные параметры без изменений

Заходим во вкладку NVIC Settings и включаем прерывания

Заходим во вкладку DMA Settings и подключаем DMA

Настройка выводов узла подключения приемника-gnss

В данной статье [Прием и парсинг NMEA-данных от GPS-приемника] я уже рассказывал про настройку и работу с приемником-gnss.

Программная реализация ведомого устройства

Ссылка на скачивание исходного кода [ https://t.me/ChipCraft В закрепленном сообщении [ #исскуствомк_исходный_код — Исходный код для STM32F030CCTx_Switch_GPS_DP].

Модуль uart_processing.c

Данный модуль реализует обработку обмена по трем интерфейсам UART, используемым в составе коммутатора:

  • UART1 - прием данных от GNSS-приемника;

  • UART2 - взаимодействие с датчиками перемещения(ДПИ, ДП32, Encoder);

  • UART3 - взаимодействие с ведущим устройством.

Функция void fillBuff_com9(int8_t typeDP)

Формирует ответ на девятую команду протокола, которая служит для запроса или установки типа подключенного датчика перемещения

Режим запроса статуса (typeDP == 1), возвращается текущее значение параметра gParams.type_DP которое отражает активный тип подключенного датчика.

Режим смены конфигурации (typeDP != 1) проверяется, отличается ли новый тип от ранее установленного (gParams.typeDP_fromAB), если произошла смена конфигурации, выполняются переинициализация датчиков.

После выполнения логики, функция формирует ответный пакет в буфере uart_rx_buf_com9:

  • преамбула (0x5A, 0xA5);

  • идентификатор команды (0x09);

  • Тип ДП(retDP);

  • признак активности GPS (gParams.isGPS);

  • статус RTK (isRTK_GPS);

  • конец сообщения (>).

Функция uart_Handler()

Это центральный узел, который предназначается для взаимодействия с ведущим устройством

Логика работы:

Анализ приема:

  • Проверяется флаг uartRxABDone, сообщающий о завершении приема пакета по интерфейсу USART3;

  • Валидность пакета подтверждается преамбулой (0xAB и 0xBA) и соответствием длины данных (uart_rx_buf_AB[2]).

Декодирование команды:

в зависимости от байта команды uart_rx_buf_AB[3] выполняется одна из ветвей:

  • 'G' (GNSS-данные) - вызывается dpi_getGPS_buffer(), возвращает GNSS буфер и передается ведущему устройству;

  • 0x09(девятая команда) - вызывается fillBuff_com9() и передается ведущему устройству;

  • 'Y' (данные от датчиков перемещения) - вызывается dpi_getDP_buffer(), формирует буфер дистанции и передается ведущему устройству;

  • 0x02 (версия прошивки) - формируется ответ в формате Vx.x.x> и передается ведущему устройству.

Обработка завершения передачи:

  • Если пакет подготовлен, управление передается функции uart_transmitAB();

  • В противном случае запускается повторный прием (uart_startRecievingAB), гарантирует непрерывность работы, после успешной отправки пакета, сбрасывается флаг uartTxIRDone_AB, восстанавливается линия приема и освобождается RS-485 (сброс сигнала DE_RE).

Модуль uart_Proc_dp.c

Краткое описание функций:

  • dpi_getDp_buffer() - получение актуального пакета для передачи;

  • dpi_getDist() - узнать накопленное расстояние;

  • dpi_resetDist() - сбросить счетчик дистанции и внутренние буферы;

  • dpi_getDpi_connect_status() - определение состояния подключения.

Данный модуль предназначен для работы с несколькими типами датчиков перемещения

ДПИ (по интерфейсу RS-485)

  • Команда 0xBA 0xDC используется для запроса дистанции;

  • Ответ от ДПИ передается в 6-байтном формате: 4 байта дистанции + 2 байта контрольной суммы CRC.

  • Функция uartHandlerDp анализирует входящий пакет;

  • CRC вычисляется по алгоритму побайтового суммирования с инверсией результата;

  • Если CRC корректна, обновляется переменная dist, в которой хранится расстояние в импульсах;

  • Результат упаковывается в буфер uart_rx_buf_dpi[];

  • dpi_time_send и dpi_time_status_connect задают цикличность запросов и ограничение времени ожидания;

  • Если ответа нет более 100мс, датчик считается отключенным (gParams.typeDP=-1).

ДП32(работа по генерации импульсов)

подключается напрямую к линии RX микроконтроллера и генерирует импульсы

  • Прерывание по фронту PB3 фиксирует факт прихода импульса;

  • Таймер TIM6 используется для определения направления перемещения()

    2 импульса - > движение назад (счетчик уменьшается)

    3 импульса - > движение вперед (счетчик увеличивается)

Настройка TIM6:

  • Выбрать GPIO_EXTI;

  • Повесить прерывание, зайти в NVIC и включить.

Encoder (данный тип датчика выдает только импульсы в одном направлении, т.е. дистанция будет всегда положительная)

Каждый фронт на входе PB3 увеличивает счетчик dpEnc_counter, обновление также транслируется с преамбулой (0x5A и 0xA5).

Главный модуль proj_main.c

Инициализационный блок

  • Задержка старта (HAL_Delay(1)), обеспечивает корректность вызова системного таймера, предотвращая возможное чтение нулевого значения;

  • Инициализация параметров (setDefaultParams()), формируются стандартные настройки модуля, включая все протоколы обмена и параметры периферийных интерфейсов;

  • Перезапуск USART2, сначала деинициализирую и потом инициализирую, помогает корректно работать RS-485 перед началом работы;

  • Инициализация функций:

    • uart_GNSS_init() - подготавливает буферы и структуры для приема данных от GNSS -приемника;

    • uart_Proc_dp_init() - настройка логики обработки данных от датчиков перемещения.

    Старт обмена данными:

    • uart_startRecieving_DP() - запуск приема от датчиков;

    • uart_startTransmiting_DP() - формирование и отправка первого запроса к датчику;

    • uart_startRecieving_AB() - начало приема пакетов от ведущего устройства;

    • uart_startRecieving_GNSS() - включение приема от GNSS-приемника.

Основной цикл работы

Внутренний цикл wihle(1) реализует вызов трех основных обработчиков:

  • uart_Handler() - обеспечивает обмен с ведущим устройством по RS-485

  • uart_Handler_GNSS() - выполняет разбор входящего навигационного потока в формате NMEA, а также контроль активности GNSS-приемника;

  • uart_Handler_DP() - реализует обработку данных с датчиков перемещения.

Просмотр работы приема и передачи данных между ведущим и ведомым устройством, через терминал

С помощью преобразователя USB/RS-485 подключаюсь к DA4 и тестирую


Если статья показалась Вам интересной, буду рад выпустить для Вас еще множество статей исследований по всевозможным видам устройств, так что, если не хотите их пропустить — буду благодарен за подписку на мой ТГ-канал.

Показать полностью 22 1
10

Практическая реализация энкодера с использованием датчика HOA0902 и STM32

В системах точного позиционирования и измерения угла поворота оптические энкодеры остаются критически важным компонентом, обеспечивающим обратную связь по положению. Среди множества датчиков данной категории, будет рассмотрен HOA0902-11 - это двухканальный фотодатчик, предназначенный для высокоточного измерения углового положения, скорости и направления вращения, его конструкция и схема работы основаны на принципе оптической модуляции света через диск.

Устройство датчика:

  • Внутри установлен светодиод (ИК-излучатель), который подсвечивает импульсный диск;

  • С противоположной стороны находятся два фотоприемника (фототранзистора);

  • Эти два фотоприемника расположены со смещением относительно друг друга (90° фазовый сдвиг).

 HOA0902-11

HOA0902-11

В данной статье будут рассмотрены

  • Физические принципы работы HOA092-11;

  • Схема подключения к микроконтроллеру STM32F030CCTx;

  • Программная реализация (расчет пройденного пути, скорости и направления движения, а также вывод информации на дисплей).

Технические характеристики HOA092-11

Ссылка на техническую документацию HOA0902-11 [https://static.chipdip.ru/lib/059/DOC000059035.pdf]

  • Напряжение питания [ 4.5 - 5.5В ];

  • Тип выхода [ NPN открытый коллектор ];

  • Слот (зазор) [ 3.2 мм ];

  • Минимальный механический период (разрешение) [ предназначен для работы с механическим периодом равным 0,036 in ( 0.914 мм), что дает разрешение до 0,018 in ( 0,457 мм) ];

  • Температурный диапазон эксплуатации [ от -40°C до +70°C ]|.

Применение

  • Высокоточные оптические энкодеры;

  • Системы позиционирования в робототехнике;

  • Прецизионные системы контроля скорости вращения;

  • Линейные и ротационные измерительные системы.

Принцип работы HOA0902

  1. Инфракрасный излучатель (IRED) генерирует постоянный поток ИК-излучения;

  2. Кремниевый NPN фототранзистор выполняет функцию приемника излучения;

  3. Оптический зазор между излучателем и приемником обеспечивает зону детектирования.

Режимы работы:

  • Выход(SPEED(TACH)) - генерирует импульс при каждом пересечении порога освещенности, т.е. как только импульсный диск будет проходить через щель, появляется импульс (ширина 8 микросекунд, частота 125 kHz), как раз этот импульс я и буду обрабатывать в микроконтроллере.

В данном проекте используется импульсный диск он состоит из 16 "окон", за одно прохождение "окна", датчик будет выдавать контроллеру по 2 импульса,

Конструкция датчика и расположение "окон" на диске сделаны так, что когда одно "окно" проходит над датчиком, два приемника оказываются в разных фазах этого "окна".

Один приемник (канал A) находится точно по центру окна, когда другой (канал B) находится уже на краю (или наоборот).

Это приводит к тому, что сигналы с каналов A и B сдвинуты относительно друг друга на 90 электрических градусов.

Зачем это нужно?

Такой сдвиг (квадратура) решает сразу несколько критически важных задач:

1. Определение направления вращения (главная причина)
Это самая важная функция, схема обработки сигнала в датчике смотрит, какой канал опережает.

  • Если канал A опережает канал B → вращение по часовой стрелке.

  • Если канал B опережает канал A → вращение против часовой стрелки.

2. Повышение разрешения

Удвоение количества импульсов достигается за счет обработки двух сдвинутых по фазе сигналов, что позволяет извлекать из одной механической конструкции вдвое больше полезной информации, в данной статье датчик HOA0902-11, через который проходит импульсный диск имеющий 16 "окон" при полном обороте, будет выдавать 32 импульса, таким образом получается более точное измерение угла, расстояния и скорости, что позволяет разрешению увеличиваться.

  • 16 импульсов - шаг угла 360° / 16 = 22.5°;

  • 32 импульса - шаг угла 360° / 32 = 11.25°.

3. Повышение помехоустойчивости и надежности Система может проверять соответствие сигналов двух каналов друг другу. Если возникает одиночный ложный импульс на одном канале, которому нет соответствия на другом, его можно отфильтровать как ошибку.

  • Выход направления (DIRECTION) - это логический вывод, который формируется внутри датчика HOA0902-11 из сравнения сигналов А и В, т.е. датчик сам определяет направление вращения и выдает это как отдельный цифровой сигнал:

    DIRECTION = 0 (LOW) - вращение вперед (например, по часовой стрелке);

    DIRECTION = 1 (HIGHT) - вращение назад (против часовой стрелки).

Таким образом, не нужно в МК сравнивать А и В, чтобы вычислять направление - датчик сам это делает, достаточно просто повесить прерывание.

!!! Очень важная информация, так как датчик HOA0902-11 работает по +5В, подключать напрямую сигналы "SPEED(TACH)" и "DIRECTION(DIR)" к микроконтроллеру STM32 (у которого логика работы по +3В) опасно, есть риск повреждения выводов, в следствии МК может просто выйти из строя.

 Осциллограмма сигнала SPEED(TACH) (до делителя)

Осциллограмма сигнала SPEED(TACH) (до делителя)

 Осциллограмма сигнала DIRECTION(DIR) (до делителя)

Осциллограмма сигнала DIRECTION(DIR) (до делителя)

Для того чтобы напряжение было приемлемым, для МК, необходимо поставить делители напряжения, на сигналы "SPEED" и "DIRECTION".

 Осциллограмма сигнала SPEED(TACH) (после делителя)

Осциллограмма сигнала SPEED(TACH) (после делителя)

 Осциллограмма сигнала DIRECTION(DIR) (после делителя)Схема подключения HOA0902-11 и дисплея к микроконтроллеру STM32F030CCTx

Осциллограмма сигнала DIRECTION(DIR) (после делителя)Схема подключения HOA0902-11 и дисплея к микроконтроллеру STM32F030CCTx

На данной схеме изображено подключение датчика HOA0902-11 и дисплея, к микроконтроллеру STM32F030CCTx, а также реализация преобразователя со стабилизатором напряжения

 Схема подключения HOA0902-11 и дисплея к микроконтроллеру STM32F030CCTx

Схема подключения HOA0902-11 и дисплея к микроконтроллеру STM32F030CCTx

Перечень элементов

Пояснения к схеме

Выводы NRST и BOOT0

Вывод NRST(reset) используется для аппаратного сброса МК, подключается через резистор R7(10кОм) к питанию +3В - подтягивает NRST к логической "1", конденсатор С5(0,1мкФ), формирует RC-цепочку, используется для подавления помех и автосброса при включении питания, данный пример схемы гарантирует корректный старт МК после подачи питания, защищает от ложных срабатываний при скачках напряжения.

 Подключение NRST и BOOT0

Подключение NRST и BOOT0

Вывод BOOT0 определяет, откуда МК будет загружать программу после сброса:

  • BOOT0 = 0 - загрузка из Flash-памяти(основной режим работы);

  • BOOT0 = 1 - загрузка из системной памяти (встроенный загрузчик через UART, I2C, SPI).

В схеме вывод подтянут резистором R8 к земле (логический "0"), это обеспечивает автоматическую загрузку программы из flash-памяти после старта, если потребуется использовать встроенный загрузчик, можно временно подать "1" на BOOT0.

Обвязка питания VCC и VA

МК имеет несколько выводов питания:

  • VCC - основное цифровое питание (3.3В);

  • VA - питание аналоговой части (АЦП, компараторы и т.д.).

На выводах VCC и VA уставлен конденсатор С6 (0.1мкФ), он фильтрует высокочастотные помехи, возникающие при переключении логики, конденсатор ставиться как можно ближе к выводам МК, также дополнительно установлен танталовый конденсатор 4.7мкФ, он сглаживает низкочастотные колебания и стабилизирует питание аналоговой части.

Микросхема DA1 - MP2315 представляет собой синхронный понижающий (buck) DC-DC преобразователь с интегрированными силовыми MOSFET-ключами. Высокая частота переключения (до 2.2 МГц), компактный корпус и широкий диапазон входных напряжений (от 4.5 В до 24 В), ссылка на техническую документацию MP2315 [https://www.alldatasheet.com/datasheet-pdf/pdf/1035056/MPS/MP2315.html].

Микросхема DA2 - LP2985 представляет собой малошумящий стабилизатор, предназначен для преобразования входного напряжения +5В в стабильное напряжение +3В, используемое МК и периферийными узлами, ссылка на техническую документацию LP2985 [https://www.alldatasheet.com/datasheet-pdf/pdf/99706/TI/LP2985.html].

Подключение датчика HOA0902-11

  • Сигнал SPEED(TACH) - подключается через делитель R1 и R3, к выводу МК-12(PA2);

  • Сигнал DIR(DIRECTION) - подключается через делитель R4 и R5, к выводу МК-13(PA3).

Подключение дисплея

  • Сигнал SDA - подключается к выводу 21(PB10);

  • Сигнал SCL - подключается к выводу 22(PB11).

Настройка микроконтроллера STM32F030CCTx в CubeIDE

Настройка выводов

Вывод PA2 настроен на внешнее прерывание (EXTI) (выполняет роль триггера для подсчета импульса) к нему подключается сигнал SPEED(TACH) датчика HOA0902-11, каждый раз, когда через окно датчика проходит импульсный диск, датчик формирует импульс, далее он фиксируется аппаратным модулем EXTI, который:

  • Генерирует прерывание;

  • Устанавливает флаг encoderDone;

  • Делегирует дальнейшую обработку в функцию encoder_Handler().

Вывод PA3(DIRECTION) (GPIO_INPUT), используется для определения направления вращения.

Настройка таймеров

TIM3 используется как счетчик временных интервалов, настроен на генерацию прерываний, каждое срабатывание таймера фиксирует количество импульсов, поступивших от энкодера, таймер настраивается на прерывание раз в 100ms.

 Настройка TIM3 в CubeMX

Настройка TIM3 в CubeMX

TIM14 используется в качестве системного диспетчера вывода информации на дисплей, таймер настраивается на генерацию прерываний с периодом 200mS, при каждом срабатывании прерывания происходит вызов функции display_update(), которая обновляет содержимое экрана.

 Настройка TIM14

Настройка TIM14

Настройка приоритетов

  • EXTI line 2 and 3 interrupts - [0];

  • TIM13 - [1];

  • TIM14 - [2].

Настройка Clock

Реализация программного кода

Ссылка на скачивание исходного кода [ https://t.me/ChipCraft В закрепленном сообщении [ #исскуствомк_исходный_код - Исходный код для Encoder_HOA0902-11_STM32F030CCT6], а также видео тестирования энкодера [#исскуствомк_тестирование_Encoder].

Библиотеку для работы с дисплеем я взял с [https://github.com/afiskon/stm32-ssd1306/tree/master]

Функция display_init()

Выполняет начальную инициализацию дисплея, подключенного по интерфейсу I2C(на базе контроллера SSD1306)

  • Инициализируется драйвер дисплея;

  • Выполняется заливка экрана черным цветом;

  • На дисплее на 2 секунды отображается стартовый экран с надписью ''ChipCraft";

  • После задержки экран очищается для дальнейшей работы.

Функция encoder_Handler() обработчик инкрементального энкодера

  • Вызывается при установке флага encoderDone, который формируется в прерывании внешнего входа (EXTI);

  • Определяется направление вращения вала датчика по состоянию пина DIRECTION_Pin:

    • RESET - движение вперед (инкремент счетчика);

    • SET - движение назад (декремент счетчика).

  • Вызывается метод get_distance_m() для расчета дистанции.

Функция display_update()

Отвечает за визуализацию информации на дисплее:

  • Экран предварительно очищается с помощью ssd1306_Fill(Black);

  • В верхней части по центру отображается надпись "Encoder";

  • Ниже последовательно выводятся:

    • количество импульсов;

    • дистанция;

    • скорость.

  • Буфер графики передается на дисплей вызовом ssd1306_UpdateScreen()

Функция float get_distance_m()

Возвращает текущее значение пройденного пути в метрах, расчет выполняется как произведение общего числа импульсов pulse_counter на метрический коэффициент DIST_PER_STEP_M, который определяется из геометрии колеса и количества "окон" импульсного диска.

Формула расчета дистанции

где:

  • N - Число импульсов;

  • D - Диаметр колеса;

  • PPR - количество импульсов на оборот.

HAL_TIM_PeriodElapsedCallback Функция обратного вызова, выполняется при переполнении таймера

  • Каждые WINDOW_TIME_S секунд фиксируется количество импульсов в pulse_counter_window;

  • После чтения счетчик сбрасывается;

  • Рассчитывается скорость

    Формула расчета скорости

окно - это фиксированный промежуток времени, в течении которого производится расчет количества импульсов от датчика, в данном проекте будет 100 мс (0.1 с)

  • Скорость определяется как отношение пройденного пути за окно.

где S - путь в окне, t - длительность окна.

также в данной функции вызывается display_update(), для визуализации текущих значений на дисплее.

Модуль process_Encoder

Модуль proj_main()

  • Выполняется инициализация дисплея;

  • Запуск таймеров;

  • Запуск функции encoder_Handler().

Вывод

В результате проделанной работы реализована полноценная система измерения и отображения параметров энкодера, на базе датчика HOA0902-11 и микроконтроллера STM32F030CCTx.

Тест энкодера


Если статья показалась Вам интересной, буду рад выпустить для Вас еще множество статей исследований по всевозможным видам устройств, так что, если не хотите их пропустить – буду благодарен за подписку на мой ТГ-канал: https://t.me/ChipCraft.

Показать полностью 23 1
11

Под слоем земли

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

Метод георадиолокации (GPR‑ Ground Penetrating Radar) — это геофизический метод, основанный на зондировании грунта с помощью электромагнитных волн, ультравысоких частот (обычно от десятков МГц до нескольких ГГц), он применяется для исследования структуры подповерхностных слоев без их разрушения.

На видео представлен пример работы георадара

на глубине от 1 до 1.5 метра просматривается газовая труба

Методом георадиолокации обладает георадар - это высокотехнологичный прибор, разработанный для подповерхностного зондирования, его конструкция сочетает несколько ключевых узлов, которые обеспечивают работу системы:

  • Передатчик - генерирует элекромагнитные импульсы и посылает их в грунт;

  • Приемник - улавливает отраженные сигналы и преобразует их для последующей обработки;

  • Модуль управления - отвечает за синхронизацию излучения и приема сигналов, а также передачу данных в систему обработки;

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

    Основное свойство таких поглотителей – эффективное рассеивание и поглощение электромагнитных волн в заданном диапазоне частот, обеспечивая тем самым улучшение сигнала и разрешение в георадарных данных.

В геологии георадары применяются для решения следующих задач:

  • Картирование геологических структур - восстановление геометрии относительно протяжных границ, поверхности коренных пород под рыхлыми осадками, уровня грунтовых вод, границ между слоями с различной степенью водонасыщения, поиск месторождений, строительных материалов;

  • Определение свойств различных отложений по скорости распространения электромагнитных волн, опираясь на связь этих свойств с диэлектрической проницаемостью пород;

  • Определение толщины ледяного покрова;

  • Определение мощности водоносного слоя и картирование поддонных отложений;

  • Определение мощности зоны сезонного промерзания или оттаивания, картирование границ мерзлых и талых пород.

При проведении георадарных исследований основное внимание уделяется двум параметрам:

время пробега электромагнитной волны — сколько времени требуется сигналу, чтобы пройти от передатчика до отражающей границы и вернуться обратно к приёмнику;

амплитуда отражения — насколько сильным оказался отражённый сигнал.

Отражение возникает на границах раздела разных сред: между сухими и влажными грунтами (уровень грунтовых вод), мерзлыми и талыми породами, коренными и рыхлыми слоями, разными по составу породами, а также на стыке природных и искусственных материалов (например, грунт — бетон, новый и старый асфальт).

Сила отражённого сигнала зависит от коэффициента отражения, который определяется разницей диэлектрических проницаемостей двух соседних слоёв. Чем больше эта разница, тем контрастнее будет отражение.

Амплитуда отраженного сигнала от границы между слоями пропорциональна величине Котр. (коэффициент отражения):

Скорость распространения электромагнитной волны также связана с диэлектрической проницаемостью среды:

где c — скорость света в вакууме, ε — диэлектрическая проницаемость материала. В георадиолокации скорость обычно измеряется в сантиметрах на наносекунду (см/нс). Для удобства формула часто записывается так:

Здесь особенно важно, что воздух имеет диэлектрическую проницаемость 1, а вода — 81. Поэтому именно соотношение воды и воздуха в породе в первую очередь определяет её свойства.

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

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

Таким образом, измеряя времена пробега сигнала и анализируя его амплитуду, можно определить строение подповерхностных слоёв и физические свойства пород.

Электромагнитный импульс в георадиолокации — это короткий сигнал, состоящий из 1,0–2,0 периодов квазигармонической волны, который излучается в исследуемую среду с помощью антенны. Благодаря своей малой длительности такой импульс имеет широкий спектр частот, что позволяет фиксировать отражения от различных границ между средами — сухими и влажными грунтами, мерзлыми и талыми породами, разными по составу слоями или инженерными конструкциями. Отражённые импульсы улавливаются приёмной антенной, усиливаются и обрабатываются, а время их прохождения используется для восстановления строения подповерхностных слоёв.

Малая временная длительность излучаемого импульса приводит к возникновению достаточно широкого частотного спектра излучения

Квазигармоническая волна — это электромагнитный сигнал, близкий по форме к гармоническому (синусоидальному), но ограниченный во времени и содержащий лишь 1–2 периода колебаний. В отличие от идеальной бесконечной гармонической волны, квазигармоническая имеет широкий спектр частот, что делает её удобной для зондирования: она позволяет выявлять отражения от разных по свойствам границ в грунте и инженерных сооружениях.

Первое отражение на радарограмме называют прямой волной (сигналом прямого прохождения). Прямая волна в большинстве случаев одинаковая для всех трасс профиля. Она определяется конструкцией антенны и поверхностью профиля. Прочие волны на радарограмме являются отраженными от каких либо слоев или локальных объектов в грунте (или другой среде исследования).

Дифрагированная волна возникает из-за явления дифракции — это ситуация, когда электромагнитная волна «огибает» препятствие или рассеивается на нём. Такое происходит в том случае, если размер объекта сравним с длиной волны или меньше её.

В георадиолокации дифракция чаще всего возникает, когда сигнал встречает вытянутые объекты: трубы, кабели, элементы арматуры и другие инженерные конструкции.

На радарограмме дифракция имеет характерный «подпись» — отражение отображается не как прямая линия, а в виде гиперболы. Точка вершины этой гиперболы указывает на реальное местоположение объекта в грунте.

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

Пример поиска водоносного слоя

Отчетливо можно рассмотреть что глубина водоносного слоя пролегает от 5 до 6 метров

Отчетливо можно рассмотреть что глубина водоносного слоя пролегает от 5 до 6 метров

Водоносный слой — это природный горизонт горных пород, способный накапливать и проводить подземные воды благодаря своей пористости и проницаемости. Чаще всего такими породами являются пески, гравий или трещиноватые известняки. Эти слои играют ключевую роль в формировании и движении грунтовых вод, выступают естественными резервуарами и источниками питьевой или технической воды.

Для геодезии и инженерной геологии водоносный слой имеет особое значение: он влияет на выбор места строительства, устойчивость фундаментов, проектирование подземных сооружений и коммуникаций. По сути, это скрытая под землёй «водная артерия», от свойств и глубины залегания которой во многом зависит как природная среда, так и деятельность человека.

Амплитуда отражённого сигнала в георадиолокации напрямую связана с контрастом диэлектрических свойств соседних слоёв.

У водоносного слоя ключевая особенность — высокая диэлектрическая проницаемость, так как вода имеет ε ≈ 81 (для сравнения: воздух — 1, сухой песок — 3–5, сухой известняк — 6–8). Когда электромагнитный импульс встречает границу «сухой грунт → водонасыщенный слой», возникает резкий скачок в значении ε.

Это приводит к:

  • сильному увеличению амплитуды отражённого сигнала — чем больше разница между слоями, тем ярче отражение на записи;

  • появлению чёткой границы на радиолокационном разрезе (обычно в виде яркой горизонтальной линии).

Таким образом, водоносный слой определяется по мощному отражению, возникающему на контакте сухих и влагонасыщенных грунтов.

Таблица значений диэлектрической проницаемости (ε) различных сред


В заключение можно сказать, что метод георадиолокации является эффективным и универсальным инструментом для изучения подповерхностных структур. Он позволяет получать ценную информацию о строении грунтов, глубине залегания водоносных слоёв, границах промерзания и подземных объектах без разрушения исследуемой среды.

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

Если статья показалась Вам интересной, буду рад выпустить для Вас еще множество статей исследований по всевозможным видам устройств, так что, если не хотите их пропустить – буду благодарен за подписку на мой ТГ-канал: https://t.me/ChipCraft.

Показать полностью 12 1
12

Контроль напряжения над блоком питания на STM32: Подход к энергоэффективности и защите

Автономные системы становятся все более востребованными - от портативных приборов до сложных промышленных комплексов - надежное управление напряжением питания превращается в ключевой фактор их долговечности и эффективности. Сердце любой такой системы - аккумулятор, а его безопасность и срок службы, напрямую зависит от контроля напряжения.

В данной статье будет представлен пример контроля напряжения, над блоком питания - внутри которого (никель-металлгидридная аккумуляторная сборка NiMH 14.4В/12 банок по 1.2В(1.4В- при полной зарядке)).

В блоке питания уже есть палата управления над аккумулятором, которая выполняет задачи:

  • Работа с кнопкой;

  • Работа со светодиодом;

  • Работа с пъезоэлектрическим излучателем(звуковая индикация);

  • Контроль заряда/разряда аккумулятора(дает звуковой сигнал при напряжении менее 9 вольт и более 14).

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

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

Для решения данной проблемы я продемонстрирую пример системы контроля напряжения блока питания, в качестве микроконтроллера выбран STM32F103С8T6, который выполняет следующие задачи:

  • Непрерывный мониторинг напряжения аккумуляторной сборки, измерение производится через АЦП с использованием DMA;

  • Оповещение пользователя о низком заряде, при падении напряжения ниже установленного порога (в данном примере - 9.0В) система активизирует звуковой сигнал, время работы оповещения ограничено - звуковая индикация будет длится 5 минут;

  • Переход в энергосберегающий режим, если напряжение остается ниже порога и пользователь не предпринял действий в течении заданного времени, микроконтроллер переводит систему в режим сна, это сопровождается отключением тактирования и всей периферии, что минимизирует и предотвращает глубокий разряд аккумулятора.

Схема подключения NiMH АКБ, делителя напряжения к АЦП МК, кнопки вкл/выкл и пъезо-излучателя

Перечень компонентов

Объяснение схемы

Узел[1]

  • Входной силовой ключ, исток подключен к +12V, сток идет к блоку питания(+12_АКК) через предохранители, а затвор подтянут к земле, применение (защищенная подача напряжения питания с аккумуляторного блока);

Узел[2]

  • Вторичный силовой ключ, обеспечивает управляемое включение/отключение напряжения питания основной нагрузки системы, управление происходит через МК, сигнал PWR_ON, после включения данного узла, на стоке напряжение питания +12ВК активизируется и передает напряжение другим частям схемы, в моем примере это (узел[4]-Звуковая индикация и узел[5]-lделитель напряжения), но также можно использовать данный узел и на включение преобразователей напряжения;

Узел[3]

  • Данный узел обеспечивает логику взаимодействия с кнопкой включения/выключения, кнопка sa2, при нажатии формирует управляющий сигнал, диод АD4 и конденсатор С1 обеспечивают фильтрацию и антидребезг;

Узел[4]

  • Данный узел обеспечивает звуковую индикацию, сигнал BEEP подключается к МК;

Узел[5]

Данный узел является делителем напряжения, делит напряжение до уровня, подходящего для измерения АЦП МК (обычно до 3.3V), подстроечный резистор R8, выставлен на 1.7кОм.

Настройка микроконтроллера STM32F103 в CubeIDE

Конфигурация TIM1(PA11)

Таймер TIM1 выполняет роль генератора для звуковой индикации.

Настройка таймера:

  • Предделитель (Prescaler) и период (Auto-Reload) выбраны так, чтобы на выходе формировался сигнал с частотой в диапазоне, воспринимаемом слухом (обычно 1–5 кГц);

  • Режим работы – PWM (широтно-импульсная модуляция);

  • Коэффициент заполнения (Pulse) определяет громкость и характер звучания.

Принцип работы:
Таймер генерирует ШИМ-сигнал, который подаётся на транзисторный ключ. Транзистор управляет пьезоизлучателем или динамиком. В результате получается слышимый звук.

Преимущества такого решения:

  • Микроконтроллеру не нужно вручную формировать частоту – этим занимается таймер;

  • Легко изменять тональность: достаточно переписать значения ARR/PSC;

  • Можно реализовать разные звуковые эффекты (короткие сигналы, мелодии) простым управлением таймером из программы.

Конфигурация ADC(PA1)

В проекте используется многоканальный режим работы АЦП с двумя каналами в последовательности (Regular conversion sequence).

Rank 1 – внешний канал (ADC Channel 1).
Этот вход подключён к делителю напряжения и используется для измерения напряжения аккумулятора.
Благодаря этому микроконтроллер может в реальном времени контролировать состояние питания устройства.

Rank 2 – внутренний канал (Vrefint).
Это встроенный источник опорного напряжения микроконтроллера. Он служит для автоматической калибровки и компенсации возможных изменений питающего напряжения. С его помощью можно более точно измерять значение внешних сигналов, в том числе напряжение аккумулятора.

Для повышения эффективности задействован DMA: результаты обоих измерений (Rank 1 и Rank 2) автоматически передаются в память, а процессор получает только готовые данные.

Для правильной настройки ADC я воспользовался данной информацией, там подробно расписано как работать с ADC МК-STM32.

Конфигурация пина для работы с кнопкой

Для работы с кнопкой выбран вывод PB11, сконфигурированный в режиме:

  • GPIO_EXTI – внешний прерывающий вход. Это значит, что нажатие кнопки обрабатывается не опросом в цикле, а через аппаратное прерывание;

  • Mode - External interrupt, Falling edge trigger – прерывание срабатывает по спаду сигнала (при замыкании кнопки на землю);

  • Pull-up – включен внутренний подтягивающий резистор, который удерживает вход в состоянии логической «1», пока кнопка не нажата.

Кнопка подключена так, что в обычном состоянии на входе PB11 присутствует логическая «1» благодаря встроенному подтягивающему резистору (Pull-up). При нажатии контакт замыкается на землю, формируется логический «0» и происходит спад сигнала. Этот спад фиксируется модулем EXTI, который вызывает прерывание.

Конфигурация пина для работы с сигналом PWR_ON

Сигнал PWR_ON играет роль электронного «выключателя питания».

В исходном состоянии (Low) нагрузка обесточена.

При активации (перевод вывода в High) силовой MOSFET открывается, и напряжение +12ВК подаётся на остальные узлы системы.

В примере данная линия питает:

узел [4] – звуковую индикацию,

узел [5] – делитель напряжения для мониторинга питания.

Аналогично этот узел можно использовать и для включения DC/DC-преобразователей или других модулей, требующих управляемого питания.

Конфигурация Clock

Реализация программного кода

Ссылка на скачивание исходного кода [ https://t.me/ChipCraft В закрепленном сообщении [ #исскуствомк_исходный_код - Adc_VoltageControl_STM32F103C8T6]

Заголовочный файл keys.h (работа с кнопками)

В данном файле определены:

  • Функции работы с кнопками;

  • Битовые маски состояний;

  • константы для различных сценариев нажатий.

keys.h

Реализация модуля keys.c (работа с кнопками)

Данный модуль включает в себя задачи:

  • Устранение дребезга контактов;

  • Различие между коротким и долгим нажатием;

  • Отслеживание событий нажатия, удержания и отпускания.

keysDrv_Handler()

Вызывается постоянно в основном цикле или из системного таймера.

Нажатие кнопки (первичное событие)

2. if(gl_kDrv_key1_blockEvent == 0 && ON_OFFB_state == KEY_PRESS) {
3. gl_kDrv_key1_blockEvent = 1;
4. gl_kDrv_time_key1_press = ms;
5. }

Сохраняется время нажатия, дальнейшие события блокируются до отпускания

Фильтр дребезга

else if(gl_kDrv_key1_blockEvent == 1 &&
&&
gl_kDrv_key1_short_state==0 &&
(ms - gl_kDrv_time_key1_press) > DELAY4TIMER){
//прошло время защиты от дребезга, кнопка нажата
gl_kDrv_key1_short_state=1;
keyState &= ~KEY1Release_Drv;//снимаем бит отпускания кнопки
keyState |= KEY1_Drv;
}

Если прошло больше DELAY4TIMER, считаем кнопку реально нажатой.

Определение удержания

else if(gl_kDrv_key1_blockEvent == 1 &&
ON_OFFB_state==KEY_PRESS &&
gl_kDrv_key1_short_state==1 &&
(ms - gl_kDrv_time_key1_press) > DELAY_HOLD_TIMER){
keyState |= KEY1Hold_Drv;
}

Если прошло больше DELAY_HOLD_TIMER, выставляем бит удержания.

Отпускание кнопки

else if(gl_kDrv_key1_blockEvent == 1 && && gl_kDrv_key1_short_state==1){
gl_kDrv_key1_blockEvent=0;
gl_kDrv_key1_short_state=0;
keyState |= KEY1Release_Drv;
keyState &= ~KEY1_Drv;//снимаем бит нажатия кнопки
keyState &= ~KEY1Hold_Drv;//снимаем бит удержания кнопки
}

При отпускании кнопки сбрасываются флаги удержания и нажатия, выставляется бит отпускания.

getKeyState()

Возвращает текущее состояние кнопок в виде битовой маски

  • Позволяет определить, была ли кнопка нажата, удержана или отпущена;

  • После считывания некоторые флаги (например, отпускание) сбрасываются ,чтобы событие не повторялось.

getKeyPinState_AtNow()

Возвращает моментальное состояние ножек GPIO, без учета дребезга

  • Полезно для отладки или когда нужно мгновенно узнать, нажата ли кнопка прямо сейчас

    keys.c

Реализация модуля ADC_Calc.c (работа с АЦП)

Данный модуль реализует контроль напряжения питания через АЦП микроконтроллера STM32F103C8T6, измерения выполняются с использованием:

  • DMA (циклическая запись данных в буфер);

  • Встроенного опорного напряжения Vrefint;

  • Собственного делителя напряжения на входе.

ADC_Calc_Handler() - главный обработчик вычислений

  • Проверяет, заполнена ли первая или вторая половина DMA-буфера;

  • Усредняет значения для канала измерения и Vrefint;

  • Конвертирует результат в напряжение вызовом adc_calcVoltage();

  • Если напряжение ниже порога critical_stress → возвращает команду отключения питания (FORCE_POWER_OFF);

  • Производит фильтрацию значений по диапазону 750 < val_input < 2800 (защита от шумов и выбросов).

HAL_ADC_ConvCpltCallback()

Вызывается по прерыванию DMA Transfer Complete → устанавливает флаг adcIRFullDone

HAL_ADC_ConvHalfCpltCallback()

Вызывается по прерыванию DMA Half Transfer Complete → устанавливает флаг adcIRHalfDone

adc_init()

  • Сброс флагов и буфера.

adc_start()

Запускает АЦП в режиме DMA, далее происходит циклическое заполнение adcDMAbuf без участия процессора

adc_stop()

  • Останавливает АЦП и DMA;

  • Сбрасывает флаги готовности

adc_calcVoltage()

Ключевая функция — переводит «сырые» значения АЦП в напряжение

adc_GetVoltage()

Геттер для получения последнего значения рассчитанного напряжения

Общий алгоритм работы:

  • DMA заполняет буфер парами значений (input, Vrefint);

  • При заполнении половины буфера → срабатывает прерывание, ставится флаг;

  • ADC_Calc_Handler считывает данные, фильтрует и усредняет;

  • Вызывается adc_calcVoltage, которая переводит вольты;

  • Значение доступно через adc_GetVoltage();

  • Если напряжение меньше 9 В (по critical_stress) → отрабатывает аварийное выключение.

ADC_Calk.c

Пояснение к функции adc_calcVoltage()

Расчет VDDA, где:

VREFINT_TYP - калибровочное значение 1.20, взято из datasheet, у других МК на заводе производитель прошивает калибровочное значение в ПЗУ при изготовлении, пример получения значения с МК STM32F030CCTx [0x1FFFF7BA];

4095 - когда измеряется источник встроенным АЦП, результат выражается в единицах квантования, максимум которых равен 4095, поэтому в формуле используется множитель 4095 - это нормализация значения, чтобы связать измеренный АЦП с напряжением VDDA.

ADC_vref - значение встроенного источника опорного напряжения

Перевод значения канала в напряжение

ADC_in - напряжение измеренное с делителя напряжения (узел[5])

Коррекция через делитель напряжения

Вход подключен через делитель R1=221кОм и R2 = 27кОм, переводим в Ом,

добавил смещение (-0.5) для подстройки измерений.

Таблица замеров напряжения от 14.5 вольт до 7 вольт.

Прикладываю видео-тестирования прохода по спаду напряжения, а также видео-тестирования, сброс напряжения и уход в сон микроконтроллера при низком напряжении ссылка [ https://t.me/ChipCraft В закрепленном сообщении [ #исскуствомк_тестирование_ Adc_VoltageControl]

Реализация модуля proj_main.c (Главный метод)

Данный модуль объединяет несколько подсистем:

  • Кнопка управления (одиночное и двойное нажатие);

  • Контроль напряжения питания через АЦП;

  • Звуковая индикация состояния;

  • Автоматический переход в сон при низком напряжении.

proj_main.c

Вывод

Данная система контроля над блоком питания реализует:

  • Обработку кнопок с фильтрацией дребезга, с поддержкой короткого/долгого/двойного нажатия и отпускания;

  • Мониторинг напряжения через АЦП с защитой от просадок и автоматическим отключением при критическом низком уровне;

  • Звуковая индикация (короткие, двойные сигналы) для информирования пользователя о событиях;

  • Энергосбережение переход в режим STOP и пробуждение по прерыванию.

Систему можно использовать как основу для портативных приборов, автономных устройств и встраиваемых систем, где важно одновременно удобное управление и защита электроники.


Если статья показалась Вам интересной, буду рад выпустить для Вас еще множество статей исследований по всевозможным видам устройств, так что, если не хотите их пропустить – буду благодарен за подписку на мой ТГ-канал: https://t.me/ChipCraft.

Показать полностью 16
11

Датчик оптического потока PAT9125

Современные компьютерные мыши, тачпады, сенсорные панели и мобильная робототехника, обязаны своей точностью и отзывчивостью миниатюрным системам движения. Одним из таких является PAT9125 - это высокоточный двухосевой оптический датчик, способный с невероятной точностью отслеживать перемещение по различным поверхностям.

PAT9125 представляет собой интеллектуальный датчик, в основе которого - микроскопическая камера и инфракрасная подсветка. Он реализует текстуру поверхности под собой, фиксируя мельчайшие смещения и на основе полученных данных изображений рассчитывает вектор движения. Благодаря высокой кадровой частоте, датчик способен точно отслеживать даже быстрое перемещение, сохраняя стабильность и минимальную задержку.

Основные характеристики:

  • Количество осей: 2 (X и Y);

  • Разрешение: до 1200 CPI (Counts Per Inch);

  • Интерфейсы связи: I2C и SPI;

  • Скорость кадров: до 2300 FPS (кадров в секунду);

  • Рабочее расстояние: около 1.2мм ± 0.2мм от поверхности.

Применение и обработка данных

Считывание данных с датчика по I2C и SPI - интерфейсам, дает доступ к приращениям по осям X и Y. Эти значения можно использовать для расчета абсолютного перемещения, а при необходимости - перевести в сантиметры или метры, учитывая установленное разрешение (CPI), Таким образом, PAT9125 может эффективно выполнять роль оптического энкодера, позволяя измерять расстояние, путь и даже направление движения.

Пример схемы электрической принципиальной, подключение к микроконтроллеру STM32F103 по интерфейсу I2C.

Реализация программного кода (Настройка, прием данных, конвертация) PAT9125 и микроконтроллера STM32F103.

Настройка в CubeIDE

Выберем I2C и выставим параметры:

  • I2C Speed Mode: Standard Mode;

  • I2C Speed Frequency(KHz): 100.

Метод PAT9125_Init

В данном методе производится инициализация датчика:

  • Считывание ID и проверка доступности устройства;

  • Установление разрешения CPI, через метод PAT9125_SetCpi().

Метод PAT9125_SetCPI

Данный метод, устанавливает заданный CPI в регистры X[0x0D] и Y[0x0E], считывает один байт из регистра датчика PAT9125 по I2C, (выставлено 1000 CPI, что эквивалентно 0.0254 мм/отсчет).

Метод PAT9125_ReadReg

Считывает один байт из регистра датчика PAT9125 по I2C (используется для чтения текущих значений (идентификатора устройства, данных движения и т.д.)).

Метод PAT9125_WriteReg

Данный метод, записывает значение value в регистр reg датчика PAT9125, используется для настройки параметров датчика, например (Установка CPI-разрешения).

Метод PAT9125_ReadMotion

Данный метод, считывает информацию о перемещении по осям X и Y из датчика (режим Burst Read), так же обновляет общее смещение total_x, total_y, и вызывает функцию обновления общего пройденного пути, простыми словами (используется каждый раз, когда нужно получить новые данные движения с датчика).

Поддерживает форматы:

  • 8-битный формат и 12-битный (определяется макросом USE_12BIT_FORMAT), для работы в 8-битном формате, просто закоментируйте макрос(#define USE_12BIT_FORMAT),

  • в режиме 12-бит, данные собираются из старших и младших байтов и расширяются до знакового значения.

Метод ProcessMotionData

Данный метод является основным обработчиком движения, вызывает метод PAT9125_ReadMotion, обрабатывает данные и формирует строки для вывода по UART.

Метод UpdateTotalDistance

Данный метод вычисляет прирост пройденного пути на основе новых данных смещения и обновляет общий путь total_distance_cm

Метод convert_to_cm

Преобразует значение смещения из отсчетов в сантиметры, используя установленное разрешение CPI

Метод calculateBetaRadians

Данный метод вычисляет угол направления движения по данным X и Y

Ссылка на скачивание исходного кода [ https://t.me/ChipCraft В закрепленном сообщении [ #исскуствомк_исходный_код -оптический_датчик_PAT9125]

Вывод

Это полноценный драйвер + обработчик данных с датчика PAT9125, включающий:

  • Считывание и обработку данных о движении;

  • Перевод в физические единицы (см, мм, радианы);

  • Калибровка чувствительности.

В целом, PAT9125 - это пример того, как миниатюрные технологии могут обеспечить высочайшую точность в системах, где важна каждая микронная деталь, благодаря своей компактности, энергоэффективности и простоте интеграции, он становится идеальным выбором для современных устройств ввода и мобильных систем позиционирования.


Если статья показалась Вам интересной, буду рад выпустить для Вас еще множество статей исследований по всевозможным видам устройств, так что, если не хотите их пропустить – буду благодарен за подписку на мой ТГ-канал: https://t.me/ChipCraft.

Показать полностью 3
19

Прием и парсинг NMEA-данных от GPS-приемника

GPS-приемники сегодня используются в самых разных устройствах - от автомобильных трекеров до беспилотных летательных аппаратов, независимо от применения, большинство таких модулей передают информацию о положении в формате NMEA 0183, в этой статье я разберу, как принять эти данные от GPS-модуля на микроконтроллер STM32 и преобразовывать их в удобный для программы вид.

А также в статье будут рассмотрены два варианта подключения GPS-приемников к микроконтроллеру STM32:

  • Модуль GPS c UART-интерфейсом (TTL-уровни), подключаемый на прямую к микроконтроллеру;

  • Модуль GPS с интерфейсом RS-232, данные от такого типа gps, необходимо принимать через преобразователь уровней TTL.

В данном проекте используются GPS-приемники: LS23030 (UART) и LS23036(RS-232).

Схема подключения GPS-UART

Подключение модуля-GPS(UART) к микроконтроллеру STM32F103

Сигнал GPS, подключается к выводу PA10-31_контакт - RX(МК-STM32F103)

Для более стабильного напряжения питания можно использовать следующую схему, в которой работает понижающий преобразователь MP231, но необходим источник +12В, в моем случае используется аккумуляторная сборка (NiMH/Pb +12В).

Понижающий преобразователь напряжения MP2315 [ +12V до +5V ]

Вид осциллограммы передаваемых данных модуля-gps(uart) (линия TX)

Осциллограмма амплитуды данных от модуля-gps(uart)

Показатель амплитуды данных от модуля gps(uart) = delta [ 3.4V ], можно подключать к микроконтроллеру STM32.

Схема подключения GPS(RS-232)

Подключение модуля-GPS(RS-232) через ADM3202 к МК-STM32F103

Сигнал модуля-gps(rs-232), сначала приходит на 13 контакт преобразователя ADM3202, далее преобразованный сигнал (TTL) уходит на PA10-31_контакт - RX(МК-STM32F103)

Схема подключения ADM3202 к МКSTM32 - макет

Макет ADM3202 и подключение к STM32F103

Также для более стабильного напряжения питания по +5В, можно использовать схему преобразователя напряжения MP2315.

Для более стабильного напряжения питания по +3В, можно использовать следующую схему, в которой работает линейный стабилизатор напряжения LP2985.

Линейный стабилизатор напряжения LP2985 (+5В +3В)

Краткая информация о преобразователе ADM3202

Микроконтроллеры STM32, работают с логическими уровнями TTL/CMOS - обычно это 3.3В или 5В, интерфейс RS-232, напротив, использует более высокие и отрицательные напряжения ( от ±3В до ±12В), что делает их напрямую несовместимыми.

Если подключить напрямую модуль-GPS (RS-232) к выводам МК-STM32, это может не только привести к искажению данных, но и физически повредить выводы. ADM3202 решает эту задачу, переводя сигналы из одного уровня в другой, в обоих направлениях.

ADM3202 - это двухканальный приемопередатчик уровней RS-232 - TTL, выполняет сразу две задачи:

  • Преобразование входящих RS-232 сигналов в безопасные TTL-уровни(RX-канал);

  • Преобразование исходящих TTL-сигналов микроконтроллера в RS-232(TX-канал).

Для формирования требуемых амплитуд RS-232, внутри микросхемы используется помповый преобразователь напряжения(chage pump) с четырьмя внешними конденсаторами, это позволяет работать от одного источника питания (от 3В до 5.5В).

Вид осциллограммы передаваемых данных модуля-gps(rs-232) до преобразования ADM3202

Осциллограмма амплитуды данных от модуля-gps(rs-232) до преобразования ADM3202

Показатель амплитуды данных от модуля gps(rs-232) до преобразования = delta [ 10.6V ], нельзя подключать к микроконтроллеру STM32.

Вид осциллограммы передаваемых данных модуля-gps(rs-232) после преобразования ADM3202

Осциллограмма амплитуды данных от модуля-gps(rs-232) после преобразования ADM3202

Показатель амплитуды данных от модуля gps(rs-232) после преобразования = delta [ 3.6V ], можно подключать к микроконтроллеру STM32.

Настройка микроконтроллера STM32F103 в CubeIDE

Конфигурация Parametr Settings

В параметрах USART (Parametr Settings) я выбираю:

  • Mode: Asynchronous (асинхронный режим);

  • Baud Rate: 9600 бит/с (в моем примере два модуля-gps (rs-232 и uart) работают на скорости 9600).

все остальные параметры без изменений.

Настройка "Parameter settings"

Конфигурация NVIC Settings

Захожу в параметр (NVIC Settings) и включаю глобальное прерывание

Для отслеживания состояния интерфейса USART и обработки важных событий (например, завершения приема или ошибки), в разделе NVIC Settings было включено глобальное прерывание USART, это обеспечивает возможность немедленного реагирования со стороны микроконтроллера на изменения состояния периферии без постоянного опроса регистров.

Настройка "NVIC Settings"

При работе с GPS-модулями, которые передают NMEA-сообщения раз в секунду (1Hz), важно правильно организовать прием данных, чтобы не пропустить ни одного пакета. Необходимо настроить DMA в режиме Circular данный режим минимизирует нагрузку на процессор и гарантирует надежный прием.

Конфигурация DMA Settings

Захожу в параметр DMA Settings и выполняю следующие настройки:

  1. Выбор потока/канала: USART1_RX (прием данных);

  2. Mode: Circular ;

  3. Increment Memory Address: Enabled (автоинкремент памяти);

  4. Data Width: Byte (8 бит, соответствует формату NMEA).

Настройка "DMA Settings"

Реализация программного кода(настройка и прием данных)

Коротко о NMEA 0183

Это текстовый протокол, используемый для передачи данных между морским и авиационным навигационным оборудованием, включая GPS-приемники. Большинство современных GPS-модулей выводят информацию именно в этом формате.

Основные особенности:

  • Текстовый формат – данные передаются в виде ASCII-строк;

  • Структура сообщений – каждая строка начинается с $, содержит идентификатор типа данных и заканчивается контрольной суммой;

  • Скорость передачи – обычно 9600 бод (но может быть и выше для высокочастотных модулей);

  • Частота обновления – чаще всего 1 раз в секунду (1Hz), но бывают 5Hz, 10Hz и более.

Пример строки (GGA – Global Positioning System Fix Data):

После обработки GGA:

  • Время: 11:25:30

  • Широта: 60.20576° N

  • Долгота: 30.261315° E

  • Качество фикса: 1

  • Спутников: 10

  • Высота: 45.3 м

Пример строки (RMC – Recommended Minimum Navigation Information):

После обработки RMC:

  • Время: 11:25:30

  • Статус: Данные действительные

  • Широта: 60.20576° N

  • Долгота: 30.261315° E

  • Скорость: 5.12 узла (~9.48 км/ч)

  • Курс: 87.45°

  • Дата: 11.08.2025

Также прикрепляю еще одну ссылку, где в детальности продемонстрирована расшифровка протокола NMEA0183 [https://wiki.iarduino.ru/page/NMEA-0183/].

Определение структур данных в заголовочном файле [ NMEA.h ]

Для удобства работы с навигационной информацией из gps-приемника, здесь я заранее описываю набор структур, каждая из которых отвечает за свой логический блок данных.

Реализация модуля парсинга протокола NMEA.c

Функция decodeGGA()

Парсит строку $GPGGA и заполняет структуру GGASTRUCT данными: время, координаты, высота, количество спутников, качество фиксации.

Шаги работы функции:

  • Подготовка к поиску нужных данных

    • Переменная inx - это текущий индекс в строке GGAbuffer;

    • Сначала иду пропуск ненужных полей (счетчик двигается до следующей ,)

  • Проверка валидации качества позиционирования

    • В NMEA поле качества фиксации (Fix Quality) может быть:

      • 0 - нет фикса, 1 - GPS Fix, 2-DGPS Fix, 4/5/6 другие корректные варианты;

      • Если поле содержит из разрешенных цифр, то в gga->isfixValid устанавливается в 1, иначе функция возвращает ошибку.

  • Чтение времени

    • Извлекается время в формате HHMMSS (UTC);

    • Преобразуются числа;

    • Корректируется по смещению GMT, при необходимости меняется день (daychange++ или daycahnge--).

  • Чтение широты (Latitude)

    • Формат в NMEA: DDMM.MMM;

    • Первые цифры - градусы, остальное - минуты;

    • Код выделяет минуты, делит их на 60 и добавляет к градусам;

    • Если NS == 'S', широта делается отрицательной.

  • Чтение долготы (Longitude)

    • Формат в NMEA: DDMM.MMM;

    • Аналогично широте, но первые 3 цифры - градусы;

    • Если EW == 'W', долгота делается отрицательной.

  • Чтение типа вычисления координат

    • Из поля после долготы извлекается число (gga->calc.calculation), указывающее метод позиционирования.

  • Чтение количества спутников

    • Следующее поле - количество видимых спутников (gga->numofsat).

  • Пропуск HDOP

    • HDOP (Horizontal Dilution of Precision) не используется, просто пропускается.

  • Чтение высоты

    • Поле с высотой (gga->alt.altitude) и единицами (gga->alt.unit, обычно 'M' - метры).

  • Завершение

    • Возвращается 0 при успешном разборе.

Функция decodeRMC()

Парсит строку $GPRMC и заполняет структуру RMCSTRUCT и извлекает: валидность данных, скорость, курс и дату.

  • Пропуск времени

    • Сначала идет поле времени, но в этой функции оно не сохраняется.

  • Проверка валидности

    • Если после времени идет А(Active) - данные актуальны;

    • Если V(Void) нет актуальных данных, функция возвращает ошибку.

  • Пропуск координат

    • Пропускаются поля широты, долготы и направления (NS/EW).

  • Чтение скорости

    • В NMEA скорость указывается в узлах;

    • Код переводит строку в число с плавающей точкой и записывает в rmc->speed.

  • Чтение курса

    • Следующее поле - курс (угол направления движения в градусах относительно севера).

  • Чтение даты

    • Формат: DDMMYY;

    • Код выделяет день, месяц, год, корректирует день с учетом daychange (из GGA), и записывает в rmc->date.

Реализация модуля обработчика потока от UART-GPS uartProc_GNSS.c

Функция uart_Handler_GNSS - это основной обработчик UART-потока, вызывается постоянно из главного цикла.

Логика работы:

  1. Проверяет, сработали ли прерывания DMA (половина буфера или полный буфер);

  2. Если пришли новые данные - устанавливает флаг активности GPS (gParams.isGPS = 1);

  3. Поиск GGA или RMC

    • В режиме shabloneMode = 0 ищет последовательность GGA или RMC;

    • Когда шаблон найден, переключаемся в режим shabloneMode = 1;

    • В режиме 1 копирует байты до символа конца строки (13 или 10);

  4. Действие когда собрана строка

    • Записывает строку в буфер buf_GGA или buf_RMC в зависимости от типа;

    • Обновляет время последнего получения GPS (gps_time_receive).

  5. Декодирование

    • Вызывает decodeGGA() и decodeRMC() для извлечения данных в структуру gpsData.

  6. Формирование выходного пакета:

    • Если хотя бы одно из сообщений валидно, формирует строку с координатами, временем, количеством спутников, режим фикса, высотой и курсом.

    • Записывает в результат в uart_rezult_buf_out_AB[] с преамбулой 0x5A 0xA5 и длиной пакета.

  7. Если в течение (DELAY_GPS_STATUS_CONNECT)1000 миллисекунд новых данных нет - GPS считается отключенным (gParams.isGPS= 0).

  8. uint8_t* dpi_getGPS_buffer (Возвращает указатель на готовый пакет данных для передачи ведущему устройству, а так же его размер).

  9. void uart_startRecieving_GNSS (Запускает прием данных от GPS-приемника в режиме DMA).

Ссылка на скачивание исходного кода [ https://t.me/ChipCraft В закрепленном сообщении [ #исскуствомк_исходный_код -Исходный код для Module_GPS_NMEA0183]

Графический GPS-трекер я разработал для тестирования на С#, если Вам будет интересно, пишите в комментариях и я с радостью напишу статью.


Если статья показалась Вам интересной, буду рад выпустить для Вас еще множество статей исследований по всевозможным видам устройств, так что, если не хотите их пропустить – буду благодарен за подписку на мой ТГ-канал: https://t.me/ChipCraft.

Показать полностью 18
9

Прием и парсинг NMEA-данных от GPS-приемника

GPS-приемники сегодня используются в самых разных устройствах - от автомобильных трекеров до беспилотных летательных аппаратов, независимо от применения, большинство таких модулей передают информацию о положении в формате NMEA 0183, в этой статье я разберу, как принять эти данные от GPS-модуля на микроконтроллер STM32 и преобразовывать их в удобный для программы вид.

А также в статье будут рассмотрены два варианта подключения GPS-приемников к микроконтроллеру STM32:

  • Модуль GPS c UART-интерфейсом (TTL-уровни), подключаемый на прямую к микроконтроллеру;

  • Модуль GPS с интерфейсом RS-232, данные от такого типа gps, необходимо принимать через преобразователь уровней TTL.

В данном проекте используются GPS-приемники: LS23030 (UART) и LS23036(RS-232).

Схема подключения GPS-UART

Подключение модуля-GPS(UART) к микроконтроллеру STM32F103

Подключение модуля-GPS(UART) к микроконтроллеру STM32F103

Сигнал GPS, подключается к выводу PA10-31_контакт - RX(МК-STM32F103)

Для более стабильного напряжения питания можно использовать следующую схему, в которой работает понижающий преобразователь MP231, но необходим источник +12В, в моем случае используется аккумуляторная сборка (NiMH/Pb +12В).

Понижающий преобразователь напряжения MP2315 [ +12V до +5V ]

Понижающий преобразователь напряжения MP2315 [ +12V до +5V ]

Вид осциллограммы передаваемых данных модуля-gps(uart) (линия TX)

Осциллограмма амплитуды данных от модуля-gps(uart)

Осциллограмма амплитуды данных от модуля-gps(uart)

Показатель амплитуды данных от модуля gps(uart) = delta [ 3.4V ], можно подключать к микроконтроллеру STM32.

Схема подключения GPS(RS-232)

Подключение модуля-GPS(RS-232) через ADM3202 к МК-STM32F103

Подключение модуля-GPS(RS-232) через ADM3202 к МК-STM32F103

Сигнал модуля-gps(rs-232), сначала приходит на 13 контакт преобразователя ADM3202, далее преобразованный сигнал (TTL) уходит на PA10-31_контакт - RX(МК-STM32F103)

Схема подключения ADM3202 к МКSTM32 - макет

 Макет ADM3202 и подключение к STM32F103

Макет ADM3202 и подключение к STM32F103

Также для более стабильного напряжения питания по +5В, можно использовать схему преобразователя напряжения MP2315.

Для более стабильного напряжения питания по +3В, можно использовать следующую схему, в которой работает линейный стабилизатор напряжения LP2985.

 Линейный стабилизатор напряжения LP2985 (+5В +3В)

Линейный стабилизатор напряжения LP2985 (+5В +3В)

Краткая информация о преобразователе ADM3202

Микроконтроллеры STM32, работают с логическими уровнями TTL/CMOS - обычно это 3.3В или 5В, интерфейс RS-232, напротив, использует более высокие и отрицательные напряжения ( от ±3В до ±12В), что делает их напрямую несовместимыми.

Если подключить напрямую модуль-GPS (RS-232) к выводам МК-STM32, это может не только привести к искажению данных, но и физически повредить выводы. ADM3202 решает эту задачу, переводя сигналы из одного уровня в другой, в обоих направлениях.

ADM3202 - это двухканальный приемопередатчик уровней RS-232 - TTL, выполняет сразу две задачи:

  • Преобразование входящих RS-232 сигналов в безопасные TTL-уровни(RX-канал);

  • Преобразование исходящих TTL-сигналов микроконтроллера в RS-232(TX-канал).

Для формирования требуемых амплитуд RS-232, внутри микросхемы используется помповый преобразователь напряжения(chage pump) с четырьмя внешними конденсаторами, это позволяет работать от одного источника питания (от 3В до 5.5В).

Вид осциллограммы передаваемых данных модуля-gps(rs-232) до преобразования ADM3202

 Осциллограмма амплитуды данных от модуля-gps(rs-232) до преобразования ADM3202

Осциллограмма амплитуды данных от модуля-gps(rs-232) до преобразования ADM3202

Показатель амплитуды данных от модуля gps(rs-232) до преобразования = delta [ 10.6V ], нельзя подключать к микроконтроллеру STM32.

Вид осциллограммы передаваемых данных модуля-gps(rs-232) после преобразования ADM3202

 Осциллограмма амплитуды данных от модуля-gps(rs-232) после преобразования ADM3202

Осциллограмма амплитуды данных от модуля-gps(rs-232) после преобразования ADM3202

Показатель амплитуды данных от модуля gps(rs-232) после преобразования = delta [ 3.6V ], можно подключать к микроконтроллеру STM32.

Настройка микроконтроллера STM32F103 в CubeIDE

Конфигурация Parametr Settings

В параметрах USART (Parametr Settings) я выбираю:

  • Mode: Asynchronous (асинхронный режим);

  • Baud Rate: 9600 бит/с (в моем примере два модуля-gps (rs-232 и uart) работают на скорости 9600).

все остальные параметры без изменений.

 Настройка "Parameter settings"

Настройка "Parameter settings"

Конфигурация NVIC Settings

Захожу в параметр (NVIC Settings) и включаю глобальное прерывание

Для отслеживания состояния интерфейса USART и обработки важных событий (например, завершения приема или ошибки), в разделе NVIC Settings было включено глобальное прерывание USART, это обеспечивает возможность немедленного реагирования со стороны микроконтроллера на изменения состояния периферии без постоянного опроса регистров.

 Настройка "NVIC Settings"

Настройка "NVIC Settings"

При работе с GPS-модулями, которые передают NMEA-сообщения раз в секунду (1Hz), важно правильно организовать прием данных, чтобы не пропустить ни одного пакета. Необходимо настроить DMA в режиме Circular данный режим минимизирует нагрузку на процессор и гарантирует надежный прием.

Конфигурация DMA Settings

Захожу в параметр DMA Settings и выполняю следующие настройки:

  1. Выбор потока/канала: USART1_RX (прием данных);

  2. Mode: Circular ;

  3. Increment Memory Address: Enabled (автоинкремент памяти);

  4. Data Width: Byte (8 бит, соответствует формату NMEA).

 Настройка "DMA Settings"

Настройка "DMA Settings"

Реализация программного кода(настройка и прием данных)

Коротко о NMEA 0183

Это текстовый протокол, используемый для передачи данных между морским и авиационным навигационным оборудованием, включая GPS-приемники. Большинство современных GPS-модулей выводят информацию именно в этом формате.

Основные особенности:

  • Текстовый формат – данные передаются в виде ASCII-строк;

  • Структура сообщений – каждая строка начинается с $, содержит идентификатор типа данных и заканчивается контрольной суммой;

  • Скорость передачи – обычно 9600 бод (но может быть и выше для высокочастотных модулей);

  • Частота обновления – чаще всего 1 раз в секунду (1Hz), но бывают 5Hz, 10Hz и более.

Пример строки (GGA – Global Positioning System Fix Data):

После обработки GGA:

  • Время: 11:25:30

  • Широта: 60.20576° N

  • Долгота: 30.261315° E

  • Качество фикса: 1

  • Спутников: 10

  • Высота: 45.3 м

Пример строки (RMC – Recommended Minimum Navigation Information):

После обработки RMC:

  • Время: 11:25:30

  • Статус: Данные действительные

  • Широта: 60.20576° N

  • Долгота: 30.261315° E

  • Скорость: 5.12 узла (~9.48 км/ч)

  • Курс: 87.45°

  • Дата: 11.08.2025

Также прикрепляю еще одну ссылку, где в детальности продемонстрирована расшифровка протокола NMEA0183 [https://wiki.iarduino.ru/page/NMEA-0183/].

Определение структур данных в заголовочном файле [ NMEA.h ]

Для удобства работы с навигационной информацией из gps-приемника, здесь я заранее описываю набор структур, каждая из которых отвечает за свой логический блок данных.

Реализация модуля парсинга протокола NMEA.c

Функция decodeGGA()

Парсит строку $GPGGA и заполняет структуру GGASTRUCT данными: время, координаты, высота, количество спутников, качество фиксации.

Шаги работы функции:

  • Подготовка к поиску нужных данных

    • Переменная inx - это текущий индекс в строке GGAbuffer;

    • Сначала иду пропуск ненужных полей (счетчик двигается до следующей ,)

  • Проверка валидации качества позиционирования

    • В NMEA поле качества фиксации (Fix Quality) может быть:

      • 0 - нет фикса, 1 - GPS Fix, 2-DGPS Fix, 4/5/6 другие корректные варианты;

      • Если поле содержит из разрешенных цифр, то в gga->isfixValid устанавливается в 1, иначе функция возвращает ошибку.

  • Чтение времени

    • Извлекается время в формате HHMMSS (UTC);

    • Преобразуются числа;

    • Корректируется по смещению GMT, при необходимости меняется день (daychange++ или daycahnge--).

  • Чтение широты (Latitude)

    • Формат в NMEA: DDMM.MMM;

    • Первые цифры - градусы, остальное - минуты;

    • Код выделяет минуты, делит их на 60 и добавляет к градусам;

    • Если NS == 'S', широта делается отрицательной.

  • Чтение долготы (Longitude)

    • Формат в NMEA: DDMM.MMM;

    • Аналогично широте, но первые 3 цифры - градусы;

    • Если EW == 'W', долгота делается отрицательной.

  • Чтение типа вычисления координат

    • Из поля после долготы извлекается число (gga->calc.calculation), указывающее метод позиционирования.

  • Чтение количества спутников

    • Следующее поле - количество видимых спутников (gga->numofsat).

  • Пропуск HDOP

    • HDOP (Horizontal Dilution of Precision) не используется, просто пропускается.

  • Чтение высоты

    • Поле с высотой (gga->alt.altitude) и единицами (gga->alt.unit, обычно 'M' - метры).

  • Завершение

    • Возвращается 0 при успешном разборе.

Функция decodeRMC()

Парсит строку $GPRMC и заполняет структуру RMCSTRUCT и извлекает: валидность данных, скорость, курс и дату.

  • Пропуск времени

    • Сначала идет поле времени, но в этой функции оно не сохраняется.

  • Проверка валидности

    • Если после времени идет А(Active) - данные актуальны;

    • Если V(Void) нет актуальных данных, функция возвращает ошибку.

  • Пропуск координат

    • Пропускаются поля широты, долготы и направления (NS/EW).

  • Чтение скорости

    • В NMEA скорость указывается в узлах;

    • Код переводит строку в число с плавающей точкой и записывает в rmc->speed.

  • Чтение курса

    • Следующее поле - курс (угол направления движения в градусах относительно севера).

  • Чтение даты

    • Формат: DDMMYY;

    • Код выделяет день, месяц, год, корректирует день с учетом daychange (из GGA), и записывает в rmc->date.

Реализация модуля обработчика потока от UART-GPS uartProc_GNSS.c

Функция uart_Handler_GNSS - это основной обработчик UART-потока, вызывается постоянно из главного цикла.

Логика работы:

  1. Проверяет, сработали ли прерывания DMA (половина буфера или полный буфер);

  2. Если пришли новые данные - устанавливает флаг активности GPS (gParams.isGPS = 1);

  3. Поиск GGA или RMC

    • В режиме shabloneMode = 0 ищет последовательность GGA или RMC;

    • Когда шаблон найден, переключаемся в режим shabloneMode = 1;

    • В режиме 1 копирует байты до символа конца строки (13 или 10);

  4. Действие когда собрана строка

    • Записывает строку в буфер buf_GGA или buf_RMC в зависимости от типа;

    • Обновляет время последнего получения GPS (gps_time_receive).

  5. Декодирование

    • Вызывает decodeGGA() и decodeRMC() для извлечения данных в структуру gpsData.

  6. Формирование выходного пакета:

    • Если хотя бы одно из сообщений валидно, формирует строку с координатами, временем, количеством спутников, режим фикса, высотой и курсом.

    • Записывает в результат в uart_rezult_buf_out_AB[] с преамбулой 0x5A 0xA5 и длиной пакета.

  7. Если в течение (DELAY_GPS_STATUS_CONNECT)1000 миллисекунд новых данных нет - GPS считается отключенным (gParams.isGPS= 0).

  8. uint8_t* dpi_getGPS_buffer (Возвращает указатель на готовый пакет данных для передачи ведущему устройству, а так же его размер).

  9. void uart_startRecieving_GNSS (Запускает прием данных от GPS-приемника в режиме DMA).

Ссылка на скачивание исходного кода [ https://t.me/ChipCraft В закрепленном сообщении [ #исскуствомк_исходный_код -Исходный код для Module_GPS_NMEA0183]

Графический GPS-трекер я разработал для тестирования на С#, если Вам будет интересно, пишите в комментариях и я с радостью напишу статью.


Если статья показалась Вам интересной, буду рад выпустить для Вас еще множество статей исследований по всевозможным видам устройств, так что, если не хотите их пропустить – буду благодарен за подписку на мой ТГ-канал: https://t.me/ChipCraft.

Показать полностью 18
Отличная работа, все прочитано!

Темы

Политика

Теги

Популярные авторы

Сообщества

18+

Теги

Популярные авторы

Сообщества

Игры

Теги

Популярные авторы

Сообщества

Юмор

Теги

Популярные авторы

Сообщества

Отношения

Теги

Популярные авторы

Сообщества

Здоровье

Теги

Популярные авторы

Сообщества

Путешествия

Теги

Популярные авторы

Сообщества

Спорт

Теги

Популярные авторы

Сообщества

Хобби

Теги

Популярные авторы

Сообщества

Сервис

Теги

Популярные авторы

Сообщества

Природа

Теги

Популярные авторы

Сообщества

Бизнес

Теги

Популярные авторы

Сообщества

Транспорт

Теги

Популярные авторы

Сообщества

Общение

Теги

Популярные авторы

Сообщества

Юриспруденция

Теги

Популярные авторы

Сообщества

Наука

Теги

Популярные авторы

Сообщества

IT

Теги

Популярные авторы

Сообщества

Животные

Теги

Популярные авторы

Сообщества

Кино и сериалы

Теги

Популярные авторы

Сообщества

Экономика

Теги

Популярные авторы

Сообщества

Кулинария

Теги

Популярные авторы

Сообщества

История

Теги

Популярные авторы

Сообщества