проблема с счетчиком?

derenko2
Offline
Зарегистрирован: 22.05.2016

Доброго времени суток всем форумчанам.

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

Имеется ардуино мини про(точнее только жду с китая), автомобиль, и огромное желание сделать на нем автозапуск от штатной противоугонной системы. Логика работы в моем понимании такова - при  нажатии кнопки брелока  открытия автомобиля, на актюатор центрального замка приходит импульс не зависимо от того открыт автомобиль или нет. Трижды нажали - трижды сигнал. Так вот хотелось бы чтоб при троекратном нажатии в течении 10 секунд автомобиль заводился. Код автоматического закрытия уже заведенного авто добавлю позже. Сейчас больше интересует где я накосячил, что в протеусе  ничего не работает. Код взят с сайтов этого и этого.

 код выглядит вот так.


//v 22
//Настройки
unsigned long ENGINE_WARM_TIME = 1200000; //В миллисекундах время работы мотора после запуска 1200000 миллисекунд = 20 минут
int ENGINE_START_MAX_TIME = 5; //В секундах масимальное время работы стартера типично 3 -10 сек
const int  aktuatorPin = 4;    // контакт, к которому подсоединена кнопка

// Тут вписываем переменные – это меняющиеся значения:
int schetchiksignala = 0;   // счетчик количества срабатываний актюатора
int aktuatorState = 0;         // текущее состояние актюатора
int lastaktuatorState = 0;     // предыдущее состояние актюатора

// select pins for input
const int hand_brake_in  = 3;  //d3 adruino Контакт стояночного тормоза "-"
const int sharging_in  = 5;  //d5 adruino

const int sharging_on = 1; // 0 когда во время работы генератора или от датчика давления масла на этом входе низкое состояние , 1 когда на лампе генератора при работе генератора высокое состояние
const int hand_brake_on = 0; //  0= поднятый датчик ручника замыкает на массу тормоз активен (жигули), 1= датчик ручника в поднятом состоянии выдает высокий уровень напряжения

// select pins for output
const int starter_out  = 6;  //d6 adruino реле стартера
const int engine_out  = 7;  //d7 adruino зажигание
const int secpower_out  = 8;  //d8 цепи вторичного питания печка, фары итд
const int status_out  = 9;  //d9 светодиод статуса системы  горит = система готова к работе(включена, ручник стоит). одно мигание запущен с первой попытки 2 со второй 3 с третьей
//светодиод подключать с этого пина на массу через резистор



// variable for actual mode
int actual_mode = 0; //  2 engine started
int left_start_try = 0;  // переменная для хранения остатка числа попыток запуска
int start_in = 0; // переменная разрешения запуска
unsigned long last_start_time = 0; //время в тысячных секунды когда был запущен движок
unsigned long start_timer = 0;




void setup() {

  pinMode(aktuatorPin, INPUT);

  //---- настройка входов и выходов контроллера --------------
  // init selected pins
  pinMode(hand_brake_in, INPUT); // enable input
  //  digitalWrite(hand_brake_in, HIGH); //если подтяжка реализована аппаратно то тут ненадо

  pinMode(sharging_in, INPUT); // enable input
  //  digitalWrite(sharging_in, LOW); //generator LOW normaly

  // init outputs
  pinMode(starter_out, OUTPUT); // enable output
  digitalWrite(starter_out, LOW); //set digital 0

  pinMode(engine_out, OUTPUT); // enable output
  digitalWrite(engine_out, LOW); //set digital 0

  pinMode(secpower_out, OUTPUT); // enable output
  digitalWrite(secpower_out, LOW); //set digital 0

  pinMode(status_out, OUTPUT); // enable output
  digitalWrite(status_out, LOW); //set digital 0
  //---- конец настройки входов и выходов контроллера --------------


}


void loop()
{

  // считываем данные с входного «актюаторного» контакта:
  aktuatorState = digitalRead(aktuatorPin);

  // сравниваем текущее состояние (aktuatorState) с предыдущим:
  if (aktuatorState != lastaktuatorState) {
    // если состояние изменилось, увеличиваем значение счетчика:
    if (aktuatorState == HIGH) {
      schetchiksignala++;
      start_timer = millis(); //запоминаем время
    }
  }
  // для прогона через следующий цикл
  // делаем текущее состояние предыдущим

  lastaktuatorState = aktuatorState;
 // if (millis() > start_timer + 10 * 1000) // если текущее время больше чем первое нажатие + 10 секунд то обнуляем счетчик
  //{
    //schetchiksignala = 0;
  //}

    if (schetchiksignala % 3 == 0) {
    start_in = 1;
  } else {
   start_in = 0;
}
  


  //---- собственно это и есть весь код программы --------------
  if (actual_mode < 2 )    //если двигатель не запущен
    check_start();  //Управляем режимом запуска
  //код условия обязательно включать в фигурные скобки если должно быть выполнено несколько инструкций, в данном случае одна, поэтому скобки опущены

  else   // иначе
  {
    check_for_shutdown(); //Управляем режимом ожидания окончания прогрева
  } //но хорошая привычка фигурные скобки ставить всегда


  set_status_led(); //независимо от режима Управляем светодиодом статуса

  //------------------конец основного кода -----------------
}

//---- а дальше идут используемые функции и подфункции --------------

void check_start()
{
  if (start_in == 1 && left_start_try == 0) // 1 is command for start  - 1  значит импульс старта пришел с дистанционного управления <--- тут определяется полярность импульса запуска
  {
    left_start_try = 3;   // указываем что нужно попытаться трижды запустить движок
  }


  if ( left_start_try > 0 )
  {
    digitalWrite(engine_out, HIGH);   //включаем зажигание
    digitalWrite(secpower_out, HIGH); //включаем печку фары итд
    delay(3000); // останавливаем код на 3 секунды чтобы бензонасос набрал давление, все датчики включились

    if (digitalRead(hand_brake_in) != hand_brake_on) //без ручника не делаем запуск
    {
      actual_mode = 2; // заканчиваем попытки запустить движок
      left_start_try = 0; //без ручника другие попытки бесполезны
      return;
    }


    if (digitalRead(sharging_in) != sharging_on  )    // проверяем что генератор не работает
    {
      do_start(); // пытаемся запустить движок
      left_start_try = left_start_try - 1 ; //уменьшаем число попыток

      if (left_start_try == 0 )
        actual_mode = 2; // заканчиваем попытки запустить движок
    } // конец проверки что ручник стоит а генератор не работает
  }


} // конец процедуры старта


void do_start()
{
  //тут будет запуск движка
  //   digitalWrite(engine_out, HIGH);   //включаем зажигание
  //   digitalWrite(secpower_out, HIGH); //включаем печку фары итд
  //   delay(3000); // останавливаем код на 3 секунды чтобы бензонасос набрал давление

  digitalWrite(secpower_out, LOW); //выключаем печку фары итд

  //----------------------------------------------------------------------------------- цикл стартера
  digitalWrite(starter_out, HIGH); //включаем стартер
  for (int secs = 0; secs <= ENGINE_START_MAX_TIME ; secs++) //
  {
    delay(1000); // и продолжаем его держать включенным 1 секунду
    if (digitalRead(sharging_in) == sharging_on) //если зарядка пошла то
      break;  // прерываем цикл
  }
  //-----------------------------------------------------------------------------------
  digitalWrite(starter_out, LOW); //отключаем стартер

  if (digitalRead(sharging_in) == sharging_on) //еще раз смотрим что  зарядка пошла
  {
    actual_mode = 2; //Запоминаем что движок запущен
    last_start_time = millis(); // запоминаем время запуска движка
  }
  else
  {
    digitalWrite(engine_out, LOW);   //выключаем зажигание чтбы разблокировать реле стартера
    digitalWrite(secpower_out, LOW); //выключаем печку фары итд
    delay(5000); // останавливаем код на 3 секунды чтобы бензонасос набрал давление
  }


}


void check_for_shutdown()
{
  //сюда мы попадаем когда контроллер считает что движок работает

  if (digitalRead(sharging_in) != sharging_on  ) //проверяем что движок случайно не заглох
    do_shutdown();
  else
    digitalWrite(secpower_out, HIGH); //включаем печку фары итд

  if (digitalRead(hand_brake_in) != hand_brake_on  ) //проверяем что если злодеи сняли с ручника то глушим мотор
  {
    do_shutdown();
    left_start_try = 0; // и больше не заводим
  }

  //тут будем контролировать чтоб если забыли машинку заведенной она не молотила до скончания бензобака а выключалась через какоето время


  if (actual_mode != 0  ) //значит не выключили заглохший двигатель только что
  {

    // милисекунды в ардуино обнуляются каждые 49 суток
    // для того чтобы в случае если запуск произошел в течении последних 20 минут до обнуления мотор не молотил еще 49 суток
    //  нужно обнулить и время старта, при этом мотор максимум будет прогреваться вдвое больше обычного
    if (millis() < last_start_time)
    {
      last_start_time = 0;
    }


    if (millis() > last_start_time + ENGINE_WARM_TIME) // если текущее время больше чем время старта + время прогрева
    {
      do_shutdown();
      left_start_try = 0; // и больше не заводим
    }
  }
}



void do_shutdown()
{
  digitalWrite(secpower_out, LOW); //выключаем печку фары итд
  digitalWrite(engine_out, LOW); //вырубаем зажигание
  actual_mode = 0;  // движок выключили запомним это
  last_start_time = 0; // ну и забудем о том что он был включен
}


void set_status_led()
{
  if (digitalRead(hand_brake_in) != hand_brake_on  ) //Если ручник не стоит то выкл светодиод нечего ему в пути мигать попусту
  {
    digitalWrite(status_out, LOW);
    return; //прерываем выполнение функции
  }

  if (actual_mode ==  2) //Движок запущен
    status_led_flash(); // показываем с какой попытки был прошлый запуск
  else
    digitalWrite(status_out, HIGH); // постоянное свечение - показываем что готов к следующему запуску

}



void status_led_flash()
{
  static unsigned long big_interval = 0;
  static unsigned long flash_interval = 0;
  unsigned long flash_count = 0;
  flash_count = 3 - left_start_try;  //сколько раз мигать


  //1 секндный интервал
  if (millis() > flash_interval + 1000L)
    flash_interval = millis() ; //задаем счетчие от 0 до 1 секунды

  //задаем 6 секунд
  if (millis() > big_interval + 6000L)
  {
    big_interval = millis() ;  //задаем счетчие от 0 до 10секунд
    flash_interval = big_interval;
  }



  if (millis() <  big_interval +  flash_count * 1000L) // делим 6 секндный интервал на два периода, в первый мигаем количество раз соответствующее числу израсходованных попыток
  { //мигает
    if (millis() > flash_interval + 500L)
      digitalWrite(status_out, HIGH);
    else
      digitalWrite(status_out, LOW);

  }
  else
  { // негорит
    digitalWrite(status_out, LOW); //set digital 0
  }
}

Это мое первое знакомство с ардуино и с програмированием (разве что basic немного помню со школы :-)). Учится и читать готов. просьба толкнуть в нужном направлении.

derenko2
Offline
Зарегистрирован: 22.05.2016

предполагаю что косяк со счетчиком в строках с 70 по 95. Или его применением в дальнейшем. Проблема еще и в том что самой ардуинки еще нет и мог накосячить в протеусе. Проект протеуса тут.

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

Я не разбираюсь в логике запуска автомобиля, потому по сути сказать ничего не могу, но хочу предостеречь от очень неаккуратного кода. Он у Вас повторяется много раз (строки 264, 268, 278 и может ещё где). Вы пишете

if (millis() > flash_interval + 1000L)

так нельзя!

Если Вам нужно отработать задержку, то писать нужно:

if (millis() - flash_interval > 1000L)

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

Даже если конкретно-данный скетч и не предполагается к работе месяцами без остановки, просто привыкайте писать правильно. Это должно быть на рефлексах. А то когда-нибудь напишете так не задумываясь, а оно подведёт.

derenko2
Offline
Зарегистрирован: 22.05.2016

признаться пока не понял в чем принципиальное отличие, но обязательно исправлю и попробую разобраться. Спасибо.

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

derenko2 пишет:

признаться пока не понял в чем принципиальное отличие

Так, как у Вас написано, отсчёт интервала будет сбиваться при переполнении millis(), т.е. когда она достигнет максимального значения и станет снова нулём. А так, как я написал - пофиг, пусть переполняется, всё отработает нормально.

derenko2
Offline
Зарегистрирован: 22.05.2016

да и попробую описать логику запуска авто.

приходит три сигнала (+12v приведу к 5v через делитель) в течении 10с на actuator_pin (если интервал больше 10с то счетчик schetchiksignala обнуляется).  Контроллер проверяет наличие 0v на пине hand_brake_in( ручник натянут) и наличие 0v на пине sharging_in (нет зарядки - двигатель заглушен). если условия выполненны то подается +5 на engine_out (зажигание), +5 на secpower_out (доп оборудование) и после паузы +5 на starter_out (стартер). стартер крутит секунду - мониторит наличие зарядки, и если она появляется то прокрутка стартером прекращается. если не появляется то крутим три секунды и останов. затем еще две попытки и если запуск не прошел то окончательно отключаемся.  это вкратце. но при симулировании на протеусе ничего не происходит. сечас читаю как прикрутить в протеусе терминал к ардуине, внести в код принты на терминал и может тогда разберусь что к чему... В общем буду благодарен любой подсказке.

derenko2
Offline
Зарегистрирован: 22.05.2016

ЕвгенийП пишет:

Так, как у Вас написано, отсчёт интервала будет сбиваться при переполнении millis(), т.е. когда она достигнет максимального значения и станет снова нулём. А так, как я написал - пофиг, пусть переполняется, всё отработает нормально.

ТОЧНО! Огромное спасибо! уже переделываю!

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

Даю кстати, если уж у нас сравнение беззнаковых чисел, то и константу надо писать беззнаковую. т.е. не

if (millis() - flash_interval > 1000L)

а

if (millis() - flash_interval > 1000UL)

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

 

derenko2
Offline
Зарегистрирован: 22.05.2016

в общем не верные настройки были в протеусе. Сейчас схема начала отрабатывать, но пока не совсем адекватно. Как говорится с таким кодом авто не заглушишь. отпустил ручник - заглохла, поднял - опять заводится. Буду дальше разбираться. Как разберусь выложу результат.

derenko2
Offline
Зарегистрирован: 22.05.2016

УРА!!! Заработало!!! Пока правда в протеусе. Исправил пару опечаток и добавил терминал чтобы вкурить где косяки. По сути код терминала можно снести это одна из попыток анализа осталась. (хотя и рабочая). Итог можно поставить практически на любой авто со штатной сигналкой автозапуск. Нужны сигнал зарядки, ручника, и актюатора центрального замка. осталось придумать как переделать проводку для замыкания авто после запуска и разрешение для запуска хочу переделать на тахометр (подсчет кол-ва оборотов и если выше 500 то запуск). В общем работы еще много.


//v 22
//Настройки
unsigned long ENGINE_WARM_TIME = 1200000; //В миллисекундах время работы мотора после запуска 1200000 миллисекунд = 20 минут
int ENGINE_START_MAX_TIME = 5; //В секундах масимальное время работы стартера типично 3 -10 сек
const int  aktuatorPin = 4;    // контакт, к которому подсоединена кнопка

// Тут вписываем переменные – это меняющиеся значения:
int schetchiksignala = 0;   // счетчик количества срабатываний актюатора
int aktuatorState = 0;         // текущее состояние актюатора
int lastaktuatorState = 0;     // предыдущее состояние актюатора

// select pins for input
const int hand_brake_in  = 3;  //d3 adruino Контакт стояночного тормоза "-"
const int sharging_in  = 5;  //d5 adruino

const int sharging_on = 1; // 0 когда во время работы генератора или от датчика давления масла на этом входе низкое состояние , 1 когда на лампе генератора при работе генератора высокое состояние
const int hand_brake_on = 0; //  0= поднятый датчик ручника замыкает на массу тормоз активен (жигули), 1= датчик ручника в поднятом состоянии выдает высокий уровень напряжения

// select pins for output
const int starter_out  = 6;  //d6 adruino реле стартера
const int engine_out  = 7;  //d7 adruino зажигание
const int secpower_out  = 8;  //d8 цепи вторичного питания печка, фары итд
const int status_out  = 9;  //d9 светодиод статуса системы  горит = система готова к работе(включена, ручник стоит). одно мигание запущен с первой попытки 2 со второй 3 с третьей
//светодиод подключать с этого пина на массу через резистор



// variable for actual mode
int actual_mode = 0; //  2 engine started
int left_start_try = 0;  // переменная для хранения остатка числа попыток запуска
int start_in = 0; // переменная разрешения запуска
unsigned long last_start_time = 0; //время в тысячных секунды когда был запущен движок
unsigned long start_timer = 0;




void setup() {
  
 Serial.begin(9600);
  pinMode(aktuatorPin, INPUT);

  //---- настройка входов и выходов контроллера --------------
  // init selected pins
  pinMode(hand_brake_in, INPUT); // enable input
  //  digitalWrite(hand_brake_in, HIGH); //если подтяжка реализована аппаратно то тут ненадо

  pinMode(sharging_in, INPUT); // enable input
  //  digitalWrite(sharging_in, LOW); //generator LOW normaly

  // init outputs
  pinMode(starter_out, OUTPUT); // enable output
  digitalWrite(starter_out, LOW); //set digital 0

  pinMode(engine_out, OUTPUT); // enable output
  digitalWrite(engine_out, LOW); //set digital 0

  pinMode(secpower_out, OUTPUT); // enable output
  digitalWrite(secpower_out, LOW); //set digital 0

  pinMode(status_out, OUTPUT); // enable output
  digitalWrite(status_out, LOW); //set digital 0
  //---- конец настройки входов и выходов контроллера --------------


}


void loop()
{
  
  // считываем данные с входного «актюаторного» контакта:
  aktuatorState = digitalRead(aktuatorPin);

  // сравниваем текущее состояние (aktuatorState) с предыдущим:
  if (aktuatorState != lastaktuatorState) {
    // если состояние изменилось, увеличиваем значение счетчика:
    if (aktuatorState == HIGH) {
      schetchiksignala++;
      start_timer = millis(); //запоминаем время
  Serial.print (schetchiksignala);
    }
    
  }
  // для прогона через следующий цикл
  // делаем текущее состояние предыдущим

  lastaktuatorState = aktuatorState;
 if (millis() - start_timer > 10 * 1000) // если текущее время больше чем первое нажатие + 10 секунд то обнуляем счетчик
  {
    schetchiksignala = 0;
  }

    if (schetchiksignala == 3) {
    start_in = 1;
  } else {
   start_in = 0;
}
Serial.print ("razr");
   Serial.print( start_in);


  //---- собственно это и есть весь код программы --------------
  if (actual_mode < 2 )    //если двигатель не запущен
    check_start();  //Управляем режимом запуска
  //код условия обязательно включать в фигурные скобки если должно быть выполнено несколько инструкций, в данном случае одна, поэтому скобки опущены

  else   // иначе
  {
    check_for_shutdown(); //Управляем режимом ожидания окончания прогрева
  } //но хорошая привычка фигурные скобки ставить всегда


  set_status_led(); //независимо от режима Управляем светодиодом статуса

  //------------------конец основного кода -----------------
}





//---- а дальше идут используемые функции и подфункции --------------

void check_start()
{
  if (start_in == 1 && left_start_try == 0) // 1 is command for start  - 1  значит импульс старта пришел с дистанционного управления <--- тут определяется полярность импульса запуска
  {
    left_start_try = 3;   // указываем что нужно попытаться трижды запустить движок
  }


  if ( left_start_try > 0 )
  {
    digitalWrite(engine_out, HIGH);   //включаем зажигание
    digitalWrite(secpower_out, HIGH); //включаем печку фары итд
    delay(3000); // останавливаем код на 3 секунды чтобы бензонасос набрал давление, все датчики включились

    if (digitalRead(hand_brake_in) != hand_brake_on) //без ручника не делаем запуск
    {
      actual_mode = 2; // заканчиваем попытки запустить движок
      left_start_try = 0; //без ручника другие попытки бесполезны
      return;
    }


    if (digitalRead(sharging_in) != sharging_on  )    // проверяем что генератор не работает
    {
      do_start(); // пытаемся запустить движок
      left_start_try = left_start_try - 1 ; //уменьшаем число попыток

      if (left_start_try == 0 )
        actual_mode = 2; // заканчиваем попытки запустить движок
    } // конец проверки что ручник стоит а генератор не работает
  }


} // конец процедуры старта


void do_start()
{
  //тут будет запуск движка
  //   digitalWrite(engine_out, HIGH);   //включаем зажигание
  //   digitalWrite(secpower_out, HIGH); //включаем печку фары итд
  //   delay(3000); // останавливаем код на 3 секунды чтобы бензонасос набрал давление

  digitalWrite(secpower_out, LOW); //выключаем печку фары итд

  //----------------------------------------------------------------------------------- цикл стартера
  digitalWrite(starter_out, HIGH); //включаем стартер
  for (int secs = 0; secs <= ENGINE_START_MAX_TIME ; secs++) //
  {
    delay(1000); // и продолжаем его держать включенным 1 секунду
    if (digitalRead(sharging_in) == sharging_on) //если зарядка пошла то
      break;  // прерываем цикл
  }
  //-----------------------------------------------------------------------------------
  digitalWrite(starter_out, LOW); //отключаем стартер

  if (digitalRead(sharging_in) == sharging_on) //еще раз смотрим что  зарядка пошла
  {
    actual_mode = 2; //Запоминаем что движок запущен
    last_start_time = millis(); // запоминаем время запуска движка
  }
  else
  {
    digitalWrite(engine_out, LOW);   //выключаем зажигание чтбы разблокировать реле стартера
    digitalWrite(secpower_out, LOW); //выключаем печку фары итд
    delay(5000); // останавливаем код на 3 секунды чтобы бензонасос набрал давление
  }


}









void check_for_shutdown()
{
  //сюда мы попадаем когда контроллер считает что движок работает

  if (digitalRead(sharging_in) != sharging_on  ) //проверяем что движок случайно не заглох
    do_shutdown();
  else
    digitalWrite(secpower_out, HIGH); //включаем печку фары итд

  if (digitalRead(hand_brake_in) != hand_brake_on  ) //проверяем что если злодеи сняли с ручника то глушим мотор
  {
    do_shutdown();
    left_start_try = 0; // и больше не заводим
  }

  //тут будем контролировать чтоб если забыли машинку заведенной она не молотила до скончания бензобака а выключалась через какоето время


  if (actual_mode != 0  ) //значит не выключили заглохший двигатель только что
  {

    // милисекунды в ардуино обнуляются каждые 49 суток
    // для того чтобы в случае если запуск произошел в течении последних 20 минут до обнуления мотор не молотил еще 49 суток
    //  нужно обнулить и время старта, при этом мотор максимум будет прогреваться вдвое больше обычного
    if (millis() < last_start_time)
    {
      last_start_time = 0;
    }


    if (millis() > last_start_time + ENGINE_WARM_TIME) // если текущее время больше чем время старта + время прогрева
    {
      do_shutdown();
      left_start_try = 0; // и больше не заводим
    }
  }
}



void do_shutdown()
{
  digitalWrite(secpower_out, LOW); //выключаем печку фары итд
  digitalWrite(engine_out, LOW); //вырубаем зажигание
  actual_mode = 0;  // движок выключили запомним это
  last_start_time = 0; // ну и забудем о том что он был включен
}


void set_status_led()
{
  if (digitalRead(hand_brake_in) != hand_brake_on  ) //Если ручник не стоит то выкл светодиод нечего ему в пути мигать попусту
  {
    digitalWrite(status_out, LOW);
    return; //прерываем выполнение функции
  }

  if (actual_mode ==  2) //Движок запущен
    status_led_flash(); // показываем с какой попытки был прошлый запуск
  else
    digitalWrite(status_out, HIGH); // постоянное свечение - показываем что готов к следующему запуску

}



void status_led_flash()
{
  static unsigned long big_interval = 0;
  static unsigned long flash_interval = 0;
  unsigned long flash_count = 0;
  flash_count = 3 - left_start_try;  //сколько раз мигать


  //1 секндный интервал
  if (millis() - flash_interval > 1000UL)
    flash_interval = millis() ; //задаем счетчие от 0 до 1 секунды

  //задаем 6 секунд
  if (millis() - big_interval > 6000L)
  {
    big_interval = millis() ;  //задаем счетчие от 0 до 10секунд
    flash_interval = big_interval;
  }



  if (millis() -  big_interval +  flash_count > 1000UL) // делим 6 секндный интервал на два периода, в первый мигаем количество раз соответствующее числу израсходованных попыток
  { //мигает
    if (millis() - flash_interval > 500L)
      digitalWrite(status_out, HIGH);
    else
      digitalWrite(status_out, LOW);

  }
  else
  { // не горит
    digitalWrite(status_out, LOW); //set digital 0
  }
}