Отредактировать код, который работает :)
- Войдите на сайт для отправки комментариев
Строю контроллер 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; // обнуляем переменную
Светодиод не всегда загорается на нужное время (время заданного интервала)
Нужно это вылечить, можно и принципиально что-то изменить, но сохранив алкгоритм работы всех элементов.
Для наглядности нарисовал условную схему подключений (может пригодиться). Естественно, в жизни диоды буду подключаться через резисторы, а нагрузка -через мосфеты.
Неужели всё так идеально, что не надо даже редактировать?
Я бы во всех словах реле вторую л убрал, явно лишняя )))
:D :D :D
внимательно посмотрите пример мигаем без задержки
и сравните с вашим кодом
Посмотрел, и срааазу все понял :)
Поэтому и обращаюсь в этот раздел)