Климат контроль для автомобиля
- Войдите на сайт для отправки комментариев
Сб, 07/02/2015 - 17:21
Всем привет.
Хочу сделать проэкт климат конроля для автомобиля.
Задумка такая:
На потолке в авто поставить датчик температуры/влажности, на печку присобащить сервопривод.
Хочу чтоб можно было задавать необходимую температуру с помощью вращения потенциометра, а сервопривод будет управлять заслонкой печки добиваясь тем самым необходимой температуры в салоне.
Все параметры заданной и фактической температуры должны отображатся на цветном oled дисплее.
Подскажите с чего начать , т.к опыта нету.
я тоже думал об этом, только вот в чем вопрос, при сильном холоде, надо быстро нагреть машину, то есть надо на максимум ветер и на максимум тепло, ладно как то нагрели... при ззапотевании лобового надо переключиться на лобовое стекло, допустим переключили в ручную, а дует то слабо или не с той температурой, может в твоей по другому будет, просто у меня 3 переключатель (крутилки), одна заслонки, лобовое, ноги; вторая это 4 скорости вентилятора; и тепло холод: И как то у меня нет пока надумок как сделать что бы и в ручную можно было переключать и автоматически. и еще на сколько я помню сервопривод крутится только на 180градусов, а ручка тепло холод где то на 290-300 градусов
мне кажется только на потолке датчика недостаточно,на предыдущем автомобиле у меня точно знаю были в полу,в панели,может и ещё где,но то был климат контроль в комплекте)с авто,и вот боги смилостивелись и послали мне русскую машину ваз09,скажу даже рад что могу поэксперементировать ,хочу покрайней мере начать управлять через шим вентелятором печки,дальше по необходимости,такую вот задачу себе поставил минимум)
сервы сейчас есть и на 350град крутят,тут вопрос в другом ,сразу всё в кучу и серво,и темп.контроль,запутаешься,это моё мнение,я бы начал с шим регулирования,но так как програмировал в основном производственное оборудование контроллеры сименс и т.п.с этим не сталкивался ,а к ардуино так сказать по наводке начал присматриваться,что-то уже получается но мне гораздо проще програмировать через FLprog ,схожая с step S7 среда,но вот теперь возникла необходимость в написании отдельных блоков в среде ардуино ,учусь вот.
по примеру современного холодильника,вентилятор один ,зон две (в холодильном отделении)био фреш 0град,и остальная 2-9 град,чем не повод задуматься,и взять за прообраз например,а когда уже будет понятно как распостраняется тепло,тогда уже и с заслонками можно поиграться,для написания управления регулировкой вентилятора можно использовать следующий алгоритм-так было на хонде,на холодном двигателе (соответственно нужен датчик охл.жидкости)вентилятор работает на мин.,с прогревом обороты растут но не более 3/4 от мах.,при достижении заданной температуры падают ,но не меньше мин.как-то так
На потолке в авто поставить датчик температуры/влажности, на печку присобащить сервопривод.
Хочу чтоб можно было задавать необходимую температуру с помощью вращения потенциометра, а сервопривод будет управлять заслонкой печки добиваясь тем самым необходимой температуры в салоне.
Все параметры заданной и фактической температуры должны отображатся на цветном oled дисплее.
Подскажите с чего начать , т.к опыта нету.
- считывать данные с потенциометра
- считывать показания с датчиков температуры и влажности
- управлять сервой
- выводить данные на LCD_20_4 ( он проще цветного oled дисплея )
- изучить ПИД-регулятор ( ПропорциональноИнтегральноДифференциальный регулятор ) ( это пока рано )
машинка какая ?
Kompaniets86, знаете кого-либо из выпуска КВИРТУ-87 ?
Не не знаю.
Вобщем пока жду ве барахло из поднебесной, все уже заказал.
А сервопривод и не нужно чтоб на 360, град, я его подключу к тросику, а там всего да 100 град.
чем больше рычаг сервы, тем меньше угол
Скажите, чем закончился проект? Удалось ли его воплотить в жизнь?
У меня в Матизе стоит управление климатом, собранное на микрочиповском контроллере. Сейчас собираюсь переделать на ардуино уно с сенсорным дисплеем 2,8 дюйма. Проблем при переделке было много. Вот немногие. Сервомашинки цифровые с 10кг момента на валу не справляются с заслонками, когда напор воздуха на них давит. Сейчас заказал с моментом в 20 кг (3 сервомашинки 40$). Сервомашинка лежащая на столе имеющая небольшой джиттер практически бесшумна, при фиксации ее жестко к кузову - становится как музыкальная шкатулка - крепить надо будет через демпфер резиновый. В первой моей конструкции небыло поддержания температуры, просто выбираем любой режим вручную, и все работает. Целью было уйти от крутилок, которые занимали много места, а перенести в другое место (ниже или выше) - тросики не давали. Все это было сделано, чтобы поставить 2ДИН магнитолу. Из моего мнения - обороты вентилятора выбирать самому, положение обдува (ноги, стекло, центр) выбирать самому. Температуру в салоне регулировать по двум датчикам температуры управлением заслонкой. Также у меня реализованно плавный старт мотора печки и плавная смена оборотов.
скажите, разбирать торпеду для смены заслонок на матизе - сильно пришлось?
Нет, только передний фартук, в котором климат стоит. и бардачек 2 шурупа. Там ко всем узлам печки можно подлезть без проблем. Я просто делал все за одно, и снимал полностью всю панель приборов, всю торпеду, и печку. Делал обесшумку, и всю машину зафлокировал (она у меня теперь бархатная внутри вся), заодно и климат перебрал...
из того что я видел в конструкции климат контроля на японке могу рекомендовать следующее:
- датчиков нужно ставить несколько, чтобы контролировать температуру в нескольких точках салона
- просто поставить датчик мало, нужно обеспечить около него циркуляцию воздуха, иначе комфорта не получить - замер датчиком около потолка/панели/пола будет сильно отличаться от температуры воздуха в середине салона. Можно или маленький вентилятор поставить или еще что то придумать. В японке датчик на консоли был хитро установлен перед тонкой трубочкой которая была дальше где то подсоеденена к воздуховоду так, что вентилятор печки в ней обеспечивал разряжение и воздух в эту трубочку засасывался в микроскопических объемах, но достаточно, чтобы постоянно обдувать датчик
- управлять заслонкой мало, как минимум еще нужно управлять оборотами вентилятора, а еще лучше и возможность менять направление тока воздуха. С тем, чтобы создать не просто какую то среднюю температуру в салоне, а обеспечить комфорт и в ногах, и на уровне груди и на уровне лица.
Я с Вами полностью согласен, но у меня не лексус 2016 года, а малолитражка с низкопроизводительным мотором вентилятора, и в пасмурный день у меня чтобы не потели стекла на выбор 2 варианта. Обдув на стекло, обдув на стекло и ноги. И ни в одном из вариантов нету, чтобы убавить обороты вентилятора, только на максимум. При этом стекла задних пассажиров и стекло заднее будет запотевшее. Ни о каком температурном комфорте у меня даже мыслей нет. Мне кажется, что переделывать печку начинают те, кого не устраивает штатная, а это машины среднего класса, где есть и сквозняки, и либо передние пассажиры сгорают от жары, а задние пассажиры едут комфортно, либо передние едут комфортно, а задние мерзнут. Чтобы исправить положение - требуется не только много датчиков по всей машине, но и много воздуховодов, во все точки авто с независимой регулировкой температуры воздуха в каждом. Возможно я и ошибаюсь, но это мое личное мнение. Проблема многих машин не в управлении печкой, а в ее возможностях физически прогревать салон равномерно и комфортно для всех одинаково.
Так то оно да, но ведь можно дополнительные печки поставить, воздуховоды провести.
На каждую печку и воздуховод надо отдельное управление температурой потока и скоростью потока воздуха. Цена девайса растет, сервомашинки только стоят недешего, а надо 2 на воздуховод (объем и температура). Думаю ардуино стоит 8 длолларов, экран 5 долларов, сервомашинки в стандартную систему поставить 13х3 = 39 долларов. Датчики температуры 2 доллара за штуку. Стабилизатор питания 5 вольт (BEC) около 7 долларов. Шимка на мосфете пару долларов для управления мотором печки, и мосфет для обогрева заднего стекла. Вот и считайте бюджет самоделки. Каждый воздуховод будет удорожать стоимость минимум на 40 долларов. Может это кому и надо, я так вкладываться не хочу :)
Вот мой код под Pic18f452, схема в голове, печатка была в спринтлайоуте, но найти не могу. Хотя по программе итак понятно на какой ноге кнопка, на какой светодиод, на какой сервомашинка, на какой ноге ШИМ вентилятора, и ШИМ яркости подсветки климата.
#include <htc.h> // PIC 18F452 fuse configuration: // Config word 1 (Oscillator configuration) // 4Mhz crystal __CONFIG(1, OSCSDIS & HS); // Config word 2 __CONFIG(2, BORDIS & PWRTDIS & WDTDIS); // Config word 3 __CONFIG(3, CCP2RC1); // Config word 4 __CONFIG(4, DEBUGDIS & LVPDIS & STVREN); // Config word 5, 6 and 7 (protection configuration) __CONFIG(5, UNPROTECT); __CONFIG(6, WRTEN); __CONFIG(7, TRU); // Bank 0 __EEPROM_DATA( 0x00,0x0f,0x19,0x23,0x2E,0x00,0x04,0x00 ); // speedmotor[5] = 0 , 15 , 25 , 35 , 46 по адресу 6,7 хранится последняя настройка отопителя __EEPROM_DATA( 0x00,0x00,0x03,0x84,0x04,0xC9,0x06,0x0E ); // PPM1[6] = 0, 900, 1225, 1550, 1875, 2200 __EEPROM_DATA( 0x07,0x53,0x08,0x98,0x00,0x00,0x00,0x00 ); // 2х байтовые константы, сначала старший, потом младший байты __EEPROM_DATA( 0x00,0x00,0x03,0x84,0x08,0x98,0x00,0x00 ); // PPM2[3] = 0, 900, 2200 // Bank 1 __EEPROM_DATA( 0x0A,0x2E,0x03,0x84,0x08,0x98,0x00,0x00 ); // PWMMin, PWMMax, PPMMin - 2 байта, PPMMax - 2 байта __EEPROM_DATA( 0x0A,0x05,0x00,0x00,0x00,0x00,0x00,0x00 ); // DayLight, NightLight __EEPROM_DATA( 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ); __EEPROM_DATA( 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ); #define KeyCount 1 #define KeyLong 100 #define KeyLong2 250 volatile unsigned char PinPress[8]; volatile unsigned char KeyLongPress[8]; volatile unsigned char KeyLongPress2[8]; volatile unsigned char Status1; volatile unsigned char Status2; volatile unsigned char Status3; volatile unsigned int ObogrevTime; volatile unsigned char Vvod; volatile unsigned char Obogrev; volatile unsigned char PWMMotorSel; volatile unsigned int ADCResult; volatile unsigned char KeyPressed[8]; volatile unsigned int Servos[4]; volatile unsigned int PWM; volatile unsigned char Setup; volatile unsigned char Start; volatile unsigned char Ticks; volatile unsigned char speedmotor[5]; volatile unsigned int PPM1[6]; volatile unsigned int PPM2[3]; volatile unsigned char NeedWriteEeprom; volatile unsigned char Menu; volatile signed char Correct; volatile unsigned char PWMMax; volatile unsigned char PWMMin; volatile unsigned int PPMMax; volatile unsigned int PPMMin; volatile unsigned char DayLight; volatile unsigned char NightLight; volatile unsigned char ServoWorks; volatile unsigned int PauseWrite; volatile unsigned int Temp; void InitADC(void); void InitServo(void); void InitButton(void); void InitLED(void); void KeyScan(void); unsigned int GetADCValue(void); void InitPWM(void); void SetPWMDutyCycle(unsigned char, unsigned int); void WorkKey(void); void ADCMotor(void); void RefreshPWMMotor(void); void InitParametrs(void); void SetupKey(void); void SaveParametrs(void); void InitADC(void) { ADCS1 = 0; // 8 tosc ADCS0 = 1; // 8 tosc ADON = 1; // включить АЦП ADFM = 1; // правое выравнивание ADCS2 = 0; // 8 tosc PCFG3 = 0; // AN0, AN1, AN3 PCFG2 = 1; PCFG1 = 0; PCFG0 = 0; LVDEN = 0; SSPEN = 0; ADIE = 0; TRISA = 0b00011111; //RA2 вход габаритов, RA5 выход обогрева LATA5 = 0; TRISA5 = 0; } void InitServo(void) { LATE0 = 0; LATE1 = 0; LATE2 = 0; TRISE0 = 0; TRISE1 = 0; TRISE2 = 0; RD16 = 0; T1CKPS0 =0; T1CKPS1 =0; TMR1CS = 0; T1OSCEN = 0; TMR1H = 0xB1; TMR1L = 0xE1; TMR1IF=0; TMR1IE=1; PEIE=1; GIE=1; TMR1ON = 1; PSPMODE = 0; } void InitButton(void) { RBIE = 0; TRISB = 255; RBPU = 0; } void SaveParametrs(void) //только после настройки используется { EEPROM_WRITE(0, 0); EEPROM_WRITE(1, speedmotor[1]); EEPROM_WRITE(2, speedmotor[2]); EEPROM_WRITE(3, speedmotor[3]); EEPROM_WRITE(4, PWMMax); EEPROM_WRITE(8, (PPM1[0] >> 8)); EEPROM_WRITE(9, PPM1[0]); EEPROM_WRITE(10, (PPM1[1] >> 8)); EEPROM_WRITE(11, PPM1[1]); EEPROM_WRITE(12, (PPM1[2] >> 8)); EEPROM_WRITE(13, PPM1[2]); EEPROM_WRITE(14, (PPM1[3] >> 8)); EEPROM_WRITE(15, PPM1[3]); EEPROM_WRITE(16, (PPM1[4] >> 8)); EEPROM_WRITE(17, PPM1[4]); EEPROM_WRITE(18, (PPM1[5] >> 8)); EEPROM_WRITE(19, PPM1[5]); EEPROM_WRITE(24, (PPM2[0] >> 8)); EEPROM_WRITE(25, PPM2[0]); EEPROM_WRITE(26, (PPM2[1] >> 8)); EEPROM_WRITE(27, PPM2[1]); EEPROM_WRITE(28, (PPM2[2] >> 8)); EEPROM_WRITE(29, PPM2[2]); EEPROM_WRITE(32, PWMMin); EEPROM_WRITE(33, PWMMax); EEPROM_WRITE(40, DayLight); EEPROM_WRITE(41, NightLight); EEPROM_WRITE(34, (PPMMin >> 8)); EEPROM_WRITE(35, PPMMin); EEPROM_WRITE(36, (PPMMax >> 8)); EEPROM_WRITE(37, PPMMax); } void InitParametrs(void) { NeedWriteEeprom = 0; Ticks = 0; Start = 1; Setup = 0; Menu = 1; speedmotor[0] = eeprom_read( 0 ) ; speedmotor[1] = eeprom_read( 1 ) ; speedmotor[2] = eeprom_read( 2 ) ; speedmotor[3] = eeprom_read( 3 ) ; speedmotor[4] = eeprom_read( 4 ) ; PPM1[0] = (((eeprom_read( 8 ))<<8) + (eeprom_read( 9 ))) ; PPM1[1] = (((eeprom_read( 10 ))<<8) + (eeprom_read( 11 ))) ; PPM1[2] = (((eeprom_read( 12 ))<<8) + (eeprom_read( 13 ))) ; PPM1[3] = (((eeprom_read( 14 ))<<8) + (eeprom_read( 15 ))) ; PPM1[4] = (((eeprom_read( 16 ))<<8) + (eeprom_read( 17 ))) ; PPM1[5] = (((eeprom_read( 18 ))<<8) + (eeprom_read( 19 ))) ; PPM2[0] = (((eeprom_read( 24 ))<<8) + (eeprom_read( 25 ))) ; PPM2[1] = (((eeprom_read( 26 ))<<8) + (eeprom_read( 27 ))) ; PPM2[2] = (((eeprom_read( 28 ))<<8) + (eeprom_read( 29 ))) ; Status1 = eeprom_read( 6 ) ; Status2 = eeprom_read( 7 ) ; PWMMin = eeprom_read( 32 ) ; PWMMax = eeprom_read( 33 ) ; PPMMin = (((eeprom_read( 34 ))<<8) + (eeprom_read( 35 ))) ; PPMMax = (((eeprom_read( 36 ))<<8) + (eeprom_read( 37 ))) ; DayLight = eeprom_read( 40 ) ; NightLight = eeprom_read( 41 ) ; if (Status1 == 1) { Servos[1] = PPM1[1]; LATD5 = 1; LATD6 = 0; LATD7 = 0; LATD4 = 0; LATD2 = 0; } if (Status1 == 2) { Servos[1] = PPM1[2]; LATD6 = 1; LATD5 = 0; LATD7 = 0; LATD4 = 0; LATD2 = 0; } if (Status1 == 3) { Servos[1] = PPM1[3]; LATD7 = 1; LATD5 = 0; LATD6 = 0; LATD4 = 0; LATD2 = 0; } if (Status1 == 4) { Servos[1] = PPM1[4]; LATD4 = 1; LATD5 = 0; LATD6 = 0; LATD7 = 0; LATD2 = 0; } if (Status1 == 5) { Servos[1] = PPM1[5]; LATD2 = 1; LATD5 = 0; LATD6 = 0; LATD7 = 0; LATD4 = 0; } if (Status2 == 1) { Servos[2] = PPM2[2]; LATD1 = 1; Vvod = 1; } else { Servos[2] = PPM2[1]; LATD1 = 0; Vvod = 0; } Obogrev = 0; LATD0 = 0; NOP(); NOP(); LATA5 = 0; NOP(); NOP(); ObogrevTime = 0; Status3 = 0; } void InitLed(void) { TRISD = 0; LATD = 0; } void KeyScan(void) { if (RB0 == 0) { PinPress[1] = PinPress[1] + 1; if (PinPress[1] > KeyLong) // если кнопка удерживается дольше 2 секунд (для функции настройки) { KeyLongPress[1] = 1; } if (PinPress[1] > KeyLong2) // если кнопка удерживается дольше 16 секунд (для входа в настройки и корректировки серво) { KeyLongPress2[1] = 1; PinPress[1] = KeyLong2; // не даем выйти за предел 255 } } else // если отпущена или не нажата { if ((PinPress[1] > KeyCount) && (PinPress[1] <= KeyLong2)) // до отпускания кнопка удерживалась более 0.1 сек но меньше 2х секунд { KeyPressed[1] = 1; } else { KeyPressed[1] = 0; KeyLongPress[1] = 0; KeyLongPress2[1] = 0; } PinPress[1]=0; // после отпускания обнуляем счетчик } if (RB1 == 0) { PinPress[2] = PinPress[2] + 1; if (PinPress[2] > KeyLong) // если кнопка удерживается дольше 2 секунд (для функции настройки) { KeyLongPress[2] = 1; } if (PinPress[2] > KeyLong2) // если кнопка удерживается дольше 16 секунд (для входа в настройки и корректировки серво) { KeyLongPress2[2] = 1; PinPress[2] = KeyLong2; // не даем выйти за предел 255 } } else // если отпущена или не нажата { if ((PinPress[2] > KeyCount) && (PinPress[2] <= KeyLong2)) // до отпускания кнопка удерживалась более 0.1 сек но меньше 2х секунд { KeyPressed[2] = 1; } else { KeyPressed[2] = 0; KeyLongPress[2] = 0; KeyLongPress2[2] = 0; } PinPress[2]=0; // после отпускания обнуляем счетчик } if (RB2 == 0) { PinPress[3] = PinPress[3] + 1; if (PinPress[3] > KeyLong) // если кнопка удерживается дольше 2 секунд (для функции настройки) { KeyLongPress[3] = 1; } if (PinPress[3] > KeyLong2) // если кнопка удерживается дольше 16 секунд (для входа в настройки и корректировки серво) { KeyLongPress2[3] = 1; PinPress[3] = KeyLong2; // не даем выйти за предел 255 } } else // если отпущена или не нажата { if ((PinPress[3] > KeyCount) && (PinPress[3] <= KeyLong2)) // до отпускания кнопка удерживалась более 0.1 сек но меньше 2х секунд { KeyPressed[3] = 1; } else { KeyPressed[3] = 0; KeyLongPress[3] = 0; KeyLongPress2[3] = 0; } PinPress[3]=0; // после отпускания обнуляем счетчик } if (RB3 == 0) { PinPress[4] = PinPress[4] + 1; if (PinPress[4] > KeyLong) // если кнопка удерживается дольше 2 секунд (для функции настройки) { KeyLongPress[4] = 1; } if (PinPress[4] > KeyLong2) // если кнопка удерживается дольше 16 секунд (для входа в настройки и корректировки серво) { KeyLongPress2[4] = 1; PinPress[4] = KeyLong2; // не даем выйти за предел 255 } } else // если отпущена или не нажата { if ((PinPress[4] > KeyCount) && (PinPress[4] <= KeyLong2)) // до отпускания кнопка удерживалась более 0.1 сек но меньше 2х секунд { KeyPressed[4] = 1; } else { KeyPressed[4] = 0; KeyLongPress[4] = 0; KeyLongPress2[4] = 0; } PinPress[4]=0; // после отпускания обнуляем счетчик } if (RB4 == 0) { PinPress[5] = PinPress[5] + 1; if (PinPress[5] > KeyLong) // если кнопка удерживается дольше 2 секунд (для функции настройки) { KeyLongPress[5] = 1; } if (PinPress[5] > KeyLong2) // если кнопка удерживается дольше 16 секунд (для входа в настройки и корректировки серво) { KeyLongPress2[5] = 1; PinPress[5] = KeyLong2; // не даем выйти за предел 255 } } else // если отпущена или не нажата { if ((PinPress[5] > KeyCount) && (PinPress[5] <= KeyLong2)) // до отпускания кнопка удерживалась более 0.1 сек но меньше 2х секунд { KeyPressed[5] = 1; } else { KeyPressed[5] = 0; KeyLongPress[5] = 0; KeyLongPress2[5] = 0; } PinPress[5]=0; // после отпускания обнуляем счетчик } if (RB5 == 0) { PinPress[6] = PinPress[6] + 1; if (PinPress[6] > KeyLong) // если кнопка удерживается дольше 2 секунд (для функции настройки) { KeyLongPress[6] = 1; } if (PinPress[6] > KeyLong2) // если кнопка удерживается дольше 16 секунд (для входа в настройки и корректировки серво) { KeyLongPress2[6] = 1; PinPress[6] = KeyLong2; // не даем выйти за предел 255 } } else // если отпущена или не нажата { if ((PinPress[6] > KeyCount) && (PinPress[6] <= KeyLong2)) // до отпускания кнопка удерживалась более 0.1 сек но меньше 2х секунд { KeyPressed[6] = 1; } else { KeyPressed[6] = 0; KeyLongPress[6] = 0; KeyLongPress2[6] = 0; } PinPress[6]=0; // после отпускания обнуляем счетчик } if (RB6 == 0) { PinPress[7] = PinPress[7] + 1; if (PinPress[7] > KeyLong) // если кнопка удерживается дольше 2 секунд (для функции настройки) { KeyLongPress[7] = 1; } if (PinPress[7] > KeyLong2) // если кнопка удерживается дольше 16 секунд (для входа в настройки и корректировки серво) { KeyLongPress2[7] = 1; PinPress[7] = KeyLong2; // не даем выйти за предел 255 } } else // если отпущена или не нажата { if ((PinPress[7] > KeyCount) && (PinPress[7] <= KeyLong2)) // до отпускания кнопка удерживалась более 0.1 сек но меньше 2х секунд { KeyPressed[7] = 1; } else { KeyPressed[7] = 0; KeyLongPress[7] = 0; KeyLongPress2[7] = 0; } PinPress[7]=0; // после отпускания обнуляем счетчик } } unsigned int GetADCValue(void) { while(GODONE); // Wait for conversion completion return ((ADRESH<<8)+ADRESL); // Return 10 bit ADC value } void InitPWM(void) { TRISC1 = 0; // Make CCP2 pin as output TRISC2 = 0; // Make CCP1 pin as output CCP1CON = 0x0C; // Configure CCP1 module in PWM mode CCP2CON = 0x0C; // Configure CCP2 module in PWM mode PR2 = PWMMax; // Configure the Timer2 period (46) 4000000\4\22000+1 T2CON = 0x00; // Set no Prescaler, hence PWM frequency is set to 22KHz. SetPWMDutyCycle(1, 0); // Intialize the CCP1 PWM to 0 duty cycle SetPWMDutyCycle(2, 0); // Intialize the CCP2 PWM to 0 duty cycle T2CON |= 0x04; // Enable the Timer2, hence enable the PWM. PWMMotorSel = 0; } void SetPWMDutyCycle(unsigned char CCP, unsigned int DutyCycle) // Give a value in between 0 and 255 for DutyCycle { switch(CCP) { case 1: CCPR1L = DutyCycle; // Put MSB 8 bits in CCPR1L break; case 2: CCPR2L = DutyCycle; // Put MSB 8 bits in CCPR2L break; } } void WorkKey(void) { if (KeyPressed[1]) { Servos[1] = PPM1[1]; LATD5 = 1; LATD6 = 0; LATD7 = 0; LATD4 = 0; LATD2 = 0; Status1 = 1; NeedWriteEeprom = 1; //Записать новое значение в EEPROM PauseWrite = 500; //Но не сразу, а выждав 10 секунд (на случай если пользователь дальше настраивает климат)) } if (KeyPressed[2]) { Servos[1] = PPM1[2]; LATD6 = 1; LATD5 = 0; LATD7 = 0; LATD4 = 0; LATD2 = 0; Status1 = 2; NeedWriteEeprom = 1; //Записать новое значение в EEPROM PauseWrite = 500; //Но не сразу, а выждав 10 секунд (на случай если пользователь дальше настраивает климат)) } if (KeyPressed[3]) { Servos[1] = PPM1[3]; LATD7 = 1; LATD5 = 0; LATD6 = 0; LATD4 = 0; LATD2 = 0; Status1 = 3; NeedWriteEeprom = 1; //Записать новое значение в EEPROM PauseWrite = 500; //Но не сразу, а выждав 10 секунд (на случай если пользователь дальше настраивает климат)) } if (KeyPressed[4]) { Servos[1] = PPM1[4]; LATD4 = 1; LATD5 = 0; LATD6 = 0; LATD7 = 0; LATD2 = 0; Status1 = 4; NeedWriteEeprom = 1; //Записать новое значение в EEPROM PauseWrite = 500; //Но не сразу, а выждав 10 секунд (на случай если пользователь дальше настраивает климат)) } if (KeyPressed[5]) { Servos[1] = PPM1[5]; LATD2 = 1; LATD5 = 0; LATD6 = 0; LATD7 = 0; LATD4 = 0; Status1 = 5; NeedWriteEeprom = 1; //Записать новое значение в EEPROM PauseWrite = 500; //Но не сразу, а выждав 10 секунд (на случай если пользователь дальше настраивает климат)) } if (KeyPressed[6]) { NeedWriteEeprom = 1; //Записать новое значение в EEPROM PauseWrite = 500; //Но не сразу, а выждав 10 секунд (на случай если пользователь дальше настраивает климат)) Vvod = 1 - Vvod; if (Vvod) { Servos[2] = PPM2[2]; LATD1 = 1; Status2 = 1; } else { Servos[2] = PPM2[1]; LATD1 = 0; Status2 = 0; } } if (KeyPressed[7]) { Obogrev = 1 - Obogrev; if (Obogrev) { LATD0 = 1; NOP(); NOP(); LATA5 = 1; NOP(); NOP(); ObogrevTime = 15000; //Обогрев отключится через 5 минут 50Гц х 60сек х 5 мин } else { LATD0 = 0; NOP(); NOP(); LATA5 = 0; NOP(); NOP(); ObogrevTime = 0; } } if (ObogrevTime>0) { ObogrevTime = ObogrevTime - 1; } else if (Obogrev == 1) { Obogrev = 0; LATD0 = 0; NOP(); NOP(); LATA5 = 0; NOP(); NOP(); ObogrevTime = 0; } if (PauseWrite>0) { PauseWrite = PauseWrite - 1; } else if (NeedWriteEeprom == 1) { EEPROM_WRITE(6, Status1); EEPROM_WRITE(7, Status2); NeedWriteEeprom = 0; } if (KeyLongPress2[6] == 1) { Setup = 1; LATD5 = 0; LATD6 = 0; LATD7 = 0; LATD4 = 0; LATD2 = 0; LATD1 = 0; LATD0 = 0; } } void SetupKey(void) { if (KeyPressed[3] == 1) { Menu = Menu + 1; if (Menu > 16) { Menu = 1; } } Correct = 0; if ((KeyPressed[2] == 1)||(KeyLongPress[2] == 1)) { Correct = 1; } if ((KeyPressed[1] == 1)||(KeyLongPress[1] == 1)) { Correct = -1; } if ((KeyPressed[5] == 1)||(KeyLongPress[5] == 1)) { Correct = 10; } if ((KeyPressed[4] == 1)||(KeyLongPress[4] == 1)) { Correct = -10; } if (Menu == 1) // настройки серво 1 обдув груди { LATD5 = 1; LATD6 = 0; LATD7 = 0; LATD4 = 0; LATD2 = 0; LATD1 = 0; LATD0 = 0; PPM1[1] = PPM1[1] + Correct; Servos[1] = PPM1[1]; } if (Menu == 2) // настройки серво 1 обдув груди_ног { LATD5 = 0; LATD6 = 1; LATD7 = 0; LATD4 = 0; LATD2 = 0; LATD1 = 0; LATD0 = 0; PPM1[2] = PPM1[2] + Correct; Servos[1] = PPM1[2]; } if (Menu == 3) // настройки серво 1 обдув ног { LATD5 = 0; LATD6 = 0; LATD7 = 1; LATD4 = 0; LATD2 = 0; LATD1 = 0; LATD0 = 0; PPM1[3] = PPM1[3] + Correct; Servos[1] = PPM1[3]; } if (Menu == 4) // настройки серво 1 обдув ног_стекла { LATD5 = 0; LATD6 = 0; LATD7 = 0; LATD4 = 1; LATD2 = 0; LATD1 = 0; LATD0 = 0; PPM1[4] = PPM1[4] + Correct; Servos[1] = PPM1[4]; } if (Menu == 5) // настройки серво 1 обдув стекла { LATD5 = 0; LATD6 = 0; LATD7 = 0; LATD4 = 0; LATD2 = 1; LATD1 = 0; LATD0 = 0; PPM1[5] = PPM1[5] + Correct; Servos[1] = PPM1[5]; } if (Menu == 6) // настройки серво 2 забор воздуха улица { LATD5 = 1; LATD6 = 0; LATD7 = 0; LATD4 = 0; LATD2 = 0; LATD1 = 1; LATD0 = 0; PPM2[1] = PPM2[1] + Correct; Servos[2] = PPM2[1]; } if (Menu == 7) // настройки серво 2 забор воздуха салон { LATD5 = 0; LATD6 = 1; LATD7 = 0; LATD4 = 0; LATD2 = 0; LATD1 = 1; LATD0 = 0; PPM2[2] = PPM2[2] + Correct; Servos[2] = PPM2[2]; } if (Menu == 12) // корректировка 0 положения мотора и низ отключения мотора { LATD5 = 1; LATD6 = 0; LATD7 = 0; LATD4 = 0; LATD2 = 0; LATD1 = 0; LATD0 = 1; PWMMin = PWMMin + Correct; PWMMotorSel = PWMMin; } if (Menu == 11) // корректировка 1 положения мотора { LATD5 = 0; LATD6 = 1; LATD7 = 0; LATD4 = 0; LATD2 = 0; LATD1 = 0; LATD0 = 1; speedmotor[1] = speedmotor[1] + Correct; PWMMotorSel = speedmotor[1]; } if (Menu == 10) // корректировка 2 положения мотора { LATD5 = 0; LATD6 = 0; LATD7 = 1; LATD4 = 0; LATD2 = 0; LATD1 = 0; LATD0 = 1; speedmotor[2] = speedmotor[2] + Correct; PWMMotorSel = speedmotor[2]; } if (Menu == 9) // корректировка 3 положения мотора { LATD5 = 0; LATD6 = 0; LATD7 = 0; LATD4 = 1; LATD2 = 0; LATD1 = 0; LATD0 = 1; speedmotor[3] = speedmotor[3] + Correct; PWMMotorSel = speedmotor[3]; } if (Menu == 8) // корректировка 4 положения мотора и частоты ШИМ { LATD5 = 0; LATD6 = 0; LATD7 = 0; LATD4 = 0; LATD2 = 1; LATD1 = 0; LATD0 = 1; PWMMax = PWMMax + Correct; if (Correct) { PR2 = PWMMax; speedmotor[4] = PWMMax; PWMMotorSel = (PWMMax >>1); // Выставляем частоту ШИМ по средним оборотам на слух, чтоб мотор не пел } } if (Menu == 13) // выставляем минимум для заслонки температуры воздуха, ручка должна быть в минимуме { LATD5 = 1; LATD6 = 1; LATD7 = 1; LATD4 = 0; LATD2 = 0; LATD1 = 0; LATD0 = 0; PPMMin = PPMMin + Correct; PWMMotorSel = 0; } if (Menu == 14) // выставляем максимум для заслонки температуры воздуха, ручка должна быть в максимуме { LATD5 = 0; LATD6 = 0; LATD7 = 1; LATD4 = 1; LATD2 = 1; LATD1 = 0; LATD0 = 0; PPMMax = PPMMax + Correct; } if (Menu == 15) // яркость подсветки с выключенными габаритами (день) Регулируется только с выключенными габаритами { LATD5 = 1; LATD6 = 1; LATD7 = 0; LATD4 = 0; LATD2 = 0; LATD1 = 1; LATD0 = 1; DayLight = DayLight + Correct; } if (Menu == 16) // яркость подсветки с включенными габаритами (ночь) Регулируется только с включенными габаритами { LATD5 = 0; LATD6 = 0; LATD7 = 0; LATD4 = 1; LATD2 = 1; LATD1 = 1; LATD0 = 1; NightLight = NightLight + Correct; } if (KeyLongPress2[7] == 1) { SaveParametrs(); Setup = 0; InitParametrs(); } } void ADCMotor(void) { if (Setup == 0) { ADCResult = (1023 - GetADCValue()); if (ADCResult < 128) //выключено (в идеале 0) { PWMMotorSel = speedmotor[0]; } if ((ADCResult >= 128)&&(ADCResult < 384)) //первое положение (256) { PWMMotorSel = speedmotor[1]; } if ((ADCResult >= 384)&&(ADCResult < 640)) //середина 512 { PWMMotorSel = speedmotor[2]; } if ((ADCResult >= 640)&&(ADCResult < 896)) //третье положение (768) { PWMMotorSel = speedmotor[3]; } if (ADCResult >896) //включено постоянно (в идеале 1024) { PWMMotorSel = speedmotor[4]; } } } void ADCTemper(void) { ADCResult = (1023 - GetADCValue()); Servos[3] = PPMMin + ((((PPMMax - PPMMin)>>5)*ADCResult)>>5); // растягиваем шкалу на весь РРМ сигнал. } void RefreshPWMMotor(void) { if(PWM>PWMMotorSel) { PWM = PWM - 1; } if(PWM<PWMMotorSel) { PWM = PWM + 1; } if (PWM < PWMMin) { SetPWMDutyCycle(2, 0); } else { SetPWMDutyCycle(2, PWM); } if (RA2 == 0) { SetPWMDutyCycle(1, DayLight); } else { SetPWMDutyCycle(1, NightLight); } } void main(void) { InitServo(); InitButton(); InitLed(); InitParametrs(); InitPWM(); InitADC(); SetPWMDutyCycle(1,0); //0% duty cycle 0-46 SetPWMDutyCycle(2,0); //0% duty cycle 0-46 while(1) { while(!Start); // ожидаем старта от прерывания Start = 0; Ticks = Ticks + 1; if (Ticks > 10) { RefreshPWMMotor(); Ticks = 0; // 5 Hz } if (Ticks == 1) { CHS0 = 0; CHS1 = 0; CHS2 = 0; } if (Ticks == 2) { GODONE = 1; } if (Ticks == 3) { ADCMotor(); } if (Ticks == 5) { CHS0 = 1; CHS1 = 0; CHS2 = 0; } if (Ticks == 6) { GODONE = 1; } if (Ticks == 7) { ADCTemper(); } KeyScan(); if (Setup == 1) { SetupKey(); } else { WorkKey(); } } } void interrupt isr(void) { if(TMR1IF) { LATE0 = 0; LATE1 = 0; LATE2 = 0; TMR1ON = 0; TMR1IF =0; ServoWorks = ServoWorks + 1; if (ServoWorks == 1) { Temp = (65537 - Servos[1]); TMR1H = (Temp>>8); TMR1L = (Temp); LATE0 = 1; TMR1ON = 1; } else if (ServoWorks == 2) { Temp = (65537 - Servos[2]); TMR1H = (Temp>>8); TMR1L = (Temp); LATE1 = 1; TMR1ON = 1; } else if (ServoWorks == 3) { Temp = (65537 - Servos[3]); TMR1H = (Temp>>8); TMR1L = (Temp); LATE2 = 1; TMR1ON = 1; } else if (ServoWorks == 4) { TMR1H = 0xC9; TMR1L = 0x51; //пауза в 14 мс между работ серв (минимум 3 сервы отработают за 0,7*3 = 2,1мс, максимум 6,9 мс) итого пауза в диапазоне 16 - 21 мс, что допустимо для серв Start = 1; // Разрешаем остальной части программы работать, когда все сервы отработали ServoWorks = 0; // при следующем входе в прерывание приращение единицы выберет первую сервомашинку TMR1ON = 1; } } }Я с Вами полностью согласен, но у меня не лексус 2016 года, а малолитражка с низкопроизводительным мотором вентилятора, и в пасмурный день у меня чтобы не потели стекла на выбор 2 варианта. Обдув на стекло, обдув на стекло и ноги. И ни в одном из вариантов нету, чтобы убавить обороты вентилятора, только на максимум. При этом стекла задних пассажиров и стекло заднее будет запотевшее. Ни о каком температурном комфорте у меня даже мыслей нет. Мне кажется, что переделывать печку начинают те, кого не устраивает штатная, а это машины среднего класса, где есть и сквозняки, и либо передние пассажиры сгорают от жары, а задние пассажиры едут комфортно, либо передние едут комфортно, а задние мерзнут. Чтобы исправить положение - требуется не только много датчиков по всей машине, но и много воздуховодов, во все точки авто с независимой регулировкой температуры воздуха в каждом. Возможно я и ошибаюсь, но это мое личное мнение. Проблема многих машин не в управлении печкой, а в ее возможностях физически прогревать салон равномерно и комфортно для всех одинаково.
то о чем я писал я видел на японке 1994 года выпуска ) конечно возможности системы отопления и обдува ограничены (даже в премиальных авто, просто там границы возможностей шире), но это не повод ставить один датчик и тем более ставить датчик который не обдувается и в итоге замеряет что то еще, но не температуру воздуха в салоне. Я об этом, а не о том, что надо делать идеальную систему
Так и поставьте датчик температуры посередине салона, сделайте ему небольшое разряжение (воздуховод от датчика до вентилятора, со стороны забора воздуха, там всегда разрежение). Градиент температуры в салоне авто не более 2 градусов. Прогрев салона машины - очень инерционное мероприятие, а если еще добавить кондиционер, то например у меня уже знаний не хватит рассчитать параметры и учесть все особенности. Если это кому то под силу, пусть выскажут свое мнение. Но на мой взгляд - это не так просто, как кажется.
Иногда приходится включать кондиционер, на полную мощность, и печку на самую горячую (чтобы осушить влажный воздух).
есть интерес переделать блок управления кондиционером в блок климата, можно без автоматического управления. https://yadi.sk/i/gw8woiyat38SN
Как правильно подключить кнопки к серво.
есть интерес переделать блок управления кондиционером в блок климата, можно без автоматического управления. https://yadi.sk/i/gw8woiyat38SN
Как правильно подключить кнопки к серво.
а не получится у Вас крутить ручки с помощью серво. Усилия не хватит. У меня сервы с тягой в 10 кг\см не справляются без дополнительного редуктора. Ведь момент удержания и момент сдвига - оказалось разными вещами.
.
мужики. я так думаю у вас тут немного не доработка. читал ваши комменты. тут ситуация с таким делом, нужно несколько датчиков температур. и каждый настрое на определенные температуры. то есть: 1) датчик температуры охлаждающей жидкости. Ардуино должна считывать данные с ЭБУ. это для тех авто у которых не электрическая печь. при температуре жидкости, например: в 50 градусов, включает печь на малых температурах на лобовое. 2) датчик температуры на лобовом, будет давать сигнал и заслонка приоткрывается четок, давая слабый обогрев стекла. при высоком обогреве стекло просто лопнет. когда стекло прогреется до нужной температуры, заслонка откроется больше и => идет обогрев салона. тут уже будет регулировать датчик температур и влажности в салоне. вот думаю такой алгоритм должен быть при пуске машины на прогреве. а дальше работа системы уже просто на поддержку климата в салоне.