Arduino自動カーテンオープン目覚まし時計

「Arduino自動カーテンオープン目覚まし時計」の編集履歴(バックアップ)一覧はこちら

Arduino自動カーテンオープン目覚まし時計」(2009/04/19 (日) 23:21:34) の最新版変更点

追加された行は緑色になります。

削除された行は赤色になります。

*計画 朝になったら自動でカーテンを開ける目覚まし時計を作りたい。 カーテンの端っこにひもを引っかけて朝になったらタイマーが作動してひもを巻き取りカーテンが開くという仕組み。 **材料 -[[Arduino2009>http://www.amazon.co.jp/gp/redirect.html?ie=UTF8&location=http%3A%2F%2Fwww.amazon.co.jp%2Fs%3Fie%3DUTF8%26x%3D12%26ref%255F%3Dnb%255Fss%255Fgw%26y%3D28%26field-keywords%3Darduino%26url%3Dsearch-alias%253Daps&tag=arduino-22&linkCode=ur2&camp=247&creative=7399]] -[[モータードライバ BD6211F>http://www.switch-science.com/trac/wiki/BD62xx-Basic]] ←いただきもの -[[6速ギヤボックスHE>http://www.amazon.co.jp/gp/product/B00061HIEY?tag=arduino-22]] -リアルタイムクロック -ブレッドボード -ひも&フック(カーテンを引っ張る) -円柱ゴム(ひもを巻き取る) -木の板&ねじ -抵抗とかコンデンサとか配線材とか **消費電流 RE-260 http://www.mabuchi-motor.co.jp/motorize/branch/b_0100.html 適正電圧適正負荷で700mA 負荷によって変わるだろうから動作させながら実測する! **[[6速ギヤボックスHE>http://www.amazon.co.jp/gp/product/B00061HIEY?tag=arduino-22]] 広いギヤ比に組み替えられるのでとりあえずこれにした。 クラッチギアが付いているので大きい負荷がかかっても少し安心。 **完成品は -mega88 Arduino内蔵クロックで動かす。 -過電流で電源を止めるやつをつける。ポリスイッチ? **電源 -開発時はUSB 5V -ACアダプタ -5V or 3V http://www.switch-science.com/trac/wiki/BD62xx-Basic モーターの定格電圧が信号系(マイコン)の電源電圧よりも低い場合は困ってしまいます。 モーターによっては、PWMで一定のデューティよりも上げないように注意すれば大丈夫な場合があります。 arduinoは3Vで動くのか? -モータとArduinoの電源が同じでOK? **リアルタイムクロック -秋月の時計IC -バッテリバックアップしたい。 **ユーザインターフェイス -正回転/逆回転ボタン -タイマー時刻の設定/ロータリエンコーダ? -7セグ時計表示 **巻き取り終了の検出 マイクでクラッチの音? 一定の秒数の作動でよい? *製作 **(1)ざっと組み立て -ギアボックス -巻き取り部取り付け -ギアボックス&ブレッドボードを板に固定 -Arduinoを固定 -モータドライバにピン取り付け #image(http://www15.atwiki.jp/arduino/?cmd=upload&act=open&page=Arduino%E8%87%AA%E5%8B%95%E3%82%AB%E3%83%BC%E3%83%86%E3%83%B3%E3%82%AA%E3%83%BC%E3%83%97%E3%83%B3%E7%9B%AE%E8%A6%9A%E3%81%BE%E3%81%97%E6%99%82%E8%A8%88&file=P4180153.jpg) **(2)モータードライバの実験(2009/4/18) -正転/逆転を実験 -スピード&パワーを確認 -消費電流を確認 #video(http://www.youtube.com/watch?v=EwlVnZzOdwA) スイッチサイエンスさんのスケッチをちょっと改造で動作OK。 http://www.switch-science.com/trac/wiki/BD62xx-Basic 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 を繰り返す。 ***ノイズ? たぶんモーターからのノイズのせいでシリアル通信が途中でとぎれてしまう。 まともにデバッグできないと困るので対策が必要かもしれない。 http://www.picfun.com/motorframe.html モーターの端子と金属ケースの間にコンデンサをいれるといいらしい。 **(3)リアルタイムクロック確認(2009/4/19) http://nekosan0.bake-neko.net/connection_rtc.html nekosanのコードでOK。 よく考えたら毎日同じ時間に作動させる必要はなくて、「6時間後に作動」でいいわけだからRTCいらないや。 プログラムも簡単だ。内蔵RCで誤差はどれぐらいか?外部クリスタルつけたら誤差はどれくらい? **(4)時計表示(2009/4/19) 7セグ2桁で作動までの残り時間を出せばいい。上の桁が時間、下の桁が10分単位で十分。 いや、もっと簡単にLEDの点滅回数でいい。5回点滅なら5時間。 **(5)モーターから音を出す。 普通にモーターを回すときでもPWMの周波数で微妙に音が出てしまう。 てことは、適当にメロディーになるようにモーターに信号を与えたら・・・ 成功! スピーカーなしでBEEP音によるフィードバックが可能になった。 **ArduinoのPWM周波数 http://www.musashinodenpa.com/arduino/ref/index.php?f=0&pos=1921 によると PWM信号の周波数は約490Hzです。 http://www.arduino.cc/en/Tutorial/PWM には Arduino's PWM frequency at about 500Hz とある。 しかし、http://www.rohm.co.jp/products/databook/motor/pdf/bd621x_series-j.pdf には 20k〜100kHz を入力しなさいとある。 *とりあえず完成 #video(http://www.youtube.com/watch?v=DSfe-K2h21Q) 黄色ボタンを押すたびに、「ひも出し」「ひも巻き取り」「停止」 緑ボタンはタイマー時間設定。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円」で置き換える。
*計画 朝になったら自動でカーテンを開ける目覚まし時計を作りたい。 カーテンの端っこにひもを引っかけて朝になったらタイマーが作動してひもを巻き取りカーテンが開くという仕組み。 **材料 -[[Arduino2009>http://www.amazon.co.jp/gp/redirect.html?ie=UTF8&location=http%3A%2F%2Fwww.amazon.co.jp%2Fs%3Fie%3DUTF8%26x%3D12%26ref%255F%3Dnb%255Fss%255Fgw%26y%3D28%26field-keywords%3Darduino%26url%3Dsearch-alias%253Daps&tag=arduino-22&linkCode=ur2&camp=247&creative=7399]] -[[モータードライバ BD6211F>http://www.switch-science.com/trac/wiki/BD62xx-Basic]] ←いただきもの -[[6速ギヤボックスHE>http://www.amazon.co.jp/gp/product/B00061HIEY?tag=arduino-22]] -リアルタイムクロック -ブレッドボード -ひも&フック(カーテンを引っ張る) -円柱ゴム(ひもを巻き取る) -木の板&ねじ -抵抗とかコンデンサとか配線材とか **消費電流 RE-260 http://www.mabuchi-motor.co.jp/motorize/branch/b_0100.html 適正電圧適正負荷で700mA 負荷によって変わるだろうから動作させながら実測する! **[[6速ギヤボックスHE>http://www.amazon.co.jp/gp/product/B00061HIEY?tag=arduino-22]] 広いギヤ比に組み替えられるのでとりあえずこれにした。 クラッチギアが付いているので大きい負荷がかかっても少し安心。 **完成品は -mega88 Arduino内蔵クロックで動かす。 -過電流で電源を止めるやつをつける。ポリスイッチ? **電源 -開発時はUSB 5V -ACアダプタ -5V or 3V http://www.switch-science.com/trac/wiki/BD62xx-Basic モーターの定格電圧が信号系(マイコン)の電源電圧よりも低い場合は困ってしまいます。 モーターによっては、PWMで一定のデューティよりも上げないように注意すれば大丈夫な場合があります。 arduinoは3Vで動くのか? -モータとArduinoの電源が同じでOK? **リアルタイムクロック -秋月の時計IC -バッテリバックアップしたい。 **ユーザインターフェイス -正回転/逆回転ボタン -タイマー時刻の設定/ロータリエンコーダ? -7セグ時計表示 **巻き取り終了の検出 マイクでクラッチの音? 一定の秒数の作動でよい? *製作 **(1)ざっと組み立て -ギアボックス -巻き取り部取り付け -ギアボックス&ブレッドボードを板に固定 -Arduinoを固定 -モータドライバにピン取り付け #image(http://www15.atwiki.jp/arduino/?cmd=upload&act=open&page=Arduino%E8%87%AA%E5%8B%95%E3%82%AB%E3%83%BC%E3%83%86%E3%83%B3%E3%82%AA%E3%83%BC%E3%83%97%E3%83%B3%E7%9B%AE%E8%A6%9A%E3%81%BE%E3%81%97%E6%99%82%E8%A8%88&file=P4180153.jpg) **(2)モータードライバの実験(2009/4/18) -正転/逆転を実験 -スピード&パワーを確認 -消費電流を確認 #video(http://www.youtube.com/watch?v=EwlVnZzOdwA) スイッチサイエンスさんのスケッチをちょっと改造で動作OK。 http://www.switch-science.com/trac/wiki/BD62xx-Basic 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 を繰り返す。 ***ノイズ? たぶんモーターからのノイズのせいでシリアル通信が途中でとぎれてしまう。 まともにデバッグできないと困るので対策が必要かもしれない。 http://www.picfun.com/motorframe.html モーターの端子と金属ケースの間にコンデンサをいれるといいらしい。 **(3)リアルタイムクロック確認(2009/4/19) http://nekosan0.bake-neko.net/connection_rtc.html nekosanのコードでOK。 よく考えたら毎日同じ時間に作動させる必要はなくて、「6時間後に作動」でいいわけだからRTCいらないや。 プログラムも簡単だ。内蔵RCで誤差はどれぐらいか?外部クリスタルつけたら誤差はどれくらい? **(4)時計表示(2009/4/19) 7セグ2桁で作動までの残り時間を出せばいい。上の桁が時間、下の桁が10分単位で十分。 いや、もっと簡単にLEDの点滅回数でいい。5回点滅なら5時間。 **(5)モーターから音を出す。 普通にモーターを回すときでもPWMの周波数で微妙に音が出てしまう。 てことは、適当にメロディーになるようにモーターに信号を与えたら・・・ 成功! スピーカーなしでBEEP音によるフィードバックが可能になった。 ***ArduinoのPWM周波数 http://www.musashinodenpa.com/arduino/ref/index.php?f=0&pos=1921 によると PWM信号の周波数は約490Hzです。 http://www.arduino.cc/en/Tutorial/PWM には Arduino's PWM frequency at about 500Hz とある。 しかし、http://www.rohm.co.jp/products/databook/motor/pdf/bd621x_series-j.pdf には 20k〜100kHz を入力しなさいとある。 *とりあえず完成 #video(http://www.youtube.com/watch?v=DSfe-K2h21Q) 黄色ボタンを押すたびに、「ひも出し」「ひも巻き取り」「停止」 緑ボタンはタイマー時間設定。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円」で置き換える。

表示オプション

横に並べて表示:
変化行の前後のみ表示:
ツールボックス

下から選んでください:

新しいページを作成する
ヘルプ / FAQ もご覧ください。