After actual testing, the car ran very fast and easily lost control. This motherboard is suitable for controlling large motors. Now I am considering using RZ7899 to control the output in parallel or using a Loli remote control. The next finished product is expected to take a long time because I have to concentrate on learning and I encountered a bottleneck (I don’t know how to write the program controlled by 2.4hhz pwm. I would be very grateful if someone can help me). This time the car is very powerful. With the addition of a reducer, I am not afraid of the wheels falling off. It is recommended to add a 104 capacitor to the motor to eliminate high-frequency interference.
Manufacturing process display:
https://www.bilibili.com/read/cv6217381
Video results display
https://www.bilibili.com/video/bv1cz411B7Se
https://www.bilibili.com/video/bv1A5411s7Vs
The program is here:
//////////////////////////////////////////////////////////////////////////////////////////////
//// 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);
}
All reference designs on this site are sourced from major semiconductor manufacturers or collected online for learning and research. The copyright belongs to the semiconductor manufacturer or the original author. If you believe that the reference design of this site infringes upon your relevant rights and interests, please send us a rights notice. As a neutral platform service provider, we will take measures to delete the relevant content in accordance with relevant laws after receiving the relevant notice from the rights holder. Please send relevant notifications to email: bbs_service@eeworld.com.cn.
It is your responsibility to test the circuit yourself and determine its suitability for you. EEWorld will not be liable for direct, indirect, special, incidental, consequential or punitive damages arising from any cause or anything connected to any reference design used.
Supported by EEWorld Datasheet