目的
趣味で部屋をIoT化、もとい改造しています。
その内の一つとして、部屋の電気→スイッチをスマホから操作してみたくなりました。
ところが、部屋の電気のスイッチを直接いじるには、電気工事士の資格が必要になるため、誰でもモジュールを取り付けることでIoT化できるようなものを作る縛りゲーを自らに課しました。
#使ったもの・開発環境
PC(win10)
RaspberryPi 3 Model B+(NOOBS)
Arduino Nano (廉価版)
Pycharm Professional 2019.2(学生ライセンス)
ArduinoIDE
Python3.7.4(ラズパイ内)
Django 2.2.6(ラズパイ内)
サーボモータSG90
#構想
将来さらに改造することを考えると、ラズパイ1台ですべて制御するのは限度を感じたため、今回はラズパイを親機、arduinoを子機のように使うシステムを構想。Arduino nanoの廉価版はウルトラ安い。また、djangoで作るwebアプリは家の中で動作してくれさえすればいいので、wifi経由でラズパイのipにアクセスして使う。
また今回は、「ちゃんと手動でも操作したい」という願いを考慮する。
#ローカルのウェブサイトを立てる
pycharmでコーディングしながら、ftp通信したラズパイにデプロイしてました。
中身は超基本なものと変わらない。テンプレートで作成したbuttonによって、on/offそれぞれ作ったviewsを呼び出し、viewsの中で別のfunction.pyのフラグを上げ下げする。
import RPi.GPIO as GPIO
def switch_on_off(state):
GPIO.setmode(GPIO.BOARD)
GPIO.setup(11, GPIO.OUT)
GPIO.output(11, state)
from django.shortcuts import render, redirect
import RPi.GPIO as GPIO
from . import function
GPIO.cleanup()
def index(request):
return render(request, 'pagetop.html')
def on(request):
switch_state = True
print(switch_state)
function.switch_on_off(switch_state)
return render(request, 'pagetop.html', {'State': 'On'})
def off(request):
switch_state = False
print(switch_state)
function.switch_on_off(switch_state)
return render(request, 'pagetop.html', {'State': 'Off'})
テンプレートはこんな感じ
<table border="1" cellpadding="0">
<tr>
<th colspan="2">
部屋の電気IoT
</th>
</tr>
<tr>
<td colspan="2">
電気スイッチの状態: {{ State }}
</td>
</tr>
<tr>
<td>
<div class="switch">
<a href="{% url 'on' %}">On</a>
</div>
</td>
<td>
<div class="switch">
<a href="{% url 'off' %}">Off</a>
</div>
</td>
</tr>
</table>
これで現在のスイッチの状態を表示して、かつ簡単にon/offを制御できた。
#Arduinoとハードウェア
##Arduino制御
Arduinoでは2つの事をしたい。
- ラズパイから受け取ったon/offのフラグによってスイッチを制御
- 手動用のスイッチが押されたらon/offを反転
コードが雑なのは整理してないからで、以下のように書いた。
/// include the Servo library
#include <Servo.h>
Servo myServo; // create a servo object
int angle; // variable to hold the angle for the servo motor
bool switch1 = false;
bool switch0 = false;
const int ledpin = 5;
const int switchPin = 3;
int state,raspi_state,switch_state;
int d_state,d_r_state;
int raspi_onoff = 4;
int cycle = 0;
void actionServo(int);
int actionswitch(void);
int actionraspi(void);
void setup() {
myServo.attach(9); // attaches the servo on pin 9 to the servo object
Serial.begin(9600); // open a serial connection to your computer
myServo.write(90);
pinMode(ledpin,OUTPUT);
pinMode(switchPin,INPUT);
pinMode(raspi_onoff,INPUT);
digitalWrite(ledpin,HIGH);
delay(1000);
digitalWrite(ledpin,LOW);
state = 1;
d_state = 1;
d_r_state = 1;
}
void loop() {
state = digitalRead(switchPin);
raspi_state = digitalRead(raspi_onoff);
if(switch_state == 0){
if(actionswitch()||actionraspi() == 1){
actionServo(1);
switch_state = 1;
}
}else{
if(actionswitch()||actionraspi() == 2){
actionServo(0);
switch_state = 0;
}
}
Serial.print("raspi: ");
Serial.println(raspi_state);
delay(10);
d_state = state;
d_r_state = raspi_state;
}
void actionServo(int act){
if(act){Serial.println("ON");}else{Serial.println("OFF");}
int angle;
if(act){angle=105;}else{angle=75;}
myServo.write(angle);
digitalWrite(ledpin,HIGH);
delay(500);
myServo.write(90);
digitalWrite(ledpin,LOW);
delay(500);
}
int actionswitch(void){
if(d_state == 0){
if(state == 1){
return 1;
}
}
if(d_state == 1){
if(state == 0){
return 1;
}
}
return 0;
}
int actionraspi(void){
if(d_r_state == 0){
if(raspi_state == 1){
return 1;
}
}
if(d_r_state == 1){
if(raspi_state == 0){
return 2;
}
}
return 0;
}
1.2.の変化を読み取るための関数と、モータを作動するための関数を組み合わせて完成。
##ハードウェア
今回は、「誰でも取り付けるだけで使用できるモジュール」をコンセプトにし、スイッチの電気系統を直接いじらずオンオフを制御するため、サーボモータでスイッチを物理的に押すことで制御した(アナログ感)
ハードは3Dプリンタで作成して、あとはパーツをはめるだけ。パーツは以下の通り。
- サーボモータ
- パナソニックとかが売ってる部屋のスイッチ
- 制御ユニット(Arduino+自作電源回路)