I've had some serious issues trying to get a semi accurate % Duty Cycle Reading. When I was Testing the code, it was reading Duty Cycle from a square function generator but only on a very low frequencies (10-20Hz). Despite the fact %DC was far away from being accurate, was changing as function generator frequency was being increased and in certain cases it was going up to couple thousand... Hardware seems to work fine, I'm sure the problem is in my sloppy coding. I would like to make this code work for frequencies of at least 500-1000Hz Any help from more experienced coders will be greatly appreciated!
//~~~LED DRIVER~~~//
int ledPins [] = { 3, 5, 6, 9, 10 }; // PWM pints driving NPN Transistors
//~~~LED TIMERS~~~//
bool DriveIndividual= false; // true drives one LED at the time on intro. False keeps the whole row on
int timer1 = 130; // LED time on
int timer1d = 40; // deley between different LED rows [only used when DriveIndividual==true]
int timer2 = 120; // blinks on shift light
int bright = 150; // LED brightness Value between 0 and 255
//~~~SIGNAL SETUP~~~//
int Signal_1 = 20; // Duty Cycle % required to turn led 1 on
int Signal_2 = 35; // PWM required to turn led 2 on
int Signal_3 = 50; // PWM required to turn led 3 on
int Signal_4 = 65; // PWM required to turn led 4 on
int Signal_5 = 75; // PWM required to turn led 5 on
int Signal_6 = 90; // PWM required to blink led 5 on
int Sig_buff = 6; //+/- from PWM
//~~~PWM SETUP~~~//
volatile unsigned long fall_Time = 0; // Placeholder for microsecond time when last falling edge occured.
volatile unsigned long rise_Time = 0; // Placeholder for microsecond time when last rising edge occured.
volatile byte dutyCycle = 0; // Duty Cycle %
volatile unsigned long lastRead = 0; // Last interrupt time (needed to determine interrupt lockup due to 0% and 100% duty cycle)
//~~~INTERRUPT~~~//
void PinChangeISR0() { // Pin 2 (Interrupt 0) service routine
lastRead = micros(); // Get current time
if (digitalRead(2) == LOW) {
// Falling edge
fall_Time = lastRead; // Just store falling edge and calculate on rising edge
}
else{
// Rising edge
unsigned long total_Time = rise_Time - lastRead; // Get total cycle time
unsigned long on_Time = fall_Time - rise_Time; // Get on time during this cycle
total_Time = total_Time / on_Time; // Divide it down
dutyCycle = (100 * on_Time) / total_Time; // Convert to a percentage
rise_Time = lastRead; // Store rise time
}
}
void Intro(){
//~~~BLINK UP~~~//
for(int i=0; i<4; i++){
if (DriveIndividual == true){
analogWrite(ledPins [i], bright);
delay(timer1);
analogWrite(ledPins [i], 0);
delay(timer1d);
}
if (DriveIndividual == false){
analogWrite(ledPins [i], bright);
delay(timer1);
}
}
//~~~TOP ROW BLINK~~~//
for(int i=0; i<4; i++){
analogWrite(ledPins [4], bright);
delay(timer2);
analogWrite(ledPins [4], 0);
delay(timer2);
}
//~~~BLINK DOWN~~~//
for(int i=4; i>=0; i--){
analogWrite(ledPins [i], bright);
delay(timer1);
analogWrite(ledPins [i], 0);
delay(timer1d);
}
}
void RPM(){
static unsigned long oldLastRead = lastRead;
if (oldLastRead != lastRead) {
Serial.print(" Duty Cycle = ");
Serial.print( dutyCycle );
//Serial.print("\n");
oldLastRead = lastRead;
//DRIVE LEDS
for(int i = 0; i<5; i++){
analogWrite (ledPins [i], 0);
}
if(dutyCycle <= Signal_1){
analogWrite(ledPins [0], bright);
Serial.println(" Led 1 ON ");
}
else if(dutyCycle <= Signal_2){
analogWrite(ledPins [1], bright);
Serial.println(" Led 2 ON ");
}
else if (dutyCycle <= Signal_3){
analogWrite(ledPins [2], bright);
Serial.println(" Led 3 ON ");
}
else if (dutyCycle <= Signal_4){
analogWrite(ledPins [3], bright);
Serial.println(" Led 4 ON ");
}
else if (dutyCycle <= Signal_5){
analogWrite(ledPins [4], bright);
Serial.println(" Led 5 ON ");
}
/*else if (dutyCycle <= Signal_6 ){
do {
unsigned long prevTime = 0;
unsigned long Time = millis();
int state = 0; //start from LOW State
if((Time - prevTime) >= 200){
prevTime = Time;
if(state == 0){
state = bright;
Serial.println(" BLINKING LED 5 ");
}
if(state == bright){
state = 0;
}
}
analogWrite(ledPins [4], bright);
} while(dutyCycle <= Signal_6 && dutyCycle >Signal_5);
}*/
else { // No interrupt since last read so must be 0% or 100%
if (digitalRead(2) == LOW) {
Serial.print("0");
}
else {
Serial.print("100");
}
}
// delay(20); // Freeze microcontroller?
}
}
void setup(){
for(int i=0; i<5; i++){
pinMode(ledPins [i], OUTPUT);
}
Serial.begin(115200);
//~~~INTERRUPT~~~//
pinMode(2, INPUT);
Serial.println(F("ISR Pin 2 Configured For Input."));
attachInterrupt(0, PinChangeISR0, CHANGE);
Serial.println(F("Pin 2 ISR Function Attached."));
Intro(); // Drive all LEDs
}
void loop(){
RPM();
}