当前位置:网站首页>Arduino学习总结 + 实习项目

Arduino学习总结 + 实习项目

2022-08-09 10:57:00 魔法电子小Q

目录

基本函数

1、pinMode( )

2、digitalWrite( )

3、analogWrite( )

4、analogRead( )

5.map( )

基本点灯

串口通信

1、连接

 2、代码

IIC总线协议

1、物理层

2、协议层

3、代码

SPI通讯协议

总结三种通信协议

电机驱动 

红外遥控小车运动

1、材料

2、代码

麦克纳姆轮

1、正确安装方式ABBA

2、控制运动

3、代码(待调试)


基本函数

1、pinMode( )

将指定引脚配置为输入或输出模式 无返回值

语法:

pinMode(pin,mode)

pin:要设置的引脚编号

mode:模式

INPUT输入模式
OUTPUT输出模式
INPUT_PULLUP上拉输入模式

2、digitalWrite( )

设置引脚的输出电压为高电平或低电平 无返回值

语法:

digitalWrite(pin,value)

pin:要设置其输出的引脚编号

value:表示输出的电压

HIGH(1)

5V

LOW(0)0V

3、analogWrite( )

模拟输出函数 在指定引脚输出指定占空比的PWM方波 无返回值

语法:

analogWrite(pin,value)

pin:产生方波的指定引脚

value:占空比,介于0-255之间,用于计算一段时间内的通导时间

4、analogRead( )

模拟输入函数 读取模拟接口的值 即施加到其中一个引脚的电压

语法:

val = analogRead(pin)

val:返回值 返回0-1023之间的数字,表示0-5V的电压

pin:要读取电压的引脚

5.map( )

将变量按照映射范围来返回相应的值

语法:

val = map(value,fromLOW,fromHIGH,yoLOW,toHIGH)

将value变量按照fromLOW-formHIGH的范围,映射到toLOW-toHIGH的范围

val:接收映射返回值

基本点灯

1、闪烁的LED灯

//基本点灯
//闪烁的LED灯

int pin = 13;//Arduino Mega的LED灯引脚为13号引脚
void setup() {
  pinMode(pin,OUTPUT);
}

void loop() {
  digitalWrite(pin,HIGH);
  delay(5000);//暂停5000ms
  digitalWrite(pin,LOW);
  delay(5000);
}

2、用按钮控制LED灯的闪烁(第一种)

//基本点灯
//用按钮来控制LED灯的闪烁+按钮防抖
//这种按钮为按下闪烁,放松熄灭

int LEDpin = 13;
int pin = 2;//假设按钮连接的是2号引脚
void setup() {
  pinMode(LEDpin,OUTPUT);
  pinMode(pin,INPUT);
}

void loop() {
  if(digitalRead(pin) == HIGH){
    digitalWrite(pin,HIGH);
  }else{
    digitalWrite(pin,LOW);
  }
  delay(1);
}

3、用按钮控制LED灯的闪烁(第二种)

//基本点灯
//用按钮来控制LED灯的闪烁+按钮防抖
//这种按钮为每次按下和放松为一次改变状态

int LEDpin = 13;
int pin = 2;
int x = 0;//x=0灯灭,x=1灯亮
int deng1 = 0;//按键当时的状态
int deng2 = 0;//按键之前的状态
void setup() {
  pinMode(LEDpin,OUTPUT);
  pinMode(pin,INPUT);
}

void loop() {
  deng1 = digitalRead(pin);
  if(deng1 == 1 and deng2 == 0){
    delay(50);//按钮防抖
    if(x == 0){
      x = 1;
    }else{
      x = 0;
    }
  }
  deng2 = deng1;
  delay(1);
  if(x == 1){
    digitalWrite(LEDpin,HIGH);
  }else{
    digitalWrite(LEDpin,LOW);
  }
}

4、会呼吸的LED灯

//基本点灯
//会呼吸的LED灯

int pin = 13;
void setup() {
  pinMode(pin,OUTPUT);
}

void loop() {
  for(int i = 0;i < 255;i++){
    analogWrite(pin,i);
    delay(4);
  }
  for(int i = 255;i > 0;i++){
    analogWrite(pin,i);
    delay(4);
  }
}

串口通信

1、连接

需要两个数据引脚,一个用于传输数据的TX(pin=1),另一个用于接收的RX(pin=0)。一个设备的TX连接另一个设备的RX,反之,RX连接TX。

还需要两个设备共地,即参考电压一致。所以要把两个设备的GND引脚相连。

 2、代码

使用库#include <SoftwareSerial.h>

SoftwareSerial mySerial(rxPin,txPin); 类库的构造函数,通过它用户可以指定软串口RT、TX引脚。mySerial是用户自定义的软件串口对象 rxPin是软串口接收引脚(类似于RX)txPin是软串口发送引脚(类似于TX)

begin( );

available( ); Serial.available( ) 获取软串口接收到的数据个数,即获取串口接收缓冲区的字节数(缓冲区最多保存64bytes的数据)当其大于0时,说明串口接收到了数据,可以读取

//available典型用法

while(Serial.available() > 0){
    data = Serial.read();
    delay(2);
}

read( ); Serial.read( ) 从串口缓冲区中取出并读取一个bytes的数据

peek( ); Serial.peek( ) 从缓冲区返回一个字节数据,与read( )不同的是,peek( )读取数据后不会在缓冲区删除修改数据

write( ); Serial.write( ) 以字节形式输出数据到串口(与IIC中使用的wire.h一致)

listen( ); 开启串口监听状态 无返回值

isListening( ); 监测软串口是否正在监听状态 返回Boolean型值

end( ); 停止监听软串口 返回Boolean型值

overflow( ); 监测缓冲区是否溢出 返回Boolean型值

//Arduino软串口通信
//代码

#include <SoftwareSerial>

//实例化软串口
SoftwareSerial mySerial(2,3);//RX接收,TX发送

void setup(){
  Serial.begin(9600);
  Serial.println("Goodnight moon!");
  mySerial.begin(9600);
  mySerial.println("Hello, world?");
}

void loop(){
  if(mySerial.available() > 0){
    Serial.write(mySerial.read());
  }
  if(Serial.available() > 0){
    mySerial.write(Serial.read());
  }
}



//Arduino多个软串口通信
//代码

#include <SoftwareSerial.h>
//实例化两个自定义软串口对象
SoftwareSerial portOne(10,11);//RX TX
SoftwareSerial portTwo(8,9);//RX TX

void setup() {
  Serial.begin(9600);
  while(!Serial){
  }
  portOne.begin(9600);
  portTwo.begin(9600);
}

void loop() {
  //监听1号软串口
  portOne.listen();

  Serial.println("Data from port one:");
  //while(portOne.available()>0 and portOne.isListening())
  //监测一下是否处于监听状态
  while(portOne.available()>0){
    char Byte = portOne.read();
    Serial.write(Byte);
  }
  Serial.println();

  //监听2号软串口
  portTwo.listen();

  Serial.println("Data from port two:");
  while(portTwo.available()>0){
    char Byte = portTwo.read();
    Serial.write(Byte);
  }
  Serial.println();
}

IIC总线协议

1、物理层

由两条总线,分别是SDA(Send Data)串行数据线SCL(Send Clock Line)串行时钟线组成

SDA:串行数据线 传输数据的

SCL:串行时钟线 控制数据发送的时序

各设备连接到总线的输出端时为漏极开路(OD)输出集电极开路(OC)输出

2、协议层

初始空闲状态:SCL、SDA保持高电平

开始信号:SCL保持高电平,SDA由高电平变为低电平

(延时>4.7us时 SCL由高电平变为低电平)

停止信号:SCL保持高电平,SDA由低电平变为高电平

应答时,只有SCL处于低电平时SDA才能发生高低电平的变化

 

3、代码

使用库#include <wire.h>

begin( ); 初始化IIC的连接,并作为主/从机设备加入IIC总线 无返回值

1)begin( ); 无参数 以主机模式加入IIC总线

2)begin(address); 有参数 以从机模式加入IIC总线 address为0-127的任意地址,代表从机的地址

write( ); 主机状态时,主机将要发送的数据加入发送队列;从机状态时,从机发送数据至请求的主机 返回byte型值 返回输入的字节数

1)Wire.write(value); value:以单字节传送

2)Wire.write(string); string:以一系列字节传送

3)Wire.write(data,length); data:以字节形式发送数组 length:传输的字节数

requestFrom( ); 主机向从机发送数据请求信号,从机端可使用onRequest( )注册一个事件以响应主机的请求,主机可通过available( )和read( )函数读取这些数据

1)Wire.requestFrom(address,quantity); address:设备的地址 quantity:请求的字节数

2)Wire.requestFrom(address,quantity,stop); stop:boolean型值 当其为true时,发送一个停止信息,释放IIC总线 当其为false时,发送一个重新开始信息,保持IIC有效连接

onRequest( ); 注册一个事件,当从机接收到主机的数据请求时即被触发

Wrie.onRequest(handler); handler:可被触发的事件

beginTransmission( ); 设定传输数据到指定地址的从机设备,搭配endTransmisssion( )函数结束传输 

Wire.beginTransmission(address); address:要发送的从机的7位地址

endTransmission( ); 结束传输数据 返回值为byte型值,表示传输状态

1)0 传输成功 2)1 数据过长 3)2 在地址发送时接收到NACK信号 4)3 在数据发送时接收到NACK信号 5)4 其他错误

1)Wire.endTransmission( ); 无参数,等效于true

2)Wire.endTransmission(stop); stop:Boolean型值 当其为true时,发送一个停止信息,释放IIC总线 当其为false时,发送一个重新开始信息,保持IIC有效连接

onRecetive( ); 在从机端注册一个事件,当从机收到主机发送的数据时即被触发

Wire.onRecetive(handler); handler:当从机接收到数据时即可被触发的事件

代码参考路径:

解读IIC通讯协议与代码实现_sjxpf922的博客-CSDN博客_iic通信协议

IIC原理超详细讲解---值得一看_Z小旋的博客-CSDN博客_iic

SPI通讯协议

SPI协议详解(图文并茂+超详细)_小麦大叔的博客-CSDN博客_spi协议

总结三种通信协议

UART串行通信异步通信全双工(双向同时)
IIC串行通信同步通信半双工(双向不同时)
SPI串行通信同步通信

全双工(双向同时) 

注:异步通信和同步通信的区别为是否有时钟同步信号

电机驱动 

电脑连接Arduino开发板,开发板6、7号数字引脚分别连接L289N驱动模块的In1,In2接口,驱动模块的+5v、+12v、GND接口连接上电源模块的5v、12v、接地接口、电源模块再分别连接锂电池和电机进行驱动。

红外遥控小车运动

1、材料

红外接收模块、红外发射器

2、代码

使用库#include <IRremote.h>

操作流程:

IRrecv myIRrecv(IRRECV_PIN); //实例化

decode_results results; //声明接收编码信息的结构体对象

myIRrecv.enableIRIn( ); //初始化红外编码

myIRrecv.decode(&results); //decode( )方法被调用来判断是否已接受到编码,如果收到,它返回一个非零值,并将结果存到decode_results结构中

myIRrecv.resume( ); //接收下一个编码

results.value( ); //接收到的编码数据信息

十六进制 HEX

十进制 DEC 

代码: 

#include <IRremote.h>
int IRRECV_PIN = 12; //引脚
IRrecv myIRrecv(IRRECV_PIN); //实例化
decode_results results; //声明接收编码的信息的结构体对象

void setup() {
  myIRrecv.enableIRIn();//初始化红外编码
  Serial.begin(9600);
}

void loop() {
  if(myIRrecv.decode(&result)){
    //接收到了编码信息
    Serial.println(results.value,HEX);
    //results.value中含有接收到的编码信息 HEX表示用十六进制打印出来
    myIRrecv.resume();  
    //接收下一个编码
  }

}

 用红外控制LED灯代码:

#include <IRremote.h>
int IRRECV_PIN = 12; //引脚
int LED = 13;
IRrecv myIRrecv(IRRECV_PIN); //实例化
decode_results results; //声明接收编码的信息的结构体对象

void setup() {
  myIRrecv.enableIRIn();//初始化红外编码
  Serial.begin(9600);
  pinMode(LED,OUTPUT);
}

void loop() {
  if(myIRrecv.decode(&result)){
    //接收到了编码信息
    Serial.println(results.value,HEX);
    //results.value中含有接收到的编码信息 HEX表示用十六进制打印出来
    myIRrecv.resume();  
    //接收下一个编码
  }
  //打开串口监视器,查看红外遥控器任意按钮所返回的值
  
  //开灯
  if(results.value == 16724175){ //假设值
    digitalWrite(LED,HIGH);
  }
  
  //关灯
  if(results.value == 16718055){ //假设值
    digitalWrite(LED,LOW);
  }
}

用红外控制普通小车的运动代码:

#include <IRremote.h>
int INA1 = 8;
int INA2 = 9;//右边
int PWA = 6;
int INB1 = 7;
int INB2 = 4;//左边
int PWB = 5;
int IRRECV_PIN = 12;
int speedvalue = 80;
IRrecv myIRrecv(IRRECV_PIN);
decode_results results;

void forward(int);//前进 16718055
void backward(int);//后退 16730805
void turnleft(int);//左转 16716015
void turnright(int);//右转 16734885
void stopcar();//停车 16726215
//+ 16754775
//- 16769055

void setup(){
  pinMode(INA1,OUTPUT);
  pinMode(INA2,OUTPUT);
  pinMode(INB1,OUTPUT);
  pinMode(INB2,OUTPUT);
  pinMode(PWA,OUTPUT);
  pinMode(PWB,OUTPUT);
  myIRrecv.enableIRIn();
  Serial.begin(9600);
}

void loop(){
  if(myIRrecv.decode(&results)){
    //Serial.println(results.value,DEC);

    //前进
    if(results.value == 16718055){
      forward(speedvalue);
    }

    //后退
    if(results.value == 16730805){
      backward(speedvalue);
    }

    //左转
    if(results.value == 16716015){
      turnleft(speedvalue);
    }

    //右转
    if(results.value == 16734885){
      turnright(speedvalue);
    }

    //停车
    if(results.value == 16726215){
      stopcar(speedvalue);
    }

    //速度+
    if(results.value == 16754775){
      if(speedvalue + 10 <= 250){
        speedvalue += 10;
      }
    }

    //速度-
    if(results.value == 16769055){
      if(speedvalue - 10 >= 30){
        speedvalue -= 10;
      }
    }
    Serial.println(speedvalue);
    myIRrecv.resume();//接收下一个编码
  }
}

/*
 * 函数名:forward(int pwm_value)
 * 功能:小车前进
 * 参数:pwm_value
 * 返回值:无
*/
void forward(int pwm_value){
  digitalWrite(INA1,HIGH);
  digitalWrite(INA2,LOW);
  analogWrite(PWA,pwm_value);
  digitalWrite(INB1,HIGH);
  digitalWrite(INB2,LOW);
  analogWrite(PWB,pwm_value);
}

/*
 * 函数名:backward(int pwm_value)
 * 功能:小车后退
 * 参数:pwm_value
 * 返回值:无
*/
void backward(int pwm_value){
  digitalWrite(INA1,LOW);
  digitalWrite(INA2,HIGH);
  analogWrite(PWA,pwm_value);
  digitalWrite(INB1,LOW);
  digitalWrite(INB2,HIGH);
  analogWrite(PWB,pwm_value);
}

/*
 * 函数名:turnleft(int pwm_value)
 * 功能:小车左转
 * 参数:pwm_value
 * 返回值:无
*/
void turnleft(int pwm_value){
  digitalWrite(INA1,HIGH);
  digitalWrite(INA2,LOW);
  analogWrite(PWA,pwm_value);
  digitalWrite(INB1,LOW);
  digitalWrite(INB2,HIGH);
  analogWrite(PWB,pwm_value);
}

/*
 * 函数名:turnright(int pwm_value)
 * 功能:小车右转
 * 参数:pwm_value
 * 返回值:无
*/
void turnright(int pwm_value){
  digitalWrite(INA1,LOW);
  digitalWrite(INA2,HIGH);
  analogWrite(PWA,pwm_value);
  digitalWrite(INB1,HIGH);
  digitalWrite(INB2,LOW);
  analogWrite(PWB,pwm_value);
}

/*
 * 函数名:stopcar()
 * 功能:小车
 * 参数:无
 * 返回值:无
*/
void stopcar(){
  analogWrite(PWA,0);
  analogWrite(PWB,0);
}

麦克纳姆轮

1、正确安装方式ABBA

2、控制运动

1)向前运动:AB轮都向前转

2)向后运动:AB轮都向后转

3)向右平移:A轮正转B轮反转

4)向左平移:A轮反转B轮正转

5)向右旋转:左边AB轮正转右边BA轮反转

6)向左旋转:左边AB轮反转右边BA轮正转

7)向右前方运动:A轮正转B轮不动

8)向左后方运动:A轮反转B轮不动

9)向左前方运动:A轮不动B轮正转

10)向右后方运动:A轮不动B轮反转

11)绕前轮轴中点右旋:前面AB轮不动后面B轮正转A轮反转

12)绕前轮轴中点左旋:前面AB轮不动后面B轮反转A轮正转

13)绕后轮轴中点右旋:前面A轮正转B轮反转后面AB轮不动

14)绕后轮轴中点左旋:前面A轮反转B轮正转后面AB轮不动

3、代码(待调试)

#include <IRremote.h>

#define left_PINA 5;
#define left_PINB 6;
#define right_PINA 9;
#define right_PINB 10;
#define speedvalue 180;
/*
 * int left_PINA = 5;
   int left_PINB = 6;
   int right_PINA = 9;
   int right_PINB = 10;
 */
 
IRrecv myIRrecv(IRRECV_PIN);
decode_results results;
void control_motor(speedvalue);//电机控制
void electric_put();//引脚初始化
void forward(int);//前进 2
void forward(int)
void backward(int);//后退 8
void turnleft(int);//左转 4
void turnright(int);//右转 6
void turnleftforward(int);//左前方运动 1
void turnrightforward(int);//右前方运动 3
void turnleftbackward(int);//左后方运动 7
void turnrightbackward(int);//右后方运动 9
void stopcar();//停车 5

void setup(){
  electric_put();
  myIRrecv.enableIRIn();
  Serial.begin(9600);
}

void loop(){
  if(myIRrecv.decode(&results)){
    //Serial.println(results.value,DEC);
    control_motor(speedvalue);
    }
    Serial.println(speedvalue);
    myIRrecv.resume();//接收下一个编码
    delay(600);
  }
}

/*********电机引脚设置输出***********/
void electric_put(){
  pinMode(left_PINA,OUTPUT);
  pinMode(left_PINB,OUTPUT);
  pinMode(right_PINA,OUTPUT);
  pinMode(right_PINB,OUTPUT);
}
/*********************************/

/***********控制电机转动************/
void control_motor(speedvalue){
  if(results.value == ){
    forward(speedvalue);
  }else if(results.value == ){
    backward(speedvalue);
  }else if(results.value == ){
    turnleft(speedvalue);
  }else if(results.value == ){
    turnright(speedvalue);
  }else if(results.value == ){
    turnleftforward(speedvalue);
  }else if(results.value == ){
    turnrightforward(speedvalue);
  }else if(results.value == ){
    turnleftbackward(speedvalue);
  }else if(results.value == ){
    turnrightbackward(speedvalue);
  }else if(results.value == ){
    stopcar();
  }
}
else if(results.value == ){
   /  /*********************************/

/*
 * 函数名:forward(int pwm_value)
 * 功能:小车前进
 * 参数:pwm_value
 * 返回值:无
*/
void forward(int pwm_value){
  analogWrite(left_PINA,pwm_value);
  analogWrite(left_PINB,0);
  analogWrite(right_PINA,pwm_value);
  analogWrite(right_PINB,0);
}

/*
 * 函数名:backward(int pwm_value)
 * 功能:小车后退
 * 参数:pwm_value
 * 返回值:无
*/
void backward(int pwm_value){
  analogWrite(left_PINA,0);
  analogWrite(left_PINB,pwm_value);
  analogWrite(right_PINA,0);
  analogWrite(right_PINB,pwm_value);
}

/*
 * 函数名:turnleft(int pwm_value)
 * 功能:小车左转
 * 参数:pwm_value
 * 返回值:无
*/
void turnleft(int pwm_value){
  analogWrite(left_PINA,0);
  analogWrite(left_PINB,pwm_value);
  analogWrite(right_PINA,pwm_value);
  analogWrite(right_PINB,0);
}

/*
 * 函数名:turnright(int pwm_value)
 * 功能:小车右转
 * 参数:pwm_value
 * 返回值:无
*/
void turnright(int pwm_value){
  analogWrite(left_PINA,pwm_value);
  analogWrite(left_PINB,0);
  analogWrite(right_PINA,0);
  analogWrite(right_PINB,pwm_value);
}

/*
 * 函数名:turnleftforward(int pwm_value)
 * 功能:小车左前方运动
 * 参数:pwm_value
 * 返回值:无
*/
void turnleftforward(int pwm_value){
  analogWrite(left_PINA,pwm_value-60);
  analogWrite(left_PINB,0);
  analogWrite(right_PINA,pwm_value);
  analogWrite(right_PINB,0);
}

/*
 * 函数名:turnrightforward(int pwm_value)
 * 功能:小车右前方运动
 * 参数:pwm_value
 * 返回值:无
*/
void turnrightforward(int pwm_value){
  analogWrite(left_PINA,pwm_value);
  analogWrite(left_PINB,0);
  analogWrite(right_PINA,pwm_value-60);
  analogWrite(right_PINB,0);
}

/*
 * 函数名:turnleftbackward(int pwm_value)
 * 功能:小车左后方运动
 * 参数:pwm_value
 * 返回值:无
*/
void turnleftbackward(int pwm_value){
  analogWrite(left_PINA,0);
  analogWrite(left_PINB,pwm_value-60);
  analogWrite(right_PINA,0);
  analogWrite(right_PINB,pwm_value);
}

/*
 * 函数名:turnrightbackward(int pwm_value)
 * 功能:小车右后方运动
 * 参数:pwm_value
 * 返回值:无
*/
void turnrightbackward(int pwm_value){
  analogWrite(left_PINA,0);
  analogWrite(left_PINB,pwm_value);
  analogWrite(right_PINA,0);
  analogWrite(right_PINB,pwm_value-60);
}

/*
 * 函数名:stopcar()
 * 功能:小车
 * 参数:无
 * 返回值:无
*/
void stopcar(){
  analogWrite(left_PINA,0);
  analogWrite(left_PINB,0);
  analogWrite(right_PINA,0);
  analogWrite(right_PINB,0);
}

基本的学习都已经完成了,接下来就是一些调试和完善优化……

原网站

版权声明
本文为[魔法电子小Q]所创,转载请带上原文链接,感谢
https://blog.csdn.net/dayday_0724/article/details/126011995