一级减速竞速赛车 arduino控制

1周前

简介:为了年少时候的梦想,不断的努力改进,终于完成了这个最终的设计方案,如果再改进的话,我觉得就是在后轮加个差速器前轮改成直接转向就好了,但是应该很困难,这个就以后再说了。

开源协议: GPL 3.0

描述

经过实际测试车跑的非常快,容易失控,这个主板适用于控制大电机,现在考虑使用RZ7899并联控制输出或者是使用萝莉遥控器控制,下一个成品预计会很长时间,因为要专心学习而且遇到了瓶颈(2.4hhz pwm控制的程序不会写要是有大佬帮助我感激不尽) 这次车是厉害的很 加入了减速器就不怕车轮掉下来了。 建议电机上加104电容消除高频干扰。

视频成果展示 https://www.bilibili.com/video/bv1cz411B7Se https://www.bilibili.com/video/bv1A5411s7Vs

程序在这:

//////////////////////////////////////////////////////////////////////////////////////////////
//// Communication protocol start
//// ----the only thing you need to do is modifying the numbers of variables according to your demand
//
//****define what to send to cell phone*******************
#define NUM_TX_BOOL   0
#define NUM_TX_ByTE   0
#define NUM_TX_SHORT  2
#define NUM_TX_INT    0
#define NUM_TX_FLOAT  0
//*******************************************************

//****define what we want to get from cell phone********
#define NUM_RX_BOOL   3
#define NUM_RX_ByTE   5
#define NUM_RX_SHORT  0
#define NUM_RX_INT    0
#define NUM_RX_FLOAT  0
//*******************************************************

// size of Loop Buffer is editable depending on the data packet transmission rate and memory space
#define LOOP_BUFFER_SIZE 512
#define SIZE_RECV_PERTIME 64  // fixed

/////////////////////////////////////////////////////
//Do not change the code below+++++++++++++++++++++++
/////////////////////////////////////////////////////
// data structure to send to phone
struct {
bool bools        [NUM_TX_BOOL];
int8_t bytes      [NUM_TX_ByTE];
int16_t shorts    [NUM_TX_SHORT];
int32_t  integers [NUM_TX_INT];
float   floats    [NUM_TX_FLOAT];
}txPack;

// data structure to recv from phone
struct {
bool bools        [NUM_RX_BOOL];
int8_t bytes      [NUM_RX_ByTE];
int16_t shorts    [NUM_RX_SHORT];
int32_t  integers [NUM_RX_INT];
float   floats    [NUM_RX_FLOAT];
} rxPack;

byte loopBuffer[LOOP_BUFFER_SIZE];
byte rxPacketBuffer[((NUM_RX_BOOL+7)>>3)+NUM_RX_ByTE+(NUM_RX_SHORT<<1)+(NUM_RX_INT<<2)+(NUM_RX_FLOAT<<2)+3];
byte txPacketBuffer[((NUM_TX_BOOL+7)>>3)+NUM_TX_ByTE+(NUM_TX_SHORT<<1)+(NUM_TX_INT<<2)+(NUM_TX_FLOAT<<2)+3];

int16_t RXPACK_SIZE = sizeof(rxPacketBuffer);
int16_t TXPACK_SIZE = sizeof(txPacketBuffer);
int32_t INDEX_RANGE = LOOP_BUFFER_SIZE*2;

HardwareSerial *pSerial;

void initPack(HardwareSerial &serial, int32_t baudRate)
{
serial.begin(baudRate);
serial.setTimeout(0);
pSerial = &serial;
}
void getVariables(void)
{
unsigned char byte_pos=0,bit_pos=0;
#if (NUM_RX_BOOL>0)
for(int i=0;i<NUM_RX_BOOL;i++)
{
rxPack.bools[i] = (0x01<<bit_pos)&rxPacketBuffer[byte_pos];
bit_pos++;
if(bit_pos>=8)
{
byte_pos++;
bit_pos=0;
}
}
if(bit_pos!=0)
byte_pos++;
#endif

#if (NUM_RX_ByTE>0)
for(int i=0;i<NUM_RX_ByTE;i++)
{
rxPack.bytes[i] = rxPacketBuffer[byte_pos];
byte_pos++;
}
#endif

#if (NUM_RX_SHORT>0)
for(int i=0;i<NUM_RX_SHORT;i++)
{
rxPack.shorts[i] = (rxPacketBuffer[byte_pos+1]<<8)|rxPacketBuffer[byte_pos];
byte_pos+=2;
}
#endif

#if (NUM_RX_INT>0)
for(int i=0;i<NUM_RX_INT;i++)
{
rxPack.integers[i] = (rxPacketBuffer[byte_pos+3]<<24)| (rxPacketBuffer[byte_pos+2]<<16)| (rxPacketBuffer[byte_pos+1]<<8)|rxPacketBuffer[byte_pos];
byte_pos+=4;
}
#endif

#if (NUM_RX_FLOAT>0)
float f;
byte *p = (byte *) &f;
int pp=0;
for(int i=0;i<NUM_RX_FLOAT;i++)
{
p[0+pp] =  rxPacketBuffer[byte_pos];
p[1+pp] =  rxPacketBuffer[byte_pos+1];
p[2+pp] =  rxPacketBuffer[byte_pos+2];
p[3+pp] =  rxPacketBuffer[byte_pos+3];
pp+=4;
byte_pos+=4;
rxPack.floats[i] = f;
}
#endif

}
int32_t  rxIndex=0;
int32_t rdIndex=0;
int32_t err=0;
int32_t sum;
bool recvPack(void)
{

int start_index;
int tail_index;
int cut_size;
int rx_length;
bool isOK = 0;
int rx_pack_index;

// read bytes to loop buffer
start_index = rxIndex%LOOP_BUFFER_SIZE;
if(start_index+SIZE_RECV_PERTIME<=LOOP_BUFFER_SIZE)
{
rx_length+=pSerial->readBytes(loopBuffer+start_index,SIZE_RECV_PERTIME);
rxIndex+=rx_length;
}else
{
cut_size = LOOP_BUFFER_SIZE-start_index;
rx_length=pSerial->readBytes(loopBuffer+start_index,cut_size);
rxIndex+=rx_length;
if(rx_length==cut_size)
{
cut_size = SIZE_RECV_PERTIME-cut_size;
rx_length=pSerial->readBytes(loopBuffer,cut_size);
rxIndex+=rx_length;
}
}

// extract a complete packet
while(rdIndex<(rxIndex-2*RXPACK_SIZE))
rdIndex+=RXPACK_SIZE;

while(rdIndex<=rxIndex-RXPACK_SIZE)
{
start_index = rdIndex%LOOP_BUFFER_SIZE;
isOK = 0;
if(loopBuffer[start_index]==0xA5)
{
tail_index = (start_index+RXPACK_SIZE-1)%LOOP_BUFFER_SIZE;
if(loopBuffer[tail_index]==0x5A)  // Head and Tail match
{
rx_pack_index = 0;
// Check Summing
sum = 0;
// if data packet is divided into two segments
if(tail_index<start_index)
{
for(int i = start_index+1;i<LOOP_BUFFER_SIZE;i++)
{
rxPacketBuffer[rx_pack_index] = loopBuffer[i];
rx_pack_index++;
sum+=loopBuffer[i];
}
for(int i = 0;i<tail_index-1;i++)
{
rxPacketBuffer[rx_pack_index] = loopBuffer[i];
rx_pack_index++;
sum+=loopBuffer[i];
}
tail_index--;
if(tail_index<0)
tail_index+=LOOP_BUFFER_SIZE;

if(loopBuffer[tail_index]==(sum&0xff))
isOK = 1;
}else // data packet is contiguous
{
for(int i = start_index+1;i<tail_index-1;i++)
{
rxPacketBuffer[rx_pack_index] = loopBuffer[i];
rx_pack_index++;
sum+=loopBuffer[i];
}
if(loopBuffer[tail_index-1]==(sum&0xff))
isOK = 1;
}
if(isOK) // parse the data to rxPack
{
getVariables();
rdIndex+=RXPACK_SIZE;
}
}
}
if(!isOK)
{
rdIndex++;
err++;
}
}
// limit the range of read index and recv index
if(rxIndex>INDEX_RANGE&&rdIndex>INDEX_RANGE)
{
rxIndex-=INDEX_RANGE;
rdIndex-=INDEX_RANGE;
}
return isOK;
}

void sendPack(void)
{
short byte_pos=0,bit_pos=0;
int32_t sum=0;
txPacketBuffer[byte_pos++] = 0xA5;

#if (NUM_TX_BOOL>0)
for(int i=0;i<NUM_TX_BOOL;i++)
{
if(txPack.bools[i])
txPacketBuffer[byte_pos] |= 0x01<<bit_pos;
else
txPacketBuffer[byte_pos] &= ~(0x01<<bit_pos);
bit_pos++;
if(bit_pos>=8)
{
byte_pos++;
bit_pos=0;
}
}
if(bit_pos!=0)
byte_pos++;
#endif

#if (NUM_TX_ByTE>0)

for(int i=0;i<NUM_TX_ByTE;i++)
txPacketBuffer[byte_pos++] = txPack.bytes[i];

#endif

#if (NUM_TX_SHORT>0)
for(int i=0;i<NUM_TX_SHORT;i++)
{
txPacketBuffer[byte_pos++] = txPack.shorts[i]&0xff;
txPacketBuffer[byte_pos++] = (txPack.shorts[i]>>8)&0xff;
}
#endif

#if (NUM_TX_INT>0)
for(int i=0;i<NUM_TX_INT;i++)
{
txPacketBuffer[byte_pos++] = txPack.integers[i]&0xff;
txPacketBuffer[byte_pos++] = (txPack.integers[i]>>8)&0xff;
txPacketBuffer[byte_pos++] = (txPack.integers[i]>>16)&0xff;
txPacketBuffer[byte_pos++] = (txPack.integers[i]>>24)&0xff;
}
#endif

#if (NUM_TX_FLOAT>0)
float f;
byte *add;
for(int i=0;i<NUM_TX_FLOAT;i++)
{
f = txPack.floats[i];
add = (byte *)&f;

txPacketBuffer[byte_pos++] = add[0];
txPacketBuffer[byte_pos++] = add[1];
txPacketBuffer[byte_pos++] = add[2];
txPacketBuffer[byte_pos++] = add[3];
}
#endif

for(int i=1;i<TXPACK_SIZE-2;i++)
sum+=txPacketBuffer[i];
txPacketBuffer[byte_pos++] = sum&0xff;
txPacketBuffer[byte_pos] = 0x5a;

pSerial->write(txPacketBuffer,TXPACK_SIZE);
}

/////////////////////////////////////////////////////
//Do not change the code above-----------------------
/////////////////////////////////////////////////////
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@//
//// Communication protocol end//////////////////////
/////////////////////////////////////////////////////

#define righA_PIN 9
#define righB_PIN 10
#include <Servo.h>

void motor_pinint();
void LEFTmotorcontrolGO();
void RIGHTmotorcontrolBACK();
void RIGHTmotorcontrolGO();
void LEFTmotorcontrolBACK();
void motorcontrolSTOP();
void LEFTmotorcontrolSTOP();
void RIGHTmotorcontrolSTOP();
void STOPP();
void sdcl();

/*电机引脚初始化*/
void motor_pinint()
{
pinMode (righA_PIN, OUTPUT); //设置引脚为输出引脚
pinMode (righB_PIN, OUTPUT); //设置引脚为输出引脚
pinMode (6, OUTPUT); //设置引脚为输出引脚
pinMode (5, OUTPUT); //设置引脚为输出引脚
pinMode (12, OUTPUT); //设置引脚为输出引脚
pinMode (2,OUTPUT);
pinMode (A0, INPUT);
}

Servo myservo;  // 定义Servo对象来控制
int pos = 0;    // 角度存储变量
int sudu=0;
int SPEED=0;
int led=0;
int closetime=0;
int opentime=0;
int dangwei=0;
int zhuanxiang=0;
int k=9900;
int i=0;
int sc=0;
int duoji=100;
int sd=0;
int zxcha=0;
unsigned long duration;
unsigned long A=0.0;//定义duration变量为无符号长整数型变量

void setup()
{
myservo.attach(11);
motor_pinint();
Serial.begin(19200); //串口波特率9600(PC端使用)
initPack(Serial,19200);
}

void loop()
{
if(recvPack())
{
sudu=rxPack.bytes[0];
duoji=rxPack.bytes[3];
zxcha=rxPack.bytes[4];
led=rxPack.bools[0]2;
*    sc=rxPack.bools[1];*
*    sd=rxPack.bools[2];*
*      if (sc==1) myservo.write(duoji);*
*      else myservo.write(100);*
*    dangwei=rxPack.bytes[1];*
*    zhuanxiang=rxPack.bytes[2];*
*    digitalWrite(12,led);*
*    SPEED=dangweisudu;
Serial.println(SPEED);
if(SPEED>9900){
digitalWrite(2,LOW);
LEFTmotorcontrolGO();
RIGHTmotorcontrolGO();}
else if(SPEED<-9900){
digitalWrite(2,LOW);
RIGHTmotorcontrolBACK();
LEFTmotorcontrolBACK();}
else if(SPEED>=1000)
{
digitalWrite(2,LOW);
opentime = map(SPEED, 1000, 9900, 200, 0);
closetime = map(SPEED, 1000, 9900, 5, 100);
RIGHTmotorcontrolGO();
LEFTmotorcontrolGO();
delay(closetime);           //延时1000ms
if(zhuanxiang>=30)
{
k=(zhuanxiangSPEED)/100;
zhuanxiang=map(k,300,9900,zxcha,0);
LEFTmotorcontrolSTOP();
delay(zhuanxiang);
}
motorcontrolSTOP();
delay(opentime);           //延时1s
}

else if(SPEED<=-1000)
{
digitalWrite(2,LOW);
SPEED=-SPEED;
opentime = map(SPEED, 1000, 9900, 200, 0);
closetime = map(SPEED, 1000, 9900, 5, 100);
RIGHTmotorcontrolBACK();
LEFTmotorcontrolBACK();
delay(closetime);           //延时1000ms
if(zhuanxiang<=-30)
{
zhuanxiang=-zhuanxiang;
k=(zhuanxiang*SPEED)/100;
zhuanxiang=map(k,300,9900,zxcha,0);
RIGHTmotorcontrolSTOP();
delay(zhuanxiang);
}
motorcontrolSTOP();
delay(opentime);           //延时1s
}
else{
motorcontrolSTOP();
STOPP();
}
}
if (sd==1) {sdcl();
sendPack();}

}

void RIGHTmotorcontrolGO()
{
digitalWrite(righA_PIN, HIGH);
digitalWrite(righB_PIN, LOW);
}

void LEFTmotorcontrolGO()
{
digitalWrite(5, HIGH);
digitalWrite(6, LOW);
}
void RIGHTmotorcontrolBACK()
{
digitalWrite(righA_PIN, LOW);
digitalWrite(righB_PIN, HIGH);
digitalWrite(6, HIGH);
digitalWrite(5, LOW);
}

void LEFTmotorcontrolBACK()
{
digitalWrite(6, HIGH);
digitalWrite(5, LOW);
}

void RIGHTmotorcontrolSTOP()
{
digitalWrite(2,LOW);
digitalWrite(righA_PIN, LOW);
digitalWrite(righB_PIN, LOW);
}
void LEFTmotorcontrolSTOP()
{
digitalWrite(2,LOW);
digitalWrite(5, LOW);
digitalWrite(6, LOW);

}
void motorcontrolSTOP()
{
digitalWrite(5, LOW);
digitalWrite(6, LOW);
digitalWrite(righA_PIN, LOW);
digitalWrite(righB_PIN, LOW);

}

void STOPP()
{
delay(5);
digitalWrite(2,HIGH);
Serial.println("停止");

}

void sdcl()
{
duration = pulseIn(A0,HIGH);
A = 17278759.595/duration;
Serial.println(A);
txPack.shorts[0] =(A);
txPack.shorts[1] =(A/100*3.6);
//Serial.println(duration);
}

文档

竞速级赛车

在编辑器中打开

竞赛级赛车成品电路板

在编辑器中打开

BOM

ID Name Designator Footprint Quantity
1 NO U8 ARDUINO_NANO444444 1
2 10uF C3 CAP-TH_BD4.0-P1.50-D0.8-FD 1
3 200 R1,R3 R0805 2
4 JQC-3FF/05-1ZS(551) K1,K2,K4,K3 RELAY-TH_HF3FF/XX-1ZXX(XXX) 4
5 470 1470,2470,4470,3470,1 R0805 5
6 L78M05CDT-TR U5,DUOJI TO-252-2_L6.5-W6.1-P4.58-LS10.0-BR 2
7 LM317_C77880 U2 TO-252-2_L6.6-W6.1-P4.57-LS9.9-TL-CW 1
8 车底基座 U1 遥控车基座 1
9 1N4007 14007,34007 SMA_L4.4-W2.8-LS5.4-RD 2
10 24007 24007 SMA_L4.4-W2.8-LS5.4-RD 1
11 44007 44007 SMA_L4.4-W2.8-LS5.4-RD 1
12 AP2300 Q2,Q1 SOT-23 2
13 68000-103HLF H1,H2,H3 HDR-TH_3P-P2.54-V 3
14 电机接口 U7,U9 电机接口 2
15 S8050_C181158 18050,28050,48050,38050 SOT-23-3_L2.9-W1.6-P1.90-LS2.8-BR 4
16 EL817S(B)(TU)-F U3,U10,U11,U12 SOP-4_L6.5-W4.6-P2.54-LS10.2-TL 4
17 100nF C1 C0603 1
18 MSS22D18G2 SWLY,SWLY1,SWLY2 SW-TH_MSS22D18GX 3
19 E6C0805URAC1UDA DJ LED0805-R-RD 1
20 10uf C4 C0805 1
21 10k R22,R4 R0805 2
22 10K 10K1,10K2,10K4,10K3 R0805 4
23 1K 1K1,1K2,1K4,1K3 R0805 4
24 A2541HWV-6P LYMK HDR-TH_6P-P2.54-V_A2541HWV-6P 1
25 TJ-L5FYTYGTDLSFLC6TW-A5 LED2,LED1 LED-TH_BD5.8-P2.54-FD 2
26 电源12V焊盘 U4,U6 电源12V焊盘 2
27 1K R2 R0805 1
28 YS-MBZ12095DYB05_C409831 BUZZER3 BUZ-TH_BD12.0-P7.60-D0.6-FD 1

展开

工程成员

登录注册之后才可以进行评论操作
工程所有者当前已关闭评论
征集令发布者当前已关闭评论
全部评论 1

verysunshine

记得继电器那里要加粗导线 因为要走大电流

2020-05-23 22:04:28
回复

服务时间

周一至周五 9:00~18:00
  • 0755 - 2382 4495
  • 153 6159 2675

服务时间

周一至周五 9:00~18:00
  • 立创EDA微信号

    easyeda

  • QQ交流群

    664186054

  • 立创EDA公众号

    lceda-cn