Hello,
I’ve been search for a answer to a question for a long time and have found nothing that fits.
I have a BLDC Motor with Hall Outputs (x3). I have a motor controller that has a PMW input. 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 BLDC with Hall PID Speed Control 001 - YouTube