PWM to PWM stepdown

Hi
I need to take a 12v hall effect sensor and reduce the PWM to an output. I dont know the ratio yet.
I found this one going the other way here
http://forum.arduino.cc/index.php?topic=102250.0

Can i get away with changing the pwminperiod to 1k Hz and the pwmoutperiod to whatever the ratio turns out to be, say 500Hz for arguments sakes.

Andy

// PWM input 1 variables
byte pwmIn1IO = 2;                             // IO used to measure PWM input 1, IO 2 is also interrupt 0
volatile unsigned long pwmIn1PulseStartTime;   // store PWM pulse start time in uS
volatile long pwmIn1PulseElapsedTime;          // store PWM pulse length in uS
unsigned long pwmIn1Period = 500ul;            // used to calc pwmIn1Duty percentage, 500 uS = 2K Hz
byte pwmIn1Duty;                               // PWM pulse length converted to duty cycle in percent * 100
volatile boolean pwmIn1Ready;                  // used to flag the duty cycle calc after a completed PWM pulse measurement
unsigned long pwmIn1Timeout = 50;              // uS added to pwmIn1Period for the timeout
volatile boolean pwmIn1Invert = 1;             // used to invert input PWM readings
// PWM output 1 variables
byte pwmOut1Pin = 8;                    // IO for PWM ouput 1
unsigned long pwmOut1Period = 100000ul; // base period in uS for PWM out 1, 10Hz
unsigned long pwmOut1PulseTime = 0ul;   // pulse active time in uS
unsigned long pwmOut1PrevEndTime = 0ul; // previous PWM period end time in uS
boolean pwmOut1State = 0;               // tracks the current phase of the PWM output, ie active or inactive ("on" or "off")
boolean pwmOut1Invert = 0;              // used to invert PWM output, '0' means active is HIGH or 5V

void setup() {
  // set IO modes
  pinMode(pwmIn1IO, INPUT);
  digitalWrite(pwmIn1IO, HIGH);    // set internal pullup resistor
  attachInterrupt(0, pwmIn1Trigger, CHANGE);    // catch interrupt 0 (IO 2) changing state and send to pwmIn1Trigger()
  pinMode(pwmOut1Pin, OUTPUT);
  digitalWrite(pwmOut1Pin, pwmOut1Invert);
}

void loop(){

  // if a pulse has been measured
  if (pwmIn1Ready){
    pwmIn1Ready = false;
    if (pwmIn1PulseElapsedTime <= pwmIn1Period){    // to help deal with 0% or 100% duty cycle conditions, let the timeout code deal with it
      pwmIn1Duty = (int)(pwmIn1PulseElapsedTime * 100ul / pwmIn1Period); // calc duty cycle of input pwm
      pwmIn1Duty = constrain(pwmIn1Duty,0,100);
      pwmOut1PulseTime = pwmIn1Duty * pwmOut1Period / 100ul; // calc output pwm's pulse time in uS
    }
  }  
  // timeout code, if input pwm does not finish a measurement due to 0% or 100% duty cycle, ie. there are no pulses to trigger the interrupt
  if (micros() > pwmIn1PulseStartTime + pwmIn1Period + pwmIn1Timeout){  
    if (digitalRead(pwmIn1IO) == pwmIn1Invert){
      pwmOut1PulseTime = 0;              // set 0 duty cycle
    } else {
      pwmOut1PulseTime = pwmOut1Period;  // set max duty cycle
    }
    pwmIn1PulseStartTime = micros();     // reset pwm in pulse start time
  }  
  // if output pwm is "active", check for end of pulse time
  if (pwmOut1State){
    if (micros() >= (pwmOut1PrevEndTime + pwmOut1PulseTime)){
      digitalWrite(pwmOut1Pin, pwmOut1Invert);  // pulse "active" time has expired, toggle pwm output IO
      pwmOut1State = 0;    // set state tracking flag
    }
  }
  // if output pwm is "inactive" or "off", check for end of pwm period time
  if (!pwmOut1State){
    if (micros() >= (pwmOut1PrevEndTime + pwmOut1Period)){
      digitalWrite(pwmOut1Pin, !pwmOut1Invert);
      pwmOut1PrevEndTime = micros();  // originally I used (pwmOut1PrevEndTime += pwmOut1Period)
                                      // depends which is more important, steady frequency or accurate pwm "active" pulse length
      pwmOut1State = 1;
    }    
  }
}

// runs when interrupt is triggered
void pwmIn1Trigger(){
  if (digitalRead(pwmIn1IO) != pwmIn1Invert){
    pwmIn1PulseStartTime = micros();
  } else {
    pwmIn1PulseElapsedTime = micros() - pwmIn1PulseStartTime; // may glitch during timer wrap-around
    pwmIn1Ready = true;
  }
}

Hi,

andy120:
Hi
I need to take a 12v hall effect sensor and reduce the PWM to an output. I dont know the ratio yet.
I found this one going the other way here
PWM to PWM converter - Project Guidance - Arduino Forum

Can i get away with changing the pwminperiod to 1k Hz and the pwmoutperiod to whatever the ratio turns out to be, say 500Hz for arguments sakes.

Andy

Can you post a link to the Hall Effect sensor please, it sound unusual that it has a PWM output.
Tom..... :slight_smile:

TomGeorge:
...post a link to the Hall Effect sensor please, it sound unusual that it has a PWM output.

Perhaps he means converting the frequency of pulses from the Hall Effect switch to a PWM? We shall see.

You appear to be unaware of the PulseIn() function.

Hi
The sensor produces a pulse stream (+12 in, pulse out), which i think starts at 600-700Hz and maxs around 5kHz.
The output i suspect will start from 300Hz.
To understand pulsein, gives me the duration of a pulse from rise to rise. So I could total a second (=> RPS) using running average, and display via serial.
Can I then divide what RPS by various ratios to give the proportional PWM out.

Is that heading in the right direction?

Andy

Hi,

  • So the sensor is outputting a string of Pulses.
  • The pulse interval changes, that is it FREQUENCY not PWM. (tacho sensor)
  • You want to convert the frequency to a PWM duty cycle, 0 to 100%

Is there a spec on what the output PWM frequency has to be?
What does the PWM output do or go to?
Can you post the spec on the Hall Effect device please?
Is its output 12V pulses or open collector?

Tom..... :slight_smile:

Please explain: do you want an output signal with a frequency proportional to the RPM, or a PWM signal with a duty cycle proportional to the RPM?