Closed loop with Chinese BLDC Controller

Hello, this maybe too much of a simple question but I been working on this conundrum for a long time without ay detailed knowledge of programming etc.

This is what I have managed to do. I have a JK42BLS01 motor which has hall outputs. I have managed to connect it to a couple of different BLDC controllers (BLD120A and a generic Chinese one).

I have uploaded Arduino code to an ATtiny 85 and can control the motor and run it at different speeds by generating a PMW signal. The only control I have is the ability to change the speed incrementally from 1 - 255 in the Arduino code. 1 being zero and 255 being 100% of full speed.

I can also connect the hall outputs to an Arduino Nano and can monitor the signals.

However, this is the controller that I am using:

It is called : DC 12V-36V 500W PWM Brushless Motor Controller Motor Control Hall Motor. I have no other information other than it also accepts at PMW signal.

It doesn’t feature in the list of controllers on the community site.

It also has what is called a “Tachometer Pulse output”. I would assume that this is a square wave generated by the three hall outputs?

My goal is very simple. I would like to run the motor in a closed loop at a constant speed under differing torque loads.

The motor will be used to run a very old 35mm movie camera which needs to run at 25 frames per second (roughly 6250 RPM) with little or no variation in speed. This will then enable the camera to be used for synchronised sound shooting.

Would this be possible for someone who looks at Arduino code and has little to no idea why any of it works?

Here is a video of the motor running the camera at 2 frames per second using the board from a BLD120A BLDC controller. I’ve decided to use the generic Chinese one as it’s cheaper and smaller and seems to work just as well.

This is the code that I’m running on the ATtiny. I changed to Pin Configuration to make it work as the code was written for an Arduino Nano:

int PWM_Pin = 0; /* give PWM_Pin name to D3 pin */
// Perform initialization inside setup()
void setup()
{
pinMode(PWM_Pin,OUTPUT); /*declare D3 pin as an output pin /
}
// loop() executes continously
void loop()
{
analogWrite(PWM_Pin,255); /
Produce 100% duty cycle PWM on D3 */

}

Any help would be gratefully appreciated.

Kind regards

Zynsk

@Zynsk

Welcome to the forum.

This is a forum for SimpleFOC. The code and hardware you have has nothing to do with running SimpleFOC.

Perhaps someone could help you, however, it may be unlikely.

Also, looking at the picture, the chips have the model and serial scrubbed off, which is a very common aliexpress practice to hide the hardware (stolen/off-brand). That makes it really hard to even find out that hardware you run.

Cheers,
Valentine

Thought that might be the case. Looked at the velocity control example and thought that was similar but like I said I know next to nothing and when I cracked running a motor using Arduino code I thought that someone would be able to connect the dots for me. I just couldn’t understand enough to make it work.

Thanks for the the reply. I appreciate it.

Cheers

Marek

Hello,
Been working on this for a while since the last post and this is where I’ve got:

I have a BLDC Motor with Hall Outputs (x3). It’s a 42BLF20 (12000 RPM) 24 VDC with Hall outputs. I have a motor controller that has a PMW input JYQD V7 3.3). The motor controller also has a “signal output” which takes the 3 hall signals and amalgamates them to a single 12 pulses per rotation 2.65V Square wave.

I can control the motor using the PMW output from both and Arduino Uno and an ATTiny 85.

I can also read the RPM with the Arduino.

My problem is that I would like to close the loop and control the RPM of the motor using the PMW signal which is being controlled by the RPM reader.

I have found some PID code but am not sure how to implement it correctly.

My goal is to run the motor at either exactly 6250 RPM (75000 pulse per minute) or alternatively 6000 RPM (72000 pulse per minute)

The question is; Can I do this with and Arduino/ATtiny 85?

If I can, what to I need to change in this code to make it work?

I did not write the code as I have no skills in coding. I do understand enough to change parameters if I know which ones to change (which I don’t in this case)

Can anyone help or point me in the right direction to get help please?

Many thanks

Marek

This is the code I’ve been using to run the motor at 25% speed (PMW 64) I don’t know what IN1 and IN2 are just in case you want to know:

#include <util/atomic.h> // For the ATOMIC_BLOCK macro

#define ENCA 2 // YELLOW
#define PWM 5
#define IN2 6
#define IN1 7

volatile int posi = 0; // specify posi as volatile: https://www.arduino.cc/reference/en/language/variables/variable-scope-qualifiers/volatile/
long prevT = 0;
float eprev = 0;
float eintegral = 0;

void setup() {
  Serial.begin(9600);
  pinMode(ENCA,INPUT);
  attachInterrupt(digitalPinToInterrupt(ENCA),readEncoder,RISING);
  
  pinMode(PWM,OUTPUT);
  pinMode(IN1,OUTPUT);
  pinMode(IN2,OUTPUT);
  
  Serial.println("target pos");
}

void loop() {

  // set target position
  //int target = 1200;
  int target = 250*sin(prevT/1e6);

  // PID constants
  float kp = 1;
  float kd = 0.025;
  float ki = 0.0;

  // time difference
  long currT = micros();
  float deltaT = ((float) (currT - prevT))/( 1.0e6 );
  prevT = currT;

  // Read the position in an atomic block to avoid a potential
  // misread if the interrupt coincides with this code running
  // see: https://www.arduino.cc/reference/en/language/variables/variable-scope-qualifiers/volatile/
  int pos = 0; 
  ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
    pos = posi;
  }
  
  // error
  int e = pos - target;

  // derivative
  float dedt = (e-eprev)/(deltaT);

  // integral
  eintegral = eintegral + e*deltaT;

  // control signal
  float u = kp*e + kd*dedt + ki*eintegral;

  // motor power
  float pwr = fabs(u);
  if( pwr > 64 ){
    pwr = 64;
  }

  // motor direction
  int dir = 1;
  if(u<0){
    dir = -1;
  }

  // signal the motor
  setMotor(dir,pwr,PWM,IN1,IN2);


  // store previous error
  eprev = e;

  Serial.print(target);
  Serial.print(" ");
  Serial.print(pos);
  Serial.println();
}

void setMotor(int dir, int pwmVal, int pwm, int in1, int in2){
  analogWrite(pwm,pwmVal);
  if(dir == 1){
    digitalWrite(in1,HIGH);
    digitalWrite(in2,LOW);
  }
  else if(dir == -1){
    digitalWrite(in1,LOW);
    digitalWrite(in2,HIGH);
  }
  else{
    digitalWrite(in1,LOW);
    digitalWrite(in2,LOW);
  }  
}

void readEncoder(){
    posi++;
  }`Preformatted text`

Here’s a video for the motor running:

[Arduino PID BLDC Motor Control - YouTube]. https://youtu.be/GRr_g87BeAo