Just came to a finish of a code that reads 4 temps, controls 4 fans and reads the 4 fans RPM. Thought I'd put it up before I add other features. It comes in parts cause the code is long.
/*
* This code does 3 basic things.
*
* 1. It reads the temperature from four TMP36 analogue sensors. This reading
* compares to the internal 2,56 volt reference and the sensors are fed by an
* LP2950 3,3 volt regulator connected to the Arduino Mega 2560's internal 5
* volt. If the TMP36 sensors would measure 125 degrees Celsius they would produce
* 1,75 volt on their vout pin but that it theory as I am not planning to
* measure higher temperatures then around 60 C which would translate to 1,1 volt.
* The analogue pins reads this voltage by getting a value between 0 and 1024. The code
* converts this value to degrees Celsius by dividing the reference voltage which I
* measuered to 2577 mV with 1024 and then subtracting 500 mV and then divide the
* lot with 10. The degrees Celsius I will be able to display on an LCD or whatever.
* However I also do a copy of the ADC-pin reading and constrain this value to
* inbetween 300 and 450 which represents about 25 to 63 degrees Celsius. This value
* I put in a map algorithm that do a linear conversion of the temp value to a value
* that I use for setting the fan contol pins duty cycle between 20 and 320.
*
* 2. It produces a 25 kHz 5 volt p-p squarewave signal on four pins that can be
* modulated in duty cycle between 0 and 100%. Those pins controls one 12 volt
* PWM fan each. The duty cycle value is set by the map algorithm described above.
* I use pin 11 and 12 controlled by timer 1 and 5 and 2 controlled by timer 3
* for this.
*
* 2. It reads the length of the DC fans built in hall sensor(s) activity.
* The readings are in microseconds and with a formula this can be converted
* and presented as Revolutions Per Minute (RPM) and/or percentage spinning
* of the fans max revolutions per time unit. To avoid to much flickering when
* displaying this value it runs to a smoothing algorithm as well that adds the
* last four measurements and displays that total value divided by 4.
* I tested to use the internal built in 20k pullup resistors but the microamp
* current is not enough for stable readings so instead I use external 2,4 k
* resistors that gives around 2 mA of current per pin. This current gets shorted
* to ground by the fans internal mosfets that takes the reading from high to low
* two times per revolution. Noctua recommends up to 5 mA in their specs.
*
* PS. In my first versions of the code I tried working with arrays as long as
* possible but I ran in to problem when trying to attatch the OCR duty cycle
* values to the PWM values in an array so I rewrote it all to straight code,
* hence the length of it all since I do everything four times in the code.
*/
const int tmpPin0 = A12; // Temp pin assignments
const int tmpPin1 = A13;
const int tmpPin2 = A14;
const int tmpPin3 = A15;
const int pwmPin0 = 11; // PWM pin assignments
const int pwmPin1 = 12;
const int pwmPin2 = 5;
const int pwmPin3 = 2;
const int hallSensorPin0 = 13; // Hall sensor pin assignments
const int hallSensorPin1 = 9;
const int hallSensorPin2 = 22;
const int hallSensorPin3 = 23;
int tmpReading0; // Variables for the temp
int tmpReading1; // sensor Readings
int tmpReading2;
int tmpReading3;
int tmpConstr0; // Variables for the temp
int tmpConstr1; // sensor Voltages
int tmpConstr2;
int tmpConstr3;
int tmpDegree0; // Variables for temp
int tmpDegree1; // sensor Degrees Celsius
int tmpDegree2;
int tmpDegree3;
int pwm1A = 120; // Variables for the duty
int pwm1B = 120; // cycles (0-320 = 0-100%)
int pwm3A = 120; // Boot up values 120
int pwm3B = 120;
unsigned long highPulseTime0; // Variables for the durations
unsigned long highPulseTime1; // of the high pulses
unsigned long highPulseTime2;
unsigned long highPulseTime3;
unsigned long lowPulseTime0; // Variables for the durations
unsigned long lowPulseTime1; // of the low pulses
unsigned long lowPulseTime2;
unsigned long lowPulseTime3;
unsigned long newPulseTime0; // Variables for the durations
unsigned long newPulseTime1; // of the new pulses, ie high
unsigned long newPulseTime2; // plus low pulse
unsigned long newPulseTime3;
int revsPerMinute0; // Variables for RPM values
int revsPerMinute1; // calculated from the pulse times
int revsPerMinute2;
int revsPerMinute3;
int smoothedRevsPerMinute0; // Variables for the
int smoothedRevsPerMinute1; // smoothed RPM values
int smoothedRevsPerMinute2;
int smoothedRevsPerMinute3;
int percentage0; // Variables for percentage value
int percentage1; // calculated from their RPM values
int percentage2; // and their max RPM values
int percentage3;
const int samples = 4; // No of samples used for smoothing
const int maxRevFan0 = 1140; // Constants for each fans maximum
const int maxRevFan1 = 1570; // revs per minute
const int maxRevFan2 = 2180;
const int maxRevFan3 = 1550;