計画
朝になったら自動でカーテンを開ける目覚まし時計を作りたい。
カーテンの端っこにひもを引っかけて朝になったらタイマーが作動してひもを巻き取りカーテンが開くという仕組み。
材料
消費電流
広いギヤ比に組み替えられるのでとりあえずこれにした。
クラッチギアが付いているので大きい負荷がかかっても少し安心。
完成品は
- mega88 Arduino内蔵クロックで動かす。
- 過電流で電源を止めるやつをつける。ポリスイッチ?
電源
- 開発時はUSB 5V
- ACアダプタ
- 5V or 3V
http://www.switch-science.com/trac/wiki/BD62xx-Basic
モーターの定格電圧が信号系(マイコン)の電源電圧よりも低い場合は困ってしまいます。
モーターによっては、PWMで一定のデューティよりも上げないように注意すれば大丈夫な場合があります。
arduinoは3Vで動くのか?
リアルタイムクロック
ユーザインターフェイス
- 正回転/逆回転ボタン
- タイマー時刻の設定/ロータリエンコーダ?
- 7セグ時計表示
巻き取り終了の検出
マイクでクラッチの音?
一定の秒数の作動でよい?
製作
(1)ざっと組み立て
- ギアボックス
- 巻き取り部取り付け
- ギアボックス&ブレッドボードを板に固定
- Arduinoを固定
- モータドライバにピン取り付け
(2)モータードライバの実験(2009/4/18)
- 正転/逆転を実験
- スピード&パワーを確認
- 消費電流を確認
int FIN = 5;
int RIN = 6;
int LED = 13;
int OFFSET = 0.7 * 256 / 5; // analogに255を出したら5V => 0.7V
int MAX = 3.0 * 256 / 5 - OFFSET; // RE-260なので3V 3.0V-0.7V = 2.7V
int degree10 = 0;
int i;
void setup() {
Serial.begin(300);
pinMode(FIN, OUTPUT);
pinMode(RIN, OUTPUT);
pinMode(LED, OUTPUT);
for(i=0; i<5; i++){
digitalWrite(LED, HIGH);
delay(200);
digitalWrite(LED, LOW);
delay(200);
}
}
void loop() {
delay(10);
degree10 += 3;
degree10 %= 3600;
long v = int(sin(degree10 * 2 * PI / 360 /10) * MAX);
Serial.println(v);
if (v > 0) {
analogWrite(FIN, v + OFFSET); // v(0V..2.7V) OFFSET(=0.7V) なので 0.7V..3.0V
analogWrite(RIN, 0);
} else
if (v < 0) {
analogWrite(FIN, 0);
analogWrite(RIN, OFFSET - v); // v(-0V..-2.7V) OFFSET(=0.7V) なので 0.7V..3.0V
} else {
analogWrite(FIN, 255);
analogWrite(RIN, 255);
}
}
正回転・逆回転をなめらかに繰り返す。
OFFSETは回転開始の最低電圧。
正:0.7V => 0.8V => ... => 2.9V => 3.0V => 2.9V => ... 0.7V
逆:0.7V => 0.8V => ... => 2.9V => 3.0V => 2.9V => ... 0.7V
を繰り返す。
ノイズ?
(3)リアルタイムクロック確認(2009/4/19)
(4)時計表示(2009/4/19)
7セグ2桁で作動までの残り時間を出せばいい。上の桁が時間、下の桁が10分単位で十分。
いや、もっと簡単にLEDの点滅回数でいい。5回点滅なら5時間。
(5)モーターから音を出す。
普通にモーターを回すときでもPWMの周波数で微妙に音が出てしまう。
てことは、適当にメロディーになるようにモーターに信号を与えたら・・・
成功!
スピーカーなしでBEEP音によるフィードバックが可能になった。
ArduinoのPWM周波数
PWM信号の周波数は約490Hzです。
Arduino's PWM frequency at about 500Hz
20k〜100kHz
を入力しなさいとある。
とりあえず完成
黄色ボタンを押すたびに、「ひも出し」「ひも巻き取り」「停止」
緑ボタンはタイマー時間設定。1時間単位。押すたびにモーターから音を出して操作を確認できる。
タイマー作動後は小鳥のさえずりっぽい音を出してさわやかに目覚める。
/* Curtains Timer */
#include <Debounce.h> // http://www.arduino.cc/playground/Code/Debounce
int FIN = 5;
int RIN = 6;
int LED = 13;
int SW_YELLOW = 3;
int SW_GREEN = 2;
Debounce sw_yellow = Debounce(20, SW_YELLOW);
Debounce sw_green = Debounce(20, SW_GREEN);
int motorMode = 0; // 0:STOP,1:right,2:left
int timerMode = 0;
int timerHour = 0; // 0:0FF, 1:1h ... 12:12h
int ledWait = 0; // blink interval.
unsigned long lastPushedMs = 0;
unsigned long alarmStartMs = 0;
unsigned long alarmStopMs = 0;
unsigned long motorStopMs = 0;
unsigned long MOTOR_RUN_DURATION_MS = 60000;
unsigned long SNOOZE_MS = 180000;
unsigned long WAIT_MS_PER_PUSH = 3600000;
void setup() {
int i;
Serial.begin(9600);
pinMode(FIN, OUTPUT);
pinMode(RIN, OUTPUT);
pinMode(SW_YELLOW, INPUT);
pinMode(SW_GREEN, INPUT);
digitalWrite(SW_YELLOW, HIGH); // pull-up
digitalWrite(SW_GREEN, HIGH); // pull-up
// boot blink & sound!!
for(i=0; i<3000; i++){
analogWrite(FIN, 255*1/5);
analogWrite(RIN, 0);
delayMicroseconds(-i/10+350);
analogWrite(FIN, 0);
analogWrite(RIN, 255*1/5);
delayMicroseconds(-i/10+350);
#define LED_WAIT 300
if(i%LED_WAIT==0){
if(i/LED_WAIT % 2 == 0){
digitalWrite(LED, HIGH);
}else{
digitalWrite(LED, LOW);
}
}
}
}
void loop(){
motor_loop();
timer_loop();
}
void motor_loop() {
if(sw_yellow.update() && sw_yellow.read()==LOW) {
motorMode = (motorMode+1) % 3;
motorStopMs = millis() + MOTOR_RUN_DURATION_MS;
}
switch(motorMode){
case 1:
analogWrite(FIN, 255*3/5);
analogWrite(RIN, 0);
break;
case 2:
analogWrite(FIN, 0);
analogWrite(RIN, 255*3/5);
break;
default:
analogWrite(FIN, 0);
analogWrite(RIN, 0);
break;
}
if((motorStopMs!=0) && (motorStopMs<millis())){
motorMode = 0;
motorStopMs = 0;
}
}
void timer_loop(){
int i;
int pushed = 0;
if(sw_green.update() && sw_green.read()==LOW){
pushed = 1;
lastPushedMs = millis();
}
if(timerMode==0){ // nop
ledWait = 300;
if(pushed){
motorBeep(100, 100);
motorBeep(150, 100);
motorBeep(200, 100);
timerMode = 1;
}
}else
if(timerMode==1){ // setting
if(pushed){
timerHour = (timerHour+1)%13;
int beepDelay = 600;
for(i=0; i<timerHour; i++){ beepDelay = beepDelay*20/23; };
motorBeep(beepDelay, 100);
if(timerHour==0){
delay(50);
motorBeep(beepDelay, 100);
}
//Serial.println(timerHour);
}
if((1<=timerHour) && (lastPushedMs+10000<millis())){
int beepDelay = 600*20/23;
for(i=0; i<timerHour; i++){
beepDelay = beepDelay*20/23;
motorBeep(beepDelay, 100);
delay(100);
}
alarmStartMs = millis() + timerHour*WAIT_MS_PER_PUSH;
//Serial.println(timerHour);
timerMode = 2; // goto waiting
}
ledWait = 0;
}else
if(timerMode==2){ // waiting
ledWait = 2000;
if(alarmStartMs<millis()){
for(i=0; i<10; i++){
delay(50);
motorBeep(100, 100);
}
alarmStopMs = millis() + MOTOR_RUN_DURATION_MS;
motorStopMs = 0;
motorMode = 2;
timerMode = 3; // goto alarm
}
//if(millis()%1000==0){ Serial.println(alarmStartMs-millis()); }
}else
if(timerMode==3){ // alarm!!
ledWait = 100;
if(alarmStopMs<millis()){
for(i=0; i<3; i++){
delay(50);
motorBeep(600, 100);
}
motorMode = 0;
timerMode = 4; // goto stop
}
//if(millis()%1000==0){ Serial.println(alarmStopMs-millis()); }
}else
if(timerMode==4){ // stop.
ledWait = 4000;
if(pushed){
motorBeep(700, 500);
}
if((millis()%SNOOZE_MS)==0){
for(i=10+random(10); 0<=i; i--){
cheep(10+random(50), 100+random(80), 10+random(10), 100+random(300));
}
}
}
// LED 0:OFF, 1+:Nms blink
digitalWrite(LED, LOW);
if(0<ledWait && (millis()/((ledWait+1)/2)%2)==0){
digitalWrite(LED, HIGH);
}
}
// beep from motor
void motorBeep(int beepDelay, int lenMs)
{
digitalWrite(LED, HIGH);
unsigned long breakMs = millis()+lenMs;
for(;;){
analogWrite(FIN, 255*1/5);
analogWrite(RIN, 0);
delayMicroseconds(beepDelay);
analogWrite(FIN, 0);
analogWrite(RIN, 255*1/5);
delayMicroseconds(beepDelay);
if(breakMs<millis()){ break; }
}
analogWrite(FIN, 0);
analogWrite(RIN, 0);
digitalWrite(LED, LOW);
}
// a cheeping little bird
void cheep(int start, int end, int sped, int dely)
{
int i;
for(i=start; i<end; i+=sped){
motorBeep(i, 10);
}
delay(dely);
}
(6)Arduino mega88
(TODO)
Arduino2009は他の実験でも使いたいので格安「Arduino mega88 250円」で置き換える。
最終更新:2009年04月19日 23:21