Доводчик стекол с блек джеком
- Войдите на сайт для отправки комментариев
Решил сваять доводчик окон и люка в авто.
Пока жду детальки из китая сваял проект в протеусе. Подскажите что не так или что можно по вашему мнению улучшить. Для ардуины это первые шаги, раньше бывало писал на бейсике.
При выключении зажигания на чинается отсчет времени до отключения питания на ардуину, задам где-то на пол часа т.к от этого же провода питания собираюсь подать питание на магнитолу.
Если в течении получаса будет закрыт центральный замок то начнут по очереди закрываться: люк, правое стекло, левое стекло. Отключение моторов будет происходить по превышению тока выше уставки и запасной вариант по истечении заданного времени времени.
Уставка по току калибруется двумя кнопками. 1-ой кнопкой при полностью открытых окнах берется замер. 2-ой кнопкой при полностью закрытых окнах.
также реализовал режим автодовода при включенном зажигании т.е при удержании кнопки правой двери или люка более 1 секунды а затем ее отпускании стекло продолжит двигаться до перемещения в крайнее положение (левая небудет т.к на ней заводской автодоводчик)
вот схемы протеуса почти такие как будут,кроме изображенных реле, там будут применяться модули с оптопарой. и питание от TIP122 будет подавться на на RESET а на vin(ненашел как по другому реализовать в протеусе отключение питани ардуины)
черновая: симуляция работает
чистовая: почемуто нехочет
в архиве скетч и проэкты протеус
https://drive.google.com/file/d/0B7zPXIoEu3OhMDFlclJWX2VhNms/view?usp=sharing
вот скетч
#include <EEPROM.h> unsigned long time1; // всякие разные переменные нужные для сопутствующих вычислений unsigned long time2; int dtoka; int dtoka1; int kv; int tmot; int zzz; int nnn; int jjj; int vpr; int xxx; int tok; byte hi; byte low; int dverA_L_HI; int dverA_L_LOW; int dverA_R_LOW; int dverA_R_HI; int lukA_LOW; int lukA_HI; int lukA; int dverA_L; int dverA_R; int TIME_DVER = 5000; // максимальное время закрытия дверей в авторежиме. каждая 1000 = 1 секунде int TIME_LUK =5000; // максимальное время закрытия люка в авторежиме. каждая 1000 = 1 секунде int TIME_AUTO = 1000; // время до включения режима автодовода unsigned long TIME_OFF = 5000; //время до отключения питания если не произойдет закрытие дверей "нужно для работы магнитолы пока не закроются двери или не выйдет время" boolean AUTO_ZAKR = 0; // в этом куске задаются номера пинов переменным int POWER = 8; int M_LUK_NAZ = A4; int M_LUK_VPER = A5; int POW_HALL = 9; int OC_ZAM_DVER = 7; int OC_ZAZIGANIE = 6; int OC_PR_VERH = 2; int OC_PR_NIZ = 3; int OC_LUK_NAZ = 4; int OC_LUK_VPER = 5; int M_PR_VERH = A1; int M_LEV_VERH = A3; int M_PR_NIZ = A2; int tokz = A0; int KAL_LOW = 10; int KAL_HI = 11; void setup() { pinMode(12, OUTPUT); // на свободные ноги ставлю на выход, притягиваю к земле digitalWrite(12, LOW); pinMode(13, OUTPUT); // digitalWrite(13, LOW); pinMode(0, OUTPUT); // digitalWrite(0, LOW); pinMode(1, OUTPUT); //- digitalWrite(1, LOW); //Serial.begin(9600); pinMode(KAL_LOW, INPUT); // кнопка калибровки тока по датчику при движущемся стекле pinMode(KAL_HI, INPUT); // кнопка калибровки тока по датчику при застопоренном стекле digitalWrite(KAL_LOW, HIGH); // подтяг digitalWrite(KAL_HI, HIGH); // pinMode(M_PR_NIZ, OUTPUT); //мотор правой двери вниз digitalWrite(M_PR_NIZ, HIGH); pinMode(M_LEV_VERH, OUTPUT); //мотор левой двери вверх digitalWrite(M_LEV_VERH, HIGH); pinMode(M_PR_VERH, OUTPUT); //мотор правой двери вверх digitalWrite(M_PR_VERH, HIGH); pinMode(POWER, OUTPUT); // пин OC_POWER включает питание при отключенном зажигании digitalWrite(POWER, HIGH); pinMode(OC_ZAM_DVER, INPUT); // вход с ЦЗ двери, импульс +12в pinMode(OC_ZAZIGANIE, INPUT); // зажигание pinMode(POW_HALL, OUTPUT); // на питание датчика тока digitalWrite(POW_HALL, LOW); pinMode(M_LUK_VPER, OUTPUT); // мотор люка вперед pinMode(M_LUK_NAZ, OUTPUT); // мотор люка назад digitalWrite(M_LUK_VPER, HIGH); digitalWrite(M_LUK_NAZ, HIGH); pinMode(OC_LUK_VPER, INPUT); // вход с кнопки люка вперед pinMode(OC_LUK_NAZ, INPUT); // вход с кнопки люка назад pinMode(OC_PR_VERH, INPUT); //вход правая дверь кнопка стекло вверх pinMode(OC_PR_NIZ, INPUT); //вход правая дверь кнопка стекло вниз hi = EEPROM.read(1); // этот блок считывает автокалибровочные данные low = EEPROM.read(2); lukA_LOW = word(hi,low); hi = EEPROM.read(3); low = EEPROM.read(4); dverA_R_LOW = word(hi,low); hi = EEPROM.read(5); low = EEPROM.read(6); dverA_L_LOW = word(hi,low); hi = EEPROM.read(7); low = EEPROM.read(8); lukA_HI = word(hi,low); hi = EEPROM.read(9); low = EEPROM.read(10); dverA_R_HI = word(hi,low); hi = EEPROM.read(11); low = EEPROM.read(12); dverA_L_HI = word(hi,low); lukA=lukA_HI-lukA_LOW; lukA=lukA/2; lukA=lukA+lukA_LOW; dverA_R=dverA_R_HI-dverA_R_LOW; dverA_R=dverA_R/2; dverA_R=dverA_R+dverA_R_LOW; dverA_L=dverA_L_HI-dverA_L_LOW; dverA_L=dverA_L/2; dverA_L=dverA_L+dverA_L_LOW; delay(500); } //---------------------------------------------------------------------------------------------------------------------------------------------------------------- void loop() { //Serial.println(dverA_L); //digitalWrite(12, HIGH);delay (50);digitalWrite(12, LOW);delay (50); /// удалить if(digitalRead(OC_LUK_VPER)==HIGH){kv=OC_LUK_VPER; vpr=M_LUK_VPER; tmot=TIME_LUK; AUTO_ZAKR=0; tok=lukA; motor();} //люк вперед, if(digitalRead(OC_LUK_NAZ)==HIGH){kv=OC_LUK_NAZ; vpr=M_LUK_NAZ; tmot=TIME_LUK; AUTO_ZAKR=0; tok=lukA; motor();} //люк назад, if(digitalRead(OC_PR_VERH)==HIGH){kv=OC_PR_VERH; vpr=M_PR_VERH; tmot=TIME_DVER; AUTO_ZAKR=0; tok=dverA_R; motor();} //правая дверь вверх, if(digitalRead(OC_PR_NIZ)==HIGH){kv=OC_PR_NIZ; vpr=M_PR_NIZ; tmot=TIME_DVER; AUTO_ZAKR=0;tok=dverA_R; motor();} //правая дверь вниз, if (digitalRead(OC_ZAZIGANIE)==LOW && digitalRead(OC_ZAM_DVER)==HIGH) // включение режима доводчика { kv=OC_LUK_VPER; vpr=M_LUK_VPER; tmot=TIME_LUK; AUTO_ZAKR=1; tok=lukA; motor(); // режим доводчика, люк вперед, delay (100); if (digitalRead(OC_ZAZIGANIE)==HIGH) {goto stop2;} // если снова включено зажигание то прекратить kv=OC_PR_VERH; vpr=M_PR_VERH; tmot=TIME_DVER; AUTO_ZAKR=1; tok=dverA_R; motor(); // режим доводчика, правая дверь вверх, delay (100); if (digitalRead(OC_ZAZIGANIE)==HIGH) {goto stop2;} // если снова включено зажигание то прекратить vpr=M_LEV_VERH; tmot=TIME_DVER; AUTO_ZAKR=1;tok=dverA_L; motor(); // режим доводчика, левая дверь вверх, delay (100); if (digitalRead(OC_ZAZIGANIE)==HIGH) {goto stop2;} // если снова включено зажигание то прекратить digitalWrite (POWER, LOW); //завершение цикла доводчика, отключение питания stop2: delay (5); // надо что-то втавить иначе не компилится } time1= millis(); if (digitalRead(OC_ZAZIGANIE)==HIGH) {time2= millis();} if (TIME_OFF<time1-time2) {digitalWrite (POWER, LOW);} // выставить время до автоотключения при выключенном зажигании и незакрытии дверей " нужно для работы магнитолы до закрытия дверейЭ if (digitalRead(KAL_LOW)==LOW){kalibr_LOW();} if (digitalRead(KAL_HI)==LOW){kalibr_HI();} } //------------------------------------------------------------------------------------------------------------------------------------------------------------ void motor() { digitalWrite(POW_HALL, HIGH); // включает питание датчика тока digitalWrite(vpr, LOW); // включение реле мотора delay(100); // на дребезг, на прогрев датчика тока nnn=0; zzz=0; time2=0; for (time1 = millis(); time2 <=tmot; time2=millis()-time1) // tmot задает максимальное время работы { if (AUTO_ZAKR==0) { if (time2<TIME_AUTO && digitalRead(kv)==LOW){goto stop1;}} // значение 1000 время до автоработы мотора. если прошло меньше секунды и отпущена кнопка завершаем цикл. в режиме доводчика это условие пропускается dtoka1 = 0; for (xxx=0; xxx <= 20; xxx++) // цикл на выборку 20 замеров по току мотора { if(digitalRead(kv)==HIGH){zzz=1;}else { nnn=1;} // отрабатывает повторное нажатие клавиши в том же направлении для выключения автоработы мотора jjj=zzz+nnn; // if (jjj==2){goto stop1;} // zzz=0; dtoka = analogRead(tokz); // считывает значение тока при работающем моторе dtoka=dtoka-492; delay(5); dtoka1 = dtoka1+dtoka; // if(digitalRead(kv)==LOW){ if(digitalRead(OC_LUK_VPER)==HIGH || digitalRead(OC_LUK_NAZ)==HIGH || digitalRead(OC_PR_VERH)==HIGH || digitalRead(OC_PR_NIZ)==HIGH ) {goto stop1;}} //отключение авторежима при нажатии любой клавиши } //dtoka1=dtoka1/0.42; if (dtoka1>=tok){break;} } stop1: digitalWrite(vpr, HIGH); // выключает реле питания на мотор digitalWrite(POW_HALL, LOW); // выключает питание датчика тока while(1){if(digitalRead(kv)==LOW){break;}} // цикл защиты от щелканья реле } //---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- // калибровку можно написать короче но мне лень с переменными возиться void kalibr_LOW() // калибровка по току при передвижении стекла , после калибровки выключить зажигание { digitalWrite(POW_HALL, HIGH); digitalWrite(M_LUK_VPER, LOW); delay(1000); dtoka1 = 0; for (xxx=0; xxx <= 20; xxx++) // цикл на выборку 20 замеров по току мотора { dtoka = analogRead(tokz); // считывает значение тока при работающем моторе dtoka=dtoka-492; delay(5); dtoka1 = dtoka1+dtoka; // } //dtoka1=dtoka1/0.42; //Serial.println(lukA); hi = highByte(dtoka1); low = lowByte(dtoka1); EEPROM.write(1, hi); EEPROM.write(2, low); digitalWrite(M_LUK_VPER, HIGH); delay(1000); digitalWrite(M_PR_VERH, LOW); delay(1000); dtoka1 = 0; for (xxx=0; xxx <= 20; xxx++) // цикл на выборку 20 замеров по току мотора { dtoka = analogRead(tokz); // считывает значение тока при работающем моторе dtoka=dtoka-492; delay(5); dtoka1 = dtoka1+dtoka; // } //dtoka1=dtoka1/0.42; //Serial.println(lukA); hi = highByte(dtoka1); low = lowByte(dtoka1); EEPROM.write(3, hi); EEPROM.write(4, low); digitalWrite(M_PR_VERH, HIGH); delay(1000); digitalWrite(M_LEV_VERH, LOW); delay(1000); dtoka1 = 0; for (xxx=0; xxx <= 20; xxx++) // цикл на выборку 20 замеров по току мотора { dtoka = analogRead(tokz); // считывает значение тока при работающем моторе dtoka=dtoka-492; delay(5); dtoka1 = dtoka1+dtoka; // } //dtoka1=dtoka1/0.42; //Serial.println(lukA); hi = highByte(dtoka1); low = lowByte(dtoka1); EEPROM.write(5, hi); EEPROM.write(6, low); digitalWrite(M_LEV_VERH, HIGH); delay(1000); digitalWrite(POW_HALL, LOW); } //--------------------------------------------------------------------------------------------------------------------------------------------------------------- void kalibr_HI() // после калибровки выключить зажигание { digitalWrite(POW_HALL, HIGH); digitalWrite(M_LUK_VPER, LOW); delay(1000); dtoka1 = 0; for (xxx=0; xxx <= 20; xxx++) // цикл на выборку 20 замеров по току мотора { dtoka = analogRead(tokz); // считывает значение тока при работающем моторе dtoka=dtoka-492; delay(5); dtoka1 = dtoka1+dtoka; // } //dtoka1=dtoka1/0.42; //Serial.println(lukA); hi = highByte(dtoka1); low = lowByte(dtoka1); EEPROM.write(7, hi); EEPROM.write(8, low); digitalWrite(M_LUK_VPER, HIGH); delay(1000); digitalWrite(M_PR_VERH, LOW); delay(1000); dtoka1 = 0; for (xxx=0; xxx <= 20; xxx++) // цикл на выборку 20 замеров по току мотора { dtoka = analogRead(tokz); // считывает значение тока при работающем моторе dtoka=dtoka-492; delay(5); dtoka1 = dtoka1+dtoka; // } //dtoka1=dtoka1/0.42; //Serial.println(lukA); hi = highByte(dtoka1); low = lowByte(dtoka1); EEPROM.write(9, hi); EEPROM.write(10, low); digitalWrite(M_PR_VERH, HIGH); delay(1000); digitalWrite(M_LEV_VERH, LOW); delay(1000); dtoka1 = 0; for (xxx=0; xxx <= 20; xxx++) // цикл на выборку 20 замеров по току мотора { dtoka = analogRead(tokz); // считывает значение тока при работающем моторе dtoka=dtoka-492; delay(5); dtoka1 = dtoka1+dtoka; // } //dtoka1=dtoka1/0.42; //Serial.println(lukA); hi = highByte(dtoka1); low = lowByte(dtoka1); EEPROM.write(11, hi); EEPROM.write(12, low); digitalWrite(M_LEV_VERH, HIGH); delay(1000); digitalWrite(POW_HALL, LOW); }
переправил всю часть автокалибровки, теперь нет дополнительных кнопок на калибровку, просто надо до включения зажигания зажать кнопку люка назад и после включения зажигания отпустить.
перед проведением автокалибровки окна и люки должны быть максимально открыты
автокалибровка задает токи отключения двигателей равное среднему между токами при свободном движении стекол и токами когда стекло дойдет до упора в и максимальное время работы двигателей если не сработал датчик тока, оно равно времени закрытия + 3 секунды.
тут схемы протеуса, скетч, hex
https://drive.google.com/file/d/0B7zPXIoEu3OhbUc4cThnWk5uTUk/view?usp=sharing
таки сваял в железе, схема несколько претерпела изменения из за модулей реле. 12 вольтовые модули переключаются при напряжении на оптопаре 10в что оказалось печалькой, нормально работают только те где есть контакты VCC и COM, а также те где есть перемычка(ее надо снять и подать на JD-VCC +12v, на VCC +5v. Вот такие негодятся https://www.aliexpress.com/item-img/1-Channel-12V-Relay-Module-Optocoupler-Low-Level-Trigger-Expansion-Board-for-Arduino/32699477704.html?spm=2114.10010208.1000017.2.gwFZDh
вот такой датчик тока https://www.aliexpress.com/item-img/Free-shipping-5PCS-LOT-Hall-Current-Sensor-Module-ACS712-5A-20A-30A-model-for-arduino/32348760733.html?spm=2114.10010208.1000017.2.3bQqCv
показывает нестабильные результаты хоть и используется выборка 50 показаний, надеюсь что он так плохо работает только с малыми токами(больше 0,5 A нечем было нагрузить), надеюсь вживую он будет работать лучше.
Осталось дело за корпусом, надеюсь через неделю провести натурные испытания
схема в протеусе и скетч https://drive.google.com/drive/folders/0B7zPXIoEu3OhRWVKSzVsbkVETUE?usp=sharing
Вот скетч на текущий момент
продолжение было?)
работает, правда отказался от автокалибровки, и привода люка(на него отдельный модуль довода сделал) ну и схему переделал, не стал использовать оптопары, поставил просто реле с транзисторами, скетч рабочий где-то сохранен, а вот схему скорее всего потерял.
для использования вот этот скетч крайне специфичен т.к нет автодовода левой двери(там есть родной) и одновременно люк и дверь не могут работать и сделан был конкретно для пыжа206 без кан шины
если нужен доводчик то лучше этот посмотреть
http://arduino.ru/forum/proekty/dovodchik-stekol