Arduino基础知识复习12.18
文章目錄
- 前言
- 一. 原型技術(shù)中的編程基礎(chǔ)(Arduino C)
- a. 變量和數(shù)據(jù)類型
- 浮點(diǎn)型變量
- 數(shù)組
- String
- C字符串
- 比較和位運(yùn)算
- *復(fù)合運(yùn)算和賦值
- *字符串和數(shù)字的互相轉(zhuǎn)化
- b. 程序結(jié)構(gòu)控制
- 順序
- 選擇
- 循環(huán)
- c. 函數(shù)
- d. 庫的使用
- 內(nèi)置庫
- 創(chuàng)建自己的庫
- 二. 物理原型開發(fā)基礎(chǔ)(Arduino)
- a. 交互式硬件原型的開發(fā)基礎(chǔ):電流、常?電?元件、示意圖與電路圖,萬?表、焊接、 ?包板的使?。
- b. 串?通信
- 串口(UART)
- 硬件串口
- 串口通訊的函數(shù)
- 軟件串口
- 多個(gè)串口
- c. 簡單數(shù)字和模擬輸?
- 開關(guān)
- 按鍵消抖
- 數(shù)字鍵盤
- 模擬輸入
- *多路復(fù)用模擬輸入
- 測量電壓
- d. 獲取傳感器輸?
- 動作(數(shù)字量高低電平,類似開關(guān))
- 動作檢測(集成被動紅外探測器PIR,只需判斷模擬量高電平)
- 光(光敏電阻模擬量)
- 距離(超聲波,輸出模式純凈高電平+輸入模式計(jì)算脈沖時(shí)間)
- 精確測距(*紅外IR傳感器比超聲波精度高但量程小,輸出非線性需要查表)
- 振動(壓電傳感器/爆震傳感器,應(yīng)力越大電壓越高。模擬量)
- 聲音
- 溫度
- *RFID標(biāo)簽
- *旋轉(zhuǎn)動作(旋轉(zhuǎn)編碼器)
- *鼠標(biāo)
- *GPS
- *加速度(陀螺儀測量角加速度,加速度計(jì)測量移動加速度如重力加速度)
- e. 可視輸出、物理輸出、聲?輸出
- 顯示
- 電機(jī)
- 音頻
- f. ?線通信和?絡(luò)
- * I2C和SPI
- 無線XBEE
- 藍(lán)牙
- *互聯(lián)網(wǎng)
- 三. 上述技術(shù)在設(shè)計(jì)原型制作和開發(fā)中的應(yīng)?。
- 1.接收到____信號時(shí),_____動作
- 2.智能水杯(傳感器、顯示器、LED、蜂鳴器、藍(lán)牙等等綜合運(yùn)用)
前言
含星號*的不太常用。閱讀前最好有一點(diǎn)基礎(chǔ)知識,可以看個(gè)視頻入門一下。本文參考書為Arduino Cookbook(Michael Margolis 等著)中譯本《Arduino權(quán)威指南》。Arduino是開放的電子開發(fā)平臺,包含硬件和軟件。
常用的一種硬件Arduino UNO如下圖:
記:
左邊5V輸出、GND引腳, 0-5模擬引腳
右邊USB接口 GND 13-0數(shù)字引腳(3 5 6 9 10 11支持PWM)
模擬引腳帶ADC功能,10位精度,analogRead(pin),可將0~5V的電壓轉(zhuǎn)換為0 ~1023
PWM:脈沖寬度調(diào)制。analogWrite(pin,value); value值改變的是PWM的脈沖寬度,范圍為0~255
一. 原型技術(shù)中的編程基礎(chǔ)(Arduino C)
Arduino中的程序長這樣:
const int ledPin=13;//LED連接到數(shù)字引腳13 void setup() {pinMode(ledPin,OUTPUT);//以輸出方式初始化一個(gè)引腳 } void loop() {digitalWrite(ledPin,HIGH);//點(diǎn)亮LEDdelay(1000);//等待1000ms即1sdigitalWrite(ledPin,LOW);//熄滅LEDdelay(1000); }a. 變量和數(shù)據(jù)類型
| int | 2 | -32768~36767 | 整數(shù)值 |
| unsigned int | 2 | 0~65535 | 正整數(shù)值 |
| long | 4 | -2^16~ 2 ^16-1 | 大范圍整數(shù) |
| unsigned long | 4 | 0~2^32-1 | 大范圍正整數(shù) |
| float | 4 | 3.4028235E+38~-3.4028235E+38 | 帶小數(shù)部分的數(shù)字,7位有效十進(jìn)制數(shù)字(32位存儲巨大范圍內(nèi)的所有值,8位用于小數(shù)位置(指數(shù)),剩下24位留給符號和數(shù)值) |
| double | 4 | 同float | 在arduino里只是float的另一個(gè)名稱 |
| boolean | 1 | false(0)或true(1) | 代表true或false值 |
| char | 1 | -128~127 | 代表單個(gè)字符,也可以代表范圍內(nèi)的有符號值 |
| Byte | 1 | 0~255 | 類似char,但無符號值 |
其他:
string:char陣列(字符),通常用來包含文本
void:僅用在無返回值的函數(shù)聲明
浮點(diǎn)型變量
/* 浮點(diǎn)例子 初始化浮點(diǎn)值至1.1,每次減少0.1至0 */ boolean almostEqual(float a, float b);//定義了一個(gè)布爾型返回值的函數(shù)“視作幾乎相等”, float value=1.1; void setup() {Serial.begin(9600); } void loop() {value=value-0.1;if(value==0)Serial.println("the value is exactly zero");else if(almostEqual(value,0))//比較此時(shí)value值和0的差距是否近似相等{Serial.print("The value");Serial.print(value,7);//打印到7位小數(shù)Serial.println("is almost equal to zero");}elseSerial.println(value);delay(100); }/*定義了一個(gè)布爾型返回值的函數(shù)“視作幾乎相等”,輸入形式參數(shù)為a和b,如果a和b之前差很小,則返回true把DELTA的值設(shè)成能視作相等的最大差值*/boolean almostEqual(float a, float b){const float DELTA=.00001;//視作幾乎相等的最大差值if (a==0) return fabs(b) <=DELTA;//fabs() 浮點(diǎn)絕對值if (b==0) return fabs(a) <=DELTA;//上面的if代碼是為了防止分母為0報(bào)錯(cuò)return fabs((a-b)/max(fabs(a),fabs(b))) <= DELTA;//其實(shí)我感覺用這一句就夠了return fabs(a-b)<=DELTA;}數(shù)組
/* 數(shù)組程序 由開關(guān)陣列控制LED陣列 */int inputPins[]={2,3,4,5}; //為開關(guān)輸入創(chuàng)建引腳陣列 int ledPinds[]={10,11,12,13};//為LED輸出創(chuàng)建引腳陣列void setup() {for(int index=0;index<4;index++){pinMode(ledPins[index],OUTPUT);//聲明LED對應(yīng)引腳為輸出模式pinMode(inputPins[index],);//聲明按鍵對應(yīng)引腳為輸入模式digitalWrite(inputPins[index],HIGH);//按鍵引腳,允許上拉電阻} }void loop() {for(int index=x;index<4;index++){int val=digitaleRead(inputPins[index]);//讀取輸入值if(val=LOW)//檢查開關(guān)是否按下{digitalWrite(ledPins[index],HIGH);//如果按下就點(diǎn)對應(yīng)燈}else{digitalWrite(ledPins[index],LOW);//熄滅LED}} }
要點(diǎn):使用數(shù)字引腳,開關(guān)接GND,LED需要接電阻和GND
String
/*arduino字符串和c字符數(shù)組相比使用簡單,但存在內(nèi)存泄露、占用問題。 */String text1="2只老虎"; String text2="愛跳舞"; String text3;//在程序內(nèi)被賦值void setup() {Serial.begin(9600);Serial.print(text1);Serial.print("is");Serial.print(text1.length());//length()返回字符數(shù)Serial.println("characters long.");Serial.print("text2 is");Serial.print(text2.length());Serial.println("characters long.");text1.concat(text2);Serial.println("用了text1.concat(text2);后text1變?yōu)?#34;);Serial.println(text1); //加法運(yùn)算符可以結(jié)合字符串text3=text1+text2;Serial.println("用了text3=text1+text2;后text3=");Serial.println(text3);}void loop(){}
C字符串
//strcpy(destination,source);//復(fù)制字符串從source到de
//strncpy(destination,source,6);//復(fù)制6個(gè)字符從source到de
//strcat(destination,source);//復(fù)制字符串從source到de的結(jié)尾
String text1=“Arduino”;
char stringA[8];//聲明長達(dá)7個(gè)字符加上終止空字符的字符串
char stringB[8]=“Arduino”;//同上,并初始化
char stringC[16]=“Arduino”;//同上,但字符串有加長的空間
char stringD[]=“Arduino”;//由編譯器初始化串并計(jì)算大小
* text1.concat(stringC);可以兼容,但+不能兼容char和string
比較和位運(yùn)算
1.字符和數(shù)量值
比較相等關(guān)系
== != < > >= <=
if (strcmp(string1,string2)==0) //判斷相等則返回0值,第一個(gè)大返回值大于零,否則小于0 //*可以在string2后加“,4”指定判斷4個(gè)字符Serial.print("相等");2.邏輯比較
&&與 ||或 !非
3.位運(yùn)算
&按位與,二進(jìn)制數(shù),如果兩個(gè)位都是1,才設(shè)置運(yùn)算后的那個(gè)位為1,如3&1等于1(11&01=01)
|按位或,對應(yīng)的兩個(gè)位有1得1,3|1=11(11|01=11)
^按位異或,對應(yīng)的兩個(gè)位是一個(gè)1才設(shè)置1,如5 ^ 4 =2(110 ^ 100=010)
~取反,反轉(zhuǎn)每個(gè)位(比特bit)的值,如 ~ 1 =254(~00000001=11111110)
4.余數(shù)
%
5.其他常用計(jì)算函數(shù)
abs(x)計(jì)算x的絕對值 constrain(x,min,max)返回一個(gè)在min和max范圍內(nèi)的值 min(x,y) max(x,y)
返回最值 pow(x,y) 計(jì)算x的y次方 sqrt(x) x的平方根 floor(x) 向下取整,不大于x的最大整數(shù)值
ceil(x)向上取整,不小于x的最小整數(shù)值 sin(x) cos(x) tan(x)
*設(shè)置和讀取位
最右邊是最低位 bitSet(x,bitPosition) 設(shè)置 寫入1 bitClear(x,bitPosition)清除 寫入0
bitRead(,)返回指定位的值 bitWrite(x,bitPosition,value)
設(shè)置x的第bitPosition位為value值(0或1) bit(bitPosition)返回給定的比特位置的值 bit(0)=1
bit (1)=2 bit(2)=4
所以8個(gè)開關(guān)的狀態(tài)可以包裝成一個(gè)單一的8位值,而不需要8個(gè)字節(jié)或整數(shù) int整數(shù)值剛好由2個(gè)字節(jié),16個(gè)位組成。
取高低字節(jié)就是取高8位低8位:
本質(zhì)上是位運(yùn)算,所以可以自己定義這樣的函數(shù)如下
//w為32位數(shù),取高16位就是把整體右移16位。宏表達(dá)式為 #define highWord(w) ((w)>>16) //取低16位就是把高16位變成0,可以用高16位為0的數(shù)去 與運(yùn)算 #define lowWord(w) ((w) & 0xffff )*從高字節(jié)和低字節(jié)組合成一個(gè)int或long值
word(high,low)把高低字節(jié)組裝成一個(gè)16位值(2字節(jié))
*復(fù)合運(yùn)算和賦值
| += 或-=和*=或/= | value+=5;//本身加5,用于遞增或遞減 |
| >>=或<<= | value>>=2;//向右移動2位 |
| &=或 |= | value&=2;//用2對value做二進(jìn)制 與屏蔽 |
*字符串和數(shù)字的互相轉(zhuǎn)化
/* *1.從給定數(shù)字創(chuàng)建一個(gè)字符串 itoa 從整數(shù)到ASCII碼,Itoa長整數(shù)到ASCII碼 */void setup() {Serial.begin(9600);}char buffer1[12];//long數(shù)據(jù)類型有11個(gè)字符 包括減號和末尾空字符void loop(){long value=15;itoa(value,buffer1,2);//要轉(zhuǎn)的值value,將要存放輸出字符串的緩沖區(qū)為buffer1,2進(jìn)制// Serial.print(value);Serial.print(buffer1);Serial.print("為轉(zhuǎn)換的二進(jìn)制值,有");Serial.print(strlen(buffer1));Serial.print("位數(shù),");value=23333;itoa(value,buffer1,16);Serial.print(value);Serial.print("轉(zhuǎn)為16進(jìn)制數(shù)");Serial.print(buffer1);Serial.print("有");Serial.print(strlen(buffer1));Serial.println("位數(shù)");delay(1000);}//結(jié)果:1111為轉(zhuǎn)換的二進(jìn)制值,有4位數(shù),23333轉(zhuǎn)為16進(jìn)制數(shù)5b25有4位數(shù) /* *2.從給定字符串創(chuàng)建一個(gè)數(shù)字 */ const int ledPin=LED_BUILTIN;//LED連接的管腳、 int blinkDelay;//閃爍周期 char strValue[6]; int index=0;//存儲所接收的數(shù)字的數(shù)字索引 void setup() {Serial.begin(9600);pinMode(ledPin,OUTPUT);//LED引腳為輸出}void loop(){if(Serial.available()){char ch=Serial.read();//讀取電腦串口發(fā)來的文字為ASCII字符Serial.print(ch);if(index<4 && isDigit(ch)){//緩沖區(qū)未滿而且ch是數(shù)字字符strValue[index++]=ch;//在字符串里加上ASCII字符}else{//這里是當(dāng)緩沖區(qū)滿或者遇到第一個(gè)非數(shù)字strValue[index]=0;blinkDelay=atoi(strValue);//使用atoi將字符串轉(zhuǎn)換為int,賦值給閃爍周期值index=0;}}blink();}void blink() {digitalWrite(ledPin,HIGH);delay(blinkDelay/2);//等待閃爍周期的一半digitalWrite(ledPin,LOW);delay(blinkDelay/2);//等待閃爍周期的一半}//這個(gè)程序存在的缺陷是一旦開始閃爍了,delay期間就不會執(zhí)行任何串口的監(jiān)測b. 程序結(jié)構(gòu)控制
順序
選擇
1.if
if()
{
語句;
}
2.switch
只能整型或者字符型
switch(字符變量) {case '1':函數(shù)1;break;case '+':函數(shù)2;default:函數(shù)3break; }循環(huán)
1.while
while(條件){} do { } while(條件);2.for
for(int i=0;i<4;i++){ ...}3.跳出循環(huán)
break;
continue;
c. 函數(shù)
int blink3(int period)
{…}
返回類型 函數(shù)名 (參數(shù)類型 參數(shù)名字)
需要函數(shù)返回多個(gè)值可以在最開始定義全局變量,然后在函數(shù)中改變?nèi)肿兞俊R部梢允褂靡?#xff0c;符號&表示該參數(shù)是引用,函數(shù)內(nèi)值的變化也將改變調(diào)用該函數(shù)時(shí)被賦值的變量的值。如下:
void swap(int &value1,int &value2)
返回類型 函數(shù)名 (參數(shù)類型 &參數(shù)名字)
函數(shù)聲明:告知編譯器你要引用函數(shù),出現(xiàn)在頂部,結(jié)束加分號如下:
void swap(int &value1,int &value2);
常用函數(shù)先略,后面出現(xiàn)再介紹。
d. 庫的使用
內(nèi)置庫
#include <Servo.h>//頭文件在庫的文件夾
#include “Servo.h”//頭文件在當(dāng)前文件夾
一些常用的庫:SoftwareSerial軟串口
SPI以太網(wǎng)和SPI硬件
Wire I2C設(shè)備
Stepper 步進(jìn)電機(jī)的工作
*其他:
EEPROM內(nèi)存 Ethernet以太網(wǎng)通訊 FIrmata簡化串行通訊和板卡控制的協(xié)議
LiquidCrystal 液晶顯示器 SD支持使用外部硬件讀取和寫文文件到SD卡
Matrix 管理LED陣列
Sprite 激活與LED陣列…
創(chuàng)建自己的庫
*可以先不看
#開頭的語句被稱為預(yù)處理命令
#define 標(biāo)識符字符串 宏定義
#include 文件包含 條件編譯 用來防止重復(fù)定義
#ifndef 標(biāo)識符 程序段
#endif
#if 表達(dá)式 程序段1
#else 程序段2
#endif
/* 創(chuàng)建一個(gè) blinkLED.cpp 一個(gè)以給定的毫秒數(shù)時(shí)間點(diǎn)亮LED的簡單庫
*/
#include “Arduino.h”//arduin函數(shù)和常數(shù)的庫所需要的
#include “blinkLED.h”//包含了你庫的函數(shù)定義
//在給定的引腳以給定的時(shí)間閃爍LED void blinkLED(int pin, int duration) {
digitalWrite(pin, HIGH); //打開LED delay(duration);
digitalWrite(pin, LOW); //關(guān)閉LED delay(duration); }
/* 再創(chuàng)建一個(gè)blinkLED.h要放在和cpp文件一起的文件夾*/
#include “Arduino.h” void blinkLED(int pin, int duration);//函數(shù)原型
//最后在blinkLibTest程序中#include “blinkLED.h”
關(guān)鍵字高亮顯示需要再建立一個(gè)keywords.txt文件,鍵入:你的關(guān)鍵詞 KEYWORD1
二. 物理原型開發(fā)基礎(chǔ)(Arduino)
a. 交互式硬件原型的開發(fā)基礎(chǔ):電流、常?電?元件、示意圖與電路圖,萬?表、焊接、 ?包板的使?。
面包板原理圖
從原理圖可以看到,面包板上下區(qū)是橫向5位相通,一般用于接電源和接地,中間區(qū)域是縱向5位相通,通常用于放置電路元件和電路連接線。
電阻:對電流起阻礙作用的元件。
電容:裝電的容器,旁路、去耦、濾波、儲能作用。
二極管:單項(xiàng)傳導(dǎo)電流,整流、穩(wěn)壓作用。
三級管:放大、振蕩、開關(guān)作用。EBC三級,有兩種是PNP和NPN。
繼電器:可控電子開關(guān),原理電磁效應(yīng)控制線圈。
傳感器
電阻類:光敏電阻(光亮電阻降)
人體熱釋電紅外傳感器:對人體輻射出的紅外線敏感,無人在監(jiān)測范圍內(nèi)輸出低電平,有人輸出高電平脈沖信號。
溫度傳感器
五相傾斜:內(nèi)部由一個(gè)金屬球和4個(gè)觸點(diǎn)組成,檢測4個(gè)傾斜方向和水平位置共5種狀態(tài)。
觸摸模塊:電容觸摸感應(yīng)原理檢測人體接觸,有人高無人低。
模擬聲音傳感器:檢測周圍環(huán)境聲音的大小
氣體傳感器:使用氣敏材料是在清潔空氣中電導(dǎo)率較低的二氧化錫,當(dāng)傳感器所處環(huán)境中存在可燃?xì)怏w時(shí),傳感器的電導(dǎo)率隨著空氣中可燃?xì)怏w濃度的增加而增大。使用簡單的電路就可以將電導(dǎo)率的變化轉(zhuǎn)換為與該氣體濃度相對應(yīng)的輸出信號。
時(shí)鐘模塊:雖然arduino的millis()和micro()可以獲取運(yùn)行時(shí)間,但是到一定時(shí)間就會溢出,而且斷電不保存,可以用時(shí)鐘模塊準(zhǔn)確、長時(shí)間計(jì)時(shí)。
顯示器
b. 串?通信
串口(UART)
一種信息交互方式,硬件提供Arduino和它正在與之通信的設(shè)備之間的電信號,軟件使用硬件發(fā)送所連接的硬件可以理解的字節(jié)或位。
硬件位于0(RX) 1(TX)兩個(gè)引腳。
Arduino的串口庫隔離了大部分硬件的復(fù)雜性,比較容易使用。
硬件串口
原理:串口硬件的發(fā)送和接收表示序列位的電脈沖數(shù)據(jù)。Arduino使用TTL電平表示構(gòu)成字節(jié)信息的0和1,用0V表示比特率0 , 5V(或3.3V)表示比特值1。
大多數(shù)arduino板子有一個(gè)芯片把硬件串口轉(zhuǎn)換成通用串口總線USB,用于連接到其他硬件串口。有的設(shè)備使用RS-232標(biāo)準(zhǔn)進(jìn)行串口連接,通常有9針連接器,是一種舊的通訊協(xié)議,采用的電壓與arduino不兼容。
Arduino Mega有4個(gè)硬件串口,可以與4個(gè)串口設(shè)備進(jìn)行通訊,其中一個(gè)有USB接口
串口通訊的函數(shù)
1.初始化
Serial.begin(9600);//發(fā)送和接受的波特率范圍是300~115200。9600,即每秒鐘傳輸9600個(gè)“位元”(比特bit)
2.輸出
Serial.print() 打印完不換行
Serial.println(“char1”);
Serial.println(char1); 打印完換行
Serial.println(char1,HEX);//HEX是16進(jìn)制形式輸出 OCT是10進(jìn)制 BIN是二進(jìn)制
(*print和write的區(qū)別,print發(fā)送的不是數(shù)據(jù)本身而是轉(zhuǎn)換為字符,然后將字符對應(yīng)的ASCII碼發(fā)出去,串口監(jiān)視器收到ASCIII碼就會顯示對應(yīng)的字符,而write發(fā)送的是數(shù)值本身,串口監(jiān)視器收到后會把數(shù)值當(dāng)做ASCII碼而顯示對應(yīng)的字符)
3.輸入
Serial.read()
調(diào)用該函數(shù)時(shí),arduino會從64B的緩沖區(qū)中取出1B的數(shù)據(jù)
4.Serial.available();
返回值就是當(dāng)前緩沖區(qū)中接收到的數(shù)據(jù)字節(jié)數(shù)
*串口事件 void serialEvent(){} 當(dāng)串口緩沖區(qū)中有數(shù)據(jù),就會觸發(fā)該事件。
*可以利用C++的流插入語法和模板,如果聲明了一個(gè)流模板就可以使用它。
可以簡化為 Serial<< “At” << t <<“seconds,speed=”<< s <<", distance =" << d << endl;
舉一個(gè)USB串口通訊的實(shí)例(實(shí)際上在前面已經(jīng)涉及過了)
/* 打印數(shù)字到串口監(jiān)視器 */ void setup() {Serial.begin(9600);//發(fā)送和接受的波特率范圍是300~115200。9600,即每秒鐘傳輸9600個(gè)“位元”(比特bit) } int number=0; void loop() {Serial.print("The number is ");Serial.println(number);//打印數(shù)字并換行delay(500);number++; }也可以再復(fù)習(xí)一下這個(gè)用Serial.read接收電腦從串口傳來的數(shù)據(jù),然后轉(zhuǎn)為數(shù)字,改變LED閃爍周期的。
接受單個(gè)數(shù)字的
復(fù)雜一點(diǎn)的,要用C語言轉(zhuǎn)換函數(shù)atoi或atol把文本轉(zhuǎn)化為數(shù)字
/* *從給定字符串創(chuàng)建一個(gè)數(shù)字 */ const int ledPin=LED_BUILTIN;//LED連接的管腳、 int blinkDelay;//閃爍周期 char strValue[4];//最多包含4位數(shù)字 int index=0;//存儲所接收的數(shù)字的數(shù)字索引 void setup() {Serial.begin(9600);pinMode(ledPin,OUTPUT);//LED引腳為輸出}void loop(){if(Serial.available()){char ch=Serial.read();//讀取電腦串口發(fā)來的文字為ASCII字符Serial.print(ch);if(index<4 && isDigit(ch)){//緩沖區(qū)未滿而且ch是數(shù)字字符strValue[index++]=ch;//在字符串里加上ASCII字符}else{//這里是當(dāng)緩沖區(qū)滿或者遇到第一個(gè)非數(shù)字strValue[index]=0;blinkDelay=atoi(strValue);//使用atoi將字符串轉(zhuǎn)換為int,賦值給閃爍周期值index=0;}}blink();}//這個(gè)程序存在的缺陷是一旦開始閃爍了,delay期間就不會執(zhí)行任何串口的監(jiān)測 void blink() {digitalWrite(ledPin,HIGH);delay(blinkDelay/2);//等待閃爍周期的一半digitalWrite(ledPin,LOW);delay(blinkDelay/2);//等待閃爍周期的一半}可以學(xué)習(xí)一下處理思路,實(shí)戰(zhàn)可以直接用Serial.parseInt()或Serial.parseFloat()讀取串口字符,并返回表示的數(shù)值
/* *parseInt方法從給定字符串創(chuàng)建一個(gè)數(shù)字 */ const int NUMBER_OF_FIELDS =3;//預(yù)計(jì)有多少個(gè)逗號分割的字段 int fieldIndex=0;//接受的當(dāng)前字段 int values[NUMBER_OF_FIELDS];//保存所有字段數(shù)值的數(shù)組void setup() {Serial.begin(9600);}void loop(){if(Serial.available()){for(fieldIndex=0;fieldIndex<3;fieldIndex++){values[fieldIndex]=Serial.parseInt();//獲取一個(gè)數(shù)值}Serial.print(fieldIndex);Serial.println("fields received:");for(int i=0;i<fieldIndex;i++){Serial.println(values[1]);}}}發(fā)送多個(gè)文本最簡單的方法就是字符分割
軟件串口
一個(gè)標(biāo)準(zhǔn)的arduino有一個(gè)硬件串口,但你也可以用軟件庫來模擬附加的端口(通信通道),以連接一個(gè)以上的設(shè)備,即軟件串口,它需要耗費(fèi)內(nèi)存資源,所以速度效率不如硬件串口。
程序示例:
#include <softwareSerial.h>
const int rxpin=2;//用于接收LCD的引腳 const int txpin=3;//用于傳送到LCD顯示屏的引腳 SoftwareSerial
serial_lcd(rxpin,txpin);//新的串口為引腳2個(gè)和3個(gè)
void setup(){serial_lcd.begin(9600);}
多個(gè)串口
1.只有RX接收腳的LCD
/*
在同一時(shí)間將數(shù)據(jù)發(fā)送到兩個(gè)串口設(shè)備,硬件串口
*/
//void setup(){ // 初始化mega的兩個(gè)串口
Serial.begin(9600);//主串口
Serial1.begin(9600);//mega也可以用serial1到serial3 }
/*
SoftwareSerialOutput
輸出數(shù)據(jù)到軟件串口
*/
#include <softwareSerial.h>
const int rxpin=2;//用于接收LCD的引腳
const int txpin=3;//用于傳送到LCD顯示屏的引腳
SoftwareSerial serial_lcd(rxpin,txpin);//新的串口為引腳2個(gè)和3個(gè)
void setup()
{
Serial.begin(9600);
serial_lcd.begin(9600);//初始化軟件串口也為9600b/s
}
int number=0;
void loop(){
serial_lcd.print("The number is ");//文本發(fā)送到LCD
serial_lcd.print(number);
Serial.print("the number is ");//在PC控制臺打印數(shù)字
Serial.print(number);
delay(1000);
number++;
}
GPS同理,
區(qū)別是軟串口的波特率改為4800
loop中改為這一段
c. 簡單數(shù)字和模擬輸?
開關(guān)
if(digitalRead(inputPin)=HIGH)
{digitalWrite(ledPin,HIGH)}
arduino內(nèi)部有上拉電阻,可以不用外部電阻,程序需要修改一下
按鍵消抖
本程序針對下拉電阻,按鈕按下輸入arduino高電平
const int inputPin=2;//輸入引腳號 const int ledPin=13;//輸出引腳號 const int debounceDelay=10;//穩(wěn)定之前循環(huán)等待的次數(shù)//按鍵穩(wěn)定閉合debounceDelay時(shí)間,則返回true boolean debounce(int pin) {boolean state;//用于記錄本次狀態(tài)boolean previousState;previousState=digitalRead(pin);for(int counter=0;counter<debounceDelay;counter++){delay(1);//每次延時(shí)1msstate=digitalRead(pin);if(state!=previousState)//按鍵狀態(tài)發(fā)生變化{counter=0;//計(jì)數(shù)器重新計(jì)數(shù)previousState=state;}}//按鍵狀態(tài)不變return state;}void setup(){pinMode(inputPin,INPUT);pinMode(ledPin,OUTPUT); }void loop(){if(debounce(inputPin)){digitalWrite(ledPin,HIGH);}}如果用前面提到的上拉電阻,就要改變一下boolean debounce的返回值如下:
boolean debounce(int pin){boolean state;boolean previousState;previousState=digitalRead(Pin);for(counter=0;counter<debounceDelay;counter++) {//增加debounceDelay值直到計(jì)數(shù)與按鍵動作同步delay(1);//等待1msstate=digitalRead(pin);//讀取引腳if(state!=previousState){counter=0;state=previousState;}}if(state==LOW)//low表示按下return true;elsereturn false; }//用count顯示按壓的次數(shù) int count; void setup() {pinMode(inPin,INPUT)pinMode(outPin,OUTPUT) } void loop {if (debounce(input)){digitalWrite(outPin,HIGH);count++;Serial.println(count);} }/*
*switchTime 函數(shù)將返回開關(guān)被按壓的毫秒數(shù)
*使用上拉電阻
*靜態(tài)變量,即使在函數(shù)返回后仍然保留,只能在該函數(shù)內(nèi)訪問,好處是不能被一些其他函數(shù)意外地修改
*/
const int switchAPin=2;//開關(guān)2 的引腳
const int switchBPin=3;//開關(guān)3 的引腳
//帶引用的函數(shù)必須顯式聲明
unsigned long switchTime(int pin, boolean &state,unsigned long &startTime);
long switchATime();
long switchBTime();
void setup()
{
pinMode(switchAPin,INPUT);
digitalWrite(switchAPin,HIGH);//打開上拉電阻
pinMode(switchBPin,INPUT);
digitalWrite(switchBPin,HIGH);//打開上拉電阻
}
void loop(){
unsigned long time;
Serial.print(",按鍵A的時(shí)間為:");
time=switchATime();
Serial.print(time);
Serial.print(",按鍵B的時(shí)間為:");
time=switchBTime();
Serial.print(time);
delay(1000);
}
unsigned long switchTime(int pin,boolean &state, unsigned long &startTime)
{
if(digitalRead(pin)!=state)//檢查開關(guān)量是否改變
{
state=!state;//是 則反轉(zhuǎn)狀態(tài)值
startTime=millis();//存儲時(shí)間
}
if(state == LOW)
return millis()-startTime;//返回以毫秒為單位的時(shí)間
else{return 0;//開關(guān)沒有按下 在HIGH狀態(tài)
}
}
long switchATime()
{
//聲明靜態(tài)變量
//開關(guān)狀態(tài)改變第一次檢測被檢測到的時(shí)間
static unsigned long startTime=0;
static boolean state;//開關(guān)的當(dāng)前狀態(tài)
return switchTime(switchAPin,state,startTime);
}
long switchBTime()
{
//聲明靜態(tài)變量
//開關(guān)狀態(tài)改變第一次檢測被檢測到的時(shí)間
static unsigned long startTime=0;
static boolean state;//開關(guān)的當(dāng)前狀態(tài)
return switchTime(switchBPin,state,startTime);
}
數(shù)字鍵盤
按鍵相當(dāng)于一個(gè)常開開關(guān)
模擬輸入
**analogRead()**會自動設(shè)置輸入,
0V對應(yīng)0,5V對應(yīng)1023
/* 按一個(gè)電位器的位置設(shè)置的速度閃爍LED 注意區(qū)分模擬輸入0和數(shù)字輸入0
*/
const int potPin = 0; //選擇電位器的輸入引腳
const int ledPin = 13;
int val = 0;
void setup()
{
pinMode(ledPin, OUTPUT); //
}
void loop() {
val = analogRead(potPin); //讀取電位器上的電壓
digitalWrite(ledPin, HIGH);
delay(val);
digitalWrite(ledPin, LOW);
delay(val);
}
/* 按一個(gè)電位器的位置設(shè)置的速度閃爍LED
*/
const int potPin = 0; //選擇電位器的輸入引腳
const int ledPin = 13;
int val = 0;
void setup()
{
pinMode(ledPin, OUTPUT);
Serial.begin(9600);
}
void loop() {
val = analogRead(potPin); //讀取電位器上的電壓
int percent;//映射的值
percent=map(val,0,1023,0,100);//map整數(shù)運(yùn)算讀取的電壓值對應(yīng)百分比 的映射
digitalWrite(ledPin, HIGH);
delay(percent);
digitalWrite(ledPin, LOW);
delay(100-percent);
Serial.println(percent);
}
*多路復(fù)用模擬輸入
測量電壓
應(yīng)用:電量不足時(shí)LED閃爍,到臨界電壓級別時(shí)LED長亮
long warningThreshold = 1200; //毫伏在警告級別 - LED閃爍
long criticalThreshold = 1000; //臨界電壓級別 - LED長量
const int batteryPin = 0;
const int ledPin = 13;
void setup()
{
pinMode(ledPin, OUTPUT);
}
void loop()
{
int val = analogRead(batteryPin);
if (val < (warningThreshold * 1023L / 5000))
{ //在上面的行中 一個(gè)數(shù)后跟L得到一個(gè)32位的值
flash(val / 1023);
}
else if (val < (criticalThreshold * 1023L / 5000))
{
digitalWrite(ledPin, HIGH);
}
}
void flash(int percent)
{ digitalWrite(ledPin, HIGH);
delay(percent + 1);
digitalWrite(ledPin, LOW);
delay(100 - percent); //檢查延時(shí)==0?
}
d. 獲取傳感器輸?
傳感器提供信息的方式:
數(shù)字開關(guān):傾斜 動作傳感器
模擬信號:光 振動 聲音 加速度
脈沖寬度:距離傳感器 pulseln命令測量脈沖持續(xù)時(shí)間
串口:RFID GPS
同步協(xié)議:I2C SPI
通用傳感設(shè)備 鼠標(biāo)和游戲控制器等
各傳感器原理簡介見二、a
動作(數(shù)字量高低電平,類似開關(guān))
//傾斜傳感器
const int tiltSensorPin = 2; //連接傳感器 的引腳
const int firstLEDPin = 11;
const int secondLEDPin = 12;
void setup() {
pinMode(tiltSensorPin, INPUT); //設(shè)置 傳感器引腳 為輸入
digitalWrite(tiltSensorPin, HIGH); //上拉電阻
pinMode(firstLEDPin, OUTPUT);
pinMode(secondLEDPin, OUTPUT);
}
void loop() {
if (digitalRead(tiltSensorPin) )
{
digitalWrite(firstLEDPin, HIGH);
digitalWrite(secondLEDPin, LOW);
}
else {
digitalWrite(firstLEDPin, LOW);
digitalWrite(secondLEDPin, HIGH);
}
}
可以理由按鍵消抖的原理消抖,程序略
動作檢測(集成被動紅外探測器PIR,只需判斷模擬量高電平)
這種傳感器引腳標(biāo)有OUT - +
長這個(gè)樣子的傳感器基本上都是這么控制的↓,但是要注意信號電平的高低。
//紅外傳感器控制LED
const int inputPin = 2; //連接傳感器 的模擬輸入引腳2
const int ledPin = 13;
void setup() {
pinMode(ledPin, OUTPUT); //聲明LED作為輸出
pinMode(inputPin , INPUT); //被動紅外傳感器為輸入引腳
}
void loop() {
int val = digitalRead(inputPin);
if (val == HIGH)
{ digitalWrite(ledPin, HIGH);
delay(500);
digitalWrite(ledPin, LOW);
}
}
光(光敏電阻模擬量)
//光敏電阻控制LED
const int SensorPin = 0; //連接傳感器 的模擬輸入引腳0
const int ledPin = 13;
void setup() {
pinMode(ledPin,OUTPUT);//LED引腳設(shè)為輸出
}
void loop() {
int rate=analogRead(sensorPin);//讀取模擬輸入
digitalWrite(ledPin,HIGH);//設(shè)置LED開
== delay(rate);//等待時(shí)間取決于光照水平==
digitalWrite(ledPin,LOW);//設(shè)置LED開
delay(rate);//等待時(shí)間取決于光照水平
}
距離(超聲波,輸出模式純凈高電平+輸入模式計(jì)算脈沖時(shí)間)
//超聲波距離傳感器控制LED
const int pingPin = 5; //連接傳感器 的模擬輸入引腳5
const int ledPin = 13;
void setup() {
pinMode(ledPin, OUTPUT); //聲明LED作為輸出
Serial.begin(9600);
}
void loop() {
int cm = ping(pingPin); Serial.println(cm);
digitalWrite(ledPin, HIGH);
delay(cm * 10); //每厘米增加了10ms的延遲
digitalWrite(ledPin, LOW);
delay(cm * 10);
}
int ping(int pingPin)
{ long duration, cm;
pinMode(pingPin, OUTPUT); //首先要給一個(gè)簡短的的低電平脈沖以確保高電位脈沖觸發(fā)
digitalWrite(pingPin, LOW);
delayMicroseconds(2);
digitalWrite(pingPin, HIGH);
delayMicroseconds(5);
digitalWrite(pingPin, LOW);
pinMode(pingPin, INPUT); //傳感器引腳改為輸入模式,接受信號
duration = pulseIn(pingPin, HIGH); //計(jì)算出傳感器引腳輸入從低到高的時(shí)間,單位為微秒
//時(shí)間轉(zhuǎn)換成距離
cm = duration * 29/ 2;//來回距離 超聲波速度29us/cm
}
有不需要ping的超聲波傳感器,也是用pulseIn(pingPin, HIGH),是計(jì)算脈沖寬度,直接讀值就可以。測量距離=pulseIn(pingPin, HIGH)*脈沖寬度速率
精確測距(*紅外IR傳感器比超聲波精度高但量程小,輸出非線性需要查表)
//紅外距離傳感器 測距輸出
const int sensorPin = 0; //連接傳感器 的模擬輸入引腳0
const int ledPin = 13;
const long referenceMv = 5000; //長整形以防止做乘法時(shí)溢出
void setup() {
pinMode(ledPin, OUTPUT); //聲明LED作為輸出
Serial.begin(9600);
}
void loop() {
int val = analogRead(sensorPin);
== int mv = (val * referenceMv) / 1023;==//mv為距離信號
Serial.print(mv);
Serial.print(",");
int cm = getDistance(mv);
Serial.println(cm);
digitalWrite(ledPin, HIGH);
delay(cm * 10); //每厘米增加了10ms的延遲
digitalWrite(ledPin, LOW);
delay(cm * 10);
}
const int TABLE_ENTRIES = 12;
const int firstElement = 250; //第一項(xiàng)是250mv
const int INTERVAL = 250; //每個(gè)項(xiàng)之間的毫伏數(shù)
static int distance[TABLE_ENTRIES] = {150, 140, 130, 100, 60, 50, 40, 35, 30, 25, 20,15};//器件手冊提供 假設(shè)單位是cm
int getDistance(int mV)
{
if (mV < INTERVAL )//判斷是否在范圍內(nèi), 可能還要寫個(gè)超出最大距離的判斷
return distance[TABLE_ENTRIES - 1]; //當(dāng)距離比最小距離要小,返回最小距離
else
{
int index = mV / INTERVAL; //計(jì)算近似的信號值
float frac = (mV % 250) / (float)INTERVAL;//取余數(shù),然后除以每項(xiàng)之差,用來插值計(jì)算
return distance[index] - ((distance[index] - distance[index + 1])* frac);
//返回計(jì)算出的距離值
}
}
振動(壓電傳感器/爆震傳感器,應(yīng)力越大電壓越高。模擬量)
val=analogRead(sensorPin);
if(val>=THRESHOLD){…}
聲音
//駐極體話筒
const int sensorPin = 0; //連接傳感器 的模擬輸入引腳0(可以省略
const int ledPin = 13;
const int middleValue = 512; //模擬值范圍的中間值
const int numberOfSamples = 128; //每次讀取多少個(gè)數(shù)過小無法覆蓋完整波形周期,過大可能錯(cuò)過短的聲音
int sample;//每次讀取的值
long signal;//你已經(jīng)去除直流偏移之后的讀數(shù)
long averageReading;//循環(huán)讀數(shù)的平均值
long runningAverage = 0; //計(jì)算值的運(yùn)行平均數(shù)
const int averagedOver = 16; //新值以何種程度影響運(yùn)行平均值,數(shù)字越大速度越慢
const int threshold = 400; //在什么水平LED亮
void setup() {
pinMode(ledPin, OUTPUT); //聲明LED作為輸出
Serial.begin(9600);
}
void loop() {
long sumOfSquares = 0; //正負(fù)幅值的平方和
for (int i = 0; i < numberOfSamples; i++) {
sample = analogRead(0); //讀取一個(gè)數(shù)
signal = sample - middleValue; //算模擬信號 距離 直流中心值 的 偏移
signal *= signal;
sumOfSquares += signal;
}
averageReading = sumOfSquares / numberOfSamples; //計(jì)算運(yùn)行平均值
runningAverage = ((averagedOver - 1) * runningAverage + averageReading) / averagedOver;
//即新運(yùn)行平均值=原運(yùn)行平均值+(這次采樣平均值-原運(yùn)行平均值)/16,分母averagedOver越大,每次改變就越小
//新值影響平均值的速度就越慢
if (runningAverage > threshold) {
digitalWrite(ledPin, HIGH);
}
else {
digitalWrite(ledPin, LOW);
}
Serial.println(runningAverage);//打印檢查
}
const int TABLE_ENTRIES = 12;
const int firstElement = 250; //第一項(xiàng)是250mv
const int INTERVAL = 250; //每個(gè)項(xiàng)之間的毫伏數(shù)
static int distance[TABLE_ENTRIES] = {150, 140, 130, 100, 60, 50, 40, 35, 30, 25, 20, 15}; //器件手冊提供
int getDistance(int mV)
{
if (mV < INTERVAL * TABLE_ENTRIES - 1)
return distance[TABLE_ENTRIES - 1]; //當(dāng)距離比最小距離要大,返回最小距離
else
{
int index = mV / INTERVAL; //插值計(jì)算,
float frac = (mV % 250) / (float)INTERVAL;
return distance[index] - ((distance[index] - distance[index + 1]) * frac);
}
}
溫度
類似光敏傳感器,該溫度傳感器模擬電壓與溫度成正比,需要寫相應(yīng)程序計(jì)算。
*RFID標(biāo)簽
RFID 射頻識別,對無線電頻率敏感,易被干擾。
硬件圖注意讀取器有使能和輸出引腳,前一個(gè)是arduino用來發(fā)給它激活信號(低電平)的,后一個(gè)是它把接收到的RFID傳輸給Arduino的,占用了硬串口,理論上你應(yīng)該不能用電腦看到傳輸了什么數(shù)據(jù)。程序?qū)崿F(xiàn)RFID讀取并對特定ID回應(yīng):
const int startByte = 10; //每個(gè)標(biāo)簽之前的ASCII換行符
const int endByte = 13; //ASCII回車結(jié)束每個(gè)標(biāo)簽
const int tagLength = 10; //標(biāo)簽數(shù)位
const int totalLength = tagLength + 2; //標(biāo)簽的長度 + 開始和結(jié)束字節(jié)
char tag[tagLength + 1]; //保存標(biāo)簽和一個(gè)終止空白符
int bytesread = 0;
void setup() {
Serial.begin(2400);//設(shè)置為RFID閱讀器的波特率
pinMode(2, OUTPUT); //輸出到RFID
digitalWrite(2, LOW); //使能RFID}
}
void loop() {
if (Serial.available() >= totalLength) //檢測是否有足夠數(shù)據(jù)
{
if (Serial.read() == startByte)
{ bytesread == 0; //標(biāo)簽的開始,重置計(jì)數(shù)為0
while (bytesread < tagLength) //讀取10位編碼
{ int val = Serial.read();
if ((val == startByte) || (val == endByte)) //檢查編碼結(jié)束
break;
tag[bytesread] = val;
bytesread = bytesread + 1; //準(zhǔn)備讀取下一個(gè)數(shù)字
} if (Serial.read() == endByte) //檢查正確的結(jié)束字符
{ tag[bytesread] = 0; //終止字符串
Serial.print(“RFID 標(biāo)簽是:”);
Serial.println(tag);
}
}
}
}
*旋轉(zhuǎn)動作(旋轉(zhuǎn)編碼器)
測量并顯示某物的旋轉(zhuǎn),跟蹤速度和方向
代碼邏輯:
首先把AB對應(yīng)的4、2引腳置為輸入模式,然后寫高激活,
當(dāng)A腳的狀態(tài)和上次測量不同時(shí),(上升沿或者下降沿)
B是低的,編碼器位置減1,
若B高電平,編碼器位置加1。
最后計(jì)算角度=(編碼器位置 %走一圈的步數(shù))*360度/走一圈的步數(shù)
拓展知識:中斷
利用中斷可以實(shí)現(xiàn)只有在收到傳感器信號“當(dāng)A腳的狀態(tài)和上次測量不同時(shí),(上升沿或者下降沿)”的時(shí)候程序才會去檢查傳感器值,而不是始終檢查傳感器值。
*鼠標(biāo)
*GPS
*加速度(陀螺儀測量角加速度,加速度計(jì)測量移動加速度如重力加速度)
e. 可視輸出、物理輸出、聲?輸出
顯示
1.數(shù)字輸出
pinMode(outputPin,OUTPUT)
digitalWrite(outputPin,value)
2.模擬輸出(uno的3 5 6 9 10 11引腳可以用)
analogWrite()
使用了一種脈沖寬度調(diào)制PWM技術(shù),用數(shù)字脈沖模擬一個(gè)模擬信號
3.燈光控制。LED燈、陣列和數(shù)碼顯示,LCD文本和圖形顯示。
4.LED規(guī)格
5.復(fù)用,多個(gè)LED復(fù)用引腳,利用視覺暫留,靠按位掃描驅(qū)動。
利用復(fù)用技術(shù)16個(gè)引腳即可控制64個(gè)LED,
依次點(diǎn)亮所有LED的程序邏輯如下:
首先在setup中循環(huán)調(diào)好所有的行列引腳為輸出模式
然后在loop中,計(jì)數(shù)當(dāng)前為第n個(gè)燈,/和%計(jì)算出行列值,
之后for循環(huán)掃描每一行列依次點(diǎn)燈,具體為:拉低當(dāng)前列,要判斷當(dāng)前點(diǎn)的燈有沒有達(dá)到n的位置,未達(dá)到或者剛好達(dá)到就輸出行高電平,超過就輸出低電平,最后延時(shí)為這個(gè)LED給出20ms的幀時(shí)間,然后給低電平,關(guān)燈。
6.最大引腳電流 <40mA <200mA。驅(qū)動高功率需要用晶體管和外接電源。
計(jì)算LED串聯(lián)的電阻值
數(shù)碼管
這個(gè)是共陽極,給低電平點(diǎn)亮 段
數(shù)碼管相當(dāng)于8位LED串聯(lián),分共陰極和共陽極
驅(qū)動單位共陽極數(shù)碼管的程序邏輯:
首先定義數(shù)組存儲字形碼
const byte numeral[10]={
//ABCDEF/dp 共陰極的字形碼
B11111 1100,//0
, , , , …};2 個(gè)字節(jié)的每一位可以代表一個(gè)引腳的輸出狀態(tài)
然后定義引腳,設(shè)置為輸出模式
在循環(huán)中調(diào)用數(shù)碼管顯示函數(shù)顯示值,延時(shí)
數(shù)碼管顯示的函數(shù):void showDigit(int number),循環(huán)檢查是否點(diǎn)亮 for(int segement=1;segment<8;sengment++) 用到bitRead(numeral[number],segment) 讀給定數(shù)字的字形碼,賦值給isBitSet,如果為1,則isBitSet != isBitSet ,如果是共陰極數(shù)碼管就不用這個(gè)操作,最后對應(yīng)引腳拉低。
驅(qū)動多位LED數(shù)碼管顯示器
在單位的基礎(chǔ)上,增加一個(gè)位數(shù)循環(huán),依次點(diǎn)亮指定位指定的led段
為解決引腳占用,可以接MAX7221等數(shù)碼管驅(qū)動芯片,需要查芯片的命令手冊,并用到SPI通信,
用自定義函數(shù)sendCommend(int command, int value)發(fā)送指令函數(shù),利用digitalWrite(使能引腳,LOW) SPI.transfer(command);SPI.transfer(value); digitalWrite(使能引腳,HIGH)
電機(jī)
1.舵機(jī) 即直流伺服電機(jī)。分為帶位置反饋的角度控制舵機(jī)和斷開位置反饋的連續(xù)旋轉(zhuǎn)舵機(jī)。
紅正棕負(fù)橙信號
控制舵機(jī)角度:
第一步庫和對象
#include <Servo.h>//引入舵機(jī)庫
Servo myservo;//創(chuàng)建舵機(jī)對象來控制指定舵機(jī)
第二步 信號引腳連接對象
void setup()
{
myservo.attach(9);//把連接在引腳9上的舵機(jī)賦予舵機(jī)對象
}
第三步使用wite寫角度
void loop()
{
myservo.write(angle);
}
正反轉(zhuǎn)搖擺:
#include <Servo.h>//引入舵機(jī)庫 Servo myservo;//創(chuàng)建舵機(jī)對象來控制舵機(jī)int angle = 0; //用來存儲舵機(jī)位置的變量void setup() {myservo.attach(9);//把連接在引腳9上的舵機(jī)賦予舵機(jī)對象 }void loop() {for (angle = 0; angle < 180; angle++){ //步長為1度myservo.write(angle);delay(20);//舵機(jī)命令之間等待20ms}for (angle = 180; angle > 0; angle--){myservo.wirte(angle);//在相反方向上移動舵機(jī)delay(20);}}如果是連續(xù)旋轉(zhuǎn)舵機(jī),控制同理,但是給90°停止轉(zhuǎn)動,距離90°越遠(yuǎn),向一個(gè)方向轉(zhuǎn)速越快。
2.有刷電機(jī)和無刷電機(jī)
可用H橋電路控制有刷電機(jī),直接用元件即可,需要接一個(gè)用來使能的模擬引腳用analogWrite()PWM控制速度,一對數(shù)字引腳控制不同方向旋轉(zhuǎn)和停止。
具體略。
可利用業(yè)余調(diào)速器控制無刷電機(jī) 代碼和舵機(jī)代碼相等
3.步進(jìn) 每步走1°、2°、30°或更多。也是H橋,但可以用Stepper的庫
4.振動馬達(dá) 像點(diǎn)亮LED一樣就行,代碼見第"三"部分
音頻
揚(yáng)聲器原理
壓電裝置:施加脈沖時(shí)會產(chǎn)生聲音的陶瓷換能器
有源蜂鳴器自身包含震蕩源,給高電平就能響,
所以介紹無源蜂鳴器,由arduino給音頻信號
如果要同時(shí)產(chǎn)生多個(gè)音調(diào)做出電子琴的效果,可以用Tone.h的庫,用switch分支選擇輸出給揚(yáng)聲器的音調(diào),演奏對象.play(音調(diào))方法。
f. ?線通信和?絡(luò)
* I2C和SPI
I2C內(nèi)部集成電路和SPI串行外設(shè)接口標(biāo)準(zhǔn)的建立是為傳感器和微控制器之間的數(shù)字信息傳輸提供簡單的方法。
I2C只需要2路信號連接到arduino,同一時(shí)間只能在一個(gè)方向上傳送。通常用于不需要大量數(shù)據(jù)的傳感器。(加速度計(jì)、外部實(shí)時(shí)時(shí)鐘RTC、外部存儲器芯片EPROM、數(shù)字溫度計(jì)、LED數(shù)碼管、另一個(gè)arduino等)
SPI速度更快,有獨(dú)立的輸入輸出連線,可以同時(shí)收發(fā)數(shù)據(jù)。
I2C總線的兩路連線叫SCL和SDA,Arduino作為主設(shè)備。
用Wire.h庫可以輕松初始化和通訊。
下面一個(gè)例子是和游戲手柄I2C通訊
時(shí)鐘
無線XBEE
分為發(fā)送端和接收端,用到VirturalWire.h 庫傳輸文本消息
藍(lán)牙
//藍(lán)牙模塊 //電腦串口發(fā)送消息arduino收到后發(fā)到藍(lán)牙端,藍(lán)牙端發(fā)消息,arduino收到后發(fā)給電腦串口 //硬件串口的引腳0 1要和電腦發(fā)消息占用了,所以用軟串口傳輸信息 #include<SoftwareSerial.h>const int rxpin = 2; //引腳用于接收 const int txpin = 3; //引腳用來發(fā)送SoftwareSerial buletooth(rxpin, txpin); //給出的端口上的新串口void setup() {Serial.begin(9600);bluetooth.begin(9600);//初始化軟件串口Serial.println("Serial ready");bluetooth.println("藍(lán)牙準(zhǔn)備就緒"); }void loop() {if (bluetooth.available()) {char c = (char)bluetooth.read();Serial.write(c);}if (Serial.available()) {char c = (char)Serial.read();bluetooth.write(c);} }*互聯(lián)網(wǎng)
1.以太網(wǎng):低級別的信號層,提供基本的物理信息傳遞能力。這些信息的源地址和目的地址由媒界訪問控制MAC地址來確定。arduino程序定義的MAC地址需要在網(wǎng)絡(luò)上唯一。
2.傳輸控制協(xié)議TCP和網(wǎng)際協(xié)議IP,
3.本地IP地址,路由器提供,在路由器上的動態(tài)主機(jī)配置協(xié)議DHCP服務(wù)創(chuàng)建。從web瀏覽器發(fā)出的web請求和所得到的的回應(yīng)使用超文本傳輸協(xié)議HTTP信息。網(wǎng)頁通常使用超文本標(biāo)記語言HTML格式。網(wǎng)絡(luò)交換格式已被開發(fā)用在應(yīng)用計(jì)算機(jī)軟件實(shí)現(xiàn)可靠的網(wǎng)絡(luò)數(shù)據(jù)提取,XML和JSON是流行的格式。
三. 上述技術(shù)在設(shè)計(jì)原型制作和開發(fā)中的應(yīng)?。
1.接收到____信號時(shí),_____動作
最簡單的可以看做按鈕和LED燈
按鈕可以換成各種傳感器還有通訊傳輸接受的數(shù)據(jù),LED可以換成電機(jī)、蜂鳴器、顯示屏等。
原理圖都和這個(gè)大差不差,圖片順時(shí)針轉(zhuǎn)90度,
左邊模擬量
連傳感器、H橋驅(qū)動模塊等元件的使能引腳給速度值
右邊數(shù)字量
連開關(guān)、LED、有源蜂鳴器、馬達(dá)、傳感器的使能腳、H橋的方向引腳。
PWM(3/5/6/9/10/11):電機(jī)、無源蜂鳴器等。
數(shù)字引腳通過程序可以模擬成串口通信引腳。
*(0和1一般不用,占用硬件串口UART。
2和3可以接外部中斷。10-13SPI通信)
細(xì)化改一下可以做智能窗簾。
2.智能水杯(傳感器、顯示器、LED、蜂鳴器、藍(lán)牙等等綜合運(yùn)用)
溫度傳感器(塑料水杯) 壓力傳感器(水量監(jiān)控) LCD液晶顯示器 LED燈x2 蜂鳴器
水量監(jiān)控:壓力傳感器實(shí)時(shí)健康水量。
智能飲水累計(jì):初始飲水量為0,如果壓力傳感器計(jì)數(shù)小于1,暫停一段時(shí)間再計(jì)數(shù),并計(jì)算飲水?dāng)?shù)。如果一段時(shí)間后飲水量未變,蜂鳴器報(bào)警。
不同溫度下指示燈不同,溫度傳感器監(jiān)測到水溫超過。
水溫報(bào)警功能,如果水溫過高拿起水杯,蜂鳴器響起,提示使用者。
藍(lán)牙用于信息傳輸,可以控制硬件。
總結(jié)
以上是生活随笔為你收集整理的Arduino基础知识复习12.18的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: while 和 do while
- 下一篇: 启动hadoop组件时报错:(Permi