Índice:
- Suprimentos
- Etapa 1: Fiação
- Etapa 2: Torne sua célula de carga utilizável
- Etapa 3: banco de dados normalizado
- Etapa 4: codificando a célula de carga
- Etapa 5: Codificando o Sensor de Água
- Etapa 6: Codificando o Sensor de Proximidade
- Etapa 7: Codificando os motores de passo
- Etapa 8: Codificando o LCD
- Etapa 9: Fim
2025 Autor: John Day | [email protected]. Última modificação: 2025-01-13 06:58
Já sentiu vontade de perder muito tempo alimentando seu animal de estimação? Você já teve que ligar para alguém para alimentar seus animais de estimação enquanto estava de férias? Tentei consertar esses dois problemas com meu projeto escolar atual: Petfeed!
Suprimentos
Raspberry Pi 3b
Célula de carga de barra (10kg)
Amplificador de célula de carga HX711
Sensor de nível de água (https://www.dfrobot.com/product-1493.html)
Sensor de proximidade ultrassônico
LCD de 16 pinos
2x motor de passo 28byj-48
2x driver de motor de passo ULN2003
Etapa 1: Fiação
muitos cabos aqui. Pegue seus cabos de jumper e comece a fixar!
Etapa 2: Torne sua célula de carga utilizável
para usar a célula de carga, primeiro precisamos prendê-la a dois pratos: um prato de fundo e um prato no qual pesaremos nossos alimentos.
Os parafusos de que você precisa são um par de parafusos M4 com parafusos correspondentes e um par de parafusos M5 com parafusos correspondentes. Usei uma pequena broca para fazer os furos.
(foto:
Etapa 3: banco de dados normalizado
os dados de nossos sensores devem ser salvos em um banco de dados. Para os arquivos Python para conectar ao banco de dados: veja abaixo.
então você também precisa de um arquivo de configuração:
[connector_python] user = * seunomedeusuario * host = 127.0.0.1 #if porta local = 3306 senha = * suasenha * banco de dados = * yourdb * [application_config] driver = 'SQL Server'
Etapa 4: codificando a célula de carga
import RPi. GPIO as GPIOimport threading import time from hx711 import HX711 from helpers.stepperFood import StepperFood from helpers. LCDWrite import LCDWrite from repositories. DataRepository import DataRepository
Depois de importar todas as nossas bibliotecas (note, estamos usando a Biblioteca HX711 para conduzir a célula de carga), podemos começar a escrever nosso código real
TARRA_CONSTANT = 80600
GRAM_CONSTANT = 101
Para descobrir nossas constantes, primeiro defina TARRA_CONSTANT = 0 e GRAM_CONSTANT = 1.
Em seguida, precisamos descobrir o valor que nossa célula de carga lê quando não há nada sendo pesado. Este valor será TARRA_CONSTANT.
Já para GRAM_CONSTANT, basta pegar um objeto cujo peso você conheça (usei um pacote de espaguete), pesar e dividir a leitura da célula de carga com o peso real do objeto. Para mim, isso foi 101.
classe LoadCell (threading. Thread):
def _init _ (self, socket, lcd): threading. Thread._ init _ (self) self.hx711 = HX711 (dout_pin = 5, pd_sck_pin = 6, canal = 'A', ganho = 64) self.socket = socket self.lcd = lcd
aqui, inicializamos a classe LoadCell e mapeamos os pinos.
def run (self):
try: while True: self.hx711.reset () # Antes de começar, redefina o HX711 (não é obrigatório) mede_avg = soma (self.hx711.get_raw_data ()) / 5 peso = redondo ((mede_avg - TARRA_CONSTANT) / GRAM_CONSTANT, 0) print ("weight: {0}". Format (weight)) DataRepository.insert_weight (weight) data_weight = DataRepository.get_data_sensor (3) historyId = data_weight ["SensorsHistory"] db_weight = data_weight ["value"] actionTime = data_weight ["actionTime"] self.socket.emit ('data_weight', {"id": historyId, "Weight": db_weight, "Time": DataRepository.serializeDateTime (actionTime)}) print ("zou moeten emitten") writeWeight = "weight:" + str (db_weight) msg = "PETFEED" LCDWrite.message () if int (db_weight [: - 2]) <= 100: StepperFood.run () time.sleep (20) exceto Exceção como e: print ("Erro com pesagem" + str (e))
Etapa 5: Codificando o Sensor de Água
import timeimport threading from repositories. DataRepository import DataRepository from RPi import GPIOGPIO.setmode (GPIO. BCM) GPIO.setwarnings (False) GPIO_Water = 18 GPIO.setup (GPIO_Water, GPIO. IN) classe WaterSensor (threading. Thread): def self, socket): threading. Thread._ init _ (self) self.socket = socket self.vorige_status = 0 def run (self): try: while True: water = self.is_water () print (water) status = water [" status "] action = water [" action "] DataRepository.insert_water (str (status), action) data_water = DataRepository.get_data_sensor (2) historyId = data_water [" SensorsHistory "] value = data_water [" value "] if value == "0": value = "te weinig water" else: value = "genoeg water" actionTime = data_water ["actionTime"] self.socket.emit ('data_water', {"id": historyId, "value": value, "Time": DataRepository.serializeDateTime (actionTime), "action": action}) time.sleep (5) exceto Exceção como ex: print (ex) print ('error bij watersensor') def is_water (self): status = GPIO.input (GPIO_Wate r) if self.vorige_status == 0 e status == 1: print ('water gedetecteerd') sensorData = {"status": status, "action": "water gedetecteerd"} self.vorige_status = status status = GPIO.input (GPIO_Water) if self.vorige_status == 1 e status == 1: print ('water aanwezig') sensorData = {"status": status, "action": "water aanwezig"} status = GPIO.input (GPIO_Water) se self.vorige_status == 1 e status == 0: print ('water weg') sensorData = {"status": status, "action": "water weg"} self.vorige_status = status status = GPIO.input (GPIO_Water) if self.vorige_status == 0 e status == 0: print ('startpositie') status = GPIO.input (GPIO_Water) sensorData = {"status": status, "action": "startpositie"} return sensorData
Etapa 6: Codificando o Sensor de Proximidade
import timeimport threading from repositories. DataRepository import DataRepository from RPi import GPIO GPIO.setmode (GPIO. BCM) GPIO.setwarnings (False) GPIO_Trig = 4 GPIO_Echo = 17 GPIO.setup (GPIO_Trig, GPIO. OUT) GPIO.setup (GPIO_Echo, GPIO). IN) def current_milli_time (): return int (round (time.time () * 1000)) class UltrasonicSensor (threading. Thread): def _init _ (self, socket): threading. Thread._ init _ (self) self.socket = socket def run (self): try: last_reading = 0 interval = 5000 while True: if current_milli_time ()> last_reading + intervalo: dist = self.distance () print ("Distância medida =%.1f cm"% dist) DataRepository. insert_proximity (dist) data_prox = DataRepository.get_data_sensor (1) historyId = data_prox ["SensorsHistory"] prox = data_prox ["value"] actionTime = data_prox ["actionTime"] self.socket.emit ('data_proximity', {"id": historyId, "Proximity": prox, "Time": DataRepository.serializeDateTime (actionTime)}) last_reading = current_milli_time () exceto Exceção como ex: print (ex) de f distance (self): # set Trigger to HIGH GPIO.output (GPIO_Trig, True) # set Trigger after 0.01ms to LOW time.sleep (0.00001) GPIO.output (GPIO_Trig, False) StartTime = time.time () StopTime = time.time () # salvar StartTime while GPIO.input (GPIO_Echo) == 0: StartTime = time.time () # salvar hora de chegada enquanto GPIO.input (GPIO_Echo) == 1: StopTime = time.time () # diferença de tempo entre o início e a chegada TimeElapsed = StopTime - StartTime # multiplique pela velocidade sônica (34300 cm / s) # e divida por 2, porque distância de ida e volta = (TimeElapsed * 34300) / 2 distância de retorno
Etapa 7: Codificando os motores de passo
import RPi. GPIO as GPIOimport time import threading GPIO.setmode (GPIO. BCM) GPIO.setwarnings (False) control_pins = [12, 16, 20, 21] para pino em control_pins: GPIO.setup (pin, GPIO. OUT) GPIO.output (pin, 0) halfstep_seq =
Este código é reutilizável para o outro motor de passo, basta definir os números dos pinos de controle para seus respectivos pinos e renomear a classe para StepperWater:
Etapa 8: Codificando o LCD
Muito código, mas estamos quase terminando.
A classe LCD está incluída como arquivo LCD.py
de helpers. LCD import LCD
E = 26 RS = 25 D0 = 19 D1 = 13 D2 = 24 D3 = 22 D4 = 23 D5 = 8 D6 = 7 D7 = 10 lcd = LCD (E, RS, [D0, D1, D2, D3, D4, D5, D6, D7]) classe LCDWrite: def mensagem (msg): try: print ("try") lcd.init_LCD () lcd.send_instruction (12) lcd.clear_display () lcd.write_message (msg, '1') exceto: imprimir ("erro LCDWrite")
Etapa 9: Fim
resultado final: como o desenhamos vs. como ficou.