リバース連動で開閉する自作バックモニターですが、サーボモーターを使った1号機が思いのほか騒がしい為、ステップモーター(ステッピングモーター)に変更します。この2号機が、現在の最新状態です。
使用するステップモーター;28BYJ-48
ステップモーターは、低速ほどトルクがでます。
今回は低速作動で、さらに外部ギヤでも減速して使用するので、安価な28BYJ-48でも動くと考えて選択しました。
この28BYJ-48ですが、作動電圧が5Vと12Vの2種類あります。
はじめは5Vのものを使用してみましたがトルクに余裕がなかったために、12Vのものを採用しました。
外部減速用のギヤ(ドライブギヤとドリブンギヤ)は、28BYJ-48の出力軸径に合うものを市販品から見つけられず、やむなく壊れたプリンターから取り出したギヤを加工して使っています。
オートフリップダウンモニターのギヤ部
回路図
回路図は、Fritzingで作成しています。
右半分の回路は、ステップモーターとドライバーで、セットで安く入手できるので、自作してはいません。
左半分のArduino本体以外が、自作した回路です。
それでは、回路図の詳細について補足説明させていただきます!
Reverse Signal
車のギアをリバースに入れた時の信号で、具体的には後退灯の12Vを分岐してきています。
そのままだと12Vなので、抵抗3個とダイオード1個で5Vのデジタル信号にして、ArduinoのD10につないでいます。
Full Close SW
ステップモーターには位置情報がないのですが、モニターの現位置がわからないと、制御できません。
そのため、モニターを全閉した時に押される位置にプッシュスイッチをつけて、全閉するたびに位置情報をリセットするようにしています。
スイッチの状態を5Vのデジタル信号にするために、抵抗1個を使用して、ArduinoのD8につないでいます。
LED5
故障時のトラブルシュートが簡単になるように、モーターへの回転指令が出ているかどうかの確認用でつけておきました。
Arduinoを使った位置と速度管理
モニターが開く(降りる)方向は、モーターのステップ数だけで位置管理しています。
そのため、開いている途中でモニターの動きを強制的に止めると、中途半端に開いた状態でも全開だと誤認識して止まります。
全開検出スイッチを追加すれば回避できるのですが、そもそもモニターの自重が開き方向に働いているので、開く途中でモーターが脱調する確率は、0%に近いと考えられます。
開き方向はステップ数だけで位置管理して止める事にしました。
モニターが閉じる方向は、徐々にゆっくり閉まるようにしています。
動きに高級感を出しつつ、多少の外乱があったとしても徐々にトルクが強くなる効果でいつかは閉まることを狙っています。
モニターの動きがわかる動画をアップしました!
Arduino project #2 「リバースギヤ連動 オートフリップダウン バックモニター」Auto flip down rear view monitor
スケッチ
最後に、ご参考でスケッチを紹介しておきます。
int reversePin = 10;
int operationPin = 9;
int motororiginPin = 8;
int motorPin1 = 4;
int motorPin2 = 5;
int motorPin3 = 6;
int motorPin4 = 7;
int motorSpeed;
int count = 0;
int speedcontr = 0;
int countsperrev = 320;
int lookup[8] = {B01000, B01100, B00100, B00110, B00010, B00011, B00001, B01001};
unsigned long timeZero = millis();
boolean fullOpenning =false;
boolean fullClosing =false;
void setup() {
pinMode(reversePin,INPUT) ;
pinMode(operationPin,OUTPUT) ;
pinMode(motororiginPin,INPUT) ;
pinMode(motorPin1, OUTPUT);
pinMode(motorPin2, OUTPUT);
pinMode(motorPin3, OUTPUT);
pinMode(motorPin4, OUTPUT);
Serial.begin(9600);
}
void loop() {
if (digitalRead(reversePin) == HIGH) {
timeZero = millis();
fullClosing =false;
if(count < countsperrev ){
digitalWrite(operationPin, HIGH);
speedcontr = (1*count);
motorSpeed = 900;
clockwise();
count++;
} else {
digitalWrite(operationPin, LOW);
digitalWrite(motorPin1,LOW);
digitalWrite(motorPin2, LOW);
digitalWrite(motorPin3, LOW);
digitalWrite(motorPin4, LOW);
fullOpenning =true;
}
} else {
if (digitalRead(motororiginPin) == LOW) {
if (fullOpenning == true){
if (millis() - timeZero > 1000) {
digitalWrite(operationPin,HIGH);
if (count > 100){
motorSpeed = 1000;
anticlockwise();
count--;
} else {
speedcontr = (30*count);
motorSpeed = (4000-speedcontr);
anticlockwise();
count--;
}
} else {
digitalWrite(operationPin,HIGH);
}
} else if (fullClosing == true){
digitalWrite(operationPin, LOW);
digitalWrite(motorPin1,LOW);
digitalWrite(motorPin2, LOW);
digitalWrite(motorPin3, LOW);
digitalWrite(motorPin4, LOW);
} else {
if (millis() - timeZero > 1000) {
digitalWrite(operationPin,HIGH);
if (count > 100){
motorSpeed = 1000;
anticlockwise();
count--;
} else {
speedcontr = (5*count);
motorSpeed = (1500-speedcontr);
anticlockwise();
count--;
}
} else {
digitalWrite(operationPin,HIGH);
}
}
} else {
digitalWrite(operationPin, LOW);
digitalWrite(motorPin1,LOW);
digitalWrite(motorPin2, LOW);
digitalWrite(motorPin3, LOW);
digitalWrite(motorPin4, LOW);
count = 0;
fullOpenning =false;
fullClosing = true;
}
}
}
void anticlockwise()
{
for(int i = 0; i < 8; i++)
{
setOutput(i);
delayMicroseconds(motorSpeed);
}
}
void clockwise()
{
for(int i = 7; i >= 0; i--)
{
setOutput(i);
delayMicroseconds(motorSpeed);
}
}
void setOutput(int out)
{
digitalWrite(motorPin1, bitRead(lookup[out], 0));
digitalWrite(motorPin2, bitRead(lookup[out], 1));
digitalWrite(motorPin3, bitRead(lookup[out], 2));
digitalWrite(motorPin4, bitRead(lookup[out], 3));
}