极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 18394|回复: 3

菜鸟求助 控制360度舵机的角度

[复制链接]
发表于 2015-9-2 20:48:59 | 显示全部楼层 |阅读模式
本帖最后由 sd8655131 于 2015-9-2 21:03 编辑

准备搞一个能360度连续旋转的自动云台,本来用步进电机驱动,但发现步进电机不能满足需求。
考虑用舵机,但是问题来了。普通舵机能直接控制角度,但不能连续旋转。而360度的舵机只能通过PWM信号控制旋转方向和速度,不能像普通的舵机那样直接控制角度。

在想能不能通过GY85模块(陀螺仪、加速度计、磁阻罗盘)来作为360度舵机的传感器。当接收到角度信号,通过计算旋转方向以最小的角度旋转到达指定位置。当GY85检测到达应有角度时停止输出PWM信号。

附步进电机版的代码

  1. #include&#160;<Wire.h>
  2. #include&#160;<EEPROM.h>
  3. #include&#160;<Servo.h>
  4. #include&#160;"Stepper.h"
  5. #include&#160;"SoftModem.h"
  6. SoftModem&#160;modem;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;//软件猫
  7. //--------------------------------------------------------------------------------------------------
  8. #define&#160;DEBUG&#160;1&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;//是否显示调试信息
  9. #define&#160;PI 3.14159265359     //圆周率
  10. #define&#160;LedPin&#160;13&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;//LED管脚
  11. #define&#160;LedGps&#160;12&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;//LED管脚  gps ready
  12. #define&#160;LedHom&#160;11&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;//LED管脚  home ready
  13. #define&#160;SoundPin&#160;8&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;//蜂鸣器管脚
  14. #define&#160;SERVO_V_Pin&#160;10&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;//俯仰舵机管脚
  15. #define&#160;STEPPER_Pins&#160;5,4,3,2&#160;//步进电机管脚
  16. //--------------------------------------------------------------------------------------------------
  17. #define&#160;USE_GY85&#160;1&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;//是否使用电子罗盘(加电后自动调整方位)
  18. #if&#160;USE_GY85
  19. &#160;&#160;#include&#160;"Gy85Support.h"
  20. #endif
  21. //--------------------------------------------------------------------------------------------------
  22. #define&#160;UseSoftwareSerial&#160;0&#160;&#160;//是否使用软串口读写信息(软串口可避免电脑串口下载程序时与蓝牙冲突)
  23. #if&#160;UseSoftwareSerial
  24. &#160;&#160;#include&#160;"SoftwareSerial.h"
  25. &#160;&#160;SoftwareSerial SoftSerial(2,3); // 使用Arduino的D2、D3端口(RX, TX)作为软串口
  26. &#160;&#160;#define&#160;ExcSerial&#160;SoftSerial
  27. #else
  28. &#160;&#160;#define&#160;ExcSerial&#160;Serial
  29. #endif
  30. //--------------------------------------------------------------------------------------------------
  31. void EEPROM_write2(int address, int p) {byte *_pp_=(byte*)&(p);for(int i=0; i<2; i++) EEPROM.write(address+i, _pp_[i]);} //写p到EEPROM
  32. void EEPROM_read2(int address, int& p) {byte *_pp_=(byte*)&(p);for(int i=0; i<2; i++) _pp_[i]=EEPROM.read(address+i);}   //从EEPROM读取p
  33. //--------------------------------------------------------------------------------------------------
  34. int wxs;      //有效卫星数
  35. struct&#160;Location&#160;{
  36. &#160;&#160;double jd;  //经度
  37. &#160;&#160;double wd;  //纬度
  38. &#160;&#160;double gd;  //高度
  39. };
  40. struct&#160;Location&#160;HomeLoc&#160;=&#160;{0,0,0};&#160;//家的坐标
  41. struct&#160;Location&#160;CurrLoc&#160;=&#160;{0,0,0};&#160;//当前坐标
  42. struct&#160;Location&#160;TempLoc&#160;=&#160;{0,0,0};&#160;//临时坐标
  43. //--------------------------------------------------------------------------------------------------
  44. #define&#160;CMD_LEN&#160;16&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;//命令缓冲区长度
  45. char CmdBuf[CMD_LEN];      //命令缓冲区
  46. String Cmd;                //命令
  47. bool IsShowLocation=false; //是否显示接收到的坐标数据
  48. //bool&#160;IsShowLocation=true;
  49. int AutoSetHome=8;         //自动设置家的卫星数量(0不自动设置家)
  50. int StepsOfCircuit=2046;   //步进电机每转步数
  51. bool HomeReady=false;      //家是否已经设置
  52. int MagAttitude=3;         //电子罗盘姿态( 0:xy 1:yx 2:xz 3:zx 4:yz 5:zy )【正面向上时MagAttitude=0,正面向下时MagAttitude=1 standup is 3】
  53. int QuickOrient=0;         //根据电子罗盘快速定位
  54. int tzjd=0;               
  55. float fjspj,fjgdj;         
  56. //--------------------------------------------------------------------------------------------------
  57. struct&#160;Servo_Dgree&#160;{
  58. &#160;&#160;float H; //水平
  59. &#160;&#160;float V; //俯仰
  60. };
  61. struct&#160;Servo_Dgree&#160;cur_dgree&#160;=&#160;{0.0,&#160;0.0};
  62. struct&#160;Servo_Dgree&#160;lst_dgree&#160;=&#160;{0.0,&#160;0.0};
  63. Stepper stepper;  
  64. Servo SERVO_V;                     
  65. int Servo_V_Rev=1;                   //俯仰伺服器是否反向
  66. int SERVO_V_1=1100;                  //俯仰伺服器极限位置1
  67. int SERVO_V_2=1900;                  //俯仰伺服器极限位置2【可通过命令调整该两项,调整俯仰舵机水平和垂直的脉宽】
  68. //--------------------------------------------------------------------------------------------------
  69. void QuickOrientByMag() { //快速定位正北,精度低
  70. &#160;&#160;float tlpjd;
  71. &#160;&#160;Gy85.GetSensorsData();
  72. &#160;&#160;Gy85.CalcMagData();
  73. &#160;&#160;switch( MagAttitude ) {
  74. &#160;&#160;&#160;&#160;case 0 : tlpjd=atan2( Gy85.magRaw[0],Gy85.magRaw[1]); break;
  75. &#160;&#160;&#160;&#160;case 1 : tlpjd=atan2(-Gy85.magRaw[1],Gy85.magRaw[0]); break;
  76. &#160;&#160;&#160;&#160;case 2 : tlpjd=atan2( Gy85.magRaw[0],Gy85.magRaw[2]); break;
  77. &#160;&#160;&#160;&#160;case 3 : tlpjd=atan2(-Gy85.magRaw[2],Gy85.magRaw[0]); break;
  78. &#160;&#160;&#160;&#160;case 4 : tlpjd=atan2( Gy85.magRaw[1],Gy85.magRaw[2]); break;
  79. &#160;&#160;&#160;&#160;case 5 : tlpjd=atan2(-Gy85.magRaw[2],Gy85.magRaw[1]); break;
  80. &#160;&#160;}
  81. &#160;&#160;tlpjd=tlpjd/PI*180;
  82. &#160;&#160;stepper.StepNumberYT=0;
  83. &#160;&#160;stepper.GotoAngle(tlpjd+tzjd);
  84. &#160;&#160;stepper.StepNumberYT=0;
  85. }
  86. //--------------------------------------------------------------------------------------------------
  87. void OrientByMag() { //定位正北,精度高
  88. &#160;&#160;int i,j,k=0;
  89. &#160;&#160;float tmpv,maxv=-9999.9*9999.9;
  90. &#160;&#160;stepper.MoveSteps(1.2*stepper.Phantom+8);
  91. &#160;&#160;stepper.StepNumberYT=0;
  92. &#160;&#160;for(i=1;i<=stepper.StepsOfCircuit;i++) {
  93. &#160;&#160;&#160;&#160;stepper.MoveSteps(1);
  94. &#160;&#160;&#160;for(j=0,tmpv=0;j<4;j++) { //取值4次,避免扰动
  95. &#160;&#160;&#160;&#160;&#160;&#160;Gy85.GetSensorsData();
  96. &#160;&#160;&#160;&#160;&#160;&#160;switch( MagAttitude ) {
  97. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;case 1 :
  98. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;case 3 : tmpv+=Gy85.magRaw[0]; break;
  99. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;case 0 :
  100. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;case 5 : tmpv+=Gy85.magRaw[1]; break;
  101. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;case 2 :
  102. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;case 4 : tmpv+=Gy85.magRaw[2]; break;
  103. &#160;&#160;&#160;&#160;&#160;&#160;}
  104. &#160;&#160;&#160;&#160;}
  105. &#160;&#160;&#160;&#160;if( tmpv>maxv ) { maxv=tmpv; k=i; }
  106. &#160;&#160;}
  107. &#160;&#160;k&#160;+=&#160;stepper.AngleToSteps(tzjd);
  108. &#160;&#160;stepper.MoveSteps(&#160;stepper.SimplifySteps(k)&#160;);
  109. &#160;&#160;stepper.StepNumberYT=0;
  110. }
  111. //--------------------------------------------------------------------------------------------------
  112. void setup() {
  113. &#160;&#160;ExcSerial.begin(9600); //与手机蓝牙波特率一致
  114. &#160;&#160;modem.begin();
  115. &#160;&#160;stepper.Init(StepsOfCircuit,&#160;STEPPER_Pins);&#160;
  116. &#160;&#160;ReadConfig();
  117. &#160;&#160;stepper.SetSpeed(8);//表示每分钟转数
  118. &#160;&#160;pinMode(LedPin,OUTPUT);
  119. &#160;&#160;pinMode(LedGps,OUTPUT);
  120. &#160;&#160;&#160;pinMode(LedHom,OUTPUT);
  121. &#160;&#160;delay(2500); //延时,在此期间手动调整俯仰伺服器使天线指向水平至45度之间,减少伺服器损伤
  122. &#160;&#160;SERVO_V.attach(SERVO_V_Pin);
  123. &#160;&#160;cur_dgree.H&#160;=&#160;0.0;&#160;&#160;stepper.StepNumberYT=0;
  124. &#160;&#160;lst_dgree.V&#160;=&#160;89.0;&#160;cur_dgree.V&#160;=&#160;90.0;
  125. &#160;&#160;Servo_Move();&#160;//调用Servo_Update可能会是水平位置,所以不用
  126. &#160;&#160;delay(500);   //等待俯仰伺服器运动到位
  127. #if&#160;USE_GY85
  128. &#160;&#160;Gy85.Init();
  129. &#160;&#160;if( QuickOrient ) QuickOrientByMag(); //根据电子罗盘快速定位正北
  130. &#160;&#160;else OrientByMag(); //自检后旋转一周,测出地磁北后,根据安装调整角驱动步进电机使天线指北
  131. #endif
  132. &#160;&#160;fjspj=0.0;&#160;fjgdj=0.0;
  133. &#160;&#160;Servo_Init();&#160;//天线指向水平(正北)
  134. }
  135. //--------------------------------------------------------------------------------------------------
  136. int GPS_UPDATE; //GPS信息是否更新,false:无更新;true:坐标更新
  137. unsigned long CurrTime,GPSUpdateTime=0,SoundTime=0; //当前时间,GPS信息更新时间,上次高音提示收到有效数据时间
  138. int wxsj=-10; //无效数据连续提示次数
  139. //--------------------------------------------------------------------------------------------------
  140. void loop() {
  141. &#160;&#160;GPS_UPDATE=ReadGpsInfo();
  142. &#160;&#160;CurrTime=millis();
  143. &#160;&#160;
  144. &#160;&#160;if( GPS_UPDATE>0 ) {  //收到有效信息
  145. &#160;&#160;&#160;&#160;digitalWrite(LedGps,HIGH);
  146. &#160;&#160;&#160;&#160;GPSUpdateTime=CurrTime;
  147. &#160;&#160;&#160;&#160;wxsj=-10;
  148. &#160;&#160;&#160;/// if( CurrTime-SoundTime>1000 ) { //每秒最多提示1次
  149. &#160;&#160;&#160;///   SoundTime=CurrTime;
  150. &#160;&#160;&#160;///   Spiel(SoundPin,"A",50);       //高音提示
  151. &#160;&#160;&#160;/// }
  152. &#160;&#160;
  153. &#160;&#160;&#160;// if( GPS_UPDATE ) { //收到有效坐标
  154. &#160;&#160;&#160;&#160;&#160;&#160;if( IsShowLocation ) ShowLocation(TempLoc);
  155. &#160;&#160;&#160;&#160;&#160;&#160;if( !HomeReady && AutoSetHome>0 && wxs>=AutoSetHome ) { //自动设置家(卫星数达到自动设置家的值)
  156. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;HomeLoc=CurrLoc=TempLoc;
  157. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;HomeReady=true;
  158. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;digitalWrite(LedHom,HIGH);
  159. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Spiel(SoundPin,"135A",300);     
  160. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;delay(400);
  161. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;digitalWrite(LedHom,LOW);
  162. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;delay(400);
  163. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;digitalWrite(LedHom,HIGH);
  164. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;delay(400);
  165. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;digitalWrite(LedHom,LOW);
  166. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;delay(400);
  167. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;digitalWrite(LedHom,HIGH);
  168. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;delay(400);
  169. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;digitalWrite(LedHom,LOW);
  170. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;delay(400);
  171. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;digitalWrite(LedHom,HIGH);
  172. &#160;&#160;&#160;&#160;}
  173. &#160;&#160;&#160;&#160;&#160;&#160;if( HomeReady ) {
  174. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;if( TempLoc.jd!=CurrLoc.jd || TempLoc.wd!=CurrLoc.wd || TempLoc.gd!=CurrLoc.gd ) {
  175. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;CurrLoc=TempLoc;
  176. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;CalcAirplaneDgree();
  177. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;CalcServoDgree();
  178. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;}
  179. &#160;&#160;&#160;&#160;&#160;// }
  180. &#160;&#160;&#160;&#160;}

  181. &#160;&#160;&#160;digitalWrite(LedGps,LOW);
  182. &#160;&#160;}
  183. &#160;&#160;
  184. &#160;// stepper.MoveToObj(1);
  185. &#160;&#160;
  186. &#160;&#160;if( CurrTime-GPSUpdateTime>6000 ) { //6秒内未收到有效GPS数据
  187. &#160;&#160;&#160;&#160;GPSUpdateTime=CurrTime-2000;&#160;&#160;&#160;&#160;&#160;&#160;//每隔2秒报警一次
  188. &#160;&#160;&#160;&#160;digitalWrite(LedPin,HIGH);
  189. &#160;&#160;&#160;&#160;wxsj++;
  190. &#160;&#160;&#160;&#160;Spiel(SoundPin,"a",50);     //低音
  191. &#160;&#160;///  digitalWrite(LedGps,LOW);/////
  192. &#160;&#160;}
  193. &#160;&#160;digitalWrite(LedPin,LOW);


  194. &#160;if( ExcSerial.available()>0) { //检测并执行命令
  195. &#160;
  196. &#160;&#160;&#160;&#160;digitalWrite(LedPin,HIGH);
  197. &#160;&#160;&#160;&#160;int buflen=ExcSerial.readBytes(CmdBuf,CMD_LEN-1);
  198. &#160;&#160;&#160;&#160;ExcSerial.flush();
  199. &#160;&#160;&#160;&#160;CmdBuf[buflen]=0;
  200. &#160;&#160;&#160;&#160;while( --buflen>=0 ) {
  201. &#160;&#160;&#160;&#160;&#160;&#160;if( CmdBuf[buflen]=='\r' || CmdBuf[buflen]=='\n' )
  202. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;CmdBuf[buflen]=0;
  203. &#160;&#160;&#160;&#160;}&#160;&#160;&#160;&#160;&#160;&#160;
  204. &#160;&#160;&#160;&#160;if( CmdBuf[0]<'A' || CmdBuf[0]>'Z' ) Cmd=CmdBuf; //部分手机助手会再命令前增加字符'A'-'Z'
  205. &#160;&#160;&#160;&#160;else Cmd=&(CmdBuf[1]);
  206. &#160;&#160;&#160;&#160;if( ExecCmd(Cmd) ) ExcSerial.println("Ok!");
  207. &#160;&#160;&#160;&#160;else               ExcSerial.println("Err!!!");
  208. &#160;&#160;&#160;&#160;digitalWrite(LedPin,LOW);
  209. &#160;&#160;}
  210. }
  211. //--------------------------------------------------------------------------------------------------
  212. void AdjustAngle(int angle) { //调整角度,逆时针为正
  213. &#160;&#160;int a=stepper.AngleToSteps(angle);
  214. &#160;&#160;int c=stepper.StepNumberYT;
  215. &#160;&#160;stepper.MoveSteps(&#160;stepper.SimplifySteps(a)&#160;);
  216. &#160;&#160;stepper.StepNumberYT=c;
  217. &#160;&#160;tzjd+=angle;
  218. &#160;&#160;SaveConfig();
  219. }
  220. //--------------------------------------------------------------------------------------------------
  221. bool ExecCmd(String cmd) {
  222. &#160;&#160;ExcSerial.println("Exec Command '"+cmd+"'...");
  223. &#160;&#160;if( Cmd=="h" ) { //手动设置家(4颗星以上即可)
  224. &#160;&#160;&#160;&#160;if( wxs<4 ) {
  225. &#160;&#160;&#160;&#160;&#160;&#160;ExcSerial.println("Satellitic not enough!");
  226. &#160;&#160;&#160;&#160;&#160;&#160;return false;
  227. &#160;&#160;&#160;&#160;}
  228. &#160;&#160;&#160;&#160;HomeLoc=CurrLoc=TempLoc;
  229. &#160;&#160;&#160;&#160;HomeReady=true;
  230. &#160;&#160;&#160;&#160;ShowLocation(HomeLoc);
  231. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;digitalWrite(LedHom,HIGH);
  232. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Spiel(SoundPin,"135A",300);   //成功设置家后演奏音乐  
  233. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;delay(400);
  234. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;digitalWrite(LedHom,LOW);
  235. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;delay(400);
  236. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;digitalWrite(LedHom,HIGH);
  237. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;delay(400);
  238. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;digitalWrite(LedHom,LOW);
  239. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;delay(400);
  240. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;digitalWrite(LedHom,HIGH);
  241. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;delay(400);
  242. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;digitalWrite(LedHom,LOW);
  243. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;delay(400);
  244. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;digitalWrite(LedHom,HIGH);
  245. &#160;
  246. &#160;&#160;}
  247. &#160;&#160;else if( Cmd=="i" ) { //初始化伺服器参数
  248. &#160;&#160;&#160;&#160;SERVO_V_1=1100;
  249. &#160;&#160;&#160;&#160;SERVO_V_2=1900;
  250. &#160;&#160;&#160;&#160;Servo_V_Rev=1;
  251. &#160;&#160;&#160;&#160;MagAttitude=3;
  252. &#160;&#160;&#160;&#160;QuickOrient=0;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;//根据电子罗盘快速定位
  253. &#160;&#160;&#160;&#160;tzjd=0;&#160;
  254. &#160;&#160;&#160;&#160;AutoSetHome=8;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;//自动设置家的卫星数量(0不自动设置家)
  255. &#160;&#160;&#160;&#160;StepsOfCircuit=2100;
  256. &#160;&#160;&#160;&#160;SaveConfig();
  257. &#160;&#160;}
  258. &#160;&#160;else if( Cmd=="c" ) { //清空家数据
  259. &#160;&#160;&#160;&#160;HomeReady=false;
  260. &#160;&#160;&#160;&#160;HomeLoc.jd=0;&#160;&#160;&#160;&#160;HomeLoc.wd=0;&#160;&#160;&#160;&#160;HomeLoc.gd=0;
  261. &#160;&#160;}
  262. &#160;&#160;else if( Cmd=="s" ) { //显示接收到的坐标数据
  263. &#160;&#160;&#160;&#160;ShowLocation(TempLoc);
  264. &#160;&#160;}
  265. &#160;&#160;else if( Cmd=="sh" ) { //显示家的坐标数据
  266. &#160;&#160;&#160;&#160;ShowLocation(HomeLoc);
  267. &#160;&#160;}
  268. &#160;&#160;else if( Cmd=="js" ) { //开始监视,显示接收到的坐标数据
  269. &#160;&#160;&#160;&#160;IsShowLocation=true;
  270. &#160;&#160;}
  271. &#160;&#160;else if( Cmd=="tz" ) { //停止监视
  272. &#160;&#160;&#160;&#160;IsShowLocation=false;
  273. &#160;&#160;}
  274. &#160;&#160;else if( Cmd=="spfx" ) { //水平伺服器反向
  275. &#160;&#160;&#160;&#160;stepper.RevDir&#160;=&#160;stepper.RevDir==0&#160;?&#160;1&#160;:&#160;0&#160;;
  276. &#160;&#160;&#160;&#160;SaveConfig();
  277. &#160;&#160;}
  278. &#160;&#160;else if( Cmd=="fyfx" ) { //俯仰伺服器反向
  279. &#160;&#160;&#160;&#160;Servo_V_Rev&#160;=&#160;Servo_V_Rev==0&#160;?&#160;1&#160;:&#160;0&#160;;
  280. &#160;&#160;&#160;&#160;Servo_Move();
  281. &#160;&#160;&#160;&#160;SaveConfig();
  282. &#160;&#160;}
  283. &#160;&#160;else if( Cmd=="qo" ) { //是否根据电子罗盘快速定位
  284. &#160;&#160;&#160;&#160;QuickOrient&#160;=&#160;QuickOrient==0&#160;?&#160;1&#160;:&#160;0&#160;;
  285. &#160;&#160;&#160;&#160;SaveConfig();
  286. &#160;&#160;}
  287. &#160;&#160;else if( Cmd=="dw" ) { //重新定位
  288. &#160;&#160;&#160;&#160;if( QuickOrient ) QuickOrientByMag(); //根据电子罗盘快速定位正北
  289. &#160;&#160;&#160;&#160;else OrientByMag(); //自检后旋转一周,测出地磁北后,根据安装调整角驱动步进电机使天线指北
  290. &#160;&#160;}
  291. &#160;&#160;else if( Cmd=="ma" ) { //电子罗盘姿态变更
  292. &#160;&#160;&#160;&#160;if( ++MagAttitude>=6 ) MagAttitude=0;
  293. &#160;&#160;&#160;&#160;SaveConfig();
  294. &#160;&#160;}
  295. &#160;&#160;else if( Cmd=="bs+"  ) { StepsOfCircuit+=1;  SaveConfig(); } //步进电机每转步数+1
  296. &#160;&#160;else if( Cmd=="bs++" ) { StepsOfCircuit+=9;  SaveConfig(); } //步进电机每转步数+9
  297. &#160;&#160;else if( Cmd=="bs-"  ) { StepsOfCircuit-=1;  SaveConfig(); } //步进电机每转步数-1
  298. &#160;&#160;else if( Cmd=="bs--" ) { StepsOfCircuit-=9;  SaveConfig(); } //步进电机每转步数-9
  299. &#160;&#160;else if( Cmd=="xw+"  ) { stepper.Phantom+=1;  stepper.TestPhantom(); SaveConfig(); } //步进电机虚位+1
  300. &#160;&#160;else if( Cmd=="xw++" ) { stepper.Phantom+=9;  stepper.TestPhantom(); SaveConfig(); } //步进电机虚位+9
  301. &#160;&#160;else if( Cmd=="xw-"  ) { stepper.Phantom-=1;  stepper.TestPhantom(); SaveConfig(); } //步进电机虚位-1
  302. &#160;&#160;else if( Cmd=="xw--" ) { stepper.Phantom-=9;  stepper.TestPhantom(); SaveConfig(); } //步进电机虚位-9
  303. &#160;&#160;else if( Cmd=="jd+"  ) AdjustAngle(1);   //安装调整角度+1
  304. &#160;&#160;else if( Cmd=="jd++" ) AdjustAngle(5);   //安装调整角度+5
  305. &#160;&#160;else if( Cmd=="jd+++") AdjustAngle(50);  //安装调整角度+50
  306. &#160;&#160;else if( Cmd=="jd-"  ) AdjustAngle(-1);  //安装调整角度-1
  307. &#160;&#160;else if( Cmd=="jd--" ) AdjustAngle(-5);  //安装调整角度-5
  308. &#160;&#160;else if( Cmd=="jd---") AdjustAngle(-50); //安装调整角度-50
  309. &#160;&#160;else if( Cmd=="fy1+" ) { SERVO_V_1+=5;  SaveConfig(); cur_dgree.V=0;  Servo_Update(); } //俯仰伺服器极限位置1脉宽+5
  310. &#160;&#160;else if( Cmd=="fy1++") { SERVO_V_1+=50; SaveConfig(); cur_dgree.V=0;  Servo_Update(); } //俯仰伺服器极限位置1脉宽+50
  311. &#160;&#160;else if( Cmd=="fy1-" ) { SERVO_V_1-=5;  SaveConfig(); cur_dgree.V=0;  Servo_Update(); } //俯仰伺服器极限位置1脉宽-5
  312. &#160;&#160;else if( Cmd=="fy1--") { SERVO_V_1-=50; SaveConfig(); cur_dgree.V=0;  Servo_Update(); } //俯仰伺服器极限位置1脉宽-50
  313. &#160;&#160;else if( Cmd=="fy2+" ) { SERVO_V_2+=5;  SaveConfig(); cur_dgree.V=90; Servo_Update(); } //俯仰伺服器极限位置2脉宽+5
  314. &#160;&#160;else if( Cmd=="fy2++") { SERVO_V_2+=50; SaveConfig(); cur_dgree.V=90; Servo_Update(); } //俯仰伺服器极限位置2脉宽+50
  315. &#160;&#160;else if( Cmd=="fy2-" ) { SERVO_V_2-=5;  SaveConfig(); cur_dgree.V=90; Servo_Update(); } //俯仰伺服器极限位置2脉宽-5
  316. &#160;&#160;else if( Cmd=="fy2--") { SERVO_V_2-=50; SaveConfig(); cur_dgree.V=90; Servo_Update(); } //俯仰伺服器极限位置2脉宽-50
  317. &#160;&#160;else if( Cmd=="spcs" ) { //测试水平伺服器
  318. &#160;&#160;&#160;&#160;stepper.GotoAngle(-90);
  319. &#160;&#160;&#160;&#160;stepper.GotoAngle(0);
  320. &#160;&#160;&#160;&#160;stepper.GotoAngle(90);
  321. &#160;&#160;&#160;&#160;stepper.GotoAngle(0);
  322. &#160;&#160;}
  323. &#160;&#160;else if( Cmd=="fycs" ) { //测试俯仰伺服器
  324. &#160;&#160;&#160;&#160;cur_dgree.V&#160;=&#160;90;&#160;&#160;&#160;&#160;Servo_Move();
  325. &#160;&#160;&#160;&#160;cur_dgree.V&#160;=&#160;0;&#160;&#160;&#160;&#160;&#160;Servo_Move();
  326. &#160;&#160;}
  327. &#160;&#160;else if( Cmd=="cs" ) TestAAT(2000); //测试跟踪
  328. &#160;&#160;else if( Cmd=="zdszj" ) { //自动设置家
  329. &#160;&#160;&#160;&#160;AutoSetHome--;
  330. &#160;&#160;&#160;&#160;if( AutoSetHome<0 ) AutoSetHome=8;
  331. &#160;&#160;&#160;&#160;if( AutoSetHome<4 ) AutoSetHome=0;
  332. &#160;&#160;&#160;&#160;SaveConfig();
  333. &#160;&#160;}

  334. &#160;&#160;else if( Cmd=="?" ) { //显示帮助信息
  335. &#160;&#160;&#160;&#160;ExcSerial.println("h/c;d/s/sh;js/tz;zdszj;cs;q");
  336. &#160;&#160;&#160;&#160;ExcSerial.println("[sp/fy][fx/cs/1/2];jd;bs/xw;ma");
  337. &#160;&#160;}
  338. #if&#160;DEBUG
  339. &#160;&#160;else if( Cmd=="d" ) {  //显示调试信息
  340. &#160;&#160;&#160;&#160;ExcSerial.println("Servo_H_Rev=" + String(stepper.RevDir));
  341. &#160;&#160;&#160;&#160;ExcSerial.println("Servo_V_Rev=" + String(Servo_V_Rev));
  342. &#160;&#160;&#160;&#160;ExcSerial.println("SERVO_V_1="   + String(SERVO_V_1));
  343. &#160;&#160;&#160;&#160;ExcSerial.println("SERVO_V_2="   + String(SERVO_V_2));
  344. &#160;&#160;&#160;&#160;ExcSerial.println("Auto Home="   + String(AutoSetHome));
  345. &#160;&#160;&#160;&#160;ExcSerial.print("H=");  ExcSerial.println(lst_dgree.H);
  346. &#160;&#160;&#160;&#160;ExcSerial.print("V=");  ExcSerial.println(lst_dgree.V);
  347. &#160;&#160;&#160;&#160;ExcSerial.println("Adj Angle="   + String(tzjd));
  348. &#160;&#160;&#160;&#160;ExcSerial.println("MagAttitude=" + String(MagAttitude));
  349. &#160;&#160;&#160;&#160;ExcSerial.println("Steps/c="     + String(StepsOfCircuit));
  350. &#160;&#160;&#160;&#160;ExcSerial.println("Phantom="     + String(stepper.Phantom));
  351. &#160;&#160;&#160;&#160;ExcSerial.println("QuickOrient=" + String(QuickOrient));
  352. &#160;&#160;}
  353. #endif
  354. &#160;&#160;else {
  355. &#160;&#160;&#160;&#160;ExcSerial.println("No such command!");
  356. &#160;&#160;&#160;&#160;return false;
  357. &#160;&#160;}
  358. #if&#160;DEBUG
  359. &#160;&#160;checkFreeMem();
  360. #endif
  361. &#160;&#160;return true;
  362. }
  363. //--------------------------------------------------------------------------------------------------
  364. void SaveConfig() {
  365. &#160;&#160;EEPROM_write2(10,stepper.RevDir);
  366. &#160;&#160;EEPROM_write2(12,Servo_V_Rev);
  367. &#160;&#160;EEPROM_write2(14,SERVO_V_1);
  368. &#160;&#160;EEPROM_write2(16,SERVO_V_2);
  369. &#160;&#160;EEPROM_write2(18,stepper.Phantom);
  370. &#160;&#160;EEPROM_write2(20,QuickOrient);
  371. &#160;&#160;EEPROM_write2(22,AutoSetHome);
  372. &#160;&#160;EEPROM_write2(24,MagAttitude);
  373. &#160;&#160;while( tzjd<0   ) tzjd+=360;
  374. &#160;&#160;while( tzjd>360 ) tzjd-=360;
  375. &#160;&#160;EEPROM_write2(26,tzjd);
  376. &#160;&#160;EEPROM_write2(28,StepsOfCircuit);
  377. }
  378. //--------------------------------------------------------------------------------------------------
  379. void ReadConfig() {
  380. &#160;&#160;int bd=0x55a3,tl;
  381. &#160;&#160;EEPROM_read2(1,tl);
  382. &#160;&#160;if( bd!=tl ) { //First Run
  383. &#160;&#160;&#160;&#160;EEPROM_write2(1,bd);
  384. &#160;&#160;&#160;&#160;SaveConfig();
  385. &#160;&#160;}
  386. &#160;&#160;else {
  387. &#160;&#160;&#160;&#160;EEPROM_read2(10,stepper.RevDir);
  388. &#160;&#160;&#160;&#160;EEPROM_read2(12,Servo_V_Rev);
  389. &#160;&#160;&#160;&#160;EEPROM_read2(14,SERVO_V_1);
  390. &#160;&#160;&#160;&#160;EEPROM_read2(16,SERVO_V_2);
  391. &#160;&#160;&#160;&#160;EEPROM_read2(18,stepper.Phantom);
  392. &#160;&#160;&#160;&#160;EEPROM_read2(20,QuickOrient);
  393. &#160;&#160;&#160;&#160;EEPROM_read2(22,AutoSetHome);
  394. &#160;&#160;&#160;&#160;EEPROM_read2(24,MagAttitude);
  395. &#160;&#160;&#160;&#160;EEPROM_read2(26,tzjd);
  396. &#160;&#160;&#160;&#160;EEPROM_read2(28,StepsOfCircuit);
  397. &#160;&#160;}
  398. }
  399. //--------------------------------------------------------------------------------------------------
  400. #if&#160;DEBUG
  401. void checkFreeMem() {
  402. &#160;&#160;for(int i = 2040;i>0;i--) {
  403. &#160;&#160;&#160;&#160;char* c = (char*)malloc(i);
  404. &#160;&#160;&#160;&#160;if(c) {
  405. &#160;&#160;&#160;&#160;&#160;&#160;free(c);
  406. &#160;&#160;&#160;&#160;&#160;&#160;ExcSerial.print("Mem left:");
  407. &#160;&#160;&#160;&#160;&#160;&#160;ExcSerial.println(i);
  408. &#160;&#160;&#160;&#160;&#160;&#160;break;
  409. &#160;&#160;&#160;&#160;}
  410. &#160;&#160;}
  411. }
  412. #endif
  413. //--------------------------------------------------------------------------------------------------



复制代码
回复

使用道具 举报

发表于 2015-9-3 18:44:18 | 显示全部楼层
为什么步进无法满足要求?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-9-6 08:26:08 | 显示全部楼层
bh7jec 发表于 2015-9-3 18:44
为什么步进无法满足要求?

速度和转矩达不到要求
回复 支持 反对

使用道具 举报

发表于 2015-9-7 23:05:31 | 显示全部楼层
AAT做的是远距离,并不需要很快的速度。 转矩不够,使用带减速的步进,完全可以达到,而且好用。舵机虽然速度快,但是容易烧。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|联系我们|极客工坊

GMT+8, 2026-6-16 21:21 , Processed in 0.045526 second(s), 19 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表