Arduino servo and BLDC control code issue

Can someone help me compile these two sketches into one, so both functionalities are handled by one Arduino?

Below are the two sketches. One is a basic servo control with a potentiometer, the second one is an open loop simpleFOC BLDC control sketch. I have both working separately perfectly (2 Arduinos), but I can't get a single Arduino to perform both, as in: control the rotation of the servo with the pot while the BLDC spins on its own. I am pretty sure it is a code issue due to my lack of coding skills. Might be a matter of adding an "if" function, but note that I'd like the servo to operate whether the BLDC is on or not and vice-versa. Would that qualify as "multitasking"?

Thanks a bunch!

sketch 1 (servo pot control)

#include <Servo.h>


Servo Servo1;

int servoPin = 3;
int potPin = A0;


void setup() {
    Servo1.attach(servoPin);
}


void loop() {
    int reading = analogRead(potPin);
    int angle = map(reading, 0, 1023, 0, 180);
    Servo1.write(angle);
}

Sketch 2 (simpleFOC BLDC control)

/* Open loop FOC control of the angle of a brushless motor
 * More on https://electronoobs.com/eng_arduino_tut176.php"
 * YouTube channel: https://www.youtube.com/c/ELECTRONOOBS */

//Inputs and outputs
const int Enable_Pin = 8;         // Enable pin for the driver
const int Motor_phase_A = 9;      //Pin for driver input of phase A
const int Motor_phase_B = 10;     //Pin for driver input of phase B
const int Motor_phase_C = 11;     //Pin for driver input of phase C

//Variables used in the code
int16_t SINE_A = 0;               //Initial angle value of the phase A
int16_t SINE_B = 120;             //Initial angle value of the phase B
int16_t SINE_C = 240;             //Initial angle value of the phase C
int poles = 11;                   /*Amount of poles of the motor (change this value if the motor is not
                                  getting to a full rotation. For example, my motor has 28 poles but I had
                                  to add "11" in order to make a full rotation*/
uint32_t adc_read = 0;            //Variable to store the pot ADC value.

                                 

void setup() {
  Serial.begin(9600);
  //We need to set the PWM frequency to be the same for all 3 pins D9, D10 and D11
  TCCR0B = TCCR0B & 0b11111000 | 0x03 ; // Changing would affect millis() and delay() so better to leave it default (0x03).
  TCCR1B = TCCR1B & 0b11111000 | 0x01;  // Set PWM frequency at 31250Hz for D9 and 10, (0x03 is default value, gives 490 Hz).
  TCCR2B = TCCR2B & 0b11111000 | 0x01;  // Set PWM frequency at 31250Hz for D11 D3, (0x03 is default value, gives 490 Hz).
 
  pinMode(Motor_phase_A, OUTPUT);
  pinMode(Motor_phase_B, OUTPUT);
  pinMode(Motor_phase_C, OUTPUT);
  pinMode(Enable_Pin, OUTPUT);
  digitalWrite(Enable_Pin, HIGH);
}
 
void loop() {
  moving(); // The motor is moving. 
}



void moving()
{   
  SINE_A = SINE_A + 3;      //Add # so the rotation will continue # by # | ADJUSTS THE MOTOR SPEED
  SINE_B = SINE_A + 120;    //We have a 120 phase difference betweeen phase A and B
  SINE_C = SINE_B + 120;    //We have a 120 phase difference betweeen phase B and C
   
  //Range calculation of Sine Signal
  SINE_A = SINE_A%360;    //Keep the values between 0 and 359
  SINE_B = SINE_B%360;    //Keep the values between 0 and 359
  SINE_C = SINE_C%360;    //Keep the values between 0 and 359
 
  //Calculate the PWM values for creating a sine signal (SPWM)
  int SINE_A_PWM = sin((double)SINE_A*PI/180)*127.5+127.5;  //Multiply by PI and divide by 180 in order to pass from degrees to radians
  int SINE_B_PWM = sin((double)SINE_B*PI/180)*127.5+127.5;  //Multiply by 127.5 and add 127.5 in order to keep the range between 0-255
  int SINE_C_PWM = sin((double)SINE_C*PI/180)*127.5+127.5;  //Sine values between -1 and 1 are placed between 0-255 for PWM. 

  analogWrite(Motor_phase_A, SINE_A_PWM*0.7);               //You might change the 0.7 value for more torque...
  analogWrite(Motor_phase_B, SINE_B_PWM*0.7);               //You might change the 0.7 value for more torque...
  analogWrite(Motor_phase_C, SINE_C_PWM*0.7);               //You might change the 0.7 value for more torque...

 
}

Well posted question! Code in code tags and a precise description of the situation.

Search for "Merging codes"! It's a rather common question.

That's very good! It's the way to build "large" projects, make them work piece by piece.

Please post the combined code!

Forum generally doesn't create code but correcting existing code, here we are.

The TCCRxB is outside my territory and looks difficult. Servo.h uses system resources and there might be a collision.
I ask register knowing helpers to step in.

Waiting for Your combined code.

Using the servo library disables PWM on pins 9 and 10.

Well that would definitely explain part of the problem! lol Thanks a bunch :slight_smile:

Thank you for your response Railroader!

I will post my combined code once I've adressed the pins 9 & 10's PWM being disabled by the servo library. Hopefully that will solve the problem. TBC...

First off, thank you so much JCA34F and Railroader for your helpful responses. You helped me resolve my issue in less than 24h. I was able to "merge" my two codes, overcome the disabled PWM for pins 9 and 10, and solved an extra last minute bad whining noise from my BLDC. That's a lot of resolving in very little time for a clown like me! lol

Seriously, merging the codes was not difficult at all. Then once I reassigned the driver's IN1 & IN2 from pin9 to pin5 and pin10 to pin3 respectively, and connected the servo signal wire to pin 9, it worked like a charm. BLDC was spinning fine and I could control the direction and speed of the servo with the potentiometer without any interference on either side. Only problem was a loud whining noise coming from the BLDC. I thought it could be a frequency problem coming from pin5 which PWM is at 980hz by design (so is pin6, which is why I didn't use it). So In "void setup", on the "frequency" line for Motor_phase_A, I changed the value from "0x03" to "0x01" to match Motor_phase_B & C. That did the trick, my BLDC went completely quiet and my servo control is not affected at all.

I will attempt to draw out a clear diagram of the setup as soon as I have time. Until then, here's the code I'm now using to which I added a few of my own comments to clarify the changes I made:

#include <Servo.h> //Include Servo library.

Servo Servo1; // name the servo motor, could be any name as long as it mirrors 
/* Open loop FOC control of the angle of a brushless motor
 * More on https://electronoobs.com/eng_arduino_tut176.php"
 * YouTube channel: https://www.youtube.com/c/ELECTRONOOBS */

//Inputs and outputs
int servoPin = 9;                 // servo signal wire to Pin9 (PWM enabled, reserved by Servo lib.)
int potPin = A0;                  // potentiometer center pole to analog pin A0
const int Enable_Pin = 8;         // Enable pin for the driver
const int Motor_phase_A = 5;      //Pin for driver input of phase A | Previously was Pin9
const int Motor_phase_B = 3;     //Pin for driver input of phase B | Previously was Pin10
const int Motor_phase_C = 11;     //Pin for driver input of phase C | No change

//Variables used in the code
int16_t SINE_A = 0;               //Initial angle value of the phase A
int16_t SINE_B = 120;             //Initial angle value of the phase B
int16_t SINE_C = 240;             //Initial angle value of the phase C
int poles = 11;                   /*Amount of poles of the motor (change this value if the motor is not
                                  getting to a full rotation. For example, my motor has 28 poles but I had
                                  to add "11" in order to make a full rotation*/
uint32_t adc_read = 0;            //Variable to store the pot ADC value.

                                 

void setup() {
  Serial.begin(9600);
  //We need to set the PWM frequency to be the same for all 3 pins D9, D10 and D11
  TCCR0B = TCCR0B & 0b11111000 | 0x01 ; // Changing would affect millis() and delay() so better to leave it default (0x03). (NOTE: I changed that to 0x01 to eliminate the BLDC whining noise)
  TCCR1B = TCCR1B & 0b11111000 | 0x01;  // Set PWM frequency at 31250Hz for D9 and 10, (0x03 is default value, gives 490 Hz).
  TCCR2B = TCCR2B & 0b11111000 | 0x01;  // Set PWM frequency at 31250Hz for D11 D3, (0x03 is default value, gives 490 Hz).
 
  pinMode(Motor_phase_A, OUTPUT);
  pinMode(Motor_phase_B, OUTPUT);
  pinMode(Motor_phase_C, OUTPUT);
  pinMode(Enable_Pin, OUTPUT);
  digitalWrite(Enable_Pin, HIGH);
  Servo1.attach(servoPin); // assign Servo1 signal wire to servoPin (Pin9)
}
 
void loop() {
  moving(); // The motor is moving.

  int reading = analogRead(potPin); // READ POT - ACTUATE SERVO
  int angle = map(reading, 0, 1023, 0, 180); // pot/servo rotation mapping
  Servo1.write(angle); 

}

void moving()
{   
  SINE_A = SINE_A + 7;      //Add # so the rotation will continue # by # | ADJUSTS THE MOTOR SPEED
  SINE_B = SINE_A + 120;    //We have a 120 phase difference betweeen phase A and B
  SINE_C = SINE_B + 120;    //We have a 120 phase difference betweeen phase B and C
   
  //Range calculation of Sine Signal
  SINE_A = SINE_A%360;    //Keep the values between 0 and 359
  SINE_B = SINE_B%360;    //Keep the values between 0 and 359
  SINE_C = SINE_C%360;    //Keep the values between 0 and 359
 
  //Calculate the PWM values for creating a sine signal (SPWM)
  int SINE_A_PWM = sin((double)SINE_A*PI/180)*127.5+127.5;  //Multiply by PI and divide by 180 in order to pass from degrees to radians
  int SINE_B_PWM = sin((double)SINE_B*PI/180)*127.5+127.5;  //Multiply by 127.5 and add 127.5 in order to keep the range between 0-255
  int SINE_C_PWM = sin((double)SINE_C*PI/180)*127.5+127.5;  //Sine values between -1 and 1 are placed between 0-255 for PWM. 

  analogWrite(Motor_phase_A, SINE_A_PWM*0.7);               //You might change the 0.7 value for more torque...
  analogWrite(Motor_phase_B, SINE_B_PWM*0.7);               //You might change the 0.7 value for more torque...
  analogWrite(Motor_phase_C, SINE_C_PWM*0.7);               //You might change the 0.7 value for more torque...
  

}

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.