PICマイコンとフルブリッジドライバL293Dを使って、ウォシュレットの水量調節用ステッピングモータを外部コントロールする回路を組み立てて来ましたが、ようやく完成し稼動開始しました。
ケース加工、組み込み、取り付けまでの流れです。
まず、基板を下ケースに固定します。ドリルで穴を開けてM3のビスナットで締め付けるだけ。配線の引き出し穴は、写真の右側に10mmφの穴を開けてグロメットを押し込んでします。
基板の固定が出来たら、上ケースをネジ穴位置にあわせておおよその開口位置を決めます。
開口位置の適当な所にドリルで大穴(10mmφ)を開けたところでハンドニプラ登場です。
ハンドニプラでがっちょんがっちょんと穴を広げていきます。楽勝で直線の出た四角穴が開いていきます。持つべきものは道具です。
こんな感じ。綺麗なものです。
ヤスリで最終の位置出しをして合わせます。
開口部分はアルミの切断面が銀色になっていますので、油性マジックで断面を黒く塗ります。これだけでぐっと見た目がよくなります。
さて、取り付けです。
電源はこのソレノイドバルブへの配線からもらう事にしました。DC20Vが来ています。ソレノイドへの供給なので電力的には余裕のはずです。
こんな感じにギボシを入れて電気を横取り。
ここでひとつ問題が。
モータはこの位置(C98253と書いてあるところの上)、
別の角度から見ると、この位置に付けるのですが、あわせてみるとどうもシャフトが長すぎるようです。壊れて取り外したモータと比較すると2mmくらい軸が長いことがわかりました。これではうまく取り付けられません。
ということで、モータ出力軸を2mm程度グラインダで削り落としました。
削るときにモータが結構熱くなったので樹脂のギアが入っていたらだめかもしれないと思いましたが、結果的にはなんともありませんでした。
ということでとりつけていきます。
モータへの配線5本と、電源2本(下の写真で筐体外部に引き出されている赤白の線)が必要です。
本体側の配線をします。熱収縮チューブでちょっとだけ見た目を綺麗にします。
この位置に大穴を開けて引き込む事にしました。
モータへのコネクタを接続し、電源を繋ぎます。
本体は両面テープで固定する事にします。
こんな感じ。
動作テストです。おしり洗浄のボタンを押すとソレノイドがONしますので同時に電源が入ります。
日ごろは切れている省エネ設計^^;
で、調整です。
水量調整のバルブはおおよそ8時方向から4時方向まで回転しますので、ステッピングモータもその範囲でまわるようにし、さらにその角を10分割して、ボタンを押す毎にステップするようにプログラムを書いています。
で、やってみると、0で最大水量、3でほぼ水が止まってしまうことがわかりました。回転角のうちの1/3位しか調整範囲は無いようです。
ということで、プログラムを書き換えます。これまで8時方向から4時方向までの240度を回転させるのに合計1500パルスを入れ、ボタンを押す毎に150パルス分ずつ動くように設定していたのですが、調整範囲がおよそ80度くらいということで、可動範囲を500パルス、ボタンを押す毎に50パルスずつ動くように書き換えました。また、回転方向をよく調べていなかったので最大水量のときに7セグが0を表示していたのですが、これも逆方向になるようにしました。最小水量で0、最大で9という具合です。
これらの変更を加えてPICに焼き込み、最終動作を確認して上ケースをネジ止め、完成となりました。しばらく使って様子を見てみる事にします。
最終のソースはこちら。
ちなみに、1相駆動から2相駆動に変更しています。(1相駆動の部分はコメントアウトしています)
*******************************************************
// UniPolar Stepping Motor Driver for 16F1827
// compiler: MPLAB XC8 Compiler
// 2013/06/01
// Configration
// RA0-4,6,7: 7segments LED control
// RB0: adjusting mode button (interrupt)
// RB1: power up button input (interrupt)
// RB2: power down button input (interrupt)
// RB3: enable
// RB4,5,6,7: OUTPUT to L293D
// Driving method: 1 phase
#include <xc.h>
// CONFIG1
#pragma config FOSC = INTOSC // Oscillator Selection (INTOSC oscillator: I/O function on CLKIN pin)
#pragma config WDTE = OFF // Watchdog Timer Enable (WDT disabled)
#pragma config PWRTE = ON // Power-up Timer Enable (PWRT enabled)
#pragma config MCLRE = OFF // MCLR Pin Function Select (MCLR/VPP pin function is digital input)
#pragma config CP = OFF // Flash Program Memory Code Protection (Program memory code protection is disabled)
#pragma config CPD = OFF // Data Memory Code Protection (Data memory code protection is disabled)
#pragma config BOREN = ON // Brown-out Reset Enable (Brown-out Reset enabled)
#pragma config CLKOUTEN = OFF // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin)
#pragma config IESO = ON // Internal/External Switchover (Internal/External Switchover mode is enabled)
#pragma config FCMEN = ON // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is enabled)
// CONFIG2
#pragma config WRT = OFF // Flash Memory Self-Write Protection (Write protection off)
#pragma config PLLEN = ON // PLL Enable (4x PLL enabled)
#pragma config STVREN = ON // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will cause a Reset)
#pragma config BORV = LO // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.)
#pragma config LVP = ON // Low-Voltage Programming Enable (Low-voltage programming enabled)
#define Pulseperiod 0 // 0<–long, 255<–short change here to change motor rotation speed
#define Step 50 // Number of steps per button push
#define PulseInterval 5// Step pulse interval for stepping motor in msec
#define _XTAL_FREQ 8000000 // definition for delay
__EEPROM_DATA(0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07); // Set initial value to EEPROM
char StepPosition=1; // increment or decrement by every rotation pulse
// according to the direction
int NumberOfStep=0; //Counts up to Step
char PowerLevel=0; // Power level: 0-9
void Flash7seg(void);
void CW(int StepNumber);
void CCW(int StepNumber);
void main()
{
OSCCON=0b01110010; // internal clock 8MHz
ANSELA=0b00000000; // No analog for PORTA
ANSELB=0b00000000; // No analog for PORTB
TRISA=0b00100000; // Set I/O according to configuration
TRISB=0b00000111; // Set I/O according to configuration
WPUA=0b00100000; // Weak pull-up for RA5 enabled
WPUB=0b00000111; // Weak pull-up for RB0,1,2 enabled
OPTION_REG=0b00000000; // Weak pull-up enabled
// OPTION_REG=0b00000111; // TMR0 prescaler 1:256 & 8MHz clock then 128usec
// TMR0=Pulseperiod; // Number of TMR0 counter
// T0IF=0 ; // Reset TMR0 flag
// T0IE=1; // Enable TMR0 interruption
PORTA=0b00000000; // reset out put
PORTB=0b00000000; // reset out put
// GIE=1; // Global interruption enable
Flash7seg();
while(1)
{
if(RB1==0) // CW
{
if(RB0==1)
{
if(eeprom_read(0x00)>0) //Check if the power level is in lower limit
{
eeprom_write(0x00,eeprom_read(0x00)-1); // Write new level
RB3=1; // Motor driver enable
CW(Step); // Turn clockwise for defined steps
RB3=0; // Motor driver disable
Flash7seg(); // Change power level indicator
}
}
if(RB0==0)
{
RB3=1; // Motor driver enable
CW(50); // Turn clockwise for defined steps
RB3=0; // Motor driver disable
Flash7seg(); // Change power level indicator
}
}
if(RB2==0) // CCW
{
if(RB0==1)
{
if(eeprom_read(0x00)<9) //Check if the power level is in upper limit
{
eeprom_write(0x00,eeprom_read(0x00)+1); // Write new level
RB3=1; // Motor driver enable
CCW(Step); // Turn counter-clockwise for defined steps
RB3=0; // Motor driver disable
Flash7seg(); // Change power level indicator
}
}
if(RB0==0)
{
RB3=1; // Motor driver enable
CCW(50); // Turn counter-clockwise for defined steps
RB3=0; // Motor driver disable
Flash7seg(); // Change power level indicator
}
}
}
}
void CW(int StepNumber)
{
while(NumberOfStep<=StepNumber)
{
switch(StepPosition)
{
// case 1:
// PORTB = 0b00011000;
// break;
// case 2:
// PORTB = 0b00101000; // CW:00100000 CCW:01000000
// break;
// case 3:
// PORTB = 0b10001000;
// break;
// case 4:
// PORTB = 0b01001000; // CW:01000000 CCW:00100000
// StepPosition=0;
// break;
// double phase drive
case 1:
PORTB = 0b00111000;
break;
case 2:
PORTB = 0b10101000; // CW:00100000 CCW:01000000
break;
case 3:
PORTB = 0b11001000;
break;
case 4:
PORTB = 0b01011000; // CW:01000000 CCW:00100000
StepPosition=0;
break;
}
NumberOfStep++;
StepPosition++;
__delay_ms(PulseInterval);
}
NumberOfStep=0; // Reset NumberOfStep
}
void CCW(int StepNumber)
{
while(NumberOfStep<=StepNumber)
{
switch(StepPosition)
{
// case 1:
// PORTB = 0b00011000;
// break;
// case 2:
// PORTB = 0b01001000; // CW:00100000 CCW:01000000
// break;
// case 3:
// PORTB = 0b10001000;
// break;
// case 4:
// PORTB = 0b00101000; // CW:01000000 CCW:00100000
// StepPosition=0;
// break;
// double phase drive
case 1:
PORTB = 0b01011000;
break;
case 2:
PORTB = 0b11001000; // CW:00100000 CCW:01000000
break;
case 3:
PORTB = 0b10101000;
break;
case 4:
PORTB = 0b00111000; // CW:01000000 CCW:00100000
StepPosition=0;
break;
}
NumberOfStep++;
StepPosition++;
__delay_ms(PulseInterval);
}
NumberOfStep=0; // Reset NumberOfStep
}
void Flash7seg(void)
{
switch(eeprom_read(0x00))
{
case 9:
PORTA = 0b00001000;
break;
case 8:
PORTA = 0b00011111;
break;
case 7:
PORTA = 0b01010000;
break;
case 6:
PORTA = 0b00010100;
break;
case 5:
PORTA = 0b00000111;
break;
case 4:
PORTA = 0b10000100;
break;
case 3:
PORTA = 0b10000000;
break;
case 2:
PORTA = 0b00011110;
break;
case 1:
PORTA = 0b00000000;
break;
case 0:
PORTA = 0b00000100;
break;
}
}
なかなか面白く実用的な電子工作でした。
コメント