[hermit auto=”1″ loop=”1″ unexpand=”1″ fullheight=”1″]netease_songs#:29463098[/hermit]事情是这样的,因为高中毕业留校几个月教那些老师arduino,所以打算既然这样,那自己搞个小车玩玩挺有意思的,如果那些老师到时候有能力一起来那就最好了.

而且,考虑到高二的坑还废在那里,当初打算用树莓派去做个类似巡线小车的东西,但是后来出了个小意外,导致树莓派SD卡里的东西全炸了,妈蛋.没办法,程序源码都扔在那里面呢,只能弃坑.但是车体还是保留了下来.所以这次就是拿这个车体来玩.不过这次再也不用树莓派了,用arduino.大不了多块板子嘛,大不了顶层上stm32嘛(其实我想搞纯arduino,不想上stm32或者ARM平台).

最近先搞了电机驱动部分,因为两个轮子的电机是步进电机,所以驱动起来比较麻烦,因为要联动.看了arduino现成的库,全部都是阻塞式的.先执行完一个步进电机指令,步进电机步数到位了再执行下一条,这绝对不能用,另外找了下外面的扩展库,发现人家需要使用步进电机驱动板来控制,就是那种输出方向和步数脉冲信号就行了的那种方案.但是我打算只用达林顿管阵列ULN2803来驱动,所以步进电机的时序全部都要arduino板自己生成,没办法,只能自己写程序.

一开始是看到现成的库没有,那就打算写个步进电机的驱动库,后来放弃了,果然C++还是半吊子啊,涉及到类啊什么的,搞都搞混了,后来要求降低,就写个两个轮子能用的联动程序,没有类,简简单单纯C的程序.具体思路也简单,搞个定时器作为系统心跳,每个心跳去判断是否有步进电机有剩余步数,如果有就执行一次步进电机的时序跳变,这样从外界看就是联动的,而且可以单独设置速度,只要设置一个电机在多少个心跳以后变动一次时序就行了,最快的情况当然是一次心跳变一次时序啦~

另外感觉这样定时器中断比较频繁,而且我用的是arduino nano,引脚本来就少,所以把这块arduino nano当成步进电机控制板,用IIC和我的arduino MEGA2560板通讯,这样我的arduino MEGA2560板只要通过IIC发送命令给arduino nano板就可以不用管了,具体执行由arduino nano板负责.目前已经写好了通过IIC去控制两个步进电机.但是后期打算加上IIC读取四路红外传感器,作为巡线用,要搞就要搞完.有空余性能就要把它榨干为止~笑.

 

另外,目前用这套程序跑出来的步进电机时序是这样的.这差不多是28BYJ48步进电机的最快速度了.

 

下面贴上目前的arduino nano板上的代码:

 

[codesyntax lang=”cpp”]

#include <MsTimer2.h>
#include "Wire.h"
/*电机引脚定义*/
#define A1_PIN 5//这部分是两个步进电机的接口,使用ULN2803驱动
#define B1_PIN 4
#define C1_PIN 3
#define D1_PIN 2
#define A2_PIN 6
#define B2_PIN 7
#define C2_PIN 8
#define D2_PIN 9
#define LED_PIN 13

#define IIC_ADDR 0x2A //定义IIC通讯中本从机的地址
/*==============IIC相关定义================*/
#define SET_STEPS 0x20 //设置剩余步数
#define SET_SPEED 0x21 //设置速度
#define STOP 0x22 //紧急停止
#define ENABLE 0x23 //使能
#define DISABILITY 0x24 //失能
/*=========================================*/
void Stepper_drive1(unsigned char Stepper_numb);//0-7//输出指定编号的绕组信号
void Stepper_drive2(unsigned char Stepper_numb);//0-7//输出指定编号的绕组信号
void Stepper_Reset1(void);//清空绕组信号
void Stepper_Reset2(void);//清空绕组信号

unsigned char Delay_Timer1 = 0, Delay_Timer2 = 0; //延迟时间
unsigned char Delay_Timer_cnt1 = 0, Delay_Timer_cnt2 = 0; //延时计数
unsigned char Stepper_Step_Number1 = 0, Stepper_Step_Number2 = 0; //当前电机执行到的绕组编号
long Steps1 = 0, Steps2 = 0; //电机还剩余的步数
bool Effective_Flag1 = false, Effective_Flag2 = false; //有效标志位

void setup()//初始化
{
pinMode(A1_PIN, OUTPUT);
pinMode(B1_PIN, OUTPUT);
pinMode(C1_PIN, OUTPUT);
pinMode(D1_PIN, OUTPUT);
pinMode(A2_PIN, OUTPUT);
pinMode(B2_PIN, OUTPUT);
pinMode(C2_PIN, OUTPUT);
pinMode(D2_PIN, OUTPUT);
pinMode(LED_PIN, OUTPUT);
Stepper_Reset1();
Stepper_Reset2();
Wire.begin(IIC_ADDR);//设置IIC通讯地址
Wire.onReceive(IIC_IRQ);
MsTimer2::set(1, TIMER2_IRQ); // 中断设置函数,每 1ms 进入一次中断
MsTimer2::start(); //开始计时
}

void IIC_IRQ(int number)//IIC中断函数
{
unsigned char data_buffer[6];
unsigned char com, code;
long tmp_data;
digitalWrite(LED_PIN, HIGH);
com = Wire.read();
code = Wire.read();
data_buffer[0] = Wire.read();
data_buffer[1] = Wire.read();
data_buffer[2] = Wire.read();
data_buffer[3] = Wire.read();
if (data_buffer[0] != 0)
{
tmp_data = -1 * (((unsigned long)data_buffer[1] << 16) + ((unsigned long)data_buffer[2] << 8) + (data_buffer[3]));
}
else
{
tmp_data = 1 * (((unsigned long)data_buffer[1] << 16) + ((unsigned long)data_buffer[2] << 8) + (data_buffer[3]));
}
Command_Processing(com, code, tmp_data);
digitalWrite(LED_PIN, LOW);
}

void Command_Processing(unsigned char command, unsigned char Code, long data) //命令处理(命令,电机代号,数据)
{
switch (command)
{
case SET_STEPS://设置剩余步数
{
if (Code == 1)
{
Steps1 = data;
}
else if (Code == 2)
{
Steps2 = data;
}
break;
}
case SET_SPEED://设置速度
{
if (Code == 1)
{
Delay_Timer_cnt1 = 0;
Delay_Timer1 = data;
}
else if (Code == 2)
{
Delay_Timer_cnt1 = 0;
Delay_Timer2 = data;
}
break;
}
case STOP://紧急停止
{
if (Code == 1)
{
Effective_Flag1 = false; //失能标志
}
else if (Code == 2)
{
Effective_Flag2 = false; //失能标志
}
break;
}
case ENABLE://使能
{
if (Code == 1)
{
Effective_Flag1 = true; //使能标志
}
else if (Code == 2)
{
Effective_Flag2 = true; //使能标志
}
break;
}
case DISABILITY://失能
{
if (Code == 1)
{
Effective_Flag1 = false; //失能标志
}
else if (Code == 2)
{
Effective_Flag2 = false; //失能标志
}
break;
}
}
}

void Stepper_drive1(unsigned char Stepper_numb)//0-7,输出指定绕组信号
{
switch (Stepper_numb)
{
case 0:
{
digitalWrite(A1_PIN, HIGH);
digitalWrite(B1_PIN, LOW);
digitalWrite(C1_PIN, LOW);
digitalWrite(D1_PIN, LOW);
break;
}
case 1:
{
digitalWrite(A1_PIN, HIGH);
digitalWrite(B1_PIN, HIGH);
digitalWrite(C1_PIN, LOW);
digitalWrite(D1_PIN, LOW);
break;
}
case 2:
{
digitalWrite(A1_PIN, LOW);
digitalWrite(B1_PIN, HIGH);
digitalWrite(C1_PIN, LOW);
digitalWrite(D1_PIN, LOW);
break;
}
case 3:
{
digitalWrite(A1_PIN, LOW);
digitalWrite(B1_PIN, HIGH);
digitalWrite(C1_PIN, HIGH);
digitalWrite(D1_PIN, LOW);
break;
}
case 4:
{
digitalWrite(A1_PIN, LOW);
digitalWrite(B1_PIN, LOW);
digitalWrite(C1_PIN, HIGH);
digitalWrite(D1_PIN, LOW);
break;
}
case 5:
{
digitalWrite(A1_PIN, LOW);
digitalWrite(B1_PIN, LOW);
digitalWrite(C1_PIN, HIGH);
digitalWrite(D1_PIN, HIGH);
break;
}
case 6:
{
digitalWrite(A1_PIN, LOW);
digitalWrite(B1_PIN, LOW);
digitalWrite(C1_PIN, LOW);
digitalWrite(D1_PIN, HIGH);
break;
}
case 7:
{
digitalWrite(A1_PIN, HIGH);
digitalWrite(B1_PIN, LOW);
digitalWrite(C1_PIN, LOW);
digitalWrite(D1_PIN, HIGH);
break;
}
}
}

void Stepper_Reset1(void)//清空绕组信号
{
digitalWrite(A1_PIN, LOW);
digitalWrite(B1_PIN, LOW);
digitalWrite(C1_PIN, LOW);
digitalWrite(D1_PIN, LOW);
}

void Stepper_Reset2(void)//清空绕组信号
{
digitalWrite(A2_PIN, LOW);
digitalWrite(B2_PIN, LOW);
digitalWrite(C2_PIN, LOW);
digitalWrite(D2_PIN, LOW);
}

void Stepper_drive2(unsigned char Stepper_numb)//0-7,输出指定绕组信号
{
switch (Stepper_numb)
{
case 0:
{
digitalWrite(A2_PIN, HIGH);
digitalWrite(B2_PIN, LOW);
digitalWrite(C2_PIN, LOW);
digitalWrite(D2_PIN, LOW);
break;
}
case 1:
{
digitalWrite(A2_PIN, HIGH);
digitalWrite(B2_PIN, HIGH);
digitalWrite(C2_PIN, LOW);
digitalWrite(D2_PIN, LOW);
break;
}
case 2:
{
digitalWrite(A2_PIN, LOW);
digitalWrite(B2_PIN, HIGH);
digitalWrite(C2_PIN, LOW);
digitalWrite(D2_PIN, LOW);
break;
}
case 3:
{
digitalWrite(A2_PIN, LOW);
digitalWrite(B2_PIN, HIGH);
digitalWrite(C2_PIN, HIGH);
digitalWrite(D2_PIN, LOW);
break;
}
case 4:
{
digitalWrite(A2_PIN, LOW);
digitalWrite(B2_PIN, LOW);
digitalWrite(C2_PIN, HIGH);
digitalWrite(D2_PIN, LOW);
break;
}
case 5:
{
digitalWrite(A2_PIN, LOW);
digitalWrite(B2_PIN, LOW);
digitalWrite(C2_PIN, HIGH);
digitalWrite(D2_PIN, HIGH);
break;
}
case 6:
{
digitalWrite(A2_PIN, LOW);
digitalWrite(B2_PIN, LOW);
digitalWrite(C2_PIN, LOW);
digitalWrite(D2_PIN, HIGH);
break;
}
case 7:
{
digitalWrite(A2_PIN, HIGH);
digitalWrite(B2_PIN, LOW);
digitalWrite(C2_PIN, LOW);
digitalWrite(D2_PIN, HIGH);
break;
}
}
}

void TIMER2_IRQ(void)//定时器中断函数
{
//步进电机1控制
if (Effective_Flag1 == true) //如果电机有效
{
if (Steps1 != 0 and Delay_Timer_cnt1 == Delay_Timer1) //如果还有未走完的步数,而且延时已到
{
Delay_Timer_cnt1 = 0; //延迟计数清零
if (Steps1 > 0) //如果是正转
{
Steps1--;//步数减一
if (Stepper_Step_Number1 < 7)//如果绕组编号小于7
{
Stepper_Step_Number1++;//绕组编号加一
}
else if(Stepper_Step_Number1 == 7)Stepper_Step_Number1 = 0;//如果绕组编号等于7,绕组编号归零
Stepper_drive1(Stepper_Step_Number1);//输出绕组信号
}
else if (Steps1 < 0) //如果是反转
{
Steps1++;//步数加一
if (Stepper_Step_Number1 > 0)//如果绕组编号大于0
{
Stepper_Step_Number1--;//绕组编号减一
}
else if(Stepper_Step_Number1 == 0)Stepper_Step_Number1 = 7;//如果绕组编号等于0,绕组编号设为7
Stepper_drive1(Stepper_Step_Number1);//输出绕组信号
}
}
else if (Delay_Timer_cnt1 <= Delay_Timer1 and Steps1!=0) //如果计数还不够
{
Delay_Timer_cnt1++;//延时计数加一
}
else if (Steps1 == 0)//如果步数等于0
{
Stepper_Reset1();//复位信号
}
}
else //如果电机无效
{
Stepper_Reset1();//复位信号
}

//步进电机2控制
if (Effective_Flag2 == true) //如果电机有效
{
if (Steps2 != 0 and Delay_Timer_cnt2 == Delay_Timer2) //如果还有未走完的步数,而且延时已到
{
Delay_Timer_cnt2 = 0; //清零
if (Steps2 > 0) //如果是正转
{
Steps2--;
if (Stepper_Step_Number2 < 7)
{
Stepper_Step_Number2++;
}
else if (Stepper_Step_Number2 == 7)Stepper_Step_Number2 = 0;
Stepper_drive2(Stepper_Step_Number2);
}
else if (Steps2 < 0) //如果是反转
{
Steps2++;
if (Stepper_Step_Number2 > 0)
{
Stepper_Step_Number2--;
}
else if (Stepper_Step_Number2 == 0)Stepper_Step_Number2 = 7;
Stepper_drive2(Stepper_Step_Number2);
}
}
else if (Delay_Timer_cnt2 <= Delay_Timer2 and Steps2!=0) //如果计数还不够
{
Delay_Timer_cnt2++;
}
else if (Steps2 == 0) //如果剩余步数已经等于0
{
Stepper_Reset2();
}
}
}

void loop()
{

}

[/codesyntax]