Таймер для мытья рук или чистки зубов на Ардуино

Делаем таймер для мытья рук или чистки зубов на основе платы Arduino, сервопривода и ультразвукового датчика HC-SR04.

Комплектующие

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

Для создания таймера на Ардуино мы будем использовать следующие комплектующие:

  • Arduino Uno
  • Соединительных провода папа-папа x 3
  • Соединительные провода мама-папа x 4
  • Сервопривод SG-90
  • Ультразвуковой датчик HC-SR04

Отдельно мы сделаем стрелку из бумаги, которую приклеим на сервопривод и дополнительно из бумаги вырежем циферблат.

Также должна быть установлена интегрированная среда разработки Arduino IDE.

Схема соединения

Подключаем датчик и сервопривод в соответствии со схемой подключения ниже.

Для ультразвукового датчика HC-SR04 используйте мама/папа для подключения следующих контактов:

  • Датчик HC-SR04 -> Arduino
  • VCC -> 5V на Arduino
  • Trig -> Pin 9 на Arduino
  • Echo -> Pin 10 на Arduino
  • GND -> GND на Arduino

Для серводвигателя используйте провода папа-папа для подключений:

  • Сервопривод -> Arduino
  • Красный (5V) -> Vin на Ардуино
  • Черный  (GND) -> GND на Arduino
  • Оранжевый (Signal) -> Pin 7 на Arduino

Собираем таймер

Как только электронные соединения собраны, можно собрать все вместе, т.е. к нашей схеме мы добавим еще и сам таймер в виде циферблата.

Возьмите лист бумаги или тонкого картона и вырежьте прямоугольное отверстие под сервопривод, как на фото выше. На этой бумаге мы должны нарисовать что-тор вроде циферблата, чтобы наблюдать сколько времени еще осталось.

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

Последний шаг для создания таймера - собрать все вместе и разместить уже в том месте, где вы хотите его применять. Для начала мы используем его в ванной комнате, чтобы отслеживать как тщательно мы моем руки.

Но таймер можно применять и для чистки зубов и для других целей, например, выполнения физических упражнений.

Позиционирование датчика HC-SR04 здесь является ключевым, т.к. нужно найти баланс. Датчик должен быть достаточно далеко от воды, но в то же время он должен без ложных срабатываний фиксировать движение ваших рук.

Ультразвуковой датчик работает, посылая ультразвуковые звуковые волны и измеряя время, необходимое для их возвращения. Если датчик получает отражения от предметов, которые не являются руками в раковине, он может без необходимости активировать таймер.

Внимание. Воды для электронных устройств очень опасна! Размещайте Arduino и другие детали дальше от влаги и воды.

Как только датчик вы разместили там, где нужно, - подключите Arduino к питанию, например, через USB-адаптер.

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

Код и скетч

Когда таймер собран и подключен нам нужно "прошить" Arduino, т.е. загрузить нашу программу на плату.

Инструкции по установке библиотек с использованием Arduino IDE мы написали в этой статье.

Ниже представлены две разные версии программного обеспечения.

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

Второй скетч - это более продвинутая версия, которая включает в себя некоторую обработку сигналов, чтобы заставить ультразвуковой датчик работать более согласованно в разных приемниках. Нам нужно предварительно установить три библиотеки:

Не забудьте, что ваш Arduino всегда будет запускать последний эскиз, который был загружен на плату, даже если он не подключен к вашему компьютеру.

Простой таймер

#include <Servo.h>

const int trigPin = 9;
const int echoPin = 10;

float duration, distance;

//this is the threshold where the sensor will trigger the 
//countdown. If you are getting extra countdowns or the 
//countdown won't start, you may need to adjust this for your sink
int threshold = 200;

void setup() {

  Serial.begin(9600);
  
  //attach pin 7 to servo and sweep it to indicate that the timer is on
  countServo.attach(7);
  countServo.write(180);
  delay(700);
  countServo.write(0);
  delay(700);
  countServo.write(180);
}

void loop() {
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);

  duration = pulseIn(echoPin, HIGH);
  distance = (duration * .0343) / 2;
  Serial.println(distance);

  if (distance < threshold) {
    countdownServo();
  }
  delay(100);
}



//this moves the servo 4.5 degrees every half second
//to smooth out the movemnt (vs 9 degrees every second)
//for 20 seconds.
void countdownServo() {
  Serial.println("Counting down");
  int halfseconds = 40;

  for (int i = halfseconds; i >= 0; i--) {

    countServo.write((int)(i * 4.5));
    delay(500);
  }

  //reset the servo, clear the queue
  countServo.write(180);
  clearQueue();
  delay(700);
}

Продвинутый таймер

#include <NewPing.h> // Provides Accurate, Non-blocking sensor data from the Ultrasonic Sensor
#include <Ewma.h>    // Smoothing library - used to remove jitter from sensor data
#include <cppQueue.h> // Queue Library - used to implment mean subttraction so sensor can work in more sinks. 

#include <Servo.h>

#define TRIGGER_PIN  9  // Arduino pin tied to trigger pin on the ultrasonic sensor.
#define ECHO_PIN     10  // Arduino pin tied to echo pin on the ultrasonic sensor.
#define MAX_DISTANCE 200 // Maximum distance we want to ping for (in centimeters). Maximum sensor distance is rated at 400-500cm.

#define IMPLEMENTATION FIFO //Queue implementation as First in First out
#define OVERWRITE      true //Queue will overwrite oldest value when full

int queue_length = 20;
int num_buffer_frames = 50;

NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE);
Servo countServo;
Queue window(sizeof(float), queue_length, IMPLEMENTATION, OVERWRITE);

Ewma adcFilter1(0.05); //filter used to smooth sensor data

void setup() {

  Serial.begin(115200);

  //attach pin 7 to servo and sweep it to indicate that the timer is on
  countServo.attach(7);
  countServo.write(180);
  delay(700);
  countServo.write(0);
  delay(700);
  countServo.write(180);

  //start with a clear queue. 
  clearQueue();

}

void loop() {
  delay(50); // Wait 50ms between ultrasonic pings (about 20 pings/sec).
  //get filtered data from the sensor
  float filtered1 = adcFilter1.filter(sonar.ping_cm()); 
  
  //subtract the mean so sensor data is centered around zero.
  //This allows the sensor to adjust to different environments and look
  //for change rather than a preset threshold. 
  float filtered_mean_removed_value = filtered1 - meanZero(filtered1); 
                                                                       

  Serial.println(filtered_mean_removed_value);

  //If the sensor reads something significantly different from what 
  //it's normally seeing (the empty sink): We start the countdown! 🎉
  
  if (filtered_mean_removed_value > 15 || filtered_mean_removed_value < -15) {
        countdownServo();
  }
}


//helper function to calculate a moving mean. 
int meanZero(float smoothedVal) {
  
  //push the most recent reading into the queue
  window.push(&smoothedVal); 
  
  int retval = 0;

  //iterate through the queue and add values to return val
  for (int i = 0; i < queue_length; i++) {
    float for_mean;
    window.peekIdx(&for_mean, i);
    retval = retval + (int)for_mean;
  }

  //calculate the mean and return. 
  int mean = retval / queue_length;
  
  return mean;
}

void clearQueue() {
  for (int i = 0; i < queue_length; i++) {
    float queue_zeroer = 0;
    window.push(&queue_zeroer);
  }
}

//this moves the servo 4.5 degrees every half second
//to smooth out the movemnt (vs 9 degrees every second)
//for 20 seconds. 
void countdownServo() {
  Serial.println("Counting down");
  int halfseconds = 40;

  for (int i = halfseconds; i >= 0; i--) {

    countServo.write((int)(i * 4.5));
    delay(500);
  }
  
    //reset the servo, clear the queue
    countServo.write(180);
    clearQueue();
    delay(700);
}

Возможные проблемы

Если вы обнаружите, что таймер постоянно включается не только при приближении рук, подумайте о том, чтобы переместить ультразвуковой датчик так, чтобы он был направлен прямо в область, в которой находятся ваши руки.

Обязательно подумайте об уменьшении чувствительности при увеличении «пороговой» переменной в скетче Arduino.

Если руки в раковине не активируют таймер, попробуйте увеличить чувствительность, уменьшив пороговую переменную в эскизе Arduino.

Если поведение нестабильно, попробуйте переподключить провода и убедитесь, что соединения с ультразвуковым датчиком надежны. Мы заметили, что они могут очень легко ослабнуть и, возможно, их можно зафиксировать изолентой.

Тестировать таймер полезно до установки устройства по месту назначения.

Итоговый результат

Попробуйте помыть руки и посмотрите, начнется ли обратный отсчет. Если это не так, или если он запускается самостоятельно, ознакомьтесь с советами по устранению неполадок выше.

На этом всё. Чаще мойте руки и не болейте.

Источник: Hackster.io
27 марта 2020 в 19:06
Опубликовано:
Уроки, ,

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

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