| 作者/攝影 | 袁佑緣 |
| 時間 |
|
| 成本 |
|
| 難度 | * * * * * * |
| 材料表 |
|
1. 平衡車車體製作
本範例的平衡車車體主要是由雷切壓克力構成,壓克力的厚度是使用3mm的板材,再藉由螺絲螺帽組合而成,車子的馬達使用的是兩顆小型的5V減速馬達,輪子的部份也是由壓克力組成,胎皮則是貼上一層防滑墊,車子的底部則有兩個3號電池座,裡面各裝兩顆7V的鋰電池,一個用來驅動控制板,另一個則用來驅動馬達。
詳細的CAD檔可以參考筆者放在網路上的onsahpe專案,有興趣的讀者可以參考看看喔!
圖一、平衡車的模擬動畫
圖二、組裝爆炸圖
圖四六七八、車體的三視圖
圖八、平衡車實體圖
2.電路接線
本次範例使用的馬達驅動晶片是TA7279P,其腳位功能與編號如下圖(節錄自官方datasheet) ,請將5號及10號腳位接到鋰電池的電源上,並把A、B兩個channel的馬達訊號輸入腳位,也就是1、3、12、13接到Arduino 101上的3、5、6、9號腳位來當作控制板的訊號控制腳位,因為這些腳位才有辦法做PWM訊號的輸出,也因此才能控制馬達的轉速。
至於馬達的部份,請將下表output(輸出)的腳位各自接到兩顆馬達上即可,例如:A channel想控制左馬達,B channel想控制右馬達,那就把4、6號腳位接到左馬達上,9、11號腳位接到右馬達上。
另外也別忘記要給TA7279馬達驅動晶片供給工作電壓,只要在14號腳位供給5V的電力,7號腳位接地就行囉。
圖九、TA7279P腳位功能圖
圖十、TA7279P腳位編號圖
圖十一、完成車體與電線配置!
3. Arduino環境準備
請先準備好Arduino IDE,並請在Arduion IDE上的Boards Manager那邊搜尋關鍵字intel,並如下圖安裝Intel Cuire Board。至於驅動程式的部份,使用MacOS跟Linux的朋友不用擔心,直接使用就可以了,那如果是windows的使用者在第一次將控制板接到電腦上時,會挑出自動安裝驅動程式的視窗,請耐心等候電腦完成安裝就可以進行到下一步囉!
圖十二、Arduino IDE Boards Manager設定
4.程式設計
[pastacode lang=”cpp” manual=”%23include%20%22CurieIMU.h%22%20%2F%2F%E5%BC%95%E5%85%A5Arduino%20101%20IMU%E7%9A%84%E5%87%BD%E5%BC%8F%E5%BA%AB%EF%BC%8C%E7%94%A8%E4%BE%86%E5%81%B5%E6%B8%AC%E8%BB%8A%E9%AB%94%E7%9A%84%20%20%20%20%20%20%20%20%20%20%20%20%E8%A7%92%E9%80%9F%E5%BA%A6%E8%88%87%E5%8A%A0%E9%80%9F%E5%BA%A6%E6%96%B9%E5%90%91%0A%0A%2F%2F%E5%AE%A3%E5%91%8APID%E6%8E%A7%E5%88%B6%E7%9A%84%E5%90%84%E5%80%8B%E5%8F%83%E6%95%B8%EF%BC%8C%E5%90%84%E5%80%8B%E5%8F%83%E6%95%B8%E7%9A%84%E6%9C%80%E4%BD%B3%E6%95%B8%E5%80%BC%E5%BF%85%E9%A0%88%E8%A6%96%E8%BB%8A%E9%AB%94%E6%83%85%E6%B3%81%E8%80%8C%E5%AE%9A%EF%BC%8C%E4%B8%8D%E5%90%8C%E7%9A%84%E8%BB%8A%E9%AB%94%E6%9C%83%E6%9C%89%E6%89%80%E4%B8%8D%E5%90%8C%EF%BC%8C%E9%9B%BB%E5%8A%9B%E7%9A%84%E5%A4%A7%E5%B0%8F%E4%B9%9F%E6%9C%83%E6%9C%89%E5%BD%B1%E9%9F%BF%0Aconst%20float%20kp%20%3D%2024%3B%20%0Aconst%20float%20ki%20%3D%200.05%3B%0Aconst%20float%20kd%20%3D%2015%3B%0A%0A%2F%2F%E5%AE%A3%E5%91%8A%E5%8F%83%E6%95%B8K%E4%BD%9C%E7%82%BAcomplimentray%20filter%E7%9A%84%E5%8F%83%E6%95%B8%0Aconst%20float%20K%20%3D%200.95%3B%0A%0A%2F%2Flist%20number%E7%9A%84%E5%A4%A7%E5%B0%8F%E6%9C%83%E6%B1%BA%E5%AE%9A%E5%8F%96%E5%B9%B3%E5%9D%87%E7%9A%84%E6%A8%A3%E6%9C%AC%E6%95%B8%EF%BC%8C%E8%B6%8A%E5%A4%9A%E5%89%87%E8%B6%8A%E6%BA%96%EF%BC%8C%E4%BD%86%E4%B9%9F%E6%9C%83%E8%8A%B1%E6%8E%89%E6%9B%B4%E5%A4%9A%E8%A8%88%E7%AE%97%E6%99%82%E9%96%93%0Aconst%20int%20angle_list_number%20%3D%205%3B%0Aconst%20int%20error_list_number%20%3D%2010%3B%0A%0A%2F%2F%E8%A8%AD%E5%AE%9A%E9%A6%AC%E9%81%94%E5%88%9D%E9%80%9F%E7%82%BA0%0Aint%20speed%20%3D%200%3B%0A%0A%2F%2F%E5%AE%9A%E7%BE%A9%E9%A6%AC%E9%81%94%E7%9A%84%E9%A9%85%E5%8B%95%E8%85%B3%E4%BD%8D%0Aconst%20int%20motor_A_1%20%3D%203%3B%0Aconst%20int%20motor_A_2%20%3D%205%3B%0Aconst%20int%20motor_B_1%20%3D%206%3B%0Aconst%20int%20motor_B_2%20%3D%209%3B%0A%0A%2F%2F%E5%AE%A3%E5%91%8A%E9%80%B2%E8%A1%8C%E8%A7%92%E5%BA%A6%E8%A8%88%E7%AE%97%E8%88%87PID%E6%8E%A7%E5%88%B6%E6%9C%83%E7%94%A8%E5%88%B0%E7%9A%84%E4%B8%80%E4%BA%9B%E5%8F%83%E6%95%B8%0Afloat%20time%2C%20time_pre%2C%20time_step%3B%0Afloat%20gyro_angle%20%3D%200%3B%0Afloat%20acce_angle%20%3D%200%3B%0Afloat%20angle_list%5Bangle_list_number%5D%3B%0Afloat%20pre_error%20%3D%200%3B%0Afloat%20error_list%5Berror_list_number%5D%3B%0Afloat%20diff_error%20%3D%200%3B%0Afloat%20offset%20%3D%200%3B%0A%0Avoid%20setup()%0A%7B%0A%09for(int%20i%20%3D%200%3B%20i%20%3C%20angle_list_number%3B%20i%2B%2B)%0A%09%09angle_list%5Bi%5D%20%3D%200.0%3B%0A%09for(int%20i%20%3D%200%3B%20i%20%3C%20error_list_number%3B%20i%2B%2B)%0A%09%09error_list%5Bi%5D%20%3D%200.0%3B%0A%09pinMode(motor_A_1%2C%20OUTPUT)%3B%0A%09pinMode(motor_A_2%2C%20OUTPUT)%3B%0A%09pinMode(motor_B_1%2C%20OUTPUT)%3B%0A%09pinMode(motor_B_2%2C%20OUTPUT)%3B%0A%09pinMode(13%2C%20OUTPUT)%3B%0A%0A%09Serial.begin(9600)%3B%0A%09Serial.println(%22Start!!!%22)%3B%0A%0A%2F%2F%E8%A8%AD%E5%AE%9AArduino%20101%20%E7%9A%84IMU%E6%84%9F%E6%B8%AC%E5%99%A8%09%0A%20%20%20%20%20%20CurieIMU.begin()%3B%0A%09CurieIMU.setAccelerometerRange(4)%3B%0A%09CurieIMU.setGyroRange(250)%3B%0A%09time%20%3D%20millis()%3B%0A%09for(int%20i%20%3D%200%3B%20i%20%3C%205%3B%20i%2B%2B)%0A%09%7B%0A%09%09Serial.println(%22Ready…%22)%3B%0A%09%09delay(200)%3B%09%0A%09%7D%0A%09int%20time2%20%3D%20millis()%3B%0A%0A%2F%2F%E5%BE%85%E6%A9%9F%E5%85%A9%E7%A7%92%E5%BE%8C%EF%BC%8C%E5%8F%96%E5%BE%97%E4%B8%80%E5%80%8B%E5%88%9D%E5%A7%8B%E4%BD%8D%E7%BD%AE%E7%9A%84%E8%A7%92%E5%BA%A6%EF%BC%8C%E9%80%99%E5%80%8B%E4%BD%8D%E7%BD%AE%E5%B0%87%E6%9C%83%E6%98%AF%E5%B9%B3%E8%A1%A1%E8%BB%8A%E7%9B%AE%E6%A8%99%E7%9A%84%E5%B9%B3%E8%A1%A1%E4%BD%8D%E7%BD%AE%0A%09while((millis()-time2)%20%3C%202000)%0A%09%09offset%20%3D%20get_angle()%3B%0A%09digitalWrite(13%2C%20HIGH)%3B%0A%7D%0A%0Avoid%20loop()%0A%7B%0A%2F%2F%E4%B8%BB%E8%BF%B4%E5%9C%88%E6%9C%83%E4%B8%80%E7%9B%B4%E5%8E%BB%E8%AE%80%E5%8F%96%E7%8F%BE%E5%9C%A8%E8%A7%92%E5%BA%A6%E8%88%87%E7%9B%AE%E6%A8%99%E8%A7%92%E5%BA%A6%E7%9A%84%E8%AA%A4%E5%B7%AE%EF%BC%8C%E4%B8%A6%E9%80%8F%E9%81%8EPID%E6%8E%A7%E5%88%B6%E4%BE%86%E5%9B%9E%E5%82%B3%E4%BF%AE%E6%AD%A3%E5%8B%95%E4%BD%9C%E7%B5%A6%E9%A6%AC%E9%81%94%0A%09float%20error%20%3D%20get_angle()%3B%0A%09float%20feedback%20%3D%20PID_feedback(error)%3B%0A%09if(abs(error)%20%3E%2070)%0A%2F%2F%E7%95%B6%E5%82%BE%E6%96%9C%E8%A7%92%E5%BA%A6%E9%81%8E%E5%A4%A7%E6%99%82%EF%BC%8C%E6%9C%83%E8%A6%96%E7%82%BA%E5%80%92%E6%8E%89%EF%BC%8C%E6%AD%A4%E6%99%82%E5%B0%87%E6%9C%83%E5%81%9C%E6%A9%9F%E4%B8%A6%E7%AD%89%E5%BE%85%E9%87%8D%E5%95%9F%0A%09%7B%0A%09%09while(true)%0A%09%09%7B%0A%09%09%09analogWrite(motor_A_1%2C%200)%3B%0A%09%09%09digitalWrite(motor_A_2%2C%20LOW)%3B%0A%09%09%09analogWrite(motor_B_1%2C%200)%3B%0A%09%09%09digitalWrite(motor_B_2%2C%20LOW)%3B%0A%09%09%09Serial.println(%22Stop!!!%22)%3B%0A%09%09%7D%0A%09%7D%0A%09balance(feedback)%3B%0A%7D%0A%0A%2F%2F%E5%B9%B3%E8%A1%A1%E5%87%BD%E5%BC%8F%E5%B0%87%E6%9C%83%E6%A0%B9%E6%93%9APID%E7%AE%97%E5%87%BA%E7%9A%84%E5%9B%9E%E9%A5%8B%E6%95%B8%E5%80%BC%EF%BC%8C%E5%91%BC%E5%8F%AB%E9%A6%AC%E9%81%94%E5%81%9A%E5%87%BA%E7%9B%B8%E5%B0%8D%E6%87%89%E7%9A%84%E4%BF%AE%E6%AD%A3%E5%8B%95%E4%BD%9C%0Avoid%20balance(float%20feedback)%0A%7B%0A%09speed%20%3D%20int(feedback)%3B%0A%09if(speed%20%3C%200)%0A%09%7B%0A%09%09analogWrite(motor_A_1%2C%20abs(speed))%3B%0A%09%09analogWrite(motor_B_1%2C%20abs(speed))%3B%0A%09%09digitalWrite(motor_A_2%2C%20LOW)%3B%0A%09%09digitalWrite(motor_B_2%2C%20LOW)%3B%0A%09%7D%0A%09else%0A%09%7B%0A%09%09digitalWrite(motor_A_1%2C%20LOW)%3B%0A%09%09digitalWrite(motor_B_1%2C%20LOW)%3B%0A%09%09analogWrite(motor_A_2%2C%20abs(speed))%3B%0A%09%09analogWrite(motor_B_2%2C%20abs(speed))%3B%0A%09%7D%0A%7D%0A%0A%2F%2F%E8%AE%80%E5%8F%96%E8%A7%92%E5%BA%A6%E7%9A%84%E5%87%BD%E5%BC%8F%E6%9C%83%E9%80%8F%E9%81%8E%E8%A8%88%E6%99%82%E5%99%A8%E7%B4%AF%E5%8A%A0%E7%9A%84%E9%83%A8%E4%BB%BD%EF%BC%8C%E5%B0%87IMU%E8%AE%80%E5%88%B0%E7%9A%84%E8%A7%92%E9%80%9F%E5%BA%A6%E9%9B%A2%E6%95%A3%E7%A9%8D%E5%88%86%E6%88%90%E8%A7%92%E5%BA%A6%EF%BC%8C%E5%90%8C%E6%99%82%E6%9C%83%E5%81%9A%E5%B9%B3%E5%9D%87%E5%8F%96%E5%80%BC%E4%B8%A6%E8%BC%94%E4%BB%A5complimentary%20filter%E7%9A%84%E6%96%B9%E5%BC%8F%E4%BE%86%E5%B0%87%E7%B2%BE%E7%A2%BA%E7%9A%84%E8%A7%92%E5%BA%A6%E6%95%B8%E5%80%BC%E8%A8%88%E7%AE%97%E5%87%BA%E4%BE%86%0Afloat%20get_angle()%0A%7B%0A%09time_pre%20%3D%20time%3B%0A%09time%20%3D%20millis()%3B%0A%09time_step%20%3D%20(time%20-%20time_pre)%2F1000%3B%0A%0A%09float%20ax%2C%20ay%2C%20az%3B%0A%09float%20gx%2C%20gy%2C%20gz%3B%0A%09CurieIMU.readAccelerometerScaled(ax%2C%20ay%2C%20az)%3B%0A%09CurieIMU.readGyroScaled(gx%2C%20gy%2C%20gz)%3B%0A%0A%2F%2F%E5%B0%87%E4%BB%A5%E4%B8%8B%E7%9A%84%E8%A8%BB%E8%A7%A3%E5%8F%96%E6%B6%88%E6%8E%89%E7%9A%84%E8%A9%B1%E5%8F%AF%E4%BB%A5%E5%BE%9EArduino%20101%E7%9A%84Serial%E8%AE%80%E5%88%B0%E6%AD%A4%E5%88%BB%E6%84%9F%E6%87%89%E5%99%A8%E7%9A%84%E5%8E%9F%E5%A7%8B%E6%95%B8%E5%80%BC%EF%BC%8C%E8%A8%98%E5%BE%97baud%20rate%E8%A6%81%E8%B7%9F%E5%89%8D%E9%9D%A2%E5%AE%A3%E5%91%8A%E7%9A%84%E4%B8%80%E6%A8%A3%E8%A8%AD%E5%AE%9A%E6%88%909600%EF%BC%8C%E5%8F%A6%E5%A4%96%E8%A6%81%E6%8F%90%E9%86%92%E4%B8%80%E4%B8%8B%E5%A6%82%E6%9E%9C%E9%96%8B%E5%95%9FSerial%E8%BC%B8%E5%87%BA%E7%9A%84%E5%8A%9F%E8%83%BD%E7%9A%84%E8%A9%B1%EF%BC%8C%E6%9C%83%E6%B6%88%E8%80%97%E6%8E%89%E9%A1%8D%E5%A4%96%E7%9A%84%E8%A8%88%E7%AE%97%E8%B3%87%E6%BA%90%EF%BC%8C%E6%89%80%E4%BB%A5%E5%A6%82%E6%9E%9C%E5%B7%B2%E7%B6%93%E4%B8%8D%E9%9C%80%E8%A6%81%E5%86%8D%E8%AE%80%E5%8F%96%E6%95%B8%E5%80%BC%E6%99%82%EF%BC%8C%E6%9C%80%E5%A5%BD%E6%8A%8A%E4%BB%A5%E4%B8%8B%E7%9A%84%E7%A8%8B%E5%BC%8F%E7%A2%BC%E8%A8%BB%E8%A7%A3%E6%8E%89%0A%09%2F%2FSerial.print(ax)%3B%0A%09%2F%2FSerial.print(%22%5Ct%22)%3B%0A%09%2F%2FSerial.print(ay)%3B%0A%09%2F%2FSerial.print(%22%5Ct%22)%3B%0A%09%2F%2FSerial.print(az)%3B%0A%09%2F%2FSerial.print(%22%5Ct%22)%3B%0A%09%2F%2FSerial.print(gx)%3B%0A%09%2F%2FSerial.print(%22%5Ct%22)%3B%0A%09%2F%2FSerial.print(gy)%3B%0A%09%2F%2FSerial.print(%22%5Ct%22)%3B%0A%09%2F%2FSerial.print(gz)%3B%0A%09%2F%2FSerial.println()%3B%0A%09%0A%09gyro_angle%20%2B%3D%20gy*time_step%3B%0A%09acce_angle%20%3D%20(180%2F3.141593)%20*%20atan(ax%2Faz)%3B%0A%09for(int%20i%20%3D%200%3B%20i%20%3C%20angle_list_number-1%3B%20i%2B%2B)%0A%09%09angle_list%5Bi%5D%20%3D%20angle_list%5Bi%2B1%5D%3B%0A%09angle_list%5Bangle_list_number-1%5D%20%3D%20K%20*%20acce_angle%20%2B%20(1-K)%20*%20gyro_angle%3B%0A%09float%20mean_angle%3B%0A%09mean_angle%20%3D%200.0%3B%0A%09for(int%20i%20%3D%200%3B%20i%20%3C%20angle_list_number%3B%20i%2B%2B)%0A%09%09mean_angle%20%2B%3D%20angle_list%5Bi%5D%3B%0A%09mean_angle%20%2F%3D%205%3B%0A%09mean_angle%20-%3D%20offset%3B%0A%09return%20mean_angle%3B%0A%0A%7D%0A%0A%2F%2FPID%E5%9B%9E%E9%A5%8B%E7%9A%84%E5%87%BD%E5%BC%8F%E6%9C%83%E5%B0%87%E9%8C%AF%E8%AA%A4%E9%80%B2%E8%A1%8C%E4%B8%80%E9%80%A3%E4%B8%B2%E7%9A%84%E8%A8%88%E7%AE%97%EF%BC%8C%E4%B8%A6%E6%A0%B9%E6%93%9A%E9%96%8B%E9%A0%AD%E6%88%91%E5%80%91%E8%A8%AD%E5%AE%9A%E7%9A%84%E4%B8%89%E5%80%8B%E4%BF%82%E6%95%B8%E4%BE%86%E5%81%9A%E5%87%BA%E9%81%A9%E7%95%B6%E7%9A%84%E5%9B%9E%E9%A5%8B%0Afloat%20PID_feedback(float%20error)%0A%7B%0A%09for(int%20i%20%3D%200%3B%20i%20%3C%20error_list_number-1%3B%20i%2B%2B)%0A%09%09error_list%5Bi%5D%20%3D%20error_list%5Bi%2B1%5D%3B%0A%09error_list%5Berror_list_number-1%5D%20%3D%20error%3B%0A%0A%09float%20sum_error%20%3D%200%3B%0A%09for(int%20i%20%3D%200%3B%20i%20%3C%20error_list_number%3B%20i%2B%2B)%0A%09%09sum_error%20%2B%3D%20error_list%5Bi%5D%3B%0A%09diff_error%20%3D%20error%20-%20pre_error%3B%0A%09pre_error%20%3D%20error%3B%0A%09float%20p_term%20%3D%20kp%20*%20error%3B%0A%09float%20i_term%20%3D%20ki%20*%20sum_error%3B%0A%09float%20d_term%20%3D%20kd%20*%20diff_error%3B%0A%09float%20feedback%20%3D%20p_term%20%2B%20i_term%20%2B%20d_term%3B%0A%09if(feedback%20%3E%3D%20255)%0A%09%09feedback%20%3D%20255%3B%0A%09else%20if(feedback%20%3C%3D%20-255)%0A%09%09feedback%20%3D%20-255%3B%0A%0A%2F%2F%E8%B7%9F%E5%89%8D%E9%9D%A2%E4%B8%80%E6%A8%A3%EF%BC%8C%E6%8A%8A%E4%BB%A5%E4%B8%8B%E7%A8%8B%E5%BC%8F%E7%A2%BC%E7%9A%84%E8%A8%BB%E8%A7%A3%E6%8B%BF%E6%8E%89%E7%9A%84%E8%A9%B1%E5%8F%AF%E4%BB%A5%E5%BE%9ESerial%E8%AE%80%E5%87%BA%E5%AF%A6%E9%9A%9B%E5%BE%97%E5%87%BA%E7%9A%84%E5%9B%9E%E9%A5%8B%0A%09%2F%2F%20Serial.print(%22P_term%3A%20%22)%3B%0A%09%2F%2F%20Serial.print(p_term)%3B%0A%09%2F%2F%20Serial.print(%22%5CtI_term%3A%20%22)%3B%0A%09%2F%2F%20Serial.print(i_term)%3B%0A%09%2F%2F%20Serial.print(%22%5CtD_term%3A%20%22)%3B%0A%09%2F%2F%20Serial.print(d_term)%3B%0A%09%2F%2F%20Serial.print(%22%5CtError%3A%20%22)%3B%0A%09%2F%2F%20Serial.print(error)%3B%0A%09%2F%2F%20Serial.print(%22%5CtFeedback%3A%20%22)%3B%0A%09%2F%2F%20Serial.println(feedback)%3B%0A%09return%20feedback%3B%0A%7D%0A” message=”” highlight=”” provider=”manual”/]
5.實際操作
相關文章:
- Arduino (Genuino) 101 與 ScratchX 環境建置
- [開箱文] Arduino 101 / Genuino 101 – Arduino.cc 與 Intel 合作,板載藍牙 BLE 與六軸加速度計/陀螺儀
- [活動紀錄 ] Arduino/Genuino 101 教學課程分享in Clubhouse
- [101專題計畫分享] Arduino101(Genuino 101)&App Inventor – RGB LED控制
- [程式教學] Arduino 101結合 Processing 互動滾球遊戲


















arduino uno 要做的話請問怎麼接線
您好,要買一個 IMU。這文章給您參考一下 https://maker.pro/arduino/projects/build-arduino-self-balancing-robot