owned this note
owned this note
Published
Linked with GitHub
###### tags: `blogger` date: `2018.04`
:::danger
本文章為舊版Blogger內容轉移,目前暫停維護
:::
# 使用 Arduino D1 製作 Wifi 自走車(上)
(搭配 AppInventor 2, IpCam)
<p style="text-align:center;"><img src="https://1.bp.blogspot.com/-ma23UwY2gSA/YP55ICnzShI/AAAAAAAAWU8/nSWJwQdIRkABVu5NPTdDr7HqD052SZD1QCLcBGAsYHQ/s320/qEClYDv.jpg" width="40%"></p>
## 一.摘要
  本專案將透過Arduino D1開發板作為核心來製作Wifi自走車。Arduino D1為一款擁有WiFi功能的Arduino開發版,相較於Arduino Yun更是便宜了不少,因此成為多數基礎物連開發的首選。然而Arduino D1 並不是沒有缺點,他的最大缺點「類比輸入只有一個腳位」導致許多感應器不能同時連到Arduino D1,不過對本文來說影響並不大,因此還是選擇了Arduino D1。
## 二.材料
| 材料名稱 | 數量 | 大約價格 |
| --------------------- | --- | ------ |
| Arduino D1 開發板 | 1片 | 180 |
| 自走車車體、減速馬達、車輪 | 1組 | 250 |
| L9110直流馬達驅動板 | 1片 | 30 |
| 3.7V鋰電池 | 2顆 | 170 |
| 鋰電池電池座 | 1個 | 20 |
| 電源供應板 | 1片 | 50 |
| 16\*2LCD ( 搭配I2C) | 1組 |100 |
| HC-SR04 超音波感應模組 | 1片 | 25 |
| 超音波感應模組托架 | 1個 | 40 |
| 杜邦線 | 數條 | 50 |
| M3銅柱、M3螺絲螺帽 | 數個 | 50 |
| 具有wifi功能之手機 | 2台 | |
| App inventor 2 | | |
| Arduino IDE | | |
## 三.D1腳位及運作架構圖
* Arduino D1
<p style="text-align:center;"><img src="http://i.imgur.com/HiFmAkz.png" width="30%"></p>
* 配線圖
<p style="text-align:center;"><img src="https://i.imgur.com/CtWQmFi.png" width="50%"></p>
* 流程圖
<p style="text-align:center;"><img src="https://i.imgur.com/CVdNOB6.png" width="70%"></p>
## 四.組裝車體
  車體組裝方式一各人有所不同,只要能運作即可,在此提供敝人的組裝方式:
1. 馬達與輪子的部分就直接跳過吧,相信各位不用3分鐘就能組裝完成
2. 底板下方的部分除了輪子外,L9110S馬達控制板也在此,並平行於馬達安裝,有6條杜邦線透過中間的圓孔穿透到底板上方連接Arduino D1及電源供應板。
<p style="text-align:center;"><img src="https://i.imgur.com/NImJ0bJ.jpg" width="35%"> <img src="https://i.imgur.com/KAqvjti.jpg" width="35%"></p>
3. 底板上方的部分即是Arduino D1、電源供應板、以及被拖架拖著的HC-SR04 超音波感應模組,電源供應板將電池的7.4~8.4V降為5V供D1使用,另外,馬達控制板(L9110S)使用的是未經變壓過的電源驅動馬達。(詳細腳位接法請見==3.D1腳位及運作架構圖==)
<p style="text-align:center;"><img src="https://i.imgur.com/Ul9TdG2.png" width="35%"> <img src="https://i.imgur.com/E6S1n7L.png" width="35%"></p>
4. 頂板為LCD、電池和一部手機,並使用銅柱固定
<p style="text-align:center;"><img src="https://i.imgur.com/2MRB6xt.jpg" width="35%"> <img src="https://i.imgur.com/mKGExtk.jpg" width="35%"></p>
## 五.車體Arduino程式碼
  關於Arduino IDE的設定可以參考佑來了的教學影片[Arduino教學- WiFi無線入門](https://www.youtube.com/watch?v=q-14MtNWltg)。開發板須設定為`WeMos D1(Retired)`本專案以範例檔`WifiWebServer`的架構改寫(如有註解不當或缺失歡迎留言補充)
**宣告部分**
```c=
/*函式庫宣告*/
#include <ESP8266WiFi.h>
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
/*常數宣告*/
const char* ssid = "WIFIARD"; //Wifi SSID
const char* password = "12345678"; //Wifi PassWord
const double usPcm = 29.4; //microSecond Per cm.
const float minDistance=10.00;
//距離下限(若低於距離下限則馬達不得前進)
/*變數宣告*/
String req = ""; //儲存接收到之字串
String stat =""; //車子狀態
//(B=測距模組失效,W=行進中,N=正常待命,D=距離前方障礙物過近)
int Speed_L = 0 ; //左馬達速度
int Speed_R = 0 ; //右馬達速度
float distance; //hc-sr04 距離
/*腳位宣告*/
#define hc_trig D10
#define hc_echo D11
#define motor_L_A D0
#define motor_L_B D1
#define motor_R_A D2
#define motor_R_B D5
#define lcd_SDA D14
#define lcd_SCL D15
/*其他宣告*/
WiFiServer server(80); //伺服器port宣告
LiquidCrystal_I2C lcd(0x27, 16, 2); //LCD宣告
```
**函式宣告**
```c=
String get_process_Message(WiFiClient client){ //接收並處理資料
req = client.readStringUntil('\r');
/*
* req=> GET /資料 HTTP/1.1
* replace(A, B) A換為B
*/
req.replace("GET /", "");//去頭
req.replace("HTTP/1.1", "");//去尾
client.flush();
Speed_L =req.substring(0,1).toInt()-5;
Speed_R =req.substring(1,2).toInt()-5;
}
void dataToHtml(WiFiClient client){ //資訊製網
String s = "HTTP/1.1 200 OK\r\nContent-Type:
text/html\r\n\r\n< !DOCTYPE HTML > < html >,";
s += String(String(Speed_L) + "," + String(Speed_R) + "," +
String(distance) + "," + String(stat) + ",< /html >");
client.print(s);
}
void printLcd(LiquidCrystal_I2C lcd, int R, int C, String text){ //LCD輸出
lcd.setCursor(R, C);
lcd.print(text);
}
float Ranging(){ //測距
float duration;
float distance;
digitalWrite(hc_trig, HIGH);
delayMicroseconds(200);
digitalWrite(hc_trig, LOW);
duration = pulseIn (hc_echo, HIGH);
distance = duration/2/usPcm;
return(distance-1);
}
void set_Motor(int Speed_L, int Speed_R){ //設定馬達速度
if(Speed_L>0){//設定左輪
analogWrite(motor_L_A,map(Speed_L,0,4,300,800));
analogWrite(motor_L_B,0);
}else if(Speed_L<0){
analogWrite(motor_L_A,0);
analogWrite(motor_L_B,map(Speed_L,0,-4,300,800));
}else{//(Speed_L==0)
analogWrite(motor_L_A,0);
analogWrite(motor_L_B,0);
}
if(Speed_R>0){//設定右輪
analogWrite(motor_R_A,map(Speed_R,0,4,300,800));
analogWrite(motor_R_B,0);
}else if(Speed_R<0){
analogWrite(motor_R_A,0);
analogWrite(motor_R_B,map(Speed_R,0,-4,300,800));
}else{//(Speed_R==0)
analogWrite(motor_R_A,0);
analogWrite(motor_R_B,0);
}
}
```
**初始化部分**
```c=
void setup() {
pinMode (hc_trig , OUTPUT);
pinMode (hc_echo , INPUT );
pinMode (motor_L_A, OUTPUT);
pinMode (motor_L_B, OUTPUT);
pinMode (motor_R_A, OUTPUT);
pinMode (motor_R_B, OUTPUT);
Wire.begin(lcd_SDA, lcd_SCL);
lcd.begin();
printLcd(lcd, 0, 0, "WELCOME");
delay(1000);
lcd.clear();
printLcd(lcd, 0, 0, "Connect to WIfi");
printLcd(lcd, 0, 1, "SSID:");
printLcd(lcd, 5, 1, ssid);
WiFi.begin(ssid, password);//連線至指定wifi
while (WiFi.status() != WL_CONNECTED) { //連線中
delay(500);
}
server.begin(); //啟用伺服器
lcd.clear();
printLcd(lcd, 0, 0, "WiFi connected!");
printLcd(lcd, 0, 1, WiFi.localIP().toString());
delay(1000);
}
```
**迴圈部分**
```c=
void loop() {
if (WiFi.status() != WL_CONNECTED) { //檢查連線
lcd.clear();
printLcd(lcd, 0, 0, "Lose connected!");
delay(2000);
return;
}
WiFiClient client = server.available();
if (!client) { //未接收訊息要做的事
distance =Ranging();
if(distance == -1.00){
stat="B";
}else if(distance < minDistance){
//若車子距離前方障礙物過近則馬達不得前進
if(Speed_L>0){
Speed_L=0;
}
if(Speed_R>0){
Speed_R=0;
}
stat="D";
}else if(Speed_L!=0 | Speed_R!=0){
stat="W";
}else{
stat="N";
}
set_Motor(Speed_L, Speed_R);
lcd.clear();
printLcd(lcd, 0, 0, String(distance));
printLcd(lcd, 10, 0, String(Speed_L));
printLcd(lcd, 13, 0, String(Speed_R));
dataToHtml(client);
delay(100);
return;
}
while(!client.available()){
delay(1);
} //接收到資料要做的事
get_process_Message(client);
distance =Ranging();
if(distance == -1.00){
stat="B";
}else if(distance < minDistance){
//若車子距離前方障礙物過近則馬達不得前進
if(Speed_L>0){
Speed_L=0;
}
if(Speed_R>0){
Speed_R=0;
}
stat="D";
}else if(Speed_L!=0 | Speed_R!=0){
stat="W";
}else{
stat="N";
}
set_Motor(Speed_L, Speed_R);
lcd.clear();
printLcd(lcd, 0, 0, String(distance));
printLcd(lcd, 10, 0, String(Speed_L));
printLcd(lcd, 13, 0, String(Speed_R));
dataToHtml(client);
delay(10);
}
```
## 以下三部分請見 [使用 Arduino D1 製作 Wifi 自走車(下)](http://bo-sgoldhouse.blogspot.tw/2018/04/arduino-d1-wifi_15.html)
* 六.即時影像傳輸
* 七.手機控制端App介面
* 八.手機控制端程式碼
==感謝您閱讀本文章==