Jump to content

DIY fan controller with Arduino

Olaf6541
Go to solution Solved by Olaf6541,

Last update of this topic

I've installed the fan controller in the pc:

 

vRxiivS.jpg

 

And a comparison of the LEDs off vs on, I also placed the temp sensor into the loop:

 

3MQ3gqo.jpg

 

UImJYgq.jpg

 

Currently tweaking the fan curves for the fans, everything seems to work as intended. ?

Thanks everyone for the help, you guys were very helpful!

Hi all,

After concluding that my current motherboard doesn't really have the capabilities for my custom waterloop that I'm lookiing for, I decided I want to make my own controller.

I will be using an Arduino Uno in combination with the motherboard PWM signal. The PWM signal is set to a fixed RPM and the Arduino uses a temperature sensor in the waterloop to determine when a group of fans has to be switched on. A molex connector will serve as the power input, using the 5v for powering a relay controlled by the Arduino and the 12v connected to the PWM connectors. This way the PWM header can supply much more than 1A and switch between off and fixed RPM. I ordered a dual ssd pcie bracket board and a 1-to-3 molex pcie bracket splitter to create a dual pcie slot fan controller.

 

- Is the scheme below correct?

- If I shutdown my PC (and therefore power to the Arduino) and turn it back on will the Arduino just boot and continue to run its program?

- The 'standard' 2pin temperature sensors for motherboards and fan controllers are just simple 10k NTC thermistors?

WOBJrgT.png

Link to comment
Share on other sites

Link to post
Share on other sites

Seems overly complicated.

When your circuit receives power, it means the computer is turned on. Why would you need to monitor the pwm signal from the motherboard?

relays are not really required, it's kind of excessive and it would annoy you with the constant clicks. Also adds complexity since the arduino uno output pins most likely won't have enough current capability to keep so many relays energized.

Cheap 5v relays will need probably around 30-50mA constant current to stay latched, and your Arduino can probably do 15ma per pin or something like that.

If you really need/want relays, use 12v relays since you have 12v anyway, and use a cheapo npn transistor in-between your arduiono and the relay (and add a diode for protection) ... see the video below about using npn transistors to turn on stuff.

Anyway, you don't really need isolation, so you can just use a npn transistor directly connected to the arduino output pin, with the right hFe value and base current (2-3mA would be plenty) 1A+ is possible.

 

There's all kinds of temperature sensors. Yeah, you can use NTCs or PTCs and use ADC to convert resistance to voltage. There's also "digital" temperature sensors which use 1-wire or i2c or spi to send you the temperature.

Here's for example a 1wire temperature sensor, MAX31820 https://www.digikey.com/product-detail/en/maxim-integrated/MAX31820MCR/MAX31820MCR-ND/4271348

You have cheaper sensors like MCP9700 or the more precise LMT8xLP  which simply output a voltage (10mV/degree celsius for the microchip part), so you can ADC : https://www.digikey.com/product-detail/en/microchip-technology/MCP9700-E-TO/MCP9700-E-TO-ND/1212509 or https://www.digikey.com/product-detail/en/texas-instruments/LMT87LP/296-37821-ND/4876350

 

(forgot to embed video i mentioned, see below)

Link to comment
Share on other sites

Link to post
Share on other sites

2 hours ago, James Evens said:

Basically you are looking at this:

Yea seems pretty similar.

2 hours ago, James Evens said:

You can also power the arduino with the 5V from the PSU. Also double check that you don't need a opamp and/or voltage divider for the thermo element .

I need an USB datalink anyway so I figured I could just use the 5V from USB, and I'm actually planning on using a voltage divider to measure the resistance on the thermistor. I already wrote the Arduino code to get the temperature from this.

2 hours ago, James Evens said:

If  you shutdown and restart the pc the arduino will also restart.

Thanks, just needed someone to confirm that.

13 minutes ago, mariushm said:

When your circuit receives power, it means the computer is turned on. Why would you need to monitor the pwm signal from the motherboard?

I'm not monitoring the PWM signal, I'm just combining a fixed PWM signal with an on/off switch on the 12V.

15 minutes ago, mariushm said:

Cheap 5v relays will need probably around 30-50mA constant current to stay latched, and your Arduino can probably do 15ma per pin or something like that.

I assumed the relay board draws power from the 5V Vcc input provided by molex from the PSU?

16 minutes ago, mariushm said:

There's all kinds of temperature sensors. Yeah, you can use NTCs or PTCs and use ADC to convert resistance to voltage. There's also "digital" temperature sensors which use 1-wire or i2c or spi to send you the temperature.

I have a spare temp sensor from a fan controller lying around which I will be using for some testing but I was actually looking at something liike this: temp sensor. Unfortunately there is not much info on this product other than that it is 10k Ohm...

Link to comment
Share on other sites

Link to post
Share on other sites

I forgot to embed the video that explains how to use npn transistors (and mentions the reason for protection diode), very informative if you would want to make something yourself:

 

 

Link to comment
Share on other sites

Link to post
Share on other sites

Relays are totally unnecessary. As mentioned above, they add complexity and annoyances to your setup. I've used relays in the past couple arduino projects I've done and the coils typically draw nearly 200ma to stay latched, which is way more than a digital IO pin can supply on an arduino. You need to have a transistor to switch the relay, but since you aren't dealing with that much power, you might as well cut out the relay middle man and have your fans controlled by transistors.

 

For controlling the fans, I think you should keep your motherboard and arduino separate. Have the arduino generate the PWM signal based on the temperature of the water, and let the motherboard do its own thing. Just keep in mind the motherboard will probably yell at you if you don't have a fan or pump or something plugged into the CPU fan header.

 

That alphacool temperature sensor you found is probably a 10k thermistor, which is a resistor that changes its resistance linearly with temperature. Here's how to use them with arduino. https://learn.adafruit.com/thermistor/overview

 

 

ASU

Link to comment
Share on other sites

Link to post
Share on other sites

25 minutes ago, Hackentosher said:

Relays are totally unnecessary. As mentioned above, they add complexity and annoyances to your setup. I've used relays in the past couple arduino projects I've done and the coils typically draw nearly 200ma to stay latched, which is way more than a digital IO pin can supply on an arduino. You need to have a transistor to switch the relay, but since you aren't dealing with that much power, you might as well cut out the relay middle man and have your fans controlled by transistors.

Yea it is probably better to use transistors for this, I will look into that.

26 minutes ago, Hackentosher said:

For controlling the fans, I think you should keep your motherboard and arduino separate. Have the arduino generate the PWM signal based on the temperature of the water, and let the motherboard do its own thing. Just keep in mind the motherboard will probably yell at you if you don't have a fan or pump or something plugged into the CPU fan header.

Actually the first thing I did was looking for a way to use the PWM signal from the Arduino, but this is only at 500Hz and nowhere near the 25kHz needed. I read some threads online of people trying to get this to work and fans reacts very odd if the frequency is way off. I found some suggestions but it requires to fiddle with the internal clockspeeds and doesn't work that well for multiple outputs... And dont worry I already turned that 'feature' off.

 

But indeed, being able to generate a 25kHz PWM signal on the Arduino would make thing way less complicated...

Link to comment
Share on other sites

Link to post
Share on other sites

1 minute ago, Olaf6541 said:

Yea it is probably better to use transistors for this, I will look into that.

The video linked above me is great information, very informative

Quote

Actually the first thing I did was looking for a way to use the PWM signal from the Arduino, but this is only at 500Hz and nowhere near the 25kHz needed. I read some threads online of people trying to get this to work and fans reacts very odd if the frequency is way off. I found some suggestions but it requires to fiddle with the internal clockspeeds and doesn't work that well for multiple outputs... And dont worry I already turned that 'feature' off.

 

But indeed, being able to generate a 25kHz PWM signal on the Arduino would make thing way less complicated...

Interesting, I didn't know that. Maybe if you get an arduino with more balls, like something with a cortex m4? 

ASU

Link to comment
Share on other sites

Link to post
Share on other sites

If you're not afraid of a bit of surface mount soldering, Microchip has some nice fan controller parts (they bought a company making them, like they did with Arduino)

Check out EMC2305 which allows you to control up to 5 fans : https://www.digikey.com/product-detail/en/microchip-technology/EMC2305-1-AP-TR/EMC2305-1-AP-CT-ND/4490169

 

The only catch is that it's a 3.6v max part, and that it's SMBUS but SMBUS is easy, it's just another serial protocol and you'll probably find libraries made for Arduino.

As for being a 3.6v max part, the serial data and clock pins are 5v tolerant, so you can safely wire it with a 5v micro .. you just need a ldo for the chip.

 

At 2$ it's worth buying one just to mess around with .. and it's not that hard to solder, all pads but the center pad are visible on the edges.

 

There's also EMC2303 which controls up to 3 fans, so you could basically interact with 2 of them if you want 6 fan headers.. and they're cheap at 1.28$ : https://www.digikey.com/product-detail/en/microchip-technology/EMC2303-1-KP-TR/EMC2303-1-KP-CT-ND/4490168

 

See this demo board, you can download schematic from "Documents and Software" section for a real life example... you can simplify the board for your needs :

ADM00879 - EMC2305 & EMC1438 Fan Ctrl and Temp Demo  : https://www.microchip.com/Developmenttools/ProductDetails/ADM00879

 

 

 

Link to comment
Share on other sites

Link to post
Share on other sites

1 hour ago, mariushm said:

If you're not afraid of a bit of surface mount soldering, Microchip has some nice fan controller parts (they bought a company making them, like they did with Arduino)

Check out EMC2305 which allows you to control up to 5 fans : https://www.digikey.com/product-detail/en/microchip-technology/EMC2305-1-AP-TR/EMC2305-1-AP-CT-ND/4490169

 

The only catch is that it's a 3.6v max part, and that it's SMBUS but SMBUS is easy, it's just another serial protocol and you'll probably find libraries made for Arduino.

As for being a 3.6v max part, the serial data and clock pins are 5v tolerant, so you can safely wire it with a 5v micro .. you just need a ldo for the chip.

 

At 2$ it's worth buying one just to mess around with .. and it's not that hard to solder, all pads but the center pad are visible on the edges.

 

There's also EMC2303 which controls up to 3 fans, so you could basically interact with 2 of them if you want 6 fan headers.. and they're cheap at 1.28$ : https://www.digikey.com/product-detail/en/microchip-technology/EMC2303-1-KP-TR/EMC2303-1-KP-CT-ND/4490168

I did some digging online and found a more in depth guide on how the pwm function on Arduino works:

https://www.arduino.cc/en/Tutorial/SecretsOfArduinoPWM

That guide suggest I can assign duty cycles to a custom frequency, so if I can get two timers to a frequency of 25kHz I have the control I was looking for.

 

ZgCpmmn.png

If I set OCR2A to 9 that gives 16Mhz / 64 / (9+1) = 25kHz. With OCR2B set to (n+1) I can select duty cycles of 10%, 20%, 30%, etc.

 

First I need to get the temperature sensor part done, then I will look into how well my fans (ML120, EVO 120S) react to the PWM signals of the Arduino. If this fails I can borrow the PWM signals of the motherboard.

 

As for the transistors, is this something that makes sense?

 

2FP6hyR.png

Edited by Olaf6541
Link to comment
Share on other sites

Link to post
Share on other sites

Yeah, the transistor part looks ok, but you don't have to be so super exact with the values. Also, it's best to pick values so you'll know for sure the transistor will be fully on in any conditions. see graphs in datasheet about hfe minimums at specific temperatures and at certain current amounts.

 

There must be a resistor to limit the current going into the pin, but modern transistors typically have high hFe values and you can pick some standard value like 100 / 150 / 180 / 330 / 470 ohm and don't worry so much about it.

For example, here's a 30 cent   PBSS4250X from Nexperia (NXP) with a hFe of 300 : https://www.digikey.com/product-detail/en/nexperia-usa-inc/PBSS4250X115/1727-5750-1-ND/2697143

 

...to be on the safe side, you'd pick 250 for all the computations. So with a super common 470 ohm resistor you'd have ~9mA current which is well bellow the io per pin of arduino, and still allows you 9 x 250 = 2250mA or 2A+ of current.

 

another one that looks good to me is this njt4031 from on semi in sot223 (easier to keep cool) .. safe to use 200 for gain: https://www.digikey.com/product-detail/en/on-semiconductor/NJT4031NT1G/NJT4031NT1GOSCT-ND/1693205

 

Link to comment
Share on other sites

Link to post
Share on other sites

18 minutes ago, mariushm said:

Yeah, the transistor part looks ok, but you don't have to be so super exact with the values. Also, it's best to pick values so you'll know for sure the transistor will be fully on in any conditions. see graphs in datasheet about hfe minimums at specific temperatures and at certain current amounts.

 

There must be a resistor to limit the current going into the pin, but modern transistors typically have high hFe values and you can pick some standard value like 100 / 150 / 180 / 330 / 470 ohm and don't worry so much about it.

For example, here's a 30 cent   PBSS4250X from Nexperia (NXP) with a hFe of 300 : https://www.digikey.com/product-detail/en/nexperia-usa-inc/PBSS4250X115/1727-5750-1-ND/2697143

 

...to be on the safe side, you'd pick 250 for all the computations. So with a super common 470 ohm resistor you'd have ~9mA current which is well bellow the io per pin of arduino, and still allows you 9 x 250 = 2250mA or 2A+ of current.

 

another one that looks good to me is this njt4031 from on semi in sot223 (easier to keep cool) .. safe to use 200 for gain: https://www.digikey.com/product-detail/en/on-semiconductor/NJT4031NT1G/NJT4031NT1GOSCT-ND/1693205

 

The highest load will be a group of 6 ML120's drawing 1.35A at 12V when at full speed, that's why I chose 250 ohm with 100 gain. But higher gain gives much more margin, thanks!

And for connecting this, the base will be attached to an Arduino output pin, the collector to the molex ground and the emitter to the negative of the fans?

Link to comment
Share on other sites

Link to post
Share on other sites

10 hours ago, Olaf6541 said:

The highest load will be a group of 6 ML120's drawing 1.35A at 12V when at full speed, that's why I chose 250 ohm with 100 gain. But higher gain gives much more margin, thanks!  

Yeah but you don't want the transistor to actually limit current, you want it to be just a on/off switch, fully on, fully off ... that's why it's good in this application to let it pass as much current.

Quote

And for connecting this, the base will be attached to an Arduino output pin, the collector to the molex ground and the emitter to the negative of the fans?

No, output pin to resistor, resistor to base.  fan ground to collector, emitter to ground. when energy flows into base pin, there's connection created between collector and emitter so there's energy going between 12v ..fan .. ground

optionally add diode from collector to 12v so that if your fan fails or gets stuck and you get more than 12v on collector it can flow back to 12v safely instead of hitting the transistor with voltage spikes. I don't really think it's needed

 

Just realized you got the C and E wrong in your picture, sorry i was too tired yesterday to notice.

 

 

tran43.gif.d9b75fcf59b4e50fb59bc4f90893a753.gif

 

RL is your fan.

 

See also https://www.electronics-tutorials.ws/transistor/tran_2.html

 

ps. and if this was an application where you'd need the transistor to turn off super fast, you may want to add a resistor (something like 1..10kohm, anything higher than your normal resistor) between base and ground, to discharge the gate to ground when your micro no longer sends energy through the resistor. The capacitance of the base is usually small so the transistor would turn off by itself anyway.

 

This base-ground pin is pretty much needed with mosfets (only mosfets have gate not base, and they don't need gate resistor like transistors do), those have more capacitance, can remain on for seconds unless the gate is pulled down to ground through a resistor

 

See this for example of using mosfet as switch (scroll down below the theory at beginning) : https://www.electronics-tutorials.ws/transistor/tran_7.html

 

tran21.gif.7feb7d520193d7d9a830d47389943903.gif(replace lamp with fan, rin is optional)

Link to comment
Share on other sites

Link to post
Share on other sites

16 hours ago, Olaf6541 said:

But indeed, being able to generate a 25kHz PWM signal on the Arduino would make thing way less complicated...

The arduino runs a AVR at 16Mhz which can easily generate 25Khz hardware PWM with timer 1 & 2...

Heck, 25Khz would even be doable in software.

Link to comment
Share on other sites

Link to post
Share on other sites

1 hour ago, mariushm said:

ps. and if this was an application where you'd need the transistor to turn off super fast, you may want to add a resistor (something like 1..10kohm, anything higher than your normal resistor) between base and ground, to discharge the gate to ground when your micro no longer sends energy through the resistor. The capacitance of the base is usually small so the transistor would turn off by itself anyway.

If that resistor is much larger then the base resistor it will do little to turn off the transistor faster. After all, your micro controller is already pulling the base low trough the smaller base resistor when it wants to turn the transistor off. When the resistor is much smaller then the base resistor it will help, but then you need a much higher voltage on the base resistor to turn the transistor on because the 2 resistors create a divider.

 

Better ways to quickly turn off a transistor fast is to prevent the transistor from saturating. This can be done with a schottky diode between base-collector (Baker clamp), or modify the circuit to use a topology that cannot saturate, such as a emitter-follower.

 

Anyways, we're talking nanoseconds here for small signal transistors, nothing to worry about for this application.

 

As for the MOSFET. Whether or not Rin is optional depends on the gate capacitance and your switching speed. If you're switching a large gate capacitance quickly enough without a gate resistor it'll look like a short to the micro-controller output.

 

Link to comment
Share on other sites

Link to post
Share on other sites

1 hour ago, mariushm said:

Just realized you got the C and E wrong in your picture, sorry i was too tired yesterday to notice.

Yep I somehow managed to get C and E mixed up and I actually meant base with resistor to output, but the drawing itself is correct.

 

1 hour ago, mariushm said:

This base-ground pin is pretty much needed with mosfets (only mosfets have gate not base, and they don't need gate resistor like transistors do), those have more capacitance, can remain on for seconds unless the gate is pulled down to ground through a resistor

When the temperature drops below the threshold the fans don't have to stop instantly, so even if that happens it won't be an issue.

 

So this becomes the updated scheme:

R9UqIsM.png

 

I borrowed the 5V molex pins to send the PWM signal, I could even use the other ground pin for a tacho signal but I'm not really that interested in the actual fan speed. But I guess I could just connect them to A1/A2/A3.

 

I connected the ground of the molex wire into the ground of the Arduino, and also connected the temperature sensor ground to that ground wire. Is that okay?

Link to comment
Share on other sites

Link to post
Share on other sites

On 12/26/2018 at 12:48 PM, Olaf6541 said:

But indeed, being able to generate a 25kHz PWM signal on the Arduino would make thing way less complicated...

How many banks of fans are you trying to individually control speed for? If you're only looking for 2 or less banks, you can do 25khz directly from the arduino with no side effects. If you need 4 or less, you can do this, although you will be halving the clock speed (and thus messing with the results of functions like "delay()" and "millis()").

It has to do with the timer register settings.

Scroll to "timers control": Arduino Register Control

Stack Exchange: https://arduino.stackexchange.com/questions/25609/set-pwm-frequency-to-25-khz

ENCRYPTION IS NOT A CRIME

Link to comment
Share on other sites

Link to post
Share on other sites

1 hour ago, straight_stewie said:

How many banks of fans are you trying to individually control speed for? If you're only looking for 2 or less banks, you can do 25khz directly from the arduino with no side effects. If you need 4 or less, you can do this, although you will be halving the clock speed (and thus messing with the results of functions like "delay()" and "millis()").

It has to do with the timer register settings.

Scroll to "timers control": Arduino Register Control

Stack Exchange: https://arduino.stackexchange.com/questions/25609/set-pwm-frequency-to-25-khz

My current setup consists of 6 identical radiator fans (ML120, 0.225A@12V) and 2 identical exhaust fans (Vardar 120s, 0.046A@12V). I also have a pump and intake fan but they can run at a fixed speed and don't need temperature dependence. So I only need to output 2 different duty cycles at 25kHz.

 

mjMMAIB.png

Link to comment
Share on other sites

Link to post
Share on other sites

@Olaf6541

https://www.amazon.com/Swiftech-8W-PWM-SPL-ST-Way-PWM-Splitter-Sata/dp/B00IF6R4C8

Reading through it seems its mainly the current capability that the motherboard lacks. I like messing around with Arduino but if you just need more fans what I linked is easy. 

 

Otherwise *smiles * 

https://forum.arduino.cc/index.php?topic=415167.0

Dual PWM 25KHz on arduino with code. potential triple 25 KHz

Link to comment
Share on other sites

Link to post
Share on other sites

21 hours ago, r4tch3t said:

Reading through it seems its mainly the current capability that the motherboard lacks. I like messing around with Arduino but if you just need more fans what I linked is easy. 

Actually it's the temperature input that is lacking, my current momtherboard already has 3 independant PWM outputs. But with this Arduino I have two extra temperature dependant PWM outputs, and still some room for other projects.

 

21 hours ago, r4tch3t said:

https://forum.arduino.cc/index.php?topic=415167.0

Dual PWM 25KHz on arduino with code. potential triple 25 KHz

Thanks, that code is very useful so I combined it with the temperature sensor code.

Now it's just waiting for all the packages I ordered. ?

 

float R2, T, V; //Declaration of variables: thermistor R2, temperature and voltage readout of the thermistor.
float c1 = 1.009249522e-03, c2 = 2.378405444e-04, c3 = 2.019202697e-07;  //Steinhart-Hart coefficients (requires calibration).
float R1 = 10000; //Set value of resistor R1.

float Ta = 20.0; //Set temperature threshold A.
float Tb = 25.0; //Set temperature threshold B.
bool Tc = false; //Set trigger condition C.

//Dual 25kHz PWM using Timer1 Mode 10
word pwmA = 160; // 50% duty (0-320 = 0-100% duty cycle)
word pwmB = 80; // 25% duty (0-320 = 0-100% duty cycle)

void setup() {
  Serial.begin(9600);
  pinMode(2, OUTPUT);  //Define output A.
  pinMode(4, OUTPUT);  //Define output B.
  pinMode(7, OUTPUT);  //Define output C.

  pinMode(9, OUTPUT);  //pwmA
  pinMode(10, OUTPUT); //pwmB
  
  TCCR1A = 0;            //clear timer registers
  TCCR1B = 0;
  TCNT1 = 0;
  
  TCCR1B |= _BV(CS10);   //no prescaler
  ICR1 = 320;            //PWM mode counts up 320 then down 320 counts (25kHz)
  
  OCR1A = pwmA;          //0-320 = 0-100% duty cycle
  TCCR1A |= _BV(COM1A1); //output A clear rising/set falling

  OCR1B = pwmB;          //0-320 = 0-100% duty cycle
  TCCR1A |= _BV(COM1B1); //output B clear rising/set falling

  TCCR1B |= _BV(WGM13);  //PWM mode with ICR1 Mode 10
  TCCR1A |= _BV(WGM11);  //WGM13:WGM10 set 1010
}

void loop() {
  V = (float)analogRead(A0);  //Determine voltage over thermistor.
  R2 = R1 * (1023.0 / V - 1.0);   //Determine resistance of thermistor.
  T = (1.0 / (c1 + c2*log(R2) + c3*log(R2)*log(R2)*log(R2))) - 273.15;  //Determine temperature using Steinhart-Hart equation.
  
  if (T >= Ta)  {digitalWrite(2, HIGH);}  //Trigger condition for output A.
  else          {digitalWrite(2, LOW);}
  if (T >= Tb)  {digitalWrite(4, HIGH);}  //Trigger condition for output B.
  else          {digitalWrite(4, LOW);}
  if (Tc)       {digitalWrite(7, HIGH);}  //Trigger condition for output C.
  else          {digitalWrite(7, LOW);}
  delay(1000);  //Repeat every second
}

 

Link to comment
Share on other sites

Link to post
Share on other sites

  • 4 weeks later...

Update time! and some more questions.

 

I removed the the transistors for output A and B since I can turn the fans off using the PWM signal, and added the tachowires for monitoring the fan speed. The temp sensor is now connected through the shared molex connector with the 12V output that I'm now using for three LEDs that are going to help me when I'm doing maintenance inside the rack.

 

oZ5EcC6.png

 

And this is what I've managed to put together so far:

 

xtvxlPl.jpg

 

vRqRTpE.jpg

 

The fans are working on 12V and are reporting a RPM signal so that all works, I don't have access to PWM fans currently so I haven't been able to test that. Also the leds are working fine. The temp sensor turned out to be a 10K NTC sensor as expected, already managed to calibrate it. Still waiting on the transistor to arrive...

 

Alright now the questions:

 

- RPM reading are too high. For a 1200RPM fan 0-100RPM when the fan isn't turning and when it's turning it's fluctuating around 1500-3000RPM. So I think the incoming square wave is not very clean. Can I solve that with a capacitor? (There's an interrupt on the rising edge of the wave that counts the amount of interrupts per second, extrapolating that to RPM. I'm using the internal pull up resistor)

 

- The LEDs are working but they are quite bright (and hot). Also when doing maintenance I'm not putting a lot of heat into the waterloop so I don't need the fans. I guess I could then just upload another code that puts a PWM signal (using delay() function) down pin 7 to the transistor to make a low frequency PWM signal to limit the LED brightness? (e.g. 1 millisecond on, 4 off for 20% -> 1/5milli=200Hz)

Link to comment
Share on other sites

Link to post
Share on other sites

5 hours ago, YiGiT353 said:

1) Yeah try using a capacitor. Seems like the readings suddenly bump

2) The "delay" function delays your whole program so it might interfere with something else. Using PWM for LED brightness is a very overcomplicated solution too. Simply use a higher value resistor for the LEDs. A 220 or a 330 Ohm resistor would be fine.

Unfortunately I don't have the tools to find out what the distortions look like so I have no idea what capacitor I will need...

And I do have some more resistors so I can try some more combinations.

 

Edit: I used a 470 ohm resistor with 3 LEDs and they are a bit dimmer than I wanted, so I made a second parallel row of 3 LEDs and the heat problem seems to be solved now.

Link to comment
Share on other sites

Link to post
Share on other sites

I did some testing with the rpm input, and I found some interesting things:

 

- I  forgot to make the counters in the interrupt functions volatile, and this seemed to fix the issue.

 

- However, this only works for one input. When I attach the second input pin to the Arduino, both rpm signals drop significantly. Even when I put the second pin in pinhole 4/5/6/7 this alters the rpm reading on pin 2. When I put a ~1mA current through pin 7 I get 10k-20k rpm...

 

- Furthermore, the interrupts seem to interfere with the PWM mode on timer1, when I comment out that section the readings are fine, when I put it back I get about 50% more interrupts. 

 

Relevant code for my problem:

Spoiler

//------------------------- Constants -------------------------//

const int pwmAoutput = 9;  //Pin for PWM output A
const int pwmBoutput = 10; //Pin for PWM output B
const int rpmAInput = 2;   //Pin for RPM sensor A input
const int rpmBInput = 3;   //Pin for RPM sensor B input

//------------------------- Variables -------------------------//

word pwmA = 96;  //Set duty cycle (0-320 = 0-100% duty cycle)
word pwmB = 96;  //Set duty cycle (0-320 = 0-100% duty cycle)
word rpmA = 0;   //Fan RPM of output A
word rpmB = 0;   //Fan RPM of output B

volatile word counterA = 0; //Counter rpmA
volatile word counterB = 0; //Counter rpmB

//------------------------- Functions -------------------------//

void RPMcounterA() {          //Counts RPM signal of output A
    counterA++;               //Increase amount of pulses by one
}

void RPMcounterB() {          //Counts RPM signal of output B
    counterB++;               //Increase amount of pulses by one
}

void setup() {
  Serial.begin(9600);  //Serial data rate
  
  pinMode(pwmAoutput, OUTPUT);       //Output A (pwmA)
  pinMode(pwmBoutput, OUTPUT);       //Output B (pwmB)
  pinMode(rpmAInput, INPUT_PULLUP);  //Input rpm sensor (rpmA)
  pinMode(rpmBInput, INPUT_PULLUP);  //Input rpm sensor (rpmB)
  
  attachInterrupt(digitalPinToInterrupt(rpmAInput), RPMcounterA, RISING);  //Generate interrupt to measure rpmA
  attachInterrupt(digitalPinToInterrupt(rpmBInput), RPMcounterB, RISING);  //Generate interrupt to measure rpmB
  
  TCCR1A = 0;            //Clear timer registers
  TCCR1B = 0;
  TCNT1 = 0;
  
  TCCR1B |= _BV(CS10);   //No prescaler
  ICR1 = 320;            //PWM mode counts up 320 then down 320 counts (25kHz)
  
  OCR1A = pwmA;          //0-320 = 0-100% duty cycle
  TCCR1A |= _BV(COM1A1); //Output A clear rising/set falling
  
  OCR1B = pwmB;          //0-320 = 0-100% duty cycle
  TCCR1A |= _BV(COM1B1); //Output B clear rising/set falling
  
  TCCR1B |= _BV(WGM13);  //PWM mode with ICR1 Mode 10
  TCCR1A |= _BV(WGM11);  //WGM13:WGM10 set 1010
  
}

void loop() {
  
  rpmA = counterA*30;  //Calculate rpmA
  counterA = 0;        //Reset counterA
  rpmB = counterB*30;  //Calculate rpmB
  counterB = 0;        //Reset counterB
  
  Serial.print("A: ");      //Display A rpm and duty cycle
  Serial.print(rpmA, DEC);
  Serial.print("RPM, ");
  Serial.print(pwmA*10/32);
  Serial.print("%    ");
  
  Serial.print("B: ");      //Display B rpm and duty cycle
  Serial.print(rpmB, DEC);
  Serial.print("RPM, ");
  Serial.print(pwmB*10/32);
  Serial.println("%");
  
  delay(1000);  //Repeat every second
}

 

 

Link to comment
Share on other sites

Link to post
Share on other sites

19 minutes ago, Olaf6541 said:

<snip>

You should put guards in place such as a mutex or semaphore to guard against interrupts interfering with non-atomic operations on 'counterA' and 'counterB'. Heisenbugs like you're describing are text-book examples of race conditions.

Link to comment
Share on other sites

Link to post
Share on other sites

I tried a different approach by sampling the square wave, here's a ~13Hz (about 400RPM) wave sampled at 100Hz, this should result in alternating four 0's and four 1's on average:

 

ykYzffm.png

 

As you can see the signal is quite noisy and at higher rpm (800 and above) I get more and more 1's.

(I counted the 'rising' edge when the new input is higher than the old one, resulting in too high rpm)

 

At least the PWM signal works quite well, the fans clearly ramp up when the temp sensor is heated.

Link to comment
Share on other sites

Link to post
Share on other sites

22 hours ago, Olaf6541 said:

<snip>

Can you post the code you wrote for this aswell ? So we can check if it does not contain any of the same atomicity errors.

 

This is really the part where you ought to get a 'scope. Even an cheap, fourth hand, ancient analog scope would be better then shooting in the dark. (Don't be tempted to buy one of those toy ebay kits tough).

Link to comment
Share on other sites

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×