Adafruit_Learning_System_Gu.../Two_Way_Servo_Telegraph/code.py
2025-04-10 10:27:40 -07:00

142 lines
4.2 KiB
Python

# SPDX-FileCopyrightText: 2022 Liz Clark for Adafruit Industries
# SPDX-License-Identifier: MIT
from os import getenv
import time
import ssl
import board
import touchio
import pwmio
from analogio import AnalogIn
import adafruit_requests
import socketpool
import wifi
from adafruit_io.adafruit_io import IO_HTTP, AdafruitIO_RequestError
from simpleio import map_range
from adafruit_motor import servo
# Get WiFi details and Adafruit IO keys, ensure these are setup in settings.toml
# (visit io.adafruit.com if you need to create an account, or if you need your Adafruit IO key.)
ssid = getenv("CIRCUITPY_WIFI_SSID")
password = getenv("CIRCUITPY_WIFI_PASSWORD")
aio_username = getenv("ADAFRUIT_AIO_USERNAME")
aio_key = getenv("ADAFRUIT_AIO_KEY")
if None in [ssid, password, aio_username, aio_key]:
raise RuntimeError(
"WiFi and Adafruit IO settings are kept in settings.toml, "
"please add them there. The settings file must contain "
"'CIRCUITPY_WIFI_SSID', 'CIRCUITPY_WIFI_PASSWORD', "
"'ADAFRUIT_AIO_USERNAME' and 'ADAFRUIT_AIO_KEY' at a minimum."
)
# select which display is running the code
servo_one = True
# servo_two = True
# angles for servo
ANGLE_MIN = 0
ANGLE_MAX = 180
print(f"Connecting to {ssid}")
wifi.radio.connect(ssid, password)
print(f"Connected to {ssid}!")
pool = socketpool.SocketPool(wifi.radio)
requests = adafruit_requests.Session(pool, ssl.create_default_context())
# Initialize an Adafruit IO HTTP API object
io = IO_HTTP(aio_username, aio_key, requests)
# pylint: disable=undefined-variable
# disabling undefined-variable for ease of comment/uncomment
# servo_one or servo_two at top for user
# setup for display 1
if servo_one:
# servo calibration values
CALIB_MIN = 15708
CALIB_MAX = 43968
# create feeds
try:
# get feed
out_feed = io.get_feed("touch-1")
in_feed = io.get_feed("touch-2")
except AdafruitIO_RequestError:
# if no feed exists, create one and push the first value
out_feed = io.create_new_feed("touch-1")
in_feed = io.create_new_feed("touch-2")
io.send_data(in_feed["key"], float(abs((ANGLE_MAX-ANGLE_MIN)/2)))
# setup for display 2
if servo_two:
CALIB_MIN = 15668
CALIB_MAX = 43550
try:
# get feed
out_feed = io.get_feed("touch-2")
in_feed = io.get_feed("touch-1")
except AdafruitIO_RequestError:
# if no feed exists, create one and push the first value
out_feed = io.create_new_feed("touch-2")
in_feed = io.create_new_feed("touch-1")
io.send_data(in_feed["key"], float(abs((ANGLE_MAX-ANGLE_MIN)/2)))
received_data = io.receive_data(in_feed["key"])
# Pin setup
SERVO_PIN = board.A1
FEEDBACK_PIN = board.A2
touch = touchio.TouchIn(board.TX)
# servo setup
pwm = pwmio.PWMOut(SERVO_PIN, duty_cycle=2 ** 15, frequency=50)
servo = servo.Servo(pwm)
servo.angle = None
# setup feedback
feedback = AnalogIn(FEEDBACK_PIN)
# position finder function for servo
def get_position():
return map_range(feedback.value, CALIB_MIN, CALIB_MAX, ANGLE_MIN, ANGLE_MAX)
# touch debounce
touch_state = False
# new_msg value
new_msg = None
# last_msg value
last_msg = None
# time.monotonic() holder for pinging IO
clock = 5
while True:
# check IO for new data every 5 seconds
if (time.monotonic() - clock) > 5:
# get data
received_data = io.receive_data(in_feed["key"])
# reset clock
clock = time.monotonic()
# if touched...
if touch.value and touch_state is False:
touch_state = True
# when touch is released...
if not touch.value and touch_state is True:
# get position of servo
pos = get_position()
# send position to IO
io.send_data(out_feed["key"], float(pos))
# delay to settle
time.sleep(1)
# reset touch state
touch_state = False
# if a new value is detected
if float(received_data["value"]) != last_msg:
# assign value to new_msg
new_msg = float(received_data["value"])
# set servo angle
servo.angle = new_msg
# quick delay to settle
time.sleep(1)
# release servo
servo.angle = None
# log msg
last_msg = new_msg