打印
[电机控制]

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

[复制链接]
21326|15
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
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 | 只看该作者
看到分享的链接了,学习一下,非常赞。

使用特权

评论回复
5
MianQi|  楼主 | 2024-5-20 15:38 | 只看该作者

从数据手册的说明来看,这个芯片是专为 BLDC 设计地。从外围电路的搭建以及管脚接线的实际经验来看,用起来的确很方便。

使用特权

评论回复
6
shenxiaolin| | 2024-6-14 16:08 | 只看该作者
有代码么?抄一下代码,
哈哈哈

使用特权

评论回复
7
MianQi|  楼主 | 2024-6-17 06:34 | 只看该作者
Arduino IDE 版本的是一个单独的文件:
/*
* Sensorless brushless DC (BLDC) motor control with Arduino UNO and L6234 driver.
*/


#define SPEED_UP          A0
#define SPEED_DOWN        A1
#define PWM_MAX_DUTY      255
#define PWM_MIN_DUTY      50
#define PWM_START_DUTY    100

byte bldc_step = 0, motor_speed;
unsigned int i;

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

  pinMode(SPEED_UP,   INPUT_PULLUP);
  pinMode(SPEED_DOWN, INPUT_PULLUP);

  sei();
}

// Analog comparator ISR
ISR (ANALOG_COMP_vect) {
  // BEMF debounce
  for(int i = 0; i < 10; i++) {
    if(bldc_step & 1){
      if(!(ACSR & 0x20)) i -= 1;
      } else {
         if((ACSR & 0x20)) i -= 1;
        }
    }
  bldc_move();
  bldc_step++;
  bldc_step %= 6;
  }
  
void bldc_move(){
  // BLDC motor commutation function
  switch(bldc_step){
    case 0:
    AH_BL();
    BEMF_C_RISING();
    break;
    case 1:
    AH_CL();
    BEMF_B_FALLING();
    break;
    case 2: BH_CL();
    BEMF_A_RISING();
    break;
    case 3: BH_AL();
    BEMF_C_FALLING();
    break; case 4:
    CH_AL();
    BEMF_B_RISING();
    break;
    case 5:
    CH_BL();
    BEMF_A_FALLING();
    break;
    }
  }
  
void loop() {
  SET_PWM_DUTY(PWM_START_DUTY); // Setup starting PWM with duty cycle = PWM_START_DUTY
  i = 5000; // Motor start

  while(i > 100) {
    delayMicroseconds(i);
    bldc_move();
    //delay(10);
    bldc_step++;
    bldc_step %= 6;
    i = i - 20;
  }

  motor_speed = PWM_START_DUTY;
  ACSR |= 0x08;                    // Enable analog comparator interrupt
  
  while(1) {
    while(!(digitalRead(SPEED_UP)) && motor_speed < PWM_MAX_DUTY){
      motor_speed++;
      SET_PWM_DUTY(motor_speed);
      delay(100);
      }
    while(!(digitalRead(SPEED_DOWN)) && motor_speed > PWM_MIN_DUTY){
      motor_speed--;
      SET_PWM_DUTY(motor_speed);
      delay(100);
    }
  }
}

void BEMF_A_RISING(){
  ADCSRB = (0 << ACME);    // Select AIN1 as comparator negative input
  ACSR |= 0x03;            // Set interrupt on rising edge
}
void BEMF_A_FALLING(){
  ADCSRB = (0 << ACME);    // Select AIN1 as comparator negative input
  ACSR &= ~0x01;           // Set interrupt on falling edge
}
void BEMF_B_RISING(){
  ADCSRA = (0 << ADEN);   // Disable the ADC module
  ADCSRB = (1 << ACME);
  ADMUX = 2;              // Select analog channel 2 as comparator negative input
  ACSR |= 0x03;
}
void BEMF_B_FALLING(){
  ADCSRA = (0 << ADEN);   // Disable the ADC module
  ADCSRB = (1 << ACME);
  ADMUX = 2;              // Select analog channel 2 as comparator negative input
  ACSR &= ~0x01;
}
void BEMF_C_RISING(){
  ADCSRA = (0 << ADEN);   // Disable the ADC module
  ADCSRB = (1 << ACME);
  ADMUX = 3;              // Select analog channel 3 as comparator negative input
  ACSR |= 0x03;
}
void BEMF_C_FALLING(){
  ADCSRA = (0 << ADEN);   // Disable the ADC module
  ADCSRB = (1 << ACME);
  ADMUX = 3;              // Select analog channel 3 as comparator negative input
  ACSR &= ~0x01;
}

void AH_BL(){
  PORTB  =  0x04;
  PORTD &= ~0x18;
  PORTD |=  0x20;
  TCCR1A =  0;            // Turn pin 11 (OC2A) PWM ON (pin 9 & pin 10 OFF)
  TCCR2A =  0x81;         //
}
void AH_CL(){
  PORTB  =  0x02;
  PORTD &= ~0x18;
  PORTD |=  0x20;
  TCCR1A =  0;            // Turn pin 11 (OC2A) PWM ON (pin 9 & pin 10 OFF)
  TCCR2A =  0x81;         //
}
void BH_CL(){
  PORTB  =  0x02;
  PORTD &= ~0x28;
  PORTD |=  0x10;
  TCCR2A =  0;            // Turn pin 10 (OC1B) PWM ON (pin 9 & pin 11 OFF)
  TCCR1A =  0x21;         //
}
void BH_AL(){
  PORTB  =  0x08;
  PORTD &= ~0x28;
  PORTD |=  0x10;
  TCCR2A =  0;            // Turn pin 10 (OC1B) PWM ON (pin 9 & pin 11 OFF)
  TCCR1A =  0x21;         //
}
void CH_AL(){
  PORTB  =  0x08;
  PORTD &= ~0x30;
  PORTD |=  0x08;
  TCCR2A =  0;            // Turn pin 9 (OC1A) PWM ON (pin 10 & pin 11 OFF)
  TCCR1A =  0x81;         //
}
void CH_BL(){
  PORTB  =  0x04;
  PORTD &= ~0x30;
  PORTD |=  0x08;
  TCCR2A =  0;            // Turn pin 9 (OC1A) PWM ON (pin 10 & pin 11 OFF)
  TCCR1A =  0x81;         //
}

void SET_PWM_DUTY(byte duty){
  if(duty < PWM_MIN_DUTY)
    duty = PWM_MIN_DUTY;
  if(duty > PWM_MAX_DUTY)
    duty  = PWM_MAX_DUTY;
  OCR1A  = duty;                   // Set pin 9  PWM duty cycle
  OCR1B  = duty;                   // Set pin 10 PWM duty cycle
  OCR2A  = duty;                   // Set pin 11 PWM duty cycle
}

使用特权

评论回复
8
MianQi|  楼主 | 2024-6-17 06:37 | 只看该作者
Microchip Studio 版本的程序由四个文件组成:
main.c main.h bldc.c bldc.h

main.c
/*
* main.c
*/
#ifndef        F_CPU
#define F_CPU 16000000ul
#endif

#include "main.h"

#include <avr/cpufunc.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include "bldc.h"


#define PWM_MAX_DUTY      250
#define PWM_MIN_DUTY      50
//#define PWM_MIN_DUTY      100
#define PWM_START_DUTY    100

unsigned int bldc_step = 0;
volatile unsigned int value_pinc = 0;
volatile unsigned char motor_speed = 0;
unsigned int delay_ms_speed = 10;        //10-35ms = 10000-35000us

void motor_start(void);
void motor_restart(void);
void bldc_move(void);

int main(void)
{
    /* Replace with your application code */
        init_Timer0();
        init_ADC();
        init_UART();
        init_GPIO();
        init_Timer1();
        init_Timer2();
       
        // Analog comparator setting - ACSR – Analog Comparator Control and Status Registe
        // ACD ACBG ACO ACI ACIE ACIC ACIS1 ACIS0
        // Bit 4 – ACI: Analog Comparator Interrupt Flag - ACI is cleared by writing a logic one to the flag.
        //ACSR   = 0x10;           // Disable and clear (flag bit) analog comparator interrupt
       
        ACSR |= 0x08; // Enable analog comparator interrupt - Bit 3 – ACIE: Analog Comparator Interrupt Enable
       
        //motor_speed = PWM_START_DUTY;
        //SET_PWM_DUTY(motor_speed);
       
        //Enable PCINT
        PCICR = 0x02;
        PCMSK1 = 0x03;
               
        sei();        // Enable global interrupt
       
        motor_start();
       
    while (1)
    {
                //unsigned char i = PINC0;
                ///* Insert nop for synchronization*/
                //_NOP();
                //unsigned char j = PINC1;
                ///* Insert nop for synchronization*/
                //_NOP();
                ////TX(motor_speed);
                ////while(!PINC0){
                //while((!i) && (motor_speed < PWM_MAX_DUTY)){
                        //motor_speed++;
                        //SET_PWM_DUTY(motor_speed);
                        ////delay(1);
                        ////_delay_us(500);
                //}
                ////while(!PINC1){
                //while((!j) && (motor_speed > PWM_MIN_DUTY)){
                        //motor_speed--;
                        //SET_PWM_DUTY(motor_speed);
                        ////delay(1);
                        ////_delay_us(500);
                //}
                //SET_PWM_DUTY(motor_speed);
                //motor_restart();
                bldc_move();
                //_delay_us(3500);
                //_delay_ms(10);
                _delay_us(10000);
                for(unsigned int i = 0; i < motor_speed / 10; ++i) {
                        //_delay_ms(1);
                        _delay_us(10);
                }
               
                bldc_step++;
                bldc_step %= 6;
    }
}

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

ISR (PCINT1_vect) {
        value_pinc = PINC & 0x03;
        if(value_pinc == 0x01) {
                //motor_speed++;
                motor_speed += 10;
                } else if(value_pinc == 0x02) {
                //motor_speed--;
                motor_speed -= 10;
        }
        motor_restart();
}

// Timer/Counter0 overflow ISR - Vector program address - 0x0020
ISR (TIMER0_OVF_vect) {
        //TX('A');
        ++counter_adc;
        if(counter_adc >= 61) {
                //ADCSRA |= 0b01000000;        // Bit 6 – ADSC: ADC Start Conversion
                ADCSRA = 0x8D | (1<<ADSC);
                counter_adc = 0;
                } else {
                ;
        }
}

// ADC ISR -  ADC conversion complete - 0x002A
ISR (ADC_vect) {
        unsigned int temp = ADC;        // 0 - 1023
        temp /= 4;        // 0 - 254
        motor_speed = temp;
        //motor_speed = ADCH;
        //TX(motor_speed);
        //counter_adc = 0;
        //SET_PWM_DUTY(motor_speed);
}

// Analog comparator ISR - Vector program address - 0x002E
ISR (ANALOG_COMP_vect) {
        // BEMF debounce
        for(unsigned int i = 0; i < 10; i++) {
                if(bldc_step & 1){
                        if(!(ACSR & 0x20)) i -= 1;
                }
                else {
                        if((ACSR & 0x20))  i -= 1;
                }
        }
        //bldc_move();
        //_delay_us(500);
        //_delay_ms(6);
        bldc_step++;
        bldc_step %= 6;
}

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

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

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

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

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

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

void SET_PWM_DUTY(unsigned char duty){
        if(duty < PWM_MIN_DUTY)
        duty  = PWM_MIN_DUTY;
        if(duty > PWM_MAX_DUTY)
        duty  = PWM_MAX_DUTY;
        OCR1A = duty;                   // Set pin 9  PWM duty cycle
        OCR1B = duty;                   // Set pin 10 PWM duty cycle
        OCR2A = duty;                   // Set pin 11 PWM duty cycle
}

void bldc_move(){        // BLDC motor commutation function
        switch(bldc_step){
                case 0:
                AH_BL();
                BEMF_C_RISING();
                break;
                case 1:
                AH_CL();
                BEMF_B_FALLING();
                break;
                case 2:
                BH_CL();
                BEMF_A_RISING();
                break;
                case 3:
                BH_AL();
                BEMF_C_FALLING();
                break;
                case 4:
                CH_AL();
                BEMF_B_RISING();
                break;
                case 5:
                CH_BL();
                BEMF_A_FALLING();
                break;
        }
}

void motor_start(void){
        SET_PWM_DUTY(PWM_START_DUTY);
        //unsigned int i = 5000;
        unsigned int i = 5000;
        while(i > 100) {
                ////_delay_us(i);
                //for(unsigned int j=i; j > 0; --j){
                        ////_delay_us(1);
                        //_NOP();
                        //_NOP();
                //}
               
                bldc_move();
                _delay_ms(6);
                bldc_step++;
                bldc_step %= 6;
                i = i - 20;
        }
}

void motor_restart(void) {
        SET_PWM_DUTY(motor_speed);
        unsigned int i = 5000;
        bldc_move();
        _delay_ms(6);
        bldc_step++;
        bldc_step %= 6;
        i = i - 20;
}

使用特权

评论回复
9
MianQi|  楼主 | 2024-6-17 06:38 | 只看该作者
main.h
/*
* main.h
*/


#ifndef MAIN_H_
#define MAIN_H_

#ifndef        F_CPU
#define F_CPU 16000000ul
#endif

#include <util/delay.h>

volatile unsigned int counter_adc = 0;


void init_ADC(void);
void init_UART(void);
void init_Timer0(void);
void init_GPIO(void);
void init_Timer1(void);
void init_Timer2(void);

void TX(unsigned char TXData);

void SET_PWM_DUTY(unsigned char duty);


#endif /* MAIN_H_ */

使用特权

评论回复
10
MianQi|  楼主 | 2024-6-17 06:39 | 只看该作者
bldc.c
/*
* bldc.c
*/

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



void BEMF_A_RISING(){
        ADCSRB = (0 << ACME);   // Select AIN1(PD7-UNO_pin_7) as comparator negative input
        ACSR |= 0x03;           // Set interrupt on rising edge
        //ADCSRA |= (1<<ADEN);        // Enable the ADC module
}
void BEMF_A_FALLING(){
        ADCSRB = (0 << ACME);   // Select AIN1(PD7-UNO_pin_7) as comparator negative input
        ACSR &= ~0x01;          // Set interrupt on falling edge
        //ACSR |= 0x02;
        //ADCSRA |= (1<<ADEN);        // Enable the ADC module
        ACSR = 0x02;
}
void BEMF_B_RISING(){
        ADCSRA = (0 << ADEN); // Disable the ADC module
        //ADCSRA &= 0x7F;
        ADCSRB = (1 << ACME);
        ADMUX = 2;              // Select analog channel 2 as comparator negative input
        ACSR |= 0x03;
}
void BEMF_B_FALLING(){
        ADCSRA = (0 << ADEN); // Disable the ADC module
        //ADCSRA &= 0x7F;
        ADCSRB = (1 << ACME);
        ADMUX = 2;              // Select analog channel 2 as comparator negative input
        ACSR &= ~0x01;
        //ACSR |= 0x02;
        ACSR = 0x02;
}
void BEMF_C_RISING(){
        ADCSRA = (0 << ADEN); // Disable the ADC module
        //ADCSRA &= 0x7F;
        ADCSRB = (1 << ACME);
        ADMUX = 3;              // Select analog channel 3 as comparator negative input
        ACSR |= 0x03;
}
void BEMF_C_FALLING(){
        ADCSRA = (0 << ADEN); // Disable the ADC module
        //ADCSRA &= 0x7F;
        ADCSRB = (1 << ACME);
        ADMUX = 3;              // Select analog channel 3 as comparator negative input
        ACSR &= ~0x01;
        //ACSR |= 0x02;
        ACSR = 0x02;
}

void AH_BL(){
        //Set "IN1" make arm_A upper close and bottom open
        PORTD &= ~0x18;        //~0x18=0b11100111 UNO pin_4|pin_3 - IN2|IN3
        PORTD |= 0x20;        //0x20=0b00100000, UNO pin_5 - OC0B - IN1
        //Turn pin 11 (OC2A) PWM ON (pin 9 & pin 10 OFF)
        //UNO pin_11 - EN1 - OC2A
        //Clear OC2A on compare match, set OC2A at BOTTOM, (non-inverting mode)
        TCCR1A = 0;                //Normal port operation, OC1A/OC1B disconnected.
        TCCR2A = 0x81;        //WGM2 WGM1 WGM0 - 1 0 1 PWM, phase correct OCRA
        //TCCR2B = 0x08;        //WGM22 = 1
        //Set "EN2" make arm_B upper close and bottom open
        //Clear "pin_D9 - EN3" make arm_C upper open and bottom close
        PORTB = 0x04;        //UNO - pin_D10 - EN2
}
void AH_CL(){
        //Set "IN1" make arm_A upper close and bottom open
        PORTD &= ~0x18;        //~0x18=0b11100111 UNO pin_4|pin_3 - IN2|IN3
        PORTD |= 0x20;        //0x20=0b00100000, UNO pin_5 - OC0B - IN1
        //Turn pin 11 (OC2A) PWM ON (pin 9 & pin 10 OFF)
        //UNO pin_11 - EN1 - OC2A
        TCCR1A = 0;                //Normal port operation, OC1A/OC1B disconnected.
        TCCR2A = 0x81;        //WGM2 WGM1 WGM0 - 1 0 1 PWM, phase correct OCRA
        //TCCR2B = 0x08;        //WGM22 = 1
        //Set "EN3" make arm_C upper close and bottom open
        //Clear "pin_D9 - EN3" make arm_C upper open and bottom close
        PORTB  =  0x02;        //UNO pin_9 - EN3 - OC1B
}
void BH_CL(){
        //Set "IN2" make arm_B upper close and bottom open
        PORTD &= ~0x28;        //~0x28=0b11010111 UNO pin_5|pin_3 - IN1|IN3
        PORTD |=  0x10;        //0x10=0b00010000 UNO pin_4 - IN2
        //Turn pin 10 (OC1B) PWM ON (pin 9 & pin 11 OFF)
       
        //WGM13 WGM12 WGM11 WGM10 - 1 0 1 1 PWM, phase correct OCR1B TOP BOTTOM
        //COM1A1/COM1B1 COM1A0/COM1B0 - 1 0 Clear OC1A/OC1B on compare match, set OC1A/OC1B at BOTTOM (non-inverting mode)
        //TCCR1B - ICNC1 ICES1 – WGM13 WGM12 CS12 CS11 CS10
        //TCCR1B = 0x20;
        //TCCR1A = 0x2C;  //TCCR1A - COM1A1 COM1A0 COM1B1 COM1B0 – – WGM11 WGM10

        TCCR2A =  0;            // Turn pin 10 (OC1B) PWM ON (pin 9 & pin 11 OFF)
        TCCR1A =  0x21;         //
                  
        //Set "EN3" make arm_C upper close and bottom open
        //Clear "pin_D9 - EN3" make arm_C upper open and bottom close
        PORTB  =  0x02;        //UNO pin_9 - EN3
}
void BH_AL(){
        //Set "IN2" make arm_B upper close and bottom open
        PORTD &= ~0x28;
        PORTD |=  0x10;
        //Turn pin 10 (OC1B) PWM ON (pin 9 & pin 11 OFF)
       
        //WGM13 WGM12 WGM11 WGM10 - 1 0 1 1 PWM, phase correct OCR1B TOP BOTTOM
        //COM1A1/COM1B1 COM1A0/COM1B0 - 1 0 Clear OC1A/OC1B on compare match, set OC1A/OC1B at BOTTOM (non-inverting mode)
        //TCCR1B - ICNC1 ICES1 – WGM13 WGM12 CS12 CS11 CS10
        //TCCR1B = 0x20;
        //TCCR1A = 0x2C;  //TCCR1A - COM1A1 COM1A0 COM1B1 COM1B0 – – WGM11 WGM10
        TCCR1A = 0x21;
        TCCR2A =  0;
       
        //Set "EN1" make arm_A upper close and bottom open
        //Clear "pin_D11 - EN1" make arm_A upper open and bottom close
        PORTB  =  0x08;
}
void CH_AL(){
        //Set "IN3" make arm_C upper close and bottom open       
        PORTD &= ~0x30;
        PORTD |=  0x08;
        //Turn pin 9 (OC1A) PWM ON (pin 10 & pin 11 OFF)
       
        //WGM13 WGM12 WGM11 WGM10 - 1 0 1 1 PWM, phase correct OCR1B TOP BOTTOM
        //COM1A1/COM1B1 COM1A0/COM1B0 - 1 0 Clear OC1A/OC1B on compare match, set OC1A/OC1B at BOTTOM (non-inverting mode)
        //TCCR1B - ICNC1 ICES1 – WGM13 WGM12 CS12 CS11 CS10
        //TCCR1B = 0x20;
        //TCCR1A = 0x2C;  //TCCR1A - COM1A1 COM1A0 COM1B1 COM1B0 – – WGM11 WGM10
       
        TCCR1A = 0x81;
        TCCR2A =  0;
       
        //Set "EN1" make arm_A upper close and bottom open
        //Clear "pin_D11 - EN1" make arm_A upper open and bottom close
        PORTB  =  0x08;
}
void CH_BL(){
        //Set "IN3" make arm_C upper close and bottom open
        PORTD &= ~0x30;
        PORTD |=  0x08;
        //Turn pin 9 (OC1A) PWM ON (pin 10 & pin 11 OFF)
       
        //WGM13 WGM12 WGM11 WGM10 - 1 0 1 1 PWM, phase correct OCR1B TOP BOTTOM
        //COM1A1/COM1B1 COM1A0/COM1B0 - 1 0 Clear OC1A/OC1B on compare match, set OC1A/OC1B at BOTTOM (non-inverting mode)
        //TCCR1B - ICNC1 ICES1 – WGM13 WGM12 CS12 CS11 CS10
        //TCCR1B = 0x20;
        //TCCR1A = 0x8C;  //TCCR1A - COM1A1 COM1A0 COM1B1 COM1B0 – – WGM11 WGM10
       
        TCCR1A = 0x81;
        TCCR2A = 0;
       
        //Set "EN2" make arm_B upper close and bottom open
        //Clear "pin_D11 - EN2" make arm_B upper open and bottom close
        PORTB  =  0x04;
}

使用特权

评论回复
11
MianQi|  楼主 | 2024-6-17 06:39 | 只看该作者
bldc.h
/*
* bldc.h
*/


#ifndef BLDC_H_
#define BLDC_H_

//unsigned int bldc_step = 0;

void bldc_move(void);

//Back EMF                                        PinOut
//        BEMF_C                PORTD7/UNO_D7/AIN1
//        BEMF_B                PORTC2/UNO_A2/ADC2
//        BEMF_A                PORTC3/UNO_A3/ADC3
void BEMF_A_RISING(void);
void BEMF_A_FALLING(void);
void BEMF_B_RISING(void);
void BEMF_B_FALLING(void);
void BEMF_C_RISING(void);
void BEMF_C_FALLING(void);


//Phase                                     PWM(EN)                                                                   IN                         
//1 - AB        OC2B - PORTB11 - EN1                (PORTD5)IN1=1 | (PORTD4)IN2=0
//2 - AC        OC2B - PORTB11 - EN1                (PORTD5)IN1=1 | (PORTD3)IN3=0
//3 - BC        OC1B - PORTB10 - EN2                (PORTD4)IN2=1 | (PORTD3)IN3=0
//4 - BA        OC1B - PORTB10 - EN2                (PORTD4)IN2=1 | (PORTD5)IN1=0
//5 - CA        OC1A - PORTB9 - EN3                        (PORTD3)IN3=1 | (PORTD5)IN1=0
//6 - CB        OC1A - PORTB9 - EN3                        (PORTD3)IN3=1 | (PORTD4)IN2=0
void AH_BL(void);
void AH_CL(void);
void BH_CL(void);
void BH_AL(void);
void CH_AL(void);
void CH_BL(void);

void motor_start(void);


#endif /* BLDC_H_ */

使用特权

评论回复
12
MianQi|  楼主 | 2024-6-17 16:43 | 只看该作者
实际上,BLDC 的驱动程序用 ASM 来写更合适,这个帖子的浏览量当前是 15K,什么时候超过 100K,我就写一个 avrasm 版本的程序。

使用特权

评论回复
13
幸福小强| | 2024-6-26 22:16 | 只看该作者
开源方案?

使用特权

评论回复
14
幸福小强| | 2024-6-26 22:16 | 只看该作者
MianQi 发表于 2024-6-17 16:43
实际上,BLDC 的驱动程序用 ASM 来写更合适,这个帖子的浏览量当前是 15K,什么时候超过 100K,我就写一个  ...

期待楼主分享一下ASM版本的,不过汇编会的人不多了。楼主厉害。

使用特权

评论回复
15
MianQi|  楼主 | 2024-6-26 22:18 | 只看该作者

“开源方案”这个叫法有点大了,就是这么个东西,我测试过了能用,感兴趣的人自己测试一下,有问题可以在这里讨论。

使用特权

评论回复
16
幸福小强| | 2024-6-26 22:37 | 只看该作者
MianQi 发表于 2024-6-26 22:18
“开源方案”这个叫法有点大了,就是这么个东西,我测试过了能用,感兴趣的人自己测试一下,有问题可以在 ...

非常好,学习学习。感谢。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

31

主题

387

帖子

3

粉丝