0

I would like to control a DC motor's speed using the PWM output from my motherboard header.

Here's the standard pinout for a 4-wire PC fan header:

╔═══╦════════╦═════════════════╦════════╗
║ # ║  Name  ║   Description   ║  Wire  ║
╠═══╬════════╬═════════════════╬════════╣
║ 1 ║ GND    ║ Ground          ║ black  ║
║ 2 ║ +12V   ║ Fan Power       ║ yellow ║
║ 3 ║ SIGNAL ║ Fan RPM         ║ green  ║
║ 4 ║ PWM    ║ Digital Control ║ blue   ║
╚═══╩════════╩═════════════════╩════════╝

Since my DC motor doesn't have a PWM input, I thought of using an ATmega328P in my custom board to read the PWM output of the fan header -- pin 4 -- so that I can use a motor driver to control my motor's speed.

However, I'm not sure how I should read the PWM signal from the motherboard.

  1. What is the HIGH voltage level of PWM output?
    Do I need a voltage divider resistor for it?

    A source for the fan control specifies this to be 5.25V at maximum, but since I haven't tested it out myself, I don't want to risk feeding a 12V signal to my microcontroller's input lines.

  2. Should I use pulseIn() function for the 25kHZ (21~28kHZ range) PWM output?
    Can the ATmega328p handle this frequency range?

I prefer to use Arduino's bootloader with the wiring library, but if you have AVR-specific examples that I could follow, I'd appreciate it.

2
  • 1
    The PWM signal controlling the fan is allowed to be from 21 to 28kHz. The pulses for the RPM indicator are simply one (or two) pulses per rotation. Assuming 10000RPM (insanely high speed for a fan) and two pulses per rotation, you only get RPM pulses at a little over 300Hz. Those can easily be read by an Arduino.
    – JRE
    Commented Feb 6, 2019 at 10:24
  • But, not neccessarily using the "pulse" command. That gives you the width of the pulse, but not the time between pulses.
    – JRE
    Commented Feb 6, 2019 at 10:26

1 Answer 1

1

Should I use pulseIn() function for the 25kHZ (21~28kHZ range) PWM output? Can the ATmega328p handle this frequency range?

No, and No; 1/25000 = .000040 or 40 microseconds (μS) and the documentation for pulseIn() says:

Works on pulses from 10 microseconds to 3 minutes in length

However the PWM frequency is the maximum on time, at 50% you will have a square wave that is HIGH for 20 μS and low for 20 μS. pulseIn will not work if the PWM duty cycle goes below 25%

What you want to do is put an 'accumulator' (an RC filter) between the PWM output and an analog input pin, and read the voltage off of that.

However since you want to

... control a DC motor's speed using the PWM output from my motherboard header

and the fanspeed header is already designed to do this, you just use the PWM signal to drive a transistor that drives the motor, the motor itself will act as an accumulator here; no micro controller needed!

... so that I can use a motor driver to control my motor's speed.

you will need to generate an extremely similar, almost certainly identical, PWM signal to drive your motor controller/driver

A source for the fan control specifies this to be 5.25V at maximum, but since I haven't tested it out myself, I don't want to risk feeding a 12V signal to my microcontroller's input lines.

Trust your documentation or test it if you don't trust the docs!

2
  • +1, Thanks for the well-explained answer, your solution makes sense! Although in addition to driving a motor, I still would really like to read the PWM output with something and feed the data to my microcontroller, so I can for instance display it. Is there a way I can achieve this digitally instead of using an RC filter? Commented Feb 9, 2019 at 7:28
  • @DavidRefoua analogRead(...) will return a value between 0..1023; where 0 is 0V and 1023 is 5V; the RC filter is to stabilize the voltage so the ADC can read it.
    – esoterik
    Commented Feb 11, 2019 at 23:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.