from machine import Pin
from time import sleep_us, sleep
from hx711 import HX711
# =========================================
# РЕЖИМ РАБОТЫ
# =========================================
SIMULATION_MODE = True
# =========================================
# A4988
# =========================================
STEP_PIN = 25
DIR_PIN = 26
step_pin = Pin(STEP_PIN, Pin.OUT)
dir_pin = Pin(DIR_PIN, Pin.OUT)
# =========================================
# HX711
# =========================================
DT_PIN = 32
SCK_PIN = 33
scale = HX711(
dt_pin=DT_PIN,
sck_pin=SCK_PIN
)
# =========================================
# КАЛИБРОВКА
# =========================================
# Для Wokwi:
# RAW 42 ≈ 100 г
RAW_PER_GRAM = 0.42
# В режиме симуляции:
# каждые 20 шагов = примерно 1 грамм
STEPS_PER_GRAM = 20
# Откат шнека после выдачи
BACKWARD_STEPS = 20
# =========================================
# МОТОР
# =========================================
def motor_step(clockwise=True, delay_us=1000):
"""
Делает один шаг двигателя.
"""
dir_pin.value(1 if clockwise else 0)
step_pin.value(1)
sleep_us(delay_us)
step_pin.value(0)
sleep_us(delay_us)
def rotate_steps(steps_count, clockwise=True, delay_us=1000):
"""
Делает заданное количество шагов.
"""
for _ in range(steps_count):
motor_step(
clockwise=clockwise,
delay_us=delay_us
)
# =========================================
# HX711
# =========================================
def read_weight():
"""
Читает текущий вес в граммах.
Используется в реальном режиме.
"""
raw = scale.read_raw()
grams = raw / RAW_PER_GRAM
return grams
# =========================================
# ДОЗИРОВАНИЕ
# =========================================
def dispense_food(target_grams):
print()
print("==============================")
print("Начало выдачи корма")
print("Цель:", target_grams, "г")
if SIMULATION_MODE:
print("Режим: SIMULATION")
else:
print("Режим: REAL HX711")
print("==============================")
steps_done = 0
current_weight = 0.0
while True:
# ---------------------------------
# Получаем текущий вес
# ---------------------------------
if SIMULATION_MODE:
current_weight = (
steps_done / STEPS_PER_GRAM
)
if steps_done % STEPS_PER_GRAM == 0:
print(
"Вес:",
round(current_weight, 1),
"г"
)
else:
current_weight = read_weight()
# ---------------------------------
# Проверяем достижение цели
# ---------------------------------
if current_weight >= target_grams:
break
remaining = (
target_grams - current_weight
)
# ---------------------------------
# Выбираем скорость двигателя
# ---------------------------------
if remaining > 10:
delay = 500
elif remaining > 3:
delay = 1000
else:
delay = 2000
# ---------------------------------
# Делаем один шаг шнека
# ---------------------------------
motor_step(
clockwise=True,
delay_us=delay
)
steps_done += 1
# ---------------------------------
# Вывод в консоль
# ---------------------------------
if SIMULATION_MODE:
if steps_done % STEPS_PER_GRAM == 0:
print(
"Вес:",
round(current_weight, 1),
"г"
)
else:
# Чтобы не засорять консоль каждым шагом
if steps_done % 20 == 0:
print(
"Вес:",
round(current_weight, 1),
"г"
)
# =====================================
# ЦЕЛЬ ДОСТИГНУТА
# =====================================
print()
print("Цель достигнута")
print(
"Финальный вес:",
round(current_weight, 1),
"г"
)
print("Останавливаем шнек")
sleep(0.5)
print("Откат шнека назад")
rotate_steps(
BACKWARD_STEPS,
clockwise=False,
delay_us=1000
)
print("Выдача завершена")
print("==============================")
# =========================================
# ЗАПУСК
# =========================================
MAX_PORTION = 500
while True:
print()
print("Введите количество корма в граммах:")
try:
value = input("> ")
grams = float(value)
if grams <= 0:
print("Количество должно быть больше 0")
continue
if grams > MAX_PORTION:
print("Максимальная порция:", MAX_PORTION, "г")
continue
dispense_food(grams)
except ValueError:
print("Ошибка: введите число")