I spent some time taking a look at the code and values I'm going to use for my code to modulate the fan speed for coolant temperature. As I'd posted previously, I'm starting with the example that someone posted in this thread:
https://ls1tech.com/forums/forced-i...-speed-pwm-fan-control-under-25-less-diy.html
I'm going to need to look through to make sure that the pin format works the same for the Arduino Uno vs. the Nano that the person used in this example. But that one is pretty minor. I've gone through and made a few edits to his code:
1) I changed the R0 (which I understand to be resistance at 25C) and Beta (a value for the logarithmic curve that a thermistor sensor uses) for the Ford sensor. I based this on this chart I found for the Ford coolant temp sensor, although I will want to do some extra checks on the sensor I'm using:
2) The Arduino Uno has an LED built-in that you can command to turn on and off. So I edited the code to have the light on if the PWM output has the fans at max, off if they're off, and then flashing if the computer is modulating. I put this on 250 ms on, 250 ms off, but could extend it if I wanted. Ultimately once I have the system working and calibrated, this isn't likely to get touched or needed much, but I figure it's good to have anyway. The board won't be mounted in a super accessible location but it will be inside the RV where it's weather and environmentally protected (at least so goes the theory).
The one thing I don't like about the code is that it is a fairly dumb temperature-based ramp-up. This will probably work well enough, but the reality is I'd like to aim to keep the temperature of the engine around 200F. As this is written, the only way I can vary the fan speed for 200F is to vary the two temperature values. And in the winter the fan speed required for 200F would be different than it would be in the summer under the same conditions. It would be preferable to put a PID loop in place that could modulate the fans more appropriately. I've found a couple of examples of PID loops for Arduino code, but I'm not sure I understand the code well enough at this point to want to throw them in. I may try making an alternate program and I could try loading them both to see what works if I can find some PID code that I understand well enough to attempt to implement.
For those interested, here's my code, first the screen shots that are easier to read through and then the text below them:
// PWM Fan Controller for Ted doing Ted things
// Version 1, in progress
// R0 and Beta for Ford coolant temp sensor. R0 = resistance @ 25C
/*----------------------- User adjustable variables and preferences section ---------------------------------*/
float tempForFanStartup = 195.0; // target low temp. below this temperature, the fan will be off
float tempForFanOnFull = 210.0; // target High temp. above this temperature, the fan will be on at full power
// adjust these two to get the desired range. for example for a transmission, maybe 140 to 160
float R0 = 30000; // The base resistance of the coolant temp sensor used
float Beta = 4069; // The Beta of the sensor used
float voltsForFanStartup = 1.2; // Roughly the signal voltage that triggers the mazda module's slowest speed.
// A higher voltage here will effectively increase the fans lowest speed target.
/*----------------------- end of User adjustable variables and preferences -----------------------------------*/
const int fanPwmOutPin = 6; // Arduino forces this pin to 0 or 5 volts.
const int tempSensorPin = A0; // Pin to read analog voltage from the temp sensor.
int pwmDuty; // The calculated PWM duty is stored here
float pwmMinStartupDuty; // the starting duty is stored here (mazda module starts fans at about 24 % duty)
float currTemperature; // the temperature in F is stored here
void setup() { /* ++++++++++++++++++ Setup is run once when the arduino boots ++++++++++++++++++++++++++*/
Serial.begin(115200); // set up serial port for 115200 baud (optional)
analogReference (EXTERNAL) ; // note, this is using the 3.3 volt supply as the analog reference.
analogRead (tempSensorPin) ; // a couple of reads to give the A/D time to adjust
analogRead (tempSensorPin) ; // a couple of reads to give the A/D time to adjust
analogWrite(fanPwmOutPin, 0); // turn the fan off at start
pinMode(LED_BUILTIN, OUTPUT); // Going to use the built-in LED for status
digitalWrite(LED_BUILTIN, HIGH); // Makes the LED flash for half a second to show this function works
delay(500); // Will likely comment out LED code after initial diagnostic tests
digitalWrite(LED_BUILTIN,LOW);
pwmMinStartupDuty = (voltsForFanStartup / 5.0) * 255.0; // convert the Mazda starting voltage to a PWM duty
} // end setup
void loop() { /* ++++++++++++++++++ Main Loop, continuously loops forever ++++++++++++++++++++++++++++*/
readAndTranslateTempSensor();
calculate_and_send_PWM();
//print_to_serial_port(); // un-comment this line for testing and calibration to the laptop.
} // end main loop
void calculate_and_send_PWM() { /* ++++++++ subroutine to calculate and set PWM duty cycle ++++++++++++++*/
if (currTemperature < tempForFanStartup) { // If the temperature is below the lowest setpoint, turn fan off
analogWrite(fanPwmOutPin, 0); // PWM duty = 0 percent
pwmDuty = 0;
digitalWrite(LED_BUILTIN,LOW); // If fans are off, LED is off
return;
}
if (currTemperature > tempForFanOnFull) { // If the temperature is above the highest setpoint, turn fan on full
analogWrite(fanPwmOutPin, 255); // PWM duty = 100 percent
pwmDuty = 255;
digitalWrite(LED_BUILTIN,HIGH); // If fans are on full, LED is on
return;
}
float tempRange = tempForFanOnFull - tempForFanStartup ; // start calculating duty cycle
float pwmRange = 255.0 - pwmMinStartupDuty ;
float pwmDutyPct = (currTemperature - tempForFanStartup) / tempRange ;
pwmDuty = (int) (pwmMinStartupDuty + (pwmDutyPct * pwmRange) + .5); // actual PWM duty is calculated here
if (pwmDuty > 255) { // make sure duty ended up between 255 and 0
pwmDuty = 255;
}
if (pwmDuty < 0) {
pwmDuty = 0;
}
analogWrite(fanPwmOutPin, pwmDuty); // write PWM duty to PWM output pin
digitalWrite(LED_BUILTIN, HIGH); // If the fan speed is being modulated by PWM, the LED will flash
delay(250);
digitalWrite(LED_BUILTIN, LOW);
delay(250);
} // end calculate_and_send_PWM
void readAndTranslateTempSensor() { /* ++++++ subroutine to read and translate temp sensor to temp F +++++++++++++*/
int tmp = analogRead(tempSensorPin);
float r = ((1023.0 * R0) / (float)tmp) - R0;
currTemperature = Beta / log(r / 0.09919) - 273.15; // for a 10K thermister with a beta of 3435
currTemperature = (9.0 / 5.0) * currTemperature + 32; // convert to Fahrenheit
} // end readAndTranslateTempSensor
void print_to_serial_port() { /* ++++++++++ optional prints values to laptop usb port for debugging and calibration ++*/
Serial.print(F("currTemperature F: ")); Serial.print(currTemperature);
Serial.print(F(" pwmDuty: ")); Serial.println(pwmDuty);
}