[电机控制] 一个可行的 BLDC 原型设计制作和展示方案——ATmega328P + L6234 + BLDC + Arduino IDE

[复制链接]
 楼主| MianQi 发表于 2024-5-11 09:05 | 显示全部楼层 |阅读模式
本帖最后由 MianQi 于 2024-5-25 11:47 编辑

整个方案的组成:ATmega328P + L6234 + BLDC + Arduino IDE
1、MCU 选用 Arduino UNO R3
2、电动机驱动芯片选用 ST 的 L6234 双列直插 20 脚
3、电源:12v

这是整套方案的实物照:


这是电动机:


这是驱动芯片 L6234 及其外围电路:

参考的例程在这里-https://simple-circuit.com/arduino-brushless-dc-motor-control-l6234/

但是例程中的示例程序在Arduino IDE中能编译通过,电动机却不能正常运行。
于是开始查找原因。

很快发现,设置部分没有开启全局中断,加上这一句
sei(); //Enable global interrupt之后,电动机能转,但是不能连续转,从这段程序中受到启发:
i= 50000;// Motor start
while(i> 100){
   delayMicroseconds(i);
   bldc_move();
   bldc_step++;
   bldc_step%= 6;
   i= i - 20;
}
,在主循环中加入两句“delayMicroseconds(500);和一句“delayMicroseconds(3500);,电动机依然不能连续运转,于是开始查MCU –ATmega328P 的数据手册,最终发现,要在检测反向电动势的6个函数中的三个下降沿触发中加入“ACSR= 0x02;,给ACSRAnalogComparator Control and StatusRegiste)寄存器一个明确的赋值。现在,电动机能连续运转,但是重启和调速仍然有问题,最终发现针对这套实际的硬件,要修改常量“PWM_MIN_DUTY,从原来的“50”逐步试出来要改为“100”才行。

项目的演示视频在这里- https://www.bilibili.com/video/BV1iz421m7EL/
分步骤讲解在这里:
1、https://www.bilibili.com/video/BV1rM4m1r7v2/
2、https://www.bilibili.com/video/BV15y411Y7UC/
3、https://www.bilibili.com/video/BV1ry411a7BP/
4、https://www.bilibili.com/video/BV1LE421F7gx/
5、https://www.bilibili.com/video/BV1rm421K71w/
6、https://www.bilibili.com/video/BV1dJ4m1A7ef/
7、https://www.bilibili.com/video/BV1GT421S7uo/
8、https://www.bilibili.com/video/BV1vM4m1k7vZ/
9、https://www.bilibili.com/video/BV1P1421q7nn/






本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
呐咯密密 发表于 2024-5-13 13:32 | 显示全部楼层
看起来很不错啊
xuanhuanzi 发表于 2024-5-19 15:46 | 显示全部楼层

这个芯片好用吗

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
xuanhuanzi 发表于 2024-5-19 15:48 | 显示全部楼层
看到分享的链接了,学习一下,非常赞。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
 楼主| MianQi 发表于 2024-5-20 15:38 | 显示全部楼层

从数据手册的说明来看,这个芯片是专为 BLDC 设计地。从外围电路的搭建以及管脚接线的实际经验来看,用起来的确很方便。
shenxiaolin 发表于 2024-6-14 16:08 | 显示全部楼层
有代码么?抄一下代码,
哈哈哈
 楼主| MianQi 发表于 2024-6-17 06:34 | 显示全部楼层
Arduino IDE 版本的是一个单独的文件:
  1. /*
  2. * Sensorless brushless DC (BLDC) motor control with Arduino UNO and L6234 driver.
  3. */


  4. #define SPEED_UP          A0
  5. #define SPEED_DOWN        A1
  6. #define PWM_MAX_DUTY      255
  7. #define PWM_MIN_DUTY      50
  8. #define PWM_START_DUTY    100

  9. byte bldc_step = 0, motor_speed;
  10. unsigned int i;

  11. void setup() {
  12.   DDRD  |= 0x38;           // Configure pins 3, 4 and 5 as outputs
  13.   PORTD  = 0x00;
  14.   DDRB  |= 0x0E;           // Configure pins 9, 10 and 11 as outputs
  15.   PORTB  = 0x31;
  16.   // Timer1 module setting: set clock source to clkI/O / 1 (no prescaling)
  17.   TCCR1A = 0;
  18.   TCCR1B = 0x01;
  19.   // Timer2 module setting: set clock source to clkI/O / 1 (no prescaling)
  20.   TCCR2A = 0;
  21.   TCCR2B = 0x01;
  22.   // Analog comparator setting
  23.   ACSR = 0x10;           // Disable and clear (flag bit) analog comparator interrupt

  24.   pinMode(SPEED_UP,   INPUT_PULLUP);
  25.   pinMode(SPEED_DOWN, INPUT_PULLUP);

  26.   sei();
  27. }

  28. // Analog comparator ISR
  29. ISR (ANALOG_COMP_vect) {
  30.   // BEMF debounce
  31.   for(int i = 0; i < 10; i++) {
  32.     if(bldc_step & 1){
  33.       if(!(ACSR & 0x20)) i -= 1;
  34.       } else {
  35.          if((ACSR & 0x20)) i -= 1;
  36.         }
  37.     }
  38.   bldc_move();
  39.   bldc_step++;
  40.   bldc_step %= 6;
  41.   }
  42.   
  43. void bldc_move(){
  44.   // BLDC motor commutation function
  45.   switch(bldc_step){
  46.     case 0:
  47.     AH_BL();
  48.     BEMF_C_RISING();
  49.     break;
  50.     case 1:
  51.     AH_CL();
  52.     BEMF_B_FALLING();
  53.     break;
  54.     case 2: BH_CL();
  55.     BEMF_A_RISING();
  56.     break;
  57.     case 3: BH_AL();
  58.     BEMF_C_FALLING();
  59.     break; case 4:
  60.     CH_AL();
  61.     BEMF_B_RISING();
  62.     break;
  63.     case 5:
  64.     CH_BL();
  65.     BEMF_A_FALLING();
  66.     break;
  67.     }
  68.   }
  69.   
  70. void loop() {
  71.   SET_PWM_DUTY(PWM_START_DUTY); // Setup starting PWM with duty cycle = PWM_START_DUTY
  72.   i = 5000; // Motor start

  73.   while(i > 100) {
  74.     delayMicroseconds(i);
  75.     bldc_move();
  76.     //delay(10);
  77.     bldc_step++;
  78.     bldc_step %= 6;
  79.     i = i - 20;
  80.   }

  81.   motor_speed = PWM_START_DUTY;
  82.   ACSR |= 0x08;                    // Enable analog comparator interrupt
  83.   
  84.   while(1) {
  85.     while(!(digitalRead(SPEED_UP)) && motor_speed < PWM_MAX_DUTY){
  86.       motor_speed++;
  87.       SET_PWM_DUTY(motor_speed);
  88.       delay(100);
  89.       }
  90.     while(!(digitalRead(SPEED_DOWN)) && motor_speed > PWM_MIN_DUTY){
  91.       motor_speed--;
  92.       SET_PWM_DUTY(motor_speed);
  93.       delay(100);
  94.     }
  95.   }
  96. }

  97. void BEMF_A_RISING(){
  98.   ADCSRB = (0 << ACME);    // Select AIN1 as comparator negative input
  99.   ACSR |= 0x03;            // Set interrupt on rising edge
  100. }
  101. void BEMF_A_FALLING(){
  102.   ADCSRB = (0 << ACME);    // Select AIN1 as comparator negative input
  103.   ACSR &= ~0x01;           // Set interrupt on falling edge
  104. }
  105. void BEMF_B_RISING(){
  106.   ADCSRA = (0 << ADEN);   // Disable the ADC module
  107.   ADCSRB = (1 << ACME);
  108.   ADMUX = 2;              // Select analog channel 2 as comparator negative input
  109.   ACSR |= 0x03;
  110. }
  111. void BEMF_B_FALLING(){
  112.   ADCSRA = (0 << ADEN);   // Disable the ADC module
  113.   ADCSRB = (1 << ACME);
  114.   ADMUX = 2;              // Select analog channel 2 as comparator negative input
  115.   ACSR &= ~0x01;
  116. }
  117. void BEMF_C_RISING(){
  118.   ADCSRA = (0 << ADEN);   // Disable the ADC module
  119.   ADCSRB = (1 << ACME);
  120.   ADMUX = 3;              // Select analog channel 3 as comparator negative input
  121.   ACSR |= 0x03;
  122. }
  123. void BEMF_C_FALLING(){
  124.   ADCSRA = (0 << ADEN);   // Disable the ADC module
  125.   ADCSRB = (1 << ACME);
  126.   ADMUX = 3;              // Select analog channel 3 as comparator negative input
  127.   ACSR &= ~0x01;
  128. }

  129. void AH_BL(){
  130.   PORTB  =  0x04;
  131.   PORTD &= ~0x18;
  132.   PORTD |=  0x20;
  133.   TCCR1A =  0;            // Turn pin 11 (OC2A) PWM ON (pin 9 & pin 10 OFF)
  134.   TCCR2A =  0x81;         //
  135. }
  136. void AH_CL(){
  137.   PORTB  =  0x02;
  138.   PORTD &= ~0x18;
  139.   PORTD |=  0x20;
  140.   TCCR1A =  0;            // Turn pin 11 (OC2A) PWM ON (pin 9 & pin 10 OFF)
  141.   TCCR2A =  0x81;         //
  142. }
  143. void BH_CL(){
  144.   PORTB  =  0x02;
  145.   PORTD &= ~0x28;
  146.   PORTD |=  0x10;
  147.   TCCR2A =  0;            // Turn pin 10 (OC1B) PWM ON (pin 9 & pin 11 OFF)
  148.   TCCR1A =  0x21;         //
  149. }
  150. void BH_AL(){
  151.   PORTB  =  0x08;
  152.   PORTD &= ~0x28;
  153.   PORTD |=  0x10;
  154.   TCCR2A =  0;            // Turn pin 10 (OC1B) PWM ON (pin 9 & pin 11 OFF)
  155.   TCCR1A =  0x21;         //
  156. }
  157. void CH_AL(){
  158.   PORTB  =  0x08;
  159.   PORTD &= ~0x30;
  160.   PORTD |=  0x08;
  161.   TCCR2A =  0;            // Turn pin 9 (OC1A) PWM ON (pin 10 & pin 11 OFF)
  162.   TCCR1A =  0x81;         //
  163. }
  164. void CH_BL(){
  165.   PORTB  =  0x04;
  166.   PORTD &= ~0x30;
  167.   PORTD |=  0x08;
  168.   TCCR2A =  0;            // Turn pin 9 (OC1A) PWM ON (pin 10 & pin 11 OFF)
  169.   TCCR1A =  0x81;         //
  170. }

  171. void SET_PWM_DUTY(byte duty){
  172.   if(duty < PWM_MIN_DUTY)
  173.     duty = PWM_MIN_DUTY;
  174.   if(duty > PWM_MAX_DUTY)
  175.     duty  = PWM_MAX_DUTY;
  176.   OCR1A  = duty;                   // Set pin 9  PWM duty cycle
  177.   OCR1B  = duty;                   // Set pin 10 PWM duty cycle
  178.   OCR2A  = duty;                   // Set pin 11 PWM duty cycle
  179. }
 楼主| MianQi 发表于 2024-6-17 06:37 | 显示全部楼层
Microchip Studio 版本的程序由四个文件组成:
main.c main.h bldc.c bldc.h

main.c
  1. /*
  2. * main.c
  3. */
  4. #ifndef        F_CPU
  5. #define F_CPU 16000000ul
  6. #endif

  7. #include "main.h"

  8. #include <avr/cpufunc.h>
  9. #include <avr/io.h>
  10. #include <avr/interrupt.h>
  11. #include <util/delay.h>
  12. #include "bldc.h"


  13. #define PWM_MAX_DUTY      250
  14. #define PWM_MIN_DUTY      50
  15. //#define PWM_MIN_DUTY      100
  16. #define PWM_START_DUTY    100

  17. unsigned int bldc_step = 0;
  18. volatile unsigned int value_pinc = 0;
  19. volatile unsigned char motor_speed = 0;
  20. unsigned int delay_ms_speed = 10;        //10-35ms = 10000-35000us

  21. void motor_start(void);
  22. void motor_restart(void);
  23. void bldc_move(void);

  24. int main(void)
  25. {
  26.     /* Replace with your application code */
  27.         init_Timer0();
  28.         init_ADC();
  29.         init_UART();
  30.         init_GPIO();
  31.         init_Timer1();
  32.         init_Timer2();
  33.        
  34.         // Analog comparator setting - ACSR – Analog Comparator Control and Status Registe
  35.         // ACD ACBG ACO ACI ACIE ACIC ACIS1 ACIS0
  36.         // Bit 4 – ACI: Analog Comparator Interrupt Flag - ACI is cleared by writing a logic one to the flag.
  37.         //ACSR   = 0x10;           // Disable and clear (flag bit) analog comparator interrupt
  38.        
  39.         ACSR |= 0x08; // Enable analog comparator interrupt - Bit 3 – ACIE: Analog Comparator Interrupt Enable
  40.        
  41.         //motor_speed = PWM_START_DUTY;
  42.         //SET_PWM_DUTY(motor_speed);
  43.        
  44.         //Enable PCINT
  45.         PCICR = 0x02;
  46.         PCMSK1 = 0x03;
  47.                
  48.         sei();        // Enable global interrupt
  49.        
  50.         motor_start();
  51.        
  52.     while (1)
  53.     {
  54.                 //unsigned char i = PINC0;
  55.                 ///* Insert nop for synchronization*/
  56.                 //_NOP();
  57.                 //unsigned char j = PINC1;
  58.                 ///* Insert nop for synchronization*/
  59.                 //_NOP();
  60.                 ////TX(motor_speed);
  61.                 ////while(!PINC0){
  62.                 //while((!i) && (motor_speed < PWM_MAX_DUTY)){
  63.                         //motor_speed++;
  64.                         //SET_PWM_DUTY(motor_speed);
  65.                         ////delay(1);
  66.                         ////_delay_us(500);
  67.                 //}
  68.                 ////while(!PINC1){
  69.                 //while((!j) && (motor_speed > PWM_MIN_DUTY)){
  70.                         //motor_speed--;
  71.                         //SET_PWM_DUTY(motor_speed);
  72.                         ////delay(1);
  73.                         ////_delay_us(500);
  74.                 //}
  75.                 //SET_PWM_DUTY(motor_speed);
  76.                 //motor_restart();
  77.                 bldc_move();
  78.                 //_delay_us(3500);
  79.                 //_delay_ms(10);
  80.                 _delay_us(10000);
  81.                 for(unsigned int i = 0; i < motor_speed / 10; ++i) {
  82.                         //_delay_ms(1);
  83.                         _delay_us(10);
  84.                 }
  85.                
  86.                 bldc_step++;
  87.                 bldc_step %= 6;
  88.     }
  89. }

  90. void init_GPIO(void){
  91.         DDRB  |= 0x0E;  // Configure UNO pins 9, 10 and 11 as outputs
  92.         PORTB  = 0x00;
  93.         DDRD  |= 0x38;  // Configure UNO pins 3, 4 and 5 as outputs
  94.         PORTD  = 0x00;
  95.         DDRC  &= 0xFC;        // Configure UNO pins A0(D14), A1(D15) as inputs
  96.         PORTC |= 0x03;        // Set pins A0 and A1 input_pullup
  97. }

  98. ISR (PCINT1_vect) {
  99.         value_pinc = PINC & 0x03;
  100.         if(value_pinc == 0x01) {
  101.                 //motor_speed++;
  102.                 motor_speed += 10;
  103.                 } else if(value_pinc == 0x02) {
  104.                 //motor_speed--;
  105.                 motor_speed -= 10;
  106.         }
  107.         motor_restart();
  108. }

  109. // Timer/Counter0 overflow ISR - Vector program address - 0x0020
  110. ISR (TIMER0_OVF_vect) {
  111.         //TX('A');
  112.         ++counter_adc;
  113.         if(counter_adc >= 61) {
  114.                 //ADCSRA |= 0b01000000;        // Bit 6 – ADSC: ADC Start Conversion
  115.                 ADCSRA = 0x8D | (1<<ADSC);
  116.                 counter_adc = 0;
  117.                 } else {
  118.                 ;
  119.         }
  120. }

  121. // ADC ISR -  ADC conversion complete - 0x002A
  122. ISR (ADC_vect) {
  123.         unsigned int temp = ADC;        // 0 - 1023
  124.         temp /= 4;        // 0 - 254
  125.         motor_speed = temp;
  126.         //motor_speed = ADCH;
  127.         //TX(motor_speed);
  128.         //counter_adc = 0;
  129.         //SET_PWM_DUTY(motor_speed);
  130. }

  131. // Analog comparator ISR - Vector program address - 0x002E
  132. ISR (ANALOG_COMP_vect) {
  133.         // BEMF debounce
  134.         for(unsigned int i = 0; i < 10; i++) {
  135.                 if(bldc_step & 1){
  136.                         if(!(ACSR & 0x20)) i -= 1;
  137.                 }
  138.                 else {
  139.                         if((ACSR & 0x20))  i -= 1;
  140.                 }
  141.         }
  142.         //bldc_move();
  143.         //_delay_us(500);
  144.         //_delay_ms(6);
  145.         bldc_step++;
  146.         bldc_step %= 6;
  147. }

  148. void init_Timer0(void) {
  149.         // Timer0 module used for ADC sampling frequency
  150.         TCCR0A = 0x00;        //Timer/Counter Mode of Operation = Normal
  151.         // Timer0 module setting: set clock source to clkI/O / 1024 (from prescaler)
  152.         TCCR0B = 0b00000101;        //16MHz / 1024 / 256 = 61 (microsecond)
  153.         // CS02 CS01 CS00 = 101
  154.         // Timer/Counter0 Overflow Interrupt Enable = TOIE0
  155.         TIMSK0 = 0x01;
  156. }

  157. void init_ADC() {
  158.         // ADMUX – ADC Multiplexer Selection Register
  159.         //   Bit         7           6         5 4        3         2          1           0
  160.         //(0x7C) REFS1 REFS0 ADLAR – MUX3 MUX2 MUX1 MUX0
  161.         ADMUX = 0x40;        // AVCC with external capacitor at AREF pin | ADC0
  162.         //DDRC &= ~0b00000001;
  163.         // ADCSRA – ADC Control and Status Register A
  164.         //   Bit        7         6           5        4         3           2         1           0
  165.         //(0x7A) ADEN ADSC ADATE ADIF ADIE ADPS2 ADPS1 ADPS0
  166.         ADCSRA = 0x8D;        // ADC Enable | single conversion mode |  Bit 3 – ADIE: ADC Interrupt Enable
  167.         // Bits 2:0 – ADPS2:0: ADC Prescaler Select Bits
  168.         //ADCSRA |= 0b00000101;        // Division Factor - 32
  169.                
  170.         //The ADLAR bit in ADMUX, and the MUXn bits in ADMUX affect the way the result is read from the registers.
  171.         //If ADLAR is set, the result is left adjusted.
  172.         //if the result is left adjusted and no more than 8-bit precision is required, it is sufficient to read ADCH
  173.         //ADMUX |= 1<<ADLAR;
  174. }

  175. void init_UART(void) {
  176.         UCSR0A = 0b00000000; //single transmission speed, multiprocessor disabled
  177.         UCSR0B = 0b00011000; //enable Rx & Tx
  178.         UCSR0C = 0b00000110; //asynchronous, no parity, 1 stop, 8 bits
  179.         UBRR0 = 103;        //load the value for 9600 bps baud rate into whole UBRR register
  180. }

  181. void init_Timer1(void) {
  182.         // Timer1 module setting: set clock source to clkI/O / 1 (no prescaling)
  183.         TCCR1A = 0;
  184.         TCCR1B = 0x01;
  185. }

  186. void init_Timer2(void) {
  187.         // Timer2 module setting: set clock source to clkI/O / 1 (no prescaling)
  188.         TCCR2A = 0;
  189.         TCCR2B = 0x01;
  190. }

  191. void TX(unsigned char TXData) {
  192.         //do nothing until UDR0 is ready for more data to be written to it; wait for USART UDRE flag
  193.         while ((UCSR0A & (1 << UDRE0)) == 0) {};
  194.         //when flag is set send data by placing the byte into UDR0
  195.         UDR0 = TXData;
  196. }

  197. void SET_PWM_DUTY(unsigned char duty){
  198.         if(duty < PWM_MIN_DUTY)
  199.         duty  = PWM_MIN_DUTY;
  200.         if(duty > PWM_MAX_DUTY)
  201.         duty  = PWM_MAX_DUTY;
  202.         OCR1A = duty;                   // Set pin 9  PWM duty cycle
  203.         OCR1B = duty;                   // Set pin 10 PWM duty cycle
  204.         OCR2A = duty;                   // Set pin 11 PWM duty cycle
  205. }

  206. void bldc_move(){        // BLDC motor commutation function
  207.         switch(bldc_step){
  208.                 case 0:
  209.                 AH_BL();
  210.                 BEMF_C_RISING();
  211.                 break;
  212.                 case 1:
  213.                 AH_CL();
  214.                 BEMF_B_FALLING();
  215.                 break;
  216.                 case 2:
  217.                 BH_CL();
  218.                 BEMF_A_RISING();
  219.                 break;
  220.                 case 3:
  221.                 BH_AL();
  222.                 BEMF_C_FALLING();
  223.                 break;
  224.                 case 4:
  225.                 CH_AL();
  226.                 BEMF_B_RISING();
  227.                 break;
  228.                 case 5:
  229.                 CH_BL();
  230.                 BEMF_A_FALLING();
  231.                 break;
  232.         }
  233. }

  234. void motor_start(void){
  235.         SET_PWM_DUTY(PWM_START_DUTY);
  236.         //unsigned int i = 5000;
  237.         unsigned int i = 5000;
  238.         while(i > 100) {
  239.                 ////_delay_us(i);
  240.                 //for(unsigned int j=i; j > 0; --j){
  241.                         ////_delay_us(1);
  242.                         //_NOP();
  243.                         //_NOP();
  244.                 //}
  245.                
  246.                 bldc_move();
  247.                 _delay_ms(6);
  248.                 bldc_step++;
  249.                 bldc_step %= 6;
  250.                 i = i - 20;
  251.         }
  252. }

  253. void motor_restart(void) {
  254.         SET_PWM_DUTY(motor_speed);
  255.         unsigned int i = 5000;
  256.         bldc_move();
  257.         _delay_ms(6);
  258.         bldc_step++;
  259.         bldc_step %= 6;
  260.         i = i - 20;
  261. }
 楼主| MianQi 发表于 2024-6-17 06:38 | 显示全部楼层
main.h
  1. /*
  2. * main.h
  3. */


  4. #ifndef MAIN_H_
  5. #define MAIN_H_

  6. #ifndef        F_CPU
  7. #define F_CPU 16000000ul
  8. #endif

  9. #include <util/delay.h>

  10. volatile unsigned int counter_adc = 0;


  11. void init_ADC(void);
  12. void init_UART(void);
  13. void init_Timer0(void);
  14. void init_GPIO(void);
  15. void init_Timer1(void);
  16. void init_Timer2(void);

  17. void TX(unsigned char TXData);

  18. void SET_PWM_DUTY(unsigned char duty);


  19. #endif /* MAIN_H_ */
 楼主| MianQi 发表于 2024-6-17 06:39 | 显示全部楼层
bldc.c
  1. /*
  2. * bldc.c
  3. */

  4. #include <avr/io.h>
  5. //#include <util/delay.h>
  6. #include "bldc.h"



  7. void BEMF_A_RISING(){
  8.         ADCSRB = (0 << ACME);   // Select AIN1(PD7-UNO_pin_7) as comparator negative input
  9.         ACSR |= 0x03;           // Set interrupt on rising edge
  10.         //ADCSRA |= (1<<ADEN);        // Enable the ADC module
  11. }
  12. void BEMF_A_FALLING(){
  13.         ADCSRB = (0 << ACME);   // Select AIN1(PD7-UNO_pin_7) as comparator negative input
  14.         ACSR &= ~0x01;          // Set interrupt on falling edge
  15.         //ACSR |= 0x02;
  16.         //ADCSRA |= (1<<ADEN);        // Enable the ADC module
  17.         ACSR = 0x02;
  18. }
  19. void BEMF_B_RISING(){
  20.         ADCSRA = (0 << ADEN); // Disable the ADC module
  21.         //ADCSRA &= 0x7F;
  22.         ADCSRB = (1 << ACME);
  23.         ADMUX = 2;              // Select analog channel 2 as comparator negative input
  24.         ACSR |= 0x03;
  25. }
  26. void BEMF_B_FALLING(){
  27.         ADCSRA = (0 << ADEN); // Disable the ADC module
  28.         //ADCSRA &= 0x7F;
  29.         ADCSRB = (1 << ACME);
  30.         ADMUX = 2;              // Select analog channel 2 as comparator negative input
  31.         ACSR &= ~0x01;
  32.         //ACSR |= 0x02;
  33.         ACSR = 0x02;
  34. }
  35. void BEMF_C_RISING(){
  36.         ADCSRA = (0 << ADEN); // Disable the ADC module
  37.         //ADCSRA &= 0x7F;
  38.         ADCSRB = (1 << ACME);
  39.         ADMUX = 3;              // Select analog channel 3 as comparator negative input
  40.         ACSR |= 0x03;
  41. }
  42. void BEMF_C_FALLING(){
  43.         ADCSRA = (0 << ADEN); // Disable the ADC module
  44.         //ADCSRA &= 0x7F;
  45.         ADCSRB = (1 << ACME);
  46.         ADMUX = 3;              // Select analog channel 3 as comparator negative input
  47.         ACSR &= ~0x01;
  48.         //ACSR |= 0x02;
  49.         ACSR = 0x02;
  50. }

  51. void AH_BL(){
  52.         //Set "IN1" make arm_A upper close and bottom open
  53.         PORTD &= ~0x18;        //~0x18=0b11100111 UNO pin_4|pin_3 - IN2|IN3
  54.         PORTD |= 0x20;        //0x20=0b00100000, UNO pin_5 - OC0B - IN1
  55.         //Turn pin 11 (OC2A) PWM ON (pin 9 & pin 10 OFF)
  56.         //UNO pin_11 - EN1 - OC2A
  57.         //Clear OC2A on compare match, set OC2A at BOTTOM, (non-inverting mode)
  58.         TCCR1A = 0;                //Normal port operation, OC1A/OC1B disconnected.
  59.         TCCR2A = 0x81;        //WGM2 WGM1 WGM0 - 1 0 1 PWM, phase correct OCRA
  60.         //TCCR2B = 0x08;        //WGM22 = 1
  61.         //Set "EN2" make arm_B upper close and bottom open
  62.         //Clear "pin_D9 - EN3" make arm_C upper open and bottom close
  63.         PORTB = 0x04;        //UNO - pin_D10 - EN2
  64. }
  65. void AH_CL(){
  66.         //Set "IN1" make arm_A upper close and bottom open
  67.         PORTD &= ~0x18;        //~0x18=0b11100111 UNO pin_4|pin_3 - IN2|IN3
  68.         PORTD |= 0x20;        //0x20=0b00100000, UNO pin_5 - OC0B - IN1
  69.         //Turn pin 11 (OC2A) PWM ON (pin 9 & pin 10 OFF)
  70.         //UNO pin_11 - EN1 - OC2A
  71.         TCCR1A = 0;                //Normal port operation, OC1A/OC1B disconnected.
  72.         TCCR2A = 0x81;        //WGM2 WGM1 WGM0 - 1 0 1 PWM, phase correct OCRA
  73.         //TCCR2B = 0x08;        //WGM22 = 1
  74.         //Set "EN3" make arm_C upper close and bottom open
  75.         //Clear "pin_D9 - EN3" make arm_C upper open and bottom close
  76.         PORTB  =  0x02;        //UNO pin_9 - EN3 - OC1B
  77. }
  78. void BH_CL(){
  79.         //Set "IN2" make arm_B upper close and bottom open
  80.         PORTD &= ~0x28;        //~0x28=0b11010111 UNO pin_5|pin_3 - IN1|IN3
  81.         PORTD |=  0x10;        //0x10=0b00010000 UNO pin_4 - IN2
  82.         //Turn pin 10 (OC1B) PWM ON (pin 9 & pin 11 OFF)
  83.        
  84.         //WGM13 WGM12 WGM11 WGM10 - 1 0 1 1 PWM, phase correct OCR1B TOP BOTTOM
  85.         //COM1A1/COM1B1 COM1A0/COM1B0 - 1 0 Clear OC1A/OC1B on compare match, set OC1A/OC1B at BOTTOM (non-inverting mode)
  86.         //TCCR1B - ICNC1 ICES1 – WGM13 WGM12 CS12 CS11 CS10
  87.         //TCCR1B = 0x20;
  88.         //TCCR1A = 0x2C;  //TCCR1A - COM1A1 COM1A0 COM1B1 COM1B0 – – WGM11 WGM10

  89.         TCCR2A =  0;            // Turn pin 10 (OC1B) PWM ON (pin 9 & pin 11 OFF)
  90.         TCCR1A =  0x21;         //
  91.                   
  92.         //Set "EN3" make arm_C upper close and bottom open
  93.         //Clear "pin_D9 - EN3" make arm_C upper open and bottom close
  94.         PORTB  =  0x02;        //UNO pin_9 - EN3
  95. }
  96. void BH_AL(){
  97.         //Set "IN2" make arm_B upper close and bottom open
  98.         PORTD &= ~0x28;
  99.         PORTD |=  0x10;
  100.         //Turn pin 10 (OC1B) PWM ON (pin 9 & pin 11 OFF)
  101.        
  102.         //WGM13 WGM12 WGM11 WGM10 - 1 0 1 1 PWM, phase correct OCR1B TOP BOTTOM
  103.         //COM1A1/COM1B1 COM1A0/COM1B0 - 1 0 Clear OC1A/OC1B on compare match, set OC1A/OC1B at BOTTOM (non-inverting mode)
  104.         //TCCR1B - ICNC1 ICES1 – WGM13 WGM12 CS12 CS11 CS10
  105.         //TCCR1B = 0x20;
  106.         //TCCR1A = 0x2C;  //TCCR1A - COM1A1 COM1A0 COM1B1 COM1B0 – – WGM11 WGM10
  107.         TCCR1A = 0x21;
  108.         TCCR2A =  0;
  109.        
  110.         //Set "EN1" make arm_A upper close and bottom open
  111.         //Clear "pin_D11 - EN1" make arm_A upper open and bottom close
  112.         PORTB  =  0x08;
  113. }
  114. void CH_AL(){
  115.         //Set "IN3" make arm_C upper close and bottom open       
  116.         PORTD &= ~0x30;
  117.         PORTD |=  0x08;
  118.         //Turn pin 9 (OC1A) PWM ON (pin 10 & pin 11 OFF)
  119.        
  120.         //WGM13 WGM12 WGM11 WGM10 - 1 0 1 1 PWM, phase correct OCR1B TOP BOTTOM
  121.         //COM1A1/COM1B1 COM1A0/COM1B0 - 1 0 Clear OC1A/OC1B on compare match, set OC1A/OC1B at BOTTOM (non-inverting mode)
  122.         //TCCR1B - ICNC1 ICES1 – WGM13 WGM12 CS12 CS11 CS10
  123.         //TCCR1B = 0x20;
  124.         //TCCR1A = 0x2C;  //TCCR1A - COM1A1 COM1A0 COM1B1 COM1B0 – – WGM11 WGM10
  125.        
  126.         TCCR1A = 0x81;
  127.         TCCR2A =  0;
  128.        
  129.         //Set "EN1" make arm_A upper close and bottom open
  130.         //Clear "pin_D11 - EN1" make arm_A upper open and bottom close
  131.         PORTB  =  0x08;
  132. }
  133. void CH_BL(){
  134.         //Set "IN3" make arm_C upper close and bottom open
  135.         PORTD &= ~0x30;
  136.         PORTD |=  0x08;
  137.         //Turn pin 9 (OC1A) PWM ON (pin 10 & pin 11 OFF)
  138.        
  139.         //WGM13 WGM12 WGM11 WGM10 - 1 0 1 1 PWM, phase correct OCR1B TOP BOTTOM
  140.         //COM1A1/COM1B1 COM1A0/COM1B0 - 1 0 Clear OC1A/OC1B on compare match, set OC1A/OC1B at BOTTOM (non-inverting mode)
  141.         //TCCR1B - ICNC1 ICES1 – WGM13 WGM12 CS12 CS11 CS10
  142.         //TCCR1B = 0x20;
  143.         //TCCR1A = 0x8C;  //TCCR1A - COM1A1 COM1A0 COM1B1 COM1B0 – – WGM11 WGM10
  144.        
  145.         TCCR1A = 0x81;
  146.         TCCR2A = 0;
  147.        
  148.         //Set "EN2" make arm_B upper close and bottom open
  149.         //Clear "pin_D11 - EN2" make arm_B upper open and bottom close
  150.         PORTB  =  0x04;
  151. }
 楼主| MianQi 发表于 2024-6-17 06:39 | 显示全部楼层
bldc.h
  1. /*
  2. * bldc.h
  3. */


  4. #ifndef BLDC_H_
  5. #define BLDC_H_

  6. //unsigned int bldc_step = 0;

  7. void bldc_move(void);

  8. //Back EMF                                        PinOut
  9. //        BEMF_C                PORTD7/UNO_D7/AIN1
  10. //        BEMF_B                PORTC2/UNO_A2/ADC2
  11. //        BEMF_A                PORTC3/UNO_A3/ADC3
  12. void BEMF_A_RISING(void);
  13. void BEMF_A_FALLING(void);
  14. void BEMF_B_RISING(void);
  15. void BEMF_B_FALLING(void);
  16. void BEMF_C_RISING(void);
  17. void BEMF_C_FALLING(void);


  18. //Phase                                     PWM(EN)                                                                   IN                         
  19. //1 - AB        OC2B - PORTB11 - EN1                (PORTD5)IN1=1 | (PORTD4)IN2=0
  20. //2 - AC        OC2B - PORTB11 - EN1                (PORTD5)IN1=1 | (PORTD3)IN3=0
  21. //3 - BC        OC1B - PORTB10 - EN2                (PORTD4)IN2=1 | (PORTD3)IN3=0
  22. //4 - BA        OC1B - PORTB10 - EN2                (PORTD4)IN2=1 | (PORTD5)IN1=0
  23. //5 - CA        OC1A - PORTB9 - EN3                        (PORTD3)IN3=1 | (PORTD5)IN1=0
  24. //6 - CB        OC1A - PORTB9 - EN3                        (PORTD3)IN3=1 | (PORTD4)IN2=0
  25. void AH_BL(void);
  26. void AH_CL(void);
  27. void BH_CL(void);
  28. void BH_AL(void);
  29. void CH_AL(void);
  30. void CH_BL(void);

  31. void motor_start(void);


  32. #endif /* BLDC_H_ */
 楼主| MianQi 发表于 2024-6-17 16:43 来自手机 | 显示全部楼层
实际上,BLDC 的驱动程序用 ASM 来写更合适,这个帖子的浏览量当前是 15K,什么时候超过 100K,我就写一个 avrasm 版本的程序。
幸福小强 发表于 2024-6-26 22:16 | 显示全部楼层
开源方案?
幸福小强 发表于 2024-6-26 22:16 | 显示全部楼层
MianQi 发表于 2024-6-17 16:43
实际上,BLDC 的驱动程序用 ASM 来写更合适,这个帖子的浏览量当前是 15K,什么时候超过 100K,我就写一个  ...

期待楼主分享一下ASM版本的,不过汇编会的人不多了。楼主厉害。
 楼主| MianQi 发表于 2024-6-26 22:18 | 显示全部楼层

“开源方案”这个叫法有点大了,就是这么个东西,我测试过了能用,感兴趣的人自己测试一下,有问题可以在这里讨论。
幸福小强 发表于 2024-6-26 22:37 | 显示全部楼层
MianQi 发表于 2024-6-26 22:18
“开源方案”这个叫法有点大了,就是这么个东西,我测试过了能用,感兴趣的人自己测试一下,有问题可以在 ...

非常好,学习学习。感谢。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:所有未经解决的问题都一般大。

32

主题

394

帖子

3

粉丝
快速回复 在线客服 返回列表 返回顶部
个人签名:所有未经解决的问题都一般大。

32

主题

394

帖子

3

粉丝
快速回复 在线客服 返回列表 返回顶部