2020年5月30日 星期六

理解 Arduino 運作方式

參考資料:
1. https://medium.com/home-wireless/use-visual-studio-code-for-arduino-2d0cf4c1760b
2. https://tttapa.github.io/ESP8266/Chap01%20-%20ESP8266.html


Arduino 用的是 c/c++ 語言來開發韌體(firmware), Arduino 的主程式碼通稱為 sketch (例如副檔名是 .ino 的 app.ino), 至於 c 語言的主程式進入點是 main( ), Arduino 的 sketch 實際將它分成 setup( ) 及 loop( ) 兩部份, setup( ) 只會執行一次, loop( ) 則會不斷重複執行, 也就是說 sketch 可以看成是在 c 語言 main( ) 裡會呼叫執行的兩道副程式:
void main( ) {
     setup( );
     while( true )  loop( );
}

在 linux 底下要開發 Arduino, 須下載 arduino SDK, 目前最新版本是 1.8.12:
https://www.arduino.cc/download_handler.php?f=/arduino-1.8.12-linux64.tar.xz
將它解壓縮到指定目錄 (ex. /home/mint/Downloads/arduino-1.8.12), 例如
cd /home/mint/Downloads
tar -xvf  arduino-1.8.12-linux64.tar.xz

若要用 vscode 開發 Arduino, 首先要安裝 Arduino 插件(Extensions), 接著在 vscode 開啟 Settings 設定環境變數,  搜尋 Arduino:Path, 將上述目錄例如 /home/mint/Downloads/arduino-1.8.12 填入, 如果要開發 ESP8266 需要到 Settings 再搜尋 arduino.additionalUrls, 點進去編輯 settings.json , 在 arduino.additionalUrls 欄位填入 "https://arduino.esp8266.com/stable/package_esp8266com_index.json", 像是這樣:
{
    "arduino.enableUSBDetection": false,
    "arduino.path": "/home/mint/Downloads/arduino-1.8.12",
    "workbench.startupEditor": "newUntitledFile",
    "arduino.additionalUrls": "https://arduino.esp8266.com/stable/package_esp8266com_index.json"
}

之後在命令列 View -> Command Palette (或快捷鍵 F1) 搜尋 Arduino 就能看到一堆如同在 Arduino IDE 上可以使用的 cli 命令. 不過剛開始時要先開啟一個專案夾, 並在 View -> Command Palette 選擇 Arduino:Initialize 跑一遍, 初始化一個 Arduino 開發環境, 接著像是 Board Manager, Board Config, Select Serial Port , Library Manager 才能開始使用, 在 Board Manager 可以安裝開發板的 SDK, 例如搜尋 ESP8266 接著安裝, 程式就會安裝到  ~/.arduino15/packages 目錄裡面, 在 Board Config 可以直接去更改開發板用的 SOC, 在 Select Serial Port 可以改變作業系統序列裝置的虛擬位置, 根據選擇也會相對應改變 arduino.json 裡面 board, port 及 configuration 的內容, 至於 Library Manager 可以安裝社群上已經寫好的程式庫, 下載的程式庫, 將會放在目錄  ~/Arduino/libraries 裡面.

以下是修改 .vscode/arduino.json 及 .vscode/c_cpp_properties.json 的檔案內容, 例如:
# arduino.json
{
    "sketch": "app.ino",
    "output": "./build",
    "port": "/dev/ttyUSB0",
    "board": "esp8266:esp8266:d1",
    "configuration": "xtal=80,vt=flash,exception=legacy,ssl=all,eesz=4M2M,ip=lm2f,dbg=Disabled,lvl=None____,wipe=none,baud=921600"
}
上面輸出目錄  output 可以加速後續的 compiler 時間, 可以自行指定到快速區, sketch 就是主程式

# c_cpp_properties.json
{
    "configurations": [
        {
            "name": "Linux",
            "includePath": [
                "${workspaceRoot}",
                "/home/mint/.arduino15/packages/esp8266/tools/**",
                "/home/mint/.arduino15/packages/esp8266/hardware/esp8266/2.7.1/**",
                "/home/mint/Arduino/libraries"
            ],
            "forcedInclude":[ ],
            "defines": ["USBCON"],
            "compilerPath": "/usr/bin/gcc",
            "cStandard": "c11",
            "cppStandard": "c++17",
            "intelliSenseMode": "clang-x64"
        }
    ],
    "version": 4
}
上面 defines 的 USBCON 是支援讓作業系統可以打開序列終端機(Serial port console), 到此設定完成後, vscode 版的 Arduino IDE 應該就能正常運作了. 一個超簡單運行在 ESP8266 上的 http 伺服器範例:
// app.ino
#include "ESP8266WiFi.h"
#include <ESP8266WebServer.h>
char str[2000];
char placeHolder[] = {"<html><head><meta charset='utf-8'></head><body>it works: %ld</body></html>"};
ESP8266WebServer http(80);
void setup( ) {
  const bool softAP    = false;
  const char* ssid     = "myAP";
  const char* password = "myPW";
  Serial.begin(115200);
  if (softAP) {
    WiFi.softAP(ssid, password);
    Serial.println(WiFi.softAPIP( ));
  } else {
    Serial.println("Link to wifi ap to get ip address");
    WiFi.begin(ssid, password);
    while (WiFi.status() != WL_CONNECTED) {
      delay(1000);
      Serial.print(".");
    }
    Serial.println(WiFi.localIP( ));
  }
  http.on("/", [ ]( ) {
    sprintf(str, placeHolder, millis( ));
    http.send(200, "text/html", str);
  });
  http.onNotFound( [ ]( ){
    http.send(404, "text/plain", "404: Not found");
  });
  http.begin( );
}

void loop( ) {
  http.handleClient( );
}


在 vscode 下方狀態列有個插頭的符號可以開/關序列終端機, 為了透過序列阜與開發板作溝通, 在 linux 上可以針對撥接群組 dialout 添加使用者 mint 來賦予使用權限:
sudo  usermod -a  -G  dialout  mint

重新開機讓它生效, 最後在 vscode 右上方中間的磚牆符號可以驗證並編譯 sketch 程式碼的完整性, 其左邊注滿容器的符號則是編譯 sketch 主程式後就直接上傳到開發板運行.


後記 ESP8266 GPIO:
1. 總共17個3.3V的GPIO, 最高承受到3.6V, 電流驅動能力最高12mA, D0~D15內有提升(pull up)電阻, 透過呼叫 pinMode(gpio#, INPUT_PULLUP) 就能減少外掛提升電阻, 但要注意 GPIO0, GPIO2, GPIO15 帶有 bootstrapping 功能, 很有可能外加的電阻使得內建的高提升電阻值而失效,甚至造成輸入邏輯的準位判斷異常, 至於 GPIO16 則是內建下拉(pull down)電阻.
    GPIO 0(D3): Boot SPI, 開發板通常會外加提升電阻, 見下表
    GPIO 1(TX): UART TX0
    GPIO 2(D4): Boot SDIO, 開發板通常會外加提升電阻, 見下表
    GPIO 3(RX): UART RX0
    GPIO 4(D2): I²C_SDA, I²C data
    GPIO 5(D1): I²C_SCK, I²C clock
    GPIO 6~11: 外掛 Flash ROM
    GOIO 12(D6):  MISO, 高速 SPI 主輸入僕輸出
    GPIO 13(D7):  MOSI, 高速 SPI 主輸出僕輸入
    GPIO 14(D5):  SCK, 高速 SPI clock
    GPIO 15(D8):  SS, 高速 SPI select, 開發板通常會外拉下地電阻,見下表
    GPIO 16(D0):  Wakeup,  喚醒
設定 GPIO15, GPIO0, GPIO2  的開機模式 bootstrapping:
     low , low, high  : 從 UART 載入程式
     low , high, high :  從 SPI 載入程式
     high, x, x :  從 SDIO 載入程式
2. 另外還有一個類比通道(10 bits adc), 最高承受到 3V, 測量範圍是 0 ~ 1 V

2020年5月26日 星期二

Solder Mask 與 Paste Mask 的差別


1. 就字面意義來說 Solder Mask (防焊層)就是要把焊接(電氣)層遮掉, Paste Mask 則是要把護膠層遮掉,兩者使用時機並不同, 前者用在 PCB 製程, 後者用於主機板組立製程(PCBA)開鋼板.
2. 在 PCB 的製程中,一塊銅箔基板,為了要線路化,會貼上阻光膠,然後將 Solder Mask 底片放到含阻光膠的銅箔基板上,用紫外線曝光,經過紫外線曝曬,未遮住的地方就能用洗滌劑把該處阻光膠清除,留下的殘膠位置就是線路圖,接者將曝光洗滌過線路板放入強酸池加以蝕刻,曝光部位洗除後只會留下線路圖.
3. 主機板組立時為了要讓 SMT 零件上件,須先刷一層錫膏黏上零件, 因此要用 Paste Mask 層去製作鋼板,將鋼板對準 PCB 後在開孔處刷上一層錫膏,經過熱處理錫膏熔化貼合就能完成 SMT 製程
4. 因此 Solder Mask 是用於 pcb 的線路化製程. 而 Paste Mask 是在 PCBA 開 SMD PAD 的鋼板用的, 開孔大小可根據經驗適時加以調整.


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

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