Hardware components | ||||||
| × | 1 | ||||
| × | 1 | ||||
Hand tools and fabrication machines | ||||||
|
A friend was looking for a cool solution to control the HVAC (heating, ventilation, air condition) of his car via touchscreen and Arduino. The idea was inspired by an older project of mine about the interior control of a stretch limousine, but should be smaller and easier.
I've taken a Nextion touch screen again for this project and connected them directely with an Arduino UNO. All pictures and other data of the GUI is stored in the Nextion touch itself. It's very easy to connect these touch screens to a microcontroller (in our case Arduino) via the UART.
The hardware is very simple. In our project the hardware was build by my friend, but you can change the source code and connect in the first step an simple relay shield to switch the air condition and ventilation on and off. In our example we've connected three 1wire temperature sensors to the arduino (outside, inside right, inside left) to measure all needed temperatures for the HVAC control.
The motor of the ventilation can be controlled via PWM on Port D9....
/*
* HVAC car control with Arduino
* Version 1.0
* Copyright (C) 2018 Hartmut Wendt www.hwhardsoft.de
*
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <OneWire.h>
#include <TimerOne.h>
// Portkonfiguration
#define REL_VENT_FRONT 5 //relay output for ventilation front
#define REL_VENT_FOOT 6 //relay output for ventilation footwell area
#define REL_VENT_WINDOW 7 //relay output for ventilation window
#define REL_FAN_PWR 8 //relay output for fan power
#define PWM_FAN_PIN 9 //PWM output for fan power
#define REL_COMPRESSOR 11 //relay output for AC compressorr
#define REL_HEATING 12 //relay output for heating valve
#define REL_AIR_CIRCULATION 13 //relay output for air circulation
#define REL_FOG_LIGHT 14 //relay output for fog light
#define REL_HEATING_WINDOW_FRONT 15 //relay output for window heating front
#define REL_HEATING_WINDOW_REAR 16 //relay output for window heating rear
#define TEST_PIN 19 // output for sw tests
// OneWire DS18S20, DS18B20, DS1822 Temperature sensor
OneWire sens_out(2); // outside temperature sensor on D2
OneWire sens_in_right(3); // inside right side temperature sensor on D3
OneWire sens_in_left(4); // inside left side temperature sensor on D4
int temp_out = 20; // measured outside temperature
int temp_in_right = 20; // measured inside right side temperature
int temp_in_left = 20; // measured inside left side temperature
int set_in_right = 20; // setted inside right side temperature
int set_in_left = 20; // setted inside left side temperature
// Variables
int i1;
char *test;
String s1;
String inputString;
boolean AC_ENABLED = false;
int bscheduler = 0;
/** Wird beim Start einmal ausgefhrt */
void setup()
{
// set port direction
pinMode(REL_VENT_FRONT, OUTPUT);
pinMode(REL_VENT_FOOT, OUTPUT);
pinMode(REL_VENT_WINDOW, OUTPUT);
pinMode(REL_FAN_PWR, OUTPUT);
pinMode(REL_COMPRESSOR, OUTPUT);
pinMode(REL_HEATING, OUTPUT);
pinMode(REL_AIR_CIRCULATION, OUTPUT);
pinMode(REL_FOG_LIGHT, OUTPUT);
pinMode(REL_HEATING_WINDOW_FRONT, OUTPUT);
pinMode(REL_HEATING_WINDOW_REAR, OUTPUT);
pinMode(TEST_PIN, OUTPUT);
// init serial port for nextion communication.
Serial.begin(9600);
delay(250);
// first read in of temperatures
temp_out = read_temperature(sens_out);
delay(100);
temp_in_right = read_temperature(sens_in_right);
delay(100);
temp_in_left = read_temperature(sens_in_left);
//pwm init
Timer1.initialize(1000); // 1.000 us = 1 kHz
Timer1.pwm (PWM_FAN_PIN, 0);
}
// ----- Main loop -----------------------------------------------------------------------------------
void loop()
{
// processing of incomming messages from nextion
Nextion_processing();
switch(bscheduler)
{
// measure outside temperature
case 0:
temp_out = read_temperature(sens_out);
// transmit outside temperature to nextion display
Serial.print("ID1.val=");
Serial.print(temp_out);
Serial.write(0xff);
Serial.write(0xff);
Serial.write(0xff);
break;
// measure inside right temperature
case 25:
temp_in_right = read_temperature(sens_in_right);
break;
// measure inside left temperature
case 50:
temp_in_left = read_temperature(sens_in_left);
break;
// HVAC control
case 75:
clima_control();
break;
}
bscheduler++;
if (bscheduler > 100) bscheduler = 0;
delay(10);
}
// read temperature from a connected 1wire temperature sensor
int read_temperature(OneWire ds) {
byte i;
byte present = 0;
byte type_s;
byte data[12];
byte addr[8];
if ( !ds.search(addr))
{
ds.reset_search();
delay(250);
return(97);
}
if (OneWire::crc8(addr, 7) != addr[7])
{
return(98);
}
// the first ROM byte indicates which chip
switch (addr[0])
{
case 0x10:
type_s = 1;
break;
case 0x28:
type_s = 0;
break;
case 0x22:
type_s = 0;
break;
default:
return(99);
}
ds.reset();
ds.select(addr);
ds.write(0x44, 1); // start conversion, with parasite power on at the end
delay(750);
present = ds.reset();
ds.select(addr);
ds.write(0xBE); // Read Scratchpad
for ( i = 0; i < 9; i++)
{
data[i] = ds.read();
}
// Convert the data to actual temperature
int16_t raw = (data[1] << 8) | data[0];
if (type_s) {
raw = raw << 3; // 9 bit resolution default
if (data[7] == 0x10)
{
digitalWrite(TEST_PIN, HIGH);
raw = (raw & 0xFFF0) + 12 - data[6];
}
}
else
{
byte cfg = (data[4] & 0x60);
if (cfg == 0x00) raw = raw & ~7; // 9 bit resolution, 93.75 ms
else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
}
return((int)raw / 16.0);
}
unsigned long StrToHex(String str, byte digits)
{
char ConvByte[10];
str.toCharArray(ConvByte, digits);
return (unsigned long) strtol(ConvByte, NULL, 16);
}
// ------ receiving and processing of incomming data from nextion
void Nextion_processing()
{
int i1;
String s1;
while (Serial.available()) {
// get the new byte:
char inChar = (char)Serial.read();
// add it to the inputString:
inputString += inChar;
if (inChar != '|') return;
}
int i2=inputString.indexOf("=");
if (i2 > 0) {
#ifdef _debug_snd
Serial.print("Nextion: ");
Serial.print(inputString);
Serial.println(" - ");
Serial.print(inputString.substring(i2-2,i2));
Serial.print("=");
Serial.println(inputString[i2+1]);
#endif
//- id2 FOG LIGHT -
//------------------------------------------------------------------------------------------------
if (inputString.indexOf("id02=1")> -1) {
// FOG LIGHT on
digitalWrite(REL_FOG_LIGHT, HIGH);
}
else if(inputString.indexOf("id02=0")> -1) {
// FOG LIGHT off
digitalWrite(REL_FOG_LIGHT, LOW);
}
//- id5 ventilation footwell + window -
//------------------------------------------------------------------------------------------------
if (inputString.indexOf("id05=1")> -1) {
// set ventilation to foot well & window
digitalWrite(REL_VENT_FRONT, LOW);
digitalWrite(REL_VENT_FOOT, HIGH);
digitalWrite(REL_VENT_WINDOW, HIGH);
}
else if(inputString.indexOf("id05=0")> -1) {
// switch all ventilation off
digitalWrite(REL_VENT_FRONT, LOW);
digitalWrite(REL_VENT_FOOT, LOW);
digitalWrite(REL_VENT_WINDOW, LOW);
}
//- id9 ventilation footwell -
//------------------------------------------------------------------------------------------------
if (inputString.indexOf("id09=1")> -1) {
// set ventilation to foot well
digitalWrite(REL_VENT_FRONT, LOW);
digitalWrite(REL_VENT_FOOT, HIGH);
digitalWrite(REL_VENT_WINDOW, LOW);
}
else if(inputString.indexOf("id09=0")> -1) {
// switch all ventilation off
digitalWrite(REL_VENT_FRONT, LOW);
digitalWrite(REL_VENT_FOOT, LOW);
digitalWrite(REL_VENT_WINDOW, LOW);
}
//- id14 ventilation front -
//------------------------------------------------------------------------------------------------
if (inputString.indexOf("id14=1")> -1) {
// set ventilation to front
digitalWrite(REL_VENT_FRONT, HIGH);
digitalWrite(REL_VENT_FOOT, LOW);
digitalWrite(REL_VENT_WINDOW, LOW);
}
else if(inputString.indexOf("id14=0")> -1) {
// switch all ventilation off
digitalWrite(REL_VENT_FRONT, LOW);
digitalWrite(REL_VENT_FOOT, LOW);
digitalWrite(REL_VENT_WINDOW, LOW);
}
//- id22 ventilation front + footwell -
//------------------------------------------------------------------------------------------------
if (inputString.indexOf("id22=1")> -1) {
// set ventilation to front + foot well
digitalWrite(REL_VENT_FRONT, HIGH);
digitalWrite(REL_VENT_FOOT, HIGH);
digitalWrite(REL_VENT_WINDOW, LOW);
}
else if(inputString.indexOf("id22=0")> -1) {
// switch all ventilation off
digitalWrite(REL_VENT_FRONT, LOW);
digitalWrite(REL_VENT_FOOT, LOW);
digitalWrite(REL_VENT_WINDOW, LOW);
}
//- id4 electrical window heating rear -
//------------------------------------------------------------------------------------------------
if (inputString.indexOf("id04=1")> -1) {
// window heating on
digitalWrite(REL_HEATING_WINDOW_REAR, HIGH);
}
else if(inputString.indexOf("id04=0")> -1) {
// window heating off
digitalWrite(REL_HEATING_WINDOW_REAR, LOW);
}
//- id6 electrical window heating front -
//------------------------------------------------------------------------------------------------
if (inputString.indexOf("id06=1")> -1) {
// window heating on
digitalWrite(REL_HEATING_WINDOW_FRONT, HIGH);
}
else if(inputString.indexOf("id06=0")> -1) {
// window heating off
digitalWrite(REL_HEATING_WINDOW_FRONT, LOW);
}
//- id7 air circulation -
//------------------------------------------------------------------------------------------------
if (inputString.indexOf("id07=1")> -1) {
// air circulation on
digitalWrite(REL_AIR_CIRCULATION, HIGH);
}
else if(inputString.indexOf("id07=0")> -1) {
//air circulation off
digitalWrite(REL_AIR_CIRCULATION, LOW);
}
//- id10 Air Condition enabled/disabled -
//------------------------------------------------------------------------------------------------
if (inputString.indexOf("id10=1")> -1) {
// AC enabled
AC_ENABLED = true;
}
else if(inputString.indexOf("id10=0")> -1) {
// AC disabled
AC_ENABLED = false;
}
//- id18 HVAC on/off -
//------------------------------------------------------------------------------------------------
if (inputString.indexOf("id18=1")> -1) {
// HVAC on
}
else if(inputString.indexOf("id18=0")> -1) {
// HVAC off
AC_ENABLED = false;
// FAN off
digitalWrite(REL_FAN_PWR, LOW);
Timer1.pwm (PWM_FAN_PIN, 0);
//air circulation off
digitalWrite(REL_AIR_CIRCULATION, LOW);
// window heating off
digitalWrite(REL_HEATING_WINDOW_REAR, LOW);
digitalWrite(REL_HEATING_WINDOW_FRONT, LOW);
// switch all ventilation off
digitalWrite(REL_VENT_FRONT, LOW);
digitalWrite(REL_VENT_FOOT, LOW);
digitalWrite(REL_VENT_WINDOW, LOW);
}
//- id13 FAN control -
//------------------------------------------------------------------------------------------------
if (inputString.indexOf("id13=0")> -1) {
// FAN off
digitalWrite(REL_FAN_PWR, LOW);
Timer1.pwm (PWM_FAN_PIN, 0);
}
else if(inputString.indexOf("id13=1")> -1) {
// FAN level 1
digitalWrite(REL_FAN_PWR, HIGH);
Timer1.pwm (PWM_FAN_PIN, 146);
}
else if(inputString.indexOf("id13=2")> -1) {
// FAN level 2
digitalWrite(REL_FAN_PWR, HIGH);
Timer1.pwm (PWM_FAN_PIN, 293);
}
else if(inputString.indexOf("id13=3")> -1) {
// FAN level 3
digitalWrite(REL_FAN_PWR, HIGH);
Timer1.pwm (PWM_FAN_PIN, 439);
}
else if(inputString.indexOf("id13=4")> -1) {
// FAN level 4
digitalWrite(REL_FAN_PWR, HIGH);
Timer1.pwm (PWM_FAN_PIN, 585);
}
else if(inputString.indexOf("id13=5")> -1) {
// FAN level 5
digitalWrite(REL_FAN_PWR, HIGH);
Timer1.pwm (PWM_FAN_PIN, 731);
}
else if(inputString.indexOf("id13=6")> -1) {
// FAN level 6
digitalWrite(REL_FAN_PWR, HIGH);
Timer1.pwm (PWM_FAN_PIN, 877);
}
else if(inputString.indexOf("id13=7")> -1) {
// FAN level Max
digitalWrite(REL_FAN_PWR, HIGH);
Timer1.pwm (PWM_FAN_PIN, 1023);
}
//-- setted temperature right --
//------------------------------------------------------------------------------------------------
i1 = inputString.indexOf("id20=");
if (i1 > -1)
{
set_in_right = inputString.charAt(i1 + 5) - 48;
}
//-- setted temperature left --
//------------------------------------------------------------------------------------------------
i1 = inputString.indexOf("id16=");
if (i1 > -1)
{
set_in_left = inputString.charAt(i1 + 5) - 48;
}
}
while(Serial.available()) {Serial.read();}
inputString = "";
}
// HVAC control
void clima_control() {
// cooling or heating requiredn?
if (temp_out < set_in_left) {
// heating
digitalWrite(REL_COMPRESSOR, LOW);
digitalWrite(REL_HEATING, HIGH);
} else if ((temp_out > (set_in_left + 1)) && (temp_out > 15) && (AC_ENABLED == true)) {
// cooling
digitalWrite(REL_COMPRESSOR, HIGH);
digitalWrite(REL_HEATING, LOW);
} else {
// temperature ok - no further action required
digitalWrite(REL_COMPRESSOR, LOW);
digitalWrite(REL_HEATING, LOW);
}
}
Comments