I'm using PWM to control a motor and an encoder to measure its speed. I'm using this to increase the PWM frequency of pin D5:
TCCR0B = TCCR0B & B11111000 | B00000001;
The problem is that when I take the data from the encoder (square wave, 1 pulse per revolution)
in D8 and measure the frequency using PulseIn, the result is completely off. Does anyone know a solution to this?
No, it doesn't accurately measure the duration of the pulse even if the pins are directly connected. I don't understand timers very well but I'm guessing it's to do with the fact that I've changed the output frequency on pin 5.
Ok, how are you measuring the frequency using pulseIn()?
Because a call to pulseIn() can only measure half of the cycle. You would need to use pulseIn(D8, HIGH) + pulseIn(D8, LOW) to calculate the frequency.
If that gives an approximately correct result, I'll tell you the secret of why measuring the output of the encoder gives a completely different answer.
I'm using that method and at 62.5kHz it should give a total period of 16 microseconds, but it gives 11. That's when the two pins are connected directly.
Well, pulseIn() is only accurate to about 4us on many types of Arduino like Uno, so 11 may be as close as you will get.
Now I'll tell you the secret.
You seem to think that the PWM frequency determines the motor speed. That's completely wrong. If it were right, you would not need an encoder at all.
In fact, the PWM frequency has very little effect on the motor speed at all. The usual reason for selecting a higher frequency is to avoid unpleasant audible noise from the motor, by using a frequency above human hearing range.
The duty cycle of the PWM signal, not the frequency, affects the motor speed. Even the duty cycle does not determine the motor speed, it only affects it.
A 100% duty cycle will make the motor run at the maximum speed it can, based on the motor's design, the voltage powering it and the load it is connected to.
50% duty cycle will not be half speed. It may be approximately half speed if you are lucky. The relationship between duty cycle and motor speed is not linear.
Probably somewhere between 10% and 30%, the motor will start/stop running completely.
const int pulsePin = 8; // Input signal connected to Pin 12 of Arduino
int pulseHigh; // Integer variable to capture High time of the incoming pulse
int pulseLow; // Integer variable to capture Low time of the incoming pulse
float pulseTotal; // Float variable to capture Total time of the incoming pulse
float frequency; // Calculated Frequency
void setup()
{
pinMode(pulsePin, INPUT);
pinMode(5, OUTPUT);
TCCR0B = TCCR0B & B11111000 | B00000001; // PWM 62.5 kHz pins 5 and 6
Serial.begin(9600);
}
void loop()
{
int T = 255; // Period
float dT = 0.9; // Duty Cycle
float T_on = T-(T*dT);
analogWrite(5, T_on);
pulseHigh = pulseIn(pulsePin, HIGH);
pulseLow = pulseIn(pulsePin, LOW);
pulseTotal = pulseHigh + pulseLow; // Time period of the pulse in microseconds
frequency = 1000000/ pulseTotal; // Frequency in Hertz (Hz)
Serial.println(frequency);
}
That appears to be wrong, on the face of it. That would be the off-period, not the on-period. Perhaps your motor driver circuit inverts the signal from the PWM pin?
Ok, you are now ready to do some experiments to determine the relationship between duty cycle and motor speed for your motor. Maybe try 0%, 10%, 20%... 90%, 100% etc.
What duty cycle does your motor start running at? What speed does it run at that duty cycle?
What speed does it run at for 100% (the maximum speed)?
What duty cycle gives 50% of the maximum speed?
What effects does changing the PWM frequency have, for the same duty cycle?
If you reduce the duty cycle slowly from 50%, at what duty cycle does the motor stop? (This will probably be quite a lot lower than the duty cycle it starts with)
I'm suggesting these experiments for your learning, I have done similar in the past, for example with various fans out of PCs. Even two fans of the same size & brand won't be quite the same as each other.