Отредактировать код, который работает :)
- Войдите на сайт для отправки комментариев
Строю контроллер 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
внимательно посмотрите пример мигаем без задержки
и сравните с вашим кодом
Посмотрел, и срааазу все понял :)
Поэтому и обращаюсь в этот раздел)