What's new

Open Source PWM Fan Controller

Joined
Nov 28, 2020
Member Number
3093
Messages
1,102
Loc
Sacramento, CA
So thanks to the Cooling Fan Tech thread I ended up with a sweet 850w brushless fan from a JL that I'm retrofitting onto my WJ. These fans have constant hot power from the battery, then use a small PWM trigger wire so the control circuit doesn't require any actual power handling. There are plenty of sweet solutions, (Like the SPAL PWM temp sensor from that thread), so I obviously need to go and overcomplicate it :flipoff2:. I'm still an electronics newb and have no interest in doing anything production related with it, so lets open source this thing. I'll be sharing my models for the housing, any useful links and all code stuff here. I'm sure you guys will have some input to make things better and better.

I'm making a unit based on the Arduino Nano, it has 12v input, and a temperature sensor input, then has a PWM output to the fan. Has a knob for varying the temp range, and a display screen to show important data. I think cost will be around $20-25 ish

Now the funny thing (and the curse), I don't really know how to write code so we're going to figure out how terrible ChatGPT is at writing code :laughing:, and then figuring out what's broken and how to improve it as we go.

It's approximately 1.3" x 3.4" long. I don't like that the barrel plug is non locking so that may change.


PWM Fan Controller - 3.JPG


PWM Fan Controller - 4.JPG
 
So to start things off on the coding side of things, I had to come up with a decent prompt for ChatGPT, that articulated everything I was trying to achieve. I actually did another full round of asking it to write this for me, but I asked for so many corrections and adjustments along the way the got really...messy looking. So this is a fresh prompt.


Arduino PWM Fan Controller

Initial logic prompt


Output 1: Pin #6

Output – PWM Signal
PWM Frequency – 40,000 hz
PWM Duty Cycle Range – 15%-95%
Intervals – 5% increments

Output 2:

Output – I2C OLED Screen 128 pixels wide, 32 pixels tall
Displays one screen at a time, cycle through screens via momentary switch

Screen 1: “T.Range” Current temperature range, after calculating potentiometer input
Screen 2: “C.Duty” Current Duty Cycle
Screen 3: “C.Temp” Current Temperature from the temperature sensor

Input 1:

Temperature Sensor – Resistance range 400 ohms to 10 ohms.
Based on the following values, extrapolate approximate current temperature in Farenheit based on temperature sensor resistance:

366 ohms at 71 degrees
240 ohms at 95 degrees
70 ohms at 170 degrees
32 ohms at 220 degrees

Minimum PWM Duty Cycle: Begins at 160 degrees
Maximum PWM Duty Cycle: Achieved at 210 degrees
Duty cycle is zero for all temperature values below the minimum, duty cycle stays at 95% for all temperature values above the maximum.

Input 2:

10,000 ohm Potentiometer
The full range of the resistor will vary the effective temperature range of min/max PWM outputs by plus or minus 30 degrees, with the initial commanded temperature ranges landing directly in the middle at 5,000 ohms resistance.

Input 3:

Momentary Switch
Cycle through display options on OLED screen​
 
First, let's note for the future THIS IS FIRST REVISION, MOST LIKELY BROKEN CODE
It returned with:
// Include required libraries
#include <Wire.h>
#include <Adafruit_SSD1306.h>

// Initialize OLED display object
Adafruit_SSD1306 display(128, 32, &Wire, -1);

// Define constants for pins and values
const int FAN_PIN = 6;
const int TEMP_SENSOR_PIN = A0;
const int POT_PIN = A1;
const int SWITCH_PIN = 2;
const int MIN_TEMP = 160;
const int MAX_TEMP = 210;
const int MIN_DUTY = 15;
const int MAX_DUTY = 95;
const int DUTY_INCREMENT = 5;
const int POT_RANGE = 10000;
const int DEFAULT_POT_VALUE = 5000;

// Define variables for current values
float current_temp = 0;
float current_duty = 0;
int current_screen = 1;
int current_pot_value = DEFAULT_POT_VALUE;

// Define function for calculating temperature from resistance
float calc_temp(float resistance) {
if (resistance > 366) {
return 71;
} else if (resistance > 240) {
return (95 - 71) * (366 - resistance) / (366 - 240) + 71;
} else if (resistance > 70) {
return (170 - 95) * (240 - resistance) / (240 - 70) + 95;
} else if (resistance > 32) {
return (220 - 170) * (70 - resistance) / (70 - 32) + 170;
} else {
return 220;
}
}

// Define function for updating the duty cycle based on temperature and potentiometer
void update_duty() {
if (current_temp < MIN_TEMP) {
current_duty = 0;
} else if (current_temp > MAX_TEMP) {
current_duty = MAX_DUTY;
} else {
int pot_adjust = (current_pot_value - DEFAULT_POT_VALUE) / (POT_RANGE / 60);
current_duty = MIN_DUTY + (MAX_DUTY - MIN_DUTY) * (current_temp - MIN_TEMP + pot_adjust) / (MAX_TEMP - MIN_TEMP);
current_duty = round(current_duty / DUTY_INCREMENT) * DUTY_INCREMENT;
}
analogWrite(FAN_PIN, round(current_duty * 255.0 / 100.0));
}

void setup() {
// Initialize serial communication
Serial.begin(9600);

// Initialize OLED display
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.clearDisplay();

// Set up momentary switch as input
pinMode(SWITCH_PIN, INPUT_PULLUP);

// Set up fan output pin and set initial duty cycle
pinMode(FAN_PIN, OUTPUT);
analogWriteFrequency(FAN_PIN, 40000);
update_duty();
}

void loop() {
// Read current temperature sensor resistance and calculate temperature
float sensor_voltage = analogRead(TEMP_SENSOR_PIN) * 5.0 / 1023.0;
float sensor_resistance = (5.0 - sensor_voltage) / sensor_voltage * 1000.0;
current_temp = calc_temp(sensor_resistance);

// Read current potentiometer value
current_pot_value = analogRead(POT_PIN);

// Check if switch is pressed and update current screen
if (digitalRead(SWITCH_PIN) == LOW) {
current_screen++;
 
But the way it extrapolated the current temperature off the (sloppily) measured values I gave it looked pretty sloppy, so I asked

Excellent! In an effort to simplify the function for calculating temperature, can you come up with a simple graphing function such that if all given values were plotted on a chart, the outputs of the new function plot a line that is within 5% of given values?

To which it kicked back a pretty clean looking:

import numpy as np

# create the lists of resistance and temperature values
resistance = [10, 32, 70, 240, 366]
temperature = [220, 170, 160, 95, 71]

# fit a straight line to the data using polyfit
slope, intercept = np.polyfit(resistance, temperature, 1)

# define the get_temperature function
def get_temperature(resistance_value):
return slope * resistance_value + intercept

So that's where I am as of this morning. I currently have the first version of the case 3d printing, might put the hardware together this evening or tomorrow. The question is though, how far off base is the ChatGPT code? Can it be turned into something functional, or is it useless?
 
Might want to create a couple of standoffs so you can screw the two parts together. That is unless you're just going to glue or RTV the two halves together.

The plan was to glue the first one together in a couple spots once it's verified functional, but standoffs and screws would probably be worth adding for that "just in case" serviceability
 
Interesting. Picked up the same fan for a project and am curious to see how this turns out.
Sweet. Once I get it all figured out here, the itemized list of components and code will be here!

This is just mockup text, but it's a miracle that things are actually half-assed working. I will say the initial code way waaay broken, so it'll be a bit before I have an actual working version with my lack of knowledge, but getting there.

This screen will show the current temp being read by the temperature sensor, I'll have another screen showing the current PWM duty cycle being commanded, and a third screen that shows the temp operating range for the controller, tuned by the potentiometer


PWM Fan Controller - 5.jpg
 
Very cool, any chance you're able to make couple more. I'd buy some for my trucks with these efans

The idea of making more is fun, but I'm not nearly proficient enough to make it worthwhile without making it cost more than other solutions out there. If you or someone you know is decent at soldering though, the file for the housing and all the code you need will be here along with the parts lists, hopefully making DIY as easy as possible!
 
The idea of making more is fun, but I'm not nearly proficient enough to make it worthwhile without making it cost more than other solutions out there. If you or someone you know is decent at soldering though, the file for the housing and all the code you need will be here along with the parts lists, hopefully making DIY as easy as possible!
You could also post the code and files for this on something like github. The benefit would be the possibility of more outsiders helping to refine your project.
 
You could also post the code and files for this on something like github. The benefit would be the possibility of more outsiders helping to refine your project.
Once I have something functional I may do that. I've never really used github so that will be its own learning experience, but I have a vague grasp on its intended purpose

What microcontroller for PWM?
It's running on an Arduino Nano clone
 
First, let's note for the future THIS IS FIRST REVISION, MOST LIKELY BROKEN CODE
It returned with:

// Define function for calculating temperature from resistance
float calc_temp(float resistance) {
if (resistance > 366) {
return 71;
} else if (resistance > 240) {
return (95 - 71) * (366 - resistance) / (366 - 240) + 71;
} else if (resistance > 70) {
return (170 - 95) * (240 - resistance) / (240 - 70) + 95;
} else if (resistance > 32) {
return (220 - 170) * (70 - resistance) / (70 - 32) + 170;
} else {
return 220;
}
}


quote didn't pull in your resistance code, but that code hurts my feelings. Life is easier with a linear interpolation lookup function. Most anything can be fixed in embedded controls with a lookup function and a filter. And with that comment, I'd recommend apply a filter to your inputs. Some FETs and other drivers don't like rapid swings, so if the temp input has a filter on it, you can effectively slow down your output.


 
oh, another thought.. do you have to turn on the driver 100% at startup during in-rush current?

in a previous project we had to turn on the driver for a few hundred milliseconds, and then could start PWM controls. Also had to be considerate of what driver frequency we chose, as well as limiting the minimum PWM signal, as it would heat up the driver.
 
// Define function for calculating temperature from resistance
float calc_temp(float resistance) {
if (resistance > 366) {
return 71;
} else if (resistance > 240) {
return (95 - 71) * (366 - resistance) / (366 - 240) + 71;
} else if (resistance > 70) {
return (170 - 95) * (240 - resistance) / (240 - 70) + 95;
} else if (resistance > 32) {
return (220 - 170) * (70 - resistance) / (70 - 32) + 170;
} else {
return 220;
}
}


quote didn't pull in your resistance code, but that code hurts my feelings. Life is easier with a linear interpolation lookup function. Most anything can be fixed in embedded controls with a lookup function and a filter. And with that comment, I'd recommend apply a filter to your inputs. Some FETs and other drivers don't like rapid swings, so if the temp input has a filter on it, you can effectively slow down your output.



Yeahhh so I've definitely discovered that most of what ChatGPT returned is junk, but it gave me enough to ask the right questions, and start whittling it down. I was really hoping it was going to return some basic linear function, but it spit out that mess haha. I don't have a functional version written yet, but I believe I have a path that's going to be as simple as it should be, fingers crossed.

Thanks for the links too, all of this is pretty new to me so I'm learning everything as I go!


this hurts my head to try and under stand. but i want to understand.....

The code is still 100% voodoo to me, but only in the last year or two have I finally come to grasp how awesome Arduinos are in general. Essentially they take inputs (button presses, varying resistances, etc) and deliver outputs. Outputs can be displaying data on a screen, outputting a signal of any type you might want, control DC motors, stepper motors, servos, whatever you want. Some people make them RC car controllers, even RC car transmitters, home automation stuff, industrial automation as these guys have noted, just about anything.

In this case I'm just having it watch the feedback from a temperature sensor, and output a signal to control a fan. I'm just adding a knob to modify it along the way, and also making it display some of what it's doing

oh, another thought.. do you have to turn on the driver 100% at startup during in-rush current?

in a previous project we had to turn on the driver for a few hundred milliseconds, and then could start PWM controls. Also had to be considerate of what driver frequency we chose, as well as limiting the minimum PWM signal, as it would heat up the driver.
So start conditions are something I'm aware I might have to set, but I don't actually know what this fan needs yet. I also have a generic standalone PWM signal generator that I'll be using to test the fan on, both the startup conditions and PWM frequency. From what i've heard there should be some flexibility on the PWM frequency it can run on but I need to verify that. I have the output on one of the pins with the highest frequency the Arduino can output, and then can vary it from there as needed
 
Assuming is has an ADC, use it to measure voltage across sensor with fixed current source and update duty cycle as needed. Find coef.'s of sensor curve, easy math, no table. What is commutation scheme for 3-ph BL motor?
 
But the way it extrapolated the current temperature off the (sloppily) measured values I gave it looked pretty sloppy, so I asked



To which it kicked back a pretty clean looking:



So that's where I am as of this morning. I currently have the first version of the case 3d printing, might put the hardware together this evening or tomorrow. The question is though, how far off base is the ChatGPT code? Can it be turned into something functional, or is it useless?

In addition to the other comments:

Well, the bottom half of your loop function is missing from the first code snippet pasted. The quote cut it off. I would use an attachment or just create a github account and load it up there and link to it so we can submit ideas/changes and patches to help. The quote also mangles the formatting. I can help you with github and will help you with the code if you want.

Note the last code snippet ChatGPT returned was Python and the first program was in C/Sketch, so those two won't work together. You either have all MicroPython code on the board, or C/sketch code compiled to the board (unless some other alternative exists that I don't know about). I would stick with the C, the suggestions above are enough to make clean C code.

The C sketch first generated includes a reference to analogWriteFrequency. This isn't part of Arduino standard library (so the code doesn't compile). I believe that ChatGPT is thinking about something like the MegaCoreX library or some other PWM library that adds this feature, but it is impossible for me to know exactly what it is thinking. Note that the MegaCoreX library doesn't work with all Nano's, it works with the Nano Every and the Nano 4808.

A list of required hardware that this thing needs is in order, so we can better help (debug/development goes faster if we lay our hands on the exact same hardware and prototype it together and all report bugs):
  1. One 12v hardened Arduino Nano (Every?). If you can link to the specific one, that is helpful. Yes, they should all be compatible-- but I have seen many "compatible" boards are not totally 100% compatible with the reference board and if we make code for one 12V hardened Arduino Nano Every, there is no telling if another one will live as long or work as well since hardened means different things to different people, so best to list exact hardware.
  2. One Adafruit SSD1306 OLED display. At least that is the display ChatGPT generated code for.
  3. A pot control knob. Linking to the specific one you are using is also good.
  4. One temp sensor/input. Again, specify specific hardware. I have seen lots of Arduino thermometers, but few are any where near durable in extreme temps and conditions out of the box. Are you putting it into cooling/radiator fins, putting it in coolant, etc?
  5. A momentary switch to control modes/features. Specify specific momentary switch you are using.
And this hardware is to support sending a PWM signal that controls one fan, a 850w brushless fan from JL (specifiy model number) and hopefully other JL fans in the same series are also compatible (should be).

Also see here for other ideas:

 
Awesome input, thank you for that. So the more I understand, the more I grasp how completely hack/incomplete/useless the ChatGPT code is. But it at least gave me enough direction to start figuring things out. I was kinda churning my wheels trying to figure out where to start with a blank slate, but at least this way I can pick it apart, research and learn the various concepts, and then create something functional from there.

So thankfully before I started this I did enough research to know that supplying 12v is pretty risky (let alone 13-14v from the alternator), so the second board in the enclosure is a voltage regulator. I currently have it turned down to about 7v for the Arduino

This is the exact model: https://www.amazon.com/dp/B076H3XHXP

As far as the nano clone itself, this is the one I got: https://www.amazon.com/dp/B09SG7D36R

For the temp sensor, I'm using an automotive 3/8 NPT unit for coolant. Research showed it had a max resistance around 400ohms, the temperatures and resistances noted in the initial prompt are my own, albeit very rough ballpark numbers. Here's the exact temperature sensor: https://www.amazon.com/dp/B07SLYHN6M

The 128x32 I2C OLED screens I used are here: https://www.amazon.com/dp/B08CDN5PSJ

The potentiometer is just a generic 10k ohm unit I got in a bulk pack a while back

The momentary microswitch is a generic thing too. I have it completing a ground when clicked, and ChatGPT made it use the pullup resistor function thing, which seems correct from my vague understanding.


So the biggest ah-ha moment I had today is the discovery of the map() function. That solves so much of the overcomplication that was being done by ChatGPT. It can take one range of input values, and map it to a new range. So at the most basic level, I believe I should be able to take the resistance of the temp sensor for the lowest and highest values I recorded, and map them to the temperature values they correlate to in a linear fashion, with one line of code. But it wasn't until today that I grasped that the Ardunio can't actually measure resistance, so I have some resistors on the way so I can supply voltage and observe the voltage drop (things that are probably laughably intuitive for you guys...hey, I'm learning :laughing:).

Then while I have the potentiometer successfully showing up on the serial monitor with a range from 0-1023, I have now successfully mapped it to a range from -30 to +30 (the amount of temperature adjustment available at the knob, can change to whatever). So it should(?) be easy to apply as a modifier to the desired temperature range for the PWM duty cycle to sweep through.

Still a ton of learning/understanding to wade through, but it definitely feels like progress. I figure if I'm gunna learn these things, might as well start my first project with something nice and simple :lmao:
 
Last edited:
Ok, tomorrow I will go shopping and order those things. I will stand by to help you if you need it or get stuck. Further, I will try to look at the JL fan line and see if I can swing the cheapest smallest fan from the same series.

Map (and reduce) are very powerful indeed. But... keep it simple at first. You want to go through many iterations and the less code you have to debug to start with, the better it will be for you. Forget the POT, the momentary switch, the OLED display-- just focus on getting the PWM output to the fan to work at different values. For example, just get it run it for 5 seconds at a time in a loop at 100%, 75%, 50%, 25%, off. Use the USB connection to your desktop (for now) to write messages to the debug terminal so you can see them on the computer screen and verify that what is going on is what you expected. Write debug messages to the terminal something like:

  • Setting fan to 100%
  • Setting fan to 75%
  • Settting fan to 50%
  • etc
Then-- when you can control the fan at a range of different values and you feel sufficient progress was made-- check in the code to github or copy it somewhere safe and then start adding the next feature, say the temperature input.

When you start the next feature, you may even want it to be in a separate throw away program that you write just to make sure you know how the hardware works (proof of concept, or POC). For example, just read in the current temp from the probe and spit it out to the debug screen with a message. Hit the probe with hot water or cold ac air. Once you get that working with accurate values being reported, copy the code over and put it in a function in your main program...

While you are still learning you don't want to try to write all the features at once and then debug it all afterwards-- or you will be a very sad panda with a big mess on your hands that is too frustrating to figure out.

As you move all the code into one program and it gets too messy, we will help you refactor it.
 
Then while I have the potentiometer successfully showing up on the serial monitor with a range from 0-1023, I have now successfully mapped it to a range from -30 to +30 (the amount of temperature adjustment available at the knob, can change to whatever). So it should(?) be easy to apply as a modifier to the desired temperature range for the PWM duty cycle to sweep through.
Assuming that the potentiometer is linear in rotation vs resistance, you may be better suited to using a parameterized equation. Some of the following may need some syntax changed to work with arduino.

Code:
percent_pot = pot_value / max_pot_value;
temperature_adjustment = min_temperature_value + percent_pot * (max_temperature_value - min_temperature_value);

Or putting numbers in:
Code:
percent_pot = pot_value/1023;
temperature_adjustment = -30 + percent_pot * 60;

Applying similar logic to the temperature sensor and using excel to get a trendline:
Code:
temperature = 202.4 * e ^ (-0.003 * resistance);

That one has a max of 6% error. More data points would give better accuracy. If there is a sudden sharp increase or decrease in the resitance, a lookup table would work better.

And again for temperature to duty cycle:
Code:
if temperature > 210 + temperature_adjustment
    duty_cylce = 95;
elseif temperature < 160 + temperature_adjustment
    duty_cylce = 0;
else
    duty_cylce = (temperature - (160 + temperature_adjustment)) / (210 - 160) * 95;
end
 
Would be easier to use a random unlocked e38 PCM and a $15 GM CTS as your PWM controller.
But I'm curious to see where you end up with this.
 
Interesting project, I also like to make shit, train driver stuff.
Not to shit all over a home brew controller, but some things to consider.......

There are many 12V 3-PH BLDC motor control demo/reference design boards out there, with code, theory and so on.

What 3-ph FET drive are you gong to use to switch 70 amps? (850w/12v = 70A). How to dissipate the heat from switches?
Switching transient noise will be high, and needs to be handled at PCB level for it to be robust, or work at all.

The whole system needs to be hardened for automotive use, which is non-trivial. For example, when you release the key after start, the field stored in starter winding will make +12 more like -20V for a short time. (or even -100V). Blip of a winch can do same. Negative voltage will destroy things quickly.

A home brew solution will not be anywhere as reliable as a system that has gone through full development and qualification cycle. Thermal (-40 C to 150 C), electromagnetic susceptibility (Blip of a winch can shut down/reset the controller). This take a long time and lots of money.

Quality motor control S/W is highly complex to handle all error conditions (over current, catastrophic failure, under/over voltage lock out....)

I work at a chip company and one of our customers is Spal, who supplies those European car manufactures. Piles of fans and crap in the lab. All kinds of motor and power supply applications (EPS, ABS, DEF/coolant pumps, LED lighting, wireless phone charging, touch screen control and so on.

Good luck!
 
Ok, tomorrow I will go shopping and order those things. I will stand by to help you if you need it or get stuck. Further, I will try to look at the JL fan line and see if I can swing the cheapest smallest fan from the same series.

Map (and reduce) are very powerful indeed. But... keep it simple at first. You want to go through many iterations and the less code you have to debug to start with, the better it will be for you. Forget the POT, the momentary switch, the OLED display-- just focus on getting the PWM output to the fan to work at different values. For example, just get it run it for 5 seconds at a time in a loop at 100%, 75%, 50%, 25%, off. Use the USB connection to your desktop (for now) to write messages to the debug terminal so you can see them on the computer screen and verify that what is going on is what you expected. Write debug messages to the terminal something like:

  • Setting fan to 100%
  • Setting fan to 75%
  • Settting fan to 50%
  • etc
Then-- when you can control the fan at a range of different values and you feel sufficient progress was made-- check in the code to github or copy it somewhere safe and then start adding the next feature, say the temperature input.

When you start the next feature, you may even want it to be in a separate throw away program that you write just to make sure you know how the hardware works (proof of concept, or POC). For example, just read in the current temp from the probe and spit it out to the debug screen with a message. Hit the probe with hot water or cold ac air. Once you get that working with accurate values being reported, copy the code over and put it in a function in your main program...

While you are still learning you don't want to try to write all the features at once and then debug it all afterwards-- or you will be a very sad panda with a big mess on your hands that is too frustrating to figure out.

As you move all the code into one program and it gets too messy, we will help you refactor it.

Thanks. I'm definitely breaking everything down into understandable chunks for myself. I started by figuring out how to get the potentiometer outputting the full sweep successfully without worrying about the other components, which seemed to be a manageable bite to take. Then I focused on getting the screen displaying at least static data, figuring out how to toggle between various output options will be on the chopping block for later. The latest thing I've been tinkering with is getting the temp sensor outputting expected data. I've got it outputting, but choosing the value for the added resistor to get the expected values is where I am now. One bite at a time, then I'll circle back to combining the various aspects into a functional device once I've built a little confidence.

Assuming that the potentiometer is linear in rotation vs resistance, you may be better suited to using a parameterized equation. Some of the following may need some syntax changed to work with arduino.

Code:
percent_pot = pot_value / max_pot_value;
temperature_adjustment = min_temperature_value + percent_pot * (max_temperature_value - min_temperature_value);

Or putting numbers in:
Code:
percent_pot = pot_value/1023;
temperature_adjustment = -30 + percent_pot * 60;

Applying similar logic to the temperature sensor and using excel to get a trendline:
Code:
temperature = 202.4 * e ^ (-0.003 * resistance);

That one has a max of 6% error. More data points would give better accuracy. If there is a sudden sharp increase or decrease in the resitance, a lookup table would work better.

And again for temperature to duty cycle:
Code:
if temperature > 210 + temperature_adjustment
    duty_cylce = 95;
elseif temperature < 160 + temperature_adjustment
    duty_cylce = 0;
else
    duty_cylce = (temperature - (160 + temperature_adjustment)) / (210 - 160) * 95;
end
Yep, the potentiometer is linear! For the sake of my own learning, may I ask what the benefits are of the parameterized equation over just using the mapped values? I know I'm putting my lack of understanding on full display here, but it's a great way to learn haha. Just blind intuition shooting from the hip, it seems like if I'm already going to have the temperature sensor mapped to relevant temperatures Fahrenheit, and then map the potentiometer to useful temperature values for tuning, I could come up with a simple code to just add the mapped potentiometer value to the preset min/max temp range. So essentially something like (not code, just theory)

mapped_potentiometer = full 0-1023 range mapped to a range of -30 to +30

Then
Minimum duty cycle temperature = 160 + mapped potentiometer
Maximum duty cycle temperature = 210 + mapped potentiometer


Would be easier to use a random unlocked e38 PCM and a $15 GM CTS as your PWM controller.
But I'm curious to see where you end up with this.

Oh I'll say outright this is absolutely not the easiest route, but I've been looking for an actual useful purpose to learn Arduinos, so it's an enjoyable learning experience and hopefully by the end I have something useful, that may also benefit others.

Interesting project, I also like to make shit, train driver stuff.
Not to shit all over a home brew controller, but some things to consider.......

There are many 12V 3-PH BLDC motor control demo/reference design boards out there, with code, theory and so on.

What 3-ph FET drive are you gong to use to switch 70 amps? (850w/12v = 70A). How to dissipate the heat from switches?
Switching transient noise will be high, and needs to be handled at PCB level for it to be robust, or work at all.

The whole system needs to be hardened for automotive use, which is non-trivial. For example, when you release the key after start, the field stored in starter winding will make +12 more like -20V for a short time. (or even -100V). Blip of a winch can do same. Negative voltage will destroy things quickly.

A home brew solution will not be anywhere as reliable as a system that has gone through full development and qualification cycle. Thermal (-40 C to 150 C), electromagnetic susceptibility (Blip of a winch can shut down/reset the controller). This take a long time and lots of money.

Quality motor control S/W is highly complex to handle all error conditions (over current, catastrophic failure, under/over voltage lock out....)

I work at a chip company and one of our customers is Spal, who supplies those European car manufactures. Piles of fans and crap in the lab. All kinds of motor and power supply applications (EPS, ABS, DEF/coolant pumps, LED lighting, wireless phone charging, touch screen control and so on.

Good luck!

So the beauty of the JL fan is it manages all of the critical switching internally, it only requires a PWM signal to operate. Very interesting notes on the hardening and completely makes sense. It's something I'll have to keep an eye on (along with possibly carrying a backup PWM controller of some sort so I can force the fan to run if the controller fails), though people seem to have integrated arduinos into automotive applications with somewhat decent success from what I've gathered. If I need to put some sort of buffer on the incoming power I can go that route, though I might run one until failure for part of the experiment. But I have no problem sharing any failures with you guys, so you can enjoy the ride :smokin:
 
The whole system needs to be hardened for automotive use, which is non-trivial. For example, when you release the key after start, the field stored in starter winding will make +12 more like -20V for a short time. (or even -100V). Blip of a winch can do same. Negative voltage will destroy things quickly.

A home brew solution will not be anywhere as reliable as a system that has gone through full development and qualification cycle. Thermal (-40 C to 150 C), electromagnetic susceptibility (Blip of a winch can shut down/reset the controller). This take a long time and lots of money.

I ran into all this when I tried to make a transmission display for the AW4 in my XJ. It was a PITA years ago to find anything electronically hardened in the world of Arduino. The least little blip in power on any input and your board was toasted. Some things are changing slowly and there are companies making electronically hardened Arduino compatible boards that are native 12/24 volt for industrial applications/PLC controllers. There is still the matter of mounting these boards to resist vibration/heat and the fact that most of the Arduino compatible accessories and sensors are still cheap and not suitable for production use.
:shaking:
 
So dumb question about the voltage spike sensitivity, is the risk of that cured/minimized by the voltage regulator/buck converter I'm using? That's the only connection to the vehicles wiring


Here's some testing with the fan and generic PWM generator. With this knowledge I can replace some of the initial placeholder values:

 
Amazon parts orderded. Misunderstood the fan is a Jeep JL fan and not some fan made by some company named JL... so looking on junkyard dog for a fan.
 
So dumb question about the voltage spike sensitivity, is the risk of that cured/minimized by the voltage regulator/buck converter I'm using? That's the only connection to the vehicles wiring

You should be good since you have no other inputs from vehicle power. I suppose if something goes way wrong you could have the PWM output to the fan backfeed power somehow, but its probably not worth worrying about.
 
Top Back Refresh