[생활 해커] 이어폰과 스피커의 연결을 이용하여 연결을 끊는다

크랜베리 파이로 ↓를 만들었다.개인적인 고민을 해결했다고 합니다.

😟딱한 사정


내 컴퓨터에는 이어폰과 스피커가 연결되어 있다.
평소에는 스피커만 사용하다가 밤이나 집중하고 싶을 때는 이어폰으로 음악을 듣는다.
Image from Gyazo
그래서 나는 매번 아래의 곳으로 간다.
  • 헤드폰 사용 시 스피커 전원 끄기
  • 헤드폰을 사용하지 않을 경우 스피커 전원 켜기
  • 스피커를 사용하기 때문에 볼륨을 조절해야 함
  • ↑ 스피커의 전원 스위치 조작은 매우 번거로운데 자동화할 수 없습니까?나는 매우 괴롭다.

    💡해본 일


    Image from Gyazo
  • 사용자가 이어폰을 치우거나 꺼내기
  • 수습(/제거) 후 스위치의 상태가 변화
  • ※ 스위치의 개요는 뒤에 서술
  • 크랜베리 파이 감시 스위치 상태
  • 스위치 변경에 응답하여 IFTTT에 요청
  • IFTT를 통해 스피커에 연결된 스마트 플러그 제어
  • 정리-> 스피커 전원 켜기
  • 분리 -> 스피커 전원 끄기
  • 이번에는 크랜베리 파이와 스위치로 만들기로 했다.

    🔧부품 일람


    no
    부품 이름
    개수
    시험을 준비하다
    1
    크랜베리 파이
    1
    이번에는 4B로 할게요.
    2
    스위치
    1
    Amazon12×12의
    3
    도약선
    적당량
    -
    4
    스프링
    1
    -
    5
    스위치 박스
    1
    3D 프린터로 자체 제작(후술)
    6
    지능 플러그
    1
    Amazon IFTT 지원 제품 사용
    7
    PC 스피커
    1
    Amazon 전원 연결 및 볼륨 범용

    연결 다이어그램


    스위치를 감시하기 위해서는 회로 자체가 간단하다.
    Image from Gyazo

    💻컨디션


    개발 환경

  • 크랜베리 파이
  • Linux rpi 5.10.17-v7l+ #1403 SMP Mon Feb 22 11:33:35 GMT 2021 armv7l GNU/Linux
  • Python
  • Python 3.7.3 (default, Jan 22 2021, 20:04:44)
  • 크랜베리 파이 설정


    별거 없어요.

    설치 모듈


    에는 OS의 클린 설치 사전 요구 사항이 기재되어 있습니다.

    apt


    pigpio 라이브러리는 Raspberry Pi를 제어하는 GPIO 라이브러리입니다.
    다음 명령은 처음 설치할 때만 필요합니다.
    $ sudo apt install pigpio
    $ sudo service pigpiod start
    $ sudo systemctl enable pigpiod.service
    

    pip


    Python 관련 모듈을 설치합니다.
    $ python3 -m venv env
    $ source env/bin/activate
    (env) $ pip install pigpio
    (env) $ pip install gpiozero
    (env) $ pip install requests
    

    📝절차.


    아래 내용을 기재하다.
  • 3D 프린터를 통한 스위치 생성
  • 스마트 플러그의 제어 준비(IFTT의 준비)
  • 감시 스위치
  • 3D 프린터 생성 스위치


    스위치는 ↓ 느낌.
    Image from Gyazo
    스위치의 3D 데이터 제작에는 Solidpythhon이 사용됩니다.

    Solidpythhon 소개


    Python 프로그램에서 OpenSCAD 프로그램을 생성하여 3D 모델링을 구현합니다.
    설치 방법과 사용 방법은 이미 이전의 문장에서 총결하였으니 참고하십시오.
    https://zenn.dev/kotaproj/articles/a70464d8cd3540

    코드


    코드로 다음 네 개의 부품을 제작한다.
    Image from Gyazo
    sw_all.py
    from solid import *
    from solid.utils import *
    
    def add_hole(cu, cu_x=24, cu_y=24, cu_z=10, cy_h=5, cy_r=1.3, ana_w=8):
        """ネジ穴の追加
        """
        cy = cylinder(h=cy_h, r=cy_r)
        cy = rotate([0, 90, 0])(cy)
        cy = translate([-1*cy_h/2, 0, 0])(cy)
    
        offs = [ (cu_x/2, ana_w, cu_z/2),
                (cu_x/2, -ana_w, cu_z/2),
                ((-1)*cu_x/2, ana_w, cu_z/2),
                ((-1)*cu_x/2, -ana_w, cu_z/2),
                ]
        for off in offs:
            cu -= translate(off)(cy)
    
        return cu
    
    
    def make_tutu(xw, yw, zw, t=2.0):
        """筒の作成
        """
        c_base = cube([xw, yw, zw], center=False)
        c_cut = cube([xw-t, yw-t, zw-t+0.01], center=False)
        c_cut = translate([t/2, t/2, -t-0.01])(c_cut)
        c = c_base - c_cut
        c = translate([-xw/2, -yw/2, 0])(c)
        return c
    
    
    def make_tutu_ana(xw, yw, zw, t=2.0, r=3.1):
        """筒に穴あけ
        """
        c = make_tutu(xw, yw, zw, t)
        cy = cylinder(h=zw*4, r=r)
        return (c - cy)
    
    
    def make_btm(cu_x=24, cu_y=24, cu_z=10, cut_x=12, cut_y=12, cut_z=5, cut_mizo=3):
        """btm部品の作成
        """
        cu_base = cube([cu_x, cu_y, cu_z])
        cu_cut_naka = translate([(cu_x-cut_x)/2, (cu_y-cut_y)/2, cu_z-(cut_z-0.1)])(cube([cut_x, cut_y, (cut_z+0.1)]))
        cu_cut_t1 = translate([(0-0.1), (cu_y-cut_y)-cut_mizo/2 - 2.5, cu_z-(cut_z-0.01)])(cube([cu_x+1.0, cut_mizo, (cut_z+0.01)]))
        cu_cut_t2 = translate([(0-0.1), (cu_y-cut_y)-cut_mizo/2 + 2.5, cu_z-(cut_z-0.01)])(cube([cu_x+1.0, cut_mizo, (cut_z+0.01)]))
    
        wa = cu_base - (cu_cut_naka + cu_cut_t1 + cu_cut_t2)
        wa = translate([(-1)*cu_x/2, (-1)*cu_y/2, 0])(wa)
        return wa
    
    
    def make_btm_cover(cu_x=24, cu_y=24, cu_z=10, cut_x=12, cut_y=12, cut_z=5):
        """cover部品の作成
        """
        cu_base = cube([cu_x, cu_y, cu_z])
        cu_cut_naka = translate([(cu_x-cut_x)/2, (cu_y-cut_y)/2, cu_z-(cut_z-0.1)])(cube([cut_x, cut_y, (cut_z+0.1)]))
    
        wa = cu_base - (cu_cut_naka)
        wa = translate([(-1)*cu_x/2, (-1)*cu_y/2, 0])(wa)
        return wa
    
    
    def make_totu(cu_x=20, cu_y=20, cu_z=2, cy_h=10, cy_r=3):
        """totu部品の作成
        """
        cu = cube([cu_x, cu_y, cu_z], center=False)
        cu = translate([-1*cu_x/2, -1*cu_y/2, 0])(cu)
        cy = cylinder(h=cy_h, r=cy_r)
        sp = sphere(r=cy_r)
        sp = translate([0, 0, cy_h])(sp)
        return cu + cy + sp
    
    
    if __name__ == "__main__":
        # tutu
        wa_tutu = make_tutu_ana(xw=26, yw=26, zw=28, t=1.6, r=9.0)
        wa_tutu = add_hole(wa_tutu, cu_x=24, cu_y=24, cu_z=10, cy_h=5, cy_r=1.7, ana_w=8)
        wa_tutu = add_hole(wa_tutu, cu_x=24, cu_y=24, cu_z=12, cy_h=20, cy_r=2, ana_w=2.5)
        for cz in range(12):
            wa_tutu = add_hole(wa_tutu, cu_x=24, cu_y=24, cu_z=cz, cy_h=20, cy_r=2, ana_w=2.5)
            wa_tutu = add_hole(wa_tutu, cu_x=24, cu_y=24, cu_z=cz, cy_h=20, cy_r=2, ana_w=1.5)
        wa_tutu = color("blue")(wa_tutu)
        scad_render_to_file(wa_tutu, "sw_tutu.scad", include_orig_code=False)
    
        # btm
        wa_btm = make_btm(cu_x=24, cu_y=24, cu_z=10, cut_x=12.2, cut_y=12.1, cut_z=5, cut_mizo=3)
        wa_btm = add_hole(wa_btm, cu_x=24, cu_y=24, cu_z=10, cy_h=5, cy_r=1.7, ana_w=8)
        wa_btm = color("red")(wa_btm)
        scad_render_to_file(wa_btm, "sw_btm.scad", include_orig_code=False)
    
        # cover
        wa_cover = make_btm_cover(cu_x=24, cu_y=24, cu_z=4, cut_x=7.1, cut_y=7.0, cut_z=10)
        wa_cover = up(10)(wa_cover)
        wa_cover = color("cyan")(wa_cover)
        scad_render_to_file(wa_cover, "sw_cover.scad", include_orig_code=False)
    
        # totu
        wa_totu = make_totu(cu_x=22, cu_y=22, cu_z=2, cy_h=25, cy_r=8.5)
        wa_totu = wa_totu - translate([0, 0, -1])(cylinder(h=6.0, r=4))
        wa_totu = up(10)(wa_totu)
        wa_totu = color("green")(wa_totu)
        scad_render_to_file(wa_totu, "sw_totu.scad", include_orig_code=False)
    
        # all
        wa = wa_tutu + wa_btm + wa_cover + wa_totu
        scad_render_to_file(wa, "sw.scad", include_orig_code=False)
    

    파일 만들기


    인쇄할 파일을 만듭니다.
    Windows10 Python3.8에서 실시한다.
    $ python -m venv env
    $ env\Scripts\activate
    $ pip install solidpython numpy
    $ python sw_all.py
    # =>同じフォルダ内に scadファイルが作成されます。
    
    OpenSCAD에서 각 scad 파일을 열고 STL 파일을 만듭니다.
    SCAD 파일을 연 후 STL 파일을 생성할 때
    F6(렌더기) 또는 STL 아이콘을 클릭해야 합니다.
    그리고 각 부품을 인쇄한다.

    조립하다


    기본적으로 조립만 할 뿐 btm 부품의 부분을 보충해야 한다.
    Image from Gyazo
    그리고 조립해서 나사를 조여↓.
    Image from Gyazo
    갈고리의 부분은 사랑을 끊는 것이다.

    스마트 플러그 제어 준비(IFTT 준비)


    전원 공급 장치의 연결 해제를 제어하는 IFTT의 설정을 기록합니다.
    IFTT를 사용해야 하는 것은 아닙니다.
    앞서 소개한 기사에서 AC 콘센트의 켜기와 끄기를 정리했습니다.
    참고해주세요.↓
    https://zenn.dev/kotaproj/articles/b3e8766c192ce5

    사전 준비(IFTT)


    IFTT-무료 프로젝트는 세 가지 동작만 동시에 진행할 수 있습니다.
    필요에 따라 유료(Pro로 이전)와 애플릿을 무효로 설정해야 한다.

    사과


    IFTT 설정 단계는 다음과 같습니다.

  • 액세스https://ifttt.com/home 계정 생성 또는 로그인
  • Create를 통해 다음 두 개 만들기
  • 전원 끄기
  • This(Trigger)
  • "Webhooks"- "Receive a web request"
  • "Event Name": meross_speaker_poweroff
  • That(Action)
  • Meross - Turn off
  • 전원 공급 장치 연결
  • This(Trigger)
  • "Webhooks"- "Receive a web request"
  • "Event Name": meross_speaker_poweron
  • That(Action)
  • Meross - Turn on
  • Image from Gyazo

    Token 확인


    토큰이 홈페이지를 찰 수 있는지 확인해 보세요.
  • Webhooks Settings 페이지에서 확인
  • 아래 그림의 가려진 곳에 기재
  • 이 토큰은 다음 코드의 IFTT입니다저는 도쿄 사람입니다.

    감시 스위치


    크랜베리 파이 감시 스위치.

    코드


    IFTTT_자신의 환경에 맞추세요.
    head_onoff.py
    from gpiozero import Button
    from gpiozero.pins.pigpio import PiGPIOFactory
    from signal import pause
    import requests
    
    # SWのピン設定
    PIN_BTN1 = 24
    
    # IFTTT
    IFTTT_TOKEN = "xxxxxxxxxxxxxxxxxxxxxxxxxx"
    
    def post_ifttt(eventid, values=None):
        print("post_ifttt - run", eventid)
        if values is None:
            # {"value1":"1", "value2":"2", "value3":"3"}
            payload = {"value"+str(x):str(x) for x in range(1, 4)}
        else:
            # {"value1":values[0], "value2":values[1], "value3":values[2]}
            payload = {"value"+str(cnt+1):x for cnt, x in enumerate(values)}
        url = "https://maker.ifttt.com/trigger/" + eventid + "/with/key/" + IFTTT_TOKEN
        print(url)
        response = requests.post(url, data=payload)
        return
    
    def main():
        # SWピンを入力に設定(プルアップ設定)
        factory = PiGPIOFactory()
        btn = Button(PIN_BTN1, pull_up=True, bounce_time=0.3, hold_time=1.0, pin_factory=factory)
    
        def press_btn():
            print("pressed button!")
            post_ifttt("meross_speaker_poweron")
    
        def release_btn():
            print("released button!")
            post_ifttt("meross_speaker_poweroff")
    
        # 起動時の初期化
        if btn.is_pressed:
            press_btn()
        else:
            release_btn()
    
        # callback
        btn.when_pressed = press_btn
        btn.when_released = release_btn
        pause()
        return
    
    if __name__ == "__main__":
        main()
    
    시위 행진의 결과가 되다.

    🔎주안점


    절차의 요점을 간단히 기재하다.

    스위치-위로 당기기 설정-pullup


    스위치를 누르지 않은 상태에서 PIN은 부동 상태(불안정 상태)입니다.
    잡음이 있을 경우 오작동을 초래할 수 있다.
    따라서'pull up=True'를 지정해 마이크로컴퓨터의 전압(3.3V) 상태로 들어간다.
    회로도에서 저항을 사용할 때 코드에pulup을 지정할 필요가 없습니다.

    스위치 - 감지 설정 - bouncetime, hold_time


    스위치에 변경 사항이 있습니다.
    부정기를 무시하기 위해bounce시간을 300msec로 설정합니다.
    최초의 변화점(⇔放)부터 300msec를 무시하고 불필요한 사건을 추가하지 마세요.
    또한 이 어플리케이션은 즉각적인 동작이 필요하지 않으므로 1초 동안 안정된 상태로 작동합니다.
    hold_시간은 1초로 설정됩니다.

    최후


    무사히 만들고 싶은 걸 만들었어요.
    이어폰도 일정한 위치에서 정리하는 습관이 들어서 다행이다.
    이 기사를 포함해서 Lazupa의 방법을 잘 활용하세요
    https://zenn.dev/kotaproj/books/raspberrypi-tips
    총결산으로 삼다.

    좋은 웹페이지 즐겨찾기