flash-fluidnc.sh 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. #!/bin/bash
  2. #
  3. # Flash FluidNC firmware onto a connected ESP32 board
  4. #
  5. # Usage: bash flash-fluidnc.sh
  6. #
  7. # Interactive script that:
  8. # 1. Lets user choose FluidNC version (v3.9.5 for all tables, v3.8.3 for Mini Dune Weaver)
  9. # 2. Lets user select a serial port
  10. # 3. Downloads, extracts, and flashes the firmware
  11. # 4. Confirms success by checking esptool output
  12. #
  13. set -e
  14. # Colors
  15. RED='\033[0;31m'
  16. GREEN='\033[0;32m'
  17. YELLOW='\033[1;33m'
  18. BLUE='\033[0;34m'
  19. CYAN='\033[0;36m'
  20. BOLD='\033[1m'
  21. NC='\033[0m'
  22. # Versions
  23. VERSION_ALL="3.9.5"
  24. VERSION_MINI="3.8.3"
  25. GITHUB_BASE="https://github.com/bdring/FluidNC/releases/download"
  26. cleanup() {
  27. if [[ -n "${WORK_DIR:-}" && -d "$WORK_DIR" ]]; then
  28. echo -e "\n${BLUE}Cleaning up temporary files...${NC}"
  29. rm -rf "$WORK_DIR"
  30. fi
  31. }
  32. trap cleanup EXIT
  33. # ─── Step 1: Choose version ────────────────────────────────────────────────
  34. echo -e "${BOLD}${CYAN}"
  35. echo " ╔═══════════════════════════════════════╗"
  36. echo " ║ FluidNC Firmware Flasher ║"
  37. echo " ║ for Dune Weaver ║"
  38. echo " ╚═══════════════════════════════════════╝"
  39. echo -e "${NC}"
  40. echo -e "${BOLD}Select FluidNC version:${NC}"
  41. echo ""
  42. echo -e " ${GREEN}1)${NC} v${VERSION_ALL} - All tables (Dune Weaver, Pro, Gold, Mini Pro)"
  43. echo -e " ${GREEN}2)${NC} v${VERSION_MINI} - Mini Dune Weaver only"
  44. echo ""
  45. read -p "Enter choice [1/2]: " version_choice
  46. case "$version_choice" in
  47. 1)
  48. VERSION="$VERSION_ALL"
  49. echo -e "\nSelected: ${GREEN}FluidNC v${VERSION}${NC}"
  50. ;;
  51. 2)
  52. VERSION="$VERSION_MINI"
  53. echo -e "\nSelected: ${GREEN}FluidNC v${VERSION}${NC}"
  54. ;;
  55. *)
  56. echo -e "${RED}Invalid choice. Exiting.${NC}"
  57. exit 1
  58. ;;
  59. esac
  60. # ─── Step 2: Detect and select serial port ─────────────────────────────────
  61. echo ""
  62. echo -e "${BOLD}Detecting serial ports...${NC}"
  63. # Collect available serial ports (Linux + macOS patterns)
  64. PORTS=()
  65. for port in /dev/ttyUSB* /dev/ttyACM* /dev/cu.usbserial* /dev/cu.wchusbserial* /dev/cu.SLAB_USBtoUART*; do
  66. if [[ -e "$port" ]]; then
  67. PORTS+=("$port")
  68. fi
  69. done
  70. if [[ ${#PORTS[@]} -eq 0 ]]; then
  71. echo -e "${RED}No serial ports found!${NC}"
  72. echo ""
  73. echo "Make sure your ESP32 board is connected via USB."
  74. echo "On Linux, you may need to add your user to the 'dialout' group:"
  75. echo " sudo usermod -a -G dialout \$USER"
  76. exit 1
  77. fi
  78. if [[ ${#PORTS[@]} -eq 1 ]]; then
  79. PORT="${PORTS[0]}"
  80. echo -e "Found port: ${GREEN}${PORT}${NC}"
  81. read -p "Use this port? [Y/n]: " confirm
  82. if [[ "$confirm" =~ ^[Nn] ]]; then
  83. echo -e "${RED}Exiting.${NC}"
  84. exit 1
  85. fi
  86. else
  87. echo -e "Found ${GREEN}${#PORTS[@]}${NC} serial ports:"
  88. echo ""
  89. for i in "${!PORTS[@]}"; do
  90. echo -e " ${GREEN}$((i + 1)))${NC} ${PORTS[$i]}"
  91. done
  92. echo ""
  93. read -p "Select port [1-${#PORTS[@]}]: " port_choice
  94. if [[ "$port_choice" -ge 1 && "$port_choice" -le ${#PORTS[@]} ]] 2>/dev/null; then
  95. PORT="${PORTS[$((port_choice - 1))]}"
  96. else
  97. echo -e "${RED}Invalid choice. Exiting.${NC}"
  98. exit 1
  99. fi
  100. fi
  101. echo -e "Using port: ${GREEN}${PORT}${NC}"
  102. # ─── Step 3: Check for esptool ─────────────────────────────────────────────
  103. if ! command -v esptool.py &> /dev/null && ! command -v esptool &> /dev/null; then
  104. echo ""
  105. echo -e "${YELLOW}esptool not found. Installing...${NC}"
  106. pip install esptool
  107. fi
  108. # Determine the esptool command name
  109. if command -v esptool.py &> /dev/null; then
  110. ESPTOOL="esptool.py"
  111. elif command -v esptool &> /dev/null; then
  112. ESPTOOL="esptool"
  113. else
  114. echo -e "${RED}Failed to install esptool. Please install manually: pip install esptool${NC}"
  115. exit 1
  116. fi
  117. # ─── Step 4: Download and extract ──────────────────────────────────────────
  118. ZIP_NAME="fluidnc-v${VERSION}-posix.zip"
  119. DOWNLOAD_URL="${GITHUB_BASE}/v${VERSION}/${ZIP_NAME}"
  120. EXTRACT_DIR="fluidnc-v${VERSION}-posix"
  121. WORK_DIR=$(mktemp -d)
  122. echo ""
  123. echo -e "${BLUE}Downloading FluidNC v${VERSION}...${NC}"
  124. if ! curl -L --fail --progress-bar "$DOWNLOAD_URL" -o "$WORK_DIR/$ZIP_NAME"; then
  125. echo -e "${RED}Download failed!${NC}"
  126. echo "URL: $DOWNLOAD_URL"
  127. exit 1
  128. fi
  129. echo -e "${BLUE}Extracting...${NC}"
  130. unzip -q "$WORK_DIR/$ZIP_NAME" -d "$WORK_DIR"
  131. if [[ ! -d "$WORK_DIR/$EXTRACT_DIR" ]]; then
  132. echo -e "${RED}Expected directory $EXTRACT_DIR not found after extraction.${NC}"
  133. exit 1
  134. fi
  135. FLASH_DIR="$WORK_DIR/$EXTRACT_DIR"
  136. # ─── Step 5: Flash firmware ────────────────────────────────────────────────
  137. echo ""
  138. echo -e "${BOLD}${CYAN}══════════════════════════════════════════${NC}"
  139. echo -e "${BOLD} Flashing FluidNC v${VERSION} to ${PORT}${NC}"
  140. echo -e "${BOLD}${CYAN}══════════════════════════════════════════${NC}"
  141. echo ""
  142. echo -e "${YELLOW}Do NOT disconnect the board during flashing!${NC}"
  143. echo ""
  144. FLASH_SUCCESS=true
  145. # --- 5a: Flash WiFi firmware ---
  146. echo -e "${BLUE}[1/2] Flashing WiFi firmware...${NC}"
  147. echo ""
  148. WIFI_OUTPUT=$($ESPTOOL --chip esp32 --port "$PORT" --baud 460800 \
  149. --before default_reset --after hard_reset \
  150. write_flash -z --flash_mode dio --flash_freq 80m --flash_size detect \
  151. 0x1000 "$FLASH_DIR/wifi/bootloader.bin" \
  152. 0x8000 "$FLASH_DIR/wifi/partitions.bin" \
  153. 0xe000 "$FLASH_DIR/common/boot_app0.bin" \
  154. 0x10000 "$FLASH_DIR/wifi/firmware.bin" 2>&1) || true
  155. echo "$WIFI_OUTPUT"
  156. echo ""
  157. if echo "$WIFI_OUTPUT" | grep -q "Hard resetting via RTS pin"; then
  158. echo -e "${GREEN}Firmware flash successful!${NC}"
  159. else
  160. echo -e "${RED}Firmware flash may have failed!${NC}"
  161. FLASH_SUCCESS=false
  162. fi
  163. # --- 5b: Flash filesystem (LittleFS) ---
  164. echo ""
  165. echo -e "${BLUE}[2/2] Flashing filesystem (LittleFS)...${NC}"
  166. echo ""
  167. FS_OUTPUT=$($ESPTOOL --chip esp32 --port "$PORT" --baud 460800 \
  168. --before default_reset --after hard_reset \
  169. write_flash -z --flash_mode dio --flash_freq 80m --flash_size detect \
  170. 0x3d0000 "$FLASH_DIR/wifi/littlefs.bin" 2>&1) || true
  171. echo "$FS_OUTPUT"
  172. echo ""
  173. if echo "$FS_OUTPUT" | grep -q "Hard resetting via RTS pin"; then
  174. echo -e "${GREEN}Filesystem flash successful!${NC}"
  175. else
  176. echo -e "${RED}Filesystem flash may have failed!${NC}"
  177. FLASH_SUCCESS=false
  178. fi
  179. # ─── Step 6: Summary ──────────────────────────────────────────────────────
  180. echo ""
  181. echo -e "${BOLD}${CYAN}══════════════════════════════════════════${NC}"
  182. if [[ "$FLASH_SUCCESS" == true ]]; then
  183. echo -e "${GREEN} FluidNC v${VERSION} flashed successfully!${NC}"
  184. echo -e "${BOLD}${CYAN}══════════════════════════════════════════${NC}"
  185. echo ""
  186. echo "The board has been reset and should now be running FluidNC."
  187. echo "Connect to the 'FluidNC' WiFi network to access the web UI."
  188. else
  189. echo -e "${RED} Flashing completed with errors!${NC}"
  190. echo -e "${BOLD}${CYAN}══════════════════════════════════════════${NC}"
  191. echo ""
  192. echo "Review the output above for error details."
  193. echo "Common fixes:"
  194. echo " - Hold the BOOT button on the ESP32 while flashing"
  195. echo " - Try a different USB cable (data cable, not charge-only)"
  196. echo " - Check port permissions: sudo chmod 666 $PORT"
  197. echo " - Try a lower baud rate by editing this script (change 460800 to 115200)"
  198. exit 1
  199. fi