Arduino

Бесконтактный термометр с передачей данных в облако

Пандемия COVID-19 распространилась на большую часть мира. Одним из симптомов инфекции является повышение температуры, сухой кашель и одышка. Контроль температуры является важным инструментом в данных условиях. Особенно это важно для людей, которые болеют в легкой форме в домашних условиях.

Инфракрасный термометр — это самый быстрый способ узнать, высокая температура нет. Инфракрасный термометр показывает температуру мгновенно. Можно найти бесконтактные инфракрасные термометры в продаже, но не один из них не поддерживает функции IoT для сбора, систематизации и ранения данных о температуре. Чтобы решить эту проблему, мастер сделал термометр IoT, который автоматически отправляет данные на облачный сервер.

Инструменты и материалы:
-Модуль инфракрасного датчика температуры MLX90614;
-Wemos D1 mini ESP8266;
-0,96-дюймовый OLED-дисплей;
-Литий-ионная батарея 18650;
-Модуль зарядки литий-ионной батареи 1A TP4056;
-3D-принтер;
-Паяльная станция;
-Тактовая кнопка — 4 шт;
-Провода;

Шаг первый: общие сведения
Функции термометра:
1. Бесконтактный
2. Аккумуляторный
3. Поддержка WiFi и хранение данных в облаке
4. Просмотр данных из облака
5. Автоматический режим энергосбережения
6. Настройка и калибровка


В датчик MLX90614 встроено два устройства: одно — инфракрасный датчик, а другое — устройство обработки сигналов DSP (вычислительный модуль). Он работает на основе закона Стефана-Больцмана, который гласит, что все объекты излучают инфракрасную энергию, и интенсивность этой энергии будет прямо пропорциональна температуре этого объекта. Чувствительный элемент в датчике измеряет, сколько ИК-энергии излучается объектом, а вычислительный модуль преобразует ее в значение температуры с помощью встроенного 17-разрядного АЦП и выводит данные по протоколу связи I2C. Датчик измеряет как температуру объекта, так и температуру окружающей среды для калибровки значения температуры объекта.

Wemos D1 mini — это модуль с Wi-Fi на ESP8266. Он имеет один аналоговый порт и 11 цифровых портов.
Светодиодный дисплей (OLED), который будет использоваться в данном проекте, — это модель SSD1306: одноцветный 0,96-дюймовый дисплей с разрешением 128 × 64 пикселей. OLED-дисплей не нуждается в подсветки и очень экономичный.

Шаг второй: 3D дизайн и печать
Корпус для своего устройства мастер напечатал на 3D-принтере. За шаблон он взял работу другого мастера. Скачал файл и внес в него некоторые изменения. Например, переделал нишу для батареи с 9 вольтовой на 18650.

Файлы для печати можно скачать ниже.
IoT Thermometer back.stl
IoT Thermometer display panel.stl
IoT Thermometer front.stl
IoT Thermometer sensor panel.stl

Шаг третий: сборка
После распечатки всех файлов мастер начинает сборку устройства. Сначала нужно подготовить плату управления с дисплеем. Плату обрезает в соответствии с размером передней панели (28 мм х 48 мм). Монтирует три тактильные кнопки. Одна клемма всех переключателей должна быть соединена вместе, и в дальнейшем припаяна к минусу.

После монтажа кнопок следующая задача — установка дисплея. Для размещения платы Wemos D1 была вырезана еще одна монтажная плата. Кабель дисплея и перемычки от плат кнопок должны быть подключены к гнездовым разъемам. Затем нужно подключить еще одну кнопку к плате, которая будет использоваться для измерения и загрузки данных в облако и инфракрасный датчик.

В устройстве будет использоваться литий-ионная аккумуляторная батарея 18650. Аккумулятор будет установлен в ручке устройства. Для защиты и зарядки батареи используется модуль зарядки.

Сам модуль зарядки тоже размещается в ручке.

В верней части ручки устанавливается выключатель. С помощью него устройство будет включатся и выключатся.

Шаг четвертый: загрузка кода
Перед загрузкой кода необходимо подготовить учетную запись Adafruit IO. Более подробно как это сделать можно прочесть здесь. Теперь нужно загрузить код.

 Скетч/* This code works with MLX90614 (GY906) and OLED screen
* It measures both ambient and object temperature in Fahrenheit and display it on the screen
*
*
*
*/
#include
#include
#include
#include
#include
#include
#include
#include "AdafruitIO_WiFi.h"
#include
#include "Arduino.h"

#define IO_USERNAME "Your Adafruit IO Username"
#define IO_KEY "Your Adafruit IO Key"
#define WIFI_SSID "your wifi ssid"
#define WIFI_PASS "your wifi password"
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)

#define MENU D5
#define UP D6
#define DOWN D7
#define MEASURE D4

int menu = 0;
int celcius = 0;
int wifi = 1;
int body_temp = 1;
int patient_id = 1;
int display_on = 1;

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); //Declaring the display name (display)
Adafruit_MLX90614 mlx = Adafruit_MLX90614();
AdafruitIO_WiFi io(IO_USERNAME, IO_KEY, WIFI_SSID, WIFI_PASS);
//AdafruitIO_Feed *temperature = io.feed("temperature");

void setup() {

pinMode(MENU, INPUT_PULLUP);
pinMode(UP, INPUT_PULLUP);
pinMode(DOWN, INPUT_PULLUP);
pinMode(MEASURE, INPUT_PULLUP);

/************************Read Configuration fromEEPROM***************************/
EEPROM.begin(512); //Initialize EEPROM
celcius = EEPROM.read(0);
wifi = EEPROM.read(1);
body_temp = EEPROM.read(2);

mlx.begin();
display.begin(SSD1306_SWITCHCAPVCC, 0x3C); //Start the OLED display

home_page();

Serial.begin(9600);
delay(10000);
// connect to io.adafruit.com
if(wifi)connectAIO();
if(io.status() < AIO_CONNECTED){
display.clearDisplay();
display.setTextColor(WHITE);
display.setTextSize(1);
display.setFont();
display.setCursor(0,20);
display.println("No Internet Access!");
display.display();
delay(3000);
}

// we are connected
Serial.println();
Serial.println(io.statusText());

}

long time_count = millis();
void loop() {

if(!digitalRead(MENU)){
time_count = millis();
delay(200);
menu++;
if(menu>3) {
menu = 0;
EEPROM.write(0, celcius);
EEPROM.write(1, wifi);
EEPROM.write(2, body_temp);
EEPROM.commit();
}
}

if(!digitalRead(UP)){
time_count = millis();
delay(200);
if(menu==0) patient_id++;
if(menu==1) celcius = 1;
if(menu==2) wifi = 1;
if(menu==3) body_temp = 1;
}

if(!digitalRead(DOWN)){
time_count = millis();
delay(200);
if(menu==0) patient_id—;
if(menu==1) celcius = 0;
if(menu==2) wifi = 0;
if(menu==3) body_temp = 0;
}

if(wifi){
if(WiFi.status() != WL_CONNECTED){
WiFi.forceSleepWake();
delay(1);
WiFi.mode(WIFI_STA); //
WiFi.begin(WIFI_SSID, WIFI_PASS); //
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial1.print(".");
}
}
}

if(!wifi){
WiFi.disconnect(); //
WiFi.mode(WIFI_OFF);//
WiFi.forceSleepBegin();
delay(100);
}

if(menu == 0) home_page();
else if(menu == 1) scale_setup_page();
else if(menu == 2) wifi_setup_page();
else if(menu == 3) temp_setup_page();

if(!digitalRead(MEASURE)){
time_count = millis();
display.ssd1306_command(SSD1306_DISPLAYON);
display_on = 1;
Serial.println("Button Press");
delay(5000);
if(wifi){
if(io.status() >= AIO_CONNECTED){temp_write();
display.clearDisplay();
display.setTextColor(WHITE);
display.setTextSize(1);
display.setFont();
display.setCursor(0,20);
display.println("Data Sent!");
display.display();
delay(1500);
}
else{
display.clearDisplay();
display.setTextColor(WHITE);
display.setTextSize(1);
display.setFont();
display.setCursor(0,10);
display.println("No Internet access!");
display.display();
delay(1500);
}
}
//delay(3000);
}

if((millis()>= time_count + 50000) && display_on == 1){
display.ssd1306_command(SSD1306_DISPLAYOFF);
display_on = 0;
}

//display.ssd1306_command(SSD1306_DISPLAYON);
//io.run();
//temperature->save(tempF);
//delay(3000);

}

void home_page(){
float body_tempF = mlx.readObjectTempF()+ 4.5;
float ambient_tempF = mlx.readAmbientTempF();
float body_tempC = (body_tempF-32)/1.8;
float ambient_tempC = (ambient_tempF-32)/1.8;
display.clearDisplay();
display.setTextColor(WHITE);
display.setTextSize(1);
display.setFont();
display.setCursor(0,0);
if(body_temp)
display.println("Body Temperature");
else
display.println("Ambient Temp");
display.setFont(&FreeSerif12pt7b);
display.setCursor(20,40);
if(body_temp && celcius) display.println(body_tempC,2);
else if(body_temp && !celcius) display.println(body_tempF,2);
else if(!body_temp && !celcius) display.println(ambient_tempF,2);
else if(!body_temp && celcius) display.println(ambient_tempC,2);
//display.println(mlx.readObjectTempF()+4.5,2);
display.setCursor(80,40);
display.drawCircle(85, 28, 3, WHITE);
if(celcius) display.println(" C");
else display.println(" F");
display.setFont();
display.setCursor(0,55);
display.print("ID: P0");
display.println(String(patient_id));
display.setCursor(70,55);
if(WiFi.status() == WL_CONNECTED) display.println("WiFi: ON");
else display.println("WiFi: OFF");
display.display();
}

void scale_setup_page(){
display.clearDisplay();
display.setTextColor(WHITE);
display.setFont(&FreeSerif9pt7b);
display.setCursor(0,13);
display.println("Temp Scale");
display.setFont(&FreeSerif12pt7b);
display.drawCircle(65, 25, 3, WHITE);
display.drawRect(35, 25, 15, 15, WHITE);
display.setCursor(70,39);
display.println("C");
display.drawCircle(65, 45, 3, WHITE);
display.drawRect(35, 45, 15, 15, WHITE);
display.setCursor(70,60);
display.println("F");
if(celcius)
display.fillRect(37, 27, 11, 11, INVERSE);
else
display.fillRect(37, 47, 11, 11, INVERSE);
display.display();
}

void wifi_setup_page(){
display.clearDisplay();
display.setTextColor(WHITE);
display.setFont(&FreeSerif9pt7b);
display.setCursor(0,13);
display.println("WiFi Setup");
display.setFont(&FreeSerif12pt7b);
display.drawRect(10, 25, 15, 15, WHITE);
display.setCursor(40,39);
display.println("Enable");
display.drawRect(10, 45, 15, 15, WHITE);
display.setCursor(40,60);
display.println("Disable");
if(wifi)
display.fillRect(12, 27, 11, 11, INVERSE);
else
display.fillRect(12, 47, 11, 11, INVERSE);
display.display();
}

void temp_setup_page(){
display.clearDisplay();
display.setTextColor(WHITE);
display.setFont(&FreeSerif9pt7b);
display.setCursor(0,13);
display.println("Temperature");
display.setFont(&FreeSerif12pt7b);
display.drawRect(10, 25, 15, 15, WHITE);
display.setCursor(40,39);
display.println("Body");
display.drawRect(10, 45, 15, 15, WHITE);
display.setCursor(40,60);
display.println("Ambient");
if(body_temp)
display.fillRect(12, 47, 11, 11, INVERSE);
else
display.fillRect(12, 27, 11, 11, INVERSE);
display.display();
}

void power_saving_mode(){
display.ssd1306_command(SSD1306_DISPLAYOFF);
//wifi_station_disconnect();
wifi_set_opmode(NULL_MODE);
wifi_fpm_set_sleep_type(LIGHT_SLEEP_T);
wifi_fpm_open(); // Enables force sleep
//wifi_fpm_set_wakeup_cb(callback);
gpio_pin_wakeup_enable(GPIO_ID_PIN(MEASURE), GPIO_PIN_INTR_LOLEVEL); // GPIO_ID_PIN(2) corresponds to GPIO2 on ESP8266-01 , GPIO_PIN_INTR_LOLEVEL for a logic low, can also do other interrupts, see gpio.h above
wifi_fpm_do_sleep(0xFFFFFFF); // Sleep for longest possible time
}

void callback() {
display.ssd1306_command(SSD1306_DISPLAYON);
Serial1.println("Callback");
Serial.flush();
}

void temp_write(){
// set up `deepsleep` feed
String str = "P0";
str += patient_id;
int str_len = str.length() + 1;
char char_array[str_len];
str.toCharArray(char_array, str_len);
AdafruitIO_Feed *temperature = io.feed(char_array);
Serial.println("sending temperature to feed");
float body_tempF = mlx.readObjectTempF()+ 4.5;
float ambient_tempF = mlx.readAmbientTempF();
float body_tempC = (body_tempF-32)/1.8;
float ambient_tempC = (ambient_tempF-32)/1.8;

if(body_temp && celcius) temperature->save(body_tempC,2);
else if(body_temp && !celcius) temperature->save(body_tempF,2);
else if(!body_temp && !celcius) temperature->save(ambient_tempF,2);
else if(!body_temp && celcius) temperature->save(ambient_tempC,2);
// send data to deepsleep feed
//temperature->save(temp);
// write data to AIO
io.run();
}

void connectAIO() {
Serial.println("Connecting to Adafruit IO…");
io.connect();
long entering_time = millis();
// wait for a connection
while ((io.status() < AIO_CONNECTED) || (millis()> entering_time + 15000)) {
Serial.print(".");
delay(500);
}

// we are connected
Serial.println();
Serial.println(io.statusText());
}

Ну и последний шаг — окончательная сборка.
Мастер устанавливает дисплей в корпус.

Закрепляет датчик, все платы, переключатели, кнопки. Собирает детали корпуса.

Все готово.

Источник

Похожие статьи

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»
Закрыть
Закрыть