¡°ðÐðÄ¡±Ïò¹ã¶«Öж«²¿Ñغ£¿¿½ü

2008年8月21日发布的台风预警显示,第12号台风ðÐðÄ已进入中国东北部地区,预计将以每小时15-20公里的速度继续向西北方向移动,逐渐逼近东北中部,并可能于明日白天到夜间在辽宁一带登陆。受其影响,今日中午到明日中午,吉林东南部、辽宁东部、黑龙江南部等地将出现7-9级大风。

?

tf080821nmc2.jpg

ÖÐÑëÆøÏǫ́2008Äê8ÔÂ21ÈÕ10ʱ·¢²¼Ì¨·ç³ÈÉ«½ô¼±¾¯±¨£º

½ñÄêµÚ12ºĄ̊·ç¡°ðÐðÄ¡±£¨Nuri£©µÄÖÐÐÄÒÑÓÚ×òÌìÒ¹¼ä½øÈëÄϺ£¶«±±²¿º£Ã棬½ñÌìÉÏÎç10ʱ̨·çÖÐÐÄλÓÚÎÒ¹ú¹ã¶«Ê¡Ö麣Êж«ÄÏÆ«¶«·½Ïò´óÔ¼500¹«ÀïµÄº£ÃæÉÏ£¬¾ÍÊDZ±Î³20.1¶È£¬¶«¾­117.8¶È£¬ÖÐÐĸ½½ü×î´ó·çÁ¦ÓÐ13¼¶£¨38Ã×/Ã룩¡£

Ô¤¼Æ£¬Ì¨·çÖÐÐĽ«ÒÔÿСʱ15-20¹«ÀïµÄËٶȼÌÐøÏòÎ÷Æ«±±·½ÏòÒÆ¶¯£¬Öð½¥Ïò¹ã¶«Öж«²¿Ñغ£¿¿½ü£¬²¢½«ÓÚÃ÷ÌìÉÏÎçµ½Ò¹¼äÔڹ㶫»ÝÀ´µ½Ñô½­Ò»´øÑغ£µÇ½¡£

ÊÜÆäÓ°Ï죬½ñÌìÖÐÎçµ½Ã÷ÌìÖÐÎ磬°ÍÊ¿º£Ï¿¡¢°ÍÁÖÌÁº£Ï¿¡¢Ì¨ÍåÊ¡Äϲ¿Ñغ£¡¢Ì¨Íå¶«Äϲ¿º£Ã桢̨Í庣ϿÄϲ¿º£Ãæ¡¢ÄϺ£Öб±²¿º£ÃæÒÔ¼°¹ã¶«Ñغ£¡¢¸£½¨¶«Äϲ¿Ñغ£½«Óе½7-9¼¶´ó·ç£¬¡°ðÐðÄ¡±ÖÐÐľ­¹ýµÄ¸½½üº£Ãæ»òµØÇø·çÁ¦¿É´ï10-13¼¶¡£¹ã¶«Öж«²¿Ñغ£¡¢¸£½¨¶«Äϲ¿Ñغ£½«Óд󵽱©Ó꣬ÆäÖй㶫¶«²¿Ñغ£µÄ²¿·ÖµØÇøÓдó±©Óê¡£

·ÀÓùÖ¸ÄÏ£º

1.Õþ¸®¼°Ïà¹Ø²¿ÃŰ´ÕÕÖ°Ôð×öºÃ·Ą̀·çÇÀÏÕ×¼±¸¹¤×÷£»

2.Ïà¹ØË®ÓòË®ÉÏ×÷ÒµºÍ¹ýÍù´¬²°Ó¦»Ø¸Û±Ü·ç£¬¼Ó¹Ì¸Û¿ÚÉèÊ©£¬·ÀÖ¹´¬²°×ßê¡¢¸édzºÍÅöײ£»

3.¼Ó¹ÌÃÅ´°¡¢Î§°å¡¢Åï¼Ü¡¢¹ã¸æÅƵÈÒ×±»·ç´µ¶¯µÄ´î½¨ÎÇжÏΣÏÕµÄÊÒÍâµçÔ´£»

4.Ïà¹ØµØÇøÓ¦µ±×¢Òâ·À·¶Ç¿½µË®¿ÉÄÜÒý·¢µÄɽºé¡¢µØÖÊÔÖº¦¡£

#include <reg52.h> //------------------------- Òý&frac12;Ŷ¨Òå --------------------------// sbit BEEP = P2^0; //·äÃùÆ÷¿ØÖÆÒý&frac12;Å£¬?µçÆ&frac12;ÓÐЧ sbit LED1 = P2^3; //LED1£¬¿ØÖÆÒý&frac12;Å£¬µÍµçÆ&frac12;ÓÐЧ sbit LED2 = P2^2; //LED2£¬¿ØÖÆÒý&frac12;Å£¬µÍµçÆ&frac12;ÓÐЧ sbit LED3 = P2^1; //LED3£¬¿ØÖÆÒý&frac12;Å£¬µÍµçÆ&frac12;ÓÐЧ //ÊýÂë&sup1;ÜÒý&frac12;Ŷ¨Òå #define duanPore P0 //ÊýÂë&sup1;ܶοØÖƶ˿ڣ¬¸ßµçÆ&frac12;ÓÐЧ sbit DIG1 = P2^4; //ÊýÂë&sup1;ܵÚ1λλѡ¿ØÖƶ˿ڣ¬µÍµçÆ&frac12;ÓÐЧ sbit DIG2 = P2^5; //ÊýÂë&sup1;ܵÚ2λλѡ¿ØÖƶ˿ڣ¬µÍµçÆ&frac12;ÓÐЧ sbit DIG3 = P2^6; //ÊýÂë&sup1;ܵÚ3λλѡ¿ØÖƶ˿ڣ¬µÍµçÆ&frac12;ÓÐЧ sbit DIG4 = P2^7; //ÊýÂë&sup1;ܵÚ4λλѡ¿ØÖƶ˿ڣ¬µÍµçÆ&frac12;ÓÐЧ //°´&frac14;üÒý&frac12;Ŷ¨Òå sbit KEY1 = P1^0; //1ºÅÑ¡ÊÖ sbit KEY2 = P1^1; //2ºÅÑ¡ÊÖ sbit KEY3 = P1^2; //3ºÅÑ¡ÊÖ sbit KEY4 = P1^3; //4ºÅÑ¡ÊÖ sbit KEY5 = P1^4; //5ºÅÑ¡ÊÖ sbit KEY6 = P1^5; //6ºÅÑ¡ÊÖ sbit KEY7 = P3^2; //Ö÷³ÖÈË&frac14;ü sbit KEY8 = P3^3; //ÉèÖÃ&frac14;ü //---------------------- È«¾Ö±äÁ¿¶¨Òå --------------------// //ÊýÂë&sup1;ܶÎÂë±í£¬ÊÊÓÃÓÚ&sup1;&sup2;ÒõÊýÂë&sup1;Ü unsigned char code tab_duan[19] = { 0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f, //0~9 0x77,0x7c,0x39,0x5e,0x79,0x71, //A~F 0x40,0x00,0x48 //'-'£¬&sup1;رÕÏÔʾ£¬'=' }; unsigned char dat_buf[4] = {17, 17, 0, 5}; //ÏÔʾÊý¾Ý»º´æÇø£¬Ä¬ÈÏÉϵçÏÔʾ" 05" int time = 5, time1 = 5, time2 = 20; //µ&sup1;&frac14;ÆÊ±Ê±&frac14;䣬time1£ºÇÀ´ðµ&sup1;&frac14;ÆÊ±Ê±&frac14;䣬time2£º»Ø´ðµ&sup1;&frac14;ÆÊ±Ê±&frac14;ä unsigned char i = 0; unsigned int count = 0; //&frac14;ÆÊý»º´æ±äÁ¿ bit flag_lock = 1; //&frac14;üÅÌËø¶¨±êÖ¾£¬1£º&sup2;»Ëø¶¨£¬0£ºËø¶¨ //------------------------------- º¯ÊýÉùÃ÷ ------------------------------------// void DelayMs(unsigned int ms); //ÑÓʱº¯Êý£¬µ¥Î»£ºms void dig_scan(unsigned char *dat); unsigned char KeyScan(void); //¶ÀÁ¢°´&frac14;üɨÃè void InitTimer0(void); //¶¨Ê±Æ÷0³õÊ&frac14;»¯ void alarm(void); //±¨¾¯º¯Êý void AnswerTask(void); //ÇÀ´ðÈÎÎñ void SetTime(void); //ÉèÖõ&sup1;&frac14;ÆÊ±Ê±&frac14;ä /* Ö÷º¯Êý */ void main(void) { BEEP = 0; //ÉϵçĬÈÏ&sup1;رշäÃùÆ÷ LED1 = 1; InitTimer0(); //¶¨Ê±Æ÷0³õÊ&frac14;»¯ time = time1; //ÉϵçĬÈÏÇÀ´ðµ&sup1;&frac14;ÆÊ± while(1) { if(KeyScan() == 7) //Èç&sup1;ûÖ÷³ÖÈË&frac14;ü°´Ï£¬Ôò&frac12;øÐÐÇÀ´ð { alarm(); //·äÃùÆ÷ÏìÒ»Éù AnswerTask(); //&frac12;øÐÐÇÀ´ðÈÎÎñ } if(KeyScan() == 8) //Èç&sup1;ûÉèÖÃ&frac14;ü°´Ï£¬&frac12;øÈëÉèÖõ&sup1;&frac14;ÆÊ±Ê±&frac14;ä { alarm(); //·äÃùÆ÷ÏìÒ»Éù SetTime(); //&frac12;øÈëÉè&frac14;Ƶ&sup1;&frac14;ÆÊ±Ê±&frac14;ä } dat_buf[0] = 17; dat_buf[1] = 17; dat_buf[2] = time / 10; //È¡³öµ&sup1;&frac14;ÆÊ±µÄʮλÊý dat_buf[3] = time % 10; //È¡³öµ&sup1;&frac14;ÆÊ±µÄ¸öλÊý dig_scan(dat_buf); //&sup2;âÊÔÊýÂë&sup1;ÜÏÔʾ } } /* ÑÓʱº¯Êý£¬µ¥Î»£ºms */ void DelayMs(unsigned int ms) { unsigned char a,b,c; while(--ms) { for(c=1;c>0;c--) for(b=142;b>0;b--) for(a=2;a>0;a--); } } /* ÊýÂë&sup1;ÜÏÔʾɨÃè */ void dig_scan(unsigned char *dat) { /* ¶¯Ì¬É¨Ãè´¦Àí */ switch(i) { case 0: { duanPore = tab_duan[dat[0]]; //ÏÔʾµÚ1λÊýÂë&sup1;ÜÄÚÈÝ DIG1 = 0; break; } case 1: { duanPore = tab_duan[dat[1]]; //ÏÔʾµÚ2λÊýÂë&sup1;ÜÄÚÈÝ DIG2 = 0; //ѡͨµÚ2λÊýÂë&sup1;Ü break; } case 2: { duanPore = tab_duan[dat[2]]; //ÏÔʾµÚ3λÊýÂë&sup1;ÜÄÚÈÝ DIG3 = 0; //ѡͨµÚ3λÊýÂë&sup1;Ü break; } case 3: { duanPore = tab_duan[dat[3]]; //ÏÔʾµÚ4λÊýÂë&sup1;ÜÄÚÈÝ DIG4 = 0; //ѡͨµÚ4λÊýÂë&sup1;Ü break; } default: break; } DelayMs(5); //ɨÃèÑÓʱ10ms£¬¸ù¾Ýʵ&frac14;ÊÇé¿öÊʵ±Ð޸ĸÄÑÓʱʱ&frac14;ä DIG1 = 1; //ÏûÒþ DIG2 = 1; DIG3 = 1; DIG4 = 1; ++i; //ɨÃè±äÁ¿Ñ­»· if(i > 3) i = 0; } /* ¶ÀÁ¢°´&frac14;üɨÃè */ unsigned char KeyScan(void) { if(KEY1 == 0) //Èç&sup1;û°´&frac14;ü1°´Ï { DelayMs(10); //ÑÓʱ10msÈ¥³ý°´&frac14;ü¶¶¶¯ if(KEY1 == 0) //ÔÙÈ·ÈÏÒ»´Î°´&frac14;ü°´Ï£¬±íʾµ&frac12;Õâ°´&frac14;üÒѾ­Îȶ¨ÁË return 1; //Êä³ö°´&frac14;üÖµ1 } if(KEY2 == 0) //Èç&sup1;û°´&frac14;ü2°´Ï { DelayMs(10); //ÑÓʱ10msÈ¥³ý°´&frac14;ü¶¶¶¯ if(KEY2 == 0) //ÔÙÈ·ÈÏÒ»´Î°´&frac14;ü°´Ï£¬±íʾµ&frac12;Õâ°´&frac14;üÒѾ­Îȶ¨ÁË return 2; //Êä³ö°´&frac14;üÖµ2 } if(KEY3 == 0) //Èç&sup1;û°´&frac14;ü3°´Ï { DelayMs(10); //ÑÓʱ10msÈ¥³ý°´&frac14;ü¶¶¶¯ if(KEY3 == 0) //ÔÙÈ·ÈÏÒ»´Î°´&frac14;ü°´Ï£¬±íʾµ&frac12;Õâ°´&frac14;üÒѾ­Îȶ¨ÁË return 3; //Êä³ö°´&frac14;üÖµ3 } if(KEY4 == 0) //Èç&sup1;û°´&frac14;ü4°´Ï { DelayMs(10); //ÑÓʱ10msÈ¥³ý°´&frac14;ü¶¶¶¯ if(KEY4 == 0) //ÔÙÈ·ÈÏÒ»´Î°´&frac14;ü°´Ï£¬±íʾµ&frac12;Õâ°´&frac14;üÒѾ­Îȶ¨ÁË return 4; //Êä³ö°´&frac14;üÖµ4 } if(KEY5 == 0) //Èç&sup1;û°´&frac14;ü5°´Ï { DelayMs(10); //ÑÓʱ10msÈ¥³ý°´&frac14;ü¶¶¶¯ if(KEY5 == 0) //ÔÙÈ·ÈÏÒ»´Î°´&frac14;ü°´Ï£¬±íʾµ&frac12;Õâ°´&frac14;üÒѾ­Îȶ¨ÁË return 5; //Êä³ö°´&frac14;üÖµ5 } if(KEY6 == 0) //Èç&sup1;û°´&frac14;ü6°´Ï { DelayMs(10); //ÑÓʱ10msÈ¥³ý°´&frac14;ü¶¶¶¯ if(KEY6 == 0) //ÔÙÈ·ÈÏÒ»´Î°´&frac14;ü°´Ï£¬±íʾµ&frac12;Õâ°´&frac14;üÒѾ­Îȶ¨ÁË return 6; //Êä³ö°´&frac14;üÖµ6 } if(KEY7 == 0) //Èç&sup1;û°´&frac14;ü7°´Ï { DelayMs(10); //ÑÓʱ10msÈ¥³ý°´&frac14;ü¶¶¶¯ if(KEY7 == 0) //ÔÙÈ·ÈÏÒ»´Î°´&frac14;ü°´Ï£¬±íʾµ&frac12;Õâ°´&frac14;üÒѾ­Îȶ¨ÁË return 7; //Êä³ö°´&frac14;üÖµ7 } if(KEY8 == 0) //Èç&sup1;û°´&frac14;ü8°´Ï { DelayMs(10); //ÑÓʱ10msÈ¥³ý°´&frac14;ü¶¶¶¯ if(KEY8 == 0) //ÔÙÈ·ÈÏÒ»´Î°´&frac14;ü°´Ï£¬±íʾµ&frac12;Õâ°´&frac14;üÒѾ­Îȶ¨ÁË return 8; //Êä³ö°´&frac14;üÖµ8 } return 0; //ÎÞ°´&frac14;ü°´ÏÂÊä³ö0 } /* ¶¨Ê±Æ÷0³õÊ&frac14;»¯ */ void InitTimer0(void) { TMOD = 0x01; //ÅäÖö¨Ê±Æ÷0Ϊ&sup1;¤×÷Ä£Ê&frac12;1£¬16λ¶¨Ê±Æ÷ TH0 = (65536 - 10000) / 256; //¶¨Ê±10ms TL0 = (65536 - 10000) % 256; EA = 1; //´ò¿ª×ÜÖÐ¶Ï ET0 = 1; //´ò¿ª¶¨Ê±Æ÷0ÖÐ¶Ï TR0 = 0; //ÉϵçĬÈÏ&sup1;رն¨Ê±Æ÷0 } /* ¶¨Ê±Æ÷0ÖжϷþÎñº¯Êý£¬10ms&frac12;øÒ»´ÎÖÐ¶Ï */ void Timer0Interrupt(void) interrupt 1 { TH0 = (65536 - 10000) / 256; //¶¨Ê±10ms£¬ÖØÐÂ×°ÔØ&frac14;ÆÊýÖµ TL0 = (65536 - 10000) % 256; ++count; if(count > 100) //1sʱ&frac14;ä&frac14;ÆË㣺10ms * 100 = 1s { count = 0; //&frac14;ÆÊýÖµÇåÁã --time; //µ&sup1;&frac14;ÆÊ±Ê±&frac14;ä&frac14;õÒ»´Î if(time <= 0) //Èç&sup1;ûµ&sup1;&frac14;ÆÊ±&frac12;áÊø£¬Ôò&sup1;رն¨Ê±Æ÷0£¬Í£Ö&sup1;µ&sup1;&frac14;ÆÊ±£¬&sup2;¢Éù&sup1;ⱨ¾¯ºÍËø¶¨&frac14;üÅÌ { TR0 = 0; //&sup1;رն¨Ê±Æ÷0 BEEP = 1; //Éù&sup1;ⱨ¾¯ LED1 = 0; flag_lock = 0; //Ëø¶¨&frac14;üÅÌ } } } /* ±¨¾¯º¯Êý */ void alarm(void) { BEEP = 1; //·äÃùÆ÷ÏìһϠDelayMs(300); //ÑÓʱ300ms BEEP = 0; } /* ʵÏÖÇÀ´ðÈÎÎñ */ void AnswerTask(void) { unsigned char key_val; //°´&frac14;üÖµ»º´æ TR0 = 1; //Æô¶¯¶¨Ê±Æ÷0£¬¿ªÊ&frac14;µ&sup1;&frac14;ÆÊ± while(1) { if(flag_lock == 1) { key_val = KeyScan(); //»ñÈ¡°´&frac14;üÖµ switch(key_val) { case 1: { dat_buf[0] = key_val; //µÚ1λÊýÂë&sup1;ÜÏÔʾ1ºÅ dat_buf[1] = 16; //ÏÔʾ'-' time = time2; //»Ø´ðµ&sup1;&frac14;ÆÊ±£¬Ñ¡Êֻشðʱ&frac14;ä alarm(); //·äÃùÆ÷ÏìһϠflag_lock = 0; //Ëø¶¨&frac14;üÅÌ break; } case 2: { dat_buf[0] = key_val; //µÚ2λÊýÂë&sup1;ÜÏÔʾ2ºÅ dat_buf[1] = 16; //ÏÔʾ'-' time = time2; //»Ø´ðµ&sup1;&frac14;ÆÊ±£¬Ñ¡Êֻشðʱ&frac14;ä alarm(); //·äÃùÆ÷ÏìһϠflag_lock = 0; break; } case 3: { dat_buf[0] = key_val; //µÚ3λÊýÂë&sup1;ÜÏÔʾ3ºÅ dat_buf[1] = 16; //ÏÔʾ'-' time = time2; alarm(); //·äÃùÆ÷ÏìһϠflag_lock = 0; break; } case 4: { dat_buf[0] = key_val; //µÚ4λÊýÂë&sup1;ÜÏÔʾ4ºÅ dat_buf[1] = 16; //ÏÔʾ'-' time = time2; alarm(); //·äÃùÆ÷ÏìһϠflag_lock = 0; break; } case 5: { dat_buf[0] = key_val; //µÚ5λÊýÂë&sup1;ÜÏÔʾ5ºÅ dat_buf[1] = 16; //ÏÔʾ'-' time = time2; alarm(); //·äÃùÆ÷ÏìһϠflag_lock = 0; break; } case 6: { dat_buf[0] = key_val; //µÚ6λÊýÂë&sup1;ÜÏÔʾ6ºÅ dat_buf[1] = 16; //ÏÔʾ'-' time = time2; alarm(); //·äÃùÆ÷ÏìһϠflag_lock = 0; break; } default: break; } } dat_buf[2] = time / 10; //È¡³öµ&sup1;&frac14;ÆÊ±µÄʮλÊý dat_buf[3] = time % 10; //È¡³öµ&sup1;&frac14;ÆÊ±µÄ¸öλÊý dig_scan(dat_buf); //ÊýÂë&sup1;ÜÏÔʾÄÚÈÝ } } /* ÉèÖõ&sup1;&frac14;ÆÊ±Ê±&frac14;ä */ void SetTime(void) { unsigned char mode = 0; //0£ºµ÷&frac12;ÚÇÀ´ðµ&sup1;&frac14;ÆÊ±£¬1£ºµ÷&frac12;ڻشðµ&sup1;&frac14;ÆÊ±£¬2£ºÍ˳ö while(1) { if(KeyScan() == 8) //Èç&sup1;ûÔٴΰ´ÏÂÉèÖÃ&frac14;ü£¬ÔòÍ˳öÉèÖÃ&sup1;¦ÄÜ { alarm(); //·äÃùÆ÷ÏìÒ»Éù ++mode; if(mode >= 2) break; //Ìø³öµ±Ç°ËÀÑ­»· } if(KeyScan() == 7) //Èç&sup1;û°´ÏÂ&frac14;Ó&frac14;ü£¬&frac12;øÐе÷ʱ { alarm(); //·äÃùÆ÷ÏìÒ»Éù if(mode == 0) //µ÷&frac12;ÚÇÀ´ðµ&sup1;&frac14;ÆÊ± { ++time1; //µ&sup1;&frac14;ÆÊ±Ê±&frac14;ä&frac14;ÓÒ»´Î if(time1 > 30) //µ÷ʱ·¶Î§£º5s~30s time1 = 5; } if(mode == 1) //µ÷&frac12;ڻشðµ&sup1;&frac14;ÆÊ± { ++time2; //µ&sup1;&frac14;ÆÊ±Ê±&frac14;ä&frac14;ÓÒ»´Î if(time2 > 30) //µ÷ʱ·¶Î§£º5s~30s time2 = 5; } } /* µ÷ʱÏÔʾ´¦Àí */ if(mode == 0) { dat_buf[0] = 16; //ÏÔʾ'-' dat_buf[1] = time1 / 10; //È¡³öµ&sup1;&frac14;ÆÊ±µÄʮλÊý dat_buf[2] = time1 % 10; //È¡³öµ&sup1;&frac14;ÆÊ±µÄ¸öλÊý dat_buf[3] = 16; //ÏÔʾ'-' } if(mode == 1) { dat_buf[0] = 18; //ÏÔʾ'=' dat_buf[1] = time2 / 10; //È¡³öµ&sup1;&frac14;ÆÊ±µÄʮλÊý dat_buf[2] = time2 % 10; //È¡³öµ&sup1;&frac14;ÆÊ±µÄ¸öλÊý dat_buf[3] = 18; //ÏÔʾ'=' } dig_scan(dat_buf); //ÊýÂë&sup1;ÜÏÔʾÄÚÈÝ } time = time1; //»Øµ&frac12;Ö÷&frac12;çÃæÏÔʾÇÀ´ðµ&sup1;&frac14;ÆÊ± }写出一个这样的代码,主持人是1.0,时间调节是1.1,选手1.2-1.7,蜂鸣器是3.3,LED是3.4,数码管1234是2.0-2.3
09-19
static float Bias,Pwm,Integral_bias,Last_Bias; int Position_PID (int Encoder,int Target) { Bias=Encoder-Target; //&frac14;ÆËãÆ«&sup2;î Integral_bias+=Bias; //Çó³öÆ«&sup2;îµÄ»ý·Ö // Pwm=70*Bias*Ratio+0.00*Integral_bias*Ratio+200*(Bias-Last_Bias)*Ratio; //λÖÃÊ&frac12;PID¿ØÖÆÆ÷ Pwm=100*Bias*Ratio+0.00*Integral_bias*Ratio+250*(Bias-Last_Bias)*Ratio; //λÖÃÊ&frac12;PID¿ØÖÆÆ÷ Last_Bias=Bias; //±£´æÉÏÒ»´ÎÆ«&sup2;î return Pwm; //ÔöÁ¿Êä³ö } int Position_PID_1 (int Encoder,float Target) { static float Bias,Pwm,Integral_bias,Last_Bias,encoder; encoder=(float)Encoder; Bias=encoder-Target; //&frac14;ÆËãÆ«&sup2;î Integral_bias+=Bias; //Çó³öÆ«&sup2;îµÄ»ý·Ö // Pwm=90*Bias*Ratio+0.00*Integral_bias*Ratio+250*(Bias-Last_Bias)*Ratio; //λÖÃÊ&frac12;PID¿ØÖÆÆ÷ Pwm=90*Bias*Ratio+0.00*Integral_bias*Ratio+250*(Bias-Last_Bias)*Ratio; //λÖÃÊ&frac12;PID¿ØÖÆÆ÷ Last_Bias=Bias; //±£´æÉÏÒ»´ÎÆ«&sup2;î return Pwm; //ÔöÁ¿Êä³ö } int Position_PID_3 (int Encoder,int Target) { static float Bias,Pwm,Integral_bias,Last_Bias; Bias=Encoder-Target; //&frac14;ÆËãÆ«&sup2;î Integral_bias+=Bias; //Çó³öÆ«&sup2;îµÄ»ý·Ö // Pwm=70*Bias*Ratio+0.00*Integral_bias*Ratio+200*(Bias-Last_Bias)*Ratio; //λÖÃÊ&frac12;PID¿ØÖÆÆ÷ // Pwm=280*Bias*Ratio+0.00*Integral_bias*Ratio+300*(Bias-Last_Bias)*Ratio; //λÖÃÊ&frac12;PID¿ØÖÆÆ÷ Pwm=90*Bias*Ratio+0.00*Integral_bias*Ratio+250*(Bias-Last_Bias)*Ratio; //λÖÃÊ&frac12;PID¿ØÖÆÆ÷ Last_Bias=Bias; //±£´æÉÏÒ»´ÎÆ«&sup2;î return Pwm; //ÔöÁ¿Êä³ö } u16 Count_Next=0; static int Angle_Max,Position_Max; static u8 Flag_Back; u16 number=0; //int Count_FZ,Target_Position=10580; /************************************************************************** º¯Êý&sup1;¦ÄÜ£º×Ô¶¯Æð°Ú³ÌÐò Èë¿Ú&sup2;ÎÊý£ºint ·µ»Ø Öµ£º **************************************************************************/ void Run(u8 Way) { static float Count_FZ,Target_Position=10450; static float Count_Big_Angle=0.046542; if(Way==2) //ÊÖ¶¯Æð°Ú³ÌÐò { if(Angle_Balance<(ZHONGZHI+200)&&Angle_Balance>(ZHONGZHI-200)) //µ&frac12;µ×&frac12;Ó&frac12;üÆ&frac12;ºâλÖà &frac14;´¿É¿ªÆôÆ&frac12;ºâϵͳ { State=1; //µ&sup1;Á¢×´Ì¬ÖÃ1 Way_Turn=0;//Æð°Ú±ê־λÇåÁã } } } /************************************************************************** º¯Êý&sup1;¦ÄÜ£ºÇã&frac12;ÇPD¿ØÖÆ Èë¿Ú&sup2;ÎÊý£º&frac12;Ç¶È ·µ»Ø Öµ£ºÇã&frac12;Ç¿ØÖÆPWM **************************************************************************/ int balance_0(float Angle) { float Bias; //Çã&frac12;ÇÆ«&sup2;î static float Last_Bias,D_Bias,I_Bias; //PIDÏà&sup1;رäÁ¿ int balance; Bias=Angle-ZHONGZHI; I_Bias+=Bias; D_Bias=Bias-Last_Bias; balance=-Balance_KP*Bias- D_Bias*Balance_KD+ I_Bias*Balance_Ratio; Last_Bias=Bias; return balance; //PWM·µ»ØÖµ //Çó³öÆ&frac12;ºâµÄ&frac12;ǶÈÖÐÖµ ºÍ»úеÏà&sup1;Ø //Îó&sup2;î×öÀÛ&frac14;Ó£¬×ö»ý·Ö¶ÔÏó //Çó³öÆ«&sup2;îµÄ΢·Ö &frac12;øÐÐ΢·Ö¿ØÖÆ //Ê&sup1;ÓÃλÖÃPIDËã·¨&sup1;«Ê&frac12;¸øPWM¸³Öµ£¬Æ&frac12;ºâ¿ØÖÆÐèÒª¿ìËÙ·´Ó¦£¬Ê&sup1;ÓÃPD¿ØÖÆËã·¨£¬&frac14;´»ý·Ö&sup2;ÎÊýΪÁã //ÉÏ´ÎÎó&sup2;îµÈÓÚµ±Ç°Îó&sup2;î //º¯Êý·µ»ØÖµÎªÇã&frac12;Ç¿ØÖÆPWMÖµ } /************************************************************************** º¯Êý&sup1;¦ÄÜ£ºÎ»ÖÃPD¿ØÖÆ Èë¿Ú&sup2;ÎÊý£º±àÂëÆ÷ ·µ»Ø Öµ£ºÎ»ÖÿØÖÆPWM **************************************************************************/ int Position_0(int Encoder) { static float Position_PWM, Last_Position, Position_Bias, Position_Differential; static float Position_Least; Position_Least=Encoder-Position_Zero; //=-???? Position_Bias *=0.8; Position_Bias += Position_Least*0.2; Position_Differential=Position_Bias-Last_Position; Last_Position=Position_Bias; Position_PWM =Position_Bias*Position_KP+Position_Differential*Position_KD; return Position_PWM; //¶¨ÒåλÖÿØÖƱäÁ¿£¬·Ö±ðÐèÒª¶¨Òå¿ØÖÆPWMÖµ¡¢ÉÏÒ»´ÎµÄλÖÃÖµ¡¢µ±Ç°Î»ÖÃÖµ¡¢Î¢·Ö¶ÔÏóÖµ //¶¨ÒåλÖÃÎó&sup2;î±äÁ¿ //===»ñȡλÖÃÆ«&sup2;îÁ¿£¬&frac14;´Îó&sup2;îÁ¿ //Ò»&frac12;×µÍͨÂË&sup2;¨Æ÷Ëã·¨ //===Ò»&frac12;×µÍͨÂË&sup2;¨Æ÷ //===»ñȡƫ&sup2;î±ä»¯ÂÊ£¬µ±Ç°Îó&sup2;îÓëÉÏ´ÎÎó&sup2;îÇó&sup2;&frac14;´Î¢·Ö¶ÔÏóÖµ //ÉÏ´ÎÎó&sup2;îµÈÓÚµ±Ç°Îó&sup2;±£´æÉÏÒ»´ÎµÄÆ«&sup2;î //===Ê&sup1;ÓÃλÖÃPIDËã·¨&sup1;«Ê&frac12;¸øPWM¸³Öµ£¬ÐèҪλÖÿìËÙ·´Ó¦£¬&sup2;ÉÓÃPDËã·¨£¬&frac14;´»ý·Ö&sup2;ÎÊýΪÁã //º¯Êý·µ»ØÖµÎªµ&sup1;Á¢°ÚλÖÿØÖÆPWMÖµ } /************************************************************************** º¯Êý&sup1;¦ÄÜ£ºÏÞÖÆPWM¸³Öµ Èë¿Ú&sup2;ÎÊý£ºÎÞ ·µ»Ø Öµ£ºÎÞ **************************************************************************/ void Xianfu_Pwm(void) { int Amplitude=6900; //===PWMÂú·ùÊÇ7200 ÏÞÖÆÔÚ6900 if(Moto<-Amplitude) Moto=-Amplitude; if(Moto>Amplitude) Moto=Amplitude; } /************************************************************************** º¯Êý&sup1;¦ÄÜ£ºÒì³£&sup1;رյç»ú Èë¿Ú&sup2;ÎÊý£ºµçÑ&sup1; ·µ»Ø Öµ£º1£ºÒì³£ 0£ºÕý³£ **************************************************************************/ u8 Turn_Off(void) { u8 temp; if(Flag_Stop==1||(State==1 && (Angle_Balance<(ZHONGZHI-460)||Angle_Balance>(ZHONGZHI+460)))) //&sup1;رյç»ú { Flag_Stop=0; Way_Turn=0; Flag_qb2=0; Angle_Max=0; Position_Max=0; State=0; temp=1; TIM_SetCounter(TIM2,10000);//³õÊ&frac14;»¯&frac14;ÆÊýÆ÷³õÖµ } else { temp=0; } return temp; } void Encoder_App(void) { if(State == 0) //Æð°Úʱ&sup2;ÉÑùÈ¡3´ÎÇóÆ&frac12;¾ù£¬5´ÎÖÜÆÚÌ«³¤ { Angle_Balance=Get_ADC(5); } if(State==1) { Angle_Balance=Get_ADC(20);//´Ë¿ØÖÆÖÜÆÚ&sup2;»ÐèÒªÄÇô¶Ì£¬Æð°Ú³É&sup1;¦ºó&sup2;ÉÑùÈ¡5´ÎÇóÆ&frac12;¾ùÖµ£¬ } D_Angle_Balance= Angle_Balance-Last_Angle_Balance ; //===»ñȡ΢·ÖÖµ if (State == 0 && Way_Turn ==1) { if(Angle_Balance<(ZHONGZHI+200)&&Angle_Balance>(ZHONGZHI-200)) //µ&frac12;µ×&frac12;Ó&frac12;üÆ&frac12;ºâλÖà &frac14;´¿É¿ªÆôÆ&frac12;ºâϵͳ { State=1; //µ&sup1;Á¢×´Ì¬ÖÃ1 Way_Turn=0;//×Ô¶¯Æð°Ú±ê־λÇåÁã Flag_qb=0; //×Ô¶¯Æð°Ú&sup2;&frac12;ÖèÇåÁã Angle_Max=0; Flag_Back=0; } } if(State==0) { Run(Way_Turn);//Æð°Ú ÓÉÈë¿Ú&sup2;ÎÊý¿ØÖÆ 1£º×Ô¶¯Æð°Ú 2£ºÊÖ¶¯Æð°Ú if(Turn_Off()==1) //°´ÏÂÍ£Ö&sup1;&frac14;üʱͣÖ&sup1;µç»ú { Moto_qb=0; } } if(State==1) //Æð°Ú³É&sup1;¦Ö®ºó£¬&frac12;øÐе&sup1;Á¢¿ØÖÆ { Balance_Pwm =balance_0(Angle_Balance); //¿ªÆôÆ&frac12;ºâ¿ØÖÆ if(Flag_qb2==0) //λÖÿØÖÆÑÓʱÆô¶¯ { if(Angle_Balance<(ZHONGZHI+200)&&Angle_Balance>(ZHONGZHI-200))Count_Position++; // if(Count_Position>20)Flag_qb2=1, Count_Position=0,TIM_SetCounter(TIM2,10000); //ÔÚÆ&frac12;ºâλÖõ&sup1;Á¢³¬&sup1;ý300ms ¿ªÆôλÖÿØÖÆ } if(Flag_qb2==1) //¿ªÆôλÖÿØÖÆ { Encoder=TIM_GetCounter(TIM2); //===¸üбàÂëÆ÷λÖÃÐÅÏ¢ if(++Count_P2>=4) Position_Pwm=Position_0(Encoder),Count_P2=0; //===λÖÃPD¿ØÖÆ 25ms&frac12;øÐÐÒ»´ÎλÖÿØÖÆ } Moto=Balance_Pwm-Position_Pwm; //===&frac14;ÆËãµç»ú×îÖÕPWM Xianfu_Pwm(); //===PWMÏÞ·ù if(Turn_Off()==1) //°´ÏÂÍ£Ö&sup1;&frac14;ü»òÕßÇã&frac12;Ç&sup1;ý´ó±£»¤£¬µç»úÍ£Ö&sup1; { Moto=0; } if(Moto>7200) Moto=7200; if(Moto<-7200)Moto=-7200; Set_Pwm(Moto); //===¸³Öµ¸øPWM&frac14;Ä´æÆ÷ } Last_Angle_Balance=Angle_Balance; //===±£´æÉÏÒ»´ÎµÄÇã&frac12;ÇÖµ } 解释上述代码
05-22
#include "control.h" #include "Lidar.h" float Move_X = 0, Move_Z = 0; // Ä¿±êËٶȺÍÄ¿±êתÏòËÙ¶È float PWM_Left, PWM_Right; // ×óÓÒµç»úPWMÖµ float RC_Velocity, RC_Turn_Velocity; // Ò£¿Ø¿ØÖƵÄËÙ¶È u8 Mode = Normal_Mode; // Ä£Ê&frac12;Ñ¡Ôñ£¬Ä¬ÈÏÊÇÆÕͨµÄ¿ØÖÆÄ£Ê&frac12; Motor_parameter MotorA, MotorB; // ×óÓÒµç»úÏà&sup1;رäÁ¿ int Servo_PWM = SERVO_INIT; // °¢¿ËÂü¶æ»úÏà&sup1;رäÁ¿ u8 Lidar_Detect = Lidar_Detect_ON; // µç´ÅÑ&sup2;ÏßÄ£Ê&frac12;À×´ï&frac14;ì&sup2;âÕϰ­ÎĬÈÏ¿ªÆô float CCD_Move_X = 0.3; // CCDÑ&sup2;ÏßËÙ¶È float ELE_Move_X = 0.3; // µç´ÅÑ&sup2;ÏßËÙ¶È u8 Ros_count = 0, Lidar_flag_count = 0; u8 cnt = 0; Encoder OriginalEncoder; // Encoder raw data //±àÂëÆ÷Ô­Ê&frac14;Êý¾Ý short Accel_Y, Accel_Z, Accel_X, Accel_Angle_x, Accel_Angle_y, Gyro_X, Gyro_Z, Gyro_Y; int forward_cnt = 800; int left_cnt = 120; int right_cnt = 125; int stop_cnt = 200; int stop_flag = 0; int mode_cnt = 0; int state_cnt = 0; int stop_protect = 0; /************************************************************************** Function: Control Function Input : none Output : none º¯Êý&sup1;¦ÄÜ£º5ms¶¨Ê±ÖжϿØÖƺ¯Êý Èë¿Ú&sup2;ÎÊý: ÎÞ ·µ»Ø Öµ£ºÎÞ **************************************************************************/ void forward(){ MotorA.Motor_Pwm = 1999; MotorB.Motor_Pwm = 2040; } void left(){ MotorA.Motor_Pwm = 0; MotorB.Motor_Pwm = 2050; } void right(){ MotorA.Motor_Pwm = 1999; MotorB.Motor_Pwm = 0; } void stop(){ MotorA.Motor_Pwm = 0; MotorB.Motor_Pwm = 0; } void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if (htim == &htim5) { Get_KeyVal(); if(mode_cnt == 0) stop(); //Ä£Ê&frac12;Ò» if(mode_cnt == 1){ if(forward_cnt > 0){ forward(); forward_cnt--; // if(left_cnt > 0){ // left(); // left_cnt--; // if(right_cnt > 0){ // right(); // right_cnt--; } else{ stop(); } } //Ä£Ê&frac12;¶þ else if(mode_cnt == 2){ if(forward_cnt > 0){ forward(); forward_cnt--; } else if(stop_cnt > 0 && forward_cnt == 0){ stop(); stop_cnt--; } else if(stop_cnt == 0 && stop_flag == 0){ forward_cnt = 800; stop_flag = 1; } else{ stop(); } } //Ä£Ê&frac12;Èý else if(mode_cnt == 3){ if(forward_cnt > 0 && state_cnt == 0){//µÚ1״̬£ºÖ±ÐÐ forward(); forward_cnt--; } else if(right_cnt > 0 && state_cnt == 1){//µÚ2״̬£ºÓÒת right(); right_cnt--; } else if(forward_cnt > 0 && state_cnt == 2){//µÚ3״̬£ºÖ±ÐÐ forward(); forward_cnt--; } else if(left_cnt > 0 && state_cnt == 3){//µÚ4״̬£º×óת left(); left_cnt--; } else if(forward_cnt > 0 && state_cnt == 4){//µÚ5״̬£ºÖ±ÐÐ forward(); forward_cnt--; } else if(left_cnt > 0 && state_cnt == 5){//µÚ6״̬£º×óת left(); left_cnt--; } else if(forward_cnt > 0 && state_cnt == 6){//µÚ7״̬£ºÖ±ÐÐ forward(); forward_cnt--; } else{ if(stop_protect == 0 && stop_cnt == 0){ stop_cnt = 100; stop_protect = 1; } else if(stop_cnt > 0){ stop(); stop_cnt--; } else if(stop_protect == 1 && stop_cnt == 0){ stop_protect = 0; if(state_cnt == 0){//״̬1Çл»×´Ì¬2 state_cnt++; right_cnt = 125; } else if(state_cnt == 1){//״̬2Çл»×´Ì¬3 state_cnt++; forward_cnt = 585; } else if(state_cnt == 2){//״̬3Çл»×´Ì¬4 state_cnt++; left_cnt = 120; } else if(state_cnt == 3){//״̬4Çл»×´Ì¬5 state_cnt++; forward_cnt = 585; } else if(state_cnt == 4){//״̬5Çл»×´Ì¬6 state_cnt++; left_cnt = 120; } else if(state_cnt == 5){//״̬6Çл»×´Ì¬7 state_cnt++; forward_cnt = 585; } } } } Set_Pwm(-MotorA.Motor_Pwm, MotorB.Motor_Pwm); // Çý¶¯µç»ú } } /************************************************************************** Function: Bluetooth_Control Input : none Output : none º¯Êý&sup1;¦ÄÜ£ºÊÖ»úÀ¶ÑÀ¿ØÖÆ Èë¿Ú&sup2;ÎÊý: ÎÞ ·µ»Ø Öµ£ºÎÞ **************************************************************************/ void Bluetooth_Control(void) { if (Flag_Direction == 0) Move_X = 0, Move_Z = 0; // Í£Ö&sup1; else if (Flag_Direction == 1) Move_X = RC_Velocity, Move_Z = 0; // ǰ&frac12;ø else if (Flag_Direction == 2) Move_X = RC_Velocity, Move_Z = Pi / 2; // ÓÒǰ else if (Flag_Direction == 3) Move_X = 0, Move_Z = Pi / 2; // ÏòÓÒ else if (Flag_Direction == 4) Move_X = -RC_Velocity, Move_Z = Pi / 2; // ÓÒºó else if (Flag_Direction == 5) Move_X = -RC_Velocity, Move_Z = 0; // ºóÍË else if (Flag_Direction == 6) Move_X = -RC_Velocity, Move_Z = -Pi / 2; // ×óºó else if (Flag_Direction == 7) Move_X = 0, Move_Z = -Pi / 2; // Ïò×ó else if (Flag_Direction == 8) Move_X = RC_Velocity, Move_Z = -Pi / 2; // ×óǰ else Move_X = 0, Move_Z = 0; if (Car_Num == Akm_Car) { // Ackermann structure car is converted to the front wheel steering Angle system target value, and kinematics analysis is pearformed // °¢¿ËÂü&frac12;á&sup1;&sup1;С³µ×ª»»ÎªÇ°ÂÖתÏò&frac12;Ç¶È Move_Z = Move_Z * 2 / 10; } Move_X = Move_X / 1000; Move_Z = -Move_Z; // ת»»ÎªËÙ¶ÈתΪm/s } /************************************************************************** Function: PS2_Control Input : none Output : none º¯Êý&sup1;¦ÄÜ£ºPS2ÊÖ±ú¿ØÖÆ Èë¿Ú&sup2;ÎÊý: ÎÞ ·µ»Ø Öµ£ºÎÞ **************************************************************************/ void PS2_Control(void) { int LY, RX; // ÊÖ±úADCµÄÖµ int Threshold = 20; // ãÐÖµ£¬ºöÂÔÒ¡¸ËС·ù¶È¶¯×÷ static u8 Key1_Count = 0, Key2_Count = 0; // ÓÃÓÚ¿ØÖƶÁȡҡ¸ËµÄËÙ¶È // ת»¯Îª128µ&frac12;-128µÄÊýÖµ LY = -(PS2_LY - 128); // ×ó±ßYÖá¿ØÖÆÇ°&frac12;øºóÍË RX = -(PS2_RX - 128); // ÓÒ±ßXÖá¿ØÖÆ×ªÏò if (LY > -Threshold && LY < Threshold) LY = 0; if (RX > -Threshold && RX < Threshold) RX = 0; // ºöÂÔÒ¡¸ËС·ù¶È¶¯×÷ Move_X = (RC_Velocity / 128) * LY; // ËÙ¶È¿ØÖÆ£¬Á¦¶È±íʾËÙ¶È´óС if (Car_Num == Akm_Car) // °¢¿ËÂü³µ×ªÏò¿ØÖÆ£¬Á¦¶È±íʾתÏò&frac12;Ç¶È Move_Z = -(RC_Turn_Velocity / 128) * RX; else // ÆäËû³µÐÍתÏò¿ØÖÆ { if (Move_X >= 0) Move_Z = -(RC_Turn_Velocity / 128) * RX; // תÏò¿ØÖÆ£¬Á¦¶È±íʾתÏòËÙ¶È else Move_Z = (RC_Turn_Velocity / 128) * RX; } if (PS2_KEY == PSB_L1) // °´ÏÂ×ó1&frac14;ü&frac14;ÓËÙ£¨°´&frac14;üÔÚ¶¥ÉÏ£© { if ((++Key1_Count) == 20) // µ÷&frac12;Ú°´&frac14;ü·´Ó¦ËÙ¶È { PS2_KEY = 0; Key1_Count = 0; if ((RC_Velocity += X_Step) > MAX_RC_Velocity) // ǰ&frac12;ø×î´óËÙ¶È800mm/s RC_Velocity = MAX_RC_Velocity; if (Car_Num != Akm_Car) // ·Ç°¢¿ËÂü³µ¿Éµ÷&frac12;ÚתÏòËÙ¶È { if ((RC_Turn_Velocity += Z_Step) > MAX_RC_Turn_Bias) // תÏò×î´óËÙ¶È325 RC_Turn_Velocity = MAX_RC_Turn_Bias; } } } else if (PS2_KEY == PSB_R1) // °´ÏÂÓÒ1&frac14;ü&frac14;õËÙ { if ((++Key2_Count) == 20) { PS2_KEY = 0; Key2_Count = 0; if ((RC_Velocity -= X_Step) < MINI_RC_Velocity) // ǰºó×îСËÙ¶È210mm/s RC_Velocity = MINI_RC_Velocity; if (Car_Num != Akm_Car) // ·Ç°¢¿ËÂü³µ¿Éµ÷&frac12;ÚתÏòËÙ¶È { if ((RC_Turn_Velocity -= Z_Step) < MINI_RC_Turn_Velocity) // תÏò×îСËÙ¶È45 RC_Turn_Velocity = MINI_RC_Turn_Velocity; } } } else Key2_Count = 0, Key2_Count = 0; // ¶ÁÈ¡µ&frac12;ÆäËû°´&frac14;üÖØÐÂ&frac14;ÆÊý Move_X = Move_X / 1000; Move_Z = -Move_Z; // ËÙ¶ÈMove_XתΪm/s } /************************************************************************** Function: Get_Velocity_From_Encoder Input : none Output : none º¯Êý&sup1;¦ÄÜ£º¶ÁÈ¡±àÂëÆ÷ºÍת»»³ÉËÙ¶È Èë¿Ú&sup2;ÎÊý: ÎÞ ·µ»Ø Öµ£ºÎÞ **************************************************************************/ void Get_Velocity_From_Encoder(void) { // Retrieves the original data of the encoder // »ñÈ¡±àÂëÆ÷µÄÔ­Ê&frac14;Êý¾Ý float Encoder_A_pr, Encoder_B_pr; OriginalEncoder.A = Read_Encoder(Encoder1); OriginalEncoder.B = Read_Encoder(Encoder2); // Decide the encoder numerical polarity according to different car models // ¸ù¾Ý&sup2;»Í¬Ð¡³µÐͺžö¶¨±àÂëÆ÷ÊýÖµ&frac14;«ÐÔ switch (Car_Num) { case Akm_Car: Encoder_A_pr = OriginalEncoder.A; Encoder_B_pr = -OriginalEncoder.B; break; case Diff_Car: Encoder_A_pr = OriginalEncoder.A; Encoder_B_pr = -OriginalEncoder.B; break; case Small_Tank_Car: Encoder_A_pr = OriginalEncoder.A; Encoder_B_pr = -OriginalEncoder.B; break; case Big_Tank_Car: Encoder_A_pr = OriginalEncoder.A; Encoder_B_pr = -OriginalEncoder.B; break; } // The encoder converts the raw data to wheel speed in m/s // ±àÂëÆ÷Ô­Ê&frac14;Êý¾Ýת»»Îª³µÂÖËÙ¶È£¬µ¥Î»m/s MotorA.Current_Encoder = Encoder_A_pr * Frequency * Perimeter / 60000.0f; // 60000 = 4*500*30 MotorB.Current_Encoder = Encoder_B_pr * Frequency * Perimeter / 60000.0f; // 1560=4*13*30=2£¨Á&frac12;·Âö³å£©*2£¨ÉÏÏÂÑØ&frac14;ÆÊý£©*»ô¶û±àÂëÆ÷13Ïß*µç»úµÄ&frac14;õËÙ±È // MotorA.Current_Encoder= Encoder_A_pr*CONTROL_FREQUENCY*Akm_wheelspacing//(4*13*30); // MotorB.Current_Encoder= Encoder_B_pr*CONTROL_FREQUENCY*Akm_wheelspacing/Encoder_precision; } /************************************************************************** Function: Drive_Motor Input : none Output : none º¯Êý&sup1;¦ÄÜ£ºÔ˶¯Ñ§Äæ&frac12;â Èë¿Ú&sup2;ÎÊý: ÎÞ ·µ»Ø Öµ£ºÎÞ **************************************************************************/ // Ô˶¯Ñ§Äæ&frac12;⣬ÓÉxºÍyµÄËٶȵõ&frac12;±àÂëÆ÷µÄËÙ¶È,VxÊÇm/s,Vzµ¥Î»ÊǶÈ/s(&frac12;ǶÈÖÆ) // °¢¿ËÂü³µVzÊǶæ»úתÏòµÄ&frac12;ǶÈ(»¡¶ÈÖÆ) void Get_Target_Encoder(float Vx, float Vz) { float MotorA_Velocity, MotorB_Velocity; float amplitude = 3.5f; // Wheel target speed limit //³µÂÖÄ¿±êËÙ¶ÈÏÞ·ù Move_X = target_limit_float(Move_X, -1.2, 1.2); Move_Z = target_limit_float(Move_Z, -Pi / 3, Pi / 3); if (Car_Num == Akm_Car) // °¢¿ËÂü³µ { // Ackerman car specific related variables //°¢¿ËÂüС³µ×¨ÓÃÏà&sup1;رäÁ¿ float R, ratio = 636.56, AngleR, Angle_Servo; // For Ackerman small car, Vz represents the front wheel steering Angle // ¶ÔÓÚ°¢¿ËÂüС³µVz´ú±íÓÒǰÂÖתÏò&frac12;Ç¶È AngleR = Vz; R = Akm_axlespacing / tan(AngleR) - 0.5f * Wheelspacing; // Front wheel steering Angle limit (front wheel steering Angle controlled by steering engine), unit: rad // ǰÂÖתÏò&frac12;ǶÈÏÞ·ù(¶æ»ú¿ØÖÆÇ°ÂÖתÏò&frac12;ǶÈ)£¬µ¥Î»£ºrad AngleR = target_limit_float(AngleR, -0.49f, 0.32f); // Inverse kinematics //Ô˶¯Ñ§Äæ&frac12;â if (AngleR != 0) { MotorA.Target_Encoder = Vx * (R - 0.081f) / R; MotorB.Target_Encoder = Vx * (R + 0.081f) / R; } else { MotorA.Target_Encoder = Vx; MotorB.Target_Encoder = Vx; } // The PWM value of the servo controls the steering Angle of the front wheel // ¶æ»úPWMÖµ£¬¶æ»ú¿ØÖÆÇ°ÂÖתÏò&frac12;Ç¶È Angle_Servo = -0.628f * pow(AngleR, 3) + 1.269f * pow(AngleR, 2) - 1.772f * AngleR + 1.573f; Servo_PWM = SERVO_INIT + (Angle_Servo - 1.572f) * ratio; // printf("%d\r\n",Servo_PWM); // Wheel (motor) target speed limit //³µÂÖ(µç»ú)Ä¿±êËÙ¶ÈÏÞ·ù MotorA.Target_Encoder = target_limit_float(MotorA.Target_Encoder, -amplitude, amplitude); MotorB.Target_Encoder = target_limit_float(MotorB.Target_Encoder, -amplitude, amplitude); Servo_PWM = target_limit_int(Servo_PWM, 800, 2200); // Servo PWM value limit //¶æ»úPWMÖµÏÞ·ù } else if (Car_Num == Diff_Car) // &sup2;îËÙС³µ { if (Vx < 0) Vz = -Vz; else Vz = Vz; // Inverse kinematics //Ô˶¯Ñ§Äæ&frac12;â MotorA.Target_Encoder = Vx - Vz * Wheelspacing / 2.0f; // &frac14;ÆËã³ö×óÂÖµÄÄ¿±êËÙ¶È MotorB.Target_Encoder = Vx + Vz * Wheelspacing / 2.0f; // &frac14;ÆËã³öÓÒÂÖµÄÄ¿±êËÙ¶È // Wheel (motor) target speed limit //³µÂÖ(µç»ú)Ä¿±êËÙ¶ÈÏÞ·ù MotorA.Target_Encoder = target_limit_float(MotorA.Target_Encoder, -amplitude, amplitude); MotorB.Target_Encoder = target_limit_float(MotorB.Target_Encoder, -amplitude, amplitude); } else if (Car_Num == Small_Tank_Car) { if (Vx < 0) Vz = -Vz; else Vz = Vz; MotorA.Target_Encoder = Vx - Vz * Wheelspacing / 2.0f; // &frac14;ÆËã³ö×óÂÖµÄÄ¿±êËÙ¶È MotorB.Target_Encoder = Vx + Vz * Wheelspacing / 2.0f; // &frac14;ÆËã³öÓÒÂÖµÄÄ¿±êËÙ¶È // Wheel (motor) target speed limit //³µÂÖ(µç»ú)Ä¿±êËÙ¶ÈÏÞ·ù MotorA.Target_Encoder = target_limit_float(MotorA.Target_Encoder, -amplitude, amplitude); MotorB.Target_Encoder = target_limit_float(MotorB.Target_Encoder, -amplitude, amplitude); } else if (Car_Num == Big_Tank_Car) { if (Vx < 0) Vz = -Vz; else Vz = Vz; MotorA.Target_Encoder = Vx - Vz * Wheelspacing / 2.0f; // &frac14;ÆËã³ö×óÂÖµÄÄ¿±êËÙ¶È MotorB.Target_Encoder = Vx + Vz * Wheelspacing / 2.0f; // &frac14;ÆËã³öÓÒÂÖµÄÄ¿±êËÙ¶È MotorA.Target_Encoder = target_limit_float(MotorA.Target_Encoder, -amplitude, amplitude); MotorB.Target_Encoder = target_limit_float(MotorB.Target_Encoder, -amplitude, amplitude); } } /************************************************************************** Function: Get_Motor_PWM Input : none Output : none º¯Êý&sup1;¦ÄÜ£º×ª»»³ÉÇý¶¯µç»úµÄPWM Èë¿Ú&sup2;ÎÊý: ÎÞ ·µ»Ø Öµ£ºÎÞ **************************************************************************/ void Get_Motor_PWM(void) { // &frac14;ÆËã×óÓÒµç»ú¶ÔÓ¦µÄPWM MotorA.Motor_Pwm = Incremental_PI_Left(MotorA.Current_Encoder, MotorA.Target_Encoder); MotorB.Motor_Pwm = Incremental_PI_Right(MotorB.Current_Encoder, MotorB.Target_Encoder); if (Mode == Normal_Mode || Mode == Measure_Distance_Mode) { // ÂË&sup2;¨£¬Ê&sup1;Æð&sup2;&frac12;ºÍÍ£Ö&sup1;ÉÔ΢Æ&frac12;»¬Ò»Ð© MotorA.Motor_Pwm = Mean_Filter_Left(MotorA.Motor_Pwm); MotorB.Motor_Pwm = Mean_Filter_Right(MotorB.Motor_Pwm); } // ÏÞ·ù MotorA.Motor_Pwm = PWM_Limit(MotorA.Motor_Pwm, PWM_MAX, PWM_MIN); MotorB.Motor_Pwm = PWM_Limit(MotorB.Motor_Pwm, PWM_MAX, PWM_MIN); } /************************************************************************** Function: PWM_Limit Input : IN;max;min Output : OUT º¯Êý&sup1;¦ÄÜ£ºÏÞÖÆPWM¸³Öµ Èë¿Ú&sup2;ÎÊý: IN£ºÊäÈë&sup2;ÎÊý max£ºÏÞ·ù×î´óÖµ min£ºÏÞ·ù×îСֵ ·µ»Ø Öµ£ºÏÞ·ùºóµÄÖµ **************************************************************************/ float PWM_Limit(float IN, int max, int min) { float OUT = IN; if (OUT > max) OUT = max; if (OUT < min) OUT = min; return OUT; } /************************************************************************** Function: Limiting function Input : Value Output : none º¯Êý&sup1;¦ÄÜ£ºÏÞ·ùº¯Êý Èë¿Ú&sup2;ÎÊý£º·ùÖµ ·µ»Ø Öµ£ºÎÞ **************************************************************************/ float target_limit_float(float insert, float low, float high) { if (insert < low) return low; else if (insert > high) return high; else return insert; } int target_limit_int(int insert, int low, int high) { if (insert < low) return low; else if (insert > high) return high; else return insert; } /************************************************************************** Function: Check whether it is abnormal Input : none Output : 1:Abnormal;0:Normal º¯Êý&sup1;¦ÄÜ£ºÒì³£&sup1;رյç»ú Èë¿Ú&sup2;ÎÊý: ÎÞ ·µ»Ø Öµ£º1£ºÒì³£ 0£ºÕý³£ **************************************************************************/ u8 Turn_Off(void) { u8 temp = Normal; Flag_Stop = KEY2_STATE; // ¶ÁÈ¡°´&frac14;ü2״̬£¬°´&frac14;ü2¿ØÖƵç»úµÄ¿ª&sup1;Ø if (Voltage < 1000) // µç³ØµçÑ&sup1;µÍÓÚ10V&sup1;رյç»ú,LEDµÆ¿ìËÙÉÁ˸ LED_Flash(50), temp = Abnormal; else LED_Flash(200); // ÿһÃëÉÁÒ»´Î£¬Õý³£ÔËÐÐ if (Flag_Stop) temp = Abnormal; return temp; } /************************************************************************** Function: Data sliding filtering Input : data Output : Filtered data º¯Êý&sup1;¦ÄÜ£ºÊý¾Ý»¬¶¯ÂË&sup2;¨ Èë¿Ú&sup2;ÎÊý£ºÊý¾Ý ·µ»Ø Öµ£ºÂË&sup2;¨ºóµÄÊý¾Ý **************************************************************************/ float Mean_Filter_Left(float data) { u8 i; float Sum_Data = 0; float Filter_Data; static float Speed_Buf[FILTERING_TIMES] = {0}; for (i = 1; i < FILTERING_TIMES; i++) { Speed_Buf[i - 1] = Speed_Buf[i]; } Speed_Buf[FILTERING_TIMES - 1] = data; for (i = 0; i < FILTERING_TIMES; i++) { Sum_Data += Speed_Buf[i]; } Filter_Data = (s32)(Sum_Data / FILTERING_TIMES); return Filter_Data; } /************************************************************************** Function: Data sliding filtering Input : data Output : Filtered data º¯Êý&sup1;¦ÄÜ£ºÊý¾Ý»¬¶¯ÂË&sup2;¨ Èë¿Ú&sup2;ÎÊý£ºÊý¾Ý ·µ»Ø Öµ£ºÂË&sup2;¨ºóµÄÊý¾Ý **************************************************************************/ float Mean_Filter_Right(float data) { u8 i; float Sum_Data = 0; float Filter_Data; static float Speed_Buf[FILTERING_TIMES] = {0}; for (i = 1; i < FILTERING_TIMES; i++) { Speed_Buf[i - 1] = Speed_Buf[i]; } Speed_Buf[FILTERING_TIMES - 1] = data; for (i = 0; i < FILTERING_TIMES; i++) { Sum_Data += Speed_Buf[i]; } Filter_Data = (s32)(Sum_Data / FILTERING_TIMES); return Filter_Data; } /************************************************************************** Function: Lidar_Avoid Input : none Output : none º¯Êý&sup1;¦ÄÜ£ºÀ×´ï±ÜÕÏÄ£Ê&frac12; Èë¿Ú&sup2;ÎÊý£ºÎÞ ·µ»Ø Öµ£ºÎÞ **************************************************************************/ void Lidar_Avoid(void) { int i = 0; u8 calculation_angle_cnt = 0; // ÓÃÓÚÅжÏ100¸öµãÖÐÐèÒª×ö±ÜÕϵĵã float angle_sum = 0; // ´ÖÂÔ&frac14;ÆËãÕϰ­ÎïλÓÚ×ó»òÕßÓÒ u8 distance_count = 0; // ¾àÀëСÓÚijֵµÄ&frac14;ÆÊý int distance = 350; // É趨±ÜÕϾàÀë,ĬÈÏÊÇ300 if (Car_Num == Akm_Car) distance = 400; // °¢¿ËÂü³µÉ趨ÊÇ400mm else if (Car_Num == Big_Tank_Car) distance = 500; // ´óÂÄ´ø³µÉ趨ÊÇ500mm for (i = 0; i < lap_count; i++) { if ((Dataprocess[i].angle > 310) || (Dataprocess[i].angle < 50)) { if ((0 < Dataprocess[i].distance) && (Dataprocess[i].distance < distance)) // ¾àÀëСÓÚ350mmÐèÒª±ÜÕÏ,Ö»ÐèÒª100¶È·¶Î§ÄÚµã { calculation_angle_cnt++; // &frac14;ÆËã¾àÀëСÓÚ±ÜÕϾàÀëµÄµã¸öÊý if (Dataprocess[i].angle < 50) angle_sum += Dataprocess[i].angle; else if (Dataprocess[i].angle > 310) angle_sum += (Dataprocess[i].angle - 360); // 310¶Èµ&frac12;50¶Èת»¯Îª-50¶Èµ&frac12;50¶È if (Dataprocess[i].distance < 200) // &frac14;ÇÂ&frac14;СÓÚ200mmµÄµãµÄ&frac14;ÆÊý distance_count++; } } } if (calculation_angle_cnt < 8) // СÓÚ8µã&sup2;»ÐèÒª±ÜÕÏ£¬È¥³ýһЩÔëµã { if ((Move_X += 0.1) >= Aovid_Speed) // ±ÜÕϵÄËÙ¶ÈÉ趨Ϊ260£¬Öð&frac12;¥Ôö&frac14;Óµ&frac12;260¿ÉÉÔ΢Æ&frac12;»¬Ò»Ð© Move_X = Aovid_Speed; Move_Z = 0; // &sup2;»±ÜÕÏʱ&sup2;»ÐèҪתÍä } else // ÐèÒª±ÜÕÏ£¬&frac14;òµ¥µØÅжÏÕϰ­Îï·&frac12;λ { if (Car_Num == Akm_Car) // °¢¿ËÂü³µÐÍÓжæ»ú£¬ÐèÒªÌØÊâ´¦Àí { if (distance_count > 8) // ¾àÀëСÓÚ±ÜÕ&frac12;¾àÀë Move_X = -Aovid_Speed, Move_Z = 0; // ÍùºóÍË else { if ((Move_X -= 0.1) <= (Aovid_Speed * 0.5)) // ±ÜÕÏʱËÙ¶È&frac12;µµ&frac12;µÍËÙ0.25 Move_X = Aovid_Speed * 0.5; if (angle_sum > 0) // Õϰ­ÎïÆ«ÓÒ Move_Z = -Pi / 5; // ÿ´ÎתÍä&frac12;ǶÈΪPI/5£¬Ö±µ&frac12;100¶È·¶Î§ÄÚÎÞÕϰ­Îï¾ÍÍ£Ö&sup1; else // Æ«×ó Move_Z = Pi / 5; } } else { if (distance_count > 8) // СÓÚ±ÜÕ&frac12;¾àÀëµÄʱºò Move_X = -Aovid_Speed, Move_Z = 0; // ÍùºóÍË else { if ((Move_X -= 0.1) <= (Aovid_Speed * 0.5)) // ±ÜÕÏʱËÙ¶È&frac12;µµ&frac12;µÍËÙ¶È0.15 Move_X = (Aovid_Speed * 0.5); if (angle_sum > 0) // Õϰ­ÎïÆ«ÓÒ { if (Car_Num == Diff_Car) // ÿ´ÎתÍäËÙ¶ÈΪX¶È£¬Ö±µ&frac12;100¶È·¶Î§ÄÚÎÞÕϰ­Îï¾ÍÍ£Ö&sup1; Move_Z = -1; else if (Car_Num == Small_Tank_Car) Move_Z = -1; else Move_Z = -1; } else // Æ«×ó { if (Car_Num == Diff_Car) // ÿ´ÎתÍäËÙ¶ÈΪX¶È£¬Ö±µ&frac12;100¶È·¶Î§ÄÚÎÞÕϰ­Îï¾ÍÍ£Ö&sup1; Move_Z = 1; else if (Car_Num == Small_Tank_Car) Move_Z = 1; else Move_Z = 1; } } } } Move_Z = -Move_Z; } /************************************************************************** Function: Lidar_Follow Input : none Output : none º¯Êý&sup1;¦ÄÜ£ºÀ×´ï¸úËæÄ£Ê&frac12; Èë¿Ú&sup2;ÎÊý£ºÎÞ ·µ»Ø Öµ£ºÎÞ **************************************************************************/ float angle1 = 0; // ¸úËæµÄ&frac12;Ç¶È u16 mini_distance1; void Lidar_Follow(void) { static u16 cnt = 0; int i; int calculation_angle_cnt = 0; static float angle = 0; // ¸úËæµÄ&frac12;Ç¶È static float last_angle = 0; // u16 mini_distance = 65535; static u8 data_count = 0; // ÓÃÓÚÂ˳ýһдÔëµãµÄ&frac14;ÆÊý±äÁ¿ // ÐèÒªÕÒ³ö¸úËæµÄÄǸöµãµÄ&frac12;Ç¶È for (i = 0; i < lap_count; i++) { if (100 < Dataprocess[i].distance && Dataprocess[i].distance < Follow_Distance) // 1200·¶Î§ÄÚ¾ÍÐèÒª¸úËæ { calculation_angle_cnt++; if (Dataprocess[i].distance < mini_distance) // ÕÒ³ö¾àÀë×îСµÄµã { mini_distance = Dataprocess[i].distance; angle = Dataprocess[i].angle; } } } if (angle > 180) angle -= 360; // 0--360¶Èת»»³É0--180£»-180--0£¨Ë³Ê±Õ룩 if (angle - last_angle > 10 || angle - last_angle < -10) // ×öÒ»¶¨Ïû¶¶£¬&sup2;¨¶¯´óÓÚ10¶ÈµÄÐèÒª×öÅÐ¶Ï { if (++data_count == 60) // Á¬Ðø60´Î&sup2;É&frac14;¯µ&frac12;µÄÖµ(300msºó)ºÍÉϴεıȴóÓÚ10¶È£¬´Ëʱ&sup2;ÅÊÇÈÏΪÊÇÓÐЧֵ { data_count = 0; last_angle = angle; } } else // &sup2;¨¶¯Ð¡ÓÚ10¶ÈµÄ¿ÉÒÔÖ±&frac12;ÓÈÏΪÊÇÓÐЧֵ { data_count = 0; last_angle = angle; } if (calculation_angle_cnt < 6) // ÔÚ¸úËæ·¶Î§ÄڵĵãÉÙÓÚ6¸ö { if (cnt < 40) // Á¬Ðø&frac14;ÆÊý³¬40´ÎûÓÐÒª¸úËæµÄµã£¬´Ëʱ&sup2;ÅÊÇ&sup2;»ÓøúËæ cnt++; if (cnt >= 40) { Move_X = 0; // ËÙ¶ÈΪ0 Move_Z = 0; } } else { cnt = 0; if (Car_Num == Akm_Car) { if ((((angle > 15) && (angle < 180)) || ((angle > -180) && angle < -15)) && (mini_distance < 500)) // °¢¿¨Âü³µÐÍ´¦Àí³µÍ·&sup2;»¶ÔןúËæÎÏ൱ÓÚºó³µÒ»Ñù£¬Ò»´Î&sup2;»¶Ô×&frac14;£¬ÄǺóÍËÔÙÀ´¶Ô×&frac14; { Move_X = -0.20; Move_Z = -Follow_Turn_PID(last_angle, 0); } else { Move_X = Distance_Adjust_PID(mini_distance, Keep_Follow_Distance); // ±£³Ö¾àÀë±£³ÖÔÚ400mm Move_Z = Follow_Turn_PID(last_angle, 0); } } else // ÆäÓà³µÐÍ { if ((angle > 50 || angle < -50) && (mini_distance > 400)) { Move_Z = -0.0298f * last_angle; // &frac12;ǶÈ&sup2;î¾à&sup1;ý´óÖ±&frac12;Ó¿ìËÙתÏò Move_X = 0; // &sup2;îËÙС³µºÍÂÄ´øÐ¡³µ¿ÉÒÔʵÏÖÔ­µØ×ª¶¯ } else { Move_X = Distance_Adjust_PID(mini_distance, Keep_Follow_Distance); // ±£³Ö¾àÀë±£³ÖÔÚ400mm Move_Z = Follow_Turn_PID(last_angle, 0); // תÏòPID£¬³µÍ·ÓÀÔ¶¶ÔןúËæÎïÆ· } } } Move_Z = target_limit_float(Move_Z, -Pi / 6, Pi / 6); // ÏÞ·ù Move_X = target_limit_float(Move_X, -0.6, 0.6); } /************************************************************************** º¯Êý&sup1;¦ÄÜ£ºÐ¡³µ×ßÖ±ÏßÄ£Ê&frac12; Èë¿Ú&sup2;ÎÊý£ºÎÞ ·µ»Ø Öµ£ºÎÞ **************************************************************************/ void Lidar_along_wall(void) { static u32 target_distance = 0; static int n = 0; u32 distance; u8 data_count = 0; // ÓÃÓÚÂ˳ýһдÔëµãµÄ&frac14;ÆÊý±äÁ¿ for (int i = 0; i < lap_count; i++) { if (Dataprocess[i].angle > 75 && Dataprocess[i].angle < 77) { if (n == 0) { target_distance = Dataprocess[i].distance; // »ñÈ¡µÄµÚÒ»¸öµã×÷ΪĿ±ê¾àÀë n++; } if (Dataprocess[i].distance < target_distance + 100) //+100ÏÞÖÆ»ñÈ¡¾àÀëµÄ·¶Î§Öµ { distance = Dataprocess[i].distance; // »ñȡʵʱ¾àÀë data_count++; } } } // if(data_count <= 0) // Move_X = 0; // Move_X = forward_velocity; // ³õÊ&frac14;ËÙ¶È Move_Z = -Along_Adjust_PID(distance, target_distance); if (Car_Num == Akm_Car) { Move_Z = target_limit_float(Move_Z, -Pi / 4, Pi / 4); // ÏÞ·ù } else if (Car_Num == Diff_Car) Move_Z = target_limit_float(Move_Z, -Pi / 5, Pi / 5); // ÏÞ·ù } /************************************************************************** Function: Car_Perimeter_Init Input : none Output : none º¯Êý&sup1;¦ÄÜ£º&frac14;ÆËãС³µ¸÷ÂÖ×ÓµÄÖܳ¤ Èë¿Ú&sup2;ÎÊý£ºÎÞ ·µ»Ø Öµ£ºÎÞ **************************************************************************/ void Car_Perimeter_Init(void) { if (Car_Num == Diff_Car || Car_Num == Akm_Car) { Perimeter = Diff_Car_Wheel_diameter * Pi; Wheelspacing = Diff_wheelspacing; } else if (Car_Num == Small_Tank_Car) { Perimeter = Small_Tank_WheelDiameter * Pi; Wheelspacing = Small_Tank_wheelspacing; } else { Perimeter = Big_Tank_WheelDiameter * Pi; Wheelspacing = Big_Tank_wheelspacing; } } /************************************************************************** Function: Ultrasonic_Follow Input : none Output : none º¯Êý&sup1;¦ÄÜ£º³¬Éù&sup2;¨¸úËæÄ£Ê&frac12; Èë¿Ú&sup2;ÎÊý£ºÎÞ ·µ»Ø Öµ£ºÎÞ **************************************************************************/ void Ultrasonic_Follow(void) // ³¬Éù&sup2;¨¸úËæ£¬Ö»Äܵ¥·&frac12;Ïò¸úËæ { Move_Z = 0; Read_Distane(); // ¶ÁÈ¡³¬Éù&sup2;¨µÄ¾àÀë if (Distance1 < 200) // ¾àÀëСÓÚ200mm£¬Í˺ó { if ((Move_X -= 3) < -210) Move_X = -210; // ¸øÒ»210ºóÍËËÙ¶È } else if (Distance1 > 270 && Distance1 < 750) // ¾àÀëÔÚ270µ&frac12;750Ö®&frac14;äÊÇÐèÒª¸úËæÇ°&frac12;ø { if ((Move_X += 3) > 210) // ËÙ¶ÈÖð&frac12;¥Ôö&frac14;Ó£¬¸øÇ°&frac12;øËÙ¶È Move_X = 210; } else { if (Move_X > 0) { if ((Move_X -= 20) < 0) // ËÙ¶ÈÖð&frac12;¥&frac14;õµ&frac12;0 Move_X = 0; } else { if ((Move_X += 20) > 0) // ËÙ¶ÈÖð&frac12;¥&frac14;õµ&frac12;0 Move_X = 0; } } } /************************************************************************** Function: Get angle Input : way£ºThe algorithm of getting angle 1£ºDMP 2£ºkalman 3£ºComplementary filtering Output : none º¯Êý&sup1;¦ÄÜ£º»ñÈ¡&frac12;Ç¶È Èë¿Ú&sup2;ÎÊý£ºway£º»ñÈ¡&frac12;ǶȵÄËã·¨ 1£ºDMP 2£º¿¨¶ûÂü 3£º»¥&sup2;&sup1;ÂË&sup2;¨ ·µ»Ø Öµ£ºÎÞ **************************************************************************/ void Get_Angle(u8 way) { if (way == 1) // DMPµÄ¶ÁÈ¡ÔÚÊý¾Ý&sup2;É&frac14;¯Öж϶ÁÈ¡£¬Ñϸñ×ñѭʱÐòÒªÇó { Read_DMP(); // ¶ÁÈ¡&frac14;ÓËÙ¶È¡¢&frac12;ÇËÙ¶È¡¢Çã&frac12;Ç } else { Gyro_X = (I2C_ReadOneByte(devAddr, MPU6050_RA_GYRO_XOUT_H) << 8) + I2C_ReadOneByte(devAddr, MPU6050_RA_GYRO_XOUT_L); // ¶ÁÈ¡XÖáÍÓÂÝÒÇ Gyro_Y = (I2C_ReadOneByte(devAddr, MPU6050_RA_GYRO_YOUT_H) << 8) + I2C_ReadOneByte(devAddr, MPU6050_RA_GYRO_YOUT_L); // ¶ÁÈ¡YÖáÍÓÂÝÒÇ Gyro_Z = (I2C_ReadOneByte(devAddr, MPU6050_RA_GYRO_ZOUT_H) << 8) + I2C_ReadOneByte(devAddr, MPU6050_RA_GYRO_ZOUT_L); // ¶ÁÈ¡ZÖáÍÓÂÝÒÇ Accel_X = (I2C_ReadOneByte(devAddr, MPU6050_RA_ACCEL_XOUT_H) << 8) + I2C_ReadOneByte(devAddr, MPU6050_RA_ACCEL_XOUT_L); // ¶ÁÈ¡XÖá&frac14;ÓËÙ¶È&frac14;Æ Accel_Y = (I2C_ReadOneByte(devAddr, MPU6050_RA_ACCEL_YOUT_H) << 8) + I2C_ReadOneByte(devAddr, MPU6050_RA_ACCEL_YOUT_L); // ¶ÁÈ¡XÖá&frac14;ÓËÙ¶È&frac14;Æ Accel_Z = (I2C_ReadOneByte(devAddr, MPU6050_RA_ACCEL_ZOUT_H) << 8) + I2C_ReadOneByte(devAddr, MPU6050_RA_ACCEL_ZOUT_L); // ¶ÁÈ¡ZÖá&frac14;ÓËÙ¶È&frac14;Æ // if(Gyro_X>32768) Gyro_X-=65536; //Êý¾ÝÀàÐÍת»» Ò&sup2;¿Éͨ&sup1;ýshortÇ¿ÖÆÀàÐÍת»» // if(Gyro_Y>32768) Gyro_Y-=65536; //Êý¾ÝÀàÐÍת»» Ò&sup2;¿Éͨ&sup1;ýshortÇ¿ÖÆÀàÐÍת»» // if(Gyro_Z>32768) Gyro_Z-=65536; //Êý¾ÝÀàÐÍת»» // if(Accel_X>32768) Accel_X-=65536; //Êý¾ÝÀàÐÍת»» // if(Accel_Y>32768) Accel_Y-=65536; //Êý¾ÝÀàÐÍת»» // if(Accel_Z>32768) Accel_Z-=65536; //Êý¾ÝÀàÐÍת»» Accel_Angle_x = atan2(Accel_Y, Accel_Z) * 180 / Pi; // &frac14;ÆËãÇã&frac12;Ç£¬×ª»»µ¥Î»Îª¶È Accel_Angle_y = atan2(Accel_X, Accel_Z) * 180 / Pi; // &frac14;ÆËãÇã&frac12;Ç£¬×ª»»µ¥Î»Îª¶È Gyro_X = Gyro_X / 65.5; // ÍÓÂÝÒÇÁ¿³Ìת»»£¬Á¿³Ì¡À500¡ã/s¶ÔÓ¦ÁéÃô¶È65.5£¬¿É&sup2;éÊÖ&sup2;á Gyro_Y = Gyro_Y / 65.5; // ÍÓÂÝÒÇÁ¿³Ìת»» if (way == 2) { Roll = -Kalman_Filter_x(Accel_Angle_x, Gyro_X); // ¿¨¶ûÂüÂË&sup2;¨ Pitch = -Kalman_Filter_y(Accel_Angle_y, Gyro_Y); } else if (way == 3) { Roll = -Complementary_Filter_x(Accel_Angle_x, Gyro_X); // »¥&sup2;&sup1;ÂË&sup2;¨ Pitch = -Complementary_Filter_y(Accel_Angle_y, Gyro_Y); } } } /************************************************************************** Function: The remote control command of model aircraft is processed Input : none Output : none º¯Êý&sup1;¦ÄÜ£º¶Ôº&frac12;Ä£Ò£¿Ø¿ØÖÆÃüÁî&frac12;øÐд¦Àí Èë¿Ú&sup2;ÎÊý£ºÎÞ ·µ»Ø Öµ£ºÎÞ **************************************************************************/ void Remote_Control(void) { // Data within 1 second after entering the model control mode will not be processed // ¶Ô&frac12;øÈëº&frac12;Ä£¿ØÖÆÄ£Ê&frac12;ºó1ÃëÄÚµÄÊý¾Ý&sup2;»´¦Àí static u8 thrice = 200; int Threshold = 100; // limiter //ÏÞ·ù int LX, RY; // static float Target_LX,Target_LY,Target_RY,Target_RX; Remoter_Ch1 = target_limit_int(Remoter_Ch1, 1000, 2000); Remoter_Ch2 = target_limit_int(Remoter_Ch2, 1000, 2000); // Front and back direction of left rocker. Control forward and backward. // ×óÒ¡¸Ëǰºó·&frac12;Ïò¡£¿ØÖÆÇ°&frac12;øºóÍË¡£ LX = Remoter_Ch2 - 1500; // //Left joystick left and right. Control left and right movement. // //×óÒ¡¸Ë×óÓÒ·&frac12;Ïò¡£¿ØÖÆ×óÓÒÒÆ¶¯¡£¡£ // LY=Remoter_Ch2-1500; // Right stick left and right. To control the rotation. // ÓÒÒ¡¸Ë×óÓÒ·&frac12;Ïò¡£¿ØÖÆ×Ôת¡£ RY = Remoter_Ch1 - 1500; // if (LX > -Threshold && LX < Threshold) LX = 0; if (RY > -Threshold && RY < Threshold) RY = 0; // if(LX==0) Target_LX=Target_LX/1.2f; // if(LY==0) Target_LY=Target_LY/1.2f; // if(RY==0) Target_RY=Target_RY/1.2f; // //Throttle related //ÓÍÃÅÏà&sup1;Ø // Remote_RCvelocity=RC_Velocity+RX; // if(Remote_RCvelocity<0)Remote_RCvelocity=0; // The remote control command of model aircraft is processed // ¶Ôº&frac12;Ä£Ò£¿Ø¿ØÖÆÃüÁî&frac12;øÐд¦Àí Move_X = LX; Move_Z = -RY; Move_X = Move_X * 1.3; //*1.3ÊÇΪÁËÀ«´óËÙ¶È if (Car_Num == Akm_Car) Move_Z = Move_Z * (Pi / 8) / 350.0; else Move_Z = Move_Z * 2 * (Pi / 4) / 350.0; // Unit conversion, mm/s -> m/s // µ¥Î»×ª»»£¬mm/s -> m/s Move_X = Move_X / 1000; // ZÖáÊý¾Ýת»¯ #if _4WD if (Move_X < 0) Move_Z = -Move_Z; #endif // Data within 1 second after entering the model control mode will not be processed // ¶Ô&frac12;øÈëº&frac12;Ä£¿ØÖÆÄ£Ê&frac12;ºó1ÃëÄÚµÄÊý¾Ý&sup2;»´¦Àí if (thrice > 0) Move_X = 0, Move_Z = 0, thrice--; // Control target value is obtained and kinematics analysis is performed // µÃµ&frac12;¿ØÖÆÄ¿±êÖµ£¬&frac12;øÐÐÔ˶¯Ñ§·ÖÎö // Get_Target_Encoder(Move_X,Move_Z); } 怎么把OpenMV与STM32串口通信实现二维码/APRILTag码识别及控制的代码加到上述代码中,现在openmv的二维码识别已做好,二维码采用的是Apriltag的36h11类型,id:0表示停止,id:1表示直行,id:2表示左转,id:3表示右转,现在需要再在STM32中修改或添加代码,使其能在接收到openmv识别到的指令后作出相应的动作
05-16
根据增量式PID算法原理,完成main.c文件IncPIDInit()函数pid的初始化和 int32_t BLDC_SpdPIDCalc(int32_t NextPoint)函数的编写。条件:当误差小于等于正负3时,视为无误差。 #include "main.h" #include "math.h" #include "stm32f4xx_hal.h" #include "bldc/bsp_bldc.h" #include "key/bsp_key.h" #include "beep/bsp_beep.h" #include "HMI/bsp_usartx_HMI.h" /* Ë&frac12;ÓÐÀàÐͶ¨Òå --------------------------------------------------------------*/ typedef struct { __IO int32_t SetPoint; //É趨Ŀ±ê Desired Value __IO long SumError; //Îó&sup2;îÀÛ&frac14;Æ __IO float Proportion; //±ÈÀý³£Êý Proportional Const __IO float Integral; //»ý·Ö³£Êý Integral Const __IO float Derivative; //΢·Ö³£Êý Derivative Const __IO int LastError; //Error[-1] }PID_Typedef; /* Ë&frac12;Óк궨Òå ----------------------------------------------------------------*/ //&frac12;«¸¡µãÊýxËÄÉáÎåÈëΪint32_t #define ROUND_TO_INT32(x) ((int32_t)(x)+0.5f)>=(x)? ((int32_t)(x)):((int32_t)(x)+1) #define WIN 8 #define P_DATA 0.035f // P&sup2;ÎÊý #define I_DATA 0.10f // I&sup2;ÎÊý #define D_DATA 0.0f // D&sup2;ÎÊý #define TARGET_SPEED 500 /* Ë&frac12;ÓбäÁ¿ ------------------------------------------------------------------*/ __IO int32_t flag = 0; // µÃµ&frac12;WIN´ÎËÙ¶ÈÖµµÄ±êÖ¾ __IO int32_t start_flag = 0; // Æô¶¯±êÖ¾ __IO int32_t Avg_cnt = 0; // Æ&frac12;¾ùÖµ&frac14;ÆÊý __IO float Avg_Speed[WIN]= {0};// ǰWIN´ÎµÄËÙ¶ÈÖµ static __IO int32_t BLDC_CaptureNumber = 0; // ÊäÈë&sup2;¶»ñÊý __IO PID_Typedef PID_BLDC; // BLDC PID¿ØÖÆ&frac12;á&sup1;&sup1;Ìå int32_t BLDC_SPEED_MAX = (3000); // µç»ú×î´óËÙ¶È//ĬÈÏ3000 int32_t BLDC_SPEED_MIN = (-3000); // µç»ú×î´óËÙ¶È//ĬÈÏ3000 uint32_t Time_CNT = 0; /* À©Õ&sup1;±äÁ¿ ------------------------------------------------------------------*/ /* Ë&frac12;Óк¯ÊýÔ­ÐÎ --------------------------------------------------------------*/ static void IncPIDInit(void) ; static float Avg_speed(float Speed); int32_t BLDC_SpdPIDCalc(int32_t NextPoint); void UpdateHMI_SM_PID_feedback(int32_t CaptureNumber,int32_t RPM); static void UpdateHMI_SM_PID_Param(PID_Typedef Param_Pos); void BLDC_SetTargetSpd(int32_t Spd); /* º¯ÊýÌå --------------------------------------------------------------------*/ /** * º¯Êý&sup1;¦ÄÜ: ϵͳʱÖÓÅäÖà * ÊäÈë&sup2;ÎÊý: ÎÞ * ·µ »Ø Öµ: ÎÞ * ˵ Ã÷: ÎÞ */ void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct; RCC_ClkInitTypeDef RCC_ClkInitStruct; __HAL_RCC_PWR_CLK_ENABLE(); // Ê&sup1;ÄÜPWRʱÖÓ __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);// ÉèÖõ÷Ñ&sup1;Æ÷Êä³öµçÑ&sup1;&frac14;¶±ð1 RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;// Íâ&sup2;¿¾§Õñ£¬8MHz RCC_OscInitStruct.HSEState = RCC_HSE_ON; // ´ò¿ªHSE RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; // ´ò¿ªPLL RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;// PLLʱÖÓÔ´Ñ¡ÔñHSE RCC_OscInitStruct.PLL.PLLM = 8; // 8·ÖƵMHz RCC_OscInitStruct.PLL.PLLN = 336; // 336±¶Æµ RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; // 2·ÖƵ£¬µÃµ&frac12;168MHzÖ÷ʱÖÓ RCC_OscInitStruct.PLL.PLLQ = 7; // USB/SDIO/Ëæ»úÊý&sup2;úÉúÆ÷µÈµÄÖ÷PLL·ÖƵϵÊý HAL_RCC_OscConfig(&RCC_OscInitStruct); RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; // ϵͳʱÖÓ£º168MHz RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; // AHBʱÖÓ£º 168MHz RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4; // APB1ʱÖÓ£º42MHz RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2; // APB2ʱÖÓ£º84MHz HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5); HAL_RCC_EnableCSS(); // Ê&sup1;ÄÜCSS&sup1;¦ÄÜ£¬ÓÅÏÈÊ&sup1;ÓÃÍâ&sup2;¿¾§Õñ£¬ÄÚ&sup2;¿Ê±ÖÓԴΪ±¸Óà // HAL_RCC_GetHCLKFreq()/1000 1msÖжÏÒ»´Î // HAL_RCC_GetHCLKFreq()/100000 10usÖжÏÒ»´Î // HAL_RCC_GetHCLKFreq()/1000000 1usÖжÏÒ»´Î HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000); // ÅäÖÃ&sup2;¢Æô¶¯ÏµÍ³µÎ´ð¶¨Ê±Æ÷ /* ϵͳµÎ´ð¶¨Ê±Æ÷ʱÖÓÔ´ */ HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK); /* ϵͳµÎ´ð¶¨Ê±Æ÷ÖжÏÓÅÏÈ&frac14;¶ÅäÖà */ HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0); } /** * º¯Êý&sup1;¦ÄÜ: Ö÷º¯Êý. * ÊäÈë&sup2;ÎÊý: ÎÞ * ·µ »Ø Öµ: ÎÞ * ˵ Ã÷: ÎÞ */ int main(void) { /* ¸´Î»ËùÓÐÍâÉ裬³õÊ&frac14;»¯Flash&frac12;Ó¿ÚºÍϵͳµÎ´ð¶¨Ê±Æ÷ */ HAL_Init(); /* ÅäÖÃϵͳʱÖÓ */ SystemClock_Config(); /* ³õÊ&frac14;»¯°´&frac14;üÅäÖà */ KEY_GPIO_Init(); /* ³õÊ&frac14;»¯´®¿ÚÅäÖà */ HMI_USARTx_Init(); /* ³õÊ&frac14;»¯»ô¶û´«¸ÐÆ÷&frac12;Ó¿Ú */ HALL_TIMx_Init(); /* ³õÊ&frac14;»¯¶¨Ê±Æ÷¸÷ͨµÀÊä³ö */ BLDCMOTOR_TIMx_Init(); /* Æô¶¯¶¨Ê±Æ÷ */ HAL_TIM_Base_Start(&htimx_BLDC); /* ³õÊ&frac14;»¯PID&sup2;ÎÊý*/ IncPIDInit(); // UpdateHMI_SM_PID_Param(BLDC_sPID); /* ÔÚ·ÂÕæµÄʱºò&frac12;ûÖ&sup1;¶¨Ê±Æ÷Êä³ö */ __HAL_DBGMCU_FREEZE_TIM8(); while (1) { if(Frame.PageID == PAGE_EX_PID) { switch(Frame.ObjID ) { /* ÉèÖÃÄ¿±êÖµ */ case EX_PID_NUM_POSTAR: BLDC_SetTargetSpd( Frame.Param.Init/10 ); Frame.ObjID = NONEOBJ; break; /* ÉèÖÃPID&sup2;ÎÊýP */ case EX_PID_NUM_POSP: PID_BLDC.Proportion = Frame.Param.Init/ 1000.0f; Frame.ObjID = NONEOBJ; break; /* ÉèÖÃPID&sup2;ÎÊýI */ case EX_PID_NUM_POSI: PID_BLDC.Integral = Frame.Param.Init/ 1000.0f; Frame.ObjID = NONEOBJ; break; /* ÉèÖÃPID&sup2;ÎÊýD */ case EX_PID_NUM_POSD: PID_BLDC.Derivative = Frame.Param.Init/ 1000.0f; Frame.ObjID = NONEOBJ; break; /* È·¶¨°´Å¥£¬Æô¶¯µç»ú */ case EX_PID_BTN_CONFIG: Enable_BLDC(); start_flag = 1; Frame.ObjID = NONEOBJ; break; /* Í£Ö&sup1;°´Å¥£¬Í£Ö&sup1;µç»ú */ case EX_PID_BTN_PAUSE: Disable_BLDC(); start_flag = 0; PID_BLDC.LastError = 0;// Error[-1] PID_BLDC.SumError = 0; Frame.ObjID = NONEOBJ; break; case EX_PID_BTN_UDATE:// ¶¨Ê±ÈÎÎñ£¬ÓÉ´®¿ÚÆÁ¾ö¶¨Ê±&frac14;ä&frac14;ä¸ô UpdateHMI_SM_PID_feedback(0,BLDC_CaptureNumber); UpdateHMI_SM_PID_Param(PID_BLDC); Frame.ObjID = NONEOBJ; break; } } /* Ê&sup1;Äܵç»ú */ if(KEY1_StateRead() == KEY_DOWN) { Enable_BLDC(); start_flag = 1; } /* µç»úÍ£Ö&sup1; */ if(KEY2_StateRead() == KEY_DOWN) { Disable_BLDC(); start_flag = 0; } } } /** * º¯Êý&sup1;¦ÄÜ: PID&sup2;ÎÊý³õÊ&frac14;»¯ * ÊäÈë&sup2;ÎÊý: ÎÞ * ·µ »Ø Öµ: ÎÞ * ˵ Ã÷: ÎÞ */ void IncPIDInit(void) { PID_BLDC.LastError = 0; // Error[-1] PID_BLDC.Proportion = P_DATA; // ±ÈÀý³£Êý Proportional Const PID_BLDC.Integral = I_DATA; // »ý·Ö³£Êý Integral Const PID_BLDC.Derivative = D_DATA; // ΢·Ö³£Êý Derivative Const PID_BLDC.SetPoint = TARGET_SPEED;// É趨Ŀ±êDesired Value } /****************************** ÐÅÏ¢·´À¡º¯Êý **********************************/ ///** // * º¯Êý&sup1;¦ÄÜ£º¸üд®¿ÚÆÁ&frac12;çÃæµÄPID&sup2;ÎÊýºÍÄ¿±êÖµ // * ÊäÈë&sup2;ÎÊý£ºParam_Pos,ËÙ¶È»·µÄPID&frac12;á&sup1;&sup1;ÌåÖ¸Õë // * ·µ »Ø Öµ£ºÎÞ // * ˵ Ã÷£º¸üеÄÊÇĬÈϵÄPID&sup2;ÎÊýºÍÄ¿±êÖµ // */ static void UpdateHMI_SM_PID_Param(PID_Typedef Param_Pos) { float tmp = 0; // /* ¸üд®¿ÚÆÁµÄPID&sup2;ÎÊý,PID&sup2;ÎÊý¶&frac14;ÊÇ·Å´ó1000±¶ */ tmp = ( (float)Param_Pos.Proportion * 1000.0f ); HMI_value_setting("numPosP.val",tmp); tmp = ( (float)Param_Pos.Integral * 1000.0f ); HMI_value_setting("numPosI.val",tmp); tmp = ( (float)Param_Pos.Derivative * 1000.0f ); HMI_value_setting("numPosD.val",tmp); tmp = ( (float)Param_Pos.SetPoint ); HMI_string_setting("numPosTar.txt",tmp); } /** * º¯Êý&sup1;¦ÄÜ£º¸üд®¿ÚÆÁ&frac12;çÃæµÄÊý¾Ý * ÊäÈë&sup2;ÎÊý£ºÎÞ * ·µ »Ø Öµ£ºÎÞ * ˵ Ã÷£º¸üÐÂλÖÃÖµºÍËÙ¶ÈÖµ */ void UpdateHMI_SM_PID_feedback(int32_t CaptureNumber,int32_t RPM) { HMI_string_setting("txtPosition.txt",0); HMI_string_setting("txtSpeed.txt",RPM); /* ·¢ËÍ·´À¡Öµ */ HMI_value_setting("vatmpReal.val",RPM/10); HMI_value_setting("vatmpTarget.val",ROUND_TO_INT32(PID_BLDC.SetPoint/10)); } /******************** Ëٶȱջ· PID ¿ØÖÆÉè&frac14;Æ ***********************************/ /** * º¯Êý&sup1;¦ÄÜ: »¬¶¯ÂË&sup2;¨º¯Êý * ÊäÈë&sup2;ÎÊý: ËÙ¶ÈÖµ(r/min) * ·µ »Ø Öµ: ÂË&sup2;¨ºóµÄËÙ¶ÈÖµ(r/min) * ˵ Ã÷: ¶ÔËÙ¶ÈÖµ&frac12;øÐ묶¯ÂË&sup2;¨´¦Àí,´ó¸ÅÁ÷³Ì: * ¶ÔǰWIN´Î&sup2;ÉÑùµÄËÙ¶ÈֵȡÆ&frac12;¾ùÖµ */ float Avg_speed(float Speed) { int32_t i = 0; float Sum = 0; Avg_Speed[Avg_cnt] =Speed; Avg_cnt++; if(Avg_cnt == WIN) { Avg_cnt = 0; flag = 1; } /* ÔÚ&sup2;ÉÑù´ÎÊýÉÙÓÚn´ÎµÄÇé¿öÏÂ&frac14;ÆËã¾ùÖµ */ if(flag == 0) { for(i = 0; i<Avg_cnt;i++) { Sum += Avg_Speed[i]; } Sum /= (i+1); } /* ÇóµÃǰn´ÎµÄÆ&frac12;¾ùÖµ */ else { for(i = 0; i<WIN;i++) { Sum += Avg_Speed[i]; } Sum /= WIN; } return Sum; } /** * º¯Êý&sup1;¦ÄÜ: ϵͳµÎ´ð¶¨Ê±Æ÷Öжϻص÷º¯Êý * ÊäÈë&sup2;ÎÊý: ÎÞ * ·µ »Ø Öµ: ÎÞ * ˵ Ã÷: ÿ·¢ÉúÒ»´ÎµÎ´ð¶¨Ê±Æ÷ÖжÏ&frac12;øÈë¸Ã»Øµ÷º¯ÊýÒ»´Î */ void HAL_SYSTICK_Callback() { float speed_rpm = 0; int32_t PID_Result = 0; Time_CNT++; /* 100ms &sup2;ÉÑùÖÜÆÚ,¿ØÖÆÖÜÆÚ */ if(Time_CNT >= 100) { Time_CNT = 0; /* »ñÈ¡ËÙ¶ÈÖµ:ÓÉ&sup2;¶»ñµ&frac12;µÄÂö³åÊý³ýÒÔ×ܵÄʱ&frac14;ä Pul/t */ /* BLDCMotorÊÇ4¶Ô&frac14;«,ÐýתһȦÓÐ4¸öÂö³åÐźÅ,3ÏàUVWÐźÅÏß,&sup1;&sup2;12¸öÂö³åÐźÅ, * ÿ¸öÂö³å±ßÑØ&frac14;ÆÊýÒ»´Î,ËùÒÔBLDCMÐýתһȦ,¿ÉÒÔ&sup2;¶»ñµ&frac12;µÄ»ô¶ûÐźÅÊÇ24, * &frac14;ÆÊýÖµ¿ÉÒÔ&frac14;ÆÊýµ&frac12;24.ÿ¸öÐźűßÑØ¶&frac14;»á&sup2;¶»ñµ&frac12;&frac12;Ó¿Ú¶¨Ê±Æ÷µÄCCR1, * ÿ100ms¶ÁÈ¡&sup2;¶»ñµ&frac12;µÄʱ&frac14;äºÍÂö³åÊý,¾Í¿ÉÒԵõ&frac12;µç»úµÄËÙ¶ÈÖµ. */ if(BLDCMotor.Hall_Period == 0)//±ÜÃâ³ýÊýΪ0 { speed_rpm = 0; } else /*Ëٶȵ¥Î»:RPM*/ speed_rpm = (((float)BLDCMotor.Hall_PulNum*60*HALL_TIM_FREQ) / ((float)BLDCMotor.Hall_Period*24)); //¶ÔËÙ¶ÈÖµ×ö»¬¶¯ÂË&sup2;¨´¦Àí BLDC_CaptureNumber = (int32_t)Avg_speed(speed_rpm); BLDCMotor.Hall_Period = 0; BLDCMotor.Hall_PulNum = 0; if(start_flag == 1) { if(MotorDirction == MOTOR_DIR_CCW) BLDC_CaptureNumber = -BLDC_CaptureNumber; /* PID¿ØÖÆ&frac14;ÆËã */ PID_Result = BLDC_SpdPIDCalc(BLDC_CaptureNumber); /* ·&frac12;ÏòÅж¨ */ if(PID_Result<0) { BLDCMotor.Dir = MOTOR_DIR_CCW; BLDCMotor.PWM_Duty = -PID_Result; } else { BLDCMotor.Dir = MOTOR_DIR_CW; BLDCMotor.PWM_Duty = PID_Result; } /* Õ&frac14;¿Õ±ÈÏÞ¶¨ */ if(BLDCMotor.PWM_Duty >=(int32_t)(BLDCMOTOR_TIM_PERIOD - 100)) BLDCMotor.PWM_Duty = (int32_t)(BLDCMOTOR_TIM_PERIOD - 100); /* ¸ù¾Ýµ±Ç°Ô˶¯·&frac12;Ïò,Á¢&frac14;´ÐÞ¸ÄÕ&frac14;¿Õ±È */ BLDCMotor.uwStep = HallSensor_GetPinState(); if(MotorDirction == MOTOR_DIR_CW) { // ¸ù¾Ý˳Ðò±íµÄ&sup1;æÂÉ CW = 7 - CCW; BLDCMotor.uwStep = (uint32_t)7 - BLDCMotor.uwStep; } /* ¸ù¾Ý·&frac12;ÏòÉ趨¶ÔӦͨµÀµÄÕ&frac14;¿Õ±È */ switch(BLDCMotor.uwStep) { case 2: // AÏà case 6: __HAL_TIM_SET_COMPARE(&htimx_BLDC,TIM_CHANNEL_1,BLDCMotor.PWM_Duty); break; case 4: // BÏà case 5: __HAL_TIM_SET_COMPARE(&htimx_BLDC,TIM_CHANNEL_2,BLDCMotor.PWM_Duty); break; case 1: // CÏà case 3: __HAL_TIM_SET_COMPARE(&htimx_BLDC,TIM_CHANNEL_3,BLDCMotor.PWM_Duty); break; } /* µ±»»ÏòµÄʱºò£¬µç»ú¿ÉÄÜ»áÆô¶¯Ê§°Ü£¬ÕâÀïÖØÐÂÆô¶¯Ò»´Î */ if(MotorDirction != BLDCMotor.Dir) { Disable_BLDC(); Enable_BLDC(); } else if(speed_rpm == 0) { Disable_BLDC(); Enable_BLDC(); } } } } /** * º¯ÊýÃû³Æ£ºËٶȱջ·PID¿ØÖÆÉè&frac14;Æ * ÊäÈë&sup2;ÎÊý£ºµ±Ç°¿ØÖÆÁ¿ * ·µ »Ø Öµ£ºÄ¿±ê¿ØÖÆÁ¿ * ˵ Ã÷£ºÎÞ */ int32_t BLDC_SpdPIDCalc(int32_t NextPoint) { } /** * º¯Êý&sup1;¦ÄÜ: ÉèÖÃBLDCÄ¿±êËÙ¶È * ÊäÈë&sup2;ÎÊý: ÎÞ * ·µ »Ø Öµ: ÎÞ * ˵ Ã÷: ÏÞÖÆËÙ¶ÈÔÚãÐÖµ·¶Î§ÄÚ */ void BLDC_SetTargetSpd(int32_t Spd) { if(Spd >= BLDC_SPEED_MAX) Spd = BLDC_SPEED_MAX; if(Spd <= BLDC_SPEED_MIN) Spd = BLDC_SPEED_MIN; PID_BLDC.SetPoint = Spd; }
06-21
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值