I am trying to control a dc brushed motor using this speed control, https://www.motiondynamics.com.au/12v-48v-dc-speed-control-single-direction-25a-pcb-model.html
I am having trouble with the motor pulsing at the same frequency as the time between interupts. ie, 1 sec in the attached sketch. I know it's the same frequency as the serial write, but I can comment that out and the pulsing continues.
(Pulsing is an audible tick which visibly causes a momentary reduction in rpm).
I began this project by controlling the pwm out directly through comparing actual rpm with required rpm and adjusting pwm out accordingly but I had erratic results and so switched to PID control as per attached. In both cases though, the interrupt caused a pulsing of the motor.
Using a slot type IR encoder, (lm393) to read rpm, I am trying to control the speed of the motor to a set rpm which will eventually be sent from a remote arduino. But for now, I am trying to get reliable and stable speed control.
I have a Uno with lm393 module (digital output) with 220 ohm resistor connected to pin D2. The hall effect input of the speed controller is connected to D6 and neg. Power for Uno is current via usb while power for motor is via lipo connected to speed controller.
Any idea how to stop the pulsing?
//PID controlled pwm output.
#include <PID_v1.h>
double Setpoint, Input, Output;
//Specify the links and initial tuning parameters
PID myPID(&Input, &Output, &Setpoint, 2,5,1
, DIRECT);
//RPM stuff
int speedSensor = 2;
unsigned int rpm; // rpm reading
volatile byte pulses; // number of pulses
unsigned long timeold;
unsigned long timeold2;
// number of pulses per revolution
// based on your encoder disc
unsigned int pulsesperturn = 18;
void counter()
{
//Update count
pulses++;
}
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
pinMode(speedSensor, INPUT);
analogWrite(6, 0); //Sets esc to off at start up.
//Triggers on Falling Edge (change from HIGH to LOW)
attachInterrupt(0, counter, RISING);
// Initialize
pulses = 0;
rpm = 0;
timeold = 0;
timeold2 = 0;
//initialize the variables we're linked to for PID
Input = rpm;
Setpoint = 30;
//turn the PID on
myPID.SetMode(AUTOMATIC);
Serial.println("wifi_seeder_PID");
delay(1000);
}
void loop() {
// put your main code here, to run repeatedly:
//Read sensor and compute rpm
if (millis() - timeold >= 1000) {
//Don't process interrupts during calculations*/
noInterrupts();
//rpm = ((60 * 500 / pulsesperturn ) / (millis() - timeold) * pulses);
//rpm=(pulses/pulsesperturn);
rpm=pulses*((millis() - timeold)/1000);
timeold = millis();
pulses = 0;
interrupts();
Serial.print("RPM = ");
Serial.print(rpm, DEC);
}
//Restart the interrupt processing
//Process pwm out via PID.
Input = rpm;
myPID.Compute();
analogWrite(6,Output);
// }
//Print rpm & pwm out.
if (millis() - timeold2 >= 1000) {
Serial.print(" Output ");
Serial.print(Output);
Serial.print(" Pulses ");
Serial.println(pulses);
timeold2 = millis();
}
//delay(1000);
}
Any idea how to stop the pulsing?
//PID controlled pwm output.
#include <PID_v1.h>
double Setpoint, Input, Output;
//Specify the links and initial tuning parameters
PID myPID(&Input, &Output, &Setpoint, 2,5,1
, DIRECT);
//RPM stuff
int speedSensor = 2;
unsigned int rpm; // rpm reading
volatile byte pulses; // number of pulses
unsigned long timeold;
unsigned long timeold2;
// number of pulses per revolution
// based on your encoder disc
unsigned int pulsesperturn = 18;
void counter()
{
//Update count
pulses++;
}
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
pinMode(speedSensor, INPUT);
analogWrite(6, 0); //Sets esc to off at start up.
//Triggers on Falling Edge (change from HIGH to LOW)
attachInterrupt(0, counter, RISING);
// Initialize
pulses = 0;
rpm = 0;
timeold = 0;
timeold2 = 0;
//initialize the variables we're linked to for PID
Input = rpm;
Setpoint = 30;
//turn the PID on
myPID.SetMode(AUTOMATIC);
Serial.println("wifi_seeder_PID");
delay(1000);
}
void loop() {
// put your main code here, to run repeatedly:
//Read sensor and compute rpm
if (millis() - timeold >= 1000) {
//Don't process interrupts during calculations*/
noInterrupts();
//rpm = ((60 * 500 / pulsesperturn ) / (millis() - timeold) * pulses);
//rpm=(pulses/pulsesperturn);
rpm=pulses*((millis() - timeold)/1000);
timeold = millis();
pulses = 0;
interrupts();
Serial.print("RPM = ");
Serial.print(rpm, DEC);
}
//Restart the interrupt processing
//Process pwm out via PID.
Input = rpm;
myPID.Compute();
analogWrite(6,Output);
// }
//Print rpm & pwm out.
if (millis() - timeold2 >= 1000) {
Serial.print(" Output ");
Serial.print(Output);
Serial.print(" Pulses ");
Serial.println(pulses);
timeold2 = millis();
}
//delay(1000);
}
