Tutoriales

Cómo hacer un comedero automático para perros con Arduino y Linux

Mi hija y yo recientemente hicimos juntos un pequeño proyecto de automatización. Ella quería hacer un dispensador de comida para nuestro perro, Domino, y pensé que era la excusa perfecta para escribir un código para interactuar con el hardware real.

[ Want to DIY? Download the Getting started with Raspberry Pi cheat sheet. ]

Nosotros elegimos hardware arduino, porque es de código abierto, tiene una gran comunidad de soporte y es fácil de usar tanto en hardware como en software. También es una introducción muy económica a la electrónica de bricolaje.Debido a su pequeño tamaño y bajo precio, utilizamos arduino nano para este artículo.

(José Vicente Núñez, CC BY-SA 4.0)

El proyecto no es todo trabajo original. Encontré mucha inspiración (e instrucciones) en línea, y tú también deberías hacerlo. No desarrollé la idea ni codifiqué yo mismo. ROBO HUB escribió un Tutorial detallado Tomé notas sobre cómo hacer un dispensador de comida para mascotas con materiales básicos.también hizo un videovi muchas veces (muchas de sus Youtube canal).

[ Looking for a project? Check out 10 DIY IoT projects to try using open source tools. ]

¿Cómo funcionan los dispensadores de comida?

En pocas palabras, el dispensador de alimentos funciona de la siguiente manera:

  1. La comida se coloca dentro de un recinto de cartón. En la parte inferior, cuando se detecta un obstáculo delante del dispensador de alimentos, la tapa se abre para dejar caer los alimentos.
  2. La tapa solo se abrirá si el obstáculo está a menos de 35 cm del dispensador de alimentos. Espere cinco segundos después de encenderlo y luego apáguelo de nuevo.
  3. El servo gira 90 grados, lo suficiente para abrir completamente la tapa, y luego vuelve a la posición de cero grados.

lista de materiales

Todos los enlaces son a Amazon ya que es fácil ver los productos antes de comprarlos. No cobro comisión y te animo a que busques el mejor precio.

Producto electrónico

[ Want to test your sysadmin skills? Take a skills assessment today. ]

valla de comida para perros

  • pistola de pegamento: Cualquier pistola de pegamento servirá, no se necesitan cosas sofisticadas.
  • Tijeras
  • navaja plegable: Lo uso para cortar pequeños agujeros que las tijeras no pueden usar.
  • un dibujo animado: No subestimes tu altura. Busque algo que no tenga menos de 12 pulgadas de alto. Usé una caja cuadrada, pero puedes usar un cilindro como en el tutorial original (la caja cuadrada me facilitó colocar los componentes adentro). Lo mismo ocurre con el ancho. Necesitará espacio para la electrónica y la comida.

software

  • Sudo El privilegio de instalar paquetes como Minicom (para leer datos de un puerto serie) y Fritz (para hacer unos bonitos dibujos para proyectos).
  • IDE 2 de Arduino: Descargue este código para escribir código para controlar la electrónica.
  • pitón 3 Ejecute algunos scripts para publicar datos de sensores ultrasónicos como métricas de Prometheus usando su computadora.

antes de que empieces

Estos son los consejos más importantes que puedo ofrecer para todo este tutorial:

Lo perfecto es el enemigo de lo bueno.

o como cita Voltaire proverbio italiano:

Dans ses écrits, un sage Italien
Dit que le mieux est l’ennemi du bien.

El objetivo de este ejercicio es aprender y cometer errores (intenta no repetirlos), No busca la ratonera perfecta (o el dispensador de comida), sino uno que funcione bien y que pueda mejorar con muchas iteraciones.

mira este El video de todo el proceso está aquí. Luego regresa y sigue este tutorial.

componentes de conexión

Comenzaré mostrando cómo conectar los componentes electrónicos. El esquema se muestra a continuación:

(José Vicente Núñez, CC BY-SA 4.0)

Cuando ensamblas un proyecto en Arduino, conectas componentes a digital o analógico alfiler, numerado. Hicimos lo siguiente para este proyecto:

  1. El disparador ultrasónico HC-SR04 está conectado al pin D2 en el Arduino Nano.El extremo disparador del sensor envía un pulso que rebota en los obstáculos (para una explicación más detallada, mire este video).
  2. El eco ultrasónico HC-SR04 está conectado al pin D3 en el Arduino Nano. El dispositivo recibe pulsos de rebote para obtener la distancia entre el dispensador de alimentos y el obstáculo. Mide el tiempo que tarda el pulso en viajar y utiliza la velocidad del sonido para calcular la distancia.
  3. El servo SG90 está conectado al pin D9 en el Arduino Nano. Si se detecta un obstáculo y la distancia es inferior a 35 cm (o la distancia que elijas en el código), el peón se mueve en un ángulo de 90 grados.

Los cables de tierra y 5V restantes también están conectados al Arduino Nano.Como tiene muchas conexiones, usé un Protoboard sin soldadura:

(José Vicente Núñez, CC BY-SA 4.0)

Aquí hay una foto de todos los componentes conectados a la protoboard:

(José Vicente Núñez, CC BY-SA 4.0)

Quizás se pregunte cómo hice estos gráficos.aplicación de código abierto Fritz Una excelente manera de dibujar esquemas eléctricos y diagramas de cableado, está disponible como RPM para Fedora:

$ sudo dnf install -y fritzing.x86_64 fritzing-parts.noarch

En Red Hat Enterprise Linux (RHEL) y CentOS, puede instalarlo como paquete plano:

$ flatpak install org.fritzing.Fritzing

He incluido el archivo fuente del gráfico (schematics/food_dispenser.fzz) en mi repositorio GitPara que puedas abrirlo y modificar el contenido.

[ Cheat sheet: Old Linux commands and their modern replacements ]

Código para el controlador Arduino

Si aún no ha descargado e instalado el IDE de Arduino 2, hágalo ahora.Solo sigue estas instrucciones Antes de continuar.

Puedes escribir código para Arduino usando su lenguaje de programación. Se parece mucho a C y tiene dos funciones muy simples pero importantes:

  • Configuración: inicializa el componente y establece qué puertos pueden leer y escribir datos. Se llama una sola vez.
  • Bucle: lee datos y escribe datos en el sensor.

Descubrí que el código original necesitaba alguna actualización para cubrir mi caso de uso, pero es mejor verlo y ejecutarlo para ver cómo funciona:

$ curl --fail --location --remote-name '

Sí, debe copiarlo y pegarlo en el IDE.

Reescribí el código original, manteniendo la mayor parte de la funcionalidad igual, y agregué una depuración adicional para ver si el sensor ultrasónico podía medir la distancia cuando encontraba un obstáculo:

/*
Sketch to control the motor that open/ closes the cap that lets the food drop on the dispenser.
References: 
* 
* 

Modules:
- HC-SR04: Ultrasonic sensor distance module
- SG90 9g Micro Servos: Opens / closes lid on the food dispenser
*/
#include 
Servo servo;

unsigned int const DEBUG = 1;

/*
Pin choice is arbitrary.
 */ 
const unsigned int HC_SR04_TRIGGER_PIN = 2; // Send the ultrasound ping
const unsigned int HC_SR04_ECHO_PIN = 3; // Receive the ultrasound response
const unsigned int SG90_SERVO_PIN = 9;  // Activate the servo to open/ close lid

const unsigned int MEASUREMENTS = 3;
const unsigned int DELAY_BETWEEN_MEASUREMENTS_MILIS = 50;

const unsigned long ONE_MILISECOND = 1;
const unsigned long ONE_SECOND = 1000;
const unsigned long FIVE_SECONDS = 3000;

const unsigned long MIN_DISTANCE_IN_CM = 35; // Between 2cm - 500cm

const unsigned int OPEN_CAP_ROTATION_IN_DEGRESS = 90; // Between 0 - 180
const unsigned int CLOSE_CAP_ROTATION_IN_DEGRESS = 0;

const unsigned int CLOSE = 0;

/*
Speed of Sound: 340m/s = 29microseconds/cm
Sound wave reflects from the obstacle, so to calculate the distance we consider half of the distance traveled.  
DistanceInCms=microseconds/29/2 
*/
long microsecondsToCentimeters(long microseconds) {
  return microseconds / 29 / 2;
}

unsigned long measure() {
  /*
  Send the ultrasound ping
  */
  digitalWrite(HC_SR04_TRIGGER_PIN, LOW);
  delayMicroseconds(5);
  digitalWrite(HC_SR04_TRIGGER_PIN, HIGH);
  delayMicroseconds(15);
  digitalWrite(HC_SR04_TRIGGER_PIN, LOW);

  /*
  Receive the ultrasound ping and convert to distance
  */
  unsigned long pulse_duration_ms = pulseIn(HC_SR04_ECHO_PIN, HIGH);
  return microsecondsToCentimeters(pulse_duration_ms);
}


/*
- Close cap on power on startup
- Set servo, and read/ write pins
 */
void setup() {
  pinMode(HC_SR04_TRIGGER_PIN, OUTPUT);
  pinMode(HC_SR04_ECHO_PIN, INPUT);
  servo.attach(SG90_SERVO_PIN);
  servo.write(CLOSE_CAP_ROTATION_IN_DEGRESS);
  delay(ONE_SECOND);
  servo.detach();
  if (DEBUG) {
    Serial.begin(9600);
  }
}

void loop() {
  float dist = 0;
  for (int i = 0; i < MEASUREMENTS; i++) {  // Average distance
    dist += measure();
    delay(DELAY_BETWEEN_MEASUREMENTS_MILIS);  //delay between measurements
  }
  float avg_dist_cm = dist / MEASUREMENTS;

  /*
  If average distance is less than threshold then keep the door open for 5 seconds 
  to let enough food out, then close it.
  */
  if (avg_dist_cm < MIN_DISTANCE_IN_CM) {
    servo.attach(SG90_SERVO_PIN);
    delay(ONE_MILISECOND);
    servo.write(OPEN_CAP_ROTATION_IN_DEGRESS);
    delay(FIVE_SECONDS);
    servo.write(CLOSE_CAP_ROTATION_IN_DEGRESS);
    delay(ONE_SECOND);
    servo.detach();
  }

  if (DEBUG) {
    Serial.print(avg_dist_cm);
    Serial.print("cm");
    Serial.println();
  }

}

Compilar e implementar desde la interfaz gráfica de usuario (GUI) de Arduino es simple. Después de seleccionar la placa y el puerto de los menús desplegables, simplemente haga clic en el icono de la flecha:

(José Vicente Núñez, CC BY-SA 4.0)

Después de cargar el código, se muestra de la siguiente manera:

Sketch uses 3506 bytes (11%) of program storage space. Maximum is 30720 bytes.
Global variables use 50 bytes (2%) of dynamic memory, leaving 1998 bytes for local variables. Maximum is 2048 bytes.

pregunta inicial

No todo es perfecto (juego de palabras) con este proyecto favorito. Una vez que el prototipo estuvo en funcionamiento, nos encontramos con algunos problemas.

corta duración de la batería

La duración de la batería se reduce drásticamente después de unas horas. El bucle en el código envía constantemente un "ping" ultrasónico y verifica la distancia.Después de mirar alrededor, encontré un biblioteca compatible Usando un controlador ATMega328P (para Arduino One).

He habilitado el código de depuración para monitorear el puerto serie y, a menudo, veo mensajes como este:

14:13:59.094 -> 281.00cm
14:13:59.288 -> 281.67cm
14:13:59.513 -> 280.67cm
14:13:59.706 -> 281.67cm
14:13:59.933 -> 281.33cm
14:14:00.126 -> 281.00cm
14:14:00.321 -> 300.33cm
...
14:20:00.321 -> 16.00cm
...

Ya está aquí una nueva versión con un poco de apagado para ahorrar energía:

/*
Sketch to control the motor that open/ closes the cap that lets the food drop on the dispenser.
References: 
* 
* 

Modules:
- HC-SR04: Ultrasonic sensor distance module
- SG90 9g Micro Servos: Opens / closes lid on the food dispenser
*/
#include "LowPower.h"
#include 
Servo servo;

unsigned int const DEBUG = 1;

/*
Pin choice is arbitrary.
 */ 
const unsigned int HC_SR04_TRIGGER_PIN = 2; // Send the ultrasound ping
const unsigned int HC_SR04_ECHO_PIN = 3; // Receive the ultrasound response
const unsigned int SG90_SERVO_PIN = 9;  // Activate the servo to open/ close lid

const unsigned int MEASUREMENTS = 3;
const unsigned int DELAY_BETWEEN_MEASUREMENTS_MILIS = 50;

const unsigned long ONE_MILISECOND = 1;
const unsigned long ONE_SECOND = 1000;
const unsigned long FIVE_SECONDS = 3000;

const unsigned long MIN_DISTANCE_IN_CM = 35; // Between 2cm - 500cm

const unsigned int OPEN_CAP_ROTATION_IN_DEGRESS = 90; // Between 0 - 180
const unsigned int CLOSE_CAP_ROTATION_IN_DEGRESS = 0;

const unsigned int CLOSE = 0;

/*
Speed of Sound: 340m/s = 29microseconds/cm
Sound wave reflects from the obstacle, so to calculate the distance we consider half of the distance traveled.  
DistanceInCms=microseconds/29/2 
*/
long microsecondsToCentimeters(long microseconds) {
  return microseconds / 29 / 2;
}

unsigned long measure() {
  /*
  Send the ultrasound ping
  */
  digitalWrite(HC_SR04_TRIGGER_PIN, LOW);
  delayMicroseconds(5);
  digitalWrite(HC_SR04_TRIGGER_PIN, HIGH);
  delayMicroseconds(15);
  digitalWrite(HC_SR04_TRIGGER_PIN, LOW);

  /*
  Receive the ultrasound ping and convert to distance
  */
  unsigned long pulse_duration_ms = pulseIn(HC_SR04_ECHO_PIN, HIGH);
  return microsecondsToCentimeters(pulse_duration_ms);
}


/*
- Close cap on power on startup
- Set servo, and read/ write pins
 */
void setup() {
  pinMode(HC_SR04_TRIGGER_PIN, OUTPUT);
  pinMode(HC_SR04_ECHO_PIN, INPUT);
  servo.attach(SG90_SERVO_PIN);
  servo.write(CLOSE_CAP_ROTATION_IN_DEGRESS);
  delay(ONE_SECOND);
  servo.detach();
    if (DEBUG) {
    Serial.begin(9600);
  }
}

void loop() {

  float dist = 0;
  for (int i = 0; i < MEASUREMENTS; i++) {  // Average distance
    dist += measure();
    delay(DELAY_BETWEEN_MEASUREMENTS_MILIS);  //delay between measurements
  }
  float avg_dist_cm = dist / MEASUREMENTS;

  /*
  If average distance is less than threshold then keep the door open for 5 seconds 
  to let enough food out, then close it.
  */
  if (avg_dist_cm < MIN_DISTANCE_IN_CM) {
    servo.attach(SG90_SERVO_PIN);
    delay(ONE_MILISECOND);
    servo.write(OPEN_CAP_ROTATION_IN_DEGRESS);
    delay(FIVE_SECONDS);
    servo.write(CLOSE_CAP_ROTATION_IN_DEGRESS);
    delay(ONE_SECOND);
    servo.detach();
    // Pet is eating and in front of the dispenser, we can definitely sleep longer
    LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);
  } else {
    LowPower.powerDown(SLEEP_1S, ADC_OFF, BOD_OFF);
  }

  if (DEBUG) {
    Serial.print(avg_dist_cm);
    Serial.print(" cm");
    Serial.println();
  }
}

La batería duró unas tres horas después de cambiarla, pero quería exprimir más energía. Hay muchas guías para Arduino mas sugerenciasy, por supuesto, más sobre tema de ahorro de energíapero es un buen comienzo.

El LED de encendido permanece encendido

El módulo de alimentación de placa de pruebas sin soldadura MB102 de 3,3 V/5 V mantiene el LED encendido todo el tiempo. No hay forma de desactivar el LED de alimentación de la placa de pruebas. Esto también ayuda a matar la batería. Necesito investigar más aquí.

suministro limitado de alimentos

Los tanques de almacenamiento de alimentos son muy limitados, pero los recintos para dispositivos electrónicos funcionan bien. Dado que los dispositivos electrónicos ocupan la mayor parte del espacio, se requiere un contenedor más grande. Mide 5,5 x 2,5 pulgadas de ancho y 18 pulgadas de alto (la altura es lo suficientemente buena).

Planeo construir una cerca más ancha pero no más alta. Desperdicié espacio en la parte inferior del dispensador, por lo que podría ser un buen lugar para colocar dispositivos electrónicos. No es una mala decisión usar una placa pequeña.

[ Get the guide to installing applications on Linux. ]

¿Qué va bien?

Las cosas fueron bien desde el principio y muchas de nuestras decisiones resultaron sólidas.

  • La única parte que necesitaba pegar era conectar los servos al cartón. Todas las piezas, incluida la cubierta, se pueden desmontar fácilmente (incluida la batería), por lo que aún puedo modificar el código sin tener que volver a montarlo. Me gusta el diseño.
  • La comida no se atascará dentro del recipiente. La gravedad funciona y nada se desperdicia una vez que se agota toda la comida.
  • El uso de un rectángulo en lugar de un cilindro para la caja facilita el ajuste de la pieza. Si tiene una caja pequeña y larga que puede reciclar, ya está todo listo.

Obtener información de Arduino

Ajustamos el divisor capturando la salida del puerto serie de Arduino. Si desea capturar datos para su posterior análisis, puede hacer lo siguiente:

  • Configure una alarma si la batería externa se está agotando o controle la carga restante si es posible.
  • Obtenga la distancia cuando se activa el sensor ultrasónico. Puede usar esto para calibrar mejor su dispensador de alimentos, por ejemplo, para determinar si los platos están demasiado juntos o demasiado separados.
  • Configure una alerta si el dispensador está a punto de quedarse sin comida antes de que su mascota envíe una solicitud incorrecta.

La interfaz de usuario de Arduino tiene una buena manera de mostrar la actividad en el puerto serie USB (y también le permite enviar comandos al Arduino):

(José Vicente Núñez, CC BY-SA 4.0)

A continuación, mostraré cómo llegar desde /dev/ttyUSB0 (nombre del dispositivo en mi instalación de Fedora Linux).

Capture datos en serie con Minicom

La forma más fácil es usar Minicom.Puede abrir el puerto serie con minipase.

Para instalarlo en Fedora, CentOS, RHEL y similares:

$ sudo dnf install minicom

Ejecute el siguiente comando para capturar datos, pero asegúrese de que no está capturando desde Arduino IDE 2; de lo contrario, el dispositivo se bloqueará:

$ minicom --capturefile=$HOME/Downloads/ultrasonic_sensor_cap.txt --baudrate 9600 --device /dev/ttyUSB0

ver en acción:

Pero esa no es la única manera de capturar datos. ¿Qué pasa con el uso de Python?

[ Get started with IT automation with the Ansible Automation Platform beginner's guide. ]

Obtenga datos del puerto serie con Python

También puede capturar datos en serie utilizando un script de Python:

#!/usr/bin/env python
"""
Script to dump the contents of a serial port (ideally your Arduino USB port)
Author: Jose Vicente Nunez ([email protected])
"""
import serial

BAUD = 9600
TIMEOUT = 2
PORT = "/dev/ttyUSB0"

if __name__ == "__main__":
    serial_port = serial.Serial(port=PORT, baudrate=BAUD, bytesize=8, timeout=TIMEOUT, stopbits=serial.STOPBITS_ONE)
    try:
        while True:
            # Wait until there is data waiting in the serial buffer
            if serial_port.in_waiting > 0:
                serialString = serial_port.readline()
                # Print the contents of the serial data
                print(serialString.decode('utf-8').strip())
    except KeyboardInterrupt:
        pass

Pero un script de Python no tiene que ser una mala copia de Minicom.¿Qué pasa si usa datos de exportación? SDK de cliente de Prometheus?

acá hay uno demostración:

A continuación, puede supervisar la nueva fuente de datos desde la interfaz de usuario de Prometheus scraper. Primero, dile a Prometheus dónde está el proxy. A continuación se muestran algunas configuraciones de trabajo de raspado. el último(yafd) es el nuevo script de Python:

--
global:
    scrape_interval: 30s
    evaluation_interval: 30s
    scrape_timeout: 10s
    external_labels:
        monitor: 'nunez-family-monitor'

scrape_configs:
    - job_name: 'node-exporter'
      static_configs:
          - targets: ['raspberrypi.home:9100', 'dmaf5:9100']
    - job_name: 'docker-exporter'
      static_configs:
          - targets: ['raspberrypi.home:9323', 'dmaf5:9323']
    - job_name: 'yafd-exporter'
      static_configs:
          - targets: ['dmaf5:8000']
      tls_config:
          insecure_skip_verify: true

Luego, puede verlo en el tablero de Prometheus:

(José Vicente Núñez, CC BY-SA 4.0)

Luego, puede agregar esto a Grafana e incluso agregar alertas para notificarle cuando su perro recibe comida (bueno, tal vez eso sea demasiado).

¿Que sigue?

Este proyecto es muy emocionante. No hay nada como mezclar el desarrollo de hardware y software.

Aquí hay algunos pensamientos que quiero compartir con ustedes:

  • si tienes hijos, involucrarlos: La mejor parte es lograr que mi hija se interese en la electrónica y el software. Ella se lo pasó genial conmigo. Nuestra sesión de diseño fue probablemente la parte más productiva del proyecto.
  • Es posible que desee comprar un kit de aprendizaje económico con un controlador Arduino.Mi documentación está bien y tiene Puedes aprender muchos tutoriales en línea.Debido a que el hardware es de código abierto, hay muchos fabricantes.
  • Mientras pensaba en reducir el consumo de energía en mi placa Arduino, me topé con Uso de energía solar en una placa de circuitoLe recomiendo encarecidamente que lea este artículo. Podría tener un impacto en su próximo proyecto.
  • ¿Busca módulos para su placa de desarrollo?Este Comunidad de código abierto de la biblioteca Arduino Probablemente ya.
  • Hay toneladas de mejoras de hardware que podría hacer en este dispensador de alimentos, como una mayor capacidad de alimentos, la capacidad de cargar datos de instrumentación para el monitoreo remoto y rastrear la cantidad de comida que queda en el contenedor. ¡Tantas posibilidades!

LEER  Cómo iniciar, apagar y suspender su sistema desde la línea de comandos de Linux

Publicaciones relacionadas

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Botón volver arriba