С детства мечтал о комнатном термометре, гигрометре и барометре (не прошли даром уроки природоведения и биологии). Даже был куплен настенный вариант со стрелочными приборами советского образца типа такого:
Но по ошибке был повешен на створку двери и через некоторое время прийдя в негодность, от постоянных сотрясений, начал показывать одно и тоже значение. Психрометр пугал своим видом. Да и записывать каждый день показания — глупая затея. Механические системы были похоронены на совсем с приходом контроллеров.
Долго присматривал различные отладочные платы. По совету знакомого купил я отладочную плату STM32L-Discovery от фирмы ST, подробное описание здесь. Заманчиво звучало то, что это ARM на ядре Cortex-M3. Сердцем платы является STM32L152RBT6. Также на плате есть on-board программатор и отладчик ST-Link и шести сегментный LCD дисплей.
Посты и наличие STM32L-Discovery вдохновили на реализацию проекта.
Немного освоившись в Keil загрузил вместо идущего на борту примера, другой пример Temperature project — и вуаля термометр уже готов. Микроконтроллер может измерять Vref. У него также есть свой собственный датчик температуры чипа.
Все бы хорошо но этот датчик показывает температуру кристалла, решил добавить датчик температуры DS18B20, да и one-wire интерфейс хорошо бы освоить. Оказалась чтобы что либо добавить необходимо первым делом избавится от штатного LCD экрана, он со своими 6 символами занимает практически все свободные порты процессора.
В закромах родины завалялся старенький LCD экран собранный на контроллерах Hitachi (8 строк по 25 символов)
В выше указанной статье упоминался цифровой датчик влажности воздуха HIH3610, но был приобретен емкостной датчик влажности HCH1000 и барометрический датчик HSF1000.
Итак организовались задачи по подключению оборудования:
1. Подключение и программирование LCD экрана;
2. Подключение и получение данных от RTL;
2. Подключение цифрового датчика температуры DS18B20 и чтение из него данных по шине one-wire;
3. Подключение емкостного датчика HCH1000 и получение данных;
4. Подключение пьезоэлектрического датчика HSF1000 и получение данных;
Вот такое устройство вышло:
Подключение и программирование LCD экрана
Экземпляр попавший мне в руки оказался настолько старым что документации от него не нашлось. На нем были 4 чипа HD44102CH и 2 HD44102, и 4 дискретных микросхемы описание которых я не нашел.
Reference manual на HD44102 был найден, и было 8 ножек 4 микросхем соединенных между собой и выведенных на разъем — так нашлись D0-D7, питание было найдено по дискретным микросхемам. Оставались сигналы RW,E,CS,R/S, В youtub был найден LCD модуль HLM9301 с виду очень похожий на мой LCD, итальянец на форуме www.lcdstudio.com дал распиновку которая совпадала с собранным мною априором:
1 GND; 2 VCC;
3 contraste ( generalmente terminal medio de potenciometro de 10k colocado entre vcc y gnd) 4 NC (no conectado);
5 NC; 6 CS1;
7 CS2; 8 CS3;
9 NC; 10 E;
11 R/W 12 R/S (DATA/INSTRUCTION)
13 D0; 14 D1;
15 D2; 16 D3
17 D4; 18 D5;
19 D6; 20 D7.
Но при подаче команд матрица не проявляла признаков жизни.
После долгого, не меньшего от предыдущего, поиска по интернетам выяснилось что старым графическим экранам необходимо было отрицательное напряжение для яркости. Был включен преобразователь DC-DC P6AU0505 и между выводом яркости и -5 установлен прецизионный переменный резистор 200кОм.
Команды от HD44102 подошли. Была написана библиотека работы с HLM9301. На форумах ребята утверждали что с Arduino все работало сразу со стандартной библиотекой GLCD.
Видео демонстрирует прочитанные данные из внутренних RTC и термометра.
Подключение и получение данных от RTL
Инициализация RTC происходит так:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_SYSCFG, ENABLE);
PWR_RTCAccessCmd(ENABLE);
RCC_LSEConfig(RCC_LSE_ON); //do not touch LSE to prevent RTC calendar reset
while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET) {}
RCC_RTCCLKCmd(ENABLE);
Проблема: при сбросе сбрасывался и RTC. Фрагмент кода взятый из демонстрационного примера что-то делал с LSE — этим и сбрасывался RTC.
Чтение данных:
RTC_DateTypeDef RTCDateStr;
RTC_TimeTypeDef RTCTimeStr;
RTC_GetTime(RTC_Format_BIN, &RTCTimeStr);
RTC_GetDate(RTC_Format_BIN, &RTCDateStr);
sprintf(strDisp, "%02d/%02d/%02d %02d:%02d:%02d", RTCDateStr.RTC_Year, RTCDateStr.RTC_Month, RTCDateStr.RTC_Date, RTCTimeStr.RTC_Hours, RTCTimeStr.RTC_Minutes, RTCTimeStr.RTC_Seconds);
Тут то получились две новые задачи «или»: в цепь питания микросхемы включить ионистор и при падении напряжения питания переходить в «спящий режим», или прицепить внешний RTC. Думаю попробовать оба метода…
Подключение цифрового датчика температуры DS18B20
Благодаря статьям Stm32 + 1-wire + DMA (продолжение) и Stm32 + 1-wire + DMA добавлена библиотека onewire.c но для процессора STM32L152 инициализация портов выглядит немного по-другому:
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_40MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_USART2);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_USART2);
Схема подключения взята из datasheet:
При помощи статьи «Поиск устройств» была добавлена возможность подключения нескольких устройств на шину one-wire. Разрешение у DS18B20 при считывании всех 12 бит 0,0625 градуса по Цельсию.
Подключение емкостного датчика HCH1000
Измерять емкость можно по-разному, самый простой метод зарядить и следить за падением напряжения, посчитав время вычислить емкость, либо по сопротивлению переменному току оценивать емкость. Honeywell любезно предоставило datasheet в котором датчик был задающей величиной в генераторе на 555. К последнему методу я и прибег собрав простой генератор:
Вычислить частоту оказалось не трудно STM32L152 имеет несколько таймеров которые могут работать в режиме захвата параметров PWM сигнала. Подробо здесь.
Отличием оказалось, как и в случае с one-wire конфигурация портов:
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_40MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource1, GPIO_AF_TIM2);
В остальном все по тексту в прерывании вычитываем значения счетчиков, получили длину периода, умножили на коэффициент есть емкость, от емкости согласно графиков датчика перешли к влажности.
Подключение пьезоэлектрического датчика HSF1000
Подключил датчик на Vref, GND и ко входу АЦП. Опыт показал, что точности 12 разрядного АЦП оказалось мало чтоб оценить полезный сигнал. Подключение инструментального усилителя AD8555 по стандартной схеме к датчику дало свои плоды. Усиления в 10 раз вполне хватило чтоб поднять уровень сигнала до 0,7В.
Вот главный экран устройства
значения по строкам:
1. дата время из внутреннего RTL;
2. скважность и период сигнала с генератора, также количество найденных устройств one-wire;
3. емкость датчика влажности и влажность;
4. идентификатор one-wire;
5. значение температуры;
6. значение напряжения;
7. значение температуры кристала;
8. значение давления.
Исходники проекта здесь
Автор: tarasii