고무-리모컨+α사용자 정의 - 사용자 4(LED/버저/표시)
58821 단어 PythonRaspberry Pi전자 작업tech
🏁데모
📚기사 목록
4 – LED/버저/표시← 기사
📍본문의 범위
🔧부품 일람
부품 이름
개수
컨텐트
시험을 준비하다
RaspberryPiZeroWH
1
크랜베리 파이 제로 본체
추월전자
캠 로봇
1
캠 로봇 본체
Amazon
SG90
2
SG90 호스트
추월전자
LED
2
LED 섀시
-
LED용 저항
2
저항
-
압전 버저(PKM13 EPYH4000)
1
BEEP 음용
추월전자
OLED
1
모니터 128x64dot
추월전자
※ 모든 부품은 그 개념 참조
연결 다이어그램
LED
Pin
LED
시험을 준비하다
GND
GND
LED1/2
BCM16
LED 1 - 양극
-
BCM20
LED 2 - 양극
-
버저
Pin
버저
시험을 준비하다
GND
버저 연결부
무극성
BCM21
버저 연결부
무극성
OLED
Pin
OLED
시험을 준비하다
BCM2
SDA
-
BCM3
SCL
-
GND
GND
-
3.3V
VDD
-
💻컨디션
개발 환경
크랜베리 파이 설정
OLED-I2C의 유효성
이 장치는 I2C 통신을 사용하여 제어합니다.
I2C로 통신할 수 있도록 설정해야 합니다.
다음 명령을 사용하여 I2C를 효율적으로 사용할 수 있습니다.
$ sudo raspi-config
설치 모듈
에는 OS의 클린 설치 사전 요구 사항이 기재되어 있습니다.
apt
pigpio 라이브러리는 Raspberry Pi를 제어하는 GPIO 라이브러리입니다.
다음 명령은 처음 설치할 때만 필요합니다.
$ sudo apt install pigpio
$ sudo service pigpiod start
$ sudo systemctl enable pigpiod.service
또한 일본어를 표시하는 글꼴을 설치합니다.$ sudo apt-get install fonts-ipafont
pip
Python 관련 모듈을 설치합니다.
LED,버저
$ python3 -m venv env
$ source env/bin/activate
(env) $ pip install pigpio
(env) $ pip install gpiozero
(env) $ pip install icecream
icecream은 디버깅용입니다.꼭 필요한 건 아니지만 확인 시 사용합니다.
처리가 느리다고 생각되면 print 문장으로 바꿔 주세요.
OLED
(env) $ pip install adafruit-circuitpython-ssd1306
(env) $ pip install smbus2
(env) $ pip install pillow
📝절차.
마지막으로 모든 모듈의 협업을 위해 대기열을 사용했습니다.
LED 제어
코드 - LED
led.py
from queue import Queue
import threading
import time
from gpiozero import LED
from gpiozero.pins.pigpio import PiGPIOFactory
import sys
from icecream import ic
# LEDのピン設定
PIN_LED_NO1 = 16
PIN_LED_NO2 = 20
LED_DICT = {
"no1" : PIN_LED_NO1,
"no2" : PIN_LED_NO2,
}
class LedThread(threading.Thread):
"""
LED管理
例:
queue経由で、{"name":"no1", "action":"on"}
を取得すると、LED1を点灯
"""
def __init__(self):
threading.Thread.__init__(self)
self.stop_event = threading.Event()
self.setDaemon(True)
self._rcv_que = Queue()
self._leds = {}
# 各ピンをLED設定
factory = PiGPIOFactory()
for key, pin in LED_DICT.items():
self._leds[key] = LED(pin, pin_factory=PiGPIOFactory())
return
def stop(self):
self.stop_event.set()
return
def run(self):
while True:
value = self.rcv_que.get()
ic("[led_th]", value)
if "led" not in value["type"]:
ic("[led_th]", "error!!!")
continue
if value["name"] in self._leds:
name = value["name"]
on_off = True if ("on" in value["action"]) else False
self._write_leds(name, on_off)
return
@property
def rcv_que(self):
return self._rcv_que
def _write_leds(self, name, on_off):
if on_off:
self._leds[name].on()
else:
self._leds[name].off()
return
def main():
import time
led_th = LedThread()
led_th.start()
q = led_th.rcv_que
q.put({"type": "led", "name": "no1", "action": "on"})
time.sleep(3)
q.put({"type": "led", "name": "no1", "action": "off"})
time.sleep(1)
q.put({"type": "led", "name": "no2", "action": "on"})
time.sleep(3)
q.put({"type": "led", "name": "no2", "action": "off"})
time.sleep(1)
led_th.stop()
return
if __name__ == "__main__":
main()
실행 단계 - LED
(env) $ python led.py
캠 로봇은 다음과 같은 순서에 따라 동작한다.버저 제어
코드 버저
buzzer.py
from queue import Queue
import threading
import time
from gpiozero import TonalBuzzer
from gpiozero.tones import Tone
from gpiozero.pins.pigpio import PiGPIOFactory
from icecream import ic
# BUZZERのピン設定
BUZZER_PIN = 21
# Midi note: 'C4' - ド
# Midi note: 'D4' - レ
# Midi note: 'E4' - ミ
# Midi note: 'F4' - ファ
# Midi note: 'G4' - ソ
# Midi note: 'A4' - ラ
# Midi note: 'B4' - シ
# Midi note: 'C5' - ド
BUZZER_DICT = {
"buzzer" : BUZZER_PIN,
}
class BuzzerThread(threading.Thread):
"""
ブザー管理
例:
queue経由で、{"type":"buzzer", "time": "300", "bfreq":"2000"}
を取得すると、ブザー音を300msec鳴らす
"""
def __init__(self):
threading.Thread.__init__(self)
self.stop_event = threading.Event()
self.setDaemon(True)
self._rcv_que = Queue()
self._buzzer = {}
for key, pin in BUZZER_DICT.items():
self._buzzer[key] = TonalBuzzer(pin, pin_factory=PiGPIOFactory())
return
def stop(self):
self.stop_event.set()
# cleanup
for key in self._buzzer:
self._buzzer[key].stop()
return
def run(self):
while True:
# time.sleep(0.050)
item = self.rcv_que.get()
ic("[buzzer_th]", "run : get : ", item)
if "buzzer" not in item["type"]:
ic("[buzzer_th]", "error!")
continue
ms_time = int(item["time"]) / 1000
# item["note"] : 'C4', 'D4', 'E4', 'F4', 'G4', 'A4', 'B4', 'C5'
self._buzzer[item["name"]].play(Tone(item["note"]))
time.sleep(ms_time)
self._buzzer[item["name"]].stop()
return
@property
def rcv_que(self):
return self._rcv_que
def main():
import time
buzzer_th = BuzzerThread()
buzzer_th.start()
q = buzzer_th.rcv_que
q.put({"type": "buzzer", "name": "buzzer", "time": "500", "note": "C4"}) # do
time.sleep(1)
q.put({"type": "buzzer", "name": "buzzer", "time": "500", "note": "D4"}) # re
time.sleep(1)
q.put({"type": "buzzer", "name": "buzzer", "time": "500", "note": "E4"}) # mi
time.sleep(1)
q.put({"type": "buzzer", "name": "buzzer", "time": "500", "note": "F4"}) # fa
time.sleep(1)
buzzer_th.stop()
return
if __name__ == "__main__":
main()
단계 실행 - 버저
(env) $ python buzzer.py
캠 로봇은 다음과 같은 순서에 따라 동작한다.디스플레이 제어
코드 - 표시
oled.py
from queue import Queue
import threading
import time
from systems import SystemsData
# Imports the necessary libraries...
import socket
import fcntl
import struct
import board
import digitalio
from PIL import Image, ImageDraw, ImageFont
import adafruit_ssd1306
import sys
from icecream import ic
# OLED設定
DISP_WIDTH = 128
DISP_HEIGHT = 64
DEVICE_ADDR = 0x3C
# PATH_FONT = "./ipaexm.ttf"
PATH_FONT = "/usr/share/fonts/truetype/fonts-japanese-gothic.ttf"
class OledThread(threading.Thread):
"""
OLED管理
例:
queue経由で、{"type":"oled", "time": "3000", "disp":"ip"}
disp : ip / clear
"""
def __init__(self):
ic()
threading.Thread.__init__(self)
self.stop_event = threading.Event()
self.setDaemon(True)
self._rcv_que = Queue()
self._sysdat = SystemsData()
# Setting some variables for our reset pin etc.
RESET_PIN = digitalio.DigitalInOut(board.D4)
TEXT = ""
# Very important... This lets py-gaugette 'know' what pins to use in order to reset the display
i2c = board.I2C()
self._oled = adafruit_ssd1306.SSD1306_I2C(DISP_WIDTH, DISP_HEIGHT, i2c, addr=DEVICE_ADDR, reset=RESET_PIN)
# font
self._font10 = ImageFont.truetype(PATH_FONT, 10)
self._font12 = ImageFont.truetype(PATH_FONT, 12)
self._font14 = ImageFont.truetype(PATH_FONT, 14)
self._font16 = ImageFont.truetype(PATH_FONT, 16)
self._font18 = ImageFont.truetype(PATH_FONT, 18)
# Clear display.
self._oled.fill(0)
self._oled.show()
return
def stop(self):
ic()
self.stop_event.set()
# cleanup
self._oled.fill(0)
self._oled.show()
return
def run(self):
ic()
while True:
item = self.rcv_que.get()
ic(sys._getframe().f_code.co_filename, sys._getframe().f_code.co_name, item)
if "oled" not in item["type"]:
print("[oled_th]", "error : type")
continue
self._recvice(item)
return
@property
def rcv_que(self):
return self._rcv_que
def _recvice(self, item):
ic()
val_time = int(item["time"]) / 1000
val_disp = item["disp"]
def display_ip():
ic()
def get_ip_address(ifname):
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
return socket.inet_ntoa(
fcntl.ioctl(
s.fileno(),
0x8915, # SIOCGIFADDR
struct.pack("256s", str.encode(ifname[:15])),
)[20:24]
)
# This sets TEXT equal to whatever your IP address is, or isn't
try:
TEXT = get_ip_address("wlan0") # WiFi address of WiFi adapter. NOT ETHERNET
except IOError:
try:
TEXT = get_ip_address("eth0") # WiFi address of Ethernet cable. NOT ADAPTER
except IOError:
TEXT = "NO INTERNET!"
# Clear display.
self._oled.fill(0)
self._oled.show()
# Create blank image for drawing.
image = Image.new("1", (self._oled.width, self._oled.height))
draw = ImageDraw.Draw(image)
# Draw the text
intro = "カムロボです。"
ip = "IPアドレス:"
draw.text((0, 46), TEXT, font=self._font14, fill=255)
draw.text((0, 0), intro, font=self._font18, fill=255)
draw.text((0, 30), ip, font=self._font14, fill=255)
# Display image
self._oled.image(image)
self._oled.show()
return
def display_clear():
self._oled.fill(0)
self._oled.show()
return
if "ip" in val_disp:
display_ip()
else:
# Clear display.
display_clear()
return
def main():
import time
oled_th = OledThread()
oled_th.start()
q = oled_th.rcv_que
q.put({"type": "oled", "time": "3000", "disp":"ip"})
time.sleep(10)
q.put({"type": "oled", "time": "3000", "disp":"clear"})
time.sleep(1)
oled_th.stop()
return
if __name__ == "__main__":
main()
단계 - 표시
(env) $ python oled.py
캠 로봇은 다음과 같은 순서에 따라 동작한다.🔎주안점
LED 제어 - 코드 제어
매번 불려가다
버저 제어 - 사운드 지정
다음 형식으로 지정할 수 있습니다.
MIDI Note의 경우 57-81 범위에서 지정해야 함
장치에 따라 다른 소리를 지정해도 같은 소리일 수 있습니다.
내 환경에서 톤(C4)과 톤(D4)은 같은 소리로 들린다.
디스플레이 제어 - 이미지 생성 및 그리기
코드에 사용된 Pillow 모듈은 타사 이미지 처리 모듈입니다.
이번 코드에서는 문자열이라도 먼저 이미지(Pillow 사용)를 만듭니다.
oled.128x64의 단색 이미지를 이미지()에 전달합니다.
최후
상기 이외의 활용 방법
총결산으로 삼다.
Reference
이 문제에 관하여(고무-리모컨+α사용자 정의 - 사용자 4(LED/버저/표시)), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://zenn.dev/kotaproj/articles/56fa9110f824f7텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)