I'm needing to create a PWM routine with a variable frequency and variable pulsewidth, controlled through two POTs.
The frequency should be adjustable, from 1-200 Hz
The pulsewidth should be adjustable, from 100-300 uS
It seemed pretty simple but I'm no programmer and basically pieced this together from code snippets I've found so I'm thinking there is a simpler, better way of doing this? Also since I'm counting microseconds in a 'long' I'm not sure what will happen when this variable overflows?
I tried it with a simple delayMicroseconds() at first and ran into timing issues trying to read the pots AND keep the pulse going steady.
Anyway here's my code:
// constants won't change. Used here to set pin numbers:
const int frequencyPin = A0; // pin that the frequency sensor is attached to
const int pulsewidthPin = A5; // pin that the pulse-width sensor is attached to
const int outputPin = 9; // pin that the LED is attached to
// Variables will change:
long previousMicros = 0; // will store last time LED was updated
long period = 0; // period at which to blink (microseconds)
int frequencyValue = 0; // the frequency value
int frequencyMin = 1023; // minimum frequency value
int frequencyMax = 0; // maximum frequency value
int pulsewidthValue = 0; // the pulsewidth value
int pulsewidthMin = 1023; // minimum pulsewidth value
int pulsewidthMax = 0; // maximum pulsewidth value
void setup() {
// set the digital pin as output:
pinMode(outputPin, OUTPUT);
// turn on LED to signal the start of the calibration period:
pinMode(13, OUTPUT);
digitalWrite(13, HIGH);
// calibrate during the first five seconds
while (millis() < 5000) {
frequencyValue = analogRead(frequencyPin);
pulsewidthValue = analogRead(pulsewidthPin);
// record the maximum frequency value
if (frequencyValue > frequencyMax) {
frequencyMax = frequencyValue;
}
// record the minimum frequency value
if (frequencyValue < frequencyMin) {
frequencyMin = frequencyValue;
}
// record the maximum pulsewidth value
if (pulsewidthValue > pulsewidthMax) {
pulsewidthMax = pulsewidthValue;
}
// record the minimum pulsewidth value
if (pulsewidthValue < pulsewidthMin) {
pulsewidthMin = pulsewidthValue;
}
}
}
void loop() {
// read the sensor:
frequencyValue = analogRead(frequencyPin);
pulsewidthValue = analogRead(pulsewidthPin);
// apply the calibration to the frequency reading
frequencyValue = map(frequencyValue, frequencyMin, frequencyMax, 1, 200);
// in case the frequency value is outside the range seen during calibration
frequencyValue = constrain(frequencyValue, 1, 200);
// apply the calibration to the pulsewidth reading
pulsewidthValue = map(pulsewidthValue, pulsewidthMin, pulsewidthMax, 100, 300);
// in case the pulsewidth value is outside the range seen during calibration
pulsewidthValue = constrain(pulsewidthValue, 100, 300);
// check to see if it's time to blink the LED; that is, if the
// difference between the current time and last time you blinked
// the LED is bigger than the interval at which you want to
// blink the LED.
unsigned long currentMicros = micros(); // this will hold the current time
period = 1000000/frequencyValue; // calculate the time between on-pulses
if(currentMicros - previousMicros > period) {
// save the last time you blinked the LED
previousMicros = currentMicros;
digitalWrite(outputPin, HIGH);
delayMicroseconds(pulsewidthValue);
digitalWrite(outputPin, LOW);
}
}