2021年1月25日 星期一

網購的詐術

跨境買中國大陸的貨, 常常會遇到缺件或到貨數量不足的問題, 若是能退款的就還好, 有的商家會要求下次再補, 若是同意下次回購, 無疑助長他的騙術施與另一買家, 這種商家聲譽掃地, 管理不善, 刻意製造下次回購的機會, 真是很要不得的舉動.

2021年1月4日 星期一

安裝 bCNC 用來遙控 Grbl

官網 https://github.com/vlachoudis/bCNC 是一個用  python 語言寫的控制軟體, 須事先安裝 python 的  Tkinter 模組, 之後才能執行 bCNC, 利用 python 的套件管理程式  pip 直接安裝 bCNC 模組:

      sudo apt-get install python-tk
      pip install --upgrade bCNC

接著沒意外的話就能執行 bCNC 模組

      python -m bCNC

打開文件後, 序列阜(Port)可以使用 USB Serial 轉接線, 開啟裝置

     /dev/ttyUSB0

或是 telnet 協定來連接:

     socket://esp8266.local:23

    使用 esp8266 寫一個內建 telnet server 並利用 software Serial port 摹擬出一個序列阜(swSerial)與 ATmega328P 的序列裝置對接(swRX <-> TX, swTX<->RX) , 實作出 telnet  協定後,就能打造出一個無線遙控平台, 底下是用 Arduino 方式寫的 telnet server 原始碼, 所摹擬的 UART 使用 GPIO4(swRX), GPIO5(swTX), 並結合上一篇的 AVRISP :

#include <SoftwareSerial.h>
#include <ESP8266AVRISP.h>
ESP8266AVRISP avrISP(328, 16);// AVRISP: TCP port 328, RESET: GPIO16


WiFiServer telnetServer(23); // Telnet: TCP port 23
WiFiClient telTerm;
SoftwareSerial swSerial;

void setup( ) {
  Serial.begin(115200);

     // ...

      swSerial.begin(19200, SWSERIAL_8N1, 4, 5); //swRX:GPIO4, swTX: GPIO5


      telnetServer.begin( );
      telnetServer.setNoDelay(true);


      avrISP.setReset(false); // let the AVR run
      avrISP.begin( );

      MDNS.begin("esp8266");

}

void loop( ) { 
    MDNS.update( );
    static AVRISPState_t  last_state = AVRISP_STATE_IDLE;
    AVRISPState_t new_state = avrISP.update( );
    if (last_state != new_state) {     
      switch (new_state) {
        case AVRISP_STATE_IDLE: Serial.printf("[AVRISP] idle\n");
            break;         
        case AVRISP_STATE_PENDING:Serial.printf("[AVRISP] pending\n");
            break;         
        case AVRISP_STATE_ACTIVE:
            Serial.printf("[AVRISP] programming\n");
            break;
        default: break;         
      }     
      last_state = new_state;
    } 
    if (last_state != AVRISP_STATE_IDLE) avrISP.serve( ); 

    // ...
    static char txtBuffer[1024];

   if (telnetServer.hasClient( )) {
      Serial.printf("Accept new connection\n");
      if (telTerm.connected( )) telTerm.stop( ); // stop old connection      
      telTerm = telnetServer.available( );
      telTerm.flush( );
      swSerial.flush( );
    }
        
    if (telTerm.connected( )) {
      int length = swSerial.available( );
      if (length > 0) {// swSerial -> telTerm
        for(int n = 0; n < length ; n ++) txtBuffer[n] = swSerial.read( );
        telTerm.write(txtBuffer, length);
      }
      int n = 0;
      length = telTerm.available( );
      while(length -- > 0) {// telTerm -> swSerial
        int ch = telTerm.read( );
        Serial.printf((31 < ch && ch < 127 || ch==0xd || ch==0xa) ? "%c" : "_%02x_", ch);
        if (ch == 0x0d) continue;// drop useless CR
        txtBuffer[n ++] = ch;
        if (n < sizeof(txtBuffer)) {
          txtBuffer[n] = 0;
          if ((strstr(txtBuffer,"\xff\xfb")||strstr(txtBuffer,"\xff\xfd")) && ch > 0) break;// drop
          if (strstr(txtBuffer,"exit!") || strstr(txtBuffer,"quit!")) {
            telTerm.stop( );
            break;
          }
        }       
        if (ch==0x0a || ch=='?' || n>=80) {
          if (ch != 0x0a || n > 1) swSerial.write((const uint8_t *)txtBuffer, n);                 
          break;
        }
      }
  }// bridge packet between termial and swSerial

}

    實驗發現 software uart 當 baud rate 設定 115200 時, 會掉封包或是有誤碼的情形, 改成 19200 後就能改善, 且能順利與 bCNC 連接. 記得同時要更改 grbl/config.h 內的 baud rate 設定(將 #define BAUD_RATE  115200 改成 #define BAUD_RATE  19200), 重新編譯後再用上一篇所說 avrdude 重新燒錄. 這樣就不用放一台 PC 在 GRBL 控制器的旁邊了, 一個內建軔體燒錄器的 GRBL 無線遙控器順利誕生.

    Arduino Uno 燒錄了 GRBL 軔體到主控板後, 接上 CNC shield 板子後就能直接控制步進馬達(可支援四組), CNC shield 上步進馬達驅動器的電源與主控板電源是分開的,  我使用筆電(Notebook)的 19V 直流電直接供應, 為了簡化, 使用單一電源, 同時供應主板電源, 我將 Arduino Uno 上的1117 (LDO, 用來將輸入 Vin 轉 5V 電源) 的輸入腳(第3支腳) 翹開, 也可以直接拔掉, 上網買一個, 大約 10 幾塊台幣而已, 可耐 24V 電壓的降壓型切換式電源模組(Buck Switching  Mode DC to DC regulator) 作替換, 輸出先調好成 DC 5V 才焊接上去, 之後主板就能接上 19V 的電源,最後焊一條粗的電源線將 19V 與 CNC shiled 的步進電源相連就可, 最後弄個轉接板(AVRISP + UART)讓 ESP8266 直接吃 AVRISP 上頭的 5V 電源, 整個電源路徑示意圖:

        DC 19V  Vin    +-> Ardunio Uno -> CNC shiled

                                   |->  Buck  DC to DC -> 5V   -> AVRISP ->  ESP8266 PCB

                                   xxx -> 1117 -> 5V 

    步進馬達的推動力(應該說是扭力)與所供應的電流成正比, CNC shield  可以接上 4 組 A4988 或是 DRV8825 模組 , 輸出電流可以透過模組上面的可變電阻來調整, 以 A4988 來說, 電流調整公式是:

        Imax  = Vref / (8 * Rsense)

    上述 Rsense 是模組上面的精密電阻(共有兩顆, 分別偵測 A/B 線圈電流用), 電阻上壓差(注意: 並不是 Vref)上限是  0.5 V, 而 A4988 最大輸出上限是 2 A(注意: 並不是底下公式的 Imax), 我看模組上 Rsense 用的是 R100, 也就是等於 0.1 Ohm, 因此

        Imax = Vref / 0.8 = 1.25 * Vref   A

    其中規格書上寫到  Vref 可調區間是 0 到 4 V, 也就是 Imax 可調區間是 0 ~ 5 A, 但受 A4988 輸出最大 2 A 的限制, 所以使用 Rsense 等於 0.1 Ohm 的 A4988, 其 Vref 最大也只能調到 1.6 V, 當 Vref 電壓調整到 0.5 V時, 最大驅動電流約 0.625 A, 這還得要看步進馬達是否能承受, 42 步進馬達應該沒什問題,  3 個軸的推動, 除了 Z 軸因為要承受重力負載的關係, 當返回向上時需要比較大的拉力, 網路上 DIY CNC 時常用的是 T8 全牙螺桿來傳動, 有分 2mm 或是 8mm 行程, 兩者比較來說, 8mm 行程的 T8 螺桿傳動時雖跑的比較快, 但因螺紋坡度較陡峭, 相對就需要較大的推/拉力, 而 2mm 行程的 T8 螺桿就顯的較省力, 我除了買了 2mm 與 8mm 行程的 T8 螺桿外, 還另外買了 1.26mm  行程的 M8 全牙螺桿,  用 4 爪 M8 螺帽塞進 11 mm 孔徑的木塊裏, 用來帶動 X 軸, 經實驗相互比較, 整體來說, 傳動正常, 只是 M8 螺桿轉動時, 噪音大了點, 這是摩擦力振動所產生的噪音. 目前 X 軸使用 1.26mm 行程的 M8 螺桿, Y 軸使用 8mm 行程的 T8 螺桿, Z 軸使用 2mm 行程的 T8 螺桿, A4988 全都設定為 16 micro steps, 因此需要修改 grbl/defaults.h 的設定:

  #define DEFAULT_X_STEPS_PER_MM 2540.0 // 16 microsteps, 200 steps per revolution/1.26mm = 2540 usteps/mm
  #define DEFAULT_Y_STEPS_PER_MM  400.0 // 16 microsteps, 200 steps per revolution/8mm = 400 usteps/mm
  #define DEFAULT_Z_STEPS_PER_MM 1600.0 // 16 microsteps, 200 steps per revolution/2mm = 1600 usteps/mm

    有時候行進速率太高或是摩擦力太大導致步進馬達失步, 這時可以調整軸的最大行進速率, 或是干脆換一棵扭力較強的步進馬達,  若是允許,  還能調大電流(A4988 最大只能推到 2 A) , 我目前 Y 軸使用 8mm 行程的關係, 所以使用了強力步進馬達, 速率也就調的高一點, 以下是我目前 grbl/defaults.h 的設定:

  #define DEFAULT_X_MAX_RATE 1000.0
  #define DEFAULT_Y_MAX_RATE 4000.0
  #define DEFAULT_Z_MAX_RATE  250.0

    關於主(旋)軸(spindle)的控制, 可以用 telnet 終端機先下一個命令 $$ , 列出所有設定值, 其中 $30 指示目前最大轉速(rpm)的數值 (內定 default 設定值是 1000 rpm), 對應的是當 PWM  輸出 5V 的數值. 透過 G-CODE 代碼 M3 S1000 設定順時鐘(CW)的轉速為 1000 rpm, 或是 M4  S1000 設定逆時鐘(CCW)的轉速為 1000 rpm, 當設定為 0 rpm 就相當於關閉主軸, 也就是說輸出等於 0V, 用三用電表量測 CNC Shielle 板子上標註 End Stop 的  Z+ 或 Z- (實際上 Z+ 與 Z- 是短路的)排針, 附帶一提的是, Z+ 與 Z- 在舊版的 Grbl 是拿來當作讀取 Z 軸限位開關(Limit  switch)之用, 目前在 Grbl 1.1 版本中, 為了支援 VARIABLE_SPINDLE, 已將讀取 Z 軸限位開關改到標註著 SpnEn 的位置. 改變轉速(S0 ~ S1000) 就可分別量測到 0 ~ 5V 的數值. 因此只要利用 Z+(或 Z-)腳位,  接上電阻及電容濾波器再用電晶體去推動繼電器(relay), 就能當作電源的開(ON)與關(OFF),  達成讓軟體自動控制主軸的目的.

    最後說一下摩擦係數極低的滑塊與光軸, 使用它的目的, 除了承重並維持上下及左右之間的平衡外, 還能減少行進間的摩擦力, 摩擦力相當於法向(垂直)力*摩擦係數. 而螺桿則是專門負責傳動, 兩根光軸除了要保持平行外, 和傳動螺桿間也須同時保持平行, 當鎖上螺絲時更要注意, 光軸與螺桿之間要避免拉力, 否則將會增加行進間的摩擦力, 因此光軸與螺桿定位孔以及滑塊鎖上負載的螺絲孔位置都必須垂直與精準,  這樣滑動時就不會有阻礙, 馬達推動也才不會卡卡的引起很大振動, 甚至造成像是空襲警報的噪音, 尤其是當振動久了, 很容易造成連軸螺絲脫落, 導致傳動軸空轉, 因此有必要用膠帶將連軸螺絲處多纏繞幾圈, 避免它鬆脫.

簡單 c 程式碼, 根據五行八卦相生相剋推斷吉凶

#include "stdio.h" // 五行: //               木2 //      水1           火3 //         金0     土4 // // 先天八卦 vs 五行 //                    ...