Controlling car cooling loops, which board to select?

I am converting my 1967 Volvo Amazon wagon to full electric.
This requires me to control 3 cooling loops. Hope you can help me to decide whether Arduino can do this (possibly with multiple boards) or that a platform that can multitask like Raspberry PI is more suitable.
I think Arduino can do the job, and hope to get some input on the board(s) to be used.
I am based in The Netherlands so it will be from the Genuino family.
My controlling needs are the following:

Temperature control

  • I have 3 Pierburg pumps of which the speed can be controlled by PWM (@45 to 70 Hz) and I want to dynamically set the speed based on the temperature in each of the circuits.
  • I want to be able to mix two of the circuits (to use the waste heat of one to heat another)
  • I want to be able to exclude a radiator from a loop if that one is below a certain temperature

Although I am a newbie, based on what I have read that should be possible with one board, right?

Active heating
When it is too cold outside I want to be able to switch on the heater in the cooling loop of the batteries. I want to be able to do that remotely and via a switch/button in the car.
As a nice to have, I want to be able to switch on the 12V heaters remotely as well.
I would say those tasks could be done by another board.

So in short in terms of I/O I need:

  • 3x PWM output
  • 2x valve output
  • 1x output to switch on coolant heater
  • 1x output to switch on fan heaters
  • 3x temp input
  • 2x (remote) switch input

I tend to be interested in 2x a Genuino 101 board plus a 3G/GPRS shield with SIM5215, some DS18B20 temp. sensors and two valves

oudevolvo:
This requires me to control 3 cooling loops.

The curiosity is killing me. Why does an electric vehicle need three cooling loops? I can understand one for the cabin.

[quote author=Coding Badly link=msg=3118396 date=1486373143]
Why does an electric vehicle need three cooling loops?[/quote]
1= Cooling of the AC motor (temp range 70 to 90 degrees)
2= Cooling of the controller (temp range 30 to 40 degrees)
3= Heating and cooling of the batteries (ideal temp 25 degrees)
The cabin is being heated by hot air and not using water as an intermediate.

Your main problem is obtaining suitable activators. Temperature measurement is easy.

And given your supply voltage is probably quite high, suitable power supplies and drive electronics.

As for processing, even a small arduino would be up to the job.

Allan.

Good to hear that Arduino will have sufficient processing power. Also a Uno already or is a 101 recommended?
Initially I intended to use a Siemens Logo, but that PLC was not fast enough.

allanhurst:
Your main problem is obtaining suitable activators.
And given your supply voltage is probably quite high, suitable power supplies and drive electronics.

That I do not fully understand. What so you mean by activators?
My DC-DC converter is producing 13,5V.
I saw that Arduino hand take input up until 20V, but that up until 12V is recommended so perhaps a DC-DC regulator is a good idea (found many off the shelve solutions for that).
I saw there is a relay shield for Arduino, will that do the job in driving the valves etc?

Probably an Uno would be the better choice, as it has 5v I/O. And I’d use a cheap buck convertor to get about 9v as it’s PSU .

Actuators- I meant the fans etc, but you already have those.

Relays would be fine.

You’ll have to change the timer if you need 45-70Hz PWM for the pumps - are these 5v, or do you need 12? - if so level translators will be needed.

A nagging thought - how many different PWM’s can you drive simultaneously? - perhaps someone else could confirm.

Thermistors to analog inputs for temperature sensing would be fine. It might be useful to have ambient temperature as well as a guide to how hard to run the pumps.

good luck

Allanj

Thanks! Altogether I am under the impression that it will take some research and trial and error, but that eventually it will work out. If it turns out one board cannot drive three PWM's simultaneously I will just have 3 separate boards :wink:
The pumps do run at 12V indeed. Will add "level translators" to my list.

The fans for the radiators of the controller and motor are already being controlled by the electronics running those. But the one for the cooling loop of the batteries does need to be added and will be controlled by the Arduino, thanks.

My worries about multiple PWMs seem unfounded,,,

see

regards

Allan

allanhurst:
My worries about multiple PWMs seem unfounded,,,

If the frequency of the three really has that tight of a range (45 Hz to 70 Hz) then your worries are well founded.

The Uno has three timers. They can each be configured for two outputs with a limited choice of frequencies (which does not include 45 Hz to 70 Hz) or one output with a very long list of possible frequencies.

However, timer 0 is also used for millis / micros. That limits timer 0 to two outputs with a set frequency (which is not in the 45 Hz to 70 Hz).

That leaves four options for AVR processors...

  1. More than one processor
  2. Processor with four or more timers (like a Teensy or a Mega)
  3. Pump that is not restricted to such a tight frequency range
  4. Give up millis / micros

45 to 70Hz can be done with millis() or micros() timing relatively easily. It doesn't seem like this thing is going to be doing too many time-consuming calculations.

allanhurst:
My worries about multiple PWMs seem unfounded,,,
http://forum.arduino.cc/index.php?topic=453762.0

Thanks for starting that topic!

Thanks, as a newbie I had to chew on that for a while, but I think I understand.
If I understand correctly one would ideally not modify the Timer 0.
I did some further research on the pump. Pierburg says the PWM signal can be from 45Hz to 1100Hz. However someone found out that at higher frequencies the pump does not restart upon signal loss for more than 4 seconds. He advised the PWM signal to be kept below 250Hz and had a successful setup at 70 Hz himself. When he increased to 290Hz the pump already did not restart anymore. Having said that, I think the bandwidth can be bigger than the 45Hz to 70Hz and should be 45Hz to 250Hz.

I found this topic quite useful http://forum.arduino.cc/index.php?topic=72092.0
That topic mentions a Mega 2560 and while using prescaler = 4 ---> PWM frequency is 120 Hz
That could very well work for my application.

So using a Mega 2560 sounds like a good way forward. The outputs are 5V and it supports a 4G + GPS Shield

oudevolvo:
That topic mentions a Mega 2560 and while using prescaler = 4 ---> PWM frequency is 120 Hz

Bear in mind that the person who wrote that post and the person who wrote the playground page are not using the keyword "prescaler" correctly. That matters when you are trying to understand an AVR datasheet.

The correct keyword is "clock select bits". The values are 0 through 7. Each value corresponds to either a configuration or a "prescaler divisor".

The "prescaler divisor" is the divisor for the system clock. The values are 1, 8, 64, 256, and 1024.

So, when the "clock select bits" are set to 4 the "prescaler divisor" is 256. For an 8 bit timer (or a 16 bit timer configured for an 8 bit mode) the phase-correct PWM frequency is...

16000000 / (PRESCALER DIVISOR * 510) = 16000000 / (256 * 510) = 122.549019608

Also bear in mind that many AVR timers are 16 bit. Reconfiguring the timers to run in a 16 bit mode will do wonders for your granularity.

oudevolvo:
I did some further research on the pump. Pierburg says the PWM signal can be from 45Hz to 1100Hz. However someone found out that at higher frequencies the pump does not restart upon signal loss for more than 4 seconds. He advised the PWM signal to be kept below 250Hz and had a successful setup at 70 Hz himself. When he increased to 290Hz the pump already did not restart anymore. Having said that, I think the bandwidth can be bigger than the 45Hz to 70Hz and should be 45Hz to 250Hz.

The 480Hz standard PWM output would be right in the middle of that range. (Not all pins on an Uno - pins 5 and 6 are 980Hz.)

“Failed to start” is more likely to do with the speed commanded, not the frequency. Most motors won’t start when you give them 5% or 10%, even if they will run at that low speed after starting. You may need to ‘unstick’ the motor with 20% or greater for 20-200 milliseconds.

Thanks for the additional explanation on "clock select bits" and "prescaler divisors".

Good to hear that the issue with the pump might not even be frequency. Will make it easier if I can just use the defaults. That does trigger another question though: How can the Arduino know the motor is not running even though it should and needs to be unsticked?

Here is the whole story I found about controlling this pump using PWM
http://webpages.charter.net/n8nxf/EVTV%20Pierburg%20CWA-50%20Coolant%20Pump.pdf
It does not tell however at which duty cycle the pump stopped and would not restart.
Building on that document I will keep my duty cycle in between 13% and 85%.
I will give it a try with the default 490 Hz for pins 2, 3, 5, 6, 7, 8, 9, 10, 11 or 12 (will use only 3 of them, but these are 490 Hz).

I have ordered an Arduino Mega today and some additional parts and stuff to play around with. So first I am going to familiarize myself with the board and programming language and do some tutorials.
After that I will step by step work on my project.
I also ordered a Logic Level Converter already to be able to turn the 5V PWM signal into a 12V one.

Will need to buy some converters to go from the 13,5V input from the car to:

  • 5V (Vi for the level converter)
  • 9V power the Arduino
  • 12V (Vo for the level converter)

Thanks for your great support!

oudevolvo:
That does trigger another question though: How can the Arduino know the motor is not running even though it should and needs to be unsticked?

Some possibilities...

  1. Measure the motor current. If it is abnormally high the motor is probably stalled.
  2. Measure flow past the pump. If it is abnormally low the motor is stalled or the fluid is gone.
  3. Measure pressure on the pump output. If it is abnormally low the motor is stalled or the fluid is gone.
  4. Measure pressure differential across the pump. If it is close to zero the motor is stalled or the fluid is gone.

Pumps used for computer cooling are set up to act like computer fans. There’s a PWM input and there’s a ‘tacho’ output. For a pump, this will directly give the actual RPM for the pump.

The fan specification also says that the fans are never allowed to run between 0% and 30% speed. If you give them zero PWM, then they run at 30%. That’s just due to the flow characteristic of most small computer fans. The flow below 30% is close enough to zero that you may as well switch the fan off. It also eliminates the starting problem as every fan must reliably start at 30%.

Well, I got started and am running into some challenges. Not sure whether I should start a new topic or continue in this one since the content is changing compared to my original subject.

First I hooked up an LCD on my mega and used the following code to print some dummy text

#include <LiquidCrystal.h> // includes the LiquidCrystal Library 
LiquidCrystal lcd(1, 2, 4, 5, 6, 7); // Creates an LC object. Parameters: (rs, enable, d4, d5, d6, d7) 

void setup() { 
 lcd.begin(16,2); // Initializes the interface to the LCD screen, and specifies the dimensions (width and height) of the display } 
}

void loop() { 
 lcd.setCursor(0,0); //origin
 lcd.print("T=23"); // Prints "T=23" on the LCD battery temp
 lcd.setCursor(5,0); // Sets the location at which subsequent text written to the LCD will be displayed 
 lcd.print("T=50"); // controller temp
 lcd.setCursor(11,0);
 lcd.print("T=100"); // motor temp
 lcd.setCursor(0,1); //rij 2
 lcd.print("50%"); // Prints battery pump duty cycle
 lcd.setCursor(5,1); 
 lcd.print("25%"); // Prints controller pump duty cycle
 lcd.setCursor(11,1); 
 lcd.print("100%"); // Prints motor pump duty cycle
}

So far so good (see attachment IMG_2291).
Next I connected a DS18B20 sensor and did a lookup for it’s address.
In a test Sketch I am able to read the temperature. My problem occurs when I want to print it onto the LCD. The first character does not start at 0,0 anymore like it did in the Sketch above and the display does not get cleared and “scrambles”. See attachment IMG_2318. This is my code

#include <DallasTemperature.h> // Source https://www.milesburton.com/Dallas_Temperature_Control_Library
#include <OneWire.h> // includes the OneWire Library for DS18B20 temp. sensors
#include <LiquidCrystal.h> // includes the LiquidCrystal Library for LCD display

/*-----( Declare Constants and Pin Numbers )-----*/
// Data wire is plugged into port 12 on the Arduino for battery, controller, motor
#define ONE_WIRE_BUS 12    // NOTE: No ";" on #define  

/*-----( Declare objects )-----*/
// Setup a oneWire instance to communicate with any OneWire devices 
OneWire oneWire(ONE_WIRE_BUS);

// Pass address of our oneWire instance to Dallas Temperature. 
DallasTemperature sensors(&oneWire);

// Creates an LCD object.
LiquidCrystal lcd(1, 2, 4, 5, 6, 7); // Parameters: (rs, enable, d4, d5, d6, d7) 

/*-----( Declare Variables )-----*/
// Assign the addresses of your 1-Wire temp sensors.
DeviceAddress Battery = { 0x28, 0xD3, 0x9B, 0x68, 0x08, 0x00, 0x00, 0xED }; 
DeviceAddress Controller = { 0x28, 0xD3, 0x9B, 0x68, 0x08, 0x00, 0x00, 0xED }; 
DeviceAddress Motor = { 0x28, 0xD3, 0x9B, 0x68, 0x08, 0x00, 0x00, 0xED }; 

int intTempC;
 
void setup() /****** SETUP: RUNS ONCE ******/
{ 
 lcd.begin(16,2); // Initializes the interface to the LCD screen, and specifies the dimensions (width and height) of the display } 
 Serial.begin(9600); // Set communication speed (Baud rate)
 
 //------- Initialize the Temperature measurement library--------------
  sensors.begin();
  // set the resolution to 10 bit (Can be 9 to 12 bits .. lower is faster)
  sensors.setResolution(Battery, 10);
  sensors.setResolution(Controller, 10);
  sensors.setResolution(Motor, 10);
}

void loop()   /****** LOOP: RUNS CONSTANTLY ******/
{
 sensors.requestTemperatures(); // Send the command to get temperatures

  
// Print our characters on the LCD
// NOTE: Line number and character number start at 0 not 1
  
  lcd.setCursor(0,0); //Start at character 0 on line 0
  lcd.print("T=");
  displayTemperature(Battery);
  lcd.setCursor(5,0); // Sets the location at which subsequent text written to the LCD will be displayed 
 lcd.print("T=50"); // controller temp
 lcd.setCursor(10,0);
 lcd.print("T=100"); // motor temp
 lcd.setCursor(0,1); //rij 2
 lcd.print("50%"); // Prints battery pump duty cycle
 lcd.setCursor(5,1); 
 lcd.print("25%"); // Prints controller pump duty cycle
 lcd.setCursor(11,1); 
 lcd.print("100%"); // Prints motor pump duty cycle 
  delay(500);
  lcd.clear();
  lcd.home();
}//--(end main loop )---

/*-----( Declare User-written Functions )-----*/
void displayTemperature(DeviceAddress deviceAddress)
{

float tempC = sensors.getTempC(Battery);

   if (tempC == -127.00) // Measurement failed or no device found
   {
    lcd.print("Er");
   } 
   else
   {
   intTempC = int (tempC);
   lcd.print(intTempC,DEC); 
   }
}// End printTemperature

//*********( THE END )***********

Hope you can help me out in what I am doing wrong.
Or are the DallasTemperature + OneWire + LiquidCrystal libraries not suitable to be used together?

IMG_2318.jpg

IMG_2291.jpg

you need to reset all the lcd pointers every time you rewrite it eg

          lcd.clear();
          lcd.setCursor(0, 0);
          lcd.print(F("ACT TEMP :     C"));
          lcd.setCursor(0, 1);
          lcd.print(F("TGT TEMP :     C"));
          lcd.setCursor(11, 1);
          lcd.print(F("   "));
          lcd.setCursor(11, 1);
          lcd.print(targetTEMP);

regards

Allan

Thanks for your quick response.
Sorry, I think I do not fully understand the answer.
Based on your reply I tried adding "lcd.setCursor(2,0);" after printing the 'T='

lcd.setCursor(0,0); //Start at character 0 on line 0
  lcd.print("T=");
  lcd.setCursor(2,0);
  displayTemperature(Battery);
  lcd.setCursor(5,0);

But that does not help, so I assume you mean something different.

How do I dynamically plot the value of the variable for Battery so it becomes T=25

displayTemperature(Battery); gives an int for the battery temperature sensor.

So write it to the display using

lcd.print(displayTemperature(battery));

until you tell the display to show it, it won't

Allan