Колхозим метеостанцию на 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 (он хорошо шлифуется и на белом цвете меньше видна слоистость).



    Все материалы выкладываю сюда.
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама

    Комментарии 12

      +5
      В очередной раз включу зануду.
      1. Полно подобных «метеостанций», но практически нет с измерением направления и скорости ветра.
      2. Вам удобно смотреть на индикаторе показания давления в таком виде? Так сложно их перевести в миллиметры привычные всем?
      3. Зачем этот секс с термистором, если есть ds18b20? А было бы ещё круче на термометрах сопротивления.

      Вот тогда бы я аплодировал стоя
        0
        1. хм, интересно, на эту тему не задумывался
        2. да, удобно) перевести несложно, в начале думал выводить в паскалях и мм, но решил оставить так
        3. собирал из того, что нашел дома :)
        0
        Ни о чем. Микроскопом забивать гвозди. Достаточно было взять ESP и загрузить туда NarodMon. Было бы изящнее и эффективнее. А данные получать по WiFi на телефон. Один хрен на этом дисплее ничего не разглядишь, пока не подойдешь.
          0

          Для esp делал вариант https://www.youtube.com/watch?v=nOgsU1K7hCo, с mqtt и архивированием на microSD, для телефона использую приложение Virtuino. Дисплей не нужен.

          +2
          Таблицу сопротивлений переносить ненужно, достаточно воспользоваться алгоритмом вычисления уравнения Уравнение Стейнхарта — Харта.
          В целом у вашего решения точность посредственная будет, хотя у вас диаппазон узкий может и норм. А если он будет от -45 до +90 такой подход точно не годится.
            +2
            Что ж вы терморезистор напрямую на вход контроллера подключили, а как же HЧ фильтр, а как же буфер на ОУ? В софте тоже фильтра нет.
            Белка на соседнем дереве пукнет и ваш датчик пургу покажет.
              +1
              вот вам и тема для статьи) развернуть свой комметарий.
              +1

              Проще dht использовать, чем упрочнения и таблицы мудрить, esp и в облака кидать!
              Ну а так, это типичный "hello world", неописуемая радость …
              Продолжайте обучение и переходите к практическому применению контроллеров!

                +1
                Возьмите BMP280 — там и температура, и давление, и влажность — всё по интерфейсу, без АЦП, и точность сильно получше
                  0

                  не берите BMP280 — там с влажностью все очень плохо (вероятно на рынке это давно не бош, а китайские подделки). Перепробовал штук 5 таких, со всеми зрада. Хорошо себя показал HDC1080

                    0
                    может потому что надо брать BME280?
                      +2
                      Сорян, очепятался) Имел ввиду BME280. Брал с алика где-то год назад — показывает то же, что и настенный термометр-гигрометр-барометр. Только всё руки не доходят оформить в метеостанцию. И, вроде как, при считывании данных о влажности с BME280, в формулу надо подставлять температуру (формула есть в даташите), считанную с него же, встроенной поправки нет.

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

                Самое читаемое