Вступление
В первой части статьи на примере “Умного чайника” я описал процесс разработки приложения, интегрированного в экосистему SmartThings. В этой части я усложняю пример: добавляю датчик температуры и делаю плавную индикацию RGB-светодиода. Я опишу, чем отличаются ESP8266 и ESP32, и почему в этом примере нам больше подходит именно ESP32. Также будет описана передача сообщений между потоками/тасками на примере очередей в FreeRTOS. Таким образом, данная статья предназначена для всех, кто хочет перейти от самых простых умных устройств с минимумом функционала, к устройствам чуть более сложным как с программной, так и с железной точки зрения.
Вспоминаем функции/capability
Напомню функции “чайника”, которые будем реализовывать в приложении.
Ниже в формате таблицы представлены:
Функции «чайника»
Какие из частей устройства, облака и телефона будут выполнять эти функции
Как это будет происходить
По сравнению с предыдущей версией приложения, изменилась индикация RGB-светодиода при назначении температуры нагрева. Также вместо эмуляции температурного сенсора в этом примере мы получаем реальные данные от датчика температуры DS18B20.
В приложении для представления этих функций и возможностей устройства используются следующие Capabilities:
Switch - переключатель, которым начинаем и завершаем процесс кипячения
Temperature Measurement - показывает текущую температуру “чайника”
Thermostat Heating Setpoint (или его кастомный вариант) - выбор температуры нагрева
Выбор микроконтроллера
В прошлой версии “Умного чайника” не было датчика температуры, а RGB-светодиод принимал только дискретные значения (логические 0 и 1) для каждого из 3 выводов. В новой версии устройства RGB-светодиод во время процесса подогрева должен плавно изменять цвет по спектру от зелёного до красного, проходя жёлтый и оранжевый цвета. Для этого подойдут 3 любых GPIO пина, подключенных к каналам ШИМ. Для датчика температуры DS18B20 нужен 1 цифровой пин. Всё это есть в платах ESP8266, но для разнообразия и из-за перспективы вытеснения ESP8266 новыми схожими модулями ESP32 в этом примере я буду использовать ESP32.
Далее подробнее опишу различия и перспективы ESP8266 и ESP32. Надеюсь это поможет лучше разобраться в этих модулях и подобрать наилучший вариант для вашего проекта, исходя из соотношения цена/качество.
Различия ESP8266 и ESP32
Чип ESP32 является преемником ESP8266 и превосходит его во всех характеристиках, кроме стоимости. Интересно, что оба чипа представляют собой 32-разрядные микроконтроллеры, таким образом, интуиция здесь не срабатывает.
В ESP32 больше GPIO пинов с различными функциями, более быстрый Wi-Fi и поддержка Bluetooth. ESP32 поддерживает множество периферийных интерфейсов: 2 канала ЦАП, 10 портов для подключения емкостных датчиков, Ethernet, CAN шину, датчик Холла, а также больше SPI, I2C, I2S, UART, каналов АЦП. В ESP32 есть встроенная flash-память, поддерживается её шифрование. ESP8266 дешевле ESP32, хотя цена во много зависит от того, какую модель вы выбираете и где покупаете. Исходный код для ESP32 и ESP8266 совместим, поэтому при переходе с одного на другой код менять почти не придётся. Таким образом, ESP32 предлагает много больше возможностей, а ESP8266 может быть более предпочтительным разве что в очень простых IoT приложениях и из-за более низкой цены. Подробнее о различиях ESP32 и ESP8266 вы можете прочитать в этой статье, а о программировании ESP32 в статье на Хабре.
Микроконтроллер ESP32-C3
В 2020 году Espressif анонсировала новый микроконтроллер ESP32-C3, который совместим по пинам с ESP8266. Этот микроконтроллер основан на ядре с RISC-V архитектурой. ESP32-C3 потенциально может заменить ESP8266, имея весь его функционал, но добавляя больше оперативной памяти, постоянную память, Bluetooth и шифрование. Разработка ESP32-C3 ведется с использованием фреймворка ESP-IDF, в отличие от ESP8266 с его ESP8266 RTOS SDK. Это не влияет на совместимость кода, но процесс сборки немного отличается, что даже более удобно для пользователей ESP32, которые тоже используют ESP-IDF. Таким образом, ESP32-C3 является сбалансированным по цене и функционалу микроконтроллером, который как и ESP8266 подходит под небольшие приложения, но обладает большими возможностями и лучшей безопасностью. Подробнее о ESP32-C3 вы можете прочитать в этой статье на Хабре.
На данный момент этой платы пока нет в российских магазинах, но вы уже можете купить ее на Aliexpress.
Влияние RISC-V на выбор микроконтроллера
RISC-V архитектура находит признание благодаря своей открытости, которая позволяет кастомизировать дизайн процессора, и свободе от лицензионных сборов в пользу разработчиков архитектуры. Это увеличивает конкуренцию на рынке и количество различных по характеристикам чипов, поскольку производители могут свободнее подходить к их изменению и улучшению. Архитектура процессора не всегда напрямую влияет на выбор микроконтроллера. Для производителя открытая архитектура позволяет экономить на процессорах и вкладывать в развитие других частей микроконтроллера. Также открытая архитектура способствует расширению семейства процессоров, что опять же позволяет экономить на процессоре, поскольку используется наиболее близкий к потребностям пользователей микроконтроллер. В целом открытая архитектура имеет положительные долгосрочные эффекты для производителей, и, соответственно, пользователей, поскольку открывает возможности свободного развития продуктов и обогащения рынка разнообразием новых устройств.
Сборка на макетной плате
От теории перейдем к практической реализации.
Схема подключения:
На схеме используется датчик температуры с типом корпуса TO-92. Но также датчик может быть в водонепроницаемой форме с длинным кабелем. На следующем фото слева - датчик в корпусе ТО-92, справа - в водонепроницаемом кабеле.
При создании примера я сначала использовал первый вариант, но для тестирования с настоящей подогретой водой решил перейти на второй. Фото устройства, собранного по схеме:
Организация кода
Структура директорий
Файлы проекта распределены по директориям. В основной директории - конфигурационные файлы, необходимые для сборки. Их можно просто скопировать, и только в CMakeLists.txt изменить название проекта, если вы склонировали проект не в директорию kettle_example. Директория build генерируется при сборке и не содержит исходного кода. Основное внимание на директории main и components, которые содержат компоненты с исходным кодом. В директории components располагаются все сторонние компоненты/библиотеки. В main - написанный нами код, а именно файлы работы с Capabilities, файлы управления периферией и файл main.c с бизнес-логикой. Также в main есть файл CMakeLists.txt, необходимый для сборки проекта. Процесс сборки рассмотрим далее.
Отличие сборки проекта по сравнению с ESP8266
В примерах для ESP8266 используется система сборки Make. Для успешной сборки нужно иметь Makefile в директории проекта со следующим минимальным содержимым:
PROJECT_NAME := myProject
include $(IDF_PATH)/make/project.mk
В сборке под ESP32 в дополнение используется CMake, который позволяет использовать и другие системы сборки помимо Make, например Ninja.
В каждом проекте содержится один или несколько компонентов. Компонент - это директория, в которой есть файл CMakeLists.txt. Директория main - это особенный компонент, который содержит исходный код самого проекта. Поэтому необходимо создать файл CMakeLists.txt в директории main. Содержимое этого файла можно скопировать с других примеров от SmartThings. В нашем примере CMakeLists.txt отличается лишь тем, что в idf_component_register, который регистрирует компонент, перечисляются не исходные файлы, а директории с исходными файлами. Для этого в idf_component_register используем не SRCS с перечислением файлов, а SRC_DIRS с перечислением директорий:
idf_component_register(SRC_DIRS
.
../components/esp32-ds18b20
../components/esp32-owb
EMBED_FILES "device_info.json"
"onboarding_config.json"
)
Подробнее о системах сборки ESP-проектов можно прочитать в соответствующих разделах документации для ESP32 и для ESP8266.
Подгрузка компонентов/библиотек для датчика температуры
У нас используется датчик температуры DS18B20, который работает по 1-Wire шине. В проекте используется 2 компонента, совместимых с ESP32: esp32-owb и esp32-ds18b20.
Компонент esp32-owb - это библиотека для работы с протоколом 1-Wire.
Компонент esp32-ds18b20 - это библиотека, которая предоставляет удобное api для работы с датчиком температуры, без необходимости напрямую работать по 1-Wire протоколу.
В нашем гит-проекте эти компоненты используются как подмодули/submodules, и чтобы их подгрузить, при клонировании проекта нужно использовать флаг --recurse-submodules:
$ git clone --recurse-submodules https://github.com/flisoch/SmartThings-Smart-Kettle-Example-esp32.git kettle_example
Подгрузить подмодули можно и после обычного клонирования без флага --recurse-submodules. Для этого в основной директории проекта kettle_example инициализируем и обновляем подмодуль следующими командами:
$ git submodule init
$ git submodule update
Подробнее о подмодулях вы можете прочитать в соответствующей главе книги “Pro Git”.
Бизнес-логика в коде приложения
В первой части статьи я уже описывал бизнес-логику приложения. Напомню, что под бизнес-логикой я понимаю обработку событий с периферии и с облака. При обработке происходит или управление периферией, или передача атрибутов Capability в облако.
Считывание показаний температуры с датчика
В отличие от примера для ESP8266, в этом примере добавляются события от настоящего датчика. Это взаимодействие организовано в виде передачи сообщений через очередь (FreeRTOS Queue) между двумя тасками/потоками: основным таском с управлением и мониторингом остальной периферии и таском, считывающим данные с датчика температуры. В основном таске создаётся очередь temperature_events_q, а также запускается таск, считывающий температуру.
static void app_main_task(void *arg)
{
/* . . . */
// создаём очередь с 1 элементом - для последнего значения температуры
QueueHandle_t temperature_events_q = xQueueCreate(1, sizeof(double));
// нужно для управления таском, например чтобы удалить/остановить его
TaskHandle_t xHandle = NULL;
// создаём таск, передаем аргументом очередь и xHandle
// 4096 - размер стека, 10 - приоритет таска/потока
xTaskCreate(temperature_events_task, "temperature_events_task", 4096, (void *)temperature_events_q, 10, &xHandle);
/* . . . */
}
В основном таске внутри бесконечного цикла на каждой итерации происходит попытка получить значение температуры из очереди и записать в переменную temperature_value. Если значение переменной temperature_value поменялось, то новое значение температуры отправляется в облако и отображается в UI приложения:
static void app_main_task(void *arg)
{
/* . . . */
for (;;) {
/* . . . */
xQueueReceive(temperature_events_q, &temperature_value, portMAX_DELAY);
if(prev_temp_value != temperature_value) {
prev_temp_value = temperature_value;
cap_temperature_data->set_temperature_value(cap_temperature_data, temperature_value);
cap_temperature_data->attr_temperature_send(cap_temperature_data);
}
/* . . . */
}
}
Подробнее о работе с тасками и очередями вы можете прочитать в 3 и 4 главе книги "Mastering the FreeRTOS Real Time Kernel", рекомендуемой на странице с ресурсами в документации FreeRTOS.
Светодиодная индикация
Помимо нового источника событий в коде бизнес-логики меняется управление RGB светодиодом при установке значения температуры подогрева “чайника” в коллбэке Thermostat Heating Setpoint Capability, а также в начале и завершении процесса подогрева.
static void cap_thermostat_cmd_cb(struct caps_thermostatHeatingSetpoint_data *caps_data)
{
heating_setpoint = caps_data->get_value(caps_data);
// индикация светодиода в зависимости от выбранной температуры нагрева
setpoint_rgb_indication(heating_setpoint);
if (!thermostat_enable) {
// индикация выбора температуры нагрева
setpoint_rgb_indication(heating_setpoint);
}
else {
// если чайник уже нагревается, то изменение температуры нагрева изменит цвет светодиода исходя из текущей и новой заданной температуры.
change_rgb_led_state(LEDC_MIN_DUTY, LEDC_MAX_DUTY, LEDC_MIN_DUTY);
change_rgb_led_heating(heating_setpoint, 0, cap_temperature_data->get_temperature_value(cap_temperature_data));
}
}
static void app_main_task(void *arg)
{
/* . . . */
if (thermostat_enable) {
// изменяем цвет светодиода а начале и в процессе нагревания
change_rgb_led_boiling(heating_setpoint, temperature_value);
}
if (thermostat_enable && temperature_value >= heating_setpoint) {
// завершаем процесс нагрева
thermostat_enable = false;
// в последний раз меняем цвет светодиода
change_rgb_led_heating(heating_setpoint, temperature_value);
temperature_value = 0;
buzzer_enable = true;
}
/* . . . */
if (buzzer_enable) {
beep();
buzzer_enable = false;
// возвращаем синий цвет по завершении нагревания
change_rgb_led_state(LEDC_MIN_DUTY, LEDC_MIN_DUTY, LEDC_MAX_DUTY);
cap_switch_data->set_switch_value(cap_switch_data, caps_helper_switch.attr_switch.value_off);
cap_switch_data->attr_switch_send(cap_switch_data);
}
}
Периферия
Инициализация пинов
Отличаться будет инициализация пинов для RGB светодиода и пина для датчика температуры. В RGB светодиоде пины будут сконфигурированы под ШИМ для плавного изменения красного и зеленого цветов светодиода. Для управления яркостью светодиодов и генерации ШИМ-сигналов в esp-idf есть периферийное устройство LEDC. В функции iot_gpio_init произведем конфигурацию LEDC-каналов:
Конфигурация таймера - нужно определить частоту ШИМ-сигнала и разрешение рабочего цикла.
Конфигурация канала - нужно передать настроенный таймер и соответствующий GPIO пин для вывода ШИМ-сигнала.
void iot_gpio_init(void)
{
/* . . . */
ledc_timer_config_t ledc_timer = {
.duty_resolution = LEDC_TIMER_13_BIT,
.freq_hz = 5000,
.speed_mode = LEDC_HS_MODE,
.timer_num = LEDC_TIMER,
.clk_cfg = 0,
};
ledc_timer_config(&ledc_timer);
ledc_channel_config_t ledc_channel = {
.channel = LEDC_RED_CHANNEL,
.duty = 0,
.gpio_num = LEDC_RED_GPIO,
.speed_mode = LEDC_HS_MODE,
.hpoint = 0,
.timer_sel = LEDC_TIMER};
ledc_channel_config(&ledc_channel);
ledc_channel.gpio_num = LEDC_GREEN_GPIO;
ledc_channel.channel = LEDC_GREEN_CHANNEL;
ledc_channel_config(&ledc_channel);
ledc_channel.gpio_num = LEDC_BLUE_GPIO;
ledc_channel.channel = LEDC_BLUE_CHANNEL;
ledc_channel_config(&ledc_channel);
ledc_fade_func_install(0);
/* . . . */
}
Инициализация датчика температуры
Прежде чем использовать датчик через структуру DS18B20_Info, нужно инициализировать доступ к шине 1-Wire. Для этого используется функция owb_rmt_initialize из owb_rmt.h, которая возвращает указатель на структуру OneWireBus. При этом можно использовать другую функцию, owb_gpio_initialize из owb_gpio.h. В первом случае используется не GPIO драйвер, а RMT (Remote Control) - специфический для ESP, предназначенный для работы с инфракрасными сигналами и не только. Этот вариант рекомендован разработчиками библиотеки esp32-owb, т.к. приводит к более надёжной работе и очень точным временным интервалам чтения/записи. Также включаем использование алгоритма нахождения контрольной суммы CRC.
void temperature_events_task(void *arg)
{
/* . . . */
OneWireBus *owb;
owb = owb_rmt_initialize(&rmt_driver_info, GPIO_TEMPERATURE_SENSOR, RMT_CHANNEL_1, RMT_CHANNEL_0);
owb_use_crc(owb, true); // Включить CRC проверку для ROM кода
/* . . . */
}
Затем, используя готовую структуру шины, инициализируем структуру DS18B20_Info:
void temperature_events_task(void *arg)
{
/* . . . */
DS18B20_Info * ds18b20_info;
// выделяем память
ds18b20_info = ds18b20_malloc();
// инициализируем один датчик, не несколько
ds18b20_init_solo(ds18b20_info, owb);
// включаем использование алгоритма нахождения контрольной суммы CRC
ds18b20_use_crc(ds18b20_info, true);
// устанавливаем разрешение АЦП на 12 бит(шаг в 0.0625°С)
ds18b20_set_resolution(ds18b20_info, DS18B20_RESOLUTION_12_BIT);
/* . . . */
}
Считывание и передача температуры (Очередь FreeRTOS)
После инициализации 1-Wire шины и структуры датчика DS18B20_Info в бесконечном цикле раз в секунду происходит считывание температуры и отправка её в очередь. Поскольку значение температуры считывается в переменную типа float, а в остальных частях программы, в том числе при работе с Capability, используется double, мы используем 2 переменные разных типов и преобразуем float в double:
void temperature_events_task(void *arg) {
/* . . . */
float temperature_value;
double send_value;
for (;;)
{
ds18b20_convert_all(owb);
ds18b20_wait_for_conversion(ds18b20_info);
ds18b20_read_temp(ds18b20_info, &temperature_value);
printf("TEMP READ: %f\n", temperature_value);
send_value = (double) temperature_value;
//передача температуры в очередь
xQueueSendToBack(queue, &send_value, 0);
vTaskDelay(pdMS_TO_TICKS(TEMPERATURE_EVENT_MS_RATE));
}
}
Управление RGB светодиодом
Здесь я опишу, как именно выставляются значения всем пинам светодиода при установке значения температуры подогрева “чайника” в коллбэке Thermostat Heating Setpoint Capability, а также в процессе подогрева.
Начнём с функции setpoint_rgb_indication в коллбэке. В зависимости от выбранной температуры нагрева, светодиод в течение нескольких секунд может светиться синим, жёлтым, оранжевым или красным. Для каждого из цветов выбраны соответствующие значения температур: синий - меньше 30°С, жёлтый - меньше 50°С, оранжевый - меньше 75°С, красный - меньше 100°С.
void setpoint_rgb_indication(double heating_setpoint)
{
if (heating_setpoint <= 30) {
//зеленый
change_rgb_led_state(LEDC_MIN_DUTY, LEDC_MAX_DUTY, LEDC_MIN_DUTY);
}
else if (heating_setpoint <= 50)
{
// жёлтый
change_rgb_led_state(LEDC_MAX_DUTY, LEDC_MAX_DUTY, LEDC_MIN_DUTY);
}
else if (heating_setpoint <= 75) {
//оранжевый
change_rgb_led_state(LEDC_MAX_DUTY, (int)round(LEDC_MAX_DUTY / 2), LEDC_MIN_DUTY);
}
else if (heating_setpoint <= 100) {
//красный
change_rgb_led_state(LEDC_MAX_DUTY, LEDC_MIN_DUTY, LEDC_MIN_DUTY);
}
else {
printf("heating setpoint is more than 100 or not set!\nPlease, set correct number");
}
// блокировка на несколько секунд
vTaskDelay(pdMS_TO_TICKS(HEATING_SETPOINT_RGB_DURATION));
// возвращение свечения светодиода синим цветом
change_rgb_led_state(LEDC_MIN_DUTY, LEDC_MIN_DUTY, LEDC_MAX_DUTY);
}
void change_rgb_led_state(int red, int green, int blue) {
// ШИМ рабочий цикл 0-4096
ledc_set_duty(LEDC_HS_MODE, LEDC_RED_CHANNEL, red);
ledc_update_duty(LEDC_HS_MODE, LEDC_RED_CHANNEL);
ledc_set_duty(LEDC_HS_MODE, LEDC_GREEN_CHANNEL, green);
ledc_update_duty(LEDC_HS_MODE, LEDC_GREEN_CHANNEL);
ledc_set_duty(LEDC_HS_MODE, LEDC_BLUE_CHANNEL, blue);
ledc_update_duty(LEDC_HS_MODE, LEDC_BLUE_CHANNEL);
}
В процессе подогрева цвет RGB светодиода плавно меняется от зелёного к жёлтому и затем от жёлтого к красному. В главном таске/потоке в бесконечном цикле при получении нового температурного события запускается функция change_rgb_led_heating. Цвет меняется в зависимости от прогресса нагревания. Прогресс вычисляется на основе текущей температуры и двух граничных значений - минимальной температуры и конечной заданной температуры. Пока прогресс нагревания меньше 50%, меняется красная компонента цвета. Таким образом от зелёного, добавляя красный, мы идём к жёлтому. Как только прогресс нагревания превысит 50%, красная компонента становится максимальной - меняем значение рабочего цикла на максимальное для LEDC-канала, соединенного с красным светодиодом. Затем, чтобы от жёлтого дойти до красного, нужно уменьшать зелёную компоненту, пока прогресс нагревания не дойдёт до 100%.
Функция change_rgb_led_heating
void change_rgb_led_heating(double heating_setpoint, double current_temperature)
{
// Зелёный 0, 4000, 0 -- 0%
// Жёлтый 4000, 4000, 0 -- 50%
// Красный 4000, 0, 0 -- 100%
double min = 0;
double max = heating_setpoint;
// вычисляем прогресс на основе текущей температуры и граничных значений.
//Например 26°C при минимуме 0 и температуре нагрева 50°C даст прогресс 52%
double progress = (current_temperature - min) / (max - min);
// прогресс для прошлого значения температуры
double prev_progress = (prev_temperature - min)/ (max - min);
// прогресс, после которого фиксируем красную и уменьшаем зелёную компоненту цвета светодиода
double progress_middle = 0.5;
double total_duty_resource = LEDC_MAX_DUTY * 2;
// Если не дошли до середины, зеленый на максимум, красный увеличиваем
if (progress < progress_middle) {
// Green max
ledc_set_duty(LEDC_HS_MODE, LEDC_GREEN_CHANNEL, LEDC_MAX_DUTY);
ledc_update_duty(LEDC_HS_MODE, LEDC_GREEN_CHANNEL);
// если только что пересекли середину, то увеличиваем красный частично, не на всю разницу температуры
if (just_crossed_middle_down) {
update_progress = progress_middle - progress;
updated_duty = LEDC_MAX_DUTY - update_progress * total_duty_resource;
}
else {
update_progress = progress - prev_progress;
updated_duty = ledc_get_duty(LEDC_HS_MODE, LEDC_RED_CHANNEL) + update_progress * total_duty_resource;
}
// увеличиваем красный
ledc_set_duty(LEDC_HS_MODE, LEDC_RED_CHANNEL, updated_duty);
ledc_update_duty(LEDC_HS_MODE, LEDC_RED_CHANNEL);
}
// если дошли до середины, красный на максимум, зеленый уменьшаем.
else {
// красный на максимум
ledc_set_duty(LEDC_HS_MODE, LEDC_RED_CHANNEL, LEDC_MAX_DUTY);
ledc_update_duty(LEDC_HS_MODE, LEDC_RED_CHANNEL);
// если только что пересекли середину, то уменьшаем зеленый частично, не на всю разницу температуры
if (just_crossed_middle_up) {
update_progress = progress - progress_middle;
updated_duty = LEDC_MAX_DUTY - update_progress * total_duty_resource;
}
else {
update_progress = progress - prev_progress;
updated_duty = ledc_get_duty(LEDC_HS_MODE, LEDC_GREEN_CHANNEL) - update_progress * total_duty_resource;
}
// уменьшаем зелёный
ledc_set_duty(LEDC_HS_MODE, LEDC_GREEN_CHANNEL, updated_duty);
ledc_update_duty(LEDC_HS_MODE, LEDC_GREEN_CHANNEL);
}
vTaskDelay(pdMS_TO_TICKS(RGB_BOILING_ADJUSTMENT_DURATION));
}
Заключение
На более продвинутом примере устройства “Умный чайник” мы разобрали, как собирается проект под ESP32, как используются таски и очереди FreeRTOS и датчик DS18B20 на 1-Wire шине. Мы рассмотрели различия ESP32 и ESP8266 и выбрали подходящий микроконтроллер для проекта. Теперь вам будет проще разобраться в линейке устройств ESP, использовать возможности FreeRTOS и работать с датчиками от Dallas Semiconductor.
Видео того, что получилось:
Об авторе
Ниез Юлдашев - Студент магистратуры ИТИС КФУ по специальности Программная инженерия (профиль: Аналитика, управление разработкой и FinTech), стажёр Исследовательского центра Samsung.
Комментарии (18)
zag2art
17.09.2021 11:34где-то читал, люди умные чайники на attiny13 делают...
robofreak
17.09.2021 14:18Интересно, как они к нему вайфай подключали. Иначе как решить ключевую проблему умного дома - включить чайник, сидя на диване в другой комнате :)
Polarisru
17.09.2021 14:57+1Если бы еще кто-то решил более актуальную проблему - добраться до воды в умном чайнике, было бы вообще чудесно!
sintech
17.09.2021 16:05Мне бы хватило возможности сообщать о том, что чайник пустой, но к сожалению реализовать это не проще чем научить его самостоятельно наливать в себя воду.
Jack_Vo
18.09.2021 14:28Можно использовать термопот, и наполнять его с помощью электромагнитного клапана.
rPman
18.09.2021 16:17+1Лучше всего заменить чайник на 'очень умный' кулер, с постоянным подогревом воды, когда вода заканчивается, после использования, он булькает где то минуту (не может накачать воды из пустого бутыля) и лампочка загорается
korolevdd
23.09.2021 05:47Легко. Всего неделя и вся семья привыкла доливать чайник, прежде чем ставить на базу.
FGV
17.09.2021 11:38+4ЦАП для управления яркость светодиода? Зачем? Есть же ШИМ, причем что у 8266, что у 32.
flisoch Автор
19.09.2021 23:41Здесь управление не яркостью, а самим цветом. ШИМом можно было бы например от тускло-красного к ярко-красному переходить, но не от зеленого к красному
FGV
20.09.2021 04:37Здесь управление не яркостью, а самим цветом.
И в чем разница? Есть несколько цветов (пусть будут RGB), вешаем их на несколько каналов ШИМ, и спокойно управляем яркостью каждого канала получая нужные оттенки цвета.
ШИМом можно было бы например от тускло-красного к ярко-красному переходить, но не от зеленого к красному
Так будет если все светики на один провод повесить. Но у той же 8266 ШИМ аж на четыре канала есть. Поэтому ничего не мешает менять яркость G от 0 до 255 одновременно с изменением яркости R от 255 до 0, получая тот же переход от зеленого к красному.
flisoch Автор
08.10.2021 11:14Спасибо за замечания, ШИМ действительно сработал и не хуже ЦАПа. Статью отредактировал под эти изменения
FGV
20.09.2021 10:48Ну и докучи при подключении светика напрямую к выходу ЦАП у Вас диапазон значений при которых он светится будет в районе ~100...255 (а то и еще меньше, т.к. ВАХ светодиода не линеен и у разных цветов напряжение начала свечения - разное).
aivs
22.09.2021 01:12Один раз в жизни реально жизненно необходимо было разработать «умный чайник». В Нидерландах с немецкими коллегами были в кэмпинге по роботехнике и прочим DIY. Жили в палатках, электрический чайник никто не взял, но у нас был советский спиральный водонагреватель, клали в кружку и через 2 минуты вода кипит. Решили автоматизировать: к RPi подключили реле с водонагревателем и датчик температуры, при достижении 95 градусов реле выключалось, включали с телефона. Несколько дней все радовались находчивости русских, пока мы не забыли налить воды в кружку ????????. Нужно было видеть лица немцев, когда в метре от них рванул фугас ????
volchenkodmitriy
А на какой фотографии показан сам "Умный чайник"?)))
zag2art
на самой верхней, видимо пока только прототип. Но, вообще выражение "умный чайник" - это какой-то оксюморон.
zag2art
Со второго раза понял вашу иронию :). Но лучше поздно, чем никогда.