1.主控板是ARDUINO2560,主要控制全向轮的运动,与ESP8266交互.引脚图如下:ESP8266接的是串口三。加5V供电
三个全向轮电机使用了PWM引脚2--10,分别控制使能,方向,脉冲
主要底层函数ARDUINO
ARDUINO2560+ESP8266 控制小车
:
#include "motor.h"
#define DEBUG true
#define ESP8266Serail Serial3
int LED = 13; //LED指示灯引脚
void setup() {
pinMode(LED, OUTPUT);
digitalWrite(LED, LOW);
motor_init();
Serial.begin(9600);
ESP8266Serail.begin(9600); //esp8266波特率
sendCommand("AT+RST\r\n",2000,DEBUG); // 复位
setSTA("BataRobot3","3BataRobot");//连接wifi
Serial.println("Server Ready");
digitalWrite(LED, HIGH);//完成连接指示灯
}
void loop() {
if(ESP8266Serail.available()) // 是否接受到数据
{
if(ESP8266Serail.find("+IPD,"))
{
delay(100); // 等待接收完成
int connectionId = ESP8266Serail.read()-48; // subtract 48 because the read() function returns
ESP8266Serail.find("CMD:"); // advance cursor to "pin="
char myCMD= ESP8266Serail.read();
Serial.println(myCMD);
String content;
if(myCMD=='W'||myCMD=='w')//前进
{
Forward(200);delay(10);
content = "Car Forward over ";
}
else if(myCMD=='S'||myCMD=='s')//后退
{
Back(100);
delay(200);
Stop();
content = "Car Backward over ";
}
else if(myCMD=='D'||myCMD=='d')//右转
{
Right(100); delay(500);
Stop();
content = "Car Turn Right over ";
}
else if(myCMD=='A'||myCMD=='a')//左转
{
Left(100); delay(500);
Stop();
content = "Car Turn Left over ";
}
else//停止
{
Stop();
content = "Car Stop ";
}
//sendHTTPResponse(connectionId,content);//回复
}
}
}
/*
* Name: sendHTTPResponse
* Description: Function that sends HTTP 200, HTML UTF-8 response
*/
void sendHTTPResponse(int connectionId, String content)
{
String httpResponse;// build HTTP response
String httpHeader;
// HTTP Header
httpHeader = "HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=UTF-8\r\n";
httpHeader += "Content-Length: ";
httpHeader += content.length();
httpHeader += "\r\n";
httpResponse = httpHeader + content + "\r\n"; // There is a bug in this code: the last character of "content" is not sent, I cheated by adding this extra space
sendCIPData(connectionId,httpResponse);
}
/*
* Name: sendCIPDATA
* Description: sends a CIPSEND=<connectionId>,<data> command
*
*/
void sendCIPData(int connectionId, String data)
{
String cipSend = "AT+CIPSEND=";
cipSend += connectionId;
cipSend += ",";
cipSend +=data.length();
cipSend +="\r\n";
sendCommand(cipSend,1000,DEBUG);
sendData(data,1000,DEBUG);
}
//AP模式
void setAP(String wifi,String passwd)
{
sendCommand("AT+CWMODE=2\r\n",1000,DEBUG); // 开启 AP 模式
sendCommand("AT+CWSAP=\""+wifi+"\",\""+passwd+"\",11,0\r\n",3000,DEBUG);
}
//STA模式
void setSTA(String wifi,String passwd)
{
sendCommand("AT+CWMODE=1\r\n",1000,DEBUG); // 开启 STA 模式
sendCommand("AT+CWJAP=\""+wifi+"\",\""+passwd+"\"\r\n",3000,DEBUG);
delay(10000);
sendCommand("AT+CIFSR\r\n",1000,DEBUG); //查看MAC 和ip
sendCommand("AT+CIPMUX=1\r\n",1000,DEBUG); // 多设备连接
sendCommand("AT+CIPSERVER=1,8080\r\n",1000,DEBUG); // 打开服务器
}
/*
* esp8266发送数据
* command:AT命令
* timeout:超时时间
* debug:是否接受回复
*/
String sendData(String command, const int timeout, boolean debug)
{
String response = "";
int dataSize = command.length();
char data[dataSize];
command.toCharArray(data,dataSize);
ESP8266Serail.write(data,dataSize); // send the read character to the esp8266
if(debug)
{
Serial.println("\r\n====== HTTP Response From Arduino ======");
Serial.write(data,dataSize);
Serial.println("\r\n========================================");
}
long int time = millis();
while( (time+timeout) > millis())
{
while(ESP8266Serail.available())
{
char c = ESP8266Serail.read(); // 读取回复
response+=c;
}
}
if(debug)
{
Serial.print(response);
}
return response;
}
/*
* esp8266发送命令
* command:AT命令
* timeout:超时时间
* debug:是否接受回复
*/
String sendCommand(String command, const int timeout, boolean debug)
{
String response = "";
ESP8266Serail.print(command); // send the read character to the esp8266
long int time = millis();
while( (time+timeout) > millis())
{
while(ESP8266Serail.available())
{
char c = ESP8266Serail.read(); // read the next character.
response+=c;
}
}
if(debug)
{
Serial.print(response+"\r\n");
}
return response;
}
电机控制函数:
#include "motor.h"
#include <Arduino.h>
// MD01电机驱动引脚定义
int M1SLP = 2;
int M1PWM = 3;
int M1DIR = 4;
//MD02电机驱动引脚定义
int M2SLP = 5;
int M2PWM = 6;
int M2DIR = 7;
//MD03电机驱动引脚定义
int M3SLP = 8;
int M3PWM = 9;
int M3DIR = 10;
float Vx, Vy; //定义正交分解之后的速度
float V1, V2, V3;
void motor_init()
{
pinMode(M1SLP, OUTPUT);
pinMode(M1PWM, OUTPUT);
pinMode(M1DIR, OUTPUT);
pinMode(M2SLP, OUTPUT);
pinMode(M2PWM, OUTPUT);
pinMode(M2DIR, OUTPUT);
pinMode(M3SLP, OUTPUT);
pinMode(M3PWM, OUTPUT);
pinMode(M3DIR, OUTPUT);
}
void Forward(float speed) //前进,Y轴上下移动
{
Vy = -speed;
V1 = -sqrt(3) / 2 * Vy;
V2 = sqrt(3) / 2 * Vy;
V3 = 0;
enableM1();
digitalWrite(M1DIR, HIGH);
analogWrite(M1PWM, V1);
enableM2();
digitalWrite(M2DIR, LOW);
analogWrite(M2PWM, -V2);
analogWrite(M3PWM, V3);
}
void Back(float speed) //后退,Y轴上下移动
{
Vy = -speed;
V1 = -sqrt(3) / 2 * Vy;
V2 = sqrt(3) / 2 * Vy;
V3 = 0;
enableM1();
digitalWrite(M1DIR, LOW);
analogWrite(M1PWM, V1);
enableM2();
digitalWrite(M2DIR, HIGH);
analogWrite(M2PWM, -V2);
analogWrite(M3PWM, V3);
}
void Right(float speed) //右平移,X轴移动
{
Vx = speed;
V1 = -0.5 * Vx;
V2 = -0.5 * Vx;
V3 = Vx;
enableM1();
digitalWrite(M1DIR, HIGH);
analogWrite(M1PWM, V1);
enableM2();
digitalWrite(M2DIR, HIGH);
analogWrite(M2PWM, -V2);
enableM3();
digitalWrite(M3DIR, LOW);
analogWrite(M3PWM, V3);
}
void Left(float speed) //左平移,X轴移动
{
Vx = speed;
V1 = -0.5 * Vx;
V2 = -0.5 * Vx;
V3 = Vx;
enableM1();
digitalWrite(M1DIR, LOW);
analogWrite(M1PWM, V1);
enableM2();
digitalWrite(M2DIR, LOW);
analogWrite(M2PWM, -V2);
enableM3();
digitalWrite(M3DIR, HIGH);
analogWrite(M3PWM, V3);
}
void Stop() //停止
{
disableM1();
analogWrite(M1PWM, 0);
disableM2();
analogWrite(M2PWM, 0);
disableM3();
analogWrite(M3PWM, 0);
}
void enableM1() { //MD01电机驱动使能控制
digitalWrite(M1SLP, HIGH);
}
void disableM1() { //MD01电机驱动禁用控制
digitalWrite(M1SLP, LOW);
}
void enableM2() { //MD02电机驱动使能控制
digitalWrite(M2SLP, HIGH);
}
void disableM2() { //MD02电机驱动禁用控制
digitalWrite(M2SLP, LOW);
}
void enableM3() { //MD03电机驱动使能控制
digitalWrite(M3SLP, HIGH);
}
void disableM3() { //MD03电机驱动禁用控制
digitalWrite(M3SLP, LOW);
}
上位机控制程序:TCP 通讯:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net.Sockets;
using System.Net;
using System.Threading;
using System.IO;
namespace client
{
public partial class Form1 : Form
{
private Socket clientsocket;
public string ipaddress = "192.168.0.187";
public int port = 8080;
private byte[] data = new byte[1024];//数据容器
private Thread my_thread;
public Form1()
{
InitializeComponent();
connecttoserver();
}
void OnDestory(object sender, FormClosingEventArgs e)
{
//Environment.Exit(0);
clientsocket.Shutdown(SocketShutdown.Both);
clientsocket.Close();//关闭连接
}
void connecttoserver()
{
clientsocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//跟服务器连接
clientsocket.Connect(new IPEndPoint(IPAddress.Parse(ipaddress), port));
my_thread = new Thread(Receivemessage);//开启线程接收消息
my_thread.Start();
}
void snedmessage(string message)
{
byte[] data = Encoding.UTF8.GetBytes(message);
clientsocket.Send(data);
}
private void Receivemessage()
{
while (true)
{
//在接收前判断socket是否断开
if (clientsocket.Connected ==false)
{
clientsocket.Close();
break;
}
try
{
int lenght = clientsocket.Receive(data);
string message = Encoding.UTF8.GetString(data, 0, lenght);
textBox1.BeginInvoke(new Action(() =>
{
if (textBox1.Lines.Length > 15) textBox1.Text = "";
textBox1.Text += "\r\n" + message;//显示消息
}));
}
catch
{
clientsocket.Close();
break;
}
}
}
private void button1_Click(object sender, EventArgs e)//发送
{
string value = textBox2.Text;
snedmessage("xjh:"+value);
textBox2.Text = "";
}
private void ForwardBtn_Click(object sender, EventArgs e)//前进
{
snedmessage("+IPD,CMD:W" );
}
private void BackBtn_Click(object sender, EventArgs e)//后退
{
snedmessage("+IPD,CMD:S");
}
private void RightBtn_Click(object sender, EventArgs e)//向右
{
snedmessage("+IPD,CMD:D");
}
private void LeftBtn_Click(object sender, EventArgs e)//向左
{
snedmessage("+IPD,CMD:A");
}
}
}