基于Wemos的wifi智能避障小车
4
2021-11-25
物料介绍
淘宝小破车

wemos开发板

超声波模块

改造小破车
刚买来的样子
[video width="544" height="960" mp4="https://159.75.81.167/wp-content/uploads/2021/11/sd1637660417_2.mp4"][/video] 这个原板子确实是很简陋

接一接线

Wemos串口通信
wemos接入wifi
实例实现代码char*ssid = "wifi名"; char*passwd = "密码"; void initWIFISta(){ WiFi.mode(WiFi_STA); //设置为STA模式 WiFi.begin(ssid,passwd); //连接预设的WiFi while(WiFi.status()!=WL_CONNECTED){ //监测WiFi连接状态 Serial.print("."); delay(500); //ms,每隔0.5秒打印一个.表示连接中,直到满足状态跳出此循环 } Serial.print(WiFi.localIP()); //通过串口打印当前IP delay(500); }整合后的代码
#include串口信息:char*ssid = "HUAWEI"; char*passwd = "2333...NMSL"; void initWIFISta() { WiFi.mode(WIFI_STA); //设置为STA模式 WiFi.begin(ssid, passwd); //连接预设的WiFi while (WiFi.status() != WL_CONNECTED) { //监测WiFi连接状态 Serial.print("......"); Serial.print("\n"); delay(500); //ms,每隔0.5秒打印一个.表示连接中,直到满足状态跳出此循环 } } void setup() { Serial.begin(115200); initWIFISta(); } void loop() { Serial.print(WiFi.localIP()); //通过串口打印当前IP Serial.print("\n"); delay(500); }

简介C/S模式
当联网后是不是差了点什么?没错,既然wemos能接入网络我们就能把这个作为服务器端,那么客户端可以去和服务端通信来实现某些功能。这就是当下火热的C/S模式。 C/S模式就是指客户端/服务器模式,是计算机软件协同工作的一种模式。 由于Web浏览器的兴起,B/S模式逐步取代了C/S模式,被更广泛地应用。随着计算机网络技术的成熟和应用普及,特别是局域网的发展、PC机的出现,越来越多的用户和企业开始使用计算机管理一些事务。 PC机的资源没有大型、中型甚至小型主机丰富,但将多台PC机联成网,必然会增加资源含量,各个用户都在网络上来共享所有资源。根据客户/服务器(Client/Server简记为C/S)体系结构的概念,至少用两台计算机来分别充当客户机和服务器角色。 客户端可以是X86体系的风机或RISC体系的工作站等,而服务器端硬件一般比较高档,比如:高档PC服务器或SUN专用服务器;操作系统也比较高档,比如: Windows NT和 Unix。C/S模式具有以下特点
1、C/S模式将应用与服务分离,系统具有稳定性和灵活性。 2、C/S模式配备的是点对点的结构模式,适用于局域网,有可靠的安全性 。 3、由于客户端实现与服务器端的直接连接,没有中间环节,因此响应速度快。 4、在C/S模式中,作为客户机的计算机都要安装客户机程序,一旦软件系统升级,每台客户机都要安装客户机程序,系统升级和维护较为复杂。原理示例
#include手机端利用TCP工具 连接到wemos服务器,发送命令char*ssid = "HUAWEI"; char*passwd = "2333...NMSL"; int port = 1234; WiFiServer server(port); //设置1234为服务器的端口 void initWIFISta() { WiFi.mode(WIFI_STA); //设置为STA模式 WiFi.begin(ssid, passwd); //连接预设的WiFi while (WiFi.status() != WL_CONNECTED) { //监测WiFi连接状态 Serial.print("......"); Serial.print("\n"); delay(500); //ms,每隔0.5秒打印一个.表示连接中,直到满足状态跳出此循环 } Serial.print(WiFi.localIP()); //通过串口打印当前IP } void setup() { Serial.begin(115200); initWIFISta(); server.begin(); //启动服务 } void loop() { char cmd; WiFiClient client = server.available(); //初始化 while (client.connected()) { while (client.available() > 0) { cmd = client.read(); if (cmd == '1') { //当接收到客户端命令时 向窗口打印相应信息 Serial.println("Welcome to the Tcp Tools!"); } else { Serial.println("Error!"); } } } }

客户端控制蜂鸣器
#include当在手机发送指令1时,服务器端控制蜂鸣器发声,收到其他指令时,控制蜂鸣器停止发声。char*ssid = "HUAWEI"; char*passwd = "2333...NMSL"; int port = 1234; WiFiServer server(port); //设置1234为服务的端口 void initWIFISta() { WiFi.mode(WIFI_STA); //设置为STA模式 WiFi.begin(ssid, passwd); //连接预设的WiFi while (WiFi.status() != WL_CONNECTED) { //监测WiFi连接状态 Serial.print("......"); Serial.print("\n"); delay(500); //ms,每隔0.5秒打印一个.表示连接中,直到满足状态跳出此循环 } Serial.print(WiFi.localIP()); //通过串口打印当前IP } void initBEEP() { pinMode(BEEP, OUTPUT); digitalWrite(BEEP, HIGH); } void setup() { Serial.begin(115200); initWIFISta(); server.begin(); //启动服务 initBEEP(); //启动蜂鸣器 } void loop() { char cmd; WiFiClient client = server.available(); //初始化 while (client.connected()) { while (client.available() > 0) { cmd = client.read(); if (cmd == '1') { // Serial.println("Welcome to the Tcp Tools!"); digitalWrite(BEEP, LOW); //服务器收到指令做出 控制蜂鸣器 } else { // Serial.println("Error!"); digitalWrite(BEEP, HIGH); } } } }
L9110s步进电机控制器
接线

电机控制
原理:

确定接线后的控制代码
#define Ahead D6 //D6引脚控制正转 #define Back D7 //D7引脚控制反转 #define Left D4 //D4引脚控制正转 #define Right D5 //D5引脚控制反转 void initL9110s() { //初始化,输出引脚 pinMode(Ahead, OUTPUT); pinMode(Back, OUTPUT); pinMode(Left, OUTPUT); pinMode(Right, OUTPUT); } void GoAhead() { //根据电频差来控制电机正转 digitalWrite(Ahead, HIGH); digitalWrite(Back, LOW); } void GoBack() { //根据电频差来控制电机反转 digitalWrite(Ahead, LOW); digitalWrite(Back, HIGH); } void TurnLeft() { digitalWrite(Left, HIGH); digitalWrite(Right, LOW); } void TurnRight() { digitalWrite(Left, LOW); digitalWrite(Right, HIGH); } void setup() { initL9110s(); } void loop() { //确定函数调用,先前进再后退,再左转右转 GoAhead(); delay(500); GoBack(); delay(500); TurnLeft(); delay(500); TurnRight(); delay(500); }
效果
[video width="1280" height="720" mp4="https://159.75.81.167/wp-content/uploads/2021/11/1637859205220265.mp4"][/video]通过串口控制
使用说明



代码
#define Ahead D6 #define Back D7 #define Left D4 #define Right D5 void initL9110s() { pinMode(Ahead, OUTPUT); pinMode(Back, OUTPUT); pinMode(Left, OUTPUT); pinMode(Right, OUTPUT); } void GoAhead() { digitalWrite(Ahead, HIGH); digitalWrite(Back, LOW); } void GoBack() { digitalWrite(Ahead, LOW); digitalWrite(Back, HIGH); } void TurnLeft() { digitalWrite(Left, HIGH); digitalWrite(Right, LOW); } void TurnRight() { digitalWrite(Left, LOW); digitalWrite(Right, HIGH); } void setup() { initL9110s(); Serial.begin(1152000); } void loop() { char cmd; if (Serial.available() > 0) { cmd = Serial.read(); switch (cmd) { case 'q': GoAhead(); break; case 'h': GoBack(); break; case 'z': TurnLeft(); break; case 'y': TurnRight(); break; } } }
整合WiFi模块通过网络控制
因为上面做过了网络控制蜂鸣器的子项目,这里可以直接拿之前的代码整合一下#define Ahead D6 #define Back D7 #define Left D4 #define Right D5 #include接下来烧录,然后用tcp工具连接上之后调试。char*ssid = "HUAWEI"; char*passwd = "2333...NMSL"; int port = 1234; WiFiServer server(port); //设置1234为服务的端口 void initWIFISta() { WiFi.mode(WIFI_STA); //设置为STA模式 WiFi.begin(ssid, passwd); //连接预设的WiFi while (WiFi.status() != WL_CONNECTED) { //监测WiFi连接状态 Serial.print("......"); Serial.print("\n"); delay(500); //ms,每隔0.5秒打印一个.表示连接中,直到满足状态跳出此循环 } Serial.print(WiFi.localIP()); //通过串口打印当前IP } void initL9110s() { pinMode(Ahead, OUTPUT); pinMode(Back, OUTPUT); pinMode(Left, OUTPUT); pinMode(Right, OUTPUT); } void GoAhead() { digitalWrite(Ahead, HIGH); digitalWrite(Back, LOW); } void GoBack() { digitalWrite(Ahead, LOW); digitalWrite(Back, HIGH); } void TurnLeft() { digitalWrite(Left, HIGH); digitalWrite(Right, LOW); } void TurnRight() { digitalWrite(Left, LOW); digitalWrite(Right, HIGH); } void setup() { initWIFISta(); initL9110s(); Serial.begin(115200); server.begin(); //启动网络服务 } void loop() { char cmd; WiFiClient client = server.available(); //初始化 while (client.connected()) { while (client.available() > 0) { cmd = client.read(); switch (cmd) { case 'q': GoAhead(); break; case 'h': GoBack(); break; case 'z': TurnLeft(); break; case 'y': TurnRight(); break; } } } }

加入自动避障功能
超声波模块
在上一个智能垃圾桶项目中,利用超声波模块识别物体靠近从而自动开盖,避障小车也是一样的原理,先找到之前的超声波代码。#include#define Montor D5 #define Echo D2 #define Trig D8 Servo MyMontor; long getTime() { digitalWrite(Trig, HIGH); delayMicroseconds(10); digitalWrite(Trig, LOW); return pulseIn(Echo, HIGH); } void initUltrasound() { pinMode(Echo, INPUT); pinMode(Trig, OUTPUT); } void setup() { MyMontor.attach(Montor); initUltrasound(); Serial.begin(115200); } void loop() { long distance; distance = getTime() / 58; if (distance < 10) { MyMontor.write(1); delay(2000); } else { MyMontor.write(180); } }
安卓APP控制小车
原理
基于Java(后面详解APP),点击按钮 自动给串口发送相应指令,松开按钮发送停止指令package com.gec.bluetoothcarlink; import android.app.Activity; import android.os.Bundle; import android.view.MotionEvent; import android.view.View; import android.view.View.OnTouchListener; import android.view.Window; import android.view.WindowManager; import android.widget.Button; public class ContrlActivity extends Activity { Button qian; Button hou; Button zuo; Button you; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 设置无标题栏 requestWindowFeature(Window.FEATURE_NO_TITLE); // 设置全屏 getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); // 保持屏幕常亮 getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); setContentView(R.layout.activity_contrl); initView(); } void initView() { qian = (Button) findViewById(R.id.btnqian); hou = (Button) findViewById(R.id.btnhou); zuo = (Button) findViewById(R.id.btnzuo); you = (Button) findViewById(R.id.btnyou); qian.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View arg0, MotionEvent event) { // TODO Auto-generated method stub switch (event.getAction()) { case MotionEvent.ACTION_DOWN: new NetUtils("q").sendMessage(); break; case MotionEvent.ACTION_UP: { new NetUtils("t").sendMessage(); break; } } return false; } }); hou.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View arg0, MotionEvent event) { // TODO Auto-generated method stub switch (event.getAction()) { case MotionEvent.ACTION_DOWN: new NetUtils("h").sendMessage(); break; case MotionEvent.ACTION_UP: { new NetUtils("t").sendMessage(); break; } } return false; } }); zuo.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View arg0, MotionEvent event) { // TODO Auto-generated method stub switch (event.getAction()) { case MotionEvent.ACTION_DOWN: new NetUtils("z").sendMessage(); break; case MotionEvent.ACTION_UP: { new NetUtils("b").sendMessage(); break; } } return false; } }); you.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View arg0, MotionEvent event) { // TODO Auto-generated method stub switch (event.getAction()) { case MotionEvent.ACTION_DOWN: new NetUtils("y").sendMessage(); break; case MotionEvent.ACTION_UP: { new NetUtils("b").sendMessage(); break; } } return false; } }); } }
成果演示
[video width="1280" height="720" mp4="https://159.75.81.167/wp-content/uploads/2021/11/1638194933097190.mp4"][/video]- 0
-
分享