Как стать автором
Обновить

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

Время на прочтение3 мин
Количество просмотров13K
Привет, Хабр!

В этой статье я хочу рассказать о своей небольшой поделке во время карантина – метеостанция на основе 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 (он хорошо шлифуется и на белом цвете меньше видна слоистость).



Все материалы выкладываю сюда.
Теги:
Хабы:
+16
Комментарии13

Публикации