//Pin Assignments #define CH1PIN 4 #define CH2PIN 2 #define CH3PIN 6 #define PUMPPIN 8 #define TEMP1PIN A0 #define TEMP2PIN A1 #define TEMP3PIN A2 #define RESOUT 9 //sets the resolution of the analog output #define RESIN 12 //sets the bit resolution of the analog input #define NUMSAMPLES 5 //number of samples to take and average for a single temp output #define PWMFREQ 25000 //PWM frequency as per noctua's spec const bool bleedMode = false; //used to enable updating for each temp probe. When false, readings from that sensor will not be refreshed const bool sensor1 = true; const bool sensor2 = false; const bool sensor3 = false; //Steinhart-Hart Equation Coefficents for Alphacool thermistor //https://www.thinksrs.com/downloads/programs/therm%20calc/ntccalibrator/ntccalculator.html const float A = (8.740776922 * pow(10,-4)); const float B = (2.539474635 * pow(10,-4)); const float C = (1.804597147 * pow(10,-7)); const float BETA = 3301.85; //current temp of each of the three sensors in C, will be updated constantly if sensorX = true float temp1 = 100; float temp2 = 100; float temp3 = 100; //PWM speed maps //NOTE: many fans have a minimum PWM duty cycle. Noctua is 20% //map[row][col] = {{temps in C},{fan percentage}}; float fanmap1[2][11] = {{25,26.75,28.5,30.25,32,33.75,35.5,37.25,39,40.75,42.5},{0,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1,1,1}}; float fanmap2[2][11] = {{25,26.75,28.5,30.25,32,33.75,35.5,37.25,39,40.75,42.5},{0,0,0,0,0,0.3,0.3,0.6,0.6,0.6,1}}; float fanmap3[2][11] = {{25,26.75,28.5,30.25,32,33.75,35.5,37.25,39,40.75,42.5},{0,0,0,0,0,0,0,0,0,0,0}}; float pumpmap[2][11] = {{25,26.75,28.5,30.25,32,33.75,35.5,37.25,39,40.75,42.5},{0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.75,1,1,1}}; //core1 void setup() { analogWriteResolution(RESOUT); analogReadResolution(RESIN); analogWriteFreq(PWMFREQ); pinMode(CH1PIN, OUTPUT); pinMode(CH2PIN, OUTPUT); pinMode(CH3PIN, OUTPUT); pinMode(PUMPPIN, OUTPUT); pinMode(TEMP1PIN, INPUT); pinMode(TEMP2PIN, INPUT); pinMode(TEMP3PIN, INPUT); //Startup all fans and pumps to 100% and then ramp down over a few seconds until starting temp controlled speed pwmOut(0.2, CH1PIN); pwmOut(0.2, CH2PIN); pwmOut(0.2, CH3PIN); pwmOut(0.1, PUMPPIN); Serial.begin(9600); } void loop() { //this core will be used to update PWM state for all 4 channels while(!bleedMode) { mapper(fanmap1,temp1,CH1PIN); mapper(fanmap2,temp1,CH2PIN); mapper(pumpmap,temp1,PUMPPIN); pwmOut(0.5,CH3PIN); delay(1000); } while(bleedMode) { break; } } //core2 void setup1() { delay(5000); //allow fans and pumps to ramp up to full speed and check that they all run } void loop1() { //This core will be used to constantly update the temp readings if(sensor1) { temp1 = temp(TEMP1PIN); //update temp1 Serial.println(temp1); } if(sensor2) { temp2 = temp(TEMP2PIN); //update temp2 } if(sensor3) { temp3 = temp(TEMP3PIN); //update temp3 } delay(1000); } void pwmOut(float dutyCycle, int PIN) { //takes an input of dutycycle (0-1) and the channel to assign it too int tmp = dutyCycle * 511; analogWrite(PIN, tmp); } float temp(int TEMPPIN) { //returns temperature in C with the input of a temperature pin float samples[NUMSAMPLES]; //array of samples for (int i = 0; i < NUMSAMPLES; i++) { //loop to take resistance samples with delay between each samples[i] = analogRead(TEMPPIN); delay(10); } float average = 0; for (int i = 0; i < NUMSAMPLES; i++) { //average up all samples average += samples[i]; } average /= NUMSAMPLES; float resistance = ((10000*average)/(4095-average)); //calc resistance of thermistor using average reading float T = (1/(A + (B*(log(resistance))) + (C*(pow(log(resistance), 3))))); //Steinhart-Hart Equation, uses 3 constants //float T = (1/((1/298.15) + ((1/BETA)*log(resistance/10000)))); //simplified S-H equation, using only one constant T = T - 273.15; //converts the kelvin output of the S-H Equ to Celsius return T; } void mapper(float mp[2][11], float tmp, int PIN) { if(tmp <= mp[0][0]) { pwmOut(mp[1][0], PIN); } else if(tmp <= mp[0][1]) { //pwmOut(mp[1][1], PIN); pwmOut(interpolator(temp1, mp[0][1], mp[0][0], mp[1][1], mp[1][0]), PIN); } else if(tmp <= mp[0][2]) { pwmOut(mp[1][2], PIN); pwmOut(interpolator(temp1, mp[0][2], mp[0][1], mp[1][2], mp[1][1]), PIN); } else if(tmp <= mp[0][3]) { //pwmOut(mp[1][3], PIN); pwmOut(interpolator(temp1, mp[0][3], mp[0][2], mp[1][3], mp[1][2]), PIN); } else if(tmp <= mp[0][4]) { //pwmOut(mp[1][4], PIN); pwmOut(interpolator(temp1, mp[0][4], mp[0][3], mp[1][4], mp[1][3]), PIN); } else if(tmp <= mp[0][5]) { //pwmOut(mp[1][5], PIN); pwmOut(interpolator(temp1, mp[0][5], mp[0][4], mp[1][5], mp[1][4]), PIN); } else if(tmp <= mp[0][6]) { //pwmOut(mp[1][6], PIN); pwmOut(interpolator(temp1, mp[0][6], mp[0][5], mp[1][6], mp[1][5]), PIN); } else if(tmp <= mp[0][7]) { //pwmOut(mp[1][7], PIN); pwmOut(interpolator(temp1, mp[0][7], mp[0][6], mp[1][7], mp[1][6]), PIN); } else if(tmp <= mp[0][8]) { //pwmOut(mp[1][8], PIN); pwmOut(interpolator(temp1, mp[0][8], mp[0][7], mp[1][8], mp[1][7]), PIN); } else if(tmp <= mp[0][9]) { //pwmOut(mp[1][9], PIN); pwmOut(interpolator(temp1, mp[0][9], mp[0][8], mp[1][9], mp[1][8]), PIN); } else if(tmp <= mp[0][10]) { //pwmOut(mp[1][10], PIN); pwmOut(interpolator(temp1, mp[0][10], mp[0][9], mp[1][10], mp[1][9]), PIN); } else if(tmp > mp[0][10]) { pwmOut(mp[1][10], PIN); } else{ pwmOut(1,PIN); } } float interpolator(float tmp, float Th, float Tl, float Dh, float Dl) { float dutycycle = ((Dh - Dl) / (Th - Tl)) * (tmp - Tl) + Dl; return dutycycle; }