Отредактировать код, который работает :)

kak-dela007@mail.ru
Offline
Зарегистрирован: 28.12.2016

Строю контроллер RC-самолета для дополнительных функцй (для не входящих в автопилот)
Что он должен делать  (всё уже работает, но с огрехами):
- Управлять форсажем электро-турбины (не зависимо от switch)
- Управлять двумя эл. приводами (второй включается с задержкой после первого) (когда switch == LOW)
- Уплавлять релле спуска (6 шт) параллельно еще с одним релле  (когда switch == HIGH)
(это все его функуции)

Скетч целиком 
 

#include <Servo.h>  //Подключение библиотеки Сервы

Servo fuelServo; // Объявляем имя сервы

#define rcPin1 8   // Pin 8 Connected to CH1 - порог уровня оборотов
#define rcPin2 9   // Pin 9 Connected to CH2 - обороты
#define tataPin 10  // Спуск, соединяется с приемником
#define switPin 11  // Переключение спуска, соед с приемником

/////////////////////////////Пины пуска \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

#define AirsoftPin1 7
#define AirsoftPin2 12

////////////////////////////Пины пуска_2\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

#define ledPinRok 13  // Пин спуска, (!!!как сниму со стенда, поменять на 4!!! )

#define RokPin0 14
#define RokPin1 15
#define RokPin2 16 // Пины релле спуска
#define RokPin3 17
#define RokPin4 18
#define RokPin5 19

#define servoPin 6 // назначае пин сервы

#define flame 2 //датчик пламени

const int ledPin =  5;      // номер выхода, подключенного к зажиганию
int ledState = LOW;             // этой переменной устанавливаем состояние зажигания
long previousMillis = 0;        // храним время последнего переключения зажигания
long interval = 2000;           // интервал между включение/выключением зажигания
long previousMillisTata = 0;        // храним время последнего переключения зажигания (Эйрсофт)
long interval_asinc = 50;           // интервал между включение/выключением зажигания
int i = 0; //  Переменная запоминает было ли включение зажигания
static int One = 0; //Переменная для совершения цикла зажигания один раз

int ledStateRok = LOW;             // Переменная  спуска
long interval_Rok = 2000;           // интервал спуска
long previousMillisRok = 0;        // храним время последнего спуска
int RS = 0; //Переменая для работы спуска
static int OneRok = 0; //Переменная для совершения цикла спуска один раз

int gun1 = LOW; // Переменная первого привода
int gun2 = LOW;  //Переменная второго привода

int Rok0 = LOW;
int Rok1 = LOW;
int Rok2 = LOW;  // переменные состояния релле спуска
int Rok3 = LOW;
int Rok4 = LOW;
int Rok5 = LOW;


int ch1 = 0;  // Receiver Channel 1 PPM value (переменая порога уровня оборотов с перв. знач = 0)
int ch2 = 0;  // Receiver Channel 2 PPM value (переменная оборотов)

int tata = 0;  // Переменная первого эйрсофт (для обсчета)
int swit = 0;  // переменная переключателя (Эйрсофт/спуск) (для обсчета)

void setup() {

  fuelServo.attach(servoPin); // Подключаем серво к пин 6

  pinMode(ledPin, OUTPUT);  // режим пина зажигания (светодиода)

  pinMode(rcPin1, INPUT); // Пин уровня оборотов (для срабатывания)
  pinMode(rcPin2, INPUT); // Пин оборотов (газа)
  pinMode(flame, INPUT); //пин датчика опламени
  
  Serial.begin(9600);

  pinMode (tataPin, INPUT); //Входной пин кнопки спуска
  pinMode (switPin, INPUT); //Входной пин переключения

  pinMode (AirsoftPin1, OUTPUT); //Выход привод 1
  pinMode (AirsoftPin2, OUTPUT); //Выход привод 2

  pinMode (ledPinRok, OUTPUT);

  pinMode    (14, OUTPUT);
  pinMode    (15, OUTPUT);
  pinMode    (16, OUTPUT);  // релле спуска
  pinMode    (17, OUTPUT);
  pinMode    (18, OUTPUT);
  pinMode    (19, OUTPUT);


}

void loop()
{
  /////////////////// Блок обсчета входящего ШИМ!!!!!!!!!!!!!!!!
  {
    // Read in the length of the signal in microseconds
    ch1 = pulseIn(rcPin1, HIGH, 37880);  // Функцпя pulseIn обрабатывает сигнал PWM
    ch2 = pulseIn(rcPin2, HIGH, 37880); // (Pin, State, Timeout) 37880= 2x1894 (две длины импульса)
    tata = pulseIn (tataPin, HIGH, 37880); //Обсчет входящего ШИМ
    swit = pulseIn(switPin, HIGH, 37880); //Обсчет входящего ШИМ

    ////////////////////// Блок вывода значенй ШИМ на каналах на сериал монитор\\\\\\\\\\\\\\\\\\\

    Serial.print("Channel #1: ");
    Serial.println(ch1);
    Serial.print("Channel #2: ");
    Serial.println(ch2);
    Serial.print ("Channel #3: ");
    Serial.println(tata);
    Serial.print ("Channel #4: ");
    Serial.println(swit);
    Serial.println("------------");


  }

  // устанавливаем состояния выхода, чтобы включить или выключить светодиод

  digitalWrite(ledPin, ledState);

  // !!!!!!!!!!!!!!!!!!!!!!!!!!Блок управления зажиганием и серво!!!!!!!!!!!!!!!!!!!!!!!!!


  static int z = 0; //переменная накомительная чтобы к ней плюсовалось "1" как превышает

  //порог и обнулялось как ниже границы 10% - (обнуление прописано в блоке зажигания)
  // нужна для алгоритма сервы и зажигания


  if (ch2 >= ch1 && ch2 > 1100) // Если уровень оборотов превысил порог
  {
    z++; //прибавляем к переменной 1 при каждом превышении уровнем оборотов порога
  }
  if (ch2 < 1100) //есди уровень оборотов <10%,
  {
    z = 0; // переменая Z обнуляется => серво выкл, зажигание выкл
  }

  if (z == 0) //Если уровень оборотов пересек нижнюю границу
  {
    fuelServo.write(90);
    ledState = LOW; // Серво зажигание выключается (безопасность)
  }


  //!!!!!!!!!!!!!!!!!!!!!!!!Собственно блок управления серво и зажиганием!!!!!!!!!!!!!!!!!!!!!!
  // здесь будет код, который будет работать постоянно
  // и который не должен останавливаться на время между переключениями светодиода

  long currentMillis = millis(); // Пер-я времени ,
  //Может быть и глобальной, работает и без "унсигнед"

  if (One == 1)  // Есть цикл один раз выполнялся,
  {
    ledState = LOW; //то второй раз не заработает (здесь причиа дергания сервы вовремя повторого ключения зажигаия)
  }

  if  ((One == 0) && (z > 0) && (digitalRead( flame ) )) // Если цикл ещё не выполнялся,
    // ИИ уровень оборотов > порога, ИИ огня нет
  {
    ledState = HIGH;  // включаем зажигание,
    fuelServo.write(180);  //  включаем серву,
    i = 1, currentMillis = millis(); // запоминаем переменную включения зажигания, !!!запоминаем "время начала танцев"!!! - это должно быть здесь, в действии!!
  }

  if ((i == 1) && (currentMillis - previousMillis > interval)) //Если зажигание включено,
    // ИИ прошло время больше интервала (2с)

  {
    ledState = LOW;                        // ВЫкл зажигание,
    fuelServo.write(90);                       // ВЫкл серву
    previousMillis = currentMillis;    //сохраняем время последнего переключения
    One = 1;                        //переменная однократного исполнения цикла получает=1,
    i = 0;                              //обнуляем переменную зажигания
  }

  //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!Блок обнуленя переменной "One"!!!!!!!!!!!!!!!!!!!!!!!////////
  if ((One == 1) && (z == 0)) //Если цикл один раз выполнялся, и уровень оборотов пересек нижнюю границу
  {
    One = 0; // то переменная одноразового совершения цикла обнулется (цикл можно выполнить снова)
  }

  //!!!!!!!!!!!!!Блок выключения искры при быстром вспыхивании!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

  if (!digitalRead( flame ))     // Если горит огонь (топливо быстро загорелось), то
  {
    ledState = LOW;   // искра погаснет сразу, не дожидаясь истечения таймаута
  }


  // !!!!!!!!!!!!!!!!!!Блок удержания сервы при огне и выключения (Если не зажглось)!!!!!!!!!!!!!!

  static int u = 0; //Переменная хранения состояния удержания сервы (по сути состояния всего форсажа)

  if ((!digitalRead( flame )) && (z > 0)) // Если горит огонь
  {
    fuelServo.write(180);  // Серва включена,
    u = 1;  //состояние записано
  }

  //!!!!!!!!!!!!!!!!!!!Блок повторного зажигания (если потухло)!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

  if ((u == 1) && (digitalRead( flame ))) //Если серво удерживается (форсаж работает),
    // ИИ зажигание однажды срабатывало ИИ огонь внезапно потух
  {
    One = 0; // цикл зажигания сработает еще один раз
    u = 0; // Переменная удержания обнуляется
  }



  //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!Блок управления Эйрсофт!!!!!!!!!!!!!!!!!!!!!!!!

  static int asinc = 0; // Переменная асинхронности приводов

  static int por = 0; // Переменная порядка начала работы приводов



  digitalWrite(AirsoftPin1, gun1);  // Значение переменной выводим на нужный пин
  digitalWrite(AirsoftPin2, gun2);


  // Сначавса начинает AirsoftPin1!!!!!!!!!!!!!!!!!!!


  if ((tata > 1200) && (swit < 1500)  && gun1 == LOW && por == 0 && asinc == 0)
  {
    gun1 = HIGH;
    asinc = 1;
    previousMillisTata = millis();
  }


  if ((asinc == 1) && (gun1 == HIGH)  && (gun2 == LOW)  && (por == 0) && (millis() - previousMillisTata > interval_asinc))
  {
    gun2 = HIGH;
    previousMillisTata = millis();
    por = 1;
  }


  ///// Теперь второй AirsoftPin1!!!!!!!!!!!!!!!!!!!


  if ((tata > 1200) && (swit < 1500)  && gun2 == LOW && por == 1 && asinc == 1)
  {
    gun2 = HIGH;
    asinc = 2;
    previousMillisTata = millis();
  }


  if (asinc == 2 && gun2 == HIGH && gun1 == LOW && por == 1 && (millis() - previousMillisTata > interval_asinc))
  {
    gun1 = HIGH;
    previousMillisTata = millis();
    asinc = 0;
    por = 0;
  }


  if (tata < 1100)

    gun1 = LOW, gun2 = LOW;


  // !!!!!!!!!!!!!!!!Блок управления спуском!!!!!!!!!!!!!!!!!!!!!


  static int R0 = 0;
  static int R1 = 0;
  static int R2 = 0; //Переменные очередности спуска
  static int R3 = 0;
  static int R4 = 0;
  static int R5 = 0;


  digitalWrite    (14, Rok0);
  digitalWrite    (15, Rok1);
  digitalWrite   (16, Rok2);  // Присваивание пинам значения переменных состояния
  digitalWrite   (17, Rok3);
  digitalWrite   (18, Rok4);
  digitalWrite  (19, Rok5);




  //!!!!!!!!!!!!Блок переменной zRok !!!!!!!!!!!!!!!!!!

  static int zRok = 0; //Переменая для работы спуска

  if ((tata > 1200) && (swit > 1500))

  {
    zRok = 1;
  }

  if (tata < 1200)  // Если кнопка выключена
  {
    zRok  = 0; // Спуск всегда выключен
  }

  //!!!!!!!!!!!!Блок переменной OneRok  !!!!!!!!!!!!!!!!!!

  if (OneRok == 1)  // Есть цикл один раз выполнялся,
  {
    ledStateRok = LOW; //то второй раз не заработает  до того как не выключится кнопка
  }

  //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!Собственно блок управления спуском!!!!!!!!!!!!!!!!!!!!!!!////////

  digitalWrite(ledPinRok, ledStateRok); //Присваиваем пину спуска значение перменной

  unsigned long currentMillisRok = millis(); //Объявляем переменную времени

  if ((OneRok == 0) && (zRok  == 1)) //Если кнопка нажата и цикл не выполнялся

  {
    ledStateRok = HIGH; // Спуск срабатывает
    currentMillisRok  = millis();   // !!!запоминаем "время начала танцев"!!!
    RS = 1;
  }

  if ( (RS == 1) && (currentMillisRok - previousMillisRok > interval_Rok)) //Если спуск включен,
    // ИИ прошло время больше интервала
  {
    ledStateRok = LOW; //Спуск выключается
    previousMillisRok  = currentMillisRok ;  //Запоминаем время срабатывания
    OneRok = 1; //   переменная однократного исполнения цикла получает=1
    RS = 0;   // обнуляем переменную 


  }
  //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!Блок обнуленя переменной "OneRok"!!!!!!!!!!!!!!!!!!!!!!!////////
  if ((OneRok) == 1 && (zRok == 0)) //Если цикл один раз выполнялся и кнопка не нажата
  {
    OneRok = 0; // то переменная одноразового совершения цикла обнулется (цикл можно выполнить снова)
  }



  //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!спуск "A0"!!!!!!!!!!!!!!!!!!!!!!!

  if ( RS == 1 &&  (R0 == 0))
  {
    Rok0 = HIGH; // Релле срабатывает
    R0 = 1;  // Переменная меняется на 1
  }

  if ((RS == 0) && (R0 == 1)) // Если кнопка выключена
  {
    Rok0 = LOW;
    R0 = 2;
  }

  // !!!!!!!!!!!!!!!Спуск "A1"!!!!!!!!!!!!!!!!!!!!!

  if ( RS == 1 &&  (R1 == 0) && (R0 == 2))
  {
    Rok1 = HIGH; // Релле срабатывает
    R1 = 1;  // Переменная меняется на 1
  }

  if ((RS == 0) && (R1 == 1)) // Если кнопка выключена
  {
    Rok1 = LOW;
    R1 = 2;
  }


  // !!!!!!!!!!!!!!!Спуск "A2"!!!!!!!!!!!!!!!!!!!!!

  if ( RS == 1 &&  (R2 == 0) && (R1 == 2))
  {
    Rok2 = HIGH; // Релле срабатывает
    R2 = 1;  // Переменная меняется на 1
  }

  if ((RS == 0) && (R2 == 1)) // Если кнопка выключена
  {
    Rok2 = LOW;
    R2 = 2;
  }

  // !!!!!!!!!!!!!!!Спуск "A3"!!!!!!!!!!!!!!!!!!!!!

  if ( RS == 1 &&  (R3 == 0) && (R2 == 2))
  {
    Rok3 = HIGH; // Релле срабатывает
    R3 = 1;  // Переменная меняется на 1
  }

  if ((RS == 0) && (R3 == 1)) // Если кнопка выключена
  {
    Rok3 = LOW;
    R3 = 2;
  }

  // !!!!!!!!!!!!!!!Спуск "A4"!!!!!!!!!!!!!!!!!!!!!

  if ( RS == 1 &&  (R4 == 0) && (R3 == 2))
  {
    Rok4 = HIGH; // Релле срабатывает
    R4 = 1;  // Переменная меняется на 1
  }

  if ((RS == 0) && (R4 == 1)) // Если кнопка выключена
  {
    Rok4 = LOW;
    R4 = 2;
  }



  // !!!!!!!!!!!!!!!Спуск "A5"!!!!!!!!!!!!!!!!!!!!!

  if ( RS == 1 &&  (R5 == 0) && (R4 == 2))
  {
    Rok5 = HIGH; // Релле срабатывает
    R5 = 1;  // Переменная меняется на 1
  }

  if ((RS == 0) && (R5 == 1)) // Если кнопка выключена
  {
    Rok5 = LOW;
    R0 = 0;
    R1 = 0;
    R2 = 0;
    R3 = 0;
    R4 = 0;
    R5 = 0;
  }


}  //Крайняя фигурная скобка

 

-------
Что нужно сделать: 

У двух местах, вот в этом 

  //!!!!!!!!!!!!!!!!!!!!!!!!Собственно блок управления серво и зажиганием!!!!!!!!!!!!!!!!!!!!!!
  // здесь будет код, который будет работать постоянно
  // и который не должен останавливаться на время между переключениями светодиода

  long currentMillis = millis(); // Пер-я времени ,
  //Может быть и глобальной, работает и без "унсигнед"

  if (One == 1)  // Есть цикл один раз выполнялся,
  {
    ledState = LOW; //то второй раз не заработает (здесь причиа дергания сервы вовремя повторого ключения зажигаия)
  }

  if  ((One == 0) && (z > 0) && (digitalRead( flame ) )) // Если цикл ещё не выполнялся,
    // ИИ уровень оборотов > порога, ИИ огня нет
  {
    ledState = HIGH;  // включаем зажигание,
    fuelServo.write(180);  //  включаем серву,
    i = 1, currentMillis = millis(); // запоминаем переменную включения зажигания, !!!запоминаем "время начала танцев"!!! - это должно быть здесь, в действии!!
  }

  if ((i == 1) && (currentMillis - previousMillis > interval)) //Если зажигание включено,
    // ИИ прошло время больше интервала (2с)

  {
    ledState = LOW;                        // ВЫкл зажигание,
    fuelServo.write(90);                       // ВЫкл серву
    previousMillis = currentMillis;    //сохраняем время последнего переключения
    One = 1;                        //переменная однократного исполнения цикла получает=1,
    i = 0;                              //обнуляем переменную зажигания
  }

И вот в этом 
 

//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!Собственно блок управления спуском!!!!!!!!!!!!!!!!!!!!!!!////////

  digitalWrite(ledPinRok, ledStateRok); //Присваиваем пину спуска значение перменной

  unsigned long currentMillisRok = millis(); //Объявляем переменную времени

  if ((OneRok == 0) && (zRok  == 1)) //Если кнопка нажата и цикл не выполнялся

  {
    ledStateRok = HIGH; // Спуск срабатывает
    currentMillisRok  = millis();   // !!!запоминаем "время начала танцев"!!!
    RS = 1;
  }

  if ( (RS == 1) && (currentMillisRok - previousMillisRok > interval_Rok)) //Если спуск включен,
    // ИИ прошло время больше интервала
  {
    ledStateRok = LOW; //Спуск выключается
    previousMillisRok  = currentMillisRok ;  //Запоминаем время срабатывания
    OneRok = 1; //   переменная однократного исполнения цикла получает=1
    RS = 0;   // обнуляем переменную 

Светодиод не всегда загорается на нужное время (время заданного интервала)

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

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

 

 

 

kak-dela007@mail.ru
Offline
Зарегистрирован: 28.12.2016

Неужели всё так идеально, что не надо даже редактировать? 

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

Я бы во всех словах реле вторую л убрал, явно лишняя )))

kak-dela007@mail.ru
Offline
Зарегистрирован: 28.12.2016

:D :D :D

vvadim
Offline
Зарегистрирован: 23.05.2012

внимательно посмотрите пример мигаем без задержки

и сравните с вашим кодом

kak-dela007@mail.ru
Offline
Зарегистрирован: 28.12.2016

Посмотрел, и срааазу все понял :) 
Поэтому и обращаюсь в этот раздел)