Espruino:Примеры/Сигнал о незакрытой двери холодильника: различия между версиями
Myagkij (обсуждение | вклад) (Новая страница: «{{Espruino/Панель перехода}} {{Перевод от Сubewriter}} {{Myagkij-редактор}} =<ref>[ www.espruino.com - ]</ref>= <syntaxhighlig...») |
Нет описания правки |
||
(не показано 5 промежуточных версий 2 участников) | |||
Строка 3: | Строка 3: | ||
{{Myagkij-редактор}} | {{Myagkij-редактор}} | ||
=<ref>[ www.espruino.com - ]</ref>= | =Сигнал о незакрытой двери холодильника<ref>[https://www.espruino.com/Freezer+Alarm www.espruino.com - Freezer Alarm]</ref>= | ||
[[Файл:Freezer Alarm finished.jpg|center]] | |||
Наверно, всем знакома проблема, когда вы забываете как следует закрыть холодильник, и в результате продукты внутри начинают оттаивать. Одни холодильники умеют напоминать сигналом о том, чтобы пользователь закрыл дверь, а другие нет – и в этом руководстве мы расскажем, как сделать такую сигнальную систему при помощи [[Pixl.js]]. Она пищит, если внутри холодильника слишком тепло, показывает текущую температуру и накопленные температурные данные, а также отправляет эти данные по [[BLE]], чтобы их можно было журналировать. | |||
== Нам понадобятся == | |||
* Espruino [https://www.espruino.com/Pixl.js Pixl.js]. | |||
* [https://www.espruino.com/DS18B20 Температурный датчик DS18B20] – либо с кабелем, либо в корпусе [[TO-92]], к которому надо будет подсоединить тонкий кабель. | |||
* [[Резистор]] на [[4.7 кОм]]. | |||
* Литий-полимерная [https://www.espruino.com/Battery батарея] (либо что-то больше 3.5 вольт, но меньше 15 вольт). | |||
* [https://www.espruino.com/Speaker Пьезодинамик] (я использовал модель от [https://www.rapidonline.com/Audio-Visual/Miniature-PCB-Piezo-Transducer-35-0044 Rapid]). | |||
== Температурный датчик == | |||
[[Файл:Freezer Alarm ds18b20.jpg|center]] | |||
Я использую [[DS18B20]], потому что это точный цифровой датчик, что позволяет избежать искажения данных из-за длинного провода. | |||
Датчики [[DS18B20]] бывают разных типов – к одним уже сразу подсоединён кабель (см. фото выше), а другие спрятаны в корпус [[TO-92]] (см. посередине на фото выше). Датчиком с кабелем пользоваться проще, но в нашей ситуации могут возникнуть трудности с тем, чтобы разместить его в холодильнике – из-за кабеля дверца может просто не закрыться, из-за чего, возможно, придётся просверлить в ней отверстие для кабеля. | |||
Во избежание этого я решил воспользоваться [[DS18B20]], помещённым в маленький транзисторный корпус [[TO-92]], так как это позволит мне подсоединить к нему достаточно тонкий кабель. Подключение выполняется следующим образом: | |||
[[File:1 - Freezer_Alarm_to92.jpg|center]] | |||
Тонкий кабель можно купить, но я решил сделать его сам – я взял три тонких провода и поместил их между двумя полосками прозрачного скотча. Такой кабель можно без труда провести через дверной проём, и он никак не будет мешать закрытию двери: | |||
[[File:Freezer_Alarm_sensor.jpg|center]] | |||
== Подсоединение == | |||
Устройства подключаются друг к другу очень просто: | |||
* Подключите температурный датчик [[DS18B20]] к контактам 3.3v и GND как показано на картинке выше. Контакт для передачи данных должен быть подключен к контакту A0. | |||
* Подключите [[резистор]] на [[4.7 кОм]] между контактами A0 и 3.3v. | |||
* Подключите пьезодинамик между контактами D10 и GND. Для передачи данных можно использовать любой контакт, но на этом пьезодинамике расстояние между контактами составляет 10 мм, что позволяет просто воткнуть их в гребешки Pixl.js. | |||
* Подключите батарею между контактами Vin и GND. Для этого можно воспользоваться контактами JST или Arduino-гребешком (или просто подать питание через Micro-USB). Кроме того, я подключил напрямую к батарее маленькую солнечную панель, чтобы восполнять её заряд. | |||
Чтобы упростить подключение устройств друг к другу, я отрезал от печатной платы маленькую полоску с контактными отверстиями и подсоединил её к задней части Pixl.js, а затем приклеил самодельный кабель скотчем, чтобы он не вертелся и не ломался. Впрочем, если вам так проще, можете просто воткнуть провода в гребешки контактов: | |||
[[File:Freezer_Alarm_assembled.jpg|center]] | |||
== Код == | |||
Подключитесь к [[Pixl.js]] при помощи [[Web IDE]], скопируйте код ниже в правую часть [[IDE]] и нажмите на кнопку загрузки кода. | |||
<syntaxhighlight lang="javascript"> | |||
var ALARM_TEMP = -5; // температура, при которой | |||
// будет сгенерирован сигнал | |||
var PIN_BUZZER = D10; // контакт, к которому подключен пьезодинамик | |||
var PIN_SENSOR = A0; // контакт, к которому подключен | |||
// температурный датчик | |||
var ow,sensor,history; | |||
var avrSum=0,avrNum=0; | |||
var lastTemp = 0; | |||
var alarmEnabled = true; | |||
var alarmPos = 0; | |||
var alarmInterval; | |||
// Здесь включаем или выключаем тревогу: | |||
function setAlarm(on) { | |||
if (on) { | |||
if (!alarmInterval) | |||
alarmInterval = setInterval(function() { | |||
alarmPos = !alarmPos; | |||
analogWrite(PIN_BUZZER,0.5,{freq:alarmPos?800:900}); | |||
}, 200); | |||
} else { | |||
if (alarmInterval) | |||
clearInterval(alarmInterval); | |||
alarmInterval = 0; | |||
digitalWrite(PIN_BUZZER,0); | |||
} | |||
} | |||
// Рисуем на экране температуру и график: | |||
function draw() { | |||
// Рисуем: | |||
g.clear(); | |||
g.setFontVector(30); | |||
g.setFontAlign(0,-1); | |||
g.drawString(lastTemp.toFixed(1), 64,5); | |||
g.setFontBitmap(); | |||
g.drawString("Температура", 64, 0); | |||
require("graph").drawLine(g, history, { | |||
axes : true, | |||
gridy : 5, | |||
x:0, y:37, | |||
width:128, | |||
height:27 | |||
}); | |||
g.setFontAlign(-1,-1); | |||
g.drawString(alarmEnabled?"ALARM ON":"NO ALARM",0,0); | |||
g.flip(); | |||
// Проверяем температуру: | |||
setAlarm(alarmEnabled && (lastTemp>ALARM_TEMP)); | |||
} | |||
// Эта функция будет вызываться после считывания температуры: | |||
function onTemp(temp) { | |||
if (temp===null) return; // некорректные данные | |||
avrSum+=temp; | |||
avrNum++; | |||
lastTemp = temp; | |||
// Рассылаем BLE-объявления: | |||
var th = Math.round(lastTemp*100); | |||
NRF.setAdvertising({ | |||
0x1809 : [th&255,th>>8] | |||
}); | |||
draw(); | |||
} | |||
// Кнопка BTN1 включает/выключает тревогу: | |||
setWatch(function() { | |||
alarmEnabled = !alarmEnabled; | |||
draw(); | |||
}, BTN1, {edge:1,repeat:1}); | |||
// Используя новые данные о температуре, | |||
// обновляем график и состояние тревоги: | |||
var readingInterval = setInterval(function() { | |||
if (sensor) sensor.getTemp(onTemp); | |||
}, 10000); | |||
// Сохраняем среднее значение в историю: | |||
var histInterval = setInterval(function() { | |||
history.set(new Float32Array(history.buffer,4)); | |||
history[history.length-1] = avrSum / avrNum; | |||
avrSum = 0; | |||
avrNum = 0; | |||
}, 60000); // 1 минута | |||
// При запуске настраиваем OneWire-коммуникацию: | |||
function onInit() { | |||
ow = new OneWire(PIN_SENSOR); | |||
sensor = require("DS18B20").connect(ow); | |||
history = new Float32Array(128); | |||
avrSum=0; | |||
avrNum=0; | |||
} | |||
</syntaxhighlight> | </syntaxhighlight> | ||
Загрузив этот код на [[Pixl.js]], напечатайте save() – это сохранит всё в [[Flash-память]] и запустит код. | |||
== Примечания == | |||
* Звуковые сигналы (тревогу) можно включить и выключить при помощи кнопки '''BTN1''' (её состояние показано на экране [[Pixl.js]]). | |||
* Сам датчик [[DS18B20]] тянет примерно 1 мА – это почти в 4 раза выше, чем у [[Pixl.js]]! Я этого решил не делать, но вы можете подключить к датчику провод и запитать его от IO-контакта, чтобы его можно было выключить, когда он не будет нужен. | |||
== Журналирование данных == | |||
Поскольку загруженный нами код транслирует температурные данные по BLE через стандартную характеристику 1809, мы можем их прочесть и записать. Для этого на [[Raspberry Pi]] с [[BLE]] надо будет установить программу [https://github.com/espruino/EspruinoHub EspruinoHub]. Когда будет создана директория ''«log»'', температурные данные начнут записываться в эту директорию. | |||
Затем вы можете воспользоваться библиотекой [https://github.com/espruino/TinyDash TinyDash], чтобы создавать с помощью этих данных графики. Например, вот так: | |||
[[File:Freezer_Alarm_dashboard.png|center]] | |||
Более подробно об этом рассказывается в другом руководстве. | |||
=См.также= | =См.также= | ||
=Внешние ссылки= | =Внешние ссылки= | ||
Строка 19: | Строка 173: | ||
<references /> | <references /> | ||
{{Навигационная таблица/Espruino}} | {{Навигационная таблица/Портал/Espruino}} | ||
[[Категория:Pixl.js]] | |||
[[Категория:DS18B20]] | |||
[[Категория:4.7 кОм]] | |||
[[Категория:Резистор]] | |||
[[Категория:Пример]] | |||
[[Категория:Примеры]] | |||
[[Категория:Литий-полимерная батарея]] | |||
[[Категория:Пьезодинамик]] | |||
[[Категория:setInterval]] | |||
[[Категория:setInterval()]] | |||
[[Категория:analogWrite]] | |||
[[Категория:analogWrite()]] | |||
[[Категория:clearInterval]] | |||
[[Категория:clearInterval()]] | |||
[[Категория:digitalWrite]] | |||
[[Категория:digitalWrite()]] | |||
[[Категория:clear()]] | |||
[[Категория:setFontVector()]] | |||
[[Категория:setFontAlign()]] | |||
[[Категория:drawString()]] | |||
[[Категория:setFontBitmap()]] | |||
[[Категория:drawString()]] | |||
[[Категория:require]] | |||
[[Категория:drawLine()]] | |||
[[Категория:flip()]] | |||
[[Категория:NRF.setAdvertising()]] | |||
[[Категория:NRF.setAdvertising]] | |||
[[Категория:setAdvertising]] | |||
[[Категория:setAdvertising()]] | |||
[[Категория:draw()]] | |||
[[Категория:getTemp]] | |||
[[Категория:getTemp()]] | |||
[[Категория:set()]] | |||
[[Категория:set]] | |||
[[Категория:OneWire]] | |||
[[Категория:Float32Array]] |
Текущая версия от 15:08, 20 мая 2023
Сигнал о незакрытой двери холодильника[1]
Наверно, всем знакома проблема, когда вы забываете как следует закрыть холодильник, и в результате продукты внутри начинают оттаивать. Одни холодильники умеют напоминать сигналом о том, чтобы пользователь закрыл дверь, а другие нет – и в этом руководстве мы расскажем, как сделать такую сигнальную систему при помощи Pixl.js. Она пищит, если внутри холодильника слишком тепло, показывает текущую температуру и накопленные температурные данные, а также отправляет эти данные по BLE, чтобы их можно было журналировать.
Нам понадобятся
- Espruino Pixl.js.
- Температурный датчик DS18B20 – либо с кабелем, либо в корпусе TO-92, к которому надо будет подсоединить тонкий кабель.
- Резистор на 4.7 кОм.
- Литий-полимерная батарея (либо что-то больше 3.5 вольт, но меньше 15 вольт).
- Пьезодинамик (я использовал модель от Rapid).
Температурный датчик
Я использую DS18B20, потому что это точный цифровой датчик, что позволяет избежать искажения данных из-за длинного провода.
Датчики DS18B20 бывают разных типов – к одним уже сразу подсоединён кабель (см. фото выше), а другие спрятаны в корпус TO-92 (см. посередине на фото выше). Датчиком с кабелем пользоваться проще, но в нашей ситуации могут возникнуть трудности с тем, чтобы разместить его в холодильнике – из-за кабеля дверца может просто не закрыться, из-за чего, возможно, придётся просверлить в ней отверстие для кабеля.
Во избежание этого я решил воспользоваться DS18B20, помещённым в маленький транзисторный корпус TO-92, так как это позволит мне подсоединить к нему достаточно тонкий кабель. Подключение выполняется следующим образом:
Тонкий кабель можно купить, но я решил сделать его сам – я взял три тонких провода и поместил их между двумя полосками прозрачного скотча. Такой кабель можно без труда провести через дверной проём, и он никак не будет мешать закрытию двери:
Подсоединение
Устройства подключаются друг к другу очень просто:
- Подключите температурный датчик DS18B20 к контактам 3.3v и GND как показано на картинке выше. Контакт для передачи данных должен быть подключен к контакту A0.
- Подключите резистор на 4.7 кОм между контактами A0 и 3.3v.
- Подключите пьезодинамик между контактами D10 и GND. Для передачи данных можно использовать любой контакт, но на этом пьезодинамике расстояние между контактами составляет 10 мм, что позволяет просто воткнуть их в гребешки Pixl.js.
- Подключите батарею между контактами Vin и GND. Для этого можно воспользоваться контактами JST или Arduino-гребешком (или просто подать питание через Micro-USB). Кроме того, я подключил напрямую к батарее маленькую солнечную панель, чтобы восполнять её заряд.
Чтобы упростить подключение устройств друг к другу, я отрезал от печатной платы маленькую полоску с контактными отверстиями и подсоединил её к задней части Pixl.js, а затем приклеил самодельный кабель скотчем, чтобы он не вертелся и не ломался. Впрочем, если вам так проще, можете просто воткнуть провода в гребешки контактов:
Код
Подключитесь к Pixl.js при помощи Web IDE, скопируйте код ниже в правую часть IDE и нажмите на кнопку загрузки кода.
var ALARM_TEMP = -5; // температура, при которой
// будет сгенерирован сигнал
var PIN_BUZZER = D10; // контакт, к которому подключен пьезодинамик
var PIN_SENSOR = A0; // контакт, к которому подключен
// температурный датчик
var ow,sensor,history;
var avrSum=0,avrNum=0;
var lastTemp = 0;
var alarmEnabled = true;
var alarmPos = 0;
var alarmInterval;
// Здесь включаем или выключаем тревогу:
function setAlarm(on) {
if (on) {
if (!alarmInterval)
alarmInterval = setInterval(function() {
alarmPos = !alarmPos;
analogWrite(PIN_BUZZER,0.5,{freq:alarmPos?800:900});
}, 200);
} else {
if (alarmInterval)
clearInterval(alarmInterval);
alarmInterval = 0;
digitalWrite(PIN_BUZZER,0);
}
}
// Рисуем на экране температуру и график:
function draw() {
// Рисуем:
g.clear();
g.setFontVector(30);
g.setFontAlign(0,-1);
g.drawString(lastTemp.toFixed(1), 64,5);
g.setFontBitmap();
g.drawString("Температура", 64, 0);
require("graph").drawLine(g, history, {
axes : true,
gridy : 5,
x:0, y:37,
width:128,
height:27
});
g.setFontAlign(-1,-1);
g.drawString(alarmEnabled?"ALARM ON":"NO ALARM",0,0);
g.flip();
// Проверяем температуру:
setAlarm(alarmEnabled && (lastTemp>ALARM_TEMP));
}
// Эта функция будет вызываться после считывания температуры:
function onTemp(temp) {
if (temp===null) return; // некорректные данные
avrSum+=temp;
avrNum++;
lastTemp = temp;
// Рассылаем BLE-объявления:
var th = Math.round(lastTemp*100);
NRF.setAdvertising({
0x1809 : [th&255,th>>8]
});
draw();
}
// Кнопка BTN1 включает/выключает тревогу:
setWatch(function() {
alarmEnabled = !alarmEnabled;
draw();
}, BTN1, {edge:1,repeat:1});
// Используя новые данные о температуре,
// обновляем график и состояние тревоги:
var readingInterval = setInterval(function() {
if (sensor) sensor.getTemp(onTemp);
}, 10000);
// Сохраняем среднее значение в историю:
var histInterval = setInterval(function() {
history.set(new Float32Array(history.buffer,4));
history[history.length-1] = avrSum / avrNum;
avrSum = 0;
avrNum = 0;
}, 60000); // 1 минута
// При запуске настраиваем OneWire-коммуникацию:
function onInit() {
ow = new OneWire(PIN_SENSOR);
sensor = require("DS18B20").connect(ow);
history = new Float32Array(128);
avrSum=0;
avrNum=0;
}
Загрузив этот код на Pixl.js, напечатайте save() – это сохранит всё в Flash-память и запустит код.
Примечания
- Звуковые сигналы (тревогу) можно включить и выключить при помощи кнопки BTN1 (её состояние показано на экране Pixl.js).
- Сам датчик DS18B20 тянет примерно 1 мА – это почти в 4 раза выше, чем у Pixl.js! Я этого решил не делать, но вы можете подключить к датчику провод и запитать его от IO-контакта, чтобы его можно было выключить, когда он не будет нужен.
Журналирование данных
Поскольку загруженный нами код транслирует температурные данные по BLE через стандартную характеристику 1809, мы можем их прочесть и записать. Для этого на Raspberry Pi с BLE надо будет установить программу EspruinoHub. Когда будет создана директория «log», температурные данные начнут записываться в эту директорию.
Затем вы можете воспользоваться библиотекой TinyDash, чтобы создавать с помощью этих данных графики. Например, вот так:
Более подробно об этом рассказывается в другом руководстве.
См.также
Внешние ссылки
- Справочник Espruino
- Espruino
- Перевод от Сubewriter
- Проверка:myagkij
- Оформление:myagkij
- Редактирование:myagkij
- Страницы, где используется шаблон "Навигационная таблица/Телепорт"
- Страницы с телепортом
- Pixl.js
- DS18B20
- 4.7 кОм
- Резистор
- Пример
- Примеры
- Литий-полимерная батарея
- Пьезодинамик
- SetInterval
- SetInterval()
- AnalogWrite
- AnalogWrite()
- ClearInterval
- ClearInterval()
- DigitalWrite
- DigitalWrite()
- Clear()
- SetFontVector()
- SetFontAlign()
- DrawString()
- SetFontBitmap()
- Require
- DrawLine()
- Flip()
- NRF.setAdvertising()
- NRF.setAdvertising
- SetAdvertising
- SetAdvertising()
- Draw()
- GetTemp
- GetTemp()
- Set()
- Set
- OneWire
- Float32Array