Пользователь
Регистрация: 02.07.2012
Регион: 59
Сообщений: 64
|
Управление климатом Volkswagen Touareg NF
На VW Touareg NF 2010 - 2015 год отсутствуют кнопки включения обогрева руля и лобового стекла. Управление происходит через меню климата на голове. Иногда это не удобно, хотя бы потому, что голова грузится довольно долго и утром лень ждать. С 2015 года кнопки появились, но просто поставить и подключить их не получается, потому что изменился блок управления бортовой сети.
Для решения использовалась ардуино уно и кан шилд от SeedStudio.
Засыпание не реализовано. Ардуинка тупо висит на засыпающем плюсе.
Код сильно не вылизывал. Сейчас переделываю на Leonardo с засыпанием, новый код выложу позже.
PHP код:
#include <mcp_can.h> #include <SPI.h> #include <EEPROM.h>
/* Скетч управления подогревом руля и лобового для WV Touareg 2014-2014 * тестировано на Arduino UNO и SEEDStudio CAN-BUS Shield v 1.0 * для версии CAN-BUS Shield v 1.2 поменять порт MCP на 9 */
const int MCP_PORT = 10; // Для версии 1.0, для версии 1.2 поменять на 9. const int Port = 0x601; // Порт КАН шины для управления const int Button_Glass_Pin = 4; // Пин кнопки стекла const int Button_Steer_Pin = 6; // Пин кнопки руля const int LED_Glass_Pin = 5; // Пин контрольного светодиода стекла const int LED_Steer_Pin = 7; // Пин контрольного светодиода руля const int EE_Steer_Address = 0; // Адрес постоянного хранилища состояния обогрева руля const int EE_Glass_Address = 1; // Адрес постоянного хранилища состояния обогрева стекла boolean EE_Steer = false; // Состояние руля true - вкл, false - выкл boolean EE_Glass = false; // Состояния стекла true - вкл, false - выкл
MCP_CAN CAN(MCP_PORT); // Инициализация порта CAN шины
unsigned char SteerOff[5] = {0x20, 0x74, 0x00, 0x00, 0x00}; // КАН строка выключение руля unsigned char SteerOn [5] = {0x20, 0x74, 0x00, 0x01, 0x00}; // КАН строка включение руля unsigned char GlassOff[4] = {0x20, 0x6D, 0x00, 0x01}; // КАН строка выключение стекла unsigned char GlassOn [4] = {0x20, 0x6D, 0x01, 0x01}; // КАН строка включение стекла boolean flagRecv = 0; // Флаг того, что сработало прерывание - получен сигнал по шине. unsigned char len = 0; // Длина полученной строки unsigned char buf[8]; // Буфер КАН шины
struct BUTTON // структура кнопка { boolean on; // нажатие было boolean longpress; // нажатие было длинным };
void setup() { Serial.begin(115200); // Инициализация ком порта для контрольного вывода. В будущем, все строки Serial можно закомментировать
while (CAN_OK != CAN.begin(CAN_500KBPS)) // Инициализация КАН шины : baudrate = 500k { Serial.println("CAN BUS Shield init fail"); Serial.println(" Init CAN BUS Shield again"); delay(100); } Serial.println("CAN BUS Shield init ok!");
pinMode(Button_Glass_Pin,INPUT); // Инициализация кнопки стекла pinMode(LED_Glass_Pin,OUTPUT); // Инициализация контрольного светодиода стекла pinMode(Button_Steer_Pin,INPUT); // Инициализация кнопки руля pinMode(LED_Steer_Pin,OUTPUT); // Инициализация контрольного светодиода руль digitalWrite(Button_Glass_Pin, HIGH); // Включение внутреннего подтягивающего резистора стекло digitalWrite(Button_Steer_Pin, HIGH); // Включение внутреннего подтягивающего резистора руль EE_Steer = EEPROM.read(EE_Steer_Address); // Чтение из памяти состояние руля EE_Glass = EEPROM.read(EE_Glass_Address); // Чтение из памяти состояние стекла Steer (); // Инициализация обогревов из памяти Glass (); attachInterrupt(0, MCP2515_ISR, FALLING); // Инициализация прерывания по чтению из КАН шины
CAN.init_Mask(0, 0, 0x7FF) ; // there are 2 mask in mcp2515, you need to set both of them CAN.init_Mask(1, 0, 0x7FF); // в оригинале стоит 0x3FF ? CAN.init_Filt(0, 0, Port); // принимаем сигнал с единственного порта } void MCP2515_ISR() // Обработка прерывания. Не понимаю, как это работает, поэтому сделано строго, как в примере { flagRecv = true; }
void Steer() // Подпрограмма управление рулем { if (EE_Steer) // Если флаг обогрева установлен { CAN.sendMsgBuf(Port, 0, 5, SteerOn); // Посылка команды включения обогрева руля digitalWrite(LED_Steer_Pin,HIGH); // Включение светодиода руля Serial.println(" руль включен"); } else // Иначе - флаг обогрева сброшен { CAN.sendMsgBuf(Port, 0, 5, SteerOff); // Посылка команды вкылючения обогрева руля digitalWrite(LED_Steer_Pin,LOW); // Выключение светодиода руля Serial.println(" руль выключен"); } delay(200); } void Glass() // Подпрограмма управление стеклом { if (EE_Glass) // Если флаг стекла установлен { CAN.sendMsgBuf(Port, 0, 4, GlassOn); // Посылка команды включение обогрева стекла digitalWrite(LED_Glass_Pin,HIGH); // Включение светодиода стекла Serial.println(" стекло включено"); } else // Иначе - флаг обогрева сброшен { CAN.sendMsgBuf(Port, 0, 4, GlassOff); // Посылка команды выключение обогрева стекла digitalWrite(LED_Glass_Pin,LOW); // Выключение светодиода стекла Serial.println(" стекло выключено"); } delay(200); } void Blink(int pin, int n, boolean led) // Подпрограмма "Моргание светодиодом в подтверждение". Номер пина, количество морганий, статус в котором надо оставить. { if (led) // если светодиод уже горит, то выключаем { digitalWrite(pin,LOW); delay (500); } for (int i=0; i<n; i++) { // n раз моргнули в подтверждение digitalWrite(pin,HIGH); delay (500); digitalWrite(pin,LOW); delay (500); } if (led) digitalWrite(pin,HIGH); // Включили светодиод обратно, если надо. } BUTTON Pressing(int pin) // Подпрограмма обработка нажатия кнопки. Pin - номер порта { int n = 0; // Счетчик BUTTON key; // Структура кнопки для возврата while (digitalRead(pin)==LOW && n <=100) // Обрабатывет длинное нажатие, считает тайминги, выход, если превышен таймиг или кнопка отпущена { n++; // Увеличение счетчика тайминга delay (20); } key.on = (n>0&& n<100); // Установлен флаг короткого нажатия key.longpress = (n>=100); // Установлен флаг длинное нажатие return key; }
void KeyDetect() // Подпрограмма чтения кнопки { BUTTON glass = Pressing (Button_Glass_Pin); // Чтение нажатия кнопки стекла BUTTON steer = Pressing (Button_Steer_Pin); // Чтение нажатия кнопки руля if (steer.longpress) // ОБработка длинного нажатия кнопки руля { EEPROM.write (EE_Steer_Address,EE_Steer); // Запись текущего состояния в EEPROM Serial.write("запись руль"); Blink (LED_Steer_Pin, 5, EE_Steer); // Моргнуть 5 раз и оставить в том же положении, что был delay (500); } if (glass.longpress) // ОБработка длинного нажатия кнопки стекла { EEPROM.write (EE_Glass_Address,EE_Glass); // Запись текущего состояния в EEPROM Serial.write("запись руль"); Blink (LED_Glass_Pin, 5, EE_Glass); // Моргнуть 5 раз и оставить в том же положении, что был delay(500); } if (steer.on) // ОБработка простого нажатия кнопки руля { EE_Steer = !EE_Steer; // Меняем значение флага обогрева руля на противоположное Steer (); // Отправляем на обработку с текушщим значением } if (glass.on) // ОБработка простого нажатия кнопки стекла { EE_Glass = !EE_Glass; // Обращаем значение обогрева стекла Glass(); // Отправляем на обработку с текушщим значением } } void External_Control() // ОБработка перехвата внешнего воздействия через КАН шину { flagRecv=0; boolean steer_on = true, steer_off = true; // Инициализация ключей проверки строки boolean glass_on = true, glass_off = true; /* Взято из примера, проверка всего буфера * iterate over all pending messages. If either the bus is saturated or the MCU is busy, both RX buffers * may be in use and reading a single message does not clear the IRQ conditon. */ while (CAN_MSGAVAIL == CAN.checkReceive()) // Взято из примера, очищение буфера { CAN.readMsgBuf(&len, buf); // Чтение данных из буфера КАН. Данные - len: data length, buf: data buf if (len==5) // Если длина строки == 5, то это руль { for(int i = 0; i<len; i++) { steer_on = steer_on && (buf[i]==SteerOn [i]); // Сравниваем побитово на совпадение со сторокй включения руля steer_off = steer_off && (buf[i]==SteerOff[i]); // Сравниваем побитово на совпадение со строкой выключения руля } if (steer_on) // Если перехвачена команда включения руля { EE_Steer = true; // Установка флага -подогрев руля включен digitalWrite(LED_Steer_Pin,HIGH); // Включение светодиода руля Serial.println(" Обогрев руля включен внешним воздействием"); } else if (steer_off) // Если перехвачена команды выключения руля { EE_Steer = false; // Установка флага - подогрев руля выключен digitalWrite(LED_Steer_Pin,LOW); // Выключение светодиода руля Serial.println(" Обогрев руля выключен внешним воздействием"); } else Serial.println(" неизвестная команда руль"); } else if (len==4) // Если длина строки == 4, ьо это стекло { for(int i = 0; i<len; i++) { glass_on = glass_on && (buf[i]==GlassOn [i]); // Сравниваем побитово на совпадение со строкой включения стекла glass_off = glass_off && (buf[i]==GlassOff[i]); // Сравниваем побитово на совпадение со строкой вылючения стекла } if (glass_on) // Если перехвачена команда включения стекла { EE_Glass = true; // Установка флага включения стекла digitalWrite(LED_Glass_Pin,HIGH); // Включение светодиода стекла Serial.println(" стекло включено внешним воздействием"); } else if (glass_off) // Если перехвачена команда включения стекла { EE_Glass = false; // Установка флага выключения стекла digitalWrite(LED_Glass_Pin,LOW); // Выключение светодиода стекла Serial.println(" стекло выключено внешним воздействием"); } else Serial.println(" неизвестная команда стекло"); } else { Serial.println(" неизвестная управляющая команда "); } } // Конец цикла чтения из буфера } void loop() // Основной цикл { if (flagRecv) External_Control(); // Обработка прерывания KeyDetect(); // ОБработка нажатия клавиши }
Последний раз редактировалось admin; 30.09.2020 в 16:46.
|