《超圖解Arduino 互動設計入門》第二版內容更新說明

《超圖解 Arduino 互動設計入門》第二版基本資料:

《超圖解Arduino 互動設計入門》第二版封面

作者:趙英傑
出版社:旗標出版股份有限公司
出版日期:2014.04.24
頁數:640頁,雙色印刷。
定價:NT$680

書本封面上的數字2,改自Arduino官方的社群圖標(Community Logo),該網頁提供SVG和EPS圖檔格式:

Arduino社群標誌

Arduino控制板有許多不同的版本,目前的主流是UNO,因此本書(第二版)的Arduino控制板插圖,全數改成UNO與Leonardo(李奧納多),第一章當中的Windows和Mac OS X驅動程式安裝和操作,也做了對應的更新(註:第一版的應用範例也全都和UNO板相容)。

第二版依照讀者的建議和指教,修正並補充內容,例如第二章關於電容器元件的介紹、電源短路、第四章的遞增(++)運算子、第八章的C語言指標語法…等,使用App Inventor開發Android App單元(附錄E),也根據2.0版徹底改寫。更新內容的PDF文件以及範例原始碼,請參閱:Windows版App Inventor 2.0離線版軟體(Ai2LiveComplete)安裝說明與基礎操作

此外,書末也附上依主題分類的關鍵字索引,方便讀者查閱,像是C程式語言的語法,可瀏覽「程式設計基礎」分類。第一版的索引,請參閱這篇PO文

第二版的更新內容列舉如下:

第 01 章 認識 Arduino

UNO板腳位補充說明

請參閱「Arduino UNO控制板簡介

Mac OS X系統上的UNO控制板基本操作

Mac OS X不必安裝Uno的驅動程式即可使用。將Uno板接上Mac的USB埠,將能從系統資訊視窗的USB類別,看到Arduino「通訊裝置」的資訊。

Mac OS X 系統資訊視窗

在Mac OS X系統中,請選擇工具→序列埠選單底下,以tty.usbmodem為首的選項(若您的板子不是Uno,請選擇以tty.usbserial為首的選項,詳細說明請參閱第五章或者下文):

「工具→序列埠」選單

第 02 章 認識電子零件與工具

直插式與表面黏著式元件補充說明

本書採用的電子零件都有長腳(導線),這種零件通稱「直插式」,方便手工組裝及焊接。Arduino板子上的電子零件多數沒有長腳,外觀也微小許多,而且電阻也沒有色環。這種微小、方便機器直接焊接在電路板表面的零件,通稱表面黏著元件(Surface Mount Device,簡稱SMD)。

SMD表面黏著元件

短路補充說明

按照字面上的意思,「短路」就是「最短的路徑」,相當於一般道路的捷徑,更貼切的說法是,「阻礙最少、最順暢的通路」。

短路

電流和水流一樣,會往最順暢的通路流動。電源電路一定要有負載(電阻),萬萬不可將正負電源用導線直接相連,將有大量電流通過導線,可能導致電池或導線過熱,引起火災(因為導線的電阻值趨近於0,參閱4-31頁的歐姆定律,電阻值越小,電流量越大;電流越大,消耗功率和發熱量也越大)。

電容補充說明

理想的直流電壓或訊號,應該像下圖一樣的平穩直線,但是受到外界環境或者相同電路上其他元件的干擾而出現波動(正常訊號以外的波動,稱為「雜訊」),這有可能導致某些元件開開關關,令整個電路無法如期運作。

直流與雜訊

就像蓄水池能抑制水位快速變化一樣,即使突然間湧入大量的電流,電容的輸出端仍能保持平穩地輸出。在積體電路和馬達的電源接腳,經常可以發現相當於小型蓄水池的電容(又稱為「旁路電容」),用來平穩管路間的水流波動。

馬達的濾波電容

第 03 章 Arduino 互動程式設計入門

組合語言補充說明

早期的8位元微電腦的運算能力與記憶體容量都比Arduino的微控器小很多,因此經常採用接近機械碼的組合語言(Assembly)來開發程式,程式設計師必須先徹底了解處理器的架構才有辦法用組合語言寫程式,它的執行效率高,程式碼也最精簡,但是不容易閱讀和維護。不同微處理器的指令不盡相同,將來若替換成不同的微處理器,程式碼幾乎要全部重寫。

組合語言與組譯器

由於微控器效能和C語言編譯器的改良,使得C語言程式僅比組合語言程式的執行效率低10%~20%;而且C語言的可讀性、可移植性、容易開發…等的優點,可大幅彌補執行效率的缺點,所以就連嵌入式系統開發,也是以C語言為主流。

第 04 章 開關電路與 LED 跑馬燈效果

歐姆定律公式圖表更新

為了幫助記憶,原第一版4-31頁的歐姆定律公式說明,改成這張圖說:

歐姆定律

第 05 章 序列埠通信

USB序列埠補充說明

早期的Arduino板子採用RS-232介面,後來改用USB;某些Arduino控制板採用序列通訊轉換晶片(如:FT232R)來轉換USB與TTL序列訊號,Uno板使用MEGA16U2微控器

轉換USB序列TTL訊號的MEGA16U2微控器

MEGA16U2微控器在此負責銜接USB介面和Arduino的數位0與1腳。如果有需要的話,我們還可以改寫它的程式,讓電腦將此控制板看待成滑鼠、鍵盤、電玩搖桿或MIDI數位音樂介面。只不過,Arduino工具本身並不提供燒錄此微控器程式的功能,要透過另一個叫做FLIP的燒錄程式。

Mac OS X與Linux的通訊埠補充說明

Windows系統使用COM(原意是COMmunication,通訊)代表通訊埠,Mac OS X(一種基於Unix的作業系統)和Linux則用TTY代表通訊埠。

TTY的原意是"teletypewriter"(電傳打字機,早期用來操作並和大型電腦連線的終端機)。OS X和Linux系統把每個裝置都看待成檔案,位於/dev路徑底下,因此在Mac的終端機視窗輸入底下的命令,將能列舉所有通訊埠:

列舉TTY裝置的Mac OS X指令

從ls命令的執行結果可看出,筆者的電腦連接三種通訊裝置,每個裝置都有唯一的名稱。

列舉TTY裝置

通訊埠裝置的名稱格式如下,Uno板被辨識成modem(數據機,一種通訊裝置),採用FT232序列轉換晶片的Arduino控制板,被視為序列裝置。

通訊埠裝置的名稱格式

因此如果你的控制板不是Uno,請在Arduino軟體的連接埠選項選擇以usbserial開頭的那一個。除了TTY,Mac和Linux上的通訊埠還有包含一個同名的CU,因此同一個序列埠在Arduino的序列埠選單,有兩個選項。

tty與cu裝置

TTY用於傳入訊息給裝置,CU代表call up,用於從裝置傳出訊息,兩者合作就像雙向道路,能同時收發訊息此舉稱為全雙工。在Arduino上,無論使用TTY還是CU,都能傳遞訊息,但一般大多選用TTY。

UART與USART補充說明

第一版5-9頁的註解補充:本文介紹的 RS-232 和 USB 序列線,不需要同步線,因為它們會在資料前後加上「 開始」和「 結束」訊息。這種傳送方式統稱通用非同步收發傳輸器(Universal Asynchronous Receiver/Transmitter,簡稱UART)

除了TxD和RxD這兩個非同步序列傳輸接腳,ATmega微控器還具備SPI, I2C這兩種同步式序列傳輸介面,分別在第八章和第十一章介紹。

像ATmega這種兼具同步和非同步傳輸介面的硬體,又稱為通用同步∕非同步收發傳輸器(Universal Synchronous/Asynchronous Receiver/Transmitter,簡稱 USART)

第 08 章 LED 矩陣與 SPI 介面控制

更新指標(pointer)語法說明

第二版更改指標(pointer)的語法說明,這樣比較容易理解第一版8-41頁的記憶體位址加2的敘述:*(msg+2)

透過「位址」存取變數,需要借助*(星號)和&符號,它們的意義如下:

指標操作符號

*和&經常合併使用,在底下的範例敘述中,"&LED"將取得LED變數所在的位址,然後存入pt變數,在程式用語中,*pt稱為「指向LED位址的指標(pointer)」。

指標操作敘述

以上3行程式,可以拆解成底下4行:

指標操作敘述

凡是儲存「記憶體位址」的變數,前面都要加上*號(註:下圖中的記憶體位址編號是虛構的):

指標操作敘述

第 10 章 變頻控制LED 燈光和馬達

第一版10-33頁的馬達控制板接線圖,提供新增下圖的接線版本(在第二版內文中稱作A型控制板),自行DIY馬達控制板或者市售的L298N控制板,大多是這種類型(外觀可能不太一樣):

L298N馬達控制器

底下是用於A型馬達控制板的超音波與馬達的參數,以及轉向控制函數程式(B型馬達控制板的程式,請參閱書附光碟的diy10_6B.ino檔):

const byte TrigPin = 13;	// 超音波模組的觸發腳
const int EchoPin = 12;	 	// 超音波模組的接收腳
const int dangerThresh = 580;   // 10cm × 58
const byte speed = 100;		// 馬達的PWM輸出值

long distance;  		// 暫存接收訊號的高電位持續時間

const byte ENA = 5;  	// 馬達A的致能接腳
const byte ENB = 6; 	// 馬達B的致能接腳
const byte IN1 = 10;	// 馬達A的正反轉接腳
const byte IN2 = 9;	// 馬達B的正反轉接腳
const byte IN3 = 8;	// 馬達A的正反轉接腳
const byte IN4 = 7;	// 馬達B的正反轉接腳

byte dir = 0;     // 記錄行進狀態,0代表「前進」,1代表「右轉」。

void stop() {	  // 馬達停止
 analogWrite(ENA, 0);	// 馬達A的PWM輸出
 analogWrite(ENB, 0); 	// 馬達B的PWM輸出
}

void forward() {	   // 馬達轉向:前進(兩個馬達都正轉)
 analogWrite(ENA, speed);  // 馬達A的PWM輸出
 digitalWrite(IN1, HIGH);  // 請參閱表10-5的設定
 digitalWrite(IN2, LOW);
 analogWrite(ENB, speed);  // 馬達B的PWM輸出
 digitalWrite(IN3, HIGH);  // 請參閱表10-5的設定
 digitalWrite(IN4, LOW);
}

void backward() {	   // 馬達轉向:後退(兩個馬達都反轉)
 analogWrite(ENA, speed);  // 馬達A的PWM輸出
 digitalWrite(IN1, LOW);   // 請參閱表10-5的設定
 digitalWrite(IN2, HIGH);
 analogWrite(ENB, speed);  // 馬達B的PWM輸出
 digitalWrite(IN3, LOW);   // 請參閱表10-5的設定
 digitalWrite(IN4, HIGH);
}

void turnLeft() {	   // 馬達轉向:左轉(馬達A反轉、馬達B正轉)
 analogWrite(ENA, speed);  // 馬達A的PWM輸出
 digitalWrite(IN1, LOW);   // 請參閱表10-5的設定
 digitalWrite(IN2, HIGH);
 analogWrite(ENB, speed);  // 馬達B的PWM輸出
 digitalWrite(IN3, HIGH);  // 請參閱表10-5的設定
 digitalWrite(IN4, LOW);
}

void turnRight() {	   // 馬達轉向:右轉(馬達A正轉、馬達B反轉)
 analogWrite(ENA, speed);  // 馬達A的PWM輸出
 digitalWrite(IN1, LOW);   // 請參閱表10-5的設定
 digitalWrite(IN2, HIGH);
 analogWrite(ENB, speed);  // 馬達B的PWM輸出
 digitalWrite(IN3, HIGH);  // 請參閱表10-5的設定
 digitalWrite(IN4, LOW);
}

long ping() {			// 超音波感測程式
  digitalWrite(TrigPin, HIGH);  // 觸發腳設定成高電位
  delayMicroseconds(5);		// 持續5微秒
  digitalWrite(TrigPin, LOW);	// 觸發腳設定成低電位
  
  return pulseIn(EchoPin, HIGH);  // 測量高電位的持續時間(µs)
}

底下是主程式碼,它將每隔一秒鐘檢查一次距離:

void setup(){
   pinMode(TrigPin, OUTPUT);  // 觸發腳設定成「輸出」
   pinMode(EchoPin, INPUT);   // 接收腳設定成「輸入」
   // 馬達控制板的接腳全都設定成「輸出」
   pinMode(IN1, OUTPUT); 
   pinMode(IN2, OUTPUT);
   pinMode(IN3, OUTPUT); 
   pinMode(IN4, OUTPUT);
}

void loop(){
   distance = ping();  		// 讀取障礙物的距離
   if (distance>dangerThresh) {	// 如果距離大於10cm…
      if (dir != 0) {		// 如果目前的行進狀態不是「前進」
  	 dir = 0;	        // 設定成「前進」
	 stop();		// 暫停馬達0.5秒
	 delay(500);
      }
      forward();		// 前進
   } else {
      if (dir != 1) {	// 如果目前的狀態不是「右轉」
	 dir = 1;	// 設定成「右轉」
	 stop();	// 暫停馬達0.5秒
	 delay(500);		
      }
      turnRight();	// 向右轉
   }
   delay(1000);		// 持續1秒
}
Posts created 467

119 thoughts on “《超圖解Arduino 互動設計入門》第二版內容更新說明

  1. 恭喜老師這版書榮登各大網路與實體書局,暢銷書排行榜,並且又出修訂二版

  2. 最近在做RFID實驗用ARDUINO,用ARDUINO可以執行
    但我想把它用獨立的IC atmega328 執行同樣功能
    RFID為SPI介面,但我不知道要如何獨立把IC拿出來,然後接線

    1. hi bowk:

      請參閱B-7頁的ATmega328腳位編號對照圖,SPI介面位於Arduino板的10~13腳,對應到Atmega328的16~19腳。

      因此,取下Atmega328之後,只要將SPI介面改接到它的16~19腳即可。

      have fun!
      jeffrey

    1. 對,請參閱B-4頁的電路和麵包板圖說,你至少需要接底下這些元件,Atmega328才會如期運作:

      • 一個10K(棕黑橙)電阻
      • 一個0.1uF (104)電容(接在第7和第8腳)
      • 兩個22pF電容
      • 一個16MHz石英震盪器

      thanks,
      jeffrey

  3. 現在的接法是第一隻腳接10K電阻,然後接5V
    7,8腳間接電容
    然後7腳5V
    8腳接地
    9,10間接16M時因震盪器
    然後9接22P電容
    10接22p電容
    22p另外一角接地
    22腳接地
    20腳接+5
    19接LED接電阻在接地
    RC522 SPI介面
    SDA 接5腳
    SCK接19腳
    MOSI接17腳
    MISO接18腳
    GND 接 GND
    3.3V 用ams1117 穩成3.3 用電表量差不多3V

    用Arduino UNO 測試可以動作
    但單顆IC接動不了

  4. 閃爍實驗可以成功
    RFID部分還是不行
    好像需要RESET的樣子 加上去就正常了
    好像用ams1117 電壓不夠穩 倒置沒有動作

    1. Reset腳只要拉到高電位就沒問題,AMS117的輸出電流可達1A,所以除非那部分的電路有問題,否則應該蠻穩定的,許多微電腦控制板都是用這個穩壓IC。

      thanks,
      jeffrey

  5. 趙先生您好

    恭喜您出第二版了
    我也以最快速度拿到了這本書
    但有點疑惑的是
    封面畫了一個手機遙控電燈開關的圖
    但在內文中似乎並未提供此一教學案例
    有點可惜
    好想學手機控制家電啊
    是否可能以電子檔型式補充呢?
    謝謝

    1. hi tanj:

      真不好意思,其實我想表達的是用手機(或其他裝置,例如,PS Vita或任天堂3DS遊戲機)的瀏覽器,開啟第16章「網路家電控制」單元當中的網頁,即可控制家電。

      下週我找個時間更新內容,說明「行動版」網頁的製作方式。

      thanks,
      jeffrey

  6. 其實手機控制家電,可用趙老師書中的手機藍芽控制小馬達車,下去更改,老師你說對嗎?

    1. 沒錯!App Inventor也具備傳送POST表單資料的功能,只要讓Arduino根據收到的POST資料,做出對應的開關腳位控制,即可完成一個簡易的家庭自動化控制APP。

      App Inventor的POST傳輸設定方式,可搜尋”app inventor post data”關鍵字,就能找到許多相關資料。

      have fun!
      jeffrey

  7. 您好
    請問Arduino配上藍芽模組
    能否從用程式去取出藍芽的訊號強弱數值?
    是要用一般程式還是AT command??

    1. hi ko:

      藍牙訊號的強度由RSSI表示,其原意是Received Signal Strength Indicator(接收信號強度指示器)。
      我查閱了手邊的藍牙模組(HC-05版)的AT命令說明手冊,在第14頁最下面,有個探索其他藍牙裝置信號強度的操作示範,我沒測試過,但從說明書看來,操作步驟大致如下:

      1. 送出INQM命令,設定藍牙模組的探索存取模式(參閱說明書第7頁):

      AT+INQM=1,9,48

      等號右邊的第一個參數 1,代表採用RSSI模式;
      第二個參數代表偵測藍牙裝置數量的上限;
      第三個參數設定探索時間上限(48X1.28=61.44秒)

      2. 接著執行INQ命令,開始探索:

      AT+INQ

      它將傳回類似底下三個參數的16進位資料(參數之間用逗號分隔):

      +INQ:2:72:D2224,3E0104,FFBC

      第一個參數:藍牙裝置的位址
      第二個參數:裝置的類型
      第三個參數:訊號強度值

      thanks,
      jeffrey

  8. 直接洗成板子,成功了
    不過目前有個小小問題
    RFID是一個SPI介面
    當有TAG靠近時
    是SPI介面的哪隻腳會有變化(是MOSI嗎)
    用示波器量不太出來有哪隻腳變化
    不知道是因為哪隻腳傳資料給MCU
    給MCU判斷TAG裡面的編號

    1. SPI介面中,從周邊傳送資料到主機的線路是MISO(請參閱8-11頁);檢測和分析數位訊號,建議採用邏輯分析儀。

      thanks,
      jeffrey

  9. 最近經人介紹後買了一本,內容淺顯易懂,而且也有介紹基礎的電學常識,這是一般Arduino教學書所沒提到的,基礎打好將來在設計電路時比較不會鑄成大錯

    推薦大家來買

  10. 請問如果我要用大概四個開關去操作伺服馬達不同的角度可以嗎?
    下面是我寫的程式碼:
    #include <Servo.h>
    Servo servoS, servoP;

    const byte SW1 = 0;
    const byte SW2 = 1;
    const byte SW3 = 2;
    const byte SW4 = 3;

    void setup() {

    servoS.attach(8);
    servoP.attach(9);

    pinMode(SW1, INPUT);
    pinMode(SW2, INPUT);
    pinMode(SW3, INPUT);
    pinMode(SW4, INPUT);
    // put your setup code here, to run once:

    }

    void loop() {

    boolean val1 =digitalRead(SW1);
    boolean val2 = digitalRead(SW2);
    boolean val3 = digitalRead(SW3);
    boolean val4 = digitalRead(SW4);

    if (val1)
    {
    servoP.write(60);

    }
    else if(val2)
    {
    servoS.write (180);
    }
    else if(val3)
    {
    servoP.write(360);
    }
    else if (val4)
    {
    servoS.write(360);

    }

    }

    1. hi condy:

      這程式有兩個潛在的問題:

      1. 四個開關應該是個別獨立的,但依據程式的if … else if … 結構,一旦第一個if條件成立,其餘的 else if 都不會被執行。

      應該把它們分開成4個單獨的if條件式。

      2. 一般的伺服馬達的旋轉角度極限是180度,除非你購買的款式能連續旋轉,否則無法設定超過180度。

      thanks,
      jeffrey

  11. 你好~~我按照 超圖解Arduino 互動設計入門 9-1按照圖上的接線方式
    跟程式碼 對應起來好像怪怪的,圖上接線的方式 可否幫忙確認一下呢~~謝謝

  12. 老師您好,我有寫一個c的程式,請問老師我在
    #include
    #include
    #include
    這三樣,若需改成arduino的程式,是需要怎麼寫呢??
    麻煩老師指導,謝謝您

    1. hi lu:

      大於和小於符號被系統過濾掉了,請直接寫下程式庫的名字。

      thanks,
      jeffrey

  13. 很感謝老師您給學生的解答。
    想再跟老師詢問,學生在寫c語時,寫到陣列,並且也參考超圖解地8章發現
    學生在寫membership[2][3]={{-15,-10,-5},
    {-10,-5, 0}},

    但換成arduino上寫時,是否需要在前面加入const byte呢??

    1. Arduino的程式語言,本質上就是C語言,因此宣告變數時,也需要在前面冠上類型名稱;若不加上,編譯過程會發生錯誤。

      thanks,
      jeffrey

  14. 第二版,10-35页的,马达左转和右转的代码一样的,是不是写错了。
    void turnLeft() { // 馬達轉向:左轉(馬達A反轉、馬達B正轉)
    analogWrite(ENA, speed); // 馬達A的PWM輸出
    digitalWrite(IN1, LOW); // 請參閱表10-5的設定
    digitalWrite(IN2, HIGH);
    analogWrite(ENB, speed); // 馬達B的PWM輸出
    digitalWrite(IN3, HIGH); // 請參閱表10-5的設定
    digitalWrite(IN4, LOW);
    }

    void turnRight() { // 馬達轉向:右轉(馬達A正轉、馬達B反轉)
    analogWrite(ENA, speed); // 馬達A的PWM輸出
    digitalWrite(IN1, LOW); // 請參閱表10-5的設定
    digitalWrite(IN2, HIGH);
    analogWrite(ENB, speed); // 馬達B的PWM輸出
    digitalWrite(IN3, HIGH); // 請參閱表10-5的設定
    digitalWrite(IN4, LOW);
    }

    1. hi bulkmilk:

      的确错了,电脑的剪贴功能太好用了…右转要改成:

      void turnRight() {         // 馬達轉向:右轉(馬達A正轉、馬達B反轉)
       analogWrite(ENA, speed);  // 馬達A的PWM輸出
       digitalWrite(IN1, HIGH);   // 請參閱表10-5的設定
       digitalWrite(IN2, LOW);
       analogWrite(ENB, speed);  // 馬達B的PWM輸出
       digitalWrite(IN3, LOW);  // 請參閱表10-5的設定
       digitalWrite(IN4, HIGH);
      }
      

      感谢指正!

      thanks,
      jeffrey

  15. 老師您好 不好意思 想請問一下 我再跑下面主程式的時候 dir=0; 這行一直出錯 想請問是哪邊出了問題呢

    1. 我是照著上面給的程式碼進去跑.. 就跑出dir=0;這行有錯 下面是軟體跑出的字.. thanks
      sketch_sep02a:79: error: stray ‘\’ in program
      sketch_sep02a:79: error: stray ‘\’ in program
      sketch_sep02a.ino: In function ‘void loop()’:
      sketch_sep02a:79: error: ‘u3000′ was not declared in this scope
      sketch_sep02a:79: error: expected `;’ before ‘u3000’

    2. Oh~應該是HTML列出的原始碼中的空白,包含了特殊字元,請刪除loop()函數裡的“dir = 0;”敘述前面的空白,再測試看看。

      thanks,
      jeffrey

    3. 哦哦 有解決了!!
      想再請問一下老師
      第三行的程式 const int dangerThresh = 580; // 10cm × 58
      他的58是特定的數字嗎??
      還有第60行 delayMicroseconds(5); // 持續5微秒
      每隔一秒檢查一次距離是因為 5微秒x2=1秒?
      thanks!

    4. 58μs是常溫下,聲波移動1公分所需的時間,換算方式請參閱9-25頁;5μs是觸發超音波模組的時間。

      thanks,
      jeffrey

  16. 老師您好 不好意思 想請問一下 我上傳程式碼的時候 跑出
    avrdude: stk500_recv(): programmer is not responding
    avrdude: stk500_getsync() attempt 1 of 10: not in sync: resp=0x01
    avrdude: stk500_recv(): programmer is not responding
    avrdude: stk500_getsync() attempt 2 of 10: not in sync: resp=0x01
    avrdude: stk500_recv(): programmer is not responding
    avrdude: stk500_getsync() attempt 3 of 10: not in sync: resp=0x01

  17. 16_1_3或16_1_2,DHT11的例子,用dtostrf转换后,用Konqueror打不开网页,用FireFox可以打开,但打开后会一直在加载网页,就是标签里那个图标会一直在转圈圈,几秒后,会提示页面载入出错。这时,如果刷新网页,又能显示,但几秒后还是会出错,看不到网页。Arduino版本是 1.0.5,板子是ONU,网络模块为W5100。
    如果不用dtostrf函数(就是16_1_1例子)就不会有问题。

    我现在用另一个方法
    float temp = DHT11.temperature;
    float hum = DHT11.humidity;
    server << temp;
    server << hum;
    这样也不会有问题。

  18. 老師,請問一下,假如說在沒有用Arduino控制馬達的情況下(就是用現成的載具來裝載Arduino,簡單來說就是把Arduino放在遙控車上)那我如何判斷車子是前進還是後退?(是還要額外設三個變數媽???)(X:當下的距離值 Y:下一毫秒的距離值 Z: X-Y 所得出來的值 簡稱距離差) 利用判斷Z的正負來決定是否為前進或後退~ 請問這樣是可行的媽????如果可行,又如何編寫程式碼??? (以下是我們的程式碼還沒把判斷前進後退的程式碼打進去~) 請給予指教,謝謝您~

    #include

    const byte TrigPin = 6; // 觸發接腳 D6
    const byte EchoPin = 7; // 反射接腳 D7
    //const byte BuzzerPin = 9; // 蜂鳴器 D9

    int addrpin=7;
    int busypin=8;
    char addr;

    int cm; // 障礙物的距離
    long duration; // 測量距障礙物的反射波時間

    void setup() {
    Serial.begin(9600); // 啟用串列埠

    pinMode(TrigPin, OUTPUT);
    pinMode(EchoPin, INPUT);
    //pinMode(BuzzerPin, OUTPUT);

    pinMode(addrpin, OUTPUT);
    Serial.println(“program Start here”);

    }

    void loop() {
    //long cm;
    digitalWrite(TrigPin, LOW); // 按觸發的時序, 先讓Trig為低準位2us
    delayMicroseconds(2);
    digitalWrite(TrigPin, HIGH); // Trig為高準位10us
    delayMicroseconds(10);
    digitalWrite(TrigPin, LOW); // Trig為低準位2us
    delayMicroseconds(2);
    duration = pulseIn(EchoPin, HIGH); // 開始量測反射波的飛行時間 t
    cm = duration/58; // 轉換成距離

    後面還有,不過是其他的東西,跟測距無關

    1. hi michael:

      電子羅盤(指南針)或加速度計比較適合你的需求,也有不同的模組可供選擇,底下列舉兩個模組的程式庫提供你參考:

      ADXL345加速度計(可偵測x, y, z三軸的加速度值,支援SPI及I2C兩種介面)
      HMC5883L電子指南針(I2C介面)

      thanks,
      jeffrey

  19. 老師你好:
    第一版書4-14頁,你有提到上拉電阻越高,對於抗雜訊干擾能力越弱,這句話我不太了解,能否
    幫忙解惑

    1. hi jxchen:

      根據歐姆定律 V = I × R,電阻值越大,電路中的雜訊電流所產生的電壓值也越大。

      thanks,
      jeffrey

  20. 請問如果已經購買第一版的超圖解Arduino 互動設計入門,
    還有必要購買第二版嗎?
    因為買了才發現出第二版了哈哈
    如果買的是UNO或Leonardo,插線的位置也都與第一版的圖解位置相同嗎?

    1. 您好:

      第二版主要的更新在於,控制板插圖從Duemilanove改成UNO板,其餘內容變動不大,所以第一版的讀者沒有必要再購買第二版 🙂

      Duemilanove控制板和UNO的接腳相容,只是UNO多了幾個接腳,但是書本並沒有用到那些不同的接腳,所以兩者可以替換。

      Leonardo控制板的功能比較多,但接腳定義和UNO不太一樣,所以第二版範例仍以UNO為主。

      UNO和Leonardo控制板的介紹,請參閱這兩篇貼文:

      thanks,
      jeffrey

  21. 老師您好:
    想請教老師 如果要用可變電阻值去定義數字 我該怎麼做呢?
    目前是參考6-1讀取類比值 但是一直沒有頭緒 
    煩請老師指點一下
    謝謝您

    1. hi rick:

      所謂的「定義數字」,指的是「讀取可變電阻值,然後在序列埠監控視窗顯示對應的數值」嗎?
      在你的設想中,可變電阻值和輸出值的對應關係是什麼?例如,電阻值最大時,輸出1000嗎?

      thanks,
      jeffrey

  22. 老師您好:
    老師不好意思我說的有點模糊不清,我的意思是假設可變電阻在10K,我把它定義成90度角 
    類比輸入到板子,數位輸出到LCD,讓LCD顯示我所定義的數字 
    我試想,利用電阻值變換來感測角度。 

    想請問老師 可以參考課本哪個部分呢?
    謝謝您。

    1. 使用可變電阻測量旋轉角度,雖然可行,但須考量一些問題:

      耐用性問題:可變電阻的結構設計,可能沒有考量到透過機械構造經常轉動的情況。

      其次,如果可變電阻的阻值和角度變化是線性的,假設可變電阻的轉動角度是0~200度,我們可以透過底下的敘述得知大致的角度(map()函數請參閱10-8頁說明):

      int potValue; // 類比值
      int angle;  // 角度值
      :
      :
      void loop() {
        potValue = analogRead(potPin);  // 讀取可變電阻值
        angle = map(potValue, 0, 1023, 0, 200);  // 取得對應的角度值
        :
        :
      }
      

      如果可變電阻的阻值變化不是線性的,處理上比較麻煩。假設我們每隔5度,測量實際輸出的類比值,再透過if…else if …判斷結構,即可逐一比對出角度值,類似這樣:

      int potValue; // 類比值
      :
      :
      void loop() {
        potValue = analogRead(potPin);  // 讀取可變電阻值
      
        if (potValue < 10) {  // 假設小於10是在5度以內
          // 小於5度
        } else if (potValue < 20) {
          // 小於10度...
        } else if (potValue < 30) {
          // ...
        }
        :
        :
      }
      

      比較好的角度測量方法是透過「旋轉編碼器(Rotary Encoder)」,它會在轉動時輸出時脈訊號,只要計算時脈訊號數,就能得知轉動量;有些「絕對型」的旋轉編碼器,可傳回0~359度的編碼值。

      Arduino官網的Reading Rotary Encoders Contents這一篇文章有列舉好幾個現成的旋轉編碼器程式庫,以及範例程式碼,提供你參考。

      have fun!
      jeffrey

  23. 老師
    我買了第ㄧ版的書

    在11章 的伺服馬達 控制 的範例 是否有問題
    就是用兩個可變 控制兩個伺服馬達 xy. 的那章
    問題 A0. A1. 兩個訊號 接腳 控制 第8 跟9
    但是 我A0 給他訊號 8跟9 同時動作 A1 給他訊號
    8跟9的馬達也同時動作 ????

    1. 我測試是OK的,倒是伺服馬達的電源和接地線,以11-3頁的結構圖為主;請檢查一下兩個可變電阻的接線,中間的接點是否分別接到A0和A1。

      另外請查看程式裡的pinX, pinY、posX, poxY以及valX, valY變數的設定敘述是否正確,會不會是servoX和servoY都被設定成同一個值?

      thanks,
      jeffrey

  24. 趙老師你好

    我馬達只有ㄧ個

    所以可變的分壓訊號只有ㄧ組

    所以是作ㄧ個ㄧ個通道的測試
    所以因該沒有分接的壯況
    馬達的工能是正常的
    我程式是直接用光碟的範例 無改變
    發展板我測試過沒有接腳短路問題
    希望老師 po 出你的程式 讓我合對

    因為我只會pic.
    Pic的邏輯複雜 不方便快速運用
    Arduon 的邏輯太簡潔反而看不太懂

  25. 趙老師您好:
      我想請敎LCD問題,在實作16 * 2 LCD顯示器輸出,
    我的LCD顯示器在長時間(約12小時)的運作下,
    會發生顯示器上只剩下背光,而前景的文字內容會不見,
    每次都須重新開機,這是什麼問題呢?
    我該如何修正.
    謝謝.

    1. hi chen:

      如果不是程式造成的因素,例如:LCD模組的enable(致能)腳位(書本的範例接Arduino數位8腳)被更動,你可以嘗試接一個按鈕,每次按下它時,執行 “lcd.display();” 敘述,看看能否強置讓它顯示文字。

      thanks,
      jeffrey

  26. 感謝趙老師的執導

    我的兩個伺服馬達 控制問題 我以找出問題點

    是我實驗 方法不對 造成 A0. A1. 的訊號同時給 馬達輸出

    我把我錯誤的實驗方法回饋給老師

    我 因為偷懶 只作ㄧ組訊號源 給A0. 跟 A1. 用

    當測試 x馬達 拔起 A1訊號線 給A0用 這實後 A1控接
    當然 會出問題 沒用要接地
    有趣的事 我這樣的錯誤實驗 可以讓我ㄧ次用單ㄧ訊號
    控制兩個馬達 只要更改馬達map 呵哈 老師有興趣可是看看

    也要跟老師 說聲報謙 我ㄧ度以為 我買到地雷書
    也因為老師的書寫的很棒 讓我懷疑
    台灣的專業書籍 很多都是出書的教授用他的研究生的報告出書 這些學生 的論文都有些問題 或者 學生埋伏筆
    老師會開這論壇 也代表老師負責
    請趙老師原良 學生我的懷疑
    日後要是老師 出的書 我都會買 我有藏書的習慣
    謝謝老師

    1. 其實我也是從讀者的意見回饋來了解需要補充的內容,謝謝!

      thanks,
      jeffrey

  27. 老師 您好,
    請問這本書適合初學者快速入門嗎?
    家裡已有arduino套件卻不知如何快速上手。
    謝謝老師。

  28. 老師您好,

    我使用的是2013年6月版本的Arduino互動設計入門,我的IDE版本是1.6.0. 我發現在您書中的5-18設定序列輸出的數字格式中結果好像有錯誤。
    在您書中的 Serial.print(3.14159, 4) 輸出小數點後四位是 “3.1415”. 但是我的顯示是 “3.1416”. 在 Serial.print的指令中會進行四捨五入,供您做參考。

    Harry

  29. 老師 您好,
    接arduino的藍芽有辦法傳送浮點數嗎?
    還是只有整數才能藉由藍芽傳送?

    1. hi bill:

      可以,請把藍牙想像成道路,它有速度和長度限制,但是它不管你開車載運什麼物品(資料)。

      thanks,
      jeffrey

  30. 老師你好,請問在FILE下的expamle,有沒有相對應的電路圖解,因為不知如何接線?

  31. 老師你好;如果看不太懂程式的語言,可以參考什麼嗎?
    如const byte 是什麼意思??
    另外在動手做12-1 想將輸出改為蜂鳴器,要配什麼零件及如何寫程式及如何接線呢?
    有什麼網站可以參考的嗎?

    1. hi joseph:

      有些範例會在程式開頭的註解文字說明接線方式。

      有些留有程式作者的網站位址,也許可以在該網站找到更詳細的說明。

      有些則只是簡短幾行的語法示範,通常只要熟悉到一定程度之後,直接看程式碼就能理解,然後整合到自己的電路。

      書本裡面的程式碼,從書本第三章開始,都有基本程式語法的說明,像const(常數)、byte(位元組)…等等,你也可以從書本後面的索引查詢。建議你從前面的章節開始閱讀。

      蜂鳴器的電路和程式範例,請參閱第13章。

      thanks,
      jeffrey

  32. 作者你好,

    我在實作 “動手做5-1″時, 發生監控視窗沒有出現任何訊息, 為了測試接線和設定是否有問題? 我把所有要印出的命令行搬到loop 段落時, 就會一直重複印出. 這樣代表接線和設定應該是對的. 但是為何一開始沒有任何訊息??Thanks.

    1. hi duke:

      通常只有Leonardo板才會出現類似的情況,請在setup()函式加入底下的while迴圈:

      void setup()
      {
        Serial.begin(9600);
        while (!Serial) {
          ; // 等待序列埠連線
        }
      
        : 其餘的程式碼
      }
      

      thanks,
      jeffrey

  33. 老師您好~打擾您一下
    我最近剛開始接觸ARDUINO 我想利用ARDUINO控制一個伺服達
    想在0,30,60,90度各停止3秒
    這邊有打了一支90度的程式
    但是無法停止,他只會頓一下 然後繼續轉2秒
    想請問我需要如何修改呢~
    #include
    Servo myServo;
    void stop ()
    {
    myServo.attach(9);
    }

    void setup() {
    myServo.attach(9);
    }

    void loop() {

    myServo.write(90);
    delay(2000);
    stop();
    delay(3000);
    }

    1. hi rambo:

      請參考底下的程式:

      #include <Servo.h>
      Servo myServo;
      
      // 儲存旋轉角度的陣列
      byte deg[] = {0, 30, 60, 90};
      // 陣列索引
      byte index = 0;
      
      void setup() {
        myServo.attach(9);
      }
      
      void loop() {
        myServo.write(deg[index]);
        delay(3000);
        
        if (index < sizeof(deg)) {
          index ++;
        } else {
          index = 0;
        }
      }
      

      thanks,
      jeffrey

  34. 您好 :

    個人因於近期購入二版這一本書, 目前的操作在 LCD 顯示器這一些章節上面, 想在此回報一個可能是描述錯誤的部份.

    不過 …

    首先, 還是先讓個人在此感謝作者與出版社對此書籍的用心, 個人在上面學到了很多好玩又有趣的東西呢 ^^~

    可能問題說明 :

    在章節頁面 9-15 的 schematic 圖表中應該已經表示出,
    Arduino pin X 接 74LS164 pin 1 & 2. (serial input a & b / data )
    Arduino pin Y 接 74LS164 pin 8 (CLK)

    於章節頁面說明 LiquidCrystal_SR lcd( 8, 7, TWO_WIRE );
    這個部份有些問題, 雖然實際程式運作上不會有影響.
    >> 前兩個參數的說明可能寫反了 <<

    —-
    個人於書本上提供的連結所下載的 NewliquidCrystal Ver 1.3.3 版範例中的描述如下 :

    LiquidCrystal_SR lcd(8,7,TWO_WIRE);
    // | |
    // | \– Clock Pin
    // \—- Data/Enable Pin

    所以描述 Arduino pin X 應該是接 data/enable pin 的 (第一個欄位的說明);
    Arduino pin Y 應該是接 CLK pin 的(第二個欄位的說明)

    —-
    亦於 網站查得 74LS164 datasheet, 章節頁面 9-15 的 schematic 圖表應該是沒有問題的, 所以應可確認僅是此部份的描述出了些差錯.

    以上.

    —-
    附上 74LS164 datasheet link :
    http://www.datasheets360.com/pdf/1457824909462182119?query=sn74ls164&pqid=64403720

    1. hi robin:

      感謝指正!9-15頁的74LS164電路圖是正確的,但是9-18頁的程式庫說明有誤,下圖紅字部份才是正確的,謝謝!

      串接式LCD模組程式的宣告方式

      thanks,
      jeffrey

  35. 您好~~~ ,8-41頁指標(pointer)語法問題:
    8-41頁最後用while迴圈時,chr變數是字元格式char,
    而動手做8-6的scroll function是吃byte格式的輸入,也就是英文的ASCII十進位代碼,
    為什麼不需要經過轉換就可以了呢?
    而且若我把scroll function的(byte chr)改成(char chr),也可以執行,
    為什麼呢????
    scroll function不是要把ASCII碼丟進fonts.h去抓對應的字型圖案嗎?
    謝謝解答~~~~

    1. hi 阿華:

      拍謝,現在才看到你的訊息。請先參閱8-39頁,關於fonts陣列資料的定義,該陣列元素總共有127個。

      對照8-43頁pgm_read_byte()函式裡的fonts陣列參數,可以看到迴圈的chr變數是陣列元素的「索引」,其最大值只到127,在char類型的表達範圍內,所以程式也能執行無誤。

      thanks,
      jeffrey

  36. 老師您好:
    在動手做B-2,arduino實驗板中需要一個10K(棕黑橙)電阻,若是換成金屬皮膜的電阻五色環,須使用哪一種規格?
    因為不太了解瓦數的差異,謝謝

    1. 金屬皮膜電阻又稱為「精密電阻」,它的阻值比普通的碳膜電阻精確,跟瓦數沒有關聯。就自製麵包板的Arduino來說,10K電阻僅僅當作限流,不需要採用金屬皮膜電阻(整本書的例子,都是採用碳膜電阻),那個10K電阻來說,選擇1/4W或1/8W都行。

      消耗瓦數的計算範例,請參考10-39頁。

      thanks,
      jeffrey

  37. 老師您好
    我遇到的問題是
    當我寫2組超音波模組的時候
    會有一組的超音波模組沒有感應
    ㄧ組的話是可以的
    2組的程式碼如下

    #define TRIG_PIN 11
    #define ECHO_PIN 12
    #define TRIGPIN 10
    #define ECHOPIN 13

    #define LED1 8
    #define LED2 9

    long ping() {

    digitalWrite(TRIG_PIN, LOW);
    delayMicroseconds(2);
    digitalWrite(TRIGPIN, LOW);
    delayMicroseconds(2);
    digitalWrite(TRIG_PIN, HIGH);
    delayMicroseconds(10);
    digitalWrite(TRIGPIN, HIGH);
    delayMicroseconds(10);
    digitalWrite(TRIG_PIN, LOW);
    return pulseIn(ECHO_PIN, HIGH)/58;
    digitalWrite(TRIGPIN, LOW));
    return pulseIn(ECHOPIN, HIGH)/58;
    }

    }

    void setup() {
    pinMode(TRIGPIN, OUTPUT);
    pinMode(ECHOPIN, INPUT);
    pinMode(TRIG_PIN, OUTPUT);
    pinMode(ECHO_PIN, INPUT);
    pinMode(LED1, OUTPUT);
    pinMode(LED2, OUTPUT);
    }

    void loop() {
    long cm = ping();

    if (cm <= 100) {
    digitalWrite(LED1, HIGH);
    delay(cm*1.5 + 10);
    digitalWrite(LED1, LOW);
    digitalWrite(LED2, HIGH);
    delay(cm*1.5 + 10);
    digitalWrite(LED2, LOW);
    }

    delay(100);
    }

    1. hi 大賴:

      1. 我認為超音波的trig腳,可接到同一個訊號源,不用分接兩個腳。
      2. 函式程式碼在執行到return時,就結束,返回呼叫方,所以下一個return永不會被執行(請參閱5-4頁),所以你可以把兩個超音波測定函式分開寫,分別呼叫。
      3. 或者,寫在同一個函式,但是傳回值要用陣列,因為return的一般寫法只能傳回單一值;傳回陣列需要用指標和static變數等宣告,改天我再整理一篇文章說明。

      thanks,
      jeffrey

  38. 老師你好, 我在網上未曾見過有4位密碼RANDOM生產的編程 ,arduino可否做到生產後存到一個位置嗎???因學校PROJECT遇到很多ARDUINO 難題,求作者能解說一下

    1. 不太了解你的意思…Arduino的random()函數可產生長整數(long)的隨機數字,這不是夠用了嗎?

      thanks,
      jeffrey

  39. 老師你好
    我照者書中的18-1做,但是跑不出rfid的標籤,不過”rfid ready!”的字樣有出現

    1. “rfid ready”訊息只代表Arduino的序列通訊程式運作無誤。

      每一款RFID模組的通訊參數可能不太一樣,我採用的125KHz版本,只要感應到標籤,就會從序列埠以9600bps的速率輸出資料。請詢問賣家有沒有技術文件,確認一下它的通訊規格,或者你提供模組的規格連結給我看看。

      thanks,
      jeffrey

    1. 你購買的RFID模組跟書本採用的類似,請檢查模組的序列接線(Rx, Tx)是否正確,或者把它們反過來接看看。另外也請閱讀賣家提供的文件,看看是否要調整通訊速率。

      thanks,
      jeffrey

  40. 老師你好
    你說的方法都試過了,也還是讀不出來
    還是說有要先燒一些程式進去板子?

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

Related Posts

Begin typing your search term above and press enter to search. Press ESC to cancel.

Back To Top