Thanks !
I was on vacations until a few days (diving resort
). As soon as I was at home, I worked again on the fan controller, and got interesting results. I post some pics I will comment in a few hours. At the moment, I have a manual fan controller (through tactile screen). The most important part of the software is completed. It will be time to work on hardware (5.25" unit).
Comments will come in a few hours (time for diner)...
For those who are interrested in this fan controller : it will be open hardware and open software on my website (because it is far easier to do : editing, and source downloading).
This fan controller will be easy to build, even for a beginner, or for someone who does't know anything in programming and/or electronics.
Want to see my cable management ? Here you are !
(and examining the PC, you will see how many disks I use ! 1x internal SSD, 7x internal HDD (rackable), and on the top of the case, an Icy Dock RAID with 2x HDD inside : 10 disks !). The reason why I had difficulties to find a compact case, and why I got this Lian Li...
Probes :
3 types of "probes".
- 1 - NCT (thermistors) for ambient temp, pump input (rads output), and waterblocks output (rads input).
- 2 - PWM signal decoding from CPU fan ; the measure is not relevant at lower temps, as it can be ssen on pictures : gives the same value than amb temp ! This has always been a problem with my 2 x P9X79. Asus or other monitoring softwares : same problem. Couldn't use OCCT : it reads 127°C, and considers the CPU is overheating !!! Seems to be a common issue with these mobos/CPUs.
- 3 - getting temps from GPUs is another big problem I will discuss further
- 4 - amps entering the PSU : to be done (current transformer). Will display the apparent drawn power. It could even be software compensated after measurement and comparison whith a wattmeter, or using the oscope to determine cos(phi) at diffrent loads.
I think the better solution for cooling regulation is reading the power consumption, the ambient temperature, and adjusting fans and pump according to real life tests, with alarms based on temperature (such as auto shut down).
Now, the touch screen
The fonts provided with the 320x240 display are uggly. But it is possible to use nicer public domain bitmap fonts, or to convert vector fonts. Those that can be seen here are scaled 2x : huge pixellization...
I am somewhat disapointed with the µC and the display. First, display is really slow. I what thinking of using stored bitmaps (µSD) as skins, but it takes 3-4 seconds to display one 320x240 (12bit only, 4 or 8bit not supported). The communication interface is also very slow : SPI interface. Drawing a screen or a dialog takes 0.5-1 second.
In order to get a "hardware" CPU temp, I modified the fan curve in FAN Xpert+, and did some math to calculate back temp from PWM. The accuracy is rather good, but the display fluctuates (+-1or2°C). I plan to implement some sort of buffer (FIFO or circular), and calculate a mean value over time. For PWM measuring, the program determines the duty cycle (polling 10 to 20 cycles) for a 5 milliseconds, but still fluctuates ; I think the reason is the µC having a lot of things to do (it generates PWM, measures temps, etc.), and it is not real time multithreaded.
The function : the two pulseIn do *NOT* measure one cycle, but parts of two successive ones ; but it works fine ; LO and HI durations are accumulated for 5ms, then the duty cycle is calculated, a 0 to 99.9 or so value is returned. 0 means "timeout", and 100.
!!! NOTE THAT THIS FUNCTION IS A QUICK AND DIRTY FUNCTION : RISK OF DIVIDE BY ZERO ! SOME IMPROVMENTS ARE TO BE DONE (VERY EASY) !!!
(but I tested extensively, and never crashed the µC when disconnecting the input, giving a 0/0*100 to eat to this animal; the function simply seems to return... nothing !)
#define SAMPLING_TIME 5000
#define SAMPLE_TIMEOUT 200
uint8_t ReadDutyCycle_v2(uint8_t iPin)
{
unsigned long pulseHi=0;
unsigned long pulseLo=0;
unsigned long totalHi=0;
unsigned long totalLo=0;
unsigned long timeStart=micros();
unsigned long timeElapsed=0;
while(timeElapsed<SAMPLING_TIME)
{
pulseHi=pulseIn(iPin, HIGH, SAMPLE_TIMEOUT);
pulseLo=pulseIn(iPin, LOW, SAMPLE_TIMEOUT);
if(pulseHi!=0&&pulseLo!=0) // timeout -> 0
{
totalHi+=pulseHi;
totalLo+=pulseLo;
}
timeElapsed=micros()-timeStart;
}
return (double)pulseHi/(double)(pulseLo+pulseHi)*100;
}
There are also fluctuations at analog inputs : on the above pic, the water entering the rads is 0.1°C cooler than the water entering the pump. This pic is caricatural : most of the time, rads input is 1°C hotter than output ! (at idle, of course). A buffer and a mean value would also be the solution (in the todo list).
On the FAN Xpert+ screen capture one can see the same irrelevant processor temp...
Problem : this curve is defined using the OS and the Asus utility. I will have to test the default BIOS curve after uninstalling Asus tools, but chances are it will not work (too high duty cycle / CPU fan speed and flat curve at low temps).
I am pretty sure FAN XPert+ parameters are stored somewhere in the NVRAM : I run 4 systems on my rig. If I change fan profile on one system, the profile is automatically selected when starting FAN XPert+ on the others. But these profiles seem not to be active at POST and boot time. How does it work ??? I found no information, as for NVidia hardware fan control.
Another problem with duty cycle measurement is resolution : displaying 0.1°C from the 7bit or 8bit PWM signal is absolutely stupid ! I must reduce to 1°C resolution. I will do the same for water and amb temps (10bit ADC + little resistance variations for the NTCs = low resolution)
More tricky is the PWM generator for the fan speeds control. The Arduino Mega 2560 has PWM outputs. But at 500 Hz, essentially for outputting analog voltage after integration (filtering). It is far too low for fan / pump control. It works, but it is very noisy. I tried some libraries, but none was able to generate 8 simultaneous 25 KHz PWM signals. I had to play with prescalers, and the lowest frequency with this µC is 31372.55 Hz. Typically, a PWM signal for fan control should be 21-28 KHz (Intel specs). But it seems to work fine at 31KHz. The (minor) risk is overheating of the internal motor controller - overclocking !). I think the only way to slow down the PWM outputs is to replace the 16MHz quartz for a 12MHz one (underclocking !). To be tested... or not !
Another solution is to use a specialized PWM generator, and drive it with the µC. I'd preferably test this solution if I ran into problems with 31KHz (low probability, I think !)
How to get 31KHz PWM outputs : this solution can be found everywhere on the web ! I do not touch timer 0 as it is related to time functions, and I need them for measurements.
// timer 1 (controls pin 12, 11)
TCCR1B &= 0b11111000 | 0b00000001; // set timer 1 divisor to 1 for PWM frequency of 31372.55 Hz
// timer 3 (controls pin 5, 3, 2)
TCCR3B &= 0b11111000 | 0b00000001; // set timer 3 divisor to 1 for PWM frequency of 31372.55 Hz
// timer 4 (controls pin 8, 7, 6)
//TCCR4B &= 0b11111000 | 0b00000001; // set timer 4 divisor to 1 for PWM frequency of 31372.55 Hz
// timer 5 (controls pin 44, 45, 46)
TCCR5B &= 0b11111000 | 0b00000001; // set timer 5 divisor to 1 for PWM frequency of 31372.55 Hz
Here, this gives the 8 x 31KHz PWM channels with a 8bit resolution : pins 2, 3, 5, 11, 12, 44, 45, 46
RPM measuring is another problem. I tried different libraries, polled and interrupt based, and finaly made my own. I did it by simply polling and measuring the duration of one pulse every 3 seconds or so, spreading them to avoid lags. Unfortunately, the values I get are slighly incorrect, but proportionnal : I had to multiply the result by a magic number in order to get correct RPMs : the time functions return 15% too short values ! It could be caused by the CPU cycles needed by the function itself. I found some discussion about this, with MEGA assembly langage and exact error calculation, but I am absolutely not interested in µC internals. If a magic number does the trick, it is sufficient.
uint16_t ReadRPM_v7(uint8_t nPin)
{
// 100RPM -> 1.67 Hz -> 0.6 s soit 0.15s / impulsion
// -> timeout 150000
unsigned long period=pulseIn(nPin, LOW, 200000);
if(period==0)
return 0; // timeout
uint16_t RPM=0.864 * 15000000 / period; // 0.864 = magic number
if(RPM>9999)
return 9999;
else
return RPM;
}
Measurement spreading : 3 measurements per second, this gives a complete display refresh (8 "probes") every 3 second (could be adjusted in future Options dialog)
volatile unsigned long nTimeOld_Fan=0;
volatile uint8_t bFan=0;
void UpdateRPMs()
{
unsigned long nTime=millis();
unsigned nElapsed=nTime-nTimeOld_Fan;
if(nElapsed>300) // mesurer un ventilo
{
Fans[bFan].MeasureRPM();
nTimeOld_Fan=nTime;
bFan++;
if(bFan==FAN_COUNT)
bFan=0;
}
}
Surprisingly, pulseIn(nPin, HIGH, timeout) gave more unstable results ! But HIGH or LOW, the mean values are the same. Nearly the same magic number was needed : 0.884(and this proved the TACH signal is nearly perfectly square).
Polling is a problem because when the program polls an input, it cannot do anything else ! Unfortunately, it is not possible to use lots of interruptions with the Arduino Mega ; the Arduino Due could be an interesting alternative : 32bit (Mega=8bit), 84MHz (at least 5 time faster), all 54 digital inputs "interruptable", more memory (Mega=8K). But the Due is 3.3V : need to adapt voltages at inputs and outputs. An interrupt for signal changing -> period, and the µC will not have to wait.
Polling when changing the PWM duty cycle makes the sliders less responsive if the fan runs at low RPM or is not connected : the worst case with 200 ms timeouts always reached every 300ms, so the µC is unresponsive 40% of the time. At low RPMs, the µC has to wait a whole pulse before it can move the cursor on the touch screen...
(images below : RPM are for pump channel ! The D5 turns far higher at 50% duty cycle ! For testing purpose, a group of 3x BeQuiet! Shadow Wings PWM 140mm 1000RPM is connected to this channel)
(and I discover editing this post that I wrote "HDD fan" insteed of "HDDs Fans" : 8x HDDs and 2x Fans...)
The fan speed controls : every rounded rectangle is a button, and tapping the screen displays a dialog :
The GPU hardware temps problem...
It seems there is absolutely no information on how to hack the BIOS.
I had a look to NVAPI, and "discovered" that fan controller could be on chip, unlike older (hackable) graphics card.
The old Quadro FX3700 fan parameters and curve *CAN* be hacked with the help of NiBiTor. It uses a well known fan controller.
But for more recent cards, after maybe 20 hours of search on the web, I think there is absolutely no information about fan parameters. The only known leaks are about how to make Quadro drivers recognize for example a 780ti as Quadro K6000 (BIOS mod + SMC resistors to change on the board). (that does not transform a GTX to Quadro - AFAIK, no double precision, and it does not give 12GB GDDR !!!)
The desperating information : "Yes, the "nVidia On-Die" sensor return values directly from the GPU registers.
Unfortunately the details how to access this is considered confidential and protected by NDA, so I cannot publish it."
By the author of HWINFO, on this thread :
http://www.hwinfo.com/forum/Thread-On-Die-GPU-fan-speed-on-GTX-580 Nonetheless, I will have a try with PWM, as for CPU temp. It will need a "fake fan" circuit, in order not to get a 100% duty cycle signal, due to the closed loop fan regulation. Arduino, MEGA or Due, will not have enough PWM outputs : will do that with independant PICAXE µC (they are better at PWM, AFAIR)
But I do not expect good results : fan curve is rather flat, and the temps interval very narrow with watercooling : this should give very bad resolutions. Precision X could help, after OS is loaded, the way I used Fan XPert+ by modifying the curve.
At this time I just got a Asus alarm : CPU 118°C !!! But Probe II (and my fan controller)
display a stupid 25°C (water is at 30°C with ambient at 24°C!!!) Asus software, or... Nuvoton NCT6776F ? This 25°C is reported by this fan controller on the mobo. Is the probe on i7 die, or somewhere on the mobo ???????? Speedfan says CPU=128°C, and cores = from 21 to 27°C... What's the problem with this i7 CPU / X79 mobo ???
I am wondering if this thread is in the right place... I avoided case mods : only 4 holes, and I only build a 5.25" fan controller !
post edited by schmorblatz - 2014/08/25 18:04:08