Колхозим метеостанцию на STM32 (Bluepill, STM32IDE, HAL)

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.
Привет, Хабр!
В этой статье я хочу рассказать о своей небольшой поделке во время карантина – метеостанция на основе STM32 (плата bluepill).



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

Принципиальная схема метеостанции:


В метеостанции я использовал два датчика – АМТ1001 и BMP-180 (плата GY-68). Питается все это от однобаночного Lipo аккумулятора через повышающий до 5В DC-DC преобразователь. Информация с датчиков выводится на дисплей 2004. Выводы настроил следующим образом:

Подключение датчика температуры и влажности AMT1001



Выводы датчика:
Красный — VDD (4.75 – 5.25 В)
Черный – GND
Желтый – выход датчика влажности
Белый – термистор
Считывая напряжение на выводах датчика, можно определить температуру и влажность, соотнеся значение напряжения с таблицами из datasheet. Начнем с влажности:





По графику видно, что зависимость между влажностью и напряжением линейная, а это значит, что значения АЦП можно напрямую преобразовать в значение влажности. Обозначим:
ADC_hum – значение с АЦП;
hum – значение влажности (в %);
V_hum – значение напряжения на датчике.
V_hum = 3.3 В (опорное напряжение АЦП) * ADC_hum / 4095 (кол-во разрядов АЦП).
1 % влажности соответствует 0.3/10 = 0.03 В, то
hum = V_hum / 0.03 = ADC_hum * 0.027
С вычислениями определились, теперь перейдем к коду. Датчик влажности подключен к PA4 (ADC1).
float hum;
uint16_t ADC_hum;

HAL_ADC_Start(&hadc1);                              // запуск АЦП
HAL_ADC_PollForConversion(&hadc1,100);              // ожидание вычисления
ADC_hum = HAL_ADC_GetValue(&hadc1);                 // запись результата в переменную
HAL_ADC_Stop(&hadc1);                               // остановка АЦП

hum = ADC_hum;
hum *= 0.027; 


Теперь рассмотрим термистор — резистор, сопротивление которого меняется от температуры. С помощью АЦП можно измерить напряжение на элементе, но не его сопротивление. Для работы с термистором необходимо добавить резистор на 10 кОм между выводом термистора (белый провод) и землей. В итоге получим вот такой делитель напряжения (термистор внутри подключен к VCC):



Теперь мы можем измерить сопротивление термистора, воспользовавшись первым правилом Кирхгофа – сумма токов в узле равна 0. Вспомнив школьный курс физики получим:
Untc/ Rntc = U1/R1
Выводом РА5 мы измеряем напряжение на резисторе 10к. В случае с термистором, его сопротивление меняется не пропорционально изменению температуры, в документации приведена огромная таблица значения сопротивлений транзистора при температуре от -40 до +125. Всю таблицу переносить в микроконтроллер та еще задача, я взял диапазон от 10 до 30 градусов (21 значение).
Для того, чтобы микроконтроллеру не нужно было каждый раз вычислять значение сопротивления, я сделал программу в Mathcad. Полученные результаты я перевел в массив:
int out_temp[21] ={2200, 2255,	2315, 2377, 2433, 2497, 2558, 2618, 2680, 2741, 2801, 2862, 2923, 2983, 3041, 3102, 3166, 3215, 3283, 3336, 3396};

Если АЦП покажет значение, близкое к первому элементу массива – температура 10 градусов, если ко второму – 11, и так далее, до 30 градусов. Значение десятых долей градуса можно примерно вычислить, но можно этого и не делать. Ниже представлен код, который вычисляет десятые (примерное их значение), хотя учитывая технологический разброс полагаться на десятые доли не стоит.
float temp;
uint16_t ADC_temp;
HAL_ADC_Start(&hadc2);                        // запуск АЦП 2
HAL_ADC_PollForConversion(&hadc2,100);        // ожидание вычисления
ADC_temp = HAL_ADC_GetValue(&hadc2);          // запись результата в переменную
HAL_ADC_Stop(&hadc1);                         // остановка АЦП

for (int i=0; i<21; i++)
{
	if (ADC_temp < out_temp[i+1] && ADC_temp > out_temp[i] )
	{
		int x = ADC_temp - out_temp[i];
		int xx = out_temp[i+1] - out_temp[i];
		temp = x;
		temp = temp/xx+i+10;
                break;
	}
}

Дальше я подключил датчик температуры и атмосферного давления GY- 68 (BMP180). Как с ним работать описано тут, код я брал оттуда же.
Для вывода информации я использовал дисплей 2004 с I2C адаптером (про него писал тут)
Соединил все это я следующим примитивным образом – напаял все на макетку, воткнул выключатель в разрыв питания. Датчики и дисплей подключаются через обычную гребенку. Датчики сделал выносными, так как была идея вынуть их за окно, но в таком виде дождя они не переживут.



Вот так выглядит датчик:



Корпус печатал на 3д принтере белым ABS (он хорошо шлифуется и на белом цвете меньше видна слоистость).



Все материалы выкладываю сюда
Источник: https://habr.com/ru/post/503798/


Интересные статьи

Интересные статьи

Доброго здравия всем! Сегодня я хочу вам рассказать, как постепенно студенты учатся разрабатывать ПО для микроконтроллера на примере драйвера UART на STM32F411. Код и архитектуру с небольшими ...
Введение Модель дисплея называется H016IT01. Данный дисплей интересен прежде всего тем, что он является транфлективным(transflective). Это означает, что изображение на нем должно быть видно даже...
В прошлый раз мы осваивали создание нового проекта при помощи STM CubeMX первую часть можно найти здесь. Для тех, кому лень перечитывать — закончилось все тем, что пустой проект успешно собрался...
Несмотря на то, что “в коробке” с Битриксом уже идут модули как для SOAP (модуль “Веб сервисы” в редакции “Бизнес” и старше), так и для REST (модуль “Rest API” во всех редакциях, начиная с...
В первой части я попробовал рассказать хобби-электронщикам, выросшим из штанишек Ардуино, как и зачем им стоит читать даташиты и прочую документацию к микроконтроллерам. Текст получился большой...