本帖最后由 李逍遥 于 2019-6-3 23:16 编辑
首先,感谢作者的分享,认真读完代码,学到了很多知识,但在其中发现一些错误,可能是我的拙见,如果理解错误请指出。
- 问题:在运行原代码时,电机总是转动一个角度,然后来回晃一晃,再转动一个角度,再晃一晃,起初以为是电机质量问题。在读到#define ROTATE(x) {PORTD|=x; PORTD&=(x|0x0F);} 时产生疑惑,之后仔细分析,发现错误。
- 错误:以四相单四拍为例const char SinBeat[4]={0x80,0x40,0x20,0x10}; 四相单四拍的本意是给PORTD依次赋值0x80 0x40 0x20 0x10从而实现单四拍的目的。而根据ROTATE(x)的定义,PORTD的赋值依次为0x80 0xc0 0x40 0x60 0x20 0x30 0x10 0x90这就变成四相双八拍的了 。显然,对于四相双八拍,就大错特错了,由于原代码初始使用的是四相双八拍,所以出现了晃动的现象。(同时,对于(x|0x0F) 尚有不解,因为全程没有涉及到3号脚,而且这样对3号脚也没有影响)
- 猜想:估计#define ROTATE(x) {PORTD|=x; PORTD&=(x|0x0F);} 这一条代码是专门为四相双八拍设计的,这样在定义时,只用定义四个数值即可。
- 修改:由于作者在给三种模式定义时,精确到每一步的数值,所以直接删去#define ROTATE(x) 的定义,对于逆时针旋转和顺时针旋转的函数中,将ROTATE(MODE);修改为 PORTD=MODE; 即可。
/*原作者:凌晨七點半
修改:李逍遥
时间:2019/6/3
----------------------------------------------------------------------------------------------------------------*/
//四相单四拍
const char SinBeat[4] = {0x80, 0x40, 0x20, 0x10}; //0x80转换为二进制是1000 0000对应7号脚输出高电平,0x40即0100 0000对应6号角输出高电平
//四相双四拍
const char DulBeat1[4] = {0xc0, 0x60, 0x30, 0x90};
//四相双八拍
const char DulBeat2[8] = {0x80, 0xc0, 0x40, 0x60, 0x20, 0x30, 0x10, 0x90};
//节拍模式选择
#define MODE DulBeat2 //对三种模式的选择,直接修改模式名,其他无需改动
void setup() {
pinMode(4, OUTPUT);
pinMode(5, OUTPUT);
pinMode(6, OUTPUT);
pinMode(7, OUTPUT);
Serial.begin(9600);
}
//逆时针旋转
void Anti_Clockwise(int Speed) {
for (int i = 0; i < sizeof(MODE); i++) { //sizeof(MODE)即取MODE的数组长度,从而实现切换模式时,自动修改for的循环次数
PORTD = MODE; //给引脚赋值
delay(Speed); //控制每次小角度转动停留时间,从而控制一组转动的速度
}
}
//顺时针旋转
void Clockwise(int Speed) {
for (int i = sizeof(MODE); i >= 0; i--) {
PORTD = MODE;
delay(Speed);
}
}
//循环工作区
void loop() {
for (int i = 0; i <= 128; i++) { //i为单次转动组数,使效果更明显(控制单次角度)
Anti_Clockwise(1); //小角度停留1ms,使效果更明显(控制转动速度)
}
delay(200); //完成一次for后停留的时间
}
以上内容全为个人理解,如果错误,希望指出,立马修改 2019/6/3 23:16 于重庆理工大学
|