PWM and RC filter

I’ve managed to make a PWM output supply a voltage through an RC filter quite well on a Nano.

I am using the code to generate a RPM value in thousands of revs. That value is then converted to make 2000 revs per volt on the RC filtered output.

Code line that displays revs per volt is;

analogWrite (outPin1, ((rpm_val/2000) * 255)/5);.

I use 2000 because I want it to limit at 10000 revs (5v).

Ive tested it by replacing rpm_val with numbers from 1000 to 10000 which is the max I need.

At 10,000 it limits at 4.5v and I ideally need it to run to 5v to feed a bar graph driver.

if I change the 255/5 to 255/4.5 (or any other number) it doesnt make any difference. Bit new to this…

The analog output is a fraction of the supply voltage , so if that is below 5v so will be the output . It may never quite reach 5v anyway .

You need an RC filter to generate the steady DC voltage , getting the values correct so as not to load the arduino or to have too high a resistance as to be significant compared to the LCD input needs thinking about ( the “R” makes a potential divider with the “Lcd” input impedance ).

Why not drive an LCD Display digitally from the Arduino direct, then you can make it read whatever you want .


I've got the RC working quite well and as you say it limits just below 5v.

Is my code line doing a correct conversion for a 10000 rev scale?
What doesnt anything shange if I divide by 4.5 instead of 5?


What doesnt anything shange if I divide by 4.5 instead of 5?

You haven't posted enough information for us to figure out why not, but be VERY CAREFUL about the difference between integer divides and floating point divides.

If RPM is declared integer, from 0 to 10000, then the results of division by 2000 are the exact integers 0,1,2,3,4, or 5. You get at most six steps in the output.

Post ALL the code.

here is the whole code;

int hall_pin = 3;
// set number of hall trips for RPM reading (higher improves accuracy)
float hall_thresh = 10.0;
const int outPin1 = 6; //check is pwm output pin to drive lm3914 or should
//TCCR4B = TCCR4B & B11111000 | B00000001;    // set timer 4 prescaler to 1 for PWM frequency of 31372.5 Hz

void setup() {
  pinMode(hall_pin, INPUT);
  pinMode (outPin1,OUTPUT);

void loop() {
    float hall_count = 1.0;
  float start = micros();
  bool on_state = false;
  // counting number of times the hall sensor is tripped
  // but without double counting during the same trip
  while(true){//keeps running while true but what makes it true?
    if (digitalRead(hall_pin)==0){//every time hall is switched to 0 run if
      if (on_state==false){//already set to false so make true
        on_state = true;
        hall_count+=1.0;//count = (hall_count + 1.0) + new value of hall_count
    } else{
      on_state = false;

   // Serial.println (on_state);
    if (hall_count>=hall_thresh){
    // print information about Time and RPM
  float end_time = micros();
  float time_passed = ((end_time - start)/1000000.0); //micros now - start micros/1second
  Serial.print("Time Passed: ");// in seconds
  float rpm_val = (hall_count/time_passed)*60.0;
  Serial.println(" RPM");
  delay(1);        // delay in between reads for stability
 // analogWrite (outPin1, 255);test write to scale output
 analogWrite (outPin1, ((rpm_val/2000) * 255)/5);//send pwm voltage to lm3914. CHANGE IF DAC USED

Thanks! Please post the evidence that "nothing changes" when replacing 5 by 4.5.


I have a scope and am looking at the voltage output

The analog output (if i write 255) limits to about 4.5v through the RC filter which seems normal.

so the main question is if I want the output to scsle to 10000 is the code line right below given I limit at 4.5v?

analogWrite (outPin1, ((rpm_val/2000) * 255)/5);

Appreciate the help.

The output of the filter saturates at some value less than Vcc, so it will probably make no difference if you set the PWM value to 255, or a bit less. The question is: how much less to actually see a difference?

For the moment, forget the rpm stuff, and just investigate the relationship between the PWM value and the filter output voltage, for a selection of PWM values between 0 and 255.

So I set uo the first line to just scale the output from 0-255 and it scales well across the range upto about 4.5v.

The second line is the conversion line to use instead of the test line to make it limit at 10,000 revs. Its this line that I need the sanity check on. Will it work? I think I am making every 1v of output equal to 2000 revs? If i lower the 5 divider my output goes up correspondingly so I think I am right.

analogWrite (outPin1, 126);//test write to scale output

 analogWrite (outPin1, ((rpm_val/10000) * 255)/5);

My next problem is I am driving a LM3914 with 10 LED's and the scaling seems wrong. Most of the lights go on if I use the test line with 255 or as low 50. I can see the voltage ouput going up which is fed to the 3914 input.

Ive looked at examples and have the supply voltage above the input voltage and the reference resistors look OK but I cant see whats wrong.

The output from the 3914 to the LED's only seems to scale (lights go on as the voltage rises) upto 1v

I made some improvement on scaling but.....

The circuit is

I've set the resistors so the reference input on pin 8 is 4.5v but when I send 255 to the output (which scopes at 4.5v) the last 3/4 LED's dont light and the 3914 O/Ppins for those lights remain low.

Note: pin 3 needs to be at least 1.5v above max input voltage so the sketch above is wrong. I fed mine from 9v.

Ok I worked it out. Thanks for the help.

Combination of not having the voltage right on pin 8 (needs to be 4.5) and stupidly not suppling 5v to the last set of LED's !!!

Also in my final scalining code line changes the O/P voltage accordingly so I can work out the 10000 rev scaling.

Thanks for the pointers guys