Управление температурой приточного воздуха
- Войдите на сайт для отправки комментариев
Пнд, 17/08/2020 - 18:04
Привет всем очень требуется регулятор приточного воздуха в квартиру.
Суть такая, берем ардуино нано и подключаем датчик температуры, симисторный регулятор тенов, регулятор оборотов вентилятора, пид регулятор и защиты от перегрева и обрывов с звуковой сигнализацией и дисплеем.
Что есть :
мощность тенов 2 кВт на 220, куллеры 12 вольт, датчик резистивный с делителем .i2c дисплей, кнопки для управления режимами и температурой.
Я брал скетч от паяльной станции но без успехов ,не могу разобраться в коде.
В общем это схема принципиальная
Так, а что от нас нужно-то?
Помочь со скетчем) программирование сложно для меня.
или переделать этот
/* Soldering Station HotAir Only */ #include <EEPROM.h> #include <CyberLib.h> #include <Wire.h> #include <OLED_I2C.h> #include <Bounce2.h> //OLED дисплей OLED myOLED(SDA, SCL, 8); //Подключаем дисплей extern uint8_t HAsmallNumbers[]; extern uint8_t HAbigNumbers[]; extern uint8_t SmallFont[]; extern uint8_t logoHA[]; //переменные и обозначения /* mode selector */ #define modeHotAir 0 #define modeFanPWM 1 uint16_t HA_sleeptime = 10; //время до режима сна boolean need_HA_countdown = false; //отсчёт до выключения фена byte selectedMode = modeHotAir; //выбранный режим по умолчанию uint16_t HAcountdown = 1; //счётчик таймера отключения фена uint32_t prevDisplayMillis = 0; //время предыдущего обновления дисплея uint32_t prevWorkMillis = 0; //время предыдущей проверки работы uint32_t UPbuttonPressTime = 0; //время последнего нажатия кнопки плюс uint32_t DWNbuttonPressTime = 0; //время последнего нажатия кнопки минус uint32_t prevHAmillis = 0; //последнее время активности фена uint16_t Graph_count = 0; //счётчик замера температуры uint32_t HAONbuttonPressTime = 0; //время последнего нажатия кнопки включения фена boolean need_log = false; //включение вывода лога boolean UPbuttonState, DWNbuttonState, HAONbuttonState; //флаги нажатия кнопок #define pinBuzzer 13 //пин пищалки #define min_hotair_temp 50 //минимальная температура фена #define max_hotair_temp 450 //максимальная температура фена #define min_rpm 30 //минимальные обороты кулера #define max_rpm 100 //максимальные обороты кулера #define default_temp 250 //начальная температура фена #define default_rpm 50 //начальная скорость вращения кулера //установки для кнопок #define sw_HA 2 //геркон фена #define bt_HAON 10 //кнопка включения фена #define bt_Sel 9 //кнопка выбора режима #define bt_Up 8 //кнопка плюс #define bt_Dwn 7 //кнопка минус //защита от дребезга Bounce swHotAir = Bounce(); Bounce swSolder = Bounce(); Bounce SolderOnButton = Bounce(); Bounce HotAirOnButton = Bounce(); Bounce SelButton = Bounce(); Bounce UpButton = Bounce(); Bounce DwnButton = Bounce(); //установки для фена volatile uint16_t ots = 9990; //время цикла для StartTimer1 volatile boolean HotAirON = false; //флаг включения фена volatile boolean HotAirProtect = false; //флаг защиты фена uint16_t GetHotAirT = 0; //измеренная температура фена uint16_t SetHotAirT = 100; //установленная температура фена byte SetHotAirRPM = 100; //установленная скорость вращения кулера uint16_t last_HotAirT; //последняя запомненая температура фена byte last_RPM; //последняя запомненая скорость вращения кулера boolean HAneedBeep = true; //флаг сигнала стабильности температуры byte HAgood = 0; //счётчик стабилизации температуры фена boolean needCool = true; //необходимость охлаждения фена boolean HA_gerkon = false; //флаг геркона #define pinFanPwm 6 //пин управления скоростью вращения кулера ШИМ #define Kp 1.0 //0.5 пропорциональный коэффициент ПИ-регулятора #define Ki 0.005 //0.008 интегральный коэффициент ПИ-регулятора int integral = 0; //начальное значение интегральной поправки ПИ-регулятора volatile float HAPower = 0.0; //мощность, на основании которой рассчитывается время задержки открытия симистора boolean HA_PROT = false; //флаг защиты фена //чтение последних установок из памяти void MemRead() { SetHotAirT = EEPROM_int_read(4); //прочесть значение из адреса 4 (запомненное значение температуры фена, сразу 2 ячейки) if (SetHotAirT < min_hotair_temp || SetHotAirT > max_hotair_temp) { //если запомненное не в диапазоне максимума и минимума SetHotAirT = default_temp; //выставить значение по умолчанию } SetHotAirRPM = EEPROM_int_read(8); //прочесть значение из адреса 8 (запомненное значение оборотов кулера, сразу 2 ячейки) if (SetHotAirRPM < min_rpm || SetHotAirRPM > max_rpm) { //если запомненное не в диапазоне максимума и минимума SetHotAirRPM = default_rpm; //выставить значение по умолчанию } } //запись параметров фена в память void MemHotAir() { if (last_HotAirT != SetHotAirT) { EEPROM_int_write(4, SetHotAirT); last_HotAirT = SetHotAirT; } if (last_RPM != SetHotAirRPM) { EEPROM_int_write(8, SetHotAirRPM); last_RPM = SetHotAirRPM; } } //ПИ-регулятор фена void HA_PI() { int err = SetHotAirT - GetHotAirT; //вычисляем ошибку (разницу между установленной и реальной температурой) в данный момент времени float TempPower = ((Kp * err) + (Ki * integral)); //вычисляем значение с учётом выбранных коэффициентов и накопленной интегральной поправки ПИ-регулятора if (TempPower < 100.0 && TempPower > 0.0) integral += err; //если полученное значение в диапазоне от 0 до 100 - прибавляем к интегральной поправке значение ошибки HAPower = constrain(TempPower, 0.0, 100.0); //ограничиваем значение интервалом от 0 до 100 и присваиваем получившееся значение мощности для работы с симистором CalctImpulseControl(); //вычисляем задержку для симистора } //вычисление задержки для симистора void CalctImpulseControl() { ots = (uint16_t)(acos(HAPower / 50.0 - 1.0 ) * 9900.0 / pi); } //вывод звукового сигнала void Beep(uint16_t duration) { //название функции(длительность сигнала) D13_High; delay_ms(duration); D13_Low; /* for passive buzzer */ //tone(pinBuzzer, 1000, duration); } //функция оверсэмплинга uint16_t getOversampled(uint16_t ADC_value) { unsigned long int result = 0; for (byte z = 0; z < 64; z++) { //делаем 64 замера result += ADC_value; //складываем всё вместе } return result >> 6; //делаем побитовый сдвиг для полученного значения (64 это 2 в 6-ой степени, поэтому >>6) } void setup() { pinMode(3, INPUT_PULLUP); //пин отслеживания перехода через 0 D4_Out; //пин защиты фена (реле) D4_Low; //выставить логический 0 - реле разомкнуто D5_Out; //пин нагревателя фена (выход на симистор) D5_Low; //выставить логический 0 - симистор закрыт D13_Out; //пин пищалки D13_Low; //выставить логический 0 - сигнала нет ButtonsSetup(); //инициализация кнопок if (need_log) { //если нужно выводить лог Serial.begin(115200); //открываем сериал-порт на 115200 бод } myOLED.begin(); // Инициализируем дисплей myOLED.invert(true); Splash(); //выводим лого-рисунок MemRead(); //читаем память delay_ms(2000); //ждём 2с myOLED.invert(false); initDisplay(); //выводим интерфейсные надписи на экран myOLED.update(); attachInterrupt(1, ZC, FALLING); //включаем прерывание 1 на 3ем пине для отслеживания перехода через 0 } void loop() { ScanButtons(); //работа с кнопками //выключение фена через 1 минуту простоя if (need_HA_countdown) { //если фен на подставке unsigned long currHAmillis = millis(); //запоминаем время1 if (currHAmillis - prevHAmillis > 60000) { //если время1 - последнее время активности фена больше 1мин if (HAcountdown > 1) { //если отсчёт фена больше 1 HAcountdown--; //отсчёт фена -1 if (HAcountdown == 1) { //если отсчёт фена равен 1 - сигнал Beep(100); //сигнал если осталась 1 минута } } else { //если досчитали до конца - выключаем полностью и подаём сигнал HAcountdown = 1; //отсчёт прошёл prevHAmillis = 0; //последнее время активности фена равно 0 MemHotAir(); //запомнить установленную температуру фена в память need_HA_countdown = false; // отменяем необходимость отсчёта HotAirON = false; //выключаем флаг включенного фена Beep(200); //сигнал } prevHAmillis = currHAmillis; //запоминаем время1 как последнее время активности фена } } //обновление информации на LCD с интервалом 500мс uint32_t currDisplayMillis = millis(); //запоминаем время2 if (currDisplayMillis - prevDisplayMillis > 500) { //если время2 - время последнего обновления дисплея больше 0,5с prevDisplayMillis = currDisplayMillis; //время последнего обновления дисплея присвоить время2 DisplayUpdate(); //обновить дисплей //отправляем данные в сериал-порт if (need_log) { //если включен режим вывода лога if (HotAirON) { //если включен фен Graph_count++; //увеличить счётчик номера замера температуры Serial.print(Graph_count); //вывести в сериал-порт номер замера температуры Serial.print(";"); //разделитель ";" } else { //если фен выключен Graph_count = 0; //обнулить счётчик номера замера температуры } Serial.println(GetHotAirT); //вывести значение температуры } } //работа с интервалом 50мс (фен, кулер) uint32_t currWorkMillis = millis(); if (currWorkMillis - prevWorkMillis > 50) { prevWorkMillis = currWorkMillis; WorkWithHotAir(); } } //работа с феном void WorkWithHotAir() { GetHotAirT = (0.543*(getOversampled(A0_Read)))+8.141; //считать значение с А0 с оверсэмплингом и вычислить температуру (индивидуально для каждой термопары!) if (HotAirON) { //если фен включен //переводим проценты оборотов кулера в ШИМ analogWrite(pinFanPwm, map(SetHotAirRPM, min_rpm, max_rpm, 80, 255)); //включить кулер на установленной скорости вращения //защита от перегрева или обрыва термопары if (GetHotAirT > SetHotAirT + 50 || GetHotAirT < 0) { //если температура фена больше установленной на 50 градусов или меньше 0 градусов HAProtection(); //выполнить функцию защиты фена return; } // Включаем реле D4_High; //ПИ-регулятор фена HA_PI(); if (HAneedBeep) { //если температура стабилизировалась - сигнал int delta = GetHotAirT - SetHotAirT; //разница установленной и измеренной температур if (delta > -5 && delta < 5) { //если разница в пределах 3 градусов HAgood++; //счётчик стабилизации +1 if (HAgood == 20) { //если за 20 измерений температура стабильна - пищим 2 раза Beep(50); delay_ms(200); Beep(50); HAgood = 0; //сбрасываем счётчик стабилизации HAneedBeep = false; //отменяем необходимость сигнала } } else { //если разница больше чем 3 градуса HAgood = 0; //температура нестабильна HAneedBeep = true; //включаем сигнал о стабилизации } } } else { //если фен выключен HotAirOff(); //функция выключения фена if (GetHotAirT >= 50 && needCool) { //если температура фена больше 50 градусов и флаг необходимости охлаждения включен analogWrite(pinFanPwm, 255); //включаем кулер на полные обороты } else { //если температура ниже 50 градусов и охлаждение не нужно - проверяем защиту фена от перегрева if (!HotAirProtect) { //если защита от перегрева выключена analogWrite(pinFanPwm, 0); //выключаем кулер needCool = false; //отменяем необходимость охлаждения } } need_HA_countdown = false; //отключаем отсчёт до выключения HAcountdown = 1; //таймер выключения на 1 минуту } } void HAProtection() { //функция защиты фена analogWrite(pinFanPwm, 255); //кулер на полную HotAirProtect = true; //защита от перегрева включена HA_PROT = true; //защита включена HotAirON = false; //фен выключен HotAirOff(); //выполнить выключение фена } /*********************************** Вспомогательные функции *************************************/ //чтение int значения из памяти (двухбайтовое значение хранится в двух ячейках) int EEPROM_int_read(int addr) { byte raw[2]; for (byte i = 0; i < 2; i++) { raw[i] = EEPROM.read(addr + i); } int &num = (int&)raw; return num; } //запись int значения в память (двухбайтовое значение хранится в двух ячейках) void EEPROM_int_write(int addr, int num) { byte raw[2]; (int&)raw = num; for (byte i = 0; i < 2; i++) { EEPROM.write(addr + i, raw[i]); } } //сброс таймера отключения фена void ResetHAcountdown() { HAcountdown = HA_sleeptime; } //включение таймера отключения фена void ActivateHAcountdown() { need_HA_countdown = true; HAcountdown = HA_sleeptime; } //полное выключение фена void HotAirOff() { D5_Low; //выключение нагревателя delay_ms(30); D4_Low; //выключение реле защиты if (HotAirProtect && HA_PROT) { //если включена защита фена - сигнал HA_PROT = false; Beep(1000); MemHotAir(); } //запомнить значение установленной температуры фена } //отслеживание перехода через 0 void ZC() { StartTimer1(HeaterOn, ots); RestartTimer1(); } //открытие симистора void HeaterOn() { if (HotAirON) { if (HAPower > 0.0) { D5_High; delay_us(100); } D5_Low; } StopTimer1(); } //работа с кнопками void ScanButtons() { if (swHotAir.update() && HotAirON) { //если изменилось состояние геркона и фен включен ResetHAcountdown(); //сбросить таймер отключения Beep(50); //сигнал } //кнопка включения фена if (HotAirOnButton.update()) { //обновляет объект и возвращает TRUE (1), если состояние пина изменилось (кнопка была нажата или же, наоборот, отпущена) и FALSE (0) в противном случае if (HotAirOnButton.read()) { //возвращает обновленное состояние пина (false или true) HAONbuttonState = false; } else { if (!HotAirON) { //если фен выключен HotAirON = true; //включить фен HotAirProtect = false; //выключить режим защиты от перегрева prevHAmillis = millis(); //запомнить время последнего обращения к фену ActivateHAcountdown(); //активировать отсчёт до отключения Graph_count = 0; //обнулить счётчик номера замера температуры integral = 0; //сбросить накопленное значение интегральной поправки ПИ-регулятора selectedMode = modeHotAir; //выбранный режим - 0, фен HAneedBeep = true; //включить сигнал напоминания "1 минута до отключения" needCool = true; //включить необходимость охлаждения } else { //если фен включен ResetHAcountdown(); //сбросить таймер отключения } HAONbuttonState = true; HAONbuttonPressTime = millis(); //запомнить время последнего нажатия кнопки включения фена Beep(50); //сигнал } } if (HAONbuttonState) { //долгое нажатие на кнопку включения фена (больше 1000мс) if ( millis() - HAONbuttonPressTime >= 1000 ) { HAONbuttonPressTime = millis(); //запомнить время последнего нажатия кнопки if (HotAirON) { //если фен включен HotAirON = false; //выключить фен MemHotAir(); //запомнить выставленную температуру Beep(200); //долгий сигнал } } } //кнопка выбора режима SelButton.update(); if (SelButton.fell()) { //возвращает true, если кнопка перешла из 1 в 0 Beep(50); (selectedMode < modeFanPWM) ? (selectedMode++) : (selectedMode = modeHotAir); //тернарная условная операция, (logic ? val1 : val2), если logic=true выполняем val1, иначе val2 } //кнопка плюс if (UpButton.update()) { //если кнопка изменила состояние if (UpButton.read()) { //если кнопка отпущена UPbuttonState = false; //отключить обработку долгого нажатия } else { switch (selectedMode) { case modeHotAir: //если выбран режим фена - добавить температуру на 5 градусов if (SetHotAirT < max_hotair_temp) { SetHotAirT += 5; } HAneedBeep = true; //включить сигнал напоминания "1 минута до отключения" ResetHAcountdown(); //сбросить таймер отключения break; case modeFanPWM: //если выбран режим кулера - добавить обороты на 5 процентов if (SetHotAirRPM < max_rpm) { SetHotAirRPM += 5; } HAneedBeep = true; //включить сигнал напоминания "1 минута до отключения" ResetHAcountdown(); //сбросить таймер отключения break; } UPbuttonState = true; //включить обработку долгого нажатия UPbuttonPressTime = millis(); //запомнить время последнего нажатия кнопки Beep(50); //сигнал } } if (UPbuttonState) { if ( millis() - UPbuttonPressTime >= 300 ) { //если долгое нажатие (дольше 300мс) UPbuttonPressTime = millis(); //запомнить время последнего нажатия кнопки switch (selectedMode) { case modeHotAir: //если выбран режим фена - добавить температуру на 10 градусов SetHotAirT += 10; if (SetHotAirT > max_hotair_temp) SetHotAirT = max_hotair_temp; HAneedBeep = true; //включить сигнал напоминания "1 минута до отключения" ResetHAcountdown(); //сбросить таймер отключения break; case modeFanPWM: //если выбран режим кулера - добавить обороты на 10 процентов SetHotAirRPM += 10; if (SetHotAirRPM > max_rpm) SetHotAirRPM = max_rpm; HAneedBeep = true; //включить сигнал напоминания "1 минута до отключения" ResetHAcountdown(); //сбросить таймер отключения break; } } } //кнопка минус if (DwnButton.update()) { //если кнопка изменила состояние if (DwnButton.read()) { //если кнопка отпущена DWNbuttonState = false; //отключить обработку долгого нажатия } else { switch (selectedMode) { case modeHotAir: //если выбран режим фена - убавить температуру на 5 градусов if (SetHotAirT > min_hotair_temp) { SetHotAirT -= 5; } HAneedBeep = true; //включить сигнал напоминания "1 минута до отключения" ResetHAcountdown(); //сбросить таймер отключения break; case modeFanPWM: //если выбран режим кулера - убавить обороты на 5 процентов if (SetHotAirRPM > min_rpm) { SetHotAirRPM -= 5; } HAneedBeep = true; //включить сигнал напоминания "1 минута до отключения" ResetHAcountdown(); //сбросить таймер отключения break; } DWNbuttonState = true; //включить обработку долгого нажатия DWNbuttonPressTime = millis(); //запомнить время последнего нажатия кнопки Beep(50); //сигнал } } if (DWNbuttonState) { //если долгое нажатие (дольше 300мс) if ( millis() - DWNbuttonPressTime >= 300 ) { DWNbuttonPressTime = millis(); //запомнить время последнего нажатия кнопки switch (selectedMode) { case modeHotAir: //если выбран режим фена - убавить температуру на 10 градусов SetHotAirT -= 10; if (SetHotAirT < min_hotair_temp) SetHotAirT = min_hotair_temp; HAneedBeep = true; //включить сигнал напоминания "1 минута до отключения" ResetHAcountdown(); //сбросить таймер отключения break; case modeFanPWM: //если выбран режим кулера - убавить обороты на 10 процентов SetHotAirRPM -= 10; if (SetHotAirRPM < min_rpm) SetHotAirRPM = min_rpm; HAneedBeep = true; //включить сигнал напоминания "1 минута до отключения" ResetHAcountdown(); //сбросить таймер отключения break; } } } } //вывод логотипа void Splash() { myOLED.clrScr(); myOLED.drawBitmap(0, 0, logoHA, 128, 64); myOLED.update(); //если нужно построить диаграмму выхода на заданную температуру if (need_log) { myOLED.setFont(SmallFont); myOLED.print("*", 4, 4); } } //инициализация кнопок void ButtonsSetup() { pinMode(sw_HA, INPUT_PULLUP); //пин геркона swHotAir.attach(sw_HA); //устанавливает пин, к которому подключен геркон и включает подтягивающий резистор pinMode(bt_HAON, INPUT_PULLUP); HotAirOnButton.attach(bt_HAON); //устанавливает пин, к которому подключена кнопка и включает подтягивающий резистор HotAirOnButton.interval(5); //время задержки для антидребезга в мс pinMode(bt_Sel, INPUT_PULLUP); //по аналогии с кнопкой включения фена SelButton.attach(bt_Sel); SelButton.interval(5); pinMode(bt_Up, INPUT_PULLUP); //по аналогии с кнопкой включения фена UpButton.attach(bt_Up); UpButton.interval(5); pinMode(bt_Dwn, INPUT_PULLUP); //по аналогии с кнопкой включения фена DwnButton.attach(bt_Dwn); DwnButton.interval(5); } //выводим интерфейсные надписи на экран void initDisplay() { myOLED.clrScr(); myOLED.setFont(HAbigNumbers); myOLED.print("---", 1, 0); myOLED.drawLine(2, 41, 82, 41); //вертикальная линия myOLED.drawLine(82, 2, 82, 61); //горизонтальная линия myOLED.print(".", 60, 0); //degrees myOLED.setFont(SmallFont); myOLED.print("COOLER", 86, 3); myOLED.print("TEMP", 86, 35); myOLED.print("TO", 2, 53); myOLED.print("SLEEP:", 17, 53); } //обновление дисплея void DisplayUpdate() { initDisplay(); if (HotAirProtect) { //если сработала защита фена от перегрева for (int i = 2; i < 79; i++) { for (int j = 42; j < 62; j++) { myOLED.clrPixel(i, j); //очищаем остатки надписи "TO SLEEP" } } myOLED.setFont(SmallFont); myOLED.print("! OVERHEAT !", 5, 49); //вывести предупреждение myOLED.drawRect(5, 45, 77, 59); for (int i = 6; i < 77; i++) { for (int j = 46; j < 59; j++) { //инвертирование прямоугольника сигнализации перегрева myOLED.invPixel(i, j); } } } else if (HotAirON) { //если фен включен и защита от перегрева не сработала myOLED.setFont(HAsmallNumbers); if (HAcountdown < 10) { myOLED.print("0", 55, 45); //вывести значение счётчика до отключения фена myOLED.printNumI(HAcountdown, 67, 45); } else { myOLED.printNumI(HAcountdown, 55, 45); //вывести значение счётчика до отключения фена } } myOLED.setFont(HAsmallNumbers); myOLED.printNumI(SetHotAirT, 87, 45); //вывести значение установленной температуры фена if (GetHotAirT > 505 && !HotAirON) { //если измеренная температура фена больше 505 градусов или фен выключен myOLED.setFont(HAbigNumbers); myOLED.print("---", 1, 0); //вывести прочерк } else { myOLED.setFont(HAbigNumbers); if (GetHotAirT < 100) { myOLED.print("0", 1, 0); myOLED.printNumI(GetHotAirT, 21, 0); } else { myOLED.printNumI(GetHotAirT, 1, 0); //вывести значение измеренной температуры фена } } if (needCool && !HotAirON && GetHotAirT > 50) { //если необходимо охлаждение, фен выключен и измеренная температура фена больше 50 градусов myOLED.setFont(HAsmallNumbers); myOLED.print("-./", 87, 13); //вывести значение оборотов кулера MAX } else if (SetHotAirRPM == 100) { //если обороты кулера на максимуме - пишем MAX myOLED.setFont(HAsmallNumbers); myOLED.print("-./", 87, 13); //вывести значение оборотов кулера MAX } else { //иначе myOLED.setFont(HAsmallNumbers); myOLED.printNumI(SetHotAirRPM, 87, 13); //вывести значение выставленных оборотов кулера myOLED.print(":", 111, 13); //вывести знак % } if (selectedMode == 0) { myOLED.drawRoundRect(82, 32, 127, 62); //нарисовать рамку вокруг установленной температуры } else { myOLED.drawRoundRect(82, 0, 127, 30); //нарисовать рамку вокруг выставленных оборотов кулера } myOLED.update(); }тот код где то на форуме взял, не помню где. у него бы убрать геркон переделать температуры
спрашивай у автора. При чём здесь мы?
Пост от 17 го года, автору уже пофиг
Тыгыды исчи исполнителя за чатлы
И сколько такая радость стоить будет?
И сколько такая радость стоить будет?
Этот вопросец надо разместить в отделе "Ищу исполнителя" - там и цену скажут.
Но навскидку, с учетом ТЭНов, вентилятора, управления ПИД и тд и тп - мне бы это было интересно обсуждать начиная с 6-8 тыр
эээммм ,мне тогда проще купить готовый вариант
эээммм ,мне тогда проще купить готовый вариант
абсолютно верно, рекомендую так и поступить.
Серийное всегда дешевле заказного.
Поработал немного ассенизатором - вычистил срач. Прошу больше дерьма не лить.
Краткое резюме для ТС:
1. Помогают тем, кто делает сам! Тем, кто сам не делает помочь невозможно - можно только сделать за них.
2. Хотите делать самостоятельно - делайте, на конкретные вопросы Вам ответят и помогут.
3. Не хотите (или не можете) делать самостоятельно - заказывайте в коммерческом разделе форума, сделают за Вас.
4. Не хотите ни делать, ни заказывать - идите нафиг.
Всё. Срача здесь больше не будет.
Краткое резюме для ТС:
1. Помогают тем, кто делает сам! Тем, кто сам не делает помочь невозможно - можно только сделать за них.
2. Хотите делать самостоятельно - делайте, на конкретные вопросы Вам ответят и помогут.
3. Не хотите (или не можете) делать самостоятельно - заказывайте в коммерческом разделе форума, сделают за Вас.
4. Не хотите ни делать, ни заказывать - идите нафиг.
Всё. Срача здесь больше не будет.
Идеально! Вот так бы всегда...