0% found this document useful (0 votes)
3 views

BLDC_v1

The document provides a code implementation for sensorless brushless DC (BLDC) motor control using an Arduino UNO, which includes setup for PWM, analog comparator interrupts, and motor commutation functions. It initializes the motor with a starting duty cycle and adjusts the PWM duty cycle based on voltage readings. The code includes various functions to handle motor movement and BEMF detection for effective control of the BLDC motor.

Uploaded by

Ziad Seifelnasr
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
3 views

BLDC_v1

The document provides a code implementation for sensorless brushless DC (BLDC) motor control using an Arduino UNO, which includes setup for PWM, analog comparator interrupts, and motor commutation functions. It initializes the motor with a starting duty cycle and adjusts the PWM duty cycle based on voltage readings. The code includes various functions to handle motor movement and BEMF detection for effective control of the BLDC motor.

Uploaded by

Ziad Seifelnasr
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 4

/* Sensorless brushless DC (BLDC) motor control with Arduino UNO (Arduino DIY ESC).

* This is a free software with NO WARRANTY.


* http://simple-circuit.com/
*/
#include "ADS1X15.h"

ADS1115 ADS(0x48);

#define PWM_MAX_DUTY 255


#define PWM_MIN_DUTY 50
#define PWM_START_DUTY 100

unsigned int pwmDutyCycle = 0;


unsigned int deadTime = 5;

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

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

Wire.begin();
ADS.begin();

}
// 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() {

ADS.setGain(0);

int16_t val_0 = ADS.readADC(0);

float f = ADS.toVoltage(1); // voltage factor

float voltage = val_0 * f;


pwmDutyCycle = map(voltage, 0.0, 5.0, 0, 255);

SET_PWM_DUTY(pwmDutyCycle);

delay(50);

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;
}

//pin 9 > PB1 > OC1A > CL


//pin 10 > PB2 > OC1B > BL
//pin 11 > PB3 > OC2A > AL
//pin 3 > PD3 > CH
//pin 4 > PD4 > BH
//pin 5 > PD5 > AH
void AH_BL(){ //1
PORTD &= ~0x18; // turn pin 4 PD4 & 3 PD3 off. turn pin 5 on.
PORTD |= 0x20; //
TCCR2A = 0; // Turn pin 10 (OC1B) (BL PWM ON) (pin 9 (OC1A) & pin 10
(OC1B) OFF)
TCCR1A = 0x21; //
delayMicroseconds(deadTime);

}
void AH_CL(){ //2
PORTD &= ~0x18; // turn pin 4 & 3 off. turn pin 5 on.
PORTD |= 0x20;
TCCR2A = 0; // Turn pin 9 PB1 (OC1A) PWM ON (pin 11 PB3 & pin 10 PB2
OFF)
TCCR1A = 0x81; //
delayMicroseconds(deadTime);
}
void BH_CL(){ //3
PORTD &= ~0x28; //turn pin 4 (PD4) on. Pin 3 (PD3) & 5 (PD5) off.
PORTD |= 0x10;
TCCR2A = 0; // Turn pin 9 (OC1A) PWM ON (pin 10 & pin 11 OFF)
TCCR1A = 0x81; //
delayMicroseconds(deadTime);
}
void BH_AL(){ //4
PORTD &= ~0x28; //turn pin 4 (PD4) on. Pin 3 (PD3) & 5 (PD5) off.
PORTD |= 0x10;
TCCR1A = 0; // Turn pin 11 (OC2A) PWM ON (pin 9 & pin 10 OFF)
TCCR2A = 0x81; //
delayMicroseconds(deadTime);
}
void CH_AL(){ //5
PORTD &= ~0x30; //turn pin 3 (PD3) on. Pin 4 (PD4) & 5 (PD5) off.
PORTD |= 0x08;
TCCR1A = 0; // Turn pin 11 (OC2A) PWM ON (pin 9 & pin 10 OFF)
TCCR2A = 0x81; //
delayMicroseconds(deadTime);
}
void CH_BL(){ //6
PORTD &= ~0x30; // turn pin 3 (PD3) on. Pin 4 (PD4) & 5 (PD5) off.
PORTD |= 0x08;
TCCR2A = 0; // Turn pin 10 (OC1B) PWM ON (pin 9 & pin 11 OFF)
TCCR1A = 0x21; //
delayMicroseconds(deadTime);
}

void SET_PWM_DUTY(unsigned int 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
}

You might also like