Mục lục:
Video: MÁY ĐOÁN THỨC ĂN VẬT NUÔI TỰ ĐỘNG: 9 bước
2025 Tác giả: John Day | [email protected]. Sửa đổi lần cuối: 2025-01-13 06:58
Bạn đã bao giờ cảm thấy lãng phí quá nhiều thời gian cho thú cưng của mình ăn chưa? Bạn đã bao giờ phải gọi ai đó để cho thú cưng của bạn ăn khi bạn đang đi nghỉ? Tôi đã cố gắng khắc phục cả hai vấn đề này với dự án trường học hiện tại của mình: Petfeed!
Quân nhu
Raspberry Pi 3b
Cảm biến lực thanh (10kg)
Bộ khuếch đại cảm biến tải HX711
Cảm biến Waterlevel (https://www.dfrobot.com/product-1493.html)
Cảm biến tiệm cận siêu âm
LCD 16 chân
Động cơ bước 2x 28byj-48
Trình điều khiển động cơ bước 2x ULN2003
Bước 1: Đấu dây
rất nhiều cáp ở đây. Lấy cáp jumper của bạn ra và bắt đầu ghim!
Bước 2: Làm cho tế bào tải của bạn có thể sử dụng được
Để sử dụng cảm biến lực, trước tiên chúng ta cần gắn nó vào hai đĩa: một đĩa dưới cùng và một đĩa để cân thực phẩm của mình.
Các vít bạn cần là một cặp vít M4 với bu lông phù hợp và một cặp vít M5 với bu lông phù hợp. Tôi sử dụng một mũi khoan nhỏ để tạo các lỗ.
(ảnh:
Bước 3: Cơ sở dữ liệu chuẩn hóa
dữ liệu từ các cảm biến của chúng tôi phải được lưu trong cơ sở dữ liệu. Để các tệp python kết nối với cơ sở dữ liệu: xem bên dưới.
thì bạn cũng cần một tệp cấu hình:
[connector_python] user = * yourusername * host = 127.0.0.1 #if local port = 3306 password = * yourpassword * database = * yourdb * [application_config] driver = 'SQL Server'
Bước 4: Mã hóa Load Cell
nhập RPi. GPIO dưới dạng GPIO Nhập thời gian nhập luồng từ hx711 nhập HX711 từ helpers.stepper Nhập thực phẩm StepperFood từ người trợ giúp. LCDWrite nhập LCDWrite từ kho lưu trữ. DataRepository nhập DataRepository
Sau khi nhập tất cả các thư viện của chúng tôi (lưu ý, chúng tôi đang sử dụng Thư viện HX711 để điều khiển cảm biến lực), chúng tôi có thể bắt đầu viết mã thực của mình
TARRA_CONSTANT = 80600
GRAM_CONSTANT = 101
Để tìm ra các hằng số của chúng tôi, trước tiên hãy đặt TARRA_CONSTANT = 0 và GRAM_CONSTANT = 1.
Tiếp theo, chúng ta cần tìm ra giá trị mà cảm biến lực của chúng ta đọc khi không có gì được cân. Giá trị này sẽ là TARRA_CONSTANT.
Đối với GRAM_CONSTANT, chỉ cần lấy một đối tượng mà bạn biết trọng lượng của nó (tôi đã sử dụng một gói mì Ý), cân nó và chia số đọc cảm biến lực với trọng lượng thực của đối tượng. Đối với tôi, đây là 101.
class LoadCell (threading. Thread):
def _init _ (self, socket, lcd): threading. Thread._ init _ (self) self.hx711 = HX711 (dout_pin = 5, pd_sck_pin = 6, channel = 'A', gain = 64) self.socket = socket self.lcd = LCD
ở đây chúng ta khởi tạo lớp LoadCell và ánh xạ các chân.
def run (tự):
try: while True: self.hx711.reset () # Trước khi chúng tôi bắt đầu, hãy đặt lại HX711 (không bắt buộc) Measure_avg = sum (self.hx711.get_raw_data ()) / 5 weight = round ((Measure_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 releaseten") writeWeight = "weight:" + str (db_weight) msg = "PETFEED" LCDWrite.message () if int (db_weight [: - 2]) <= 100: StepperFood.run () time.sleep (20) ngoại trừ Exception as e: print ("Lỗi khi cân" + str (e))
Bước 5: Mã hóa cảm biến nước
import timeimport threading from repositories. DataRepository nhập DataRepository từ RPi import GPIOGPIO.setmode (GPIO. BCM) GPIO.setwarnings (Sai) GPIO_Water = 18 GPIO.setup (GPIO_Water, GPIO. IN) lớp WaterSensor (threading. Thread): def (_init 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, "Thời gian": DataRepository.serializeDateTime (actionTime), "action": action}) time.sleep (5) ngoại trừ Exception as ex: print (ex) print ('error bij waterensor') def is_water (self): status = GPIO.input (GPIO_Wate r) if self.vorige_status == 0 và 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 và status == 1: print ('water aanwezig') sensorData = {"status": status, "action": "water aanwezig"} status = GPIO.input (GPIO_Water) nếu self.vorige_status == 1 và 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 và status == 0: print ('startpositie') status = GPIO.input (GPIO_Water) sensorData = {"status": status, "action": "startpositie"} return sensorData
Bước 6: Mã hóa cảm biến tiệm cận
import timeimport threading from repositories. DataRepository nhập DataRepository từ RPi nhập GPIO GPIO.setmode (GPIO. BCM) GPIO.setwarnings (Sai) GPIO_Trig = 4 GPIO_Echo = 17 GPIO.setup (GPIO_Trig, GPIO. OUT) GPIO.setup (GPIO_Echo, GPIO.setup (GPIO_Echo). 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 khoảng = 5000 trong khi True: if current_milli_time ()> last_reading + khoảng: dist = self.distance () print ("Khoảng cách đo =%.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 () ngoại trừ Exception as ex: print (ex) de f distance (self): # đặt Trigger thành HIGH GPIO.output (GPIO_Trig, True) # đặt Trigger sau 0.01ms thành LOW time.sleep (0.00001) GPIO.output (GPIO_Trig, False) StartTime = time.time () StopTime = time.time () # lưu StartTime trong khi GPIO.input (GPIO_Echo) == 0: StartTime = time.time () # lưu thời gian đến trong khi GPIO.input (GPIO_Echo) == 1: StopTime = time.time () # chênh lệch thời gian giữa thời gian bắt đầu và đến TimeElapsed = StopTime - StartTime # nhân với tốc độ âm (34300 cm / s) # và chia cho 2, vì khoảng cách đó và khoảng cách quay lại = (TimeElapsed * 34300) / 2 khoảng cách trở lại
Bước 7: Mã hóa động cơ bước
nhập RPi. GPIO làm GPIO Nhập thời gian nhập phân luồng GPIO.setmode (GPIO. BCM) GPIO.setwarnings (Sai) control_pins = [12, 16, 20, 21] cho pin trong control_pins: GPIO.setup (pin, GPIO. OUT) GPIO.output (pin, 0) halfstep_seq =
Mã này có thể được sử dụng lại cho động cơ bước khác, chỉ cần đặt số chân điều khiển thành các chân thay thế của chúng và đổi tên lớp thành StepperWater:
Bước 8: Mã hóa màn hình LCD
Rất nhiều mã, nhưng chúng tôi sắp hoàn thành.
Lớp LCD được bao gồm dưới dạng tệp LCD.py
từ người trợ giúp. LCD nhập khẩu 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]) lớp LCDWrite: def message (msg): try: print ("try") lcd.init_LCD () lcd.send_instruction (12) lcd.clear_display () lcd.write_message (msg, '1') ngoại trừ: print ("lỗi LCDWrite")
Bước 9: Kết thúc
kết quả cuối cùng: chúng tôi đã vẽ nó như thế nào so với kết quả của nó.