M5Stick を使った呼び鈴


リビングから呼んでもらうときのインターフォン的なものを。Arduino (M5Stick) を使って、こちらの部屋の Raspberry Pi に OSC を飛ばして電子ブザーを鳴らす。受信した際に今度は逆側に受信信号を渡して Arduino 側のディスプレイに受信したよ(青になるだけ)と表示。ボタンを押すと「わかったよー」ということで再び OSC を飛ばして液晶と LED ライトを消す。
ついでに以前やった二酸化炭素濃度も950を超えると LED が付くようにして、SpreadSheet を見てなくてもいいように。

コードはかなり適当なのでイケてない。

[呼び出し送信側] (M5Stick)

#include <M5StickC.h>
#include <ArduinoOSCWiFi.h>

#define BUTTON01_PIN  37               // 真中のボタン
#define LED_PIN       10.              // LED
#define SEND_PORT     55555            // OSC で使うポート番号
#define SEND_IP       ""               // 受け取る側の IP
#define LED_ON        LOW
#define LED_OFF       HIGH
#define BUTTON_ON     LOW
#define BUTTON_OFF    HIGH

const char* ssid = "";                 // WiFi の SSID
const char* pw = "";                   // WiFi の パスワード
IPAddress ip(192, 168, ?, ?);          // 固定したい IP
IPAddress gateway(192,168, ?, ?);
IPAddress subnet(255, 255, 255, 0);
IPAddress DNS(192,168, ?, ?);

bool received = false;
bool gotit = false;

void setup() {
  pinMode(BUTTON01_PIN, INPUT);
  pinMode(LED_PIN,      OUTPUT);

  Serial.begin(115200);
  while (!Serial) {
    delay(100);
  }
  Serial.println("Serial OK");

  WiFi.disconnect();
  while (WiFi.status() == WL_DISCONNECTED) {
    Serial.println("WiFi disconnecting...");
    delay(1000);
  }
  
  WiFi.config(ip, gateway, subnet, DNS);
  WiFi.begin(ssid, pw);

  while (WiFi.status() != WL_CONNECTED) {
    Serial.println("WiFi connecting...");
    delay(1000);
  }

  Serial.println("WiFi connected");
  digitalWrite(LED_PIN, LED_OFF);

  OscWiFi.subscribe(SEND_PORT, "/ring/receive",
      [&](bool _gotit) {
        Serial.println("Receive");
        if (_gotit) gotit = true;
        else received = true;
      }
  );

  M5.begin();
  M5.Axp.ScreenBreath(8);
  M5.Lcd.setRotation(0);
  M5.Lcd.fillScreen(WHITE);
  M5.Lcd.setTextSize(1);
  M5.Lcd.print("SUCCESS");

  delay(1000);
  M5.Axp.ScreenBreath(6);
  M5.Lcd.fillScreen(BLACK);
}

void loop() {
  if (digitalRead(BUTTON01_PIN) == BUTTON_ON) {
    OscWiFi.send(SEND_IP, SEND_PORT, "/ring/call", true);
    digitalWrite(LED_PIN, LED_ON);
    M5.Axp.ScreenBreath(10);
    M5.Lcd.fillScreen(WHITE);
    delay(1000);
  }
  else if (received)
  {
    M5.Lcd.fillScreen(BLUE);
    received = false;
  }
  else if (gotit)
  {
    digitalWrite(LED_PIN, LED_OFF);
    M5.Axp.ScreenBreath(6);
    M5.Lcd.fillScreen(BLACK);
    gotit = false;
  }

  OscWiFi.update();
}

[受信側] (Raspberry Pi)

import socket
import threading
import time
import RPi.GPIO as GPIO

from pythonosc import osc_server
from pythonosc.dispatcher import Dispatcher
from pythonosc import udp_client
from pythonosc.osc_message_builder import OscMessageBuilder

BUZZER_PIN = ? // ブザーのピン
TACT_PIN = ? // タクトスイッチのピン
BUZZER_ON = GPIO.HIGH
BUZZER_OFF = GPIO.LOW
TACT_ON = GPIO.HIGH

IP = "";
SEND_IP = "" // 送る IP
PORT = 55555 // OSC で使うポート番号

GPIO.setmode(GPIO.BCM)
GPIO.setup(BUZZER_PIN, GPIO.OUT)
GPIO.setup(TACT_PIN, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) # innter pull down resitance

# Get local IP
for i in range(20):
    try:
        IP = socket.gethostbyname("raspberrypi.local")
    except Exception:
        time.sleep(3);
    else:
        break


# Receive OSC
def on_received(address, message):
    client.send(msg_received.build())
        
    for num in range(6):
        GPIO.output(BUZZER_PIN, BUZZER_ON if num % 2 == 0 else BUZZER_OFF)
        time.sleep(0.2)

dispatcher = Dispatcher()
dispatcher.map("/ring/call", on_received)

server = osc_server.ThreadingOSCUDPServer((IP, PORT), dispatcher)
server_thread = threading.Thread(target=server.serve_forever);
server_thread.start()


# Send OSC
client = udp_client.UDPClient(SEND_IP, PORT)
msg_gotit = OscMessageBuilder(address='/ring/receive')
msg_gotit.add_arg(True)
msg_received = OscMessageBuilder(address='/ring/receive')
msg_received.add_arg(False)

try:
    while True:
        if GPIO.input(TACT_PIN) == TACT_ON:
            client.send(msg_gotit.build())
            time.sleep(0.5)
finally:
    GPIO.cleanup()
    server.shutdown()
    print('--- stop program ---');

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です