哪位大神能帮我写一个arduino 控制两个直流电机正反转,加减速和拐弯的程序啊?arduino程序,非常感谢。 如何用arduino板和l298n控制直流电机正反转?
\u600e\u6837\u7528Arduino\u53bb\u63a7\u5236\u76f4\u6d41\u7535\u673a\u6b63\u53cd\u8f6c\uff1f19\u3001Arduino\u5165\u95e8\u89c6\u9891\u6559\u7a0b PWM\u63a7\u52362\u4e2a\u7535\u673a\u6b63\u8f6c
\u4e00\u3001\u786c\u4ef6\u8fde\u63a5
\u91c7\u7528\u4e24\u8def\u7ee7\u7535\u5668\u6a21\u5757\u63a7\u5236\u76f4\u6d41\u7535\u52a8\u673a\u3002
\u786c\u4ef6\u8fde\u63a5
\u4e8c\u3001\u63a7\u5236\u7a0b\u5e8f
\u63a7\u5236\u7a0b\u5e8f
\u4ece\u6570\u5b57\u8f93\u51fa\u7ba1\u811a7\u30018\u4e24\u811a\u8f93\u51fa\u63a7\u5236\u4fe1\u53f7\uff0c\u63a7\u5236\u4e24\u8def\u7ee7\u7535\u5668\u4ea4\u66ff\u5bfc\u901a\u3002\u6362\u5411\u4e2d\u95f4\u6709\u4e00\u505c\u6b62\u8fc7\u7a0b\uff0c\u907f\u514d\u7535\u673a\u51b2\u51fb\u8fc7\u5927\u3002
假设您使用无线串口控制小车,那么你需要设计一个串口指令协议,一般来说,通信协议的数据帧包括3部分,一是指令头,又叫做帧同步字;二是指令内容,也叫帧内容;三是校验码。
同步字是为了便于程序分析连续传输的数据中,帧与帧之间的间隔,帧内容包含了所有经过16进制编码的各种控制指令和数据,校验码通常采用累加和与异或算法,为了计算本数据帧是否正确。(工业环境中,所有数据传输系统都存在一定的误码干扰,校验字能有效判别数据传输是否正确,进而通过错误处理机制,有效避免错误动作)。
刚好前段时间写了个小车的控制程序,使用的是双路H桥来驱动电机的,不过不是控制履带式的,稍微改动了下。
(注意,本程序仅适用于履带式小车,即左右电机正反转实现前后及转向,程序支持前后左右混控)
//********************************
// 遥控帧协议和结构
// FB|80|51|AA|FF|BB|FF|BY|BY|BY|BY|BY|BY|CR
// 00|01|02|03|04|05|06|07|08|09|10|11|12|13
// 14 byte
//FB 80 51 遥控帧同步字 00-02
//AA 前后控制量 128为中立位 03
//FF 恒定为0xFF 04
//BB 左右控制量 128为中立位 05
//FF 恒定为0xFF 06
//BY 备用控制指令 本程序为空 07-12
//CR 校验码,从00至12字节逐字节位异或 13
//********************************
// 遥测帧协议结构
// FB|80|61|AA|FF|BB|FF|BY|BY|BY|BY|BY|BY|CR
// 00|01|02|03|04|05|06|07|08|09|10|11|12|13
// 14 byte
// 重复遥控指令,除帧头外,其定义与遥控指令相同
#define BR 9600 //定义串口波特率
//遥控指令接收处理相关定义
#define TCDL 14 //定义遥控数据帧长度字节数
#define BUFF_LONG 30 //定义串口接收缓存的长度
byte BUFF[BUFF_LONG]; //定义串口数据接收存储缓存
int BUFF_IDX = 0; //定义串口数据接收存储缓存的指针
//遥测指令发送处理相关定义
#define TMFQ 80 //定义遥测数据帧发送间隔为80ms
#define TMDL 14 //定义遥测数据帧长度字节数
byte TM_Data[TMDL]; //定义遥测数据缓存
int TM_Index = 0; //定义遥测数据指针
unsigned long Time = 0; //定义遥测发送计时器为0
//定义左、右电机与Arduino的驱动信号接口
//注意,这里用了4个PWM输出,部分Arduino板可能不支持,请查看手册
int Moto_Right_A = 3;
int Moto_Right_B = 5;
int Moto_Left_A = 6;
int Moto_Left_B = 9;
//数据接收指示灯相关定义
boolean IS_Blink = false; //定义是否闪烁LED灯的变量
int LED = 13; //定义LED灯接口为13
//指令变量定义
byte RunPWM = 128; //定义前进、后退控制PWM指令变量
byte TurnPWM = 128; //定义左转、右转控制PWM指令变量
void setup()
{
pinMode(Moto_Right_A, OUTPUT); //定义输出
pinMode(Moto_Right_B, OUTPUT); //定义输出
pinMode(Moto_Left_A, OUTPUT); //定义输出
pinMode(Moto_Left_B, OUTPUT); //定义输出
pinMode(LED, OUTPUT); //定义LED管脚为数字输出
Port_Init(); //初始化串口
Blink_LED(false); //关闭指示灯
}
void loop()
{
byte c;
if (Serial.available() > 0) //如果接收到串口数据
{
c = Serial.read(); //读一个字节
Buff_AddChar(c); //塞进缓存进行存储、校验和解码
}
TM_Freq(); //尝试按要求逐字节发送遥测数据
Driver_CAR(RunPWM, TurnPWM); //驱动左右电机正反转,实现运动控制
}
//驱动左右电机调速运行,实现左右正反转组合,实现控制
//前后、左右混控
void Driver_CAR(byte Run, byte Turn)
{
byte Run_L, Run_R; //定义左右前进混合值
byte PWM_R_A, PWM_R_B, PWM_L_A, PWM_L_B; // 定义4个信号的独立PWM
Run_L = Run - (128 - Turn); //将转向PWM混合到左路
Run_R = Run - (Turn - 128); //将转向PWM混合到右路
PWM_L_A = (255 / 128) * Run_L - 255; //左路混合值结算为左路A信号PWM
PWM_L_B = (-1 * 255 / 128) * Run_L + 255; //左路混合值结算为左路B信号PWM
PWM_R_A = (255 / 128) * Run_R - 255; //右路混合值结算为右路A信号PWM
PWM_R_B = (-1 * 255 / 128) * Run_R + 255; //右路混合值结算为右路B信号PWM
analogWrite(Moto_Right_A, PWM_R_A); //输出右路A信号
analogWrite(Moto_Right_B, PWM_R_B); //输出右路B信号
analogWrite(Moto_Left_A, PWM_L_A); //输出左路A信号
analogWrite(Moto_Left_B, PWM_L_B); //输出左路B信号
}
//********************************
//子程序 Port_Init()
//功能:初始化串口通信
void Port_Init()
{
BUFF_IDX = 0; //初始化串口缓存指针为0
TM_Data[0] = 0xFB; //初始化遥测数据帧头
TM_Data[1] = 0x80; //初始化遥测数据帧头
TM_Data[2] = 0x61; //初始化遥测数据帧头
Serial.begin(BR); //定义波特率并启动串口
}
//********************************
// 子程序 Buff_AddChar(byte b)
// 功能:串口接收字节加入缓存
// 1、加入字节到缓存;
// 2、检测到帧头则尝试检测遥控帧;
// 3、管理缓存指针
void Buff_AddChar(byte b)
{
BUFF[BUFF_IDX] = b; // 缓存[缓存指针] = 接收字节
if (BUFF_IDX >= 2)
{
if (BUFF[BUFF_IDX] == 0x51 && BUFF[BUFF_IDX - 1] == 0x80 && BUFF[BUFF_IDX - 2] == 0xFB) // 检测遥控帧头
{
if (BUFF_IDX == (TCDL - 1))
{
Buff_DCHK(); // 检测校验码
}
BUFF_IDX = 0; // 缓存指针归零
return;
}
}
BUFF_IDX++;
if (BUFF_IDX > (BUFF_LONG - 1)) // 缓存指针越界
{
BUFF_IDX = 0; // 缓存指针归零
}
}
//********************************
//子程序 Buff_DCHK()
//功能:校验遥控帧校验字是否正确
void Buff_DCHK()
{
byte DCHK = 0x00;
// 0xFB XOR 0x80 XOR 0x51
DCHK = BUFF[0];
DCHK = DCHK ^ BUFF[1];
DCHK = DCHK ^ BUFF[2];
int i;
for (i = 0; i < (TCDL - 4); i++)
{
DCHK = DCHK ^ BUFF[i];
}
if (DCHK == BUFF[TCDL - 4])
{
//校验字正确
Blink_LED(true); //闪烁LED
Get_CMD(); //解码指令
}
}
//********************************
// 子程序 Get_CMD()
// 功能:解码遥控指令
void Get_CMD()
{
RunPWM = BUFF[0];
TurnPWM = BUFF[2];
//后面可以自己添加关于BY指令的解码处理
}
//********************************
//子程序 TM_Freq()
//功能:遥测数据发送帧率控制
void TM_Freq()
{
unsigned long t;
if (TM_Index < TMDL) //如果一帧数据还没有发完
{
Serial.write(TM_Data[TM_Index]); //继续发数据
TM_Index++; //指针累加
}
else //如果发完
{
if (Time == 0) //检测计时器是否为0
{
Time = millis(); //是则赋予计时器初始值
}
else //不是
{
t = millis();
if (t - Time >= TMFQ) //检测计时器是否到达帧率控制的时间
{
Time = t;
TM_Make_Data(); //到达发送时间,则组一帧遥测数据,并开始发送
}
}
}
}
//********************************
// 子程序 TM_Make_Data()
// 功能:发送遥测数据
void TM_Make_Data()
{
// 遥测帧协议结构
//FB|80|61|AA|FF|BB|FF|BY|BY|BY|BY|BY|BY|CR
//00|01|02|03|04|05|06|07|08|09|10|11|12|13
byte CHK = 0xFB; //赋值帧头
CHK = CHK ^ 0x80; //赋值帧头
CHK = CHK ^ 0x61; //赋值帧头
TM_Data[3] = RunPWM; //回写前后指令
TM_Data[4] = 0xFF;
CHK = CHK ^ TM_Data[3]; //计算校验码
CHK = CHK ^ TM_Data[4]; //计算校验码
TM_Data[5] = TurnPWM; //回写转向指令
TM_Data[6] = 0xFF;
CHK = CHK ^ TM_Data[5]; //计算校验码
CHK = CHK ^ TM_Data[6]; //计算校验码
CHK = CHK ^ TM_Data[7]; //计算校验码
CHK = CHK ^ TM_Data[8]; //计算校验码
CHK = CHK ^ TM_Data[9]; //计算校验码
CHK = CHK ^ TM_Data[10]; //计算校验码
CHK = CHK ^ TM_Data[11]; //计算校验码
CHK = CHK ^ TM_Data[12]; //计算校验码
TM_Data[13] = CHK; //计算校验码
TM_Index = 0; //清除遥测发送指针位置
}
//********************************
//子程序 Blink_LED()
//功能:闪烁内置LED灯
void Blink_LED(boolean Blink)
{
if (Blink == false)
{
IS_Blink = false;
}
else
{
IS_Blink = !IS_Blink;
}
digitalWrite(LED, IS_Blink);
}
#includetemplatevoidinsertion_sort(biIterbegin,biIterend){typedeftypenamestd::iterator_traits::value_typevalue_type;biIterbond=begin;std::advance(bond,1);for(;bond!=end;std::advance(bond,1)){value_typekey=*bond;biIterins=bond;biIterpre=ins;std::advance(pre,-1);while(ins!=begin&&*pre>key){*ins=*pre;std::advance(ins,-1);std::advance(pre,-1);}*ins=key;}}
我做电子设计的
会
绛旓細浣犵殑绋嬪簭inp鍙涓娆★紝濡傛灉鎸夐敭鎸変笅灏辫繘鍘绘寰幆锛屼竴娆″悗灏辨病鍙嶅簲浜嗐傛渶鍚庣殑while閫昏緫鏈夐棶棰樸
绛旓細绗簩涓▼搴忕殑setup鍑芥暟涓婇潰杈撳叆锛歩nt pin=12;setup鍑芥暟涓啓pinMode(pin,OUTPUT);loop鍑芥暟涓啓绗涓涓绋嬪簭鐨刲oop涓殑璇彞
绛旓細C鏄护娉㈢數瀹癸紝D鏄暣娴佷簩鏋佺銆侰鍜孌鏋勬垚鍗婃尝鏁存祦鐢佃矾锛屽皢鍙樺帇鍣ㄦ绾т氦娴佺數鍘嬪彉涓轰簡鐩存祦鐢靛帇銆俆鏄Е鍙戜簩鏋佺锛屽綋ARDUINO杈撳叆楂樼數骞崇殑鏃跺欙紝T瀵奸氾紝鍚屾椂MOC3041鑺墖鍐呴儴鍙戝厜绠$偣浜紝鍏夎﹁緭鍑鸿Е鍙戜俊鍙凤紝瑙﹀彂BAT12鍙屽悜鍙帶纭咃紝榛勮壊鐏场鐐逛寒銆侳鏄繚闄╀笣鍟婏紒澶т緺锛屼繚闄╀笣璧蜂粈涔堜綔鐢ㄤ綘搴旇鐭ラ亾鐨勩
绛旓細鏉垮瓙宸︿笅鏂规湁涓鎺掓帓姣嶏紙灏辨槸鏈闈犺繎鍦嗗舰DC鐢垫簮鎺ュ彛鐨勯偅涓鎺掞級锛屼粠宸﹀線鍙虫暟绗笁涓爣鏈塕ESET锛堝す鍦↖OREF鍜3.3V涔嬮棿鐨勯偅涓級鐨勬帓瀛斿氨鏄疪ESET Pin銆傚皢姝ゅ紩鑴氭帴鍦板悗杩呴熸柇寮鍗冲彲澶嶄綅Arduino銆
绛旓細涓夎剼寮鍏崇殑璇濓紝鍙互鐢ㄦ娴嬮珮浣庣數骞崇殑鏂规硶锛岀敤if璇彞瀹炵幇锛屾瘮濡傚皢寮鍏崇殑涓夎剼鍒嗗埆鎺ND锛 pin 3锛宲in4鑴氾紙3,4鑴氬垵濮嬩负楂樼數骞筹級锛岀▼搴忎腑妫娴3锛4鑴氱殑鐢靛钩锛屼綆鐢靛钩鐨勬椂鍊欏姩浣
绛旓細include <MsTimer2.h>// 瀹氫箟LED鐨勫紩鑴#define LED_PIN_A 1#define LED_PIN_B 2// 鏃堕棿瀹氫箟瀹#define TM_MS(n) (n)static uint16_t timerCntA;static uint16_t timerCntB;void TimerCbk (void);void setup(){ pinMode(LED_PIN_A , OUTPUT); pinMode(LED_PIN_B , OUTPUT);...
绛旓細璁℃椂鐢╠elay鏄釜寰堝ぇ鐨勯夯鐑︼紝鍥犱负delay鏃朵笉鍝嶅簲浠讳綍鎸夐挳涔嬬被鐨勬娴嬶紝鐩稿綋浜庡亣姝荤姸鎬併傛妸鎸夐挳妫娴嬫敼涓哄閮ㄤ腑鏂紝鍙互鍕夊己鐢╠elay锛屽叾瀹炶鏃朵篃鍙互鐢ㄤ腑鏂紝鎼滀簺涓柇璧勬枡鐪嬪惂
绛旓細boboUp(); inString=""; p++; a=0; }}鎴戠敤鑷繁鐨勬澘瀛愭祴璇曞彲鐢紝缁撴灉濡備笅鍥剧敤娉曟槸鍦⊿erial Monitor鏈涓婇潰鐨勭紪杈戞閲岃緭鍏涓涓鏁板瓧鍗曞嚮send灏变細鍚戞暟缁勯噷淇濆瓨涓涓暟瀛楋紙涓嶆敮鎸佽緭鍏ヤ竴涓叉暟瀛楋紝浣犺瘯鐫鑷繁鏀逛唬鐮佸惂锛夛紝褰撴暟缁勬洿鏂版椂arduino灏变細閫氳繃涓插彛鍚戣绠楁満杩斿洖涓娆℃帓濂藉簭鐨勬暟缁勩傛渶澶ф敮鎸...
绛旓細瑕佺湅鏄粈涔堣埖鏈猴紝void setup() { Serial.begin(1000000);Serial.println("#254 P0 T1500 ");delay(2000);// put your setup code here, to run once:} void loop() { Serial.println("#254 S3000");delay(10000);Serial.println("#254 S0");delay(1000);Serial.println("#254 S-3000"...
绛旓細浠庢澘瀛愬嵃鍒风湅鎼 niq_ro 鍙互鎵惧埌浣滆呯綉绔,浣嗘槸鍥犱负澧欑殑鍏崇郴鎵撲笉寮鑻辨枃椤甸潰 浠4N25 鍜 MOC3021 鐪...鎼 MOC3021 灏辩煡閬撹繖涓槸鍏夎+鍙帶纭呯殑浜ゆ祦璋冨帇鍣,閫氬父鏄崟鐗囨満PWM鎺у埗鍏夎OC3021浠ュ強鍙帶纭呮潵璋冨帇,4N25搴旇鏄仛鐢靛帇妫娴嬬殑.璐熻浇鏈韩鍙互鎵垮彈220鐨勫彲浠ヨ繖涔堝仛(姣斿椋庢墖璋冮),浣嗘槸濡傛灉鏄叧閿澶囦笉寤鸿...