-
伺服电机PID控制抖动
PID控制伺服电机总是在两个电机绝对角度位置抖动,看上去像是电机转动到这个位置顿住了一会儿,然后突然提速通过,就跟跨阶梯一样没有平滑过渡的过程。 我用姿态角做误差,写了个PI位置环输入目标姿态角、当前姿态角,输出目标速度。目标速度结合读取的当前速度做调整,再通过CAN发送速度给电机纠正角度。有写死区,在正负0.2°内清除积分,输出目标速度0停止电机转动。
4630浏览量 14回复量 关注量 -
中颖79F6442目标板TWI通讯测试
[i=s] 本帖最后由 rwf5956 于 2024-6-22 08:50 编辑 [/i] 问题:主机发出START指令后,TWICON相应的中断标志位未产生,START发送不成功,主机一直在跑START发送检测,从机一直在等待 指令说明: 1、相应的寄存器配置 CLKCON |=0x08; Delay(); CLKCON |=0x04;//时钟 TWITOUT = 0x02; //打开 SCL,SDA 上拉电阻 TWIBR=0x02; //配置发送波特率,禁止总线超时判断 f=fsys/(16+2*CR*TWIBR) TWISTA=0x0; //64 分频 TWICON = 0x40; //ENTWI,禁止高电平超时 TWTFREE = 0xff; //最大超时配置 TWIAMR =0 ;//关闭TWI地址屏蔽 IEN0|=0X80;//使能所有中断允许开关 IEN1|=0X01;//使能TWI中断 INSCON |=0X40; TWICR|=0X01;//使用默认管脚作为SCL、SDA//LCM功能配置SCL、SDA管脚 INSCON &= 0XBF; 2、代码说明 基于官方DEMOCODE 主机 /******************************************************************************* TWI 主站发送START指令 *******************************************************************************/ bit M_TwiSendStart() { TWICON |=0x20; //TWICON=OX60 总线空闲时发送起始条件 //TWICON &= 0xdf; while(1) //等待 TWI 中断(?是否初始化需要开启TWI中断允许IEN0 IEN1?) { if(TWICON&0x08) //TWICON bit3中断标志位=1,需软件复位 { if(((TWISTA&0xF8)==0x08)||((TWISTA&0xF8)==0x10)) { return OK; //成功发送开始条件或重复开始条件 } else { return FAIL; } } if(0x02 == (0x02 & TWICON))//TWICON bit1时钟线高电平超时,需软件复位 { TWICON &= 0xdf; return FAIL; //等待中断超时 } } } /******************************************************************************* (2)TWI 主站发送slave地址+W/R指令 *******************************************************************************/ UCHAR M_TwiSendCmd(UCHAR addr,UCHAR cmd) { UCHAR SlaveAddr; UCHAR i=0; if(cmd) { SlaveAddr=((addr&0x7f)<<1)|0x01; //读 } else { SlaveAddr=((addr&0x7f)<<1); //写 } TWICON &= 0xf7; //清除中断标志 TWIDAT=SlaveAddr;//执行发送指令 while(1) //等待 TWI 中断 { i++; if(TWICON&0x08)//主站自身对指令发送是否成功的反馈判断,根据是否产生TWI中断来判断的,该标志位需要再下一次判断前进行清零,复位 { if(cmd) //发送的是读指令 { if((TWISTA&0xF8)==0x40)//从站对指令发送是否成功的反馈判断, { return ACK; //成功发送 SLA+R } else if((TWISTA&0xF8)==0x48) { return NAK; } } else //发送的是写指令 { if((TWISTA&0xF8)==0x18) { return ACK; //成功发送 SLA+W } else if((TWISTA&0xF8)==0x20) { return NAK; } } if((TWISTA&0xF8)==0x38)//反馈的是其他情况 { return LOSEARBITRATION;//失去仲裁 } else if((TWISTA&0xF8)==0x68) { return RCVCMDWRITE; } else if((TWISTA&0xF8)==0x78) { return RCVCMDREAD; } else if((TWISTA&0xF8)==0xB0) { return RCVADDRESS0; } else { return ERR; } } if(i>=250)//尝试次数不超过250次 { return ERR; //等待中断超时 } } } /******************************************************************************* (3)TWI 主站发送DATA数据 *******************************************************************************/ UCHAR M_TwiSendData(UCHAR byte) { UCHAR i=0; TWICON &= 0xf7;//清除了中断标志位 TWIDAT=byte; TWICON=0x40; while(1) { i++; if(TWICON&0x08)//自身中断判断 { if((TWISTA&0xF8)==0x28) { return ACK; } else if((TWISTA&0xF8)==0x30) { return NAK; } else if((TWISTA&0xF8)==0x38) { return LOSEARBITRATION; } else { return ERR; } } if(i>=250) { return ERR; //等待中断超时 } } } /***************************************************************************************************** (4)Twi 主机发送结束指令 *****************************************************************************************************/ UCHAR M_TwiSendEnd() { UCHAR i=0; TWICON=0x50; while(1) { i++; if((TWICON&0x10)==0) { if(TWISTA==0xF8) { return OK; } else { return FAIL; } } if(i>=250) { return ERR; //等待终止位清除超时 } } } /******************************************************************************* (5)TWI 主站发送指令及数据给从站 *******************************************************************************/ bit M_SendDataToSlave() { UCHAR ret,i=0; TwiInit(); H_Timeout_check; //使能总线超时,SCL 总线高电平超时判断 ret=M_TwiSendStart();//发送起始START if(ret==OK) //send-STA OK { if(M_TwiSendCmd(0x2D,0x0)==ACK)//0X2D左移一位,对应从站地址0X5A { while(i < 0xff) { ret=M_TwiSendData(0x40+i); i++; if(ret==NAK) { return 1; //数据发送结束 } else if((ret==LOSEARBITRATION)||(ret==ERR)) { return 0; } } } else { return 0; } } else //err process { return 0; while(1); } } 从站 /******************************************************************************* (1)从站等待接收指令 *******************************************************************************/ UCHAR S_TwiWaitRcvCmd() { TWIADR=0x5A; //从机地址设定 TWICON=0x44; while(1) { // if(TWICON&0x08) // { if((TWISTA&0xF8)==0x60) //收到SLA+W { return CMD_WRITE; } else if((TWISTA&0xF8)==0xA8) //收到SLA+R { return CMD_READ; } else { return ERR; } // } } } /******************************************************************************* (2)从站等待接收数据 *******************************************************************************/ UCHAR S_TwiWaitRcvData() { UCHAR i=0; TWIDAT=0; TWICON=0x44; while(1) { i++; if(TWICON&0x08) { if(((TWISTA&0xF8)==0x80)||((TWISTA&0xF8)==0x90)) //收到1个byte数据 { _nop_(); return ACK; } else { _nop_(); return ERR; } } } } /******************************************************************************* (3)从站接收最后1个byte数据 *******************************************************************************/ UCHAR S_TwiWaitRcvLastData() { UCHAR i=0; TWIDAT=0; TWICON=0x40; while(1) { i++; if(TWICON&0x08) { if(((TWISTA&0xF8)==0x88)||((TWISTA&0xF8)==0x98)) //收到最后1个byte数据 { return NAK; } else { return ERR; } } } } /******************************************************************************* (4)从站 发送数据 *******************************************************************************/ UCHAR S_TwiSendData(UCHAR byte) { UCHAR i=0; TWIDAT=byte; TWICON=0x44; while(1) { i++; if(TWICON&0x08) { if((TWISTA&0xF8)==0xB8) { return ACK; } else if((TWISTA&0xF8)==0xC0) //主机接收数据结束,从机切换至非寻址状态 { return NAK; } else { return ERR; } } if(i>=250) { return ERR; //等待中断超时 } } } /******************************************************************************* (5)从站发送最后1byte数据 *******************************************************************************/ UCHAR S_TwiSendLastData(UCHAR byte) { UCHAR i=0; TWIDAT=byte; TWICON=0x40; while(1) { i++; if(TWICON&0x08) { if((TWISTA&0xF8)==0xC8) //从机发送数据结束,切换至非寻址状态 { return ACK; } else if((TWISTA&0xF8)==0xC0) //主机接收数据结束,从机切换至非寻址状态 { return NAK; } else { return ERR; } } if(i>=250) { return ERR; //等待中断超时 } } } /******************************************************************************* (6)从站收发数据 *******************************************************************************/ bit SlaveTransfer() { UCHAR* rcv_data,i=0,ret; TwiInit(); ret=S_TwiWaitRcvCmd(); if(ret==CMD_WRITE) { while(1) { if(S_TwiWaitRcvData()==ACK)//成功接收到1个byte { i++; rcv_data[i-1]=TWIDAT; if(i>=9) { if(S_TwiWaitRcvLastData()==NAK) { rcv_data[i]=TWIDAT; return 1; //接收数据结束 } else { return 0; //接收最后1个byte数据过程中出错 } } } else { return 0; //接收数据失败 } } } else if(ret==CMD_READ) { while(1) { ret=S_TwiSendData(0x40+i); if(ret==NAK) //主机接收数据结束 { return 1; } else if(ret==ACK) //主机还可继续接收数据 { i++; if(i>=9) { if(S_TwiSendLastData(0x49)==ERR) { return 0; //发送最后1个byte数据过程中出错 } else { return 1; //成功发送最后1个byte数据 } } } else { return 0; //发送数据出错 } } } else { return 0; } } main函数 主站: if(M_SendDataToSlave()) { UCHAR M_TwiSendEnd(); } 从站 SlaveTransfer(); [/i]
8164浏览量 3回复量 关注量 -
怎么对目标进行预判? sos
我们不知道获取的数据的真实度,如何评价对后续知识推理的影响。且部分目标的数据只有在实际运用过程中才能获取(非合作目标),我们怎么对目标进行预判?
1026浏览量 0回复量 关注量