秋栈博客

七月

基于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 

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!");
      }
    }
  }
}
手机端利用TCP工具 连接到wemos服务器,发送命令 既然原理知道了,那么就可以干一点别的事情了。

客户端控制蜂鸣器

#include 

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);
      }
    }
  }
}
当在手机发送指令1时,服务器端控制蜂鸣器发声,收到其他指令时,控制蜂鸣器停止发声。

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
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;
      }
    }
  }
}
接下来烧录,然后用tcp工具连接上之后调试。

加入自动避障功能

超声波模块

在上一个智能垃圾桶项目中,利用超声波模块识别物体靠近从而自动开盖,避障小车也是一样的原理,先找到之前的超声波代码。
#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