Проблема управления 28 реле

ARXAIL
Offline
Зарегистрирован: 31.03.2022
arduino2560 (no origin)
28 реле - 14 на впуск воздуха и 14 на выпуск

Всем привет! У меня все просто таймер считает 1 секунду и потом  timerCount2 инкрементирует их.Дальше я сравниваю этот счетчик и управляю нужными портами. Проблема в том, что timerCount2 сбрасывается и у меня цикл не отрабатывает полностью и я не знаю почему





// ports of valves
int valves[] = {22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49};


//timer's counter
volatile int timerCount2 = 0;   // считаем прерывания таймера одно прерывание в секунду

void setup() {
  //valves
  pinMode(valves[0], OUTPUT);
  pinMode(valves[1], OUTPUT);
  pinMode(valves[2], OUTPUT);
  pinMode(valves[3], OUTPUT);
  pinMode(valves[4], OUTPUT);
  pinMode(valves[5], OUTPUT);
  pinMode(valves[6], OUTPUT);
  pinMode(valves[7], OUTPUT);
  pinMode(valves[8], OUTPUT);
  pinMode(valves[9], OUTPUT);
  pinMode(valves[10], OUTPUT);
  pinMode(valves[11], OUTPUT);
  pinMode(valves[12], OUTPUT);
  pinMode(valves[13], OUTPUT);
  pinMode(valves[14], OUTPUT);
  pinMode(valves[15], OUTPUT);
  pinMode(valves[16], OUTPUT);
  pinMode(valves[17], OUTPUT);
  pinMode(valves[18], OUTPUT);
  pinMode(valves[19], OUTPUT);
  pinMode(valves[20], OUTPUT);
  pinMode(valves[21], OUTPUT);
  pinMode(valves[22], OUTPUT);
  pinMode(valves[23], OUTPUT);
  pinMode(valves[24], OUTPUT);
  pinMode(valves[25], OUTPUT);
  pinMode(valves[26], OUTPUT);
  pinMode(valves[27], OUTPUT);

  digitalWrite(valves[0], HIGH);
  digitalWrite(valves[1], HIGH);
  digitalWrite(valves[2], HIGH);
  digitalWrite(valves[3], HIGH);
  digitalWrite(valves[4], HIGH);
  digitalWrite(valves[5], HIGH);
  digitalWrite(valves[6], HIGH);
  digitalWrite(valves[7], HIGH);
  digitalWrite(valves[8], HIGH);
  digitalWrite(valves[9], HIGH);
  digitalWrite(valves[10], HIGH);
  digitalWrite(valves[11], HIGH);
  digitalWrite(valves[12], HIGH);
  digitalWrite(valves[13], HIGH);
  digitalWrite(valves[14], HIGH);
  digitalWrite(valves[15], HIGH);
  digitalWrite(valves[16], HIGH);
  digitalWrite(valves[17], HIGH);
  digitalWrite(valves[18], HIGH);
  digitalWrite(valves[19], HIGH);
  digitalWrite(valves[20], HIGH);
  digitalWrite(valves[21], HIGH);
  digitalWrite(valves[22], HIGH);
  digitalWrite(valves[23], HIGH);
  digitalWrite(valves[24], HIGH);
  digitalWrite(valves[25], HIGH);
  digitalWrite(valves[26], HIGH);
  digitalWrite(valves[27], HIGH);

  //Timers
  noInterrupts();                      // отключаем все прерывания

  TCCR3A = 0;
  TCCR3B = 0;
  OCR3A = 15624;                      // счетчик по совпадению 1 секунду отсчитываем
  TCCR3B |= (1 << WGM12);
  TCCR3B |= (1 << CS10) | (1 << CS12);  // 1024 (коэффициент деления предделителя)
  TIMSK3 |= (1 << OCIE3A);     // устанавливаем бит разрешения прерывания 1ого счетчика по совпадению с OCR1A(H и L)устанавливаем бит разрешения прерывания 1ого счетчика по совпадению с OCR1A(H и L)

  interrupts();
}

void loop() {
}


void processSections(boolean even, boolean in, boolean out) {   // функция принимает первый параметр четные или не четные секции : 2 параметр это вкл впускной клапан 3
  if (even) {
    for (int i = 2; i < 26; i = i + 4 ) {
      processing1Section(in, out, i);
    }
  }
  if (!even) {
    for (int i = 4; i < 26; i = i + 4 ) {
      processing1Section(in, out, i);
    }
  }

}

void processing1Section(boolean in, boolean out, int section) {
  if (in && !out) {
    digitalWrite(valves[section], LOW);
    digitalWrite(valves[section + 1], HIGH);
  }
  if (out && !in) {
    digitalWrite(valves[section], HIGH);
    digitalWrite(valves[section + 1], LOW);
  }

  if (!in && !out) {
    digitalWrite(valves[section], HIGH);
    digitalWrite(valves[section + 1], HIGH);
  }
}

//to process interrupt of timers
ISR(TIMER3_COMPA_vect) {
  TIMSK3 |= (0 << OCIE3A);
  timerCount2++;
  hardCode();
  TIMSK3 |= (1 << OCIE3A);
}

void hardCode() {
  if (timerCount2 == 5) {   // первая секция впуск
    processing1Section(true, false, 0);
  }

  if (timerCount2 == 20) { // не четные секции впуск
    processSections(false, true, false);
  }

  if (timerCount2 == 30) {
    
    processSections(true, true, false); // четные секции впуск
    processSections(false, false, false);  // не четные секции стоп
    processing1Section(false, false, 0); // первая секция стоп
    
  }

  if (timerCount2 == 40) {     // четные секции стоп
    
    processSections(true, false, false);
   
  }

  // процесс спуска


  if (timerCount2 == 50) {   // спускаем четные секции
    
    processSections(true, false, true);
    
  }

  if (timerCount2 == 65) {   // первая секции выпуск и вкл разгибатель
   
    processing1Section(false, true, 0);
    processing1Section(true, false, 26); // разгибатель вкл
    
  }

  if (timerCount2 == 70) {    // спускаем не четные секции

    
    processSections(false, false, true);
    

  }

  if (timerCount2 == 75) {    // спускаем не четные секции

    
    processing1Section(false, true, 26); // разгибатель спуск
    

  }

  if (timerCount2 == 90) {
    
    processSections(true, false, false);  // четные секции стоп
    processSections(false, false, false); // не четные секции стоп
    processing1Section(false, false, 26); // разгибатель стоп
    processing1Section(false, false, 0);
    timerCount2 = 0;
    
  }
}

 

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

В 15 строке:

volatile uint32_t timerCount2 = 0;

не?

Я, наверное, опять вопрос не понял....

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

Мне кажется, вы слишком много запихнули в прерывание.

128 строку убрать из прерывания, а hardCode() воткнуть в loop()

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

А еще с 19 строки по 46 проще записать так:

  for (uint8_t i = 0; i < 28; i++) {
    pinMode(valves[i], OUTPUT);
  }

А с 48 по 75 так:

  for (uint8_t i = 0; i < 28; i++) {
    digitalWrite(valves[i], HIGH);
  }

 

ARXAIL
Offline
Зарегистрирован: 31.03.2022

у меня loop  пустой наверное без разницы сколько в прерывании кода

ARXAIL
Offline
Зарегистрирован: 31.03.2022

а в чем разница между int и uint32/8_t ?

 

Upper
Offline
Зарегистрирован: 23.06.2020

Если есть возможность, добавьте вывод в Serial для отладки.

Например

- сообщение при старте, - может быть МК перезагружается от срабатывания реле.

- Сообщение при сбросе счетчика, чтобы понять когда он сбрасывается

И т.д.

 

v258
v258 аватар
Offline
Зарегистрирован: 25.05.2020

ARXAIL пишет:

у меня loop  пустой наверное без разницы сколько в прерывании кода

Нет, в прерывании много кода - есть очень, очень плохо

fogary
Offline
Зарегистрирован: 05.03.2016

BOOM пишет:

А еще с 19 строки по 46 проще записать так:

  for (uint8_t i = 0; i < 28; i++) {
    pinMode(valves[i], OUTPUT);
  }

А с 48 по 75 так:

  for (uint8_t i = 0; i < 28; i++) {
    digitalWrite(valves[i], HIGH);
  }

Почему Вы решили написать два цикла вместо одного?

_Igor_
Offline
Зарегистрирован: 10.01.2022

Думаю где то здесь

  TIMSK3 |= (0 << OCIE3A);
  timerCount2++;
  hardCode();
  TIMSK3 |= (1 << OCIE3A);
 
Upper
Offline
Зарегистрирован: 23.06.2020

_Igor_ пишет:

Думаю где то здесь

  TIMSK3 |= (0 << OCIE3A);
  timerCount2++;
  hardCode();
  TIMSK3 |= (1 << OCIE3A);
 

Здесь верхняя и нижняя строка просто лишние (а верхняя и с ошибкой), но вреда от них быть не должно.

_Igor_
Offline
Зарегистрирован: 10.01.2022
  TCCR3B = 0; !!!!!!!!!!!!!!!
BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

ARXAIL пишет:

а в чем разница между int и uint32/8_t ?

int - 2 байта, знаковый

uint8_t - 1 байт беззнаковый

uint32_t - 4 байта беззнаковый

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

ARXAIL пишет:

у меня loop  пустой наверное без разницы сколько в прерывании кода

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

_Igor_
Offline
Зарегистрирован: 10.01.2022

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

Это где написано? И откуда оно берется? 

_Igor_
Offline
Зарегистрирован: 10.01.2022

TCCR3B = 0; - таймер остановлен

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

_Igor_ пишет:

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

Это где написано? И откуда оно берется? 

это обыкновенный здравый смысл. Даже в "пустом" ардуино коде "за сценой" постоянно выполняются разные процедуры, самый простой пример - обновление миллис

Если код вашего прерывания длится дольше одного периода миллис - системные часы начнут отставать

да и вообще. идея запихать всю программу в прерывание - это худшей степени гавнокод

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

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

_Igor_ пишет:

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

Это где написано? И откуда оно берется? 

Ну обычно нигде не написано что нельзя гадить не снимая штанов. Довод что звери тоже гадят не снимая штанов не довод. Так как звери обычно штаны не носят. 

 Вот так и с прерыванием. Это такие же "штаны". У нормальных людей и в нормальных ситуациях на отработку прерываний отводится минимальное время, а основную работу делают в основном цикле. Но если кому-то хочется носить какахи в штанах, так в мире "дерьмократия".

_Igor_
Offline
Зарегистрирован: 10.01.2022

Я на слова "отводится ограниченное время" - спросил сколько? Поскольку такого нет. Учить как писать программы - это хорошо. Но если человеку не надо миллис - у него свое время и если кроме вкл-выкл через некоторые промежутки времени ничего делать не надо - можно и в ISR все вставить. Вам шашечки или ехать? если кто то докажет что этот код работать не будет - сниму шляпу.  Какая программа самая лучшая - ответ "работающая"... Боязнь что то пропустить во время ISR - это когда действительно есть что пропустить... А здесь нет. А тем кто претендует на написание НЕ говнокода и гадит снимая штаны - предлагаю выставить здесь ваши работы. Поучимся...

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

"отводится ограниченное время" это не больше 1% работы процессора, а лучше уложиться в 100 машинных команд.  Ведь вам не понравится, если Вы наняли работника. А он вместо работы трендит по мобилке и устраивает перекуры. Прерывания это оно и есть. И если вся работа это сплошные прерывания, то это не правильно построенная работа.

В этой задаче в прерывании нужно взвести флаг, а вот в основном цикле сделать всю операцию и сбросить этот флаг. И штаны будут чистые. И какахи в строго отведенном для этого месте.  https://habr.com/ru/post/453276/

ПС: А ТС пусть сначала помигает светодиодиком по таймеру, а потом уже начнет подключать реле по чуть чуть.

_Igor_
Offline
Зарегистрирован: 10.01.2022

Академические знания никто не отменял. Да, если читать лекции по программированию - вы правы. Но только почему не 0.1 и не 50? Да и конкретная реализация не обязательно требует АБСОЛЮТНО придерживаться эмпирических знаний. Мы здесь о конкретной задаче, а не при теорию. Кстати, мне приходилось писать программы в которых main - это halt. Только обработчики прерываний. И ничего - чудненько работали. Ну правда на ассемблере.

_Igor_
Offline
Зарегистрирован: 10.01.2022

А по ссылке - НИКАКИХ флагов не нашел !!!!!!!!!!!!!!!!!!!!!!!!!!

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

_Igor_ пишет:

Мы здесь о конкретной задаче, а не при теорию. Кстати, мне приходилось писать программы в которых main - это halt. Только обработчики прерываний. И ничего - чудненько работали. Ну правда на ассемблере.

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

_Igor_, вы зачем-то лезете в бутылку и пытаетесь доказать мысль "говнокод тоже иногда работает". С этим никто не спорит. Но обсуждать подобное на форуме нет ни малейшего смысла. Мы тут не делимся друг с другом "конкретными решениями" задач, ибо это нафик никому не нужно.

Если что и интересно обсудить, то это как ту или иную задачу решить либо ПРАВИЛЬНО, либо КРАСИВО.

-NMi-
Offline
Зарегистрирован: 20.08.2018

Main {
Di
Halt}
На спекки это бы было круто!!!

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Я могу говорить только за себя - в среде ардуино «не канает долгое прерывание». Уж не знаю почему, я только учусь и в код иде не лез, но солидарен с утверждением, что прерывание - на то и прерывание, что чтобы сделать сейчас незамедлительно и быстро и вернуться к выполнению основной программы. Я больше чем уверен, что даже в ОС прерывания не выполняют основной код. Нажали кнопку - поехали дальше. Все.

Green
Offline
Зарегистрирован: 01.10.2015

Ну, а если пофантазировать...  Или только строем?

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Green пишет:

Ну, а если пофантазировать...  Или только строем?

«Все в твоих руках» ))

Green
Offline
Зарегистрирован: 01.10.2015

"Да чё тут думать! Трясти надо."

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

BOOM пишет:

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

нет, НО ТАМ ЕСТЬ ПРИОРИТЕТЫ, вообще то вся ось от одное сплошное прерывание INT21h )))

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

А если по-нашему, по деревенски. Так прерывания здесь и вообще не нужны. Скорости не те.

То ТС - Напишите НОРМАЛЬНУЮ программу, которую Вы понимаете, а ни этот шмундяк.

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

ARXAIL пишет:
 


//to process interrupt of timers
ISR(TIMER3_COMPA_vect) {
  TIMSK3 |= (0 << OCIE3A);
  timerCount2++;
  hardCode();
  TIMSK3 |= (1 << OCIE3A);
}

Просто идеально, учитывая, что из hardCode() вызывается функция.

nik182
Offline
Зарегистрирован: 04.05.2015

Ой да ладно. Это же МК а не ОС на ББ. Тут собственно крутится одна задача и ей до лампочки где выполныться в основном цикле или в прерывании. Я вобщем тоже за минимум в прерывании и флаги. Но это когда задач много и они боряься за такты процессора. Если задач мало и они не требуют РТ, то можно и постебаться с наполненим разных частей программы. Работает - не трожь! Главное правило.

v258
v258 аватар
Offline
Зарегистрирован: 25.05.2020

nik182 пишет:
Работает - не трожь! Главное правило.

Дык, не работает жи )))

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

v258 пишет:

nik182 пишет:
Работает - не трожь! Главное правило.

Дык, не работает жи )))

Не работает, не трогай. Купи готовое решение от китайцев.

nik182
Offline
Зарегистрирован: 04.05.2015

v258 пишет:

nik182 пишет:
Работает - не трожь! Главное правило.

Дык, не работает жи )))

Каюсь, не до объяснил. Это относится не к этой программе, а к работающей программе с обработкой в прерывании. Если работает и не глючит, то пусть работает, не надо переписывать на короткие прерывания и флаги.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Почитаю :-)

-NMi-
Offline
Зарегистрирован: 20.08.2018

ua6em пишет:

вообще то вся ось от одное сплошное прерывание INT21h )))

Данунах...

SLKH
Offline
Зарегистрирован: 17.08.2015

BOOM пишет:

А еще с 19 строки по 46 проще записать так:

  for (uint8_t i = 0; i < 28; i++) {
    pinMode(valves[i], OUTPUT);
  }

А с 48 по 75 так:

  for (uint8_t i = 0; i < 28; i++) {
    digitalWrite(valves[i], HIGH);
  }

 

а на кой 2 цикла?



for (uint8_t i = 0; i < 28; i++) 
{
   pinMode(valves[i], OUTPUT);
   digitalWrite(valves[i], HIGH);
}