---
# System prepended metadata

title: 主控板程式

---

# `translate.py`  `dancer0.ino` 教學



---

## 1 流程

1. **先用 `editor.py`** 編排好顏色幀、舞者 LED 光效，結果都存在 `data/` 資料夾。
2. **執行 `translate.py`** 後，程式會：

   1. 讀取 `data/setting.json` + `data/data.json` …後把舞者 LED 布局、顏色表、幀資料抓進記憶體。
   2. 逐一生成 `dancer0.ino‥dancerN.ino`，全放到 `esp32_ino/` 資料夾。
3. **用 Arduino IDE / PlatformIO** 將相對應的 `.ino` 燒進那位舞者的 ESP32 板子。
4. 上台時 **`editor.py` → UDP 廣播幀號** …後 ESP32 收到就立即呼叫 `playh()`，同步更新燈條顏色。

---

## 2 `translate.py` 逐段解析

| 區塊                              | 行數                            | 作用                                                        | 重點說明                            |
| ------------------------------- | ----------------------------- | --------------------------------------------------------- | ------------------------------- |
| **載入 JSON**                     | `import json …` 之後 (行 1–14)   | `load_json()` 幫我讀設定檔，保持 `utf‑8` 編碼 | 只要設定檔格式對，這邊基本不會出錯。              |
| **全域常數**                        | 行 17–26                       | `output_dir`、`WIFI_SSID`、`WIFI_PASSWORD`                  | Wi‑Fi 連線密碼直接硬寫這裡。               |
| **工具函式**                        | 行 28–44                       | `array_to_string()` 把 Python list 轉成 Arduino 用的 `{1,2,3}` | 這一招省去手動組字串的痛苦。                  |
| **`generate_content(dancerN)`** | 行 46–108                      | **靈魂函式**：讀取第 `dancerN` 位舞者的 LED 排列 & 幀資料，拼出 `.ino` 原始碼    |                                 |
| **檔案輸出**                        | `create_ino_file()` (行 30–42) | 把字串寫進 `dancer{i}.ino`                                     | 有 `try/except`，失敗會印 Error 不會當掉。 |
| **`main()` loop**               | 行 110–115                     | for‑loop 產生全部舞者 `.ino`                                    | 執行一次就全部搞定。                      |


### 2‑1 動態產 C 陣列

```python
LED_stripe[i] = array_to_string(stripe)
NUM_LEDS[i] = len(stripe)
...
framedata = f"int data[{a}][{b}] = {c};"
``` 


* 我先把每條燈帶對應到人體部位的 **LED 索引** 攤平成 `{0,1,2,…}`。  
* 接著把多維 `frames[nowdancer]` 轉 `{顏色 index}` 矩陣，給 ESP32 直接查表。

### 2‑2 拼接 `Settingcode`

`Settingcode` 內含：
* `#define NUM_LEDSx` 讓 FastLED 知道每條燈長度。  
* `DATA_PINx` 設燈帶接腳；我固定用 GPIO 17,16,32,33,25,26,14,27。  
* `COLOR_COUNT`、`char colors[][20]` 存顏色 hex。  
* `int LEDPARTx[]` → 每一條燈帶對應到「人體部位 index」陣列。  
* 以上都在 `translate.py` 用 f‑string 串好再寫檔。

---

## 3 `dancerX.ino` 架構（其他舞者同理）

> 以下行數以 `translate.py` 內 template 為準，因為 `.ino` 直接由它輸出。

### 3‑1 巨集 & 全域變數

```cpp
#define NUM_LEDS1 60 //左手臂
#define DATA_PIN1 17
...
char colors[][20] = {"#000000","#ff0000",…};
CRGB LED1[NUM_LEDS1];
CRGB* LEDstrings[] = {LED1,…};
```  
* **`LEDstrings`** 是二維指標陣列，`FastLED.addLeds<WS2812…>` 一次註冊八條燈帶。  
* `lednums[]`、`pins[]` 也同步生成，方便迴圈掃描。

### 3‑2 `setup()` – 初始化

```cpp
void setup(){
  Serial.begin(115200);
  for(y=0;y<COLOR_COUNT;y++) colorArray[y]=hexToColor(colors[y]);
  FastLED.addLeds<WS2812, DATA_PIN1, GRB>(LEDstrings[0], NUM_LEDS1);
  ... // 其餘七條
  WiFi.begin(ssid, password);
  while(WiFi.status()!=WL_CONNECTED){ delay(1000); }
  udp.begin(localUdpPort);
}
```  

* **`hexToColor()`** 把 `#RRGGBB` 字串轉 CRGB。  
* FastLED + WS2812 設定一次就好。  
* Wi‑Fi 連平台自己架，可用手機開熱點測試。

### 3‑3 `loop()` – 收 UDP → 播放幀

```cpp
int packetSize = udp.parsePacket();
if(packetSize){
  udp.read(incomingPacket,4);
  int frameN = (incomingPacket[0]<<24)|...;
  playh(frameN);
}
```  
* 我只收 4 bytes big‑endian 整數＝「第幾幀」。  
* 收到後立即呼叫 `playh()`，無條件同步，不等校正。

### 3‑4 `playh(int frameN)` – 真正點燈

```cpp
for(int ledstring=0; ledstring<USEDPIN_NUM; ledstring++){
  CRGB* strip = LEDstrings[ledstring];
  int* map   = leds[ledstring];
  for(int led=0; led<lednums[ledstring]; led++){
     strip[led] = colorArray[ data[frameN][ map[led] ] ];
  }
}
FastLED.show();
```  
* **兩層 for‑loop**：外圈掃八條燈帶，內圈掃單顆 LED。  
* `map[led]` 取得這顆 LED 對應的人體部位 index，再去 `data[frameN][part]` 找顏色。  
* `FastLED.show()` 一次送完，延遲 < 2 ms，足夠舞台同步。

---

## 4 常見雷區 & 我的踩坑經驗

| 問題 | 現象 | 解法 |
|------|------|-----|
| **LED 條長度不符** | 部分燈不亮、跟光效對不起來| 檢查 `setting.json` 裡每條陣列長度，跟實體 LED 顆數對齊。|
| **Wi‑Fi 連不上** | ESP32 不停印 `Connecting to WiFi.` | SSID/密碼改對、確認 2.4 GHz；或改用手機熱點測。|
| **UDP 丟包** | 少數幀錯位 | 可在 `editor.py` 端每 16 ms 重送上一次幀，容錯更高（實測可行）。|

---

## 5 動手練習

1. **改光效**：打開 `data/data.json` 把 `"#ff0000"` 換 `"#00ffff"`…後重跑 `translate.py`、重新燒錄，LED 效果應馬上變。  
2. **變更 LED 排列**：在 `setting.json` 的 `"LED"` 陣列改順序，再生成 `.ino`，可測試右手臂/左手臂對調。  editor.py` `broadcast_port` 也改，觀察是否仍能同步。

---
