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

2024-02-29 18:20

本文主要是介绍Arduino蓝牙小车制作(Arduino+APP Inventor),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

简介:
小车使用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 wheelfor(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 代码块(部分):

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

在这里插入图片描述

在这里插入图片描述

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

这篇关于Arduino蓝牙小车制作(Arduino+APP Inventor)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/759637

相关文章

Android App安装列表获取方法(实践方案)

《AndroidApp安装列表获取方法(实践方案)》文章介绍了Android11及以上版本获取应用列表的方案调整,包括权限配置、白名单配置和action配置三种方式,并提供了相应的Java和Kotl... 目录前言实现方案         方案概述一、 androidManifest 三种配置方式

macOS怎么轻松更换App图标? Mac电脑图标更换指南

《macOS怎么轻松更换App图标?Mac电脑图标更换指南》想要给你的Mac电脑按照自己的喜好来更换App图标?其实非常简单,只需要两步就能搞定,下面我来详细讲解一下... 虽然 MACOS 的个性化定制选项已经「缩水」,不如早期版本那么丰富,www.chinasem.cn但我们仍然可以按照自己的喜好来更换

React实现原生APP切换效果

《React实现原生APP切换效果》最近需要使用Hybrid的方式开发一个APP,交互和原生APP相似并且需要IM通信,本文给大家介绍了使用React实现原生APP切换效果,文中通过代码示例讲解的非常... 目录背景需求概览技术栈实现步骤根据 react-router-dom 文档配置好路由添加过渡动画使用

使用Python制作一个PDF批量加密工具

《使用Python制作一个PDF批量加密工具》PDF批量加密‌是一种保护PDF文件安全性的方法,通过为多个PDF文件设置相同的密码,防止未经授权的用户访问这些文件,下面我们来看看如何使用Python制... 目录1.简介2.运行效果3.相关源码1.简介一个python写的PDF批量加密工具。PDF批量加密

基于UE5和ROS2的激光雷达+深度RGBD相机小车的仿真指南(五):Blender锥桶建模

前言 本系列教程旨在使用UE5配置一个具备激光雷达+深度摄像机的仿真小车,并使用通过跨平台的方式进行ROS2和UE5仿真的通讯,达到小车自主导航的目的。本教程默认有ROS2导航及其gazebo仿真相关方面基础,Nav2相关的学习教程可以参考本人的其他博客Nav2代价地图实现和原理–Nav2源码解读之CostMap2D(上)-CSDN博客往期教程: 第一期:基于UE5和ROS2的激光雷达+深度RG

arduino ide安装详细步骤

​ 大家好,我是程序员小羊! 前言: Arduino IDE 是一个专为编程 Arduino 微控制器设计的集成开发环境,使用起来非常方便。下面将介绍如何在不同平台上安装 Arduino IDE 的详细步骤,包括 Windows、Mac 和 Linux 系统。 一、在 Windows 上安装 Arduino IDE 1. 下载 Arduino IDE 打开 Arduino 官网

用Unity2D制作一个人物,实现移动、跳起、人物静止和动起来时的动画:中(人物移动、跳起、静止动作)

上回我们学到创建一个地形和一个人物,今天我们实现一下人物实现移动和跳起,依次点击,我们准备创建一个C#文件 创建好我们点击进去,就会跳转到我们的Vision Studio,然后输入这些代码 using UnityEngine;public class Move : MonoBehaviour // 定义一个名为Move的类,继承自MonoBehaviour{private Rigidbo

开放式耳机好用?平价开放式耳机推荐?四款开放式的蓝牙耳机推荐

开放式耳机好用吗?有平价些的开放式耳机推荐吗?那这两个问题的回答当然是肯定的。 首先开放式耳机好不好用取决于对耳机的需求,因为开放式耳机其实是比较适用于需要注意周围环境、需要‌长时间佩戴舒适以及需要频繁与人交流的场景中,在这些场景下使用开放式耳机的话就会比较有优势。就例如跑步骑行健身等运动的时候,能够兼得佩戴舒适度的同时,增加一定的安全性;还有在办公学习的时候,会很适合长时间佩戴,能够方便和

MFC中App,Doc,MainFrame,View各指针的互相获取

纸上得来终觉浅,为了熟悉获取方法,我建了个SDI。 首先说明这四个类的执行顺序是App->Doc->Main->View 另外添加CDialog类获得各个指针的方法。 多文档的获取有点小区别,有时间也总结一下。 //  App void CSDIApp::OnApp() {      //  App      //  Doc     CDocument *pD

OpenStack离线Train版安装系列—0制作yum源

本系列文章包含从OpenStack离线源制作到完成OpenStack安装的全部过程。 在本系列教程中使用的OpenStack的安装版本为第20个版本Train(简称T版本),2020年5月13日,OpenStack社区发布了第21个版本Ussuri(简称U版本)。 OpenStack部署系列文章 OpenStack Victoria版 安装部署系列教程 OpenStack Ussuri版