2019年7月28日日曜日

CO2レーザー その19(Z軸可動化Ⅵ:Limit SW)

CO2レーザー「Z軸可動化」
とうとうⅥ(六)になってしまいました。
ホントは、ⅤでLimit SWまで行き着くはずだったのですが
ATTINY85に邪魔され、かなり疲労しています(-_-;)
CNCやったりして頭を冷やして
さ~て、Limit Switchです。

一応、完成まで、単体ATTINY85で進めていくつもりです。

モデル設計の時に、宝箱で見つけた小さなスイッチを
基板ごとカットして使うことにしていました。
ペン型ノコギリで、必要な部分だけを切り出していきます。
2つの基板付きLimit SWが採れました!
たまには、こういう作業もいいです。
下側のLimit SWをマウントにM2ボルトでつけます。
Limit SWを付けました
下側は、うまいこと当たります。
拡大
Limit SWの棒に当たる、上側のポッチが小さすぎたな~
Fusion360をあまり拡大して設計すると、大きさの感覚が薄れますね~
下側のLimit SWの設計時のモデルです。
上側は、Mortorマウントに取り付けます。
が、スライドロッドが設計よりも短かったので
最上部まで上げてもLimit SWに当たりません(T_T)
上側移動架にLimit SWが当たるポッチを付けていますが
約2mm隙間が空いてます。
そこをSW側に肉盛して厚みを持たせることにします。
上側Limit SWの設計時のモデルです。
これでは、ちゃんと当たっていたのです。
長い方のスライドロッドが1本しかなく、少し短いのを使ってたのを
すっかり忘れておりました(-_-;)
エポキシパテを使います。
60分で硬化し始め、6時間で実用硬度とあります。
粘土のように形成できるので重宝します。
2mm程の肉盛りと幅を広げました!

丁度いい具合の高さになりました。
下側Limit SWのポッチも小さくて心もとなかったので
少し肉盛りと幅広げしました。
配線をしていきます。
リード線は、PS2マウスのだと思うこれ!
今は、6芯あればいいのですが、9芯
後で何か拡張できるでしょう!
コネクタは、P2.5(上側)とP2.0(下側)を持ってますが
下の小さい方を使うことにします。
ハンダ付けしました!
が、スミチューブ(別名:ヒシチューブ、熱収縮チューブ)を忘れた(-_-;)
ので、ホットメルト(別名:ホットボンド)で固めておきます^^;
コネクタのメスの方にpinをカシメます。
ちょっと線が細いので、数本失敗(T_T)
ハウジングに入れました。
このブロックでは、線を短めにして雄コネクタを付けています。
モデルの時に線処理を考えとかねばな~
なんて思っておりましたが、
思ってただけだったので、うまく処理できません(-_-;)
実は、エアホースもどう引き回そうか決めてないのです。
そこから長い線(黒線)で制御回路まで引いていきます。
ダイニングテーブルで実験中なので
すぐに退避できるよう、こんなまな板に乗せてやっております(-_-;)
Limit SWに当たるポッチを肉盛りした時に
一度、分解したので、
再度組み立てると上向きが重くなっています。
調整が非常にデリケートですね~
リードスクリューをM3ネジタイプにしたらいいのですが
このステッピングモーター、軸が一体になっていて
簡単には、M3ネジにできなかったのです。
だいぶ調整しましたが、最初より、ちと重くなったので
モーター電流を増やします。
ADC 1本で3つのKEYをスキャンするようにして
A4988のENABLEを制御できるようになったので
無操作0.5sec後にモーター電流OFFにしてます。
安心して電流増やせます^^;
0.24A/2phaseでもなんとか動いてくれますが、
0.331A/2phaseにしておきます。
で、Limit SW位置を調整します。
このSWは、Normal OPENのみです。
テスターで導通を確認しながら丁度いい位置でボルトを締めます。

では、
Limit SWのテスト
上下でLimit SWがCLOSE(LOW)したら
1mm(27step)戻して、モーターOFFして、3sec休止
わかっているのに、定番の「=」「==」をミスりましたが(-_-;)
無地動きました!
何度も往復してるとモーターがほんのり温かくなってます。
***CO2_Z-Axis_Move_H***
全部省略(-_-;)
**********

次は、HOMING動作です。
HOMEボタン押すと、
「上昇してLimit SW CLOSEしたら、Limit SW OPENまで下げて、
1sec休止(操作受付OFF)」
ATTINY85と格闘したので、やっとスケッチ通りに動いてくれます。
やっぱCNC使ったので頭が冷えたのかも?

***CO2_Z-Axis_Move_J・・・悪くないけどまだ未完成***
//*************************************************************
// CO2 Laser Cutter Z-Axis Controller
// DigiSpark (ATTINY85)
// 抵抗分割して3-KEYをADCで検出
// PB1(Step):470KΩ+Diode(Pluse 立下りなまり対策)
// PB4(LimitSW):4.7KΩ程度のPullUp必須(内部Pull-Up不安定対策)
// 1 PUSHで1mm以上移動するので
// 0.1sec以上の同一KEY押下でSTEP信号を出し、1STEP毎に0.1secのDelayを入れる。
// 0.3sec以上の同一KEY押下でNo Delayして連続移動にする。
// Limit SW 0.5mm(13step)戻って2sec 停止
// Homing 上昇してLimit SW CLOSEで停止、Limit SW OPENまで下がる、1sec停止 

// 注意 see https://digistump.com/wiki/digispark/quickref
// Digital 2 is analog (ADC channel) 1 = pin7 今回は、これ
// Digital 3 is analog (ADC channel) 3 = pin2
// Digital 4 is analog (ADC channel) 2 = pin3
// Digital 5 is analog (ADC channel) 0 = pin5
//*************************************************************

#define Direction 0 // PB0 for Direction HIGH: UP、LOW: DOWN 
#define Step 1 // PB1 for Step Pluse
//#define KEY_Detect 2 // これは間違い!! ADC ch2 = PB4 = pin3
#define KEY_Detect 1 // ADC ch1 = PB2 = pin7
#define nENABLE 3 // PB3 for nENABLE 
#define LimitSW 4 // PB4 for Limit-SW(Upper & Lower)
#define nRESET 5 // PB5 for nRESET

int DontMoveCount = 0; // 非動作期間カウント
int MaxDontMoveCount = 500; // これで約0.5秒
short ContenuousMode = 0; // 0:シングル動作、1:連続動作(未使用)
#define None_Key 4
#define UP_Key 1
#define DOWN_Key 2
#define HOME_Key 3
short KeyPosition = None_Key; //  今押したKEY 4:None Key、1:UP、2:DOWN、3:Home
short last_KeyPosition = None_Key; // 前押したKEY 4:None Key、1:UP、2:DOWN、3:Home
int SameKeyCount = 0; // 同一KEY押下時間カウント
short WaitCount = 0;   // Single Step移動時の無効化時間カウント
short WaitCountIncrease = 10; // 1LOOPの時間が約10msecになるようにする

void setup() {
  // initialize
  pinMode(Direction, OUTPUT);       // DIRECTION
  pinMode(Step, OUTPUT);       // STEP
  pinMode(KEY_Detect, INPUT); // ADC ch1(PB2)でKEY検出
  pinMode(nENABLE, OUTPUT); // nENABLE
  pinMode(LimitSW, INPUT); // LimitSW ("_PULLUP"は効かない)
  digitalWrite(LimitSW, HIGH); // 一応これで内蔵PullUpをActiveにする
  pinMode(nRESET, INPUT);        // Reset(固定だが覚書)
  // 初期値設定
  digitalWrite(Direction, HIGH); // UP
  digitalWrite(Step, LOW);
  digitalWrite(nENABLE, HIGH);  // Motor Disable
  analogReference(DEFAULT);  // Reference = VCC(5V) (念の為)
}


void loop() {
  KeyDetect(); // ADCのKEY状態をScan
  MoveProcess(); // KEY押下時間判定して移動処理
}

//**********************************************
// 抵抗分割のKEYは、ADCで検出(1pinキー回路)
// UP  : 0.0V(0~1.0V)
// DOWN: 1.76V±20% (1.4~2.2V)
// HOME: 3.0V±20% (2.4~3.6V) ・・・ 最上部に移動
// INPUT: 5V ・・・ ADC: 1024 なので
// UP  : 0 to 205
// DOWN: 286 to 451
// HOME: 491 to 738
//**********************************************

void KeyDetect() {
   // 0 以上 ~ 205以下:UP
  if ( (0 <= analogRead(KEY_Detect)) && (analogRead(KEY_Detect) <= 205)) {
    KeyPosition = UP_Key;
  }
  
  // 286 以上 ~ 451以下:DOWN
  if ( (286 <= analogRead(KEY_Detect)) && (analogRead(KEY_Detect) <= 451)) {
    KeyPosition = DOWN_Key;
  }

  // 491 以上 ~ 738以下:HOME ・・・ Limit SW 直前まで上がる
  if ( (491 <= analogRead(KEY_Detect)) && (analogRead(KEY_Detect) <= 738)) {
    KeyPosition = HOME_Key;
  }

   // KEYを押してない時は、5V(VCC)になる
   // 一定カウント超えたらnENABLEをHIGHにしてモーター電流停止
   // SW ALL OFF 739~1023
  if ((739 <= analogRead(KEY_Detect)) && (analogRead(KEY_Detect) <= 1023)) {
    KeyPosition = None_Key;
  }
}


void MoveProcess(){
    if (last_KeyPosition == KeyPosition) { // 前KEYと同一KEY押下の場合
     SameKeyCount = SameKeyCount + WaitCountIncrease; // ① 1loop分増加
     // 同一Positionに最低閾値~300msec定位していればシングルstep移動命令
     // 同一KEY押下が約100~300msecであれば、シングルstep動作
       if ( 1000 <= SameKeyCount && SameKeyCount < 3000 ) {
          if ( WaitCount == 0 ) { // KEY変化の最初
            ContenuousMode = 0;  // 連続モードOFF(未使用)
            MoveControl();  // 
            WaitCount = WaitCount + WaitCountIncrease;  // 1loop分増加
          } else { // 2回めに同一KEY検出したら290 Wait
          // 一定期間(300msec弱)不感時間を設ける為のカウンタ
            WaitCount = WaitCount + WaitCountIncrease;  // 1loop分増加
              if( WaitCount > 2900) {
                 WaitCount = 0;
              }
          }
          // KEY押下時間SameCountが100未満の場合、①のカウントUPのみ
        }
      // 同一Positionに約300msec以上定位していれば連続移動命令
        if (SameKeyCount >= 3000) {
          // 一定間隔で出力する連続モード
          ContenuousMode = 1; //(未使用)
          MoveControl(); // delayなしでMoveする
        }
     } else { // 前KEYと異なるKEY押下の場合
    // 初めてのKeyScan時の初期化処理
    // ノイズも含め全ての検出は、最初にここを通る
       last_KeyPosition = KeyPosition;
       SameKeyCount = 0;
       WaitCount = 0;
    }
}


void MoveControl() {
    switch ( KeyPosition ) {  // KEYに応じて処理
    case 1:  // UP
      DontMoveCount = 0;
      // UP処理
      // ここにLimit SW判定
         if ( digitalRead(LimitSW) == LOW ) {
           digitalWrite(Direction, LOW); // DOWN方向
             for (short i=0; i<=13; i++){
               SendStepPluse(); // 13step ≒0.5mm後退
             }
            digitalWrite(nENABLE, HIGH); // ENABLEをDISABLE、MORTOR OFF
            delay(2000); // 2sec停止
          }
      digitalWrite(nENABLE, LOW); // ENABLEをACTIVEする
      digitalWrite(Direction, HIGH);
      SendStepPluse();
    break;
    case 2:  // DOWN
      DontMoveCount = 0;
      // DOWN処理
      // ここにLimit SW判定
         if ( digitalRead(LimitSW) == LOW ) {
           digitalWrite(Direction, HIGH); // UP方向
             for (short i=0; i<=13; i++){
               SendStepPluse(); // 13step ≒0.5mm後退
             }
           digitalWrite(nENABLE, HIGH); // ENABLEをDISABLE、MORTOR OFF
           delay(2000); // 2sec停止
         }
      digitalWrite(nENABLE, LOW); // ENABLEをACTIVEする
      digitalWrite(Direction, LOW);
      SendStepPluse();
    break;
    case 3:  // HOME
      // HOMING処理・・・上側Limit SWまでUP
      DontMoveCount = 0;
      digitalWrite(nENABLE, LOW); // ENABLEをACTIVEする
      digitalWrite(Direction, HIGH);
      while (digitalRead(LimitSW) == HIGH) { // Limit SWに当たるまで
         SendStepPluse();
      }
      // Limit SWが働かないちょっと下まで下げる必要がある
      // DOWNにしてLimitSW:LOWで止める
      // Limit SW ONしたらOFFまで戻す
      if (digitalRead(LimitSW) == LOW) {
          digitalWrite(Direction, LOW); // DIRECTION DOWNへ反転
      //    ギリギリでとまりすぎるかな?
          do { // 最低1stepは戻したいのでdo
            SendStepPluse();
          } while (digitalRead(LimitSW) == LOW);
      }
      digitalWrite(nENABLE, HIGH); // ENABLEをDISABLE、MORTOR OFF
      delay(1000); // HOMEの後は、1sec停止
    break;
    case 4:  // None KEY(KEY押下なし)
      // nENABLEをDISABLEしてMOTOR OFF処理
      // 非動作期間カウントUP処理
      DontMoveCount = ++DontMoveCount;
      if ( DontMoveCount >= MaxDontMoveCount ) {
        digitalWrite(nENABLE, HIGH); // ENABLEをDISABLEする
        DontMoveCount = 0; // カウントリセット
      }
    break;
  }
}


//**********************************************
// STEP信号を1Step Pluse送出 F500固定
// 20step/回転、3mmリード=ピッチ、1/4 Microstepなので
// 20 ÷ 1/4 ÷ 3 = 26.667step/mm
// F500 = 500mm/min
// 26.667 x 500 = 13333step/min(1分間)
// 1秒間のSTEP数が、A4988のStepパルス周期になるので
// 13333 ÷ 60 = 222.22step/sec = 222.22Hz = 4.5 msec(HIGH/LOWの1周期)
// 4.5msec ÷ 2 = 2250μsec
// 1step=1/26.667mm=0.0375mm
//**********************************************
void SendStepPluse() {
  digitalWrite(1, HIGH);
  delayMicroseconds(2250);
  digitalWrite(1, LOW);
  delayMicroseconds(2250);
}
**********************

ここらで動画を
・黄ボタン:UP
・赤ボタン:DOWN
・緑ボタン:HOMING
・左上LED:5V Power
・上LED   :DIRECTION(点灯:下向き)
・下LED   :ENABLE(点灯:MOTOR ON)
最初、黄ボタンを約0.3sec以上押してると、連続移動UPになり
Limit SWに当たると0.5mm戻って、2秒間操作無効になります。
次に、赤ボタンを押してる間、連続移動DOWNして
Limit SWに当たると0.5mm戻って、2秒間操作無効になります。
最後に、緑ボタン押すと、HOMING(鏡筒が最も収縮)です。
Limit SW ONまでUPして、Limit SW OFFまで戻り、
1秒間操作無効になります。
短押し(約0.1~0.3sec)は、1step移動ですが、
動きがわからないので、撮ってません。
ここまでくるのに随分長い道のりでした~^^;
ステッピングモーターのDC電源の表示
0.346Aは、モーター全体の平均
0.346Aavr/2phaseなので、0.173Aavr/phase
Peakは、0.25A近いかも
数往復では、モーターは、温かくなる程度なので大丈夫でしょう。
パーツ選定の時に調べた、たぶん、定格:0.2Aavr/phaseだと思います。
短押し:0.0375mm(1step)だと、ほとんど動きがわからないので、
0.5mm(13step)にします。
つまり、KEY押し時間
・0.1sec未満:無反応
・0.1~0.3sec:13step(≒0.5mm)移動
・0.36sec以上:連続移動(F500)

。。。。。無事に動きました。
ATTINY85版が完成です!\(^o^)/
ボードタイプのDigisparkで動作するかは、不明です(-_-;)
***CO2_Z-Axis_Move_K・・・やっと完成\(^o^)/***
//*************************************************************
// CO2 Laser Cutter Z-Axis Controller
// For ATTINY85単体(Digisparkボードで動作するか不明)
// 抵抗分割して3-KEYをADCで検出
// PB1(Step):470KΩ+Diode(Pluse 立下りなまり対策)
// PB4(LimitSW):4.7KΩ程度のPullUp必須(内部Pull-Up不安定対策)
// Delayなしでは、1 PUSHで1mm以上移動するので
// 0.1sec以上の同一KEY押下でSTEP信号を出し、1STEP毎にDelayを入れる。
// 0.3sec以上の同一KEY押下でNo Delayして連続移動にする。
// Limit SW 0.5mm(13step)戻って2sec 停止 (Limit SW:Normal Open)
// Homing:上昇してLimit SW CLOSEで停止、Limit SW OPENまで下がる、1sec停止
// 短押(0.1~0.3sec)  1step ⇒ 13step(0.4875mm≒0.5mm)に変更
//
// 注意 see https://digistump.com/wiki/digispark/quickref
// Digital 2 is analog (ADC channel) 1 = pin7 今回は、これ
// Digital 3 is analog (ADC channel) 3 = pin2
// Digital 4 is analog (ADC channel) 2 = pin3
// Digital 5 is analog (ADC channel) 0 = pin5
//**************************************************************

#define Direction 0 // PB0 for Direction HIGH: UP、LOW: DOWN 

#define Step 1 // PB1 for Step Pluse
//#define KEY_Detect 2 // 注意:これは間違い!! ADC ch2 = PB4 = pin3
#define KEY_Detect 1 // ADC ch1 = PB2 = pin7
#define nENABLE 3 // PB3 for nENABLE 
#define LimitSW 4 // PB4 for Limit-SW(Upper & Lower)
#define nRESET 5 // PB5 for nRESET

int DontMoveCount = 0; // 非動作期間カウント

int MaxDontMoveCount = 500; // これで約0.5秒
short ContenuousMode = 0; // 0:シングル動作、1:連続動作(未使用)
#define None_Key 4
#define UP_Key 1
#define DOWN_Key 2
#define HOME_Key 3
short KeyPosition = None_Key; //  今押したKEY 4:None Key、1:UP、2:DOWN、3:Home
short last_KeyPosition = None_Key; // 前押したKEY 4:None Key、1:UP、2:DOWN、3:Home
int SameKeyCount = 0; // 同一KEY押下時間カウント
short WaitCount = 0;   // Single Step移動時の無効化時間カウント
short WaitCountIncrease = 10; // 1LOOPの時間が約10msecになるようにする

void setup() {

  // initialize
  pinMode(Direction, OUTPUT);   // DIRECTION
  pinMode(Step, OUTPUT);         // STEP
  pinMode(KEY_Detect, INPUT);  // ADC ch1(PB2)でKEY検出
  pinMode(nENABLE, OUTPUT);  // nENABLE
  pinMode(LimitSW, INPUT);       // LimitSW ("_PULLUP"は効かない)
  digitalWrite(LimitSW, HIGH);    // 一応これで内蔵PullUpをActiveにする
  pinMode(nRESET, INPUT);       // Reset(固定だが覚書)
  // 初期値設定
  digitalWrite(Direction, HIGH);  // UP
  digitalWrite(Step, LOW);
  digitalWrite(nENABLE, HIGH);  // Motor Disable
  analogReference(DEFAULT);    // Reference = Vcc(5V) (念の為)
}


void loop() {
  KeyDetect();     // ADCのKEY状態をScan
  MoveProcess(); // KEY押下時間判定して移動&Limit処理
}

//**********************************************

// 抵抗分割のKEYは、ADCで検出(1pinキー回路)
// UP  : 0.0V(0~1.0V)
// DOWN: 1.76V±20% (1.4~2.2V)
// HOME: 3.0V±20% (2.4~3.6V) ・・・ 最上部に移動
// INPUT: 5V ・・・ ADC: 1023 なので
// UP  : 0 to 205
// DOWN: 286 to 451
// HOME: 491 to 738
// No KEY:739 to 1023
//**********************************************

void KeyDetect() {

   // 0 以上 ~ 205以下:UP
  if ( (0 <= analogRead(KEY_Detect)) && (analogRead(KEY_Detect) <= 205)) {
    KeyPosition = UP_Key;
  }
  
  // 286 以上 ~ 451以下:DOWN
  if ( (286 <= analogRead(KEY_Detect)) && (analogRead(KEY_Detect) <= 451)) {
    KeyPosition = DOWN_Key;
  }

  // 491 以上 ~ 738以下:HOME ・・・ Limit SW 直前まで上がる

  if ( (491 <= analogRead(KEY_Detect)) && (analogRead(KEY_Detect) <= 738)) {
    KeyPosition = HOME_Key;
  }

   // KEYを押してない時は、5V(VCC)になる

   // 一定カウント超えたらA4988のENABLEをHIGHにしてモーター電流停止
   // SW ALL OFF 739~1023
  if ((739 <= analogRead(KEY_Detect)) && (analogRead(KEY_Detect) <= 1023)) {
    KeyPosition = None_Key;
  }
}


void MoveProcess(){

    if (last_KeyPosition == KeyPosition) { // 前KEYと同一KEY押下の場合
     SameKeyCount = SameKeyCount + WaitCountIncrease; // ① 1loop分増加
     // 同一Positionに最低閾値~300msec定位していればシングルstep移動命令
     // 同一KEY押下が約100~300msecであれば、シングルstep動作
       if ( 1000 <= SameKeyCount && SameKeyCount < 3000 ) {
          if ( WaitCount == 0 ) { // KEY変化の最初
            ContenuousMode = 0;  // シングル移動モード
            MoveControl();  // 
            WaitCount = WaitCount + WaitCountIncrease;  // 1loop分増加
          } else { // 2回めに同一KEY検出したら290msec Wait
          // 一定期間(300msec弱)不感時間を設ける為のカウンタ
            WaitCount = WaitCount + WaitCountIncrease;  // 1loop分増加
              if( WaitCount > 2900) {
                 WaitCount = 0;
              }
          }
          // KEY押下時間SameCount < 1000 の場合、①のカウントUPのみ
        }
      // 同一Positionに約300msec以上定位していれば連続移動命令
        if (SameKeyCount >= 3000) {
          // Step Pluseを出し続ける連続モード
          ContenuousMode = 1; // 連続移動モード
          MoveControl(); // delayなしでMoveする
        }
     } else { // 前KEYと異なるKEY押下の場合
    // 初めてのKeyScan時の初期化処理
    // ノイズも含め全ての検出は、最初にここを通る
       last_KeyPosition = KeyPosition;
       SameKeyCount = 0;
       WaitCount = 0;
    }
}


void MoveControl() {

    switch ( KeyPosition ) {  // KEYに応じて処理
    case 1:  // UP
      DontMoveCount = 0;
      // UP処理
      // ここにLimit SW判定
         if ( digitalRead(LimitSW) == LOW ) {
           digitalWrite(Direction, LOW); // DOWN方向
             for (short i=0; i<=13; i++){
               SendStepPluse(); // 13step ≒0.5mm後退
             }
            digitalWrite(nENABLE, HIGH); // ENABLEをDISABLE、MORTOR OFF
            delay(2000); // 2sec停止
          }
      digitalWrite(nENABLE, LOW); // ENABLEをACTIVEする
      digitalWrite(Direction, HIGH);
      SendStepPluse();
    break;
    case 2:  // DOWN
      DontMoveCount = 0;
      // DOWN処理
      // ここにLimit SW判定
         if ( digitalRead(LimitSW) == LOW ) {
           digitalWrite(Direction, HIGH); // UP方向
             for (short i=0; i<=13; i++){
               SendStepPluse(); // 13step ≒0.5mm後退
             }
           digitalWrite(nENABLE, HIGH); // ENABLEをDISABLE、MORTOR OFF
           delay(2000); // 2sec停止
         }
      digitalWrite(nENABLE, LOW); // ENABLEをACTIVEする
      digitalWrite(Direction, LOW);
      SendStepPluse();
    break;
    case 3:  // HOME
      // HOMING処理・・・上側Limit SWまでUP
      DontMoveCount = 0;
      digitalWrite(nENABLE, LOW); // ENABLEをACTIVEする
      digitalWrite(Direction, HIGH);
      while (digitalRead(LimitSW) == HIGH) { // Limit SWに当たるまで
         SendStepPluse();
      }
      // Limit SWが働かないちょっと下まで下げる必要がある
      // DOWNにしてLimitSW:LOWで止める
      // Limit SW ONしたらOFFまで戻す
      if (digitalRead(LimitSW) == LOW) {
          digitalWrite(Direction, LOW); // DIRECTION DOWNへ反転
      // Limit SW OFFまで戻す
          do { // 最低1stepは戻したいのでdo
            SendStepPluse();
          } while (digitalRead(LimitSW) == LOW);
      }
      digitalWrite(nENABLE, HIGH); // ENABLEをDISABLE、MORTOR OFF
      delay(1000); // HOMEの後は、1sec停止
    break;
    case 4:  // None KEY(KEY押下なし)
      // nENABLEをDISABLEしてMOTOR OFF処理
      // 非動作期間カウントUP処理
      DontMoveCount = ++DontMoveCount;
      if ( DontMoveCount >= MaxDontMoveCount ) {
        digitalWrite(nENABLE, HIGH); // ENABLEをDISABLEする
        DontMoveCount = 0; // カウントリセット
      }
    break;
  }
}


//**********************************************

// STEP信号を1Step Pluse送出 F500固定
// 20step/回転、3mmリード=ピッチ、1/4 Microstepなので
// 20 ÷ 1/4 ÷ 3 = 26.667step/mm、F500 = 500mm/min
// 26.667 x 500 = 13333step/min(1分間)
// 1秒間のSTEP数が、A4988のStepパルス周期になるので
// 13333 ÷ 60 = 222.22step/sec = 222.22Hz = 4.5 msec(HIGH/LOWの1周期)
// 4.5msec ÷ 2 = 2250μsec
// 1step=1/26.667mm=0.0375mm
//**********************************************
void SendStepPluse() {
  if (ContenuousMode == 0) {
    // シングル移動モード:13step(≒0.5mm)
    // 移動後、 MoveProcess()で300msec弱、操作無効にしている
     for (short i=0; i<=13; i++){
       digitalWrite(1, HIGH);
       delayMicroseconds(2250);
       digitalWrite(1, LOW);
       delayMicroseconds(2250);
     }
  }
  else { // 連続移動モード
     // MoveProcess()でDelayしない、KEY押下中、連続してPluse送出
     digitalWrite(1, HIGH);
     delayMicroseconds(2250);
     digitalWrite(1, LOW);
     delayMicroseconds(2250);    
  }
}
***

フラッシュメモリ:28%
グローバル変数(RAM):26バイト(512バイト中)
最終テストの実体配線図は、これ!
ATTINY85(図では、右下が1pin)は、
・Pin1(RESET)  :OPEN
・Pin2(PB3-OUT):ENABLE(5Vから470Ω+LED)
・Pin3(PB4-IN)   :Limit SW Normal Open(4.7KΩ PULL-UP)
・Pin4(GND)     :GND
・Pin5(PB0-OUT):DIRECTION
・Pin6(PB1-OUT):STEP(GND間に470KΩ+Diode)
・Pin7(ADC1-IN) :KEY用
・Pin8(VCC)      :5V
一応、回路図も作っておきます。
PCBを切削して基板起こすわけではないのですが、
久しぶりにEAGLE V.8.5.2(Updateしてません)で!
A4988のシンボルは、中にステッピングモーターがあって変です。
一時しのぎなので、ユニバーサル基板に組む予定です^^;
***2019.7.31 修正***
78L05の最低入出力間電圧:2V なので、IN:6.2V、OUT:5Vはダメです。
*************
次は、PIC12F1822への換装にいくかな
MPLAB Xをちょっと開いて数年前のコードを見ると
うぉ~~っ!全部呪文に見える(-_-;)
ほぼ忘れていますね~
PICを思い出すには、ちょうど良さそうですが、
どうしようかな~

2019年7月27日土曜日

小型工作機CNC2418 その75(アクリルの横穴&縦穴加工)

梅雨が上がって、真夏日になってくると
月間で「扇風機の修理」が一気に1位に出てきます。
ふと見ると、7月15日だけで閲覧数 5362回!
普段は、多くても 500弱なのです。
特定のページへの閲覧ではなく、全体を満遍なくって感じです。
ちょっと怖い気もします。
さて、今回は、CO2レーザーカッターのパーツではありません。
あるパーツ製作依頼が来たものです。

sltファイルが送られてきたので、Fusion360に読み込みます。
久々のアップロードなので、一応、手順を記録!
左上のデータパネルから[アップロード]
この画面で、stlファイルをD&Dすると
ファイル名が入るので、右下の[アップロード]します。
アップロードが進んでいって
[完了]になれば、[閉じる]で、この画面を閉じます。
左のデータパネルに通常のアイコンができているので開きます。
が、何故か未だに、stlファイルは、寸法が10倍になるので
0.1倍に縮小します。
縮小すると、原点からかなりズレた位置になるので
どこかの角を原点に合わせて移動します。
まずは、
[修正]-[メッシュ]-[メッシュからBRep]して
採寸します。
厚み:8mm
幅:28mm
高さ:20mm
寸法が、ピッタリ数値なので、スケッチは、起こし易いです。
側面図
上面図
モデルは、ほどなく完成!
これ、sunhokeyのi4 X軸のベルト固定具がアクリル製で折れ易いので
アルミにしたいとのことなのです。

ん~ん、穴が、上からと横からだあ!
加工の位置決めには、頭を一捻りしないといけません。
さ~て、横穴と縦穴をどうしようか?
8mm厚のアルミを持ってないのと、いきなりやるのは大変なので
まずは、アクリルでテストした方がよさそうです。
小さいので固定も難しそうです。
で、最初の切り出しは、当然、この面です。
問題は、この2つの縦穴をどう位置決めして開けるかです。
マーティーのCNC2418は、単純な3軸なので、横穴は開れません。
上の形状を切り出した後、ステージから一旦外さないといけないのです。
ん~ん、ん~ん。。。ひとつ閃きました!
上のがピッタリ入る穴をMDFに開けて、
CNCのWORK座標を変えずに(RESETとかせずに)
そこに加工するものを入れれば、
MDFを加工したWORK座標に合わせられるはずです。
まあ、0.1mm程度は、穴位置が狂うかもですが
実際にアクリルでやってみることにします。
モデルを横に倒して
CAMで原点を指定するために、スケッチを描いて表示しておきます。
左端の赤ぽい点を原点にするつもりです。
CAMに行って
セットアップでストックサイズと原点を指定します。
アクリルなのでエンドミルは、
PVC用の先端Flat・1-Flute・スパイラル(HUHAO製)
径1.5mmの1LX3 1512を使います。
溶着しやすいプラスチックを低速回転でザクザク切削してくれます。
特に塩ビとか柔らかめの素材に向いているようです。

この時の切削条件を使います。
結構、強気の時に考えた表なのです(-_-;)
1.5mmでアクリルなので
3000rpm(S300)、F300、深さ0.6mmでいきます。
***
設定表:<PVC・アクリル・ABS・ポリエチレン>
 エンドミル:スパイラル・タイプ(Flute:1or2)必須
D[mm]0.60.81.01.21.52.02.5 3.175
 切削送り速度 
Vf
[mm/min] 
 2000rpm PVC 100 130 160 180 200 230 240240
 3000rpm アクリル
ABS
150190230270300340360360
 4000rpm PE190260310350410460480480
深さ[mm] 0.3 0.4 0.4 0.5 0.6 0.6 0.70.7
***

[2D]-[輪郭]
[送りと速度]
下の輪郭を選択して
タブは、ちょっと多めにします。
穴は、同じ1.5mmミル、[2D]-[2Dポケット]です。
シミュレーションします。
よさそうです。
順番は、穴 ⇒ 輪郭 で、一緒にGCode吐き出します。
Geeetech I3 ProBのベッドをアルミに交換したので
そのベッド、8mm厚の黒い215 x 215mm位のが余っているので
ステージにセットします。
穴の方は、ちょっと危なっかしかったけど、なんとか貫通しました。
が、
輪郭が~~、切削屑が全く飛び散りません。
溶着しかかっています。
このまま進めると、ミルに絡まって、最悪、折れます。
PCでのマウス操作だと、こうゆう時とても焦りますが、
幸い、この時付けた、外部SWで黄色ボタンで素早く停止できました。
上からRSET、ABORT、RESUME、PAUSE、レーザー12V です。
深さ 0.6mmずつは、やりすぎました(T_T)
Fusion360に戻って、0.3mmでGCode作り直して再開。
Feedは、びびって50%、F90で開始です(-_-;)
これだけの切削屑も集塵機で吸い取れるので溶着はしてないです。
動画で!
集塵機はかなり弱めです。
まあ、いい感じにサクサクは削れてるようです。
完了後もキレイに吸い取れました。
エンドミルにも絡まっていません。
今まで使ってたアクリル板と種類が違うのかなあ
記憶が定かではありませんが、ちょっと粘っこい感じもします。
終始、全てFeed 50%のF90でやりました(-_-;)
タブの高さが低すぎて0.38mmだったか
最初のZゼロ合わせが低すぎたのか
振動で薄いタブが折れてグラついていたので
最後の一周は指で抑えながら(´-﹏-`;)
裏側
タブが見えてるので、Zゼロ調整は、合ってたようで
薄すぎて振動で全部折れたようです(T_T)
まあ、キレイにできました!
2個の縦穴は、これからです。
次は、この6mm厚のMDFでベッドを作ります。
原点は、この辺りでいいかな
一発目は、3.175mmミルでザクッと掘って
MDFなんで
深さ4mmの穴を深さ1mmずつ、F640なんて強気にしていたが、やりすぎ
削れないことは、ないのですが、振動が大き過ぎ
S800、F420、最大切削ピッチ0.6mm、深さ0.5mmに修正
更にビビってFeed 30%(F192)に落として
3.175mmミルで切削してコーナーがその半径のRになっているので
0.6mmに換えて輪郭をコーナーをなぞりR0.3にします。

これも、深さ0.6mmずつでやりすぎてたので
F260の30%(F78)に落として優しくいきます。
最後の1周はキレイにしたいのでFeed 10%、F26
位置合わせ用の台座ができました。
クリアランス0.1mmですが
かなりキチキチで、固定具がいらないくらいですが
切削中に傾く恐れがあるので、更に固定します。
縦穴のΦ3.5は、先の1.5mmと同じタイプの
PVC用の先端Flat・1-Flute・スパイラル(HUHAO製)
径3.175mmの1LX3 22を使います。
これじゃないと、ミルが短くて、スピンドルが下の方まで降りてきて
切削するパーツの右側の高い所に当たるのです。

[2D]-[輪郭]
S300(≒300rpm)、0.6mmずつ、F120です。

いざ、切削開始すると
深さ0.6mmずつですが、穴開けなのにF120で下げていました(-_-;)
最初の1ターンがミルが折れそうな程だったので
急いでFeed 10%まで落として、F12
溶着はしませんでしたが、2分23秒で
今回は、大幅下げばかり、どうも頭の調子が悪いです(-_-;)
無事完了!
固定方法ももう少し工夫しないといけません。
右側の高い所だけを固定しているので、あまり締めすぎると
左側が浮いて傾く可能性もあります。
パーツが逆さまに入るベッドにしとけば、まっ平らにできたのですが...
テスト品は、一応できましたが、
元々、オリジナルパーツ(sunhokey社のi4 X軸のベルト固定具)が
アクリル製で折れ易いので、アルミにしたいということで、
4つ必要なのです。
果たして、8mm厚ものアルミで切削できるだろうか?
まともに切削できないだろうから、何か方策を考えないといけません。
その前に材料調達!
到着まで1~2周間掛かりそうです。
首を長~~~くして待っていただくしかなさそうですm(_ _)m