当前位置: 移动技术网 > 移动技术>移动开发>Android > Arduino蓝牙小车制作(Arduino+APP Inventor)

Arduino蓝牙小车制作(Arduino+APP Inventor)

2020年07月19日  | 移动技术网移动技术  | 我要评论

简介:
小车使用Arduino MEGA2560作为主控,4个TT电机带动4WD底盘,4节18650锂电池供电,2个L298N驱动板驱动电机,采用Android APP作为上位机发布指令,操纵小车运动、播放音乐等,两者通过BT蓝牙通信,同时使用2自由度云台辅助超声波传感器探测距离,躲避障碍,灰度传感器进行PID巡线(待完善)、音频解码器和3W喇叭播放音乐、ws2812LED发彩虹光。

使用材料:

MEGA2560开发板、4WD底盘、TT电机X4、L298N驱动板X2、18650锂电池X4、18650电池盒X2、2自由度云台、SG90舵机X2、HC-02蓝牙模块、DFrobot MiNi音频解码器、3W喇叭、ws812全彩LED模块、HCSR04超声波传感器、灰度传感器X2、手机

实物图:
在这里插入图片描述
在这里插入图片描述

Arduino代码(不含PID巡线):


#include<DFRobotDFPlayerMini.h>//DFrobot音频解码器库
#include<Adafruit_NeoPixel.h>//ws2812全彩LED库
#include<Servo.h>//舵机库
//引脚定义
#define led_pin     22
#define LFwheel_1   50
#define LFwheel_2   52
#define LFpwm       11
#define RFwheel_1   46
#define RFwheel_2   48
#define RFpwm       10
#define LBwheel_1   47
#define LBwheel_2   49
#define LBpwm       13
#define RBwheel_1   51
#define RBwheel_2   53
#define RBpwm       12
#define servopin_1  8
#define servopin_2  9
#define Trig_pin    31
#define Echo_pin    33
//计时变量
unsigned long cur_time=0;
//对象实例化
DFRobotDFPlayerMini myDFPlayer;
Adafruit_NeoPixel strip = Adafruit_NeoPixel(7, led_pin, NEO_GRB + NEO_KHZ800);
Servo myservo1;
Servo myservo2;
void setup() {
  //串口波特率设置
  Serial2.begin(9600);
  Serial3.begin(9600);
  Serial.begin(115200);
  //调用初始化函数
  Init();
}

void loop() {
  //读取字符串
  String str="";
  while(Serial3.available()){
    char ch=(char)Serial3.read();
    str+=ch;
    delay(2);
  }
  
  if(str.length()>0){
      Serial.println(str);
      if(getKey(str)=="up"){
          Forward(map(getValue(str),0,70,0,255));//调用前进函数
          Serial.print("Forward:");
          Serial.println(str);
     }    
     if(getKey(str)=="down"){
         Back_off(map(getValue(str),0,70,0,255));//调用后退函数
         Serial.print("Back_off:");
         Serial.println(str);
     }    
     if(getKey(str)=="left"){
         Turn_left(map(getValue(str),0,70,0,150));//调用左转函数
         Serial.print("Turn_left:");
         Serial.println(str);
     }    
     if(getKey(str)=="right"){
        Turn_right(map(getValue(str),0,70,0,150));//调用右转函数
        Serial.print("Turn_right:");
        Serial.println(str);
     } 
     if(getKey(str)=="stop"){
        Stop();//调用停止函数
        Serial.print("Stop:");
        Serial.println(str);
     }
     if(getKey(str)=="music"){
       myDFPlayer.play(random(1,10));//调用音乐播放函数,在音乐编号1~10中随机播放
       Serial.println("Music play");  
     }
     if(getKey(str)=="mustop"){
       myDFPlayer.pause();//调用音乐暂停函数
       Serial.println("Music sleep");
     }
     if(getKey(str)=="next"){
       myDFPlayer.next();//调用下一曲函数
       Serial.println("Next song");
     }
     if(getKey(str)=="previous"){
       myDFPlayer.previous();//调用上一曲函数
       Serial.println("Previous song");
     }
     if(getKey(str)=="light"){
       rainbowCycle(10);//调用彩虹闪烁函数
       Serial.println("LED rainbow");
     }
     if(getKey(str)=="dark"){
       colorWipe(strip.Color(0, 0, 0), 50);//关灯
       Serial.println("LED dark");
     }
     if(getKey(str)=="vangle"){
        myservo2.write(getValue(str));//舵机2垂直转动
        //delay(10);
        Serial.print("Vertical Angle:");
        Serial.println(getValue(str));
     }
     if(getKey(str)=="hangle"){
        myservo1.write(getValue(str));//舵机1水平转动
        //delay(10);
        Serial.print("Horizon Angle:");
        Serial.println(getValue(str));
     }  
  } 
  if(millis()-cur_time>3000){
    cur_time=millis();
    if(getDistance()<30){//超声波测距离,如果距离小于30厘米则亮红灯警示
      colorWipe(strip.Color(255, 0, 0), 50);
      Serial.println("RED LIGHT WARING");
    }
    else{
      colorWipe(strip.Color(0, 0, 0), 50);//否则关灯
      Serial.println("BE SAFE");
    }
    
  } 
}

//定义初始化函数
void Init(){
  for(int i=46;i<=53;i++){
    pinMode(i,OUTPUT);
    digitalWrite(i,LOW);
  }
  if (!myDFPlayer.begin(Serial2)) { 
    Serial.println(F("Unable to begin:"));
    Serial.println(F("1.Please recheck the connection!"));
    Serial.println(F("2.Please insert the SD card!"));
    //while(1);   
  }
  myDFPlayer.volume(20);
  strip.begin();
  strip.show(); 
  myservo1.attach(servopin_1);
  myservo2.attach(servopin_2);
  pinMode(Trig_pin, OUTPUT); 
  pinMode(Echo_pin, INPUT); 
}
//定义前进函数
void Forward(int v){
  //左前轮
  analogWrite(LFpwm,v);
  digitalWrite(LFwheel_1,HIGH);
  digitalWrite(LFwheel_2,LOW);
  
  //右前轮
  analogWrite(RFpwm,v);
  digitalWrite(RFwheel_1,HIGH);
  digitalWrite(RFwheel_2,LOW);

  //左后轮
  analogWrite(LBpwm,v);
  digitalWrite(LBwheel_1,LOW);
  digitalWrite(LBwheel_2,HIGH);
  
  //右后轮
  analogWrite(RBpwm,v);
  digitalWrite(RBwheel_1,LOW);
  digitalWrite(RBwheel_2,HIGH);
  
}
//定义后退函数
void Back_off(int v){
  //左前轮
  analogWrite(LFpwm,v);
  digitalWrite(LFwheel_1,LOW);
  digitalWrite(LFwheel_2,HIGH);
  
  //右前轮
  analogWrite(RFpwm,v);
  digitalWrite(RFwheel_1,LOW);
  digitalWrite(RFwheel_2,HIGH);

  //左后轮
  analogWrite(LBpwm,v);
  digitalWrite(LBwheel_1,HIGH);
  digitalWrite(LBwheel_2,LOW);
  
  //右后轮
  analogWrite(RBpwm,v);
  digitalWrite(RBwheel_1,HIGH);
  digitalWrite(RBwheel_2,LOW);
  
}
//定义左转函数
void Turn_left(int v){
  //左前轮
  analogWrite(LFpwm,v);
  digitalWrite(LFwheel_1,LOW);
  digitalWrite(LFwheel_2,HIGH);
  
  //右前轮
  analogWrite(RFpwm,v);
  digitalWrite(RFwheel_1,HIGH);
  digitalWrite(RFwheel_2,LOW);

  //左后轮
  analogWrite(LBpwm,v);
  digitalWrite(LBwheel_1,HIGH);
  digitalWrite(LBwheel_2,LOW);
  
  //右后轮
  analogWrite(RBpwm,v);
  digitalWrite(RBwheel_1,LOW);
  digitalWrite(RBwheel_2,HIGH);
}
//定义右转函数
void Turn_right(int v){
  //左前轮
  analogWrite(LFpwm,v);
  digitalWrite(LFwheel_1,HIGH);
  digitalWrite(LFwheel_2,LOW);
  
  //右前轮
  analogWrite(RFpwm,v);
  digitalWrite(RFwheel_1,LOW);
  digitalWrite(RFwheel_2,HIGH);

  //左后轮
  analogWrite(LBpwm,v);
  digitalWrite(LBwheel_1,LOW);
  digitalWrite(LBwheel_2,HIGH);
  
  //右后轮
  analogWrite(RBpwm,v);
  digitalWrite(RBwheel_1,HIGH);
  digitalWrite(RBwheel_2,LOW);
}
//定义停止函数
void Stop(){
  for(int i=46;i<=53;i++){
    digitalWrite(i,LOW);
  }
}
//定义获取标识符函数
String getKey(String str){
  int pos0,pos1;
  String key;
  for(int i=0;i<str.length();i++){
    if(str[i]=='!')
      pos0=i;
    if(str[i]=='@'){
      pos1=i;
      break;
    }
      
  }
 key=str.substring(pos0+1,pos1);
  return key;
}
//定义获取数值函数
int getValue(String str){
  int pos0,pos1;
  int value;
  for(int i=0;i<str.length();i++){
    if(str[i]=='@')
      pos0=i;
    if(str[i]=='*'){
      pos1=i;
      break;
    }      
  }
  value=getInt(str.substring(pos0+1,pos1));
  return value;
}
int getInt(String str){
  int num=0;
  for(int i=0;i<str.length();i++){
    num*=10;
    num+=str[i]-'0';    
  }  
  return num;
}
//定义LED彩虹闪烁函数
void rainbowCycle(int wait) {
  int i, j;

  for(j=0; j<256*5; j++) { // 5 cycles of all colors on wheel
    for(i=0; i< strip.numPixels(); i++) {
      strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));
    }
    strip.show();
    delay(wait);
  }
}

int Wheel(byte WheelPos) {
  if(WheelPos < 85) {
   return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
  } else if(WheelPos < 170) {
   WheelPos -= 85;
   return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  } else {
   WheelPos -= 170;
   return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
}
//定义LED发光函数
void colorWipe(int c, int wait) {
  for(int i=0; i<strip.numPixels(); i++) {
      strip.setPixelColor(i, c);
      strip.show();
      delay(wait);
  }
}
//定义超声波获取距离函数
double getDistance(){
  double cm;
  digitalWrite(Trig_pin, LOW); 
  delayMicroseconds(2); 
  digitalWrite(Trig_pin, HIGH); 
  delayMicroseconds(10); 
  digitalWrite(Trig_pin, LOW); 

  cm = pulseIn(Echo_pin, HIGH)/58.0; 
  cm = (int(cm * 100.0))/100.0; 
  
  return cm;
}

APP Inventor GUI 设计:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

APP Inventor 代码块(部分):

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

结束语:
灰度传感器买错了,所以巡线的部分还没有写。

本文地址:https://blog.csdn.net/weixin_42126140/article/details/107433381

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网