Помогите с регулируемым дозатором.

subbotinHZ2
Offline
Зарегистрирован: 10.03.2018

Всем доброго дня.

Люди добрые прошу Вашей помощи в корректировке скетча (может найдется добрая душа и поможет по доброй воле).

Задача стоит такая: после включения микроконтроллера одновременно каждые 15 секунд должны срабатывать два реле (пока светодиоды) на время которое устанавливается потенциометром (от 0 до 14 секунд) .  И так бесконечно, до отключения МК.

Собрал сборую солянку из нескольких скетчей, вроде что то получилось ( светодиоты включаются каждые 15 секунд, время выключения регулируется) , но не получается сделать  одновременное включение каждые 15 секунд.

const int pot1=1; // потенциометр №1 пин А1
int ledPin1 = 2; // номер пина со светодиодом
int ledState1 = LOW; // состояние светодиода
unsigned long previousMillis1 = 0;// последний момент времени, когда состояние светодиода изменялось
long OnTime1 = 0; // длительность свечения светодиода (в миллисекундах)
long OffTime1 = 0; // светодиод не горит (в миллисекундах)

const int pot2=2; // потенциометр №2 пин А2
int ledPin2 = 3; // номер пина со светодиодом
int ledState2 = HIGH; // состояние светодиода
unsigned long previousMillis2 = 0;// последний момент времени, когда состояние светодиода изменялось
long OnTime2 = 0; // длительность свечения светодиода (в миллисекундах)
long OffTime2 =0; // светодиод не горит (в миллисекундах)

void setup() {
 // устанавливаем цифровой пин со светодиодом как ВЫХОД
 pinMode(ledPin1, OUTPUT);
 pinMode(ledPin2, OUTPUT);
}
 
void loop() {
 // выясняем не настал ли момент сменить состояние светодиода
 unsigned long currentMillis = millis(); // текущее время в миллисекундах
  OnTime1=(analogRead(pot1)*14); // ЗАДАЕМ  ВРЕМЯ ВКЛЮЧЕНИЯ СВЕЧЕНИЯ СВЕДОДИОДА, АНАЛОГОВЫЙ ВХОД 1063* 14= 14,8 СЕКУНДЫ
  OffTime1=(15000-OnTime1); //  ВЫСЧИТЫМАЕМ ОСТАВШЕЕСЯ ВРЕМЯ ОТ 15 СЕКУНД. СВЕДОДИЛД НЕ СВЕТИТСЯ
 // конечный автомат для 1-го светодиода
 if((ledState1 == HIGH) && (currentMillis - previousMillis1 >= OnTime1))
 {
   ledState1 = LOW; // выключаем
   previousMillis1 = currentMillis; // запоминаем момент времени
   digitalWrite(ledPin1, ledState1); // реализуем новое состояние
 }
 else if ((ledState1 == LOW) && (currentMillis - previousMillis1 >= OffTime1))
 {
   ledState1 = HIGH; // включаем
   previousMillis1 = currentMillis ; // запоминаем момент времени
   digitalWrite(ledPin1, ledState1); // реализуем новое состояние
 }
 
 // конечный автомат для 2-го светодиода

  OnTime2=(analogRead(pot2)*14);//  ЗАДАЕМ  ВРЕМЯ ВКЛЮЧЕНИЯ СВЕЧЕНИЯ СВЕДОДИОДА, АНАЛОГОВЫЙ ВХОД 1063* 14= 14,8 СЕКУНДЫ
  OffTime2=(15000-OnTime2);// ВЫСЧИТЫМАЕМ ОСТАВШЕЕСЯ ВРЕМЯ ОТ 15 СЕКУНД. СВЕДОДИЛД НЕ СВЕТИТСЯ
 
 if((ledState2 == HIGH) && (currentMillis - previousMillis2 >= OnTime2))
 {
   ledState2 = LOW; // выключаем
   previousMillis2 = currentMillis; // запоминаем момент времени
   digitalWrite(ledPin2, ledState2); // реализуем новое состояние
 }
 else if ((ledState2 == LOW) && (currentMillis - previousMillis2 >= OffTime2))
 {
   ledState2 = HIGH; // выключаем
   previousMillis2 = currentMillis ; // запоминаем момент времени
   digitalWrite(ledPin2, ledState2); // реализуем новое состояние
 }
}

За ранее блогодарен.

b707
Offline
Зарегистрирован: 26.05.2017

Что такое "одновременное включение нескольких светодиодов "?  И в чем разница от включения одного? Что мешает включать, как лампы в люстре - одним общим выключателем три лампочки?

svm
Offline
Зарегистрирован: 06.11.2016

b707 пишет:

Что такое "одновременное включение нескольких светодиодов "? 

Скорее всего включаются одновременно, а длительнось горения СД - разная.

А может быть и нет?

ТС не очень внятно изложил суть проблемы. Он для простой задачи делает очень много лишних непогятных телодвижений. Зачем проверять Сколько времени СД осталось быть потушенным? Да и мого еще чего.

Не проще-ли

-Считать время горения (обооих) СД

-Зажечь оба

затем три делея все равно программа больше ничего не делет

- первый (тот кто меньше горит)  15 сек"-" время горения 1 СД

- выключаем 1 СД

-второй 15 сек"-" разница времени горения 1 и 2 СД

-Выключаем оба СД

-третий 15 "-" что осталось

и так по кругу (гоу туначало). Конечно грубо по рабоче-крестьянски, но работать будет, но если использовать миллис, будет красивее и можно менять время выключения в текущем цикле.

subbotinHZ2
Offline
Зарегистрирован: 10.03.2018

Все верно.

Светодиоды должны включаться одновременно , а длительность горения регулируется потенцеометром. Затем они снова одновременно включаются. Смысл в том , что необходимо обеспечить обновременное включение сведодиодов каждые 15 секунд.

 

 

subbotinHZ2
Offline
Зарегистрирован: 10.03.2018

Вся задача состоит в том, что бы каждые 15 секунд одновременно включать  лампочки на "люстре" , а потенцеометром регулировать время горения каждой отдельно. Время горения всех лампочек разное и составляет  от 0 до 14 секунд, время не горения все что остается до следующего цикла включения. 

svm
Offline
Зарегистрирован: 06.11.2016

subbotinHZ2 пишет:

 Время горения всех лампочек разное и составляет  от 0 до 14 секунд, время не горения все что остается до следующего цикла включения. 

А зачем вам его знать? Тупо каждые 15 сек включаете и все. Это абсолютно лишняя информация которая не нужна ни вам, ни ардуине и тем более лампочке. Её задача загореться когда наступят следующие 15 сек.

subbotinHZ2
Offline
Зарегистрирован: 10.03.2018

Ее основной задачей является регулируемое время горения и включение каждые 15 секунд. 

Решил реанимировать старый дозатор жидких компонентов( очень удобный).

Каждые 15 секунд происходит слив компонентов ( горит светодиод) , время слива каждого компонента регулируется отдельно потенциометром (0-14 сек.), после паузы (светодиод не горит) которая получается тоже разной по времени, наступает цикл очередных 15 секунд и все заново.

Очень удобно проверять минутный расход жидкости слитый с дозировок.

 

 

sadman41
Offline
Зарегистрирован: 19.10.2016

Так вы не читаете, что вам пишут. 

У вас раздельные задачи такие:

1) Каждые 15 сек. зажигать все светодиоды;
2) Каждые N секунд после наступления момента (1) гасить светодиод.

Пункт (2) повторять по количеству светодиодов.

svm
Offline
Зарегистрирован: 06.11.2016

subbotinHZ2 пишет:

Ее основной задачей является регулируемое время горения и включение каждые 15 секунд. 

Ну и на здоровье. Еще раз просмотрите алгоритм который я предложил. Если есть неточности исправьте.

У Вас слишком все заморочено . Будьте проще.

subbotinHZ2
Offline
Зарегистрирован: 10.03.2018

Спасибо. Надо попробовать. Что получится отпишусь.

svm
Offline
Зарегистрирован: 06.11.2016

subbotinHZ2 пишет:
Спасибо. Надо попробовать. Что получится отпишусь.

 

Успехов. Все получится программа очень простая.

Но после того как все это заработает, скорее всего придется сделать индикацию временных задержек, потому что судить о времени по положению резистора- это мягко говоря моветон.

evgta
Offline
Зарегистрирован: 02.09.2016

как-то так

int reo1=0;
int reo2=0;
unsigned long time1 = 0;
unsigned long time2 = 0;
#define lamp1 2
#define lamp2 3
boolean flag1 = 0;
boolean flag2 = 0;


void setup() {
pinMode(A1, INPUT);
pinMode(A2, INPUT);
pinMode(2, OUTPUT);
pinMode(3, OUTPUT);  
digitalWrite(lamp1, LOW);
digitalWrite(lamp2, LOW);

start();

}

void loop() {


if (time2>=15000){start();}
time2=millis()-time1;
reo();
if (time2>=reo1 && flag1==1 ){digitalWrite(lamp1, LOW);flag1=0;}
if (time2>=reo2 && flag2==1 ){digitalWrite(lamp2, LOW);flag2=0;}


}

void start(){
digitalWrite(lamp1, HIGH);
digitalWrite(lamp2, HIGH);
time1=millis();
flag1=1;
flag2=1;
}

void reo() {
reo1 = analogRead(A1);
reo2 = analogRead(A2);
reo1 = map(reo1, 0, 1023, 0, 14000);
reo2 = map(reo2, 0, 1023, 0, 14000);

}

 

svm
Offline
Зарегистрирован: 06.11.2016

А строки 39 и 40  нужны? И сответственно  проверка их и инвертирование флагов в 29 и 30 строках?

Ардуина не переломится если лишний раз выключит уже выключенный светодиод, а код будет лаконичней и понятней.

evgta
Offline
Зарегистрирован: 02.09.2016

это для тех кто кричит: аааа!!! процессорное времяяя, аааа!!!! зачем лишний раз тыкать пин)))

ну и соответственно все что в фунции reo() можно в start() перенести, но тогда считывание показаний резисторов будет раз в 15 секунд

subbotinHZ2
Offline
Зарегистрирован: 10.03.2018

Огромное спасибо за скетч. 

Все работает. 

Буду изучать программирование.

sadman41
Offline
Зарегистрирован: 19.10.2016

evgta пишет:

это для тех кто кричит: аааа!!! процессорное времяяя, аааа!!!! зачем лишний раз тыкать пин)))

А ежели пин отщелкнется? Лучше тыкать...

evgta
Offline
Зарегистрирован: 02.09.2016

специально для лучшего чтения


int reo1=0;
int reo2=0;
int Vr_zikl=15000; //время цикла
int Vr_reo=15000;  // максимальное время работы лампочки во ремя цикла

unsigned long time1 = 0;
unsigned long time2 = 0;
#define lamp1 2
#define lamp2 3


void setup() {
pinMode(A1, INPUT);
pinMode(A2, INPUT);
pinMode(2, OUTPUT);
pinMode(3, OUTPUT);  
digitalWrite(lamp1, LOW);
digitalWrite(lamp2, LOW);
start();

}

void loop() {

if (millis()-time1>=Vr_zikl){start();}
if (millis()-time1>=reo1){digitalWrite(lamp1, LOW);}
if (millis()-time1>=reo2){digitalWrite(lamp2, LOW);}

}

void start(){

reo1 = map(analogRead(A1), 0, 1023, 0, Vr_reo );
reo2 = map(analogRead(A2), 0, 1023, 0, Vr_reo); 

digitalWrite(lamp1, HIGH);
digitalWrite(lamp2, HIGH);

time1=millis();
}

subbotinHZ2
Offline
Зарегистрирован: 10.03.2018

Нечего писать. Круто. В нашей стране еще есть мозги.

Уважение.

Спасибо.

svm
Offline
Зарегистрирован: 06.11.2016

evgta пишет:

специально для лучшего чтения

Ну вот, совсем другое дело. А то как у Льва Толстого "Война и мир", читать задолбаешься и в конце уже не поймешь, зачем Анна Каренина Му- Му под поезд бросила.

И человеку помогли, теперь уже по другому будет смотреть на программирование,не просто копировать куски чужих скетчей, а сначала думать.

evgta
Offline
Зарегистрирован: 02.09.2016

но ведь не поберег проц время, луп и покороче мог быть. печалька((

svm
Offline
Зарегистрирован: 06.11.2016

evgta пишет:

но ведь не поберег проц время, луп и покороче мог быть. печалька((

Нормальный Луп

Японцы такие штуки Хокку называют.

sadman41
Offline
Зарегистрирован: 19.10.2016

А если ищщё вот так. Вроде ничего не напутал в ночи.

uint32_t reo1 = 0,
         reo2 = 0,
         Vr_zikl = 15000, //время цикла
         Vr_reo = 15000,  // максимальное время работы лампочки во ремя цикла
         time1 = 0,
         time2 = 0;

#define lamp1 2
#define lamp2 3

void setup() {
  pinMode(A1, INPUT);
  pinMode(A2, INPUT);
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  // На первом же проходе loop() сработает условие и вызовет start()
  time1 = Vr_zikl;
}

void loop() {
  digitalWrite(lamp1, !(millis() - time1 >= reo1));
  digitalWrite(lamp2, !(millis() - time1 >= reo2));
  if (millis() - time1 >= Vr_zikl) {
    reo1 = map(analogRead(A1), 0, 1023, 0, Vr_reo );
    reo2 = map(analogRead(A2), 0, 1023, 0, Vr_reo);
    time1 = millis();
  }
}

 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

sadman41, тогда уж убрать строки 6, 12 и 13, а в 14 и 15 использовать lamp*. 

uint32_t Vr_zikl = 15000, //время цикла
         Vr_reo = 15000,  // максимальное время работы лампочки во ремя цикла
         time1 = 0;

#define lamp1 2
#define lamp2 3

void setup() {
  pinMode(lamp1, OUTPUT);
  pinMode(lamp2, OUTPUT);
  // На первом же проходе loop() сработает условие и вызовет start()
  time1 = Vr_zikl;
}

void loop() {
  digitalWrite(lamp1, !(millis() - time1 >= map(analogRead(A1), 0, 1023, 0, Vr_reo )));
  digitalWrite(lamp2, !(millis() - time1 >= map(analogRead(A2), 0, 1023, 0, Vr_reo)));
  if (millis() - time1 >= Vr_zikl) {
    time1 = millis();
  }
}

Правда, немножко изменится поведение при вращении потенциометров - реакция ускорится вплоть до повторного открытия за один 15-секундный цикл.

sadman41
Offline
Зарегистрирован: 19.10.2016

А я не против. Но посчитал, что не очень правильно менять установки по ходу пьесы. Мало ли там чего задел случайно.

svm
Offline
Зарегистрирован: 06.11.2016

А если убрать лишние переменные, и заменить их просто числами, то будет еще лаконичнее:

uint32_t time1 = 15000;
#define lamp1 2
#define lamp2 3

void setup() {
  pinMode(lamp1, OUTPUT);
  pinMode(lamp2, OUTPUT);
}

void loop() {
  digitalWrite(lamp1, !(millis() - time1 >= map(analogRead(A1), 0, 1023, 0, 15000)));
  digitalWrite(lamp2, !(millis() - time1 >= map(analogRead(A2), 0, 1023, 0, 15000)));
  if (millis() - time1 >= 15000) {time1 = millis();}
}

Еще можно и дефайны убрать и выхода назначить через регистры и ничего от программы не останется.

sadman41
Offline
Зарегистрирован: 19.10.2016

Тогда уж лучше через дефайны 15000 задавать в мапе и условии. Иначе непонятно, что они значат.

 

svm
Offline
Зарегистрирован: 06.11.2016

Это я так просто, для того кто пишет программу все будет ясно, а остальным продется немного подумать.  

Ну а в принципе неплохая тема получилась и достаточно познавательная для начинающих. 

subbotinHZ2
Offline
Зарегистрирован: 10.03.2018

Спасибо за помощь. С Вашей помощью у меня все получилось. Силовую часть и ящик соберем и на испытания.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

svm пишет:

А если убрать лишние переменные, и заменить их просто числами, то будет еще лаконичнее:

Они не лишние.

Кроме того, в исходном коде было две разные константы (хотя почему-то они были объявлены равными, хотя по условию должны быть разными: 14000 и 15000). И это важно.

В общем, эти правки явно в ущерб исходнику.