Плавное/ступенчатое изменение низкой частоты
- Войдите на сайт для отправки комментариев
Доброго времени суток, всем читающим эту тему.
Хочу сделать приблуду себе в гараж, которая сможет управлять дозирующим насосом, который плунжерного типа. Собственно написать "моргалку" не проблема.
if (millis() - timer >= 300) { // Задержка с которой тикает насос
if (fpstate == LOW) //fp - fuel pump собственно насос
fpstate = !fpstate;
else
fpstate = !fpstate;
digitalWrite(fp, fpstate);
do {
timer += 300;
if (timer < 300) break;
} while (timer < millis() - 300);
}
Но я столкнулся с тем, что мне надо временами изменять частоту насоса, по таймеру. При чем делать это несколько раз варьируя частоту от 2х до 6ти герц (по задержке в коде примерно выходит 250мс-70мс).
И так собственно вопрос стоит таким образом - как плавно (или на крайняк ступенчато) изменить частоту пульсов на выходе?
Я пробовал следующим образом, но:
а) Этим получилось только плавно затормозить
б) работает только один раз, если несколько раз вкинуть с разными счетчиками, то работает только один
в) в идеале хотел бы обойтись без delay, но это не принципиально
puls=constrain(puls,0,300); //puls это доп переменная, которой я и собирался урегулировать частоту пульсов
puls=puls+1;
delay(20);
if (millis() - timer >= puls) {
if (fpstate == HIGH)
fpstate = !fpstate;
else
fpstate = !fpstate;
digitalWrite(fp, fpstate);
do {
timer += puls;
if (timer < puls) break;
} while (timer < millis() - puls);
}
Пожалуйста пните куда смотреть, я дальше сам разберусь))
У Вас все перепутано. Проверку в 1-й строке надо делать после изменения переменной (строка 2). Кроме того кто Вам мешает вместо puls=puls+1; поставить puls=puls-1;? (кстати в си обычно пишут puls++; или puls--;)
А, в принципе, очень сложно что-то советовать, когда Вы даете кусок программы, в котором, как Вам кажется. проблема. Скорее всего проблема в другом, но я этого не вижу.
Представьте полную программу, а не непонятный огрызок.
// 9 - вентилятор // 10 - паливний насос // 11 - водний насос // 12 - свічка накала #define PERIOD1 70 //6hz #define PERIOD2 90 //5.3hz #define PERIOD3 160 //3.05hz #define PERIOD4 250 //2hz uint32_t timer = 0; uint32_t timer1, timer2; int fan = 9; // вентилятор const int fp = 13; // паливний насос int fpstate = LOW; int wp = 11; int ign = 12; int puls = 300; int test; int temp = 0; void setup() { pinMode(fan, OUTPUT); pinMode(fp, OUTPUT); pinMode(wp, OUTPUT); pinMode(ign, OUTPUT); for (int i = 0; i <= 70; i++) { analogWrite(fan, i); delay(30); } analogWrite(fan, 70); delay(10); } void loop() { puls=puls-1; puls=constrain(puls,70,300); delay(20); if (millis() - timer >= puls) { if (fpstate == HIGH) fpstate = !fpstate; else fpstate = !fpstate; digitalWrite(fp, fpstate); do { timer += puls; if (timer < puls) break; } while (timer < millis() - puls); } }Программа сама по себе не дописана, ибо не могу вот расчехлить с изменением. Попробовал последовать вашему совету и о чудо - одна проблема ушла) но осталось следующее - если я попробую повторить этот же таймер только с другими параметрами, оба считают сразу и мешают друг другу получается.
Итак, спасибо за помощь, эту беду я поборол)) по крайней мере я так думаю. Но скетч выложу на всякий сейчас и когда допилю до адекватного состояния
// 9 - вентилятор // 10 - паливний насос // 11 - водний насос // 12 - свічка накала #define PERIOD1 70 //6hz #define PERIOD2 90 //5.3hz #define PERIOD3 160 //3.05hz #define PERIOD4 250 //2hz uint32_t timer = 0; uint32_t timer1, timer2; int fan = 9; // вентилятор const int fp = 13; // паливний насос int fpstate = LOW; int wp = 11; int ign = 12; int puls=300; int test; int temp = 0; void setup() { pinMode(fan, OUTPUT); pinMode(fp, OUTPUT); pinMode(wp, OUTPUT); pinMode(ign, OUTPUT); for (int i = 0; i <= 70; i++) { analogWrite(fan, i); delay(30); } analogWrite(fan, 70); delay(10); } void loop() { test=millis(); for(puls=300; puls>=71 && timer<= 20000; puls){ puls=puls-1; puls=constrain(puls,70,300); delay(20); if (millis() - timer >= puls) { if (fpstate == HIGH) fpstate = !fpstate; else fpstate = !fpstate; digitalWrite(fp, fpstate); do { timer += puls; if (timer < puls) break; } while (timer < millis() - puls); } if(puls==71) break; } for(puls=300; puls>=250 && timer<= 20000; puls){ puls=puls-1; puls=constrain(puls,250,300); delay(20); if (millis() - timer >= puls) { if (fpstate == HIGH) fpstate = !fpstate; else fpstate = !fpstate; digitalWrite(fp, fpstate); do { timer += puls; if (timer < puls) break; } while (timer < millis() - puls); } if(timer >= 20000) break; } if (millis() - timer >= 2000) { if (fpstate == HIGH) fpstate = !fpstate; else fpstate = !fpstate; digitalWrite(fp, fpstate); do { timer += 2000; if (timer < 2000) break; } while (timer < millis() - 2000); } }Итак, спасибо за помощь, эту беду я поборол)) по крайней мере я так думаю. Но скетч выложу на всякий сейчас и когда допилю до адекватного состояния
Вот положа руку на сердце - бред бреднёвый. 68 и 82 строки - это что? delay() в замаскированной форме?
Может Вы сядете и нормальным языком опишите алгоритм, а затем потихонечку переведёте его на си++?
А то херня - с получается.
да и пофиг, главное работает)) я с ардуино знаком двое суток, мне не для комерции, а для души поделать всяко-разные вещи. Я вот что по видеоурокам успел ухватить, тем и орудую. Тут понимаете в чем дело то, да я думал использовать дилей, но вот где не читаю, все эту функцию хают на чем свет стоит. Ну и мне нужно будет еще "вписать" в это тело три-четыре дополнительные функции, которые могут не сочетаться с дилеем.
А вот по поводу, что я хочу сделать - у меня валяються три котла в гараже, вебасто у которых нет мозгов, но все остальное рабочее. Я хочу сделать автономку для гаража, жидкостную. Алгоритм в двух словах не описать, но я все же попробую:
1) Первая минута - включение водного насоса, продувка вентилятором на 20% от его мощности, с 30й секунды поджиг свечи накала на 100% с выдержкой 10с и затуханием за 20с до 70% (так и останеться вплоть до третей минуты)
2) С 60й секунды дозирующий насос работает на 6гц, 4с, после чего на 2гц, 10с. Также вентилятор вращаеться на 37-40% номинальной мощности. Примерно на 80й секунде будет стабильное горение топлива. Далее нарастает частота до 5.25гц вплоть до выхода на полную нагрузку (примерно 6я минута в зависимости от наружных условий). После 80й секунды вентилятор выходит на 90% мощности и держит ее в режиме полной нагрузки.
3) Переход на частичную нагрузку при достижении температуры 80-85С, при которой вентилятор 65%, насос 3,1гц
4) Защиты по температуре, уровню топлива, охлаждайки тоже должны входить в цикл.
Надеюсь мой текст вас не утомил)
Смело. Зная ардуино два дня :) Застрахуйте гараж и сами застрахуйтесь !
да и пофиг
Прочитал. Вот тут и проблема. Вы исходите из неправильных предпосылок. Что вам надо в итоге? - вот оттуда прыгайте, а не от "на 10-й секунде наступил конец этого мира и начался новый".
Например:
1) Включаем циркуляционный насос;
2) Включаем вытяжной вентилятор (нахера?);
3) Включаем свечу зажигания до загорания, которое контролируем???
4) достигаем установленной температуры теплоносителя, останавливаем горение.
Теперь понимаем, что предыдущая шняга - это только кусок программы. Ведь в итоге нам нужно получить в гараже конкретную температуру.
Так что:
в сетапе:
включаем циркуляционный насос
включаем вентилятор
в основной программе:
контролируем температуру в помещении и в соответствии с ней регулируем температуру теплоносителя (используя подпрограмму запуска и остановки котла).
В проектах я такую шнягу опубликовал. Чуть доработать под Вашу задачу - и все...
И вообще - Вам что больше нужно - температура в гараже или запуск котла?
Смело. Зная ардуино два дня :) Застрахуйте гараж и сами застрахуйтесь !
Да лыдыть - там на соляре. Это Вам не на газу.
Вентилятор не вытяжной, а нагнетающий, в котлах с нагнетанием всегда включается до рабочего цикла и после него, для насыщения кислородом камеры сгорания и выдува паров топлива, если таковые имеются.
Свеча не зажигания, а накала ибо топливо дизельное. Должна быть включена какое-то время на случай срыва пламени, чтобы не стартовать котел с нуля.
По достижению температуры, горение не нужно останавливать, его нужно снизить. Это делается для меньшего расхода топлива. Остановка будет более-менее эффективной только, если разброс между уставкой старта и стопа небольшой, но в таком случае будут перепады температуры из-за инертности запуска.
Вентилятор не должен постоянно работать на максимуме, только в режиме полной нагрузки.
А за проект, премного благодарен, правда. Я чуть подучусь и разберу что там и как, ибо с библиотеками я еще не разобрался, сложно))
Я потому все жестко по таймерам решил завязать, взяв за пример работу штатной вебасты, для того, чтобы в итоге понять что нужно подстраивать и как. Ведь автомобильная автономка гоняет меньше охлаждайки, чем если это будет отопление помещения.
Вентилятор не вытяжной, а нагнетающий, в котлах с нагнетанием всегда включается до рабочего цикла и после него, для насыщения кислородом камеры сгорания и выдува паров топлива, если таковые имеются.
Свеча не зажигания, а накала ибо топливо дизельное. Должна быть включена какое-то время на случай срыва пламени, чтобы не стартовать котел с нуля.
По достижению температуры, горение не нужно останавливать, его нужно снизить. Это делается для меньшего расхода топлива. Остановка будет более-менее эффективной только, если разброс между уставкой старта и стопа небольшой, но в таком случае будут перепады температуры из-за инертности запуска.
Вентилятор не должен постоянно работать на максимуме, только в режиме полной нагрузки.
А за проект, премного благодарен, правда. Я чуть подучусь и разберу что там и как, ибо с библиотеками я еще не разобрался, сложно))
Я потому все жестко по таймерам решил завязать, взяв за пример работу штатной вебасты, для того, чтобы в итоге понять что нужно подстраивать и как. Ведь автомобильная автономка гоняет меньше охлаждайки, чем если это будет отопление помещения.
Понимаете - скорее всего Вы не сможете всего этого реализовать. Но если у Вас достаточно большой объем помещения (3 тыщи кубов и более) и большой объем теплоносителя, то Вам не надо "ловить блох" - работайте на максимуме котла. Достигаете максимума - останавливаете - гистерезис - запускаете. Можно попытаться использовать подачу топлива в котел (с помощью AnalogWrite()), но не советую. Скорее всего не получится.
Итак, забил я на это дело и уехал на работу) но так вышло, что немного в другом месте пришлось делать что-то подобное и за походом я таки допилил код под свои условия.
Теперь только дописать условия защит и убрать лишнее, но в целом все реализовано как я и хотел.
uint32_t timer = 0; uint32_t timer1 = 0; uint32_t timer2 = 0; uint32_t timer3 = 0; uint32_t timer4 = 0; uint32_t timer5 = 0; uint32_t timer6 = 0; uint32_t timer7 = 0; int fan = 9; // нагнетательный вентилятор const int fp = 13; // топливный насос int fpstate = LOW; int wp = 11; // водный насос int ign = 10; // свеча накаливания // check, fancheck, igncheck - доп переменные для определенных условий int test; int puls; // собственно величина периода пульса для плунжерного насоса int check; int check1; int check2; int check3; int check4; int check5; int check6; //---------------------- int fancheck = LOW; int fancheck1; int fancheck2; int fancheck3; int fancheck4; int fancheck5; int fancheck6; //----------------- int igncheck = LOW; int igncheck1 = LOW; int igncheck2; int igncheck3; int igncheck4; int fanstep1 = 1; // шаг изменения для вентилятора int ignstep1 = 1; // шаг изменения для свечи int temp = 0; int tmpr; int PWM = 0; int stepsize1 = 1; // шаг изменения для топливного насоса int stepsize5 = 10; unsigned long currentTime; unsigned long loopTime; long previousMillis = 0; long interval = 1000; void setup() { pinMode(A3, INPUT); pinMode(fan, OUTPUT); pinMode(fp, OUTPUT); pinMode(wp, OUTPUT); pinMode(ign, OUTPUT); currentTime = millis(); loopTime = currentTime; timer = millis(); if(puls == 0){ fpstate = LOW; } puls = 0; check = LOW; check1 = LOW; check2 = LOW; check3 = LOW; check4 = LOW; PWM = 50; fancheck = LOW; fancheck1 = LOW; fancheck2 = LOW; fancheck3 = LOW; } void loop() { analogWrite(9, PWM); analogWrite(10, ign); timer = millis(); timer3 = millis(); timer5 = millis(); tmpr = analogRead(A3); currentTime = millis(); //-------------------------------------------------------------------------------------- if(timer3 >= (timer4 + 2000) && fancheck == LOW){ PWM = PWM + fanstep1; if ( PWM == 52) { fancheck = HIGH; fanstep1 = 0 ; fancheck2 = HIGH; timer3 = millis(); timer4 = millis(); } timer4 = millis(); } if(fancheck2 == HIGH && fancheck == HIGH){ fanstep1 = 1; } if(timer3 >= (timer4 + 100) && fancheck2 == HIGH){ PWM = PWM + fanstep1; if ( PWM == 104) { fanstep1 = 0 ; fancheck3 = HIGH; fancheck2 = LOW; } timer4 = millis(); } if(fancheck3 == HIGH){ fanstep1 = 1; } if(timer3 >= (timer4 + 10000) && fancheck3 == HIGH){ PWM = PWM + fanstep1; if ( PWM == 106) { fanstep1 = 0 ; fancheck3 = LOW; fancheck4 = HIGH; } timer4 = millis(); } if(fancheck4 == HIGH){ fanstep1 = 1; } if(timer3 >= (timer4 + 140) && fancheck4 == HIGH){ PWM = PWM + fanstep1; if ( PWM == 240) { fanstep1 = 0 ; fancheck3 = LOW; fancheck4 = LOW; } timer4 = millis(); } //--------------------------------------------------------------------------------------------- unsigned long currentMillis = millis(); if(currentMillis - previousMillis > puls) { previousMillis = currentMillis; if (fpstate == LOW) fpstate = HIGH; else fpstate = LOW; digitalWrite(fp, fpstate); } if(puls == 0){ fpstate = HIGH; check = HIGH; } if(currentTime >= (loopTime + 200) && check == HIGH){ puls = puls + stepsize5; if (puls == 70) { stepsize5 = 0; check = LOW; check1 = HIGH; } loopTime = currentTime; } if(check1 == HIGH){ stepsize1 = 1; } if(check1 == HIGH){ if(currentTime >= (loopTime + 2000)){ puls = puls + stepsize1; if (puls == 72) { stepsize1 = 0; check1 = LOW; check2 = HIGH; } loopTime = currentTime; } if(check2 == HIGH){ stepsize1 = 1; } } if(currentTime >= (loopTime + 36) && check2==HIGH){ puls = puls + stepsize1; if ( puls == 250) { stepsize1 = 0; check2 = LOW; check3 = HIGH; } loopTime = currentTime; } if(check3 == HIGH){ stepsize1 = 1; } if(currentTime >= (loopTime + 8000) && check3 == HIGH){ puls = puls + stepsize1; if ( puls == 252){ stepsize1 = 0; check3 = LOW; check4 = HIGH; } loopTime = currentTime; } if(check4 == HIGH){ stepsize1 = 1; } if(currentTime >= (loopTime + 2222) && check4 == HIGH){ puls = puls - stepsize1; if ( puls == 90) { stepsize1 = 0; check3 = LOW; check4 = LOW; check5 = HIGH; // fanstep1 = 1; } loopTime = currentTime; } if(timer >= (timer1 + 118) && igncheck == LOW){ ign = ign + ignstep1; if ( ign == 255) { ignstep1 = 0 ; igncheck = HIGH; igncheck1 = HIGH; } timer1 = millis(); } if(igncheck1 == HIGH){ ignstep1 = 1; } if(timer >= (timer1 + 7500) && igncheck1 == HIGH){ ign = ign - ignstep1; if ( ign == 253) { igncheck1 = LOW; igncheck2 = HIGH; ignstep1 = 0 ; } timer1 = millis(); } if(igncheck2 == HIGH){ ignstep1 = 1; } if(timer >= (timer1 + 274) && igncheck2 == HIGH){ ign = ign - ignstep1; if ( ign == 180) { igncheck2 = LOW; igncheck3 = HIGH; ignstep1 = 0 ; } timer1 = millis(); } if(igncheck3 == HIGH){ ignstep1 = 1; } if(timer >= (timer1 + 60000) && igncheck3 == HIGH){ ign = ign + ignstep1; if ( ign == 183) { igncheck3 = LOW; igncheck4 = HIGH; ignstep1 = 0 ; } timer1 = millis(); } if(igncheck4 == HIGH){ ign = LOW; igncheck4 = LOW; } }в код особо не вникал, одно замечание.
Вот так вот считать интервалы нельзя,
потому что при переполнении счетчика времени условие развалится. Вместо этого все подобные скобки. коих у вас в коде десятка три. надо переписать вот так
большое спасибо за совет, обязательно поправлю!