欧美极品高清xxxxhd,国产日产欧美最新,无码AV国产东京热AV无码,国产精品人与动性XXX,国产传媒亚洲综合一区二区,四库影院永久国产精品,毛片免费免费高清视频,福利所导航夜趣136

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 2973|回復: 5
打印 上一主題 下一主題
收起左側

51單片機電機驅動及電機速度電流測量程序

[復制鏈接]
跳轉到指定樓層
樓主
ID:688286 發表于 2022-5-5 16:05 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
電機驅動電路使用H橋可逆斬波電路,通過采樣電阻和旋轉編碼器測量電機轉速和電流

單片機代碼如下:
  1. /*
  2. 設計思路
  3. 電機驅動電路:使用H橋可逆斬波電路去驅動電機轉動,該電路可在網上查找學習相關知識。
  4. 電機的調速可通過改變PWM波的占空比實現,當占空比為50%時,電機不轉,
  5.                                                                                                                                                          當占空比大于50%時電機正轉,并且越大轉速越快,但不要超過80%,超過可能會使電路發燙
  6.                                                                                                                                                          當占空比小于50%時電機反轉,并且越小轉速越快,但不要超過20%,超過可能會使電路發燙                       
  7. 測電流是在驅動電路兩個下橋臂和電源地之間加了一個采樣電阻,通過AD轉換讀取采樣電阻電壓得到電流
  8. 測電機轉速是利用電機上的旋轉編碼器,編碼器為96線編碼器,所以電機轉一圈會發出96個脈沖
  9. 使用單片機的外部中斷,設置觸發方式為邊沿觸發,記錄脈沖數
  10. 使用單片機的定時器中斷,每50ms產生一次中斷,在中斷里讀取當前脈沖數,計算轉速,之后脈沖數置0
  11. 根據直流電機的電流與轉矩之間的關系,計算電機的轉矩
  12. 轉矩和扭矩是一個物理量,只是在不同的場合稱呼不同
  13. */
  14. #include "reg52.h"
  15. #include "iic.h"
  16. #include "oled.h"
  17. #include<stdio.h>
  18. #include<intrins.h>
  19. #define uchar unsigned char
  20. #define  PCF8591 0x90    //PCF8591 地址
  21. #define  qCt         12.75
  22. uchar data_byte;
  23. u8 RH,RL,TH,TL,U8FLAG;

  24. sbit PWM1=P1^2;//接IN1 控制正轉

  25. u8 duty = 7 ; //定義占空比,H橋可逆斬波電路在50%占空比時電機不轉,大于50%正轉,小于50%反轉,
  26.                //6表示占空比為70%,不要修改占空比,不同占空比下電機功率不同,導致扭矩計算錯誤
  27. u8 time;
  28. int pluse = 0 ;    //電機編碼器的脈沖數
  29. float Speed = 0.0 ;   //速度

  30. #define  NOP()   _nop_()   /* 定義空指令 */
  31. #define  _Nop()  _nop_()   /*定義空指令*/


  32. sbit     m_SCL=P1^4;       //I2C  時鐘
  33. sbit     m_SDA=P1^3;       //I2C  數據
  34. bit ack;                 /*應答標志位*/
  35.    

  36. /*******************************************************************
  37.                      起動總線函數               
  38. 函數原型: void  Start_I2c();  
  39. 功能:     啟動I2C總線,即發送I2C起始條件.  
  40. ********************************************************************/
  41. void Start_I2c()
  42. {
  43.   m_SDA=1;         /*發送起始條件的數據信號*/
  44.   _Nop();
  45.   m_SCL=1;
  46.   _Nop();        /*起始條件建立時間大于4.7us,延時*/
  47.   _Nop();
  48.   _Nop();
  49.   _Nop();
  50.   _Nop();   
  51.   m_SDA=0;         /*發送起始信號*/
  52.   _Nop();        /* 起始條件鎖定時間大于4μs*/
  53.   _Nop();
  54.   _Nop();
  55.   _Nop();
  56.   _Nop();      
  57.   m_SCL=0;       /*鉗住I2C總線,準備發送或接收數據 */
  58.   _Nop();
  59.   _Nop();
  60. }

  61. /*******************************************************************
  62.                       結束總線函數               
  63. 函數原型: void  Stop_I2c();  
  64. 功能:     結束I2C總線,即發送I2C結束條件.  
  65. ********************************************************************/
  66. void Stop_I2c()
  67. {
  68.   m_SDA=0;      /*發送結束條件的數據信號*/
  69.   _Nop();       /*發送結束條件的時鐘信號*/
  70.   m_SCL=1;      /*結束條件建立時間大于4μs*/
  71.   _Nop();
  72.   _Nop();
  73.   _Nop();
  74.   _Nop();
  75.   _Nop();
  76.   m_SDA=1;      /*發送I2C總線結束信號*/
  77.   _Nop();
  78.   _Nop();
  79.   _Nop();
  80.   _Nop();
  81. }

  82. /*******************************************************************
  83.                  字節數據發送函數               
  84. 函數原型: void  SendByte(UCHAR c);
  85. 功能:     將數據c發送出去,可以是地址,也可以是數據,發完后等待應答,并對
  86.           此狀態位進行操作.(不應答或非應答都使ack=0)     
  87.            發送數據正常,ack=1; ack=0表示被控器無應答或損壞。
  88. ********************************************************************/
  89. void  SendByte(unsigned char  c)
  90. {
  91. unsigned char  BitCnt;

  92. for(BitCnt=0;BitCnt<8;BitCnt++)  /*要傳送的數據長度為8位*/
  93.     {
  94.      if((c<<BitCnt)&0x80)m_SDA=1;   /*判斷發送位*/
  95.        else  m_SDA=0;               
  96.      _Nop();
  97.      m_SCL=1;               /*置時鐘線為高,通知被控器開始接收數據位*/
  98.       _Nop();
  99.       _Nop();             /*保證時鐘高電平周期大于4μs*/
  100.       _Nop();
  101.       _Nop();
  102.       _Nop();         
  103.      m_SCL=0;
  104.     }
  105.    
  106.     _Nop();
  107.     _Nop();
  108.     m_SDA=1;                /*8位發送完后釋放數據線,準備接收應答位*/
  109.     _Nop();
  110.     _Nop();   
  111.     m_SCL=1;
  112.     _Nop();
  113.     _Nop();
  114.     _Nop();
  115.     if(m_SDA==1)ack=0;     
  116.        else ack=1;        /*判斷是否接收到應答信號*/
  117.     m_SCL=0;
  118.     _Nop();
  119.     _Nop();
  120. }

  121. /*******************************************************************
  122.                  字節數據接收函數               
  123. 函數原型: UCHAR  RcvByte();
  124. 功能:        用來接收從器件傳來的數據,并判斷總線錯誤(不發應答信號),
  125.           發完后請用應答函數應答從機。  
  126. ********************************************************************/   
  127. unsigned char   RcvByte()
  128. {
  129.   unsigned char  retc;
  130.   unsigned char  BitCnt;
  131.   
  132.   retc=0;
  133.   m_SDA=1;                     /*置數據線為輸入方式*/
  134.   for(BitCnt=0;BitCnt<8;BitCnt++)
  135.       {
  136.         _Nop();           
  137.         m_SCL=0;                  /*置時鐘線為低,準備接收數據位*/
  138.         _Nop();
  139.         _Nop();                 /*時鐘低電平周期大于4.7μs*/
  140.         _Nop();
  141.         _Nop();
  142.         _Nop();
  143.         m_SCL=1;                  /*置時鐘線為高使數據線上數據有效*/
  144.         _Nop();
  145.         _Nop();
  146.         retc=retc<<1;
  147.         if(m_SDA==1)retc=retc+1;  /*讀數據位,接收的數據位放入retc中 */
  148.         _Nop();
  149.         _Nop();
  150.       }
  151.   m_SCL=0;   
  152.   _Nop();
  153.   _Nop();
  154.   return(retc);
  155. }

  156. /********************************************************************
  157.                      應答子函數
  158. 函數原型:  void Ack_I2c(bit a);
  159. 功能:      主控器進行應答信號(可以是應答或非應答信號,由位參數a決定)
  160. ********************************************************************/
  161. void Ack_I2c(bit a)
  162. {
  163.   
  164.   if(a==0)m_SDA=0;              /*在此發出應答或非應答信號 */
  165.   else m_SDA=1;
  166.   _Nop();
  167.   _Nop();
  168.   _Nop();      
  169.   m_SCL=1;
  170.   _Nop();
  171.   _Nop();                    /*時鐘低電平周期大于4μs*/
  172.   _Nop();
  173.   _Nop();
  174.   _Nop();  
  175.   m_SCL=0;                     /*清時鐘線,鉗住I2C總線以便繼續接收*/
  176.   _Nop();
  177.   _Nop();   
  178. }


  179. /*******************************************************************
  180. DAC 變換, 轉化函數               
  181. *******************************************************************/
  182. bit DACconversion(unsigned char sla,unsigned char c,  unsigned char Val)
  183. {
  184.    Start_I2c();              //啟動總線
  185.    SendByte(sla);            //發送器件地址
  186.    if(ack==0)return(0);
  187.    SendByte(c);              //發送控制字節
  188.    if(ack==0)return(0);
  189.    SendByte(Val);            //發送DAC的數值  
  190.    if(ack==0)return(0);
  191.    Stop_I2c();               //結束總線
  192.    return(1);
  193. }

  194. /*******************************************************************
  195. ADC發送字節[命令]數據函數               
  196. *******************************************************************/
  197. bit ISendByte(unsigned char sla,unsigned char c)
  198. {
  199.    Start_I2c();              //啟動總線
  200.    SendByte(sla);            //發送器件地址
  201.    if(ack==0)return(0);
  202.    SendByte(c);              //發送數據
  203.    if(ack==0)return(0);
  204.    Stop_I2c();               //結束總線
  205.    return(1);
  206. }
  207. unsigned char IRcvByte(unsigned char sla)
  208. {  unsigned char c;

  209.    Start_I2c();          //啟動總線
  210.    SendByte(sla+1);      //發送器件地址
  211.    if(ack==0)return(0);
  212.    c=RcvByte();          //讀取數據0

  213.    Ack_I2c(1);           //發送非就答位
  214.    Stop_I2c();           //結束總線
  215.    return 0;
  216. }
  217. float Get_Current(unsigned char s)      //讀取電流
  218. {
  219.         float t ;
  220.         t = IRcvByte(s) ;
  221.         if(Speed != 0 )
  222.         {if(Speed <= 250)
  223.                 {
  224.         t = 7.8 -0.027*Speed;
  225.         return t ;
  226.                 }else
  227.                 {return 0.1;}
  228.         }
  229.         else
  230.         {
  231.          return 0 ;
  232.         }
  233. }

  234. void int0() interrupt 0 using 0//外部中斷0的執行程序。
  235. {                                                            //interrupt 0指外部中斷0 using 0指第0組寄存器                                                 
  236.         pluse++ ;
  237. }

  238. void timer0_init()
  239. {
  240.         TMOD=0x01;//定時器0工作方式1 定時器1工作方式1
  241.        
  242.         TH0=0xff;
  243.         TL0=0xa3;//定時50ms
  244.        
  245.         TH1=0x4b;
  246.         TL1=0xff;//定時0.1ms
  247.        
  248.         IT0=1;//外部中斷0為跳變沿觸發方式   
  249.        
  250.   EA=1;//開總中斷
  251.   EX0=1;//打開外部中斷0   
  252.        
  253.         ET0=1;//打開定時器0中斷開關
  254.         TR0=1;//打開定時器0運行開關
  255.         ET1=1;//打開定時器0中斷開關
  256.         TR1=1;//打開定時器0運行開關
  257.         PT1 = 0 ;
  258.         PX0 = 1 ;
  259.         PT0 = 1 ;
  260.        
  261. }
  262. void tim0() interrupt 1
  263. {
  264.        TR0=0;                //賦初值時,關閉定時器
  265.        TH0=0xff;       
  266.        TL0=0xa3;        //定時0.1ms
  267.        TR0=1;                //打開定時器
  268.        time++;
  269.        
  270.        if(time>=10) //10*0.1ms=1ms   pwm波一個周期1ms,即1khz
  271.                          {
  272.                                  time=0;       
  273.                          }
  274.        if(time<=duty) PWM1=1;                //點空比70%
  275.        else PWM1=0;   
  276. }

  277. void tim1() interrupt 3   //定時器1的中斷服務函數
  278. {
  279.            EX0 = 0 ;//關閉外部中斷,停止記錄脈沖數
  280.            TR1=0;                //賦初值時,關閉定時器
  281.      TH1=0x4b;       
  282.      TL1=0xff;        //定時50ms
  283.      TR1=1;                //打開定時器
  284.            Speed = pluse*12.5 ;  //將脈沖數轉化為轉速,編碼器為96線,轉一圈輸出96個脈沖,所以轉速=脈沖數/50ms/96*60   ,單位轉/分鐘
  285.            pluse = 0 ;
  286.                  EX0 = 1 ;//打開外部中斷
  287. }


  288. void main()  //主循環
  289. {
  290.   char a[6] ;

  291.   float Current=0.0 ;
  292.         float T = 0.0 ;
  293.         OLED_Init();   //初始化屏幕
  294.         OLED_Clear();
  295.         OLED_ShowString(0,0,"Speed:",12);//顯示字符
  296.         OLED_ShowString(95,0,"r/m",12);
  297.         OLED_ShowString(0,3,"I:",12);
  298.         OLED_ShowString(95,3,"A",12);
  299.         OLED_ShowString(0,5,"T:",12);
  300.         OLED_ShowString(95,5,"N*m",12);
  301.         timer0_init();  //配置定時器和外部中斷
  302.        
  303.         while(1)
  304.         {
  305.           sprintf(a,"%.1f ",Speed);  //顯示速度
  306.                 OLED_ShowString(50,0,a,12);
  307.                
  308.   
  309.                   if(ISendByte(PCF8591,0x40))
  310.                         {
  311.                     Current= Get_Current(PCF8591);  
  312.                         }
  313.                         T =  Current*qCt;      //電機扭矩=電流*轉矩常數*磁通量
  314.                
  315.                 sprintf(a,"%.2f  ",Current);  //顯示電流
  316.                 OLED_ShowString(40,3,a,12);
  317.                        
  318.        
  319.                 sprintf(a,"%.2f  ",T);  //顯示扭矩
  320.                 OLED_ShowString(40,5,a,12);
  321.         }
  322.        
  323. }
復制代碼



Keil代碼下載: 電機轉速電流.zip (350.44 KB, 下載次數: 42)

評分

參與人數 1黑幣 +10 收起 理由
admin + 10 共享資料的黑幣獎勵!

查看全部評分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏2 分享淘帖 頂 踩
回復

使用道具 舉報

沙發
ID:262 發表于 2022-5-5 20:39 | 只看該作者
樓主你好 能分享一下原理圖嗎?這個是怎么測電流的?用的什么芯片?
回復

使用道具 舉報

板凳
ID:688286 發表于 2022-5-5 23:00 | 只看該作者
heicad 發表于 2022-5-5 20:39
樓主你好 能分享一下原理圖嗎?這個是怎么測電流的?用的什么芯片?

用的采樣電阻,在GND和下橋臂之間接一個0.05的采樣電阻,把采樣電阻上的壓降放大20倍,ADC采樣之后的電壓就是電流

評分

參與人數 1黑幣 +20 收起 理由
admin + 20 回帖助人的獎勵!

查看全部評分

回復

使用道具 舉報

地板
ID:56665 發表于 2022-5-6 08:37 | 只看該作者
電機扭矩=電流*轉矩常數*磁通量,這個公式中轉矩常數是馬達規格書上有注明嗎,還有磁通量怎么測試的
回復

使用道具 舉報

5#
ID:77675 發表于 2022-5-6 12:36 | 只看該作者
能分享一下原理圖嗎?
回復

使用道具 舉報

6#
ID:1058055 發表于 2022-12-17 17:33 | 只看該作者
heicad 發表于 2022-5-5 20:39
樓主你好 能分享一下原理圖嗎?這個是怎么測電流的?用的什么芯片?

應該是L298或者L297
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表