# MCU簡易教學 ## MCU種類 ### MCU(Microcontroller Unit),中文名為「微控制器單元」、「單晶片微電腦」。MCU 將中央處理器(CPU)、記憶體(RAM)、輸入 / 輸出介面(I/O)等等一大堆東西,全部整合在「一塊 IC」 上面。可以負責做少量、簡單的資料運算與處理。 ### 實驗室常用的MCU有: Arduino ESP32 Raspberry Pi Pico ### ESP32 ![img1](http://140.125.21.65:8418/Education/MCU/raw/commit/5b171491cfe9d8b4d594d30162d0a92fd432c6d6/PPT/img1.png) ![img2](http://140.125.21.65:8418/Education/MCU/raw/commit/5b171491cfe9d8b4d594d30162d0a92fd432c6d6/PPT/%E5%9C%96%E7%89%872.png) ### Raspberry Pi Pico ![img1](http://140.125.21.65:8418/Education/MCU/raw/commit/5b171491cfe9d8b4d594d30162d0a92fd432c6d6/PPT/%E5%9C%96%E7%89%873.png) ![img2](http://140.125.21.65:8418/Education/MCU/raw/commit/5b171491cfe9d8b4d594d30162d0a92fd432c6d6/PPT/%E5%9C%96%E7%89%874.jpg) ### 編譯器-Arduino IDE Arduino與ESP32都可以透過Arduino IDE進行編譯 強烈推薦使用Arduino IDE 版本1.8的 有人使用2.X的版本,過一星期就回歸1.8…. 若是要書寫ESP32(https://hackmd.io/@Robert/Hk1rGMsU3) ![img1](http://140.125.21.65:8418/Education/MCU/raw/commit/5b171491cfe9d8b4d594d30162d0a92fd432c6d6/PPT/%E5%9C%96%E7%89%875.png) ### 編譯器-Thonny IDE ESP32與Pi Pico都可以透過Thonny IDE進行編譯 但編譯前須先燒錄相關韌體 ESP32燒錄 [參考網址](https://chtseng.wordpress.com/2023/01/14/%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8thonnymicropython%E6%92%B0%E5%AF%ABesp32-cam%E7%A8%8B%E5%BC%8F/) 目前ESP32執行效率比 Pi Pico高,之後以ESP32為教學 ![img1](http://140.125.21.65:8418/Education/MCU/raw/branch/master/PPT/%E5%9C%96%E7%89%878.png) ### 選擇 若以一般實驗室內部進行專案開發,根據需求選擇: 若無網路需求,則以Arduino為主 IOT的需求則建議使用ESP32 控制馬達、接收資料、量測數據,這些基本的擇一使用即可 !!!極度重要!!! 在一般工廠使用,若訊號干擾很強的那種,一律走有線連接 接下來會以控制馬達作為教學 ## MCU控制 ### 馬達接線圖 ![](http://140.125.21.65:8418/Education/MCU/raw/branch/master/PPT/%E5%9C%96%E7%89%876.png) ![](http://140.125.21.65:8418/Education/MCU/raw/branch/master/PPT/%E5%9C%96%E7%89%877.png) ### MCU控制(WEB) #### ESP32寫micropython ``` python import network import ure import usocket as socket import gc import machine import time import utime from machine import Pin import uasyncio as asyncio import urequests import ujson led=Pin(2,Pin.OUT) out_1 = Pin(26,Pin.OUT) out_2 = Pin(27,Pin.OUT) wlan = network.WLAN(network.STA_IF) # 連接WIFI def connect_to_wifi(ssid, password): # 固定 IP ip = '192.168.1.185' subnet = '255.255.255.0' gateway = '192.168.1.1' dns = '8.8.8.8' wlan.active(True) wlan.active(False) wlan.active(True) wlan.ifconfig((ip, subnet, gateway, dns)) # 設定參數 wlan.connect(ssid, password) print('Starting to connect to WiFi') for i in range(20): print('Trying to connect to WiFi in {}s'.format(i)) utime.sleep(1) if wlan.isconnected(): break if wlan.isconnected(): led.value(1) time.sleep(0.5) led.value(0) time.sleep(0.5) led.value(1) time.sleep(0.5) led.value(0) print('Connected to WiFi:', ssid) print('WiFi connection successful!') print('Network configuration:', wlan.ifconfig()) # 馬達一圈 def motor_run(request): for i in range(0,200): out_2.value(1) time.sleep(0.01) out_2.value(0) time.sleep(0.01) return "HTTP/1.0 200 OK\r\nContent-Type: text/plain\r\n\r\n"+"motor run end" # 馬達1/10圈 def motor_36_run(request): for i in range(0,20): out_2.value(1) time.sleep(0.01) out_2.value(0) time.sleep(0.01) return "HTTP/1.0 200 OK\r\nContent-Type: text/plain\r\n\r\n"+"motor run end" # 錯誤請求 def handleNotFound(request): return "HTTP/1.0 404 Not Found\r\nContent-Type: text/plain\r\n\r\n"+"Page not found" # 主函数 def main(): wifi_ssid ="leo" wifi_password="00000000" # 連接WIFI connect_to_wifi(wifi_ssid, wifi_password) # 創建網頁API server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server_socket.bind(('0.0.0.0', 8080)) server_socket.listen(1) print("Server is listening on port 80...") out_1.value(0) while True: # 斷線重連 if not wlan.isconnected(): print('again') connect_to_wifi(wifi_ssid, wifi_password) client_socket, client_addr = server_socket.accept() print("Received connection from:", client_addr) request_data = client_socket.recv(1024).decode('utf-8') if request_data: if "GET /motor_run" in request_data: response_data = motor_run(request_data) elif "GET /motor_36_run" in request_data: response_data = motor_36_run(request_data) else: response_data = handleNotFound(request_data) client_socket.send(response_data.encode('utf-8')) client_socket.close() # 運行主程式 main() ``` #### ESP32寫Arduino(WEB) ``` C #include #include #include #include #include int out_1_pin = 26; int out_2_pin = 27; const char *ssid = "leo"; // Put your SSID here const char *password = "00000000"; unsigned long previousMillis =0; unsigned long interval = 30000; WebServer server(80); //WiFi連線 void WifiConnecte() { //Set your Static IP address IPAddress local_IP(192, 168,1 , 185); // Set your Gateway IP address IPAddress gateway(192, 168, 1, 1); IPAddress subnet(255, 255, 255, 0); if (!WiFi.config(local_IP, gateway, subnet)) { Serial.println("STA Failed to configure"); } //開始WiFi連線 WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println("WiFi連線成功"); Serial.print("IP Address:"); Serial.println(WiFi.localIP()); } void handleNotFound() { //digitalWrite(LED,LOW);//LED String message = "Server is running!\n\n"; //server.send(200, "text/plain", message); } //Web_chaek void web_check(void){ WiFiClient client = server.client(); String response = "HTTP/1.1 200 OK\r\n"; response += "Content-Type: multipart/x-mixed-replace; boundary=frame\r\n\r\n"; server.sendContent(response); } void motor_run(){ digitalWrite(out_1_pin, LOW); // 方向 for (int i = 0; i < 200; i++) { digitalWrite(out_2_pin, HIGH); // 将引脚设置为高电平 delay(10); // 等待10毫秒 digitalWrite(out_2_pin, LOW); // 将引脚设置为低电平 delay(10); // 等待10毫秒 } WiFiClient client = server.client(); server.send(200, "text/plain","run end"); } void motor_36_run(){ digitalWrite(out_1_pin, LOW); // 方向 for (int i = 0; i < 20; i++) { digitalWrite(out_2_pin, HIGH); // 将引脚设置为高电平 delay(10); // 等待10毫秒 digitalWrite(out_2_pin, LOW); // 将引脚设置为低电平 delay(10); // 等待10毫秒 } WiFiClient client = server.client(); server.send(200, "text/plain","run end"); } void setup() { // put your setup code here, to run once: pinMode(out_1_pin, OUTPUT); pinMode(out_2_pin, OUTPUT); Serial.begin(115200); Serial.println("Hello!"); WifiConnecte(); server.on("/motor_run",HTTP_GET,motor_run); server.on("/motor_36_run",HTTP_GET,motor_36_run); server.on("/web_check",HTTP_GET,web_check); server.onNotFound(handleNotFound); server.begin(); } void loop() { // put your main code here, to run repeatedly: unsigned long currentMills = millis(); if ((WiFi.status() != WL_CONNECTED)&& (currentMills - previousMillis >= interval)) { Serial.print(millis()); Serial.print("wifi正在連線中... "); WiFi.disconnect();//断开连接 WiFi.reconnect(); WifiConnecte(); } server.handleClient(); } ``` #### ESP32(COM) ```C int out_1_pin = 26; int out_2_pin = 27; bool LEDState = HIGH; void setup() { // initialize digital pin LED_BUILTIN as an output. Serial.begin(115200); pinMode(out_1_pin, OUTPUT); pinMode(out_2_pin, OUTPUT); } void motor_run(){ digitalWrite(out_1_pin, LOW); // 方向 for (int i = 0; i < 200; i++) { digitalWrite(out_2_pin, HIGH); // 将引脚设置为高电平 delay(10); // 等待10毫秒 digitalWrite(out_2_pin, LOW); // 将引脚设置为低电平 delay(10); // 等待10毫秒 } } void motor_36_run(){ digitalWrite(out_1_pin, LOW); // 方向 for (int i = 0; i < 20; i++) { digitalWrite(out_2_pin, HIGH); // 将引脚设置为高电平 delay(10); // 等待10毫秒 digitalWrite(out_2_pin, LOW); // 将引脚设置为低电平 delay(10); // 等待10毫秒 } } // the loop function runs over and over again forever void loop() { if (Serial.available() > 0) { // 检查是否有可用的串行数据 char receivedData[64]; // 用于存储接收到的数据 int dataSize = Serial.readBytesUntil('\n', receivedData, sizeof(receivedData)); // 读取串行数据直到遇到换行符为止 receivedData[dataSize] = '\0'; // 添加字符串结束符 Serial.print("Received: "); // 打印接收到的消息 Serial.println(receivedData); // 打印接收到的数据 if(strcmp(receivedData, "move_all") == 0) { motor_run(); Serial.println("run_all"); // 打印接收到的数据 } if(strcmp(receivedData, "move_36") == 0) { motor_36_run(); Serial.println("run_36"); // 打印接收到的数据 } } delay(10); } ``` #### Arduino(COM) ```C bool LEDState = HIGH; void setup() { // initialize digital pin LED_BUILTIN as an output. Serial.begin(115200); pinMode(13, OUTPUT); pinMode(12, OUTPUT); digitalWrite(12, HIGH); } void motor_run(){ digitalWrite(12, LOW); // 方向 for (int i = 0; i < 200; i++) { digitalWrite(13, HIGH); // 将引脚设置为高电平 delay(10); // 等待10毫秒 digitalWrite(13, LOW); // 将引脚设置为低电平 delay(10); // 等待10毫秒 } } void motor_36_run(){ digitalWrite(12, LOW); // 方向 for (int i = 0; i < 20; i++) { digitalWrite(13, HIGH); // 将引脚设置为高电平 delay(10); // 等待10毫秒 digitalWrite(13, LOW); // 将引脚设置为低电平 delay(10); // 等待10毫秒 } } // the loop function runs over and over again forever void loop() { if (Serial.available() > 0) { // 检查是否有可用的串行数据 char receivedData[64]; // 用于存储接收到的数据 int dataSize = Serial.readBytesUntil('\n', receivedData, sizeof(receivedData)); // 读取串行数据直到遇到换行符为止 receivedData[dataSize] = '\0'; // 添加字符串结束符 Serial.print("Received: "); // 打印接收到的消息 Serial.println(receivedData); // 打印接收到的数据 if(strcmp(receivedData, "move_all") == 0) { motor_run(); Serial.println("run_all"); // 打印接收到的数据 } if(strcmp(receivedData, "move_36") == 0) { motor_36_run(); Serial.println("run_36"); // 打印接收到的数据 } } delay(10); } ``` ### 影片如下 http://140.125.21.65:8418/Education/MCU/raw/branch/master/PPT/%E5%AA%92%E9%AB%942.mp4