L6234无刷直流电机控制-简易版

2023-06-20  

我本来今天想来一发源码分析的,但是我手头没有鼠标,我一想截图那么多就算了,我发一个电机驱动的代码就行。

SimpleFoc-云台电机2804+AS5600

SimpleFoc-原理图(STL6234+INA240)

4c146bc0-c253-11ed-bfe3-dac502259ad0.png

所以一个输出要两个接口控制

L6234 驱动器有 3 个输出:OUT1、OUT2 和 OUT3。每个输出由 2 个引脚控制:输入 (IN) 和使能 (EN),例如 OUT1 由 IN1 和 EN1 控制。下图显示了每个半桥的控制逻辑:

4c529ce2-c253-11ed-bfe3-dac502259ad0.png

逻辑电平

4c8e104c-c253-11ed-bfe3-dac502259ad0.png

输出电平

4caa23ae-c253-11ed-bfe3-dac502259ad0.png

另外这个原理图看左边,为了方便可以把使能脚直接都拉低

4cd17d46-c253-11ed-bfe3-dac502259ad0.png

这样使用三个引脚模拟也是可以的

1.L6234 三相电机驱动器  2.6 x 33k 欧姆电阻器 3.3 x 10k 欧姆电阻器 4.4 x 1 欧姆电阻器(功率为 2 W 或更高) 5.2 x 1N4148 二极管 6.100 uF 电解电容器(16V 或更高) 7.1 uF 电解电容器(16V 或更高) 8.220 nF (0.22 uF) 陶瓷电容器 9.100 nF (0.1 uF) 陶瓷电容器 10.10 nF (0.01 uF) 陶瓷电容器 11.2 x 按钮 12.12V 电源 直接连接:

4cf4145a-c253-11ed-bfe3-dac502259ad0.png

#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);

}

// Analog comparator ISR

ISR(ANALOG_COMP_vect)

{

    // BEMF debounce

    for (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();

    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

}

 


代码我就先不解释了,看懂需要看ATmega的书手册


文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。