おつまみディスペンサーを IoT 化してみた。


"お酒" には "おつまみ" が付きものということで、今回はタッチセンサー付きおつまみディスペンサーを IoT 化してみた。

🍶 🍺 🍻 🍷 🍸 🍹 🍾 🥃 + 🍲 🍔 🌭 🌮 🌯 🍕 🍖 🍗 🍙 🍛 🍜 🍝 🍢 🍣 🍚

キャンディ・ディスペンサーとか、おつまみディスペンサーとか、オートディスペンサーなどの検索キーワードで出てくる製品で、以下2つの製品を入手して分解したところ同じ基盤・部品・配線で実装されていたので、同じ仕組みでイケると思う。

構成

スマートスピーカー (Google Home または Amazon Alexa) を入力として、Node-RED を経由して webhook リクエストを MQTT リクエスト (Publish) へ変換し、Milkcocoa 経由でおつまみディスペンサーへ MQTT リクエスト (Subscribe) を送る構成とした。音声入力の内容によって Node-RED からの MQTT リクエストの内容を変更して、おつまみディスペンサーへのリクエストを振り分ける構成とした。

分解

本製品は中身 (おつまみ) を入れ替えるので基本的に分解して洗えるようになっている。

ケース、トレイ、回転体を取り外し、3本のネジをプラスドライバーで外すと基盤、モーター、タッチセンサーへアクセスできる。


台座は裏面の滑り止め (スポンジ) を取り外すと4本のネジが現れ、プラスドライバーで外すと電池ボックス、スライドスイッチへアクセスできる。


配線図

基盤に搭載されているシングルチャネルタッチセンサースイッチのチップの仕様はこちら。(仕様書)
既存のタッチセンサー機能を活かしつつ、リモート操作が可能となるよう、Wio-Node で MOS-FET のゲート電圧を操作することでモーターの陰極 (−) をスイッチングさせる配線とした。MOS-FETは定番の 2SK2232(60V25A) の入手が困難となったため、代替品として 2SK4017(60V5A) または 2SK703(100V5A) を使用した。
また、Wio-Node の電源は既存の電源ボックスから供給し、スライドスイッチで ON/OFF できる配線とした。

中蓋を取り外したあと、基盤 (基盤を止めているネジ付近) へ1本リード線をハンダ付けし、脚筒を通して台座の裏面へ配線する。


・モーターの陰極 (−) を制御するため基盤へハンダ付けし台座の裏面へ配線したリード線を MOS-FET (ドレイン) へ接続し、電池ボックスの陰極 (−) から MOS-EFT (ソース) へ接続し、Groveコネクタ (黄色のリード線) を抵抗 (220Ω) を挟んで MOS-FET (ゲート) へ接続する。
Wio-Node へ電源供給するための PH2 コネクタの陰極 (−) を電池ボックスへ、陽極 (+) をスライドスイッチへ接続する。

ソースコード

Wio-Nodeのソースコードはこちら

ESP8266_MOTOR_01.ino
#include <ESP8266WiFi.h>
#include <Milkcocoa.h>

#define WLAN_SSID ""  // Wi-Fi
#define WLAN_PASS ""  // Wi-Fi

#define MOTORPIN 5 // Wio-Node IO5 => MOTOR,  NodeMCU D1=GPIO5 D6=GPIO12
#define DEVICEID 1 // if selector is 0, MOTOR works in 0.1 second for health check purpose. 
                   // if selector is DEVICEID, MOTOR is switched on during timer. if NOT, MOTOR doesn't work.

WiFiClient client;

#define MILKCOCOA_APP_ID    ""  // MilkCocoa Application ID
#define MILKCOCOA_DATASTORE ""  // MilkCocoa Datastore Name
#define MILKCOCOA_SERVERPORT  1883

const char MQTT_SERVER[] PROGMEM    = MILKCOCOA_APP_ID ".mlkcca.com";
const char MQTT_CLIENTID[] PROGMEM  = __TIME__ MILKCOCOA_APP_ID;

Milkcocoa milkcocoa = Milkcocoa(&client, MQTT_SERVER, MILKCOCOA_SERVERPORT, MILKCOCOA_APP_ID, MQTT_CLIENTID);

int red, green, blue, selector, timer;

void onpush(DataElement *elem) {
  Serial.println("onpush");
  Serial.print("r:");
  Serial.print(elem->getInt("r"));
  Serial.print(",g:");
  Serial.print(elem->getInt("g"));
  Serial.print(",b:");
  Serial.print(elem->getInt("b"));
  Serial.print(",s:");
  Serial.print(elem->getInt("s"));
  Serial.print(",t:");
  Serial.print(elem->getInt("t"));
  Serial.println();

  red = elem->getInt("r");
  green = elem->getInt("g");
  blue = elem->getInt("b");
  selector = elem->getInt("s");
  timer = elem->getInt("t");

  if (selector) {
    if (selector == DEVICEID) {
      digitalWrite(MOTORPIN, HIGH); 
      delay(timer * 1000);
      digitalWrite(MOTORPIN, LOW); 
    }
  } else {
    digitalWrite(MOTORPIN, HIGH); 
    delay(100);
    digitalWrite(MOTORPIN, LOW); 
  }
}

void setupWiFi() {
  Serial.println(); Serial.println();
  Serial.print("Connecting to ");
  Serial.println(WLAN_SSID);
  WiFi.begin(WLAN_SSID, WLAN_PASS);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println();
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}

void setup() {
  pinMode(15, OUTPUT);  // for Wio-Node
  digitalWrite(15, 1);  // for Wio-Node
  Serial.begin(115200);
  setupWiFi();
  Serial.println( milkcocoa.on(MILKCOCOA_DATASTORE, "push", onpush) );
  pinMode(MOTORPIN, OUTPUT); 
}

void loop() {
  milkcocoa.loop();
}

まとめ

現在構想中の IoT 居酒屋 (仮) の実現に向けて一歩でも近づければ幸いです。