Мне интересно, почему народ не использует переменные, а вместо этого, например, читает из порта дважды? ... что читая из одного и того же порта дважды, вы рискуете считать разные значения
Так ну и что с того, что разные значения, значит значение изменилось, переменные стоит использовать если действительно в этом есть необходимость. В этих примерах по этой причине глюков не будет. А "скорость" здесь не нужна.
bool state=0;//пременная состояния кнопки
unsigned long presstime=0;//пременная для хранения "Времени между нажатиями"
int val=0;//переменная для хранения количества нажатий
void setup()
{
pinMode(13, OUTPUT);//инициализация пинов
}
void loop()
{
if(digitalRead(9)&&!state)//если кнопка нажата и state=0, то ...
{
presstime=millis();//фиксируем время нажатия
state=1;//присваиваем переменной значение 1
val++;//прибавляем еденицу к val
delay(10);//небольшая защита от дребезга
}
if(!digitalRead(9)&&state&&(millis()-presstime)>100)state=0;
//если кнопка не нажата, state=1,
//текущее время минус зафиксированое больше 100
//изменяя это значение можно регулировать минимальную длинну
//пауз между нажатиями
//обнуляем преременную state
if(val&&(millis()-presstime)>1000)//если val больше 0,
//текущее время минус зафиксировано больше 1000
//изменяя это значение можно регулировать
//максимальное время между нажатиями
{
presstime=0;//обнуляем переменную
val=0;//обнуляем переменную
}
if(val>1)//если переменная больше 1 или равна 2
//изменяя это значение можно увеличивать количество нажатий
{
digitalWrite(13,!digitalRead(13));//инвертируем состояние пина
presstime=0;//обнуляем переменную
val=0;//обнуляем переменную
}
}
А все потому что в моем коде много лишнего и для отражения сути проблемы с которой я столкнулся и была скопирована часть кода из этой темы!!!
все для того чтобы человек который вызвался мне помогать, мог с наименьшими трудозатратами подсказать решение моей проблемы!!!
Могу вас заверить на все 100% что данный код, если нажата кнопка, включит/выключит светодиод не через 45 секунд, а ровно через 6 минут. Поэтому показав пример рабочего кода, вместо своего, вы сделали все для того что бы вам никто не смог помочь.
long previousMillis = 0;
int val = 0;
void setup()
{
pinMode(13, OUTPUT);
}
void loop()
{
if(digitalRead(14) == HIGH) //если кнопка нажата ...
{
if (millis()-previousMillis > 180000)
{
previousMillis = millis();
val++;
}
}
else
{
val=0;
}
if(val>=2)
{
digitalWrite(13,!digitalRead(13)); //инвертируем состояние пина
val=0;
}
}
nestandart "ткнул пальцем в небо" и вам просто повезло, что помогло именно такое решение, и вы попрежнему не знаете в чем была проблема и в следующий раз сделаете эту же ошибку.
для того чтобы все прояснилось привожу свой вариант кода!!!
const int ACCPin = 9; //контакт подключения реле АСС
const int passengerPin = 6; // контакт контроля нахождения людей в салоне
const int doorPin = 5; // контакт контроля состояния тригеров дверей
const int fuelPumpPin = 7; //контакт контроля состояния бензонасоса
int interval2 = 1000;
int regim = 0;
int flag = 0;
unsigned long pvMillis = 0;
int val=0;
//переменные
int passenger = 0; //переменная для хранения данных с контакта контроля нахождения людей в салоне
int door = 0;//переменная для хранения данных с контакта контроля состояния тригеров дверей
int fuelPump = 0;//переменная для хранения данных с контакта реле бензонасоса
void setup() {
// задаем режим выхода для порта, подключенного к реле
pinMode(ACCPin, OUTPUT);
// задаем режим входа для портов подключенных к кнопкам и датчикам
pinMode (passengerPin, INPUT);
pinMode (doorPin, INPUT);
pinMode (fuelPumpPin, INPUT);
}
void loop()
{
// код АСС
passenger = digitalRead (passengerPin); //сохраняем состояние с контакта контроля пассажиров в переменную
door = digitalRead (doorPin); //сохраняем состояние с контакта контроля тригеров дверей в переменную
if (door == HIGH && flag == 0) //если дверь открыта , ТО
{
regim ++;
flag = 1;
if(regim>2)
{
regim = 1;
}
}
if(door == LOW && flag == 1)
{
flag = 0;
}
if(regim == 1)
{
if(passenger==HIGH)
{
digitalWrite(ACCPin, HIGH);
}
if(passenger == LOW && fuelPump == LOW )
{
unsigned long curMillis = millis();
if(curMillis - pvMillis > interval2)
{
pvMillis = curMillis;
val ++ ;
}
}
else
{
val = 0;
}
if(val >=180 )
{
digitalWrite(ACCPin, LOW);
}
}
if(regim == 2)
{
if(passenger == LOW && fuelPump == LOW )
{
unsigned long curMillis = millis();
if(curMillis - pvMillis > interval2)
{
pvMillis = curMillis;
val ++ ;
}
}
else
{
val = 0;
}
if(val >=300)
{
digitalWrite(ACCPin, LOW);
}
}
а было вот так
const int ACCPin = 9; //контакт подключения реле АСС
const int passengerPin = 6; // контакт контроля нахождения людей в салоне
const int doorPin = 5; // контакт контроля состояния тригеров дверей
const int fuelPumpPin = 7; //контакт контроля состояния бензонасоса
int interval2 = 180000;
int regim = 0;
int flag = 0;
unsigned long pvMillis = 0;
int val=0;
//переменные
int passenger = 0; //переменная для хранения данных с контакта контроля нахождения людей в салоне
int door = 0;//переменная для хранения данных с контакта контроля состояния тригеров дверей
int fuelPump = 0;//переменная для хранения данных с контакта реле бензонасоса
void setup() {
// задаем режим выхода для порта, подключенного к реле
pinMode(ACCPin, OUTPUT);
// задаем режим входа для портов подключенных к кнопкам и датчикам
pinMode (passengerPin, INPUT);
pinMode (doorPin, INPUT);
pinMode (fuelPumpPin, INPUT);
}
void loop()
{
// код АСС
passenger = digitalRead (passengerPin); //сохраняем состояние с контакта контроля пассажиров в переменную
door = digitalRead (doorPin); //сохраняем состояние с контакта контроля тригеров дверей в переменную
if (door == HIGH && flag == 0) //если дверь открыта , ТО
{
regim ++;
flag = 1;
if(regim>2)
{
regim = 1;
}
}
if(door == LOW && flag == 1)
{
flag = 0;
}
if(regim == 1)
{
if(passenger==HIGH)
{
digitalWrite(ACCPin, HIGH);
}
if(passenger == LOW && fuelPump == LOW )
{
unsigned long curMillis = millis();
if(curMillis - pvMillis > interval2)
{
pvMillis = curMillis;
val ++ ;
}
}
else
{
val = 0;
}
if(val >=2 )
{
digitalWrite(ACCPin, LOW);
}
}
if(regim == 2)
{
if(passenger == LOW && fuelPump == LOW )
{
unsigned long curMillis = millis();
if(curMillis - pvMillis > interval2)
{
pvMillis = curMillis;
val ++ ;
}
}
else
{
val = 0;
}
if(val >=5)
{
digitalWrite(ACCPin, LOW);
}
}
Вам нужно почитать про типы данных, а именно про тип int, в описании которого написанно, что данный тип может хранить числа от -32768 до 32767, а вы пытаетесь в него записать 180000, поэтому нужно просто поменять в 5-й строке тип переменной interval2 на например long и все заработает.
const int ACCPin = 9; //контакт подключения реле АСС
const int passengerPin = 6; // контакт контроля нахождения людей в салоне
const int doorPin = 5; // контакт контроля состояния тригеров дверей
const int fuelPumpPin = 7; //контакт контроля состояния бензонасоса
long interval2 = 180000;
int regim = 0;
int flag = 0;
unsigned long pvMillis = 0;
int val=0;
//переменные
int passenger = 0; //переменная для хранения данных с контакта контроля нахождения людей в салоне
int door = 0;//переменная для хранения данных с контакта контроля состояния тригеров дверей
int fuelPump = 0;//переменная для хранения данных с контакта реле бензонасоса
void setup() {
// задаем режим выхода для порта, подключенного к реле
pinMode(ACCPin, OUTPUT);
// задаем режим входа для портов подключенных к кнопкам и датчикам
pinMode (passengerPin, INPUT);
pinMode (doorPin, INPUT);
pinMode (fuelPumpPin, INPUT);
}
void loop()
{
// код АСС
passenger = digitalRead (passengerPin); //сохраняем состояние с контакта контроля пассажиров в переменную
door = digitalRead (doorPin); //сохраняем состояние с контакта контроля тригеров дверей в переменную
if (door == HIGH && flag == 0) //если дверь открыта , ТО
{
regim ++;
flag = 1;
if(regim>2)
{
regim = 1;
}
}
if(door == LOW && flag == 1)
{
flag = 0;
}
if(regim == 1)
{
if(passenger==HIGH)
{
digitalWrite(ACCPin, HIGH);
}
if(passenger == LOW && fuelPump == LOW )
{
unsigned long curMillis = millis();
if(curMillis - pvMillis > interval2)
{
pvMillis = curMillis;
val ++ ;
}
}
else
{
val = 0;
}
if(val >=1)
{
digitalWrite(ACCPin, LOW);
}
}
if(regim == 2)
{
if(passenger == LOW && fuelPump == LOW )
{
unsigned long curMillis = millis();
if(curMillis - pvMillis > interval2)
{
pvMillis = curMillis;
val ++ ;
}
}
else
{
val = 0;
}
if(val >=5)
{
digitalWrite(ACCPin, LOW);
}
}
Так же если вы хотите 3 минуты, а не 6 то и условие в 65 строкеif(val >=2) нужно поменять наif(val >=1).
leshak, не чистите пока тему. Мне интересно как быстро triada13 найдет свою ошибку.
Прошу прощения что долго не отвечал.
Сегодня просмотрел свой код "вооруженным" глазом, и нашел свой касяк: я третий опеатор цикла if поместил во внутрь скобок первого оператора цикла if. То есть после val++; должно быть две закр. скобки "}".
Здраствуйте.
Спасибо за проделанный труд, очень полезная информация.
Делаю свои робкие шаги в освоении Arduino.
Как правильно сделать, данное решение.
Есть кнопка, и концевик (по сути, тоже кнопка).
Нажиамем и удерживаем кнопку, запускается пневмо цилинд и идет до концевика или пока кнопка не отпущена. При этом он не должен выполнять операцию 1 и операцию 3.
У меня в голове получилось такое решение, но может оно не коректно
Разнести 1,2,3 оперции по кейзам.
switch(action)
{
case 1:
break;
case 2:
while (digitalRead(4) == HIGH && state != HIGH)
{
digitalWrite(13, digitalRead(4));
}
break;
case 3:
break;
}
Его еще нет, пока обдумываю как сделать.
Этот набил, чтобы было понятнее.
>> Получается так что вся ваша программа стоит колом, пока вы не выйдете из while. Это не есть хорошо.
Да, я это понимаю. Но меня это не смущало, пока вы об этом не упомянули.
Переменная state, будет меняться по прерыванию от концевика. Она может не изменить из-за цикла?
>> Использование while нецелесообразно
А как это делают?
Нужно не просто включить выключить, а именно нажать и держать, пока нажата кнопка цилиндр идет.
>> Вы спросили как правильно ? >> Я сказал свое мнение.
Наверно я не правильно выразился.
>>Я так понял, вы предлагаете проверять на каждом выполнении loop и выставлять включение, выключение.
Просто уточнял, правильно ли вас понял.
>> И заодно проверю, срабатывает прерывание и таймер, то, что он останавливает ход выполнения это не минус, в данном конкретном случае.
Это простое любопытсво, во мне заиграло:).
Разумеется, хочется правильно, поэтому и обратился.
// Переменные контактов
int btnMode = 27; // Кнопка выбора режима
int btnStop = 28; // Кнопка экстренной остановки
int btnPause = 29; // Кнопка остановки
int btnStart = 30; // Кнопка старта
// Для автоматического режима
int keyFrameDown = 31; // Запуск опускания рамки
int senFrameDown = 32; // Концевик опускания рамки 32
int keyPlateForward = 33; // Запуск плиты вперед
int senPlateForward = 34; // Концевик запуска плиты вперед 34
int keyStartPlate = 35; // Включение плиты
int senPlateStartTimmer = 32; // Получение от плиты команды на запуск таймера 36
int keyPlateBack = 37; // Запуск плиты назад
int senPlateBack = 34; // Концевик плиты назад 38
int keyBulgeOn = 39; // Включение раздува
int keyFormUp = 40; // Подъем формы
int senFormUp = 32; // Концевик подъема формы 41
int keyVacuumOn = 42; // Включение вакуума
int keyBlowingupOn = 43; // Включение раздува воздуха
int keyFrameUp = 44; // Запуск подъема рамки
int senTFrameUp = 34; // Концевик подъема рамки 45
// /Для автоматического режима
// Для ручного режима
int btnFrameDown = 22; // Кнопка опускания рамки
int btnPlateForward = 23; // Кнопка запуска плиты вперед
int btnStartPlate = 19; // Кнопка включения плиты
int btnPlateBack = 18; // Кнопка запуска плиты назад
int btnBulgeOn = 17; // Кнопка включения раздува
int btnFormUp = 16; // Кнопка подъема формы
int btnVacuumOn = 15; // Кнопка включения вакуума
int btnBlowingupOn = 14; // Кнопка включение раздува воздуха
int btnFrameUp = 7; // Запуск подъема рамки
// /Для ручного режима
// /Переменные контактов
// Перечисления автомата
typedef enum {
STATE_None, // Начало работы
STATE_Start, // Старт программы + запуск опускания рамки
STATE_WaitFrameDown, // Ждем сработки от концовика опускания рамки
STATE_PlateForward, // Запуск плиты вперед
STATE_WaitPlateForward, // Ждем сработки от концовика запуска плиты вперед
STATE_StartPlate, // Включение обогрева плиты
STATE_WaitStartPlate, // Ждем сработки окончания обогрева плиты + Отключение обогрева плиты + Запуск плиты назад
STATE_WaitPlateBack, // Ждем сработки от концовика запуска плиты назад + Остановка плиты назад + Включение раздува + Подъем формы
STATE_WaitFormUp, // Ждем сработки от подъема формы + Отключение подъема формы + Отключение раздува + Включение вакумма + таймер + Отключение вакумма + Включение поддува воздуха + таймер + Отключение поддува воздуха + Запуск подъема рамки
STATE_WaitFrameUp, // Ждем сработки от концовика подъема рамки
STATE_End // Конец работы
} ESTATE;
ESTATE state = STATE_None;
// Перечисления автомата
// Переменные COM порта
int speedCom = 9600;
// /Переменные COM порта
// Переменные
boolean currentBtnMode = LOW; // Тек. значение для кнопки выбора режима
boolean lastBtnMode = LOW; // Последние значение для кнопки выбора режима
boolean currentBtnStop = LOW; // Тек. значение для кнопки экстренной остановки
boolean lastBtnStop = LOW; // Последние значение для кнопки экстренной остановки
boolean currentBtnStart = LOW; // Тек. значение для кнопки старта
boolean lastBtnStart = LOW; // Последние значение для кнопки старта
boolean currentBtnFrameDownStatus = LOW; // Тек. значение для кнопки опускания рамки
boolean lastBtnFrameDownStatus = LOW; // Последние значение для кнопки опускания рамки
boolean currentBtnPlateForwardStatus = LOW; // Тек. значение для кнопки запуска плиты вперед
boolean lastBtnPlateForwardStatus = LOW; // Последние значение для кнопки запуска плиты вперед
// /Переменные
// Переменные таймера
int plateStartTimmerCountSec = 5; // Время в секундах, после получение от плиты команды
int vacuumOnCountSec = 5; // Время в секундах, после получение вакумма
int blowingupOnCountSec = 5; // Время в секундах, после включения раздува воздуха
unsigned long currentPlateStartTimmer; // Считываем время, прошедшее с момента запуска программы, после получение от плиты команды
unsigned long loopPlateStartTimmer; // Считываем время, прошедшее с момента запуска таймера, после получение от плиты команды
unsigned long currentVacuumOnCountSec; // Считываем время, прошедшее с момента запуска программы, после получение вакуума
unsigned long loopVacuumOnCountSec; // Считываем время, прошедшее с момента запуска таймера, после получение вакуума
unsigned long currentBlowingupOnCountSec; // Считываем время, прошедшее с момента запуска программы, после включения раздува воздуха
unsigned long loopBlowingupOnCountSec; // Считываем время, прошедшее с момента запуска таймера, после включения раздува воздуха
// /Переменные таймера
// Настройки
void setup()
{
// Настраиваем контакты
pinMode(btnMode, INPUT); // Кнопка выбора режима
pinMode(btnStop, INPUT); // Кнопка экстренной остановки
pinMode(btnPause, INPUT); // Кнопка остановки
pinMode(btnStart, INPUT); // Кнопка старта
// Для автоматического режима
pinMode(keyFrameDown, OUTPUT); // Запуск опускания рамки
pinMode(senFrameDown, INPUT); // Концевик опускания рамки
pinMode(keyPlateForward, OUTPUT); // Запуск плиты вперед
pinMode(senPlateForward, INPUT); // Концевик запуска плиты вперед
pinMode(keyStartPlate, OUTPUT); // Включение плиты
pinMode(senPlateStartTimmer, INPUT); // Получение от плиты команды на запуск таймера
pinMode(keyPlateBack, OUTPUT); // Запуск плиты назад
pinMode(senPlateBack, INPUT); // Концевик плиты назад
pinMode(keyBulgeOn, OUTPUT); // Включение раздува
pinMode(keyFormUp, OUTPUT); // Подъем формы
pinMode(senFormUp, INPUT); // Концевик подъема формы
pinMode(keyVacuumOn, OUTPUT); // Включение вакуума
pinMode(keyBlowingupOn, OUTPUT); // Включение раздува воздуха
pinMode(keyFrameUp, OUTPUT); // Запуск подъема рамки
pinMode(senTFrameUp, INPUT); // Концевик подъема рамки
// /Для автоматического режима
// Для ручного режима
pinMode(btnFrameDown, INPUT); // Кнопка опускания рамки
pinMode(btnPlateForward, INPUT); // Кнопка запуска плиты вперед
pinMode(btnStartPlate, INPUT); // Кнопка включения плиты
pinMode(btnPlateBack, INPUT); // Кнопка запуска плиты назад
pinMode(btnBulgeOn, INPUT); // Кнопка включения раздува
pinMode(btnFormUp, INPUT); // Кнопка подъема формы
pinMode(btnVacuumOn, INPUT); // Кнопка включения вакуума
pinMode(btnBlowingupOn, INPUT); // Кнопка включение раздува воздуха
pinMode(btnFrameUp, INPUT); // Запуск подъема рамки
// /Для ручного режима
// /Настраиваем контакты
// Создаем COM объект
Serial.begin(speedCom);
// /Создаем COM объект
// Иницилизация
Serial.println("Initialization");
// /Иницилизация
}
// Основная программа
void loop()
{
// Проверка нажата ли кнопка ручного режима
if (digitalRead(btnMode) == HIGH)
//if (digitalRead(btnMode) == LOW)
{
// Автоматический режим
switch (state) {
// Начало работы
case STATE_None:
if (digitalRead(btnStart) == HIGH)
{
state = STATE_Start;
Serial.println("Start Auto Cycle"); // Запуск автоматического режима
}
break;
case STATE_Start:
digitalWrite(keyFrameDown, HIGH); // Старт программы + запуск опускания рамки
state = STATE_WaitFrameDown;
Serial.println("A_1");
break;
case STATE_WaitFrameDown:
if (digitalRead(senFrameDown) == HIGH)
{
digitalWrite(keyFrameDown, LOW); // Остановка опускания рамки
state = STATE_PlateForward;
Serial.println("A_2");
}
break;
case STATE_PlateForward:
digitalWrite(keyPlateForward, HIGH); // Запуск плиты вперед
state = STATE_WaitPlateForward;
Serial.println("A_3");
break;
case STATE_WaitPlateForward:
if (digitalRead(senPlateForward) == HIGH)
{
digitalWrite(keyPlateForward, LOW); // Остановка плиты вперед
state = STATE_StartPlate;
Serial.println("A_4");
}
break;
case STATE_StartPlate:
digitalWrite(keyStartPlate, HIGH); // Включение обогрева плиты
state = STATE_WaitStartPlate;
Serial.println("A_5");
break;
case STATE_WaitStartPlate:
if (digitalRead(senPlateStartTimmer) == HIGH)
{
// Включаю таймер
SetTimmerOnMillis(currentPlateStartTimmer, loopPlateStartTimmer, plateStartTimmerCountSec);
digitalWrite(keyStartPlate, LOW); // Отключение обогрева плиты
digitalWrite(keyPlateBack, HIGH); // Запуск плиты назад
state = STATE_WaitPlateBack;
Serial.println("A_6");
}
break;
case STATE_WaitPlateBack:
if (digitalRead(senPlateBack) == HIGH)
{
digitalWrite(keyPlateBack, LOW); // Остановка плиты назад
digitalWrite(keyBulgeOn, HIGH); // Включение раздува
digitalWrite(keyFormUp, HIGH); // Подъем формы
state = STATE_WaitFormUp;
Serial.println("A_7");
}
break;
case STATE_WaitFormUp:
if (digitalRead(senFormUp) == HIGH)
{
digitalWrite(keyFormUp, LOW); // Отключение подъема формы
digitalWrite(keyBulgeOn, LOW); // Отключение раздува
digitalWrite(keyVacuumOn, HIGH); // Включение вакумма
// Включаю таймер
SetTimmerOnMillis(currentVacuumOnCountSec, loopVacuumOnCountSec, vacuumOnCountSec);
digitalWrite(keyVacuumOn, LOW); // Отключение вакумма
digitalWrite(keyBlowingupOn, HIGH); // Включение поддува воздуха
// Включаю таймер
SetTimmerOnMillis(currentBlowingupOnCountSec, loopBlowingupOnCountSec, blowingupOnCountSec);
digitalWrite(keyBlowingupOn, LOW); // Отключение поддува воздуха
digitalWrite(keyFrameUp, HIGH); // Запуск подъема рамки
state = STATE_WaitFrameUp;
Serial.println("A_8");
}
break;
case STATE_WaitFrameUp:
if (digitalRead(senTFrameUp) == HIGH)
{
digitalWrite(keyFrameUp, LOW); // Отключение подъема рамки
state = STATE_None;
Serial.println("End Auto Cycle");
}
break;
}
}
else if (digitalRead(btnMode) == LOW)
{
// Ручной режим
if (digitalRead(btnFrameDown) == HIGH && digitalRead(senFrameDown) != HIGH)
{
digitalWrite(keyFrameDown, HIGH); // Запуск опускания рамки
Serial.println("M_1");
}
else if ((digitalRead(btnFrameDown) == LOW || digitalRead(senFrameDown) == HIGH))
{
if (digitalRead(keyFrameDown) == HIGH)
{
digitalWrite(keyFrameDown, LOW); // Остановка опускания рамки
Serial.println("M_1_1");
}
}
if (digitalRead(btnPlateForward) == HIGH && digitalRead(senPlateForward) != HIGH)
{
digitalWrite(keyPlateForward, HIGH); // Запуск опускания рамки
Serial.println("M_2");
}
else if ((digitalRead(btnPlateForward) == LOW || digitalRead(senPlateForward) == HIGH))
{
if (digitalRead(keyPlateForward) == HIGH)
{
digitalWrite(keyPlateForward, LOW); // Остановка опускания рамки
Serial.println("M_2_1");
}
}
}
}
// Функция таймер с задержкой, вместо delay
void SetTimmerOnMillis(long currentPlateStartTimmer, long loopPlateStartTimmer, int plateStartTimmerCountSec)
{
currentPlateStartTimmer = millis(); // считываем время, прошедшее с момента запуска программы
loopPlateStartTimmer = currentPlateStartTimmer;
while (currentPlateStartTimmer <= (loopPlateStartTimmer + (plateStartTimmerCountSec * 1000)))
{
currentPlateStartTimmer= millis();
}
}
/* Не используется */
// Функция удаления дребезга кнопок
boolean Debounce(boolean lastValue, int switchPin)
{
boolean currentValue = digitalRead(switchPin);
if (lastValue != currentValue)
{
long currentTime = millis();
long loopTime = currentTime;
while (currentTime <= (loopTime + 5))
{
currentTime = millis();
}
currentValue = digitalRead(switchPin);
}
return currentValue;
}
Пока не оконченная, без прерываний (пока читаю значения концевика на прямую, если будет не достаточно тогда подыму их) и оптимизаций, еще код не весь закомментирован.
Но суть будет понятна, чтобы вы смогли увидеть проблему в целом. В ручной режиме, именно в нем используется такое нажатие.
Сейчас коректно?
Исправил в 18.47, там была ошибка, оказывается порты с 14 по 21, как-то забавно себя ведут.
Код очень похож на C#, мне моментом стало все понятно.
// Переменные контактов
int btnMode = 27; // Кнопка выбора режима
int btnStop = 28; // Кнопка экстренной остановки
int btnPause = 29; // Кнопка остановки
int btnStart = 30; // Кнопка старта
// Для автоматического режима
int keyFrameDown = 31; // Запуск опускания рамки
int senFrameDown = 32; // Концевик опускания рамки 32
int keyPlateForward = 33; // Запуск плиты вперед
int senPlateForward = 34; // Концевик запуска плиты вперед 34
int keyStartPlate = 35; // Включение плиты
int senPlateStartTimmer = 32; // Получение от плиты команды на запуск таймера 36
int keyPlateBack = 37; // Запуск плиты назад
int senPlateBack = 34; // Концевик плиты назад 38
int keyBulgeOn = 39; // Включение раздува
int keyFormUp = 40; // Подъем формы
int senFormUp = 32; // Концевик подъема формы 41
int keyVacuumOn = 42; // Включение вакуума
int keyBlowingupOn = 43; // Включение раздува воздуха
int keyFrameUp = 44; // Запуск подъема рамки
int senFrameUp = 34; // Концевик подъема рамки 45
// /Для автоматического режима
// Для ручного режима
int btnFrameDown = 21; // Кнопка опускания рамки
int btnPlateForward = 20; // Кнопка запуска плиты вперед
int btnStartPlate = 19; // Кнопка включения плиты
int btnPlateBack = 18; // Кнопка запуска плиты назад
int btnBulgeOn = 17; // Кнопка включения раздува
int btnFormUp = 16; // Кнопка подъема формы
int btnVacuumOn = 15; // Кнопка включения вакуума
int btnBlowingupOn = 14; // Кнопка включение раздува воздуха 14
int btnFrameUp = 22; // Запуск подъема рамки 7
// /Для ручного режима
// /Переменные контактов
// Перечисления автомата
typedef enum {
STATE_None, // Начало работы
STATE_Start, // Старт программы + запуск опускания рамки
STATE_WaitFrameDown, // Ждем сработки от концовика опускания рамки
STATE_PlateForward, // Запуск плиты вперед
STATE_WaitPlateForward, // Ждем сработки от концовика запуска плиты вперед
STATE_StartPlate, // Включение обогрева плиты
STATE_WaitStartPlate, // Ждем сработки окончания обогрева плиты + Отключение обогрева плиты + Запуск плиты назад
STATE_WaitPlateBack, // Ждем сработки от концовика запуска плиты назад + Остановка плиты назад + Включение раздува + Подъем формы
STATE_WaitFormUp, // Ждем сработки от подъема формы + Отключение подъема формы + Отключение раздува + Включение вакуума + таймер + Отключение вакуума + Включение поддува воздуха + таймер + Отключение поддува воздуха + Запуск подъема рамки
STATE_WaitFrameUp, // Ждем сработки от концовика подъема рамки
STATE_End // Конец работы
} ESTATE;
ESTATE state = STATE_None;
// Перечисления автомата
// Переменные COM порта
int speedCom = 9600;
// /Переменные COM порта
// Переменные
boolean currentBtnMode = LOW; // Тек. значение для кнопки выбора режима
boolean lastBtnMode = LOW; // Последние значение для кнопки выбора режима
boolean currentBtnStop = LOW; // Тек. значение для кнопки экстренной остановки
boolean lastBtnStop = LOW; // Последние значение для кнопки экстренной остановки
boolean currentBtnStart = LOW; // Тек. значение для кнопки старта
boolean lastBtnStart = LOW; // Последние значение для кнопки старта
boolean flagStartPlate = LOW; // Флаг хранения состояния кнопки включение плиты
boolean currentBtnBulgeOn = LOW; // Тек. значение для кнопки раздува
boolean lastBtnBulgeOn = LOW; // Последние значение для кнопки раздува
boolean flagBulgeOn = LOW; // Флаг хранения состояния кнопки раздува
boolean currentBtnVacuumOn = LOW; // Тек. значение для кнопки вакуума
boolean lastBtnVacuumOn = LOW; // Последние значение для кнопки вакуума
boolean flagVacuumOn = LOW; // Флаг хранения состояния кнопки вакуума
boolean currentBtnBlowingupOn = LOW; // Тек. значение для кнопки раздува воздуха
boolean lastBtnBlowingupOn = LOW; // Последние значение для кнопки раздува воздуха
boolean flagBlowingupOn = LOW; // Флаг хранения состояния кнопки раздува воздуха
// /Переменные
// Переменные таймера
int plateStartTimmerCountSec = 5; // Время в секундах, после получение от плиты команды
int vacuumOnCountSec = 5; // Время в секундах, после получение вакуума
int blowingupOnCountSec = 5; // Время в секундах, после включения раздува воздуха
unsigned long currentPlateStartTimmer; // Считываем время, прошедшее с момента запуска программы, после получение от плиты команды
unsigned long loopPlateStartTimmer; // Считываем время, прошедшее с момента запуска таймера, после получение от плиты команды
unsigned long currentVacuumOnCountSec; // Считываем время, прошедшее с момента запуска программы, после получение вакуума
unsigned long loopVacuumOnCountSec; // Считываем время, прошедшее с момента запуска таймера, после получение вакуума
unsigned long currentBlowingupOnCountSec; // Считываем время, прошедшее с момента запуска программы, после включения раздува воздуха
unsigned long loopBlowingupOnCountSec; // Считываем время, прошедшее с момента запуска таймера, после включения раздува воздуха
// /Переменные таймера
// Настройки
void setup()
{
// Настраиваем контакты
pinMode(btnMode, INPUT); // Кнопка выбора режима
pinMode(btnStop, INPUT); // Кнопка экстренной остановки
pinMode(btnPause, INPUT); // Кнопка остановки
pinMode(btnStart, INPUT); // Кнопка старта
// Для автоматического режима
pinMode(keyFrameDown, OUTPUT); // Запуск опускания рамки
pinMode(senFrameDown, INPUT); // Концевик опускания рамки
pinMode(keyPlateForward, OUTPUT); // Запуск плиты вперед
pinMode(senPlateForward, INPUT); // Концевик запуска плиты вперед
pinMode(keyStartPlate, OUTPUT); // Включение плиты
pinMode(senPlateStartTimmer, INPUT); // Получение от плиты команды на запуск таймера
pinMode(keyPlateBack, OUTPUT); // Запуск плиты назад
pinMode(senPlateBack, INPUT); // Концевик плиты назад
pinMode(keyBulgeOn, OUTPUT); // Включение раздува
pinMode(keyFormUp, OUTPUT); // Подъем формы
pinMode(senFormUp, INPUT); // Концевик подъема формы
pinMode(keyVacuumOn, OUTPUT); // Включение вакуума
pinMode(keyBlowingupOn, OUTPUT); // Включение раздува воздуха
pinMode(keyFrameUp, OUTPUT); // Запуск подъема рамки
pinMode(senFrameUp, INPUT); // Концевик подъема рамки
// /Для автоматического режима
// Для ручного режима
pinMode(btnFrameDown, INPUT); // Кнопка опускания рамки
pinMode(btnPlateForward, INPUT); // Кнопка запуска плиты вперед
pinMode(btnStartPlate, INPUT); // Кнопка включения плиты
pinMode(btnPlateBack, INPUT); // Кнопка запуска плиты назад
pinMode(btnBulgeOn, INPUT); // Кнопка включения раздува
pinMode(btnFormUp, INPUT); // Кнопка подъема формы
pinMode(btnVacuumOn, INPUT); // Кнопка включения вакуума
pinMode(btnBlowingupOn, INPUT); // Кнопка включение раздува воздуха
pinMode(btnFrameUp, INPUT); // Запуск подъема рамки
// /Для ручного режима
// /Настраиваем контакты
// Создаем COM объект
Serial.begin(speedCom);
// /Создаем COM объект
// Иницилизация
Serial.println("Initialization");
// /Иницилизация
}
// Основная программа
void loop()
{
// Проверка нажата ли кнопка ручного режима
if (digitalRead(btnMode) == HIGH)
//if (digitalRead(btnMode) == LOW)
{
// Автоматический режим
switch (state) {
// Начало работы
case STATE_None:
if (digitalRead(btnStart) == HIGH)
{
state = STATE_Start;
Serial.println("Start Auto Cycle"); // Запуск автоматического режима
}
break;
case STATE_Start:
digitalWrite(keyFrameDown, HIGH); // Старт программы + запуск опускания рамки
state = STATE_WaitFrameDown;
Serial.println("A_1");
break;
case STATE_WaitFrameDown:
if (digitalRead(senFrameDown) == HIGH)
{
digitalWrite(keyFrameDown, LOW); // Остановка опускания рамки
state = STATE_PlateForward;
Serial.println("A_2");
}
break;
case STATE_PlateForward:
digitalWrite(keyPlateForward, HIGH); // Запуск плиты вперед
state = STATE_WaitPlateForward;
Serial.println("A_3");
break;
case STATE_WaitPlateForward:
if (digitalRead(senPlateForward) == HIGH)
{
digitalWrite(keyPlateForward, LOW); // Остановка плиты вперед
state = STATE_StartPlate;
Serial.println("A_4");
}
break;
case STATE_StartPlate:
digitalWrite(keyStartPlate, HIGH); // Включение обогрева плиты
state = STATE_WaitStartPlate;
Serial.println("A_5");
break;
case STATE_WaitStartPlate:
if (digitalRead(senPlateStartTimmer) == HIGH)
{
// Включаю таймер
SetTimmerOnMillis(currentPlateStartTimmer, loopPlateStartTimmer, plateStartTimmerCountSec);
digitalWrite(keyStartPlate, LOW); // Отключение обогрева плиты
digitalWrite(keyPlateBack, HIGH); // Запуск плиты назад
state = STATE_WaitPlateBack;
Serial.println("A_6");
}
break;
case STATE_WaitPlateBack:
if (digitalRead(senPlateBack) == HIGH)
{
digitalWrite(keyPlateBack, LOW); // Остановка плиты назад
digitalWrite(keyBulgeOn, HIGH); // Включение раздува
digitalWrite(keyFormUp, HIGH); // Подъем формы
state = STATE_WaitFormUp;
Serial.println("A_7");
}
break;
case STATE_WaitFormUp:
if (digitalRead(senFormUp) == HIGH)
{
digitalWrite(keyFormUp, LOW); // Отключение подъема формы
digitalWrite(keyBulgeOn, LOW); // Отключение раздува
digitalWrite(keyVacuumOn, HIGH); // Включение вакуума
// Включаю таймер
SetTimmerOnMillis(currentVacuumOnCountSec, loopVacuumOnCountSec, vacuumOnCountSec);
digitalWrite(keyVacuumOn, LOW); // Отключение вакуума
digitalWrite(keyBlowingupOn, HIGH); // Включение поддува воздуха
// Включаю таймер
SetTimmerOnMillis(currentBlowingupOnCountSec, loopBlowingupOnCountSec, blowingupOnCountSec);
digitalWrite(keyBlowingupOn, LOW); // Отключение поддува воздуха
digitalWrite(keyFrameUp, HIGH); // Запуск подъема рамки
state = STATE_WaitFrameUp;
Serial.println("A_8");
}
break;
case STATE_WaitFrameUp:
if (digitalRead(senFrameUp) == HIGH)
{
digitalWrite(keyFrameUp, LOW); // Отключение подъема рамки
state = STATE_None;
Serial.println("End Auto Cycle");
}
break;
}
}
else if (digitalRead(btnMode) == LOW)
{
// Ручной режим, отладка
if (digitalRead(btnFrameDown) == HIGH && digitalRead(senFrameDown) != HIGH)
{
digitalWrite(keyFrameDown, HIGH); // Запуск опускания рамки
Serial.println("M_1");
}
else if ((digitalRead(btnFrameDown) == LOW || digitalRead(senFrameDown) == HIGH))
{
if (digitalRead(keyFrameDown) == HIGH)
{
digitalWrite(keyFrameDown, LOW); // Остановка опускания рамки
Serial.println("M_1_1");
}
}
if (digitalRead(btnPlateForward) == HIGH && digitalRead(senPlateForward) != HIGH)
{
digitalWrite(keyPlateForward, HIGH); // Запуск плиты вперед
Serial.println("M_2");
}
else if ((digitalRead(btnPlateForward) == LOW || digitalRead(senPlateForward) == HIGH))
{
if (digitalRead(keyPlateForward) == HIGH)
{
digitalWrite(keyPlateForward, LOW); // Остановка плиты вперед
Serial.println("M_2_1");
}
}
if (flagStartPlate == LOW && digitalRead(btnStartPlate) == HIGH && digitalRead(senPlateStartTimmer) != HIGH)
{
digitalWrite(keyStartPlate, HIGH); // Включение обогрева плиты
flagStartPlate = HIGH;
Serial.println("M_3");
}
else if (digitalRead(senPlateStartTimmer) == HIGH)
{
if (flagStartPlate == HIGH && digitalRead(keyStartPlate) == HIGH)
{
// Включаю таймер
SetTimmerOnMillis(currentPlateStartTimmer, loopPlateStartTimmer, plateStartTimmerCountSec);
digitalWrite(keyStartPlate, LOW); // Отключение обогрева плиты
flagStartPlate = LOW;
Serial.println("M_3_1");
}
}
if (digitalRead(btnPlateBack) == HIGH && digitalRead(senPlateBack) != HIGH)
{
digitalWrite(keyPlateBack, HIGH); // Запуск плиты назад
Serial.println("M_4");
}
else if ((digitalRead(btnPlateBack) == LOW || digitalRead(senPlateBack) == HIGH))
{
if (digitalRead(keyPlateBack) == HIGH)
{
digitalWrite(keyPlateBack, LOW); // Остановка плиты назад
Serial.println("M_4_1");
}
}
currentBtnBulgeOn = Debounce(lastBtnBulgeOn, btnBulgeOn);
if(currentBtnBulgeOn == HIGH && flagBulgeOn == LOW)
{
flagBulgeOn = HIGH;
}
if(currentBtnBulgeOn == LOW && flagBulgeOn == HIGH)
{
digitalWrite(keyBulgeOn, !digitalRead(keyBulgeOn)); // Включаем или отключаем раздув
if (digitalRead(keyBulgeOn) == HIGH)
{
Serial.println("M_5");
}
else
{
Serial.println("M_5_1");
}
flagBulgeOn = LOW;
}
if (digitalRead(btnFormUp) == HIGH && digitalRead(senFormUp) != HIGH)
{
digitalWrite(keyFormUp, HIGH); // Запуск подъема формы
Serial.println("M_6");
}
else if ((digitalRead(btnFormUp) == LOW || digitalRead(senFormUp) == HIGH))
{
if (digitalRead(keyFormUp) == HIGH)
{
digitalWrite(keyFormUp, LOW); // Отключение подъема формы
Serial.println("M_6_1");
}
}
currentBtnVacuumOn = Debounce(lastBtnVacuumOn, btnVacuumOn);
if(currentBtnVacuumOn == HIGH && flagVacuumOn == LOW)
{
flagVacuumOn = HIGH;
}
if(currentBtnVacuumOn == LOW && flagVacuumOn == HIGH)
{
digitalWrite(keyVacuumOn, !digitalRead(keyVacuumOn)); // Включаем или отключаем вакуума
if (digitalRead(keyVacuumOn) == HIGH)
{
Serial.println("M_7");
}
else
{
Serial.println("M_7_1");
}
flagVacuumOn = LOW;
}
currentBtnBlowingupOn = Debounce(lastBtnBlowingupOn, btnBlowingupOn);
if(currentBtnBlowingupOn == HIGH && flagBlowingupOn == LOW)
{
flagBlowingupOn = HIGH;
}
if(currentBtnBlowingupOn == LOW && flagBlowingupOn == HIGH)
{
digitalWrite(keyBlowingupOn, !digitalRead(keyBlowingupOn)); // Включаем или отключаем вакуума
if (digitalRead(keyBlowingupOn) == HIGH)
{
Serial.println("M_8");
}
else
{
Serial.println("M_8_1");
}
flagBlowingupOn = LOW;
}
if (digitalRead(btnFrameUp) == HIGH && digitalRead(senFrameUp) != HIGH)
{
digitalWrite(keyFrameUp, HIGH); // Запуск подъема рамки
Serial.println("M_9");
}
else if ((digitalRead(btnFormUp) == LOW || digitalRead(senFrameUp) == HIGH))
{
if (digitalRead(keyFrameUp) == HIGH)
{
digitalWrite(keyFrameUp, LOW); // Отключение подъема рамки
Serial.println("M_9_1");
}
}
}
}
// Функция таймер с задержкой, вместо delay
void SetTimmerOnMillis(long currentPlateStartTimmer, long loopPlateStartTimmer, int plateStartTimmerCountSec)
{
currentPlateStartTimmer = millis(); // считываем время, прошедшее с момента запуска программы
loopPlateStartTimmer = currentPlateStartTimmer;
while (currentPlateStartTimmer <= (loopPlateStartTimmer + (plateStartTimmerCountSec * 1000)))
{
currentPlateStartTimmer= millis();
}
}
// Функция удаления дребезга кнопок
boolean Debounce(boolean lastValue, int switchPin)
{
boolean currentValue = digitalRead(switchPin);
if (lastValue != currentValue)
{
long currentTime = millis();
long loopTime = currentTime;
while (currentTime <= (loopTime + 5))
{
currentTime = millis();
}
currentValue = digitalRead(switchPin);
}
return currentValue;
}
Конечное решение на сегодняшний день. Еще появится ручной режим, но это все после того, как станок будет сделан в металле . Может еще какие-то удобства для оператора.
Всем привет!
изучая arduino наткнулся на проблему "дребезга кнопки". Написал не большой sketch на две тактовые кнопки и две led. Впрочем посмотрите здесь пожалуйста:
int flag=0;
int pin1=22;
int pin2=25;
int led1=28;
int led2=30;
void setup()
{
pinMode(22,INPUT);
pinMode(25,INPUT);
pinMode(28,OUTPUT);
pinMode(30,OUTPUT);
}
void loop()
{
if (digitalRead(22)==HIGH&&flag==0)
{
digitalWrite(28,!digitalRead(28));
flag=1;
}
if (digitalRead(22)==LOW&&flag==1)
{
flag=0;
}
if (digitalRead(25)==HIGH&&flag==0)
{
digitalWrite(30,!digitalRead(30));
flag=2;
}
if (digitalRead(25)==LOW&&flag==2)
{
flag=0;
}
}
На второй кнопке при быстрой перемене "включил-выключил" заметны сбои. Может кто-нибудь сможет объяснить почему так происходит. Заранее спасибо.
Да дребезг я так думаю. При быстрой перемене включения кнопки"pin2" второй светодиод даёт сбои. Но ведь этого не должно быть потому как я использовал переменную flag или всё таки нужно использовать функцию delay
Всем привет!
изучая arduino наткнулся на проблему "дребезга кнопки". Написал не большой sketch на две тактовые кнопки и две led. Впрочем посмотрите здесь пожалуйста:
На второй кнопке при быстрой перемене "включил-выключил" заметны сбои. Может кто-нибудь сможет объяснить почему так происходит. Заранее спасибо.
ваш скетч не гарантирует программную обработку дребезга, по большому счету у вас получилась "русская рулетка". совпадет считывание значения дребезжащей кнопки с с предполагаемым состоянием флага, меняемого к томуже обеими кнопками или нет
примерно так нужно сделать:
#define DELAY_MS 50;
unsigned long ignoreInputs[2]={0,0};
int pin[2][2]={{22,25},{28,30}};
void setup()
{
pinMode(pin[0][0],INPUT);
pinMode(pin[0][1],INPUT);
pinMode(pin[1][0],OUTPUT);
pinMode(pin[1][1],OUTPUT);
}
void loop()
{
if (digitalRead(pin[0][0])==HIGH&& !ignoreInputs[0])
{
digitalWrite(pin[1][0],!digitalRead(pin[1][0]));
ignoreInputs[0]=millis()+DELAY_MS;
}
if (digitalRead(pin[0][1])==HIGH&& !ignoreInputs[1])
{
digitalWrite(pin[1][1],!digitalRead(pin[1][1]));
ignoreInputs[1]=millis()+DELAY_MS;
}
if(ignoreInputs[0]>=millis())ignoreInputs[0]=0;
if(ignoreInputs[1]>=millis())ignoreInputs[1]=0;
}
Благодарю за многочисленную помощь. А вот ещё кое-что сам нашёл, работает безукоризненно. Только надо библиотеку "Bounce" в ардуино импортировать. Вот новый скетч:
Вопрос. Почему фунция setup у меня вызывается постоянно?
А как вы об этом узнали? В ней не производится никаких действий. А если функция "ничего не делает", то как можно было узнать что она "постоянно вызывается"?
the_wall пишет:
Т.е. на экране у меня через раные промежутки времени происходит как бы перезагрузка.
Перезагрузка может происходит по железным причинами (плохой кабель, глючный USB порт, где-то что-то коротит, слишком большая нагрузка), так и по софтовым (например у вас висит какая-то софтина, которая постоянно открывает COM-порт, а это вызывает ребут дуины). Или сами открывает сериал монитор и вызываете "перезагрузку".
Даже если тупо вывести один текст, без кнопок, т.е. так
#include <LiquidCrystal.h>
LiquidCrystal lcd(10, 11, 5, 4, 3, 2);
void setup()
{
/* Инициализируем дисплей: 2 строки по 16 символов */
lcd.begin(16, 2);
/* Выводим на дисплей традиционную фразу (: */
lcd.print("hello, world!");
}
void loop()
{
}
То на экране через равне промежутки времени после "!" появляется типа курсор, который заполняет оставшиеся 3 клетки до конца строки. А так же начинает моргать тестовый диод. Хотя на его порт я ничего не подаю.
Если дописать так
void loop()
{
lcd.setCursor(0, 1);
/* Выводим на дисплей число секунд, прошедших с момента старта Arduino */
lcd.print(millis() / 1000);
}
То получается каждые 3 секнду обновляется экран и отсчет идет заново
Прокомментируйте кто-нибудь, зачем во многих примерах в это теме инвертируют значения и как это помогает с дребезгом контактов?
// плюс защита от "дребезга" 100% - почему?
digitalWrite(13,!digitalRead(13));
flag=1;
//это нужно для того что бы с каждым нажатием кнопки
//происходило только одно действие
// плюс защита от "дребезга" 100%
Инвертация состояния выхода это просто действие. Вместо него может быть все что угодно. В примерах я инвертирую состояние светодиода (вкл или выкл) просто для наглядности. С фильтрацией дребезга кнопки это никик не связано (за исключением приведенной вами переменной flag).
Никак это от дребезга не спасает, просто никто не читал что там понаписал автор этих комментариев, не понимая по каким причинам у него отсутствует дребезг.
Прям уж жутко... вместо i опечатка l, перекопируйте еще раз.
Мне интересно, почему народ не использует переменные, а вместо этого, например, читает из порта дважды?
Аналогично, постоянно используют конструкции millis() в сравнениях, потом снова считывают millis().
Вцелом, может быть это и пофигу для этих примеров, однако, я в таких случаях использую локальные переменные.
Смысл в том, что читая из одного и того же порта дважды, вы рискуете считать разные значения, аналогично с millis.
Например:
Понятно, что иногда это нужно (читать несколько раз), однако вылавливать такие глюки бывает очень сложно.
Понятно, что можно сказать "да это тестовая прога, пофиг", но ИМХО - это плохая практика.
Не настаиваю, пишите как хотите ;)
Еще можно так попробовать оптимизировать:
Дополнение.
Включение чего либо по двойному клику.
Вот этот код из первого сообщения в этой теме!
подскажите пожалуйста в 18 строке в if часте выражения есть число 500, как я понял это по сути время в миллисекундах
так вот , я написал нечто подобное только для выключения, но выключать мне устройство нужно через 3 минуты
я ставлю вместо 500 к примеру 180000 и и в 29 строке меняю значение с 5 на 2
Запускаю программу и засекаю время проходит примерно 45 секунд и срабатывает отключение!!!
что я делаю не так??
что я делаю не так??
Не ту перемеменную изменяете. Вот так будет работать.
Инвертация пина каждые три минуты.
Большое спасибо за помощь все работает как надо!!!
А все потому что в моем коде много лишнего и для отражения сути проблемы с которой я столкнулся и была скопирована часть кода из этой темы!!!
все для того чтобы человек который вызвался мне помогать, мог с наименьшими трудозатратами подсказать решение моей проблемы!!!
Могу вас заверить на все 100% что данный код, если нажата кнопка, включит/выключит светодиод не через 45 секунд, а ровно через 6 минут. Поэтому показав пример рабочего кода, вместо своего, вы сделали все для того что бы вам никто не смог помочь.
nestandart "ткнул пальцем в небо" и вам просто повезло, что помогло именно такое решение, и вы попрежнему не знаете в чем была проблема и в следующий раз сделаете эту же ошибку.
для того чтобы все прояснилось привожу свой вариант кода!!!
а было вот так
и срабатывала ACC LOW через 45 секунд!
Вам нужно почитать про типы данных, а именно про тип int, в описании которого написанно, что данный тип может хранить числа от -32768 до 32767, а вы пытаетесь в него записать 180000, поэтому нужно просто поменять в 5-й строке тип переменной interval2 на например long и все заработает.
Так же если вы хотите 3 минуты, а не 6 то и условие в 65 строке if(val >=2) нужно поменять на if(val >=1).
leshak, не чистите пока тему. Мне интересно как быстро triada13 найдет свою ошибку.
Прошу прощения что долго не отвечал.
Сегодня просмотрел свой код "вооруженным" глазом, и нашел свой касяк: я третий опеатор цикла if поместил во внутрь скобок первого оператора цикла if. То есть после val++; должно быть две закр. скобки "}".
Да. Именно так.
Здраствуйте.
Спасибо за проделанный труд, очень полезная информация.
Делаю свои робкие шаги в освоении Arduino.
Как правильно сделать, данное решение.
Есть кнопка, и концевик (по сути, тоже кнопка).
Нажиамем и удерживаем кнопку, запускается пневмо цилинд и идет до концевика или пока кнопка не отпущена. При этом он не должен выполнять операцию 1 и операцию 3.
У меня в голове получилось такое решение, но может оно не коректно
Разнести 1,2,3 оперции по кейзам.
Код корявый, знаю, но сама идея правильна?
>>Код корявый, знаю<<
Давайте весь код.
>>но сама идея правильна?<<
Не совсем. Использование while нецелесообразно. Получается так что вся ваша программа стоит колом, пока вы не выйдете из while. Это не есть хорошо.
>> Давайте весь код.
Его еще нет, пока обдумываю как сделать.
Этот набил, чтобы было понятнее.
>> Получается так что вся ваша программа стоит колом, пока вы не выйдете из while. Это не есть хорошо.
Да, я это понимаю. Но меня это не смущало, пока вы об этом не упомянули.
Переменная state, будет меняться по прерыванию от концевика. Она может не изменить из-за цикла?
>> Использование while нецелесообразно
А как это делают?
Нужно не просто включить выключить, а именно нажать и держать, пока нажата кнопка цилиндр идет.
Все это можно сделать с помощью конструкций if else.
Вы полностью весь алгоритм набросайте. ПОсмотрим что можно сделать.
Я так понял, вы предлагаете проверять на каждом выполнении loop и выставлять включение, выключение.
Ок, думаю, к обеду завтра напишу.
И заодно проверю, срабатывает прерывание и таймер, то, что он останавливает ход выполнения это не минус, в данном конкретном случае.
Спасибо.
>>Делаю свои робкие шаги в освоении Arduino.
Как правильно сделать, данное решение.<<
Вы спросили как правильно ?
Я сказал свое мнение.
Тем более что это начало вашей дружбы с МК. И , изначально привыкать к вот таким решениям не стоит. Их нужно применять когда нет другого варианта.
Я имею в виду торможение (а тем более остановку) программы.
>> Вы спросили как правильно ?
>> Я сказал свое мнение.
Наверно я не правильно выразился.
>>Я так понял, вы предлагаете проверять на каждом выполнении loop и выставлять включение, выключение.
Просто уточнял, правильно ли вас понял.
>> И заодно проверю, срабатывает прерывание и таймер, то, что он останавливает ход выполнения это не минус, в данном конкретном случае.
Это простое любопытсво, во мне заиграло:).
Разумеется, хочется правильно, поэтому и обратился.
Уф, даже быстрее управился, думал уйдет день.
Пока не оконченная, без прерываний (пока читаю значения концевика на прямую, если будет не достаточно тогда подыму их) и оптимизаций, еще код не весь закомментирован.
Но суть будет понятна, чтобы вы смогли увидеть проблему в целом. В ручной режиме, именно в нем используется такое нажатие.
Сейчас коректно?
Исправил в 18.47, там была ошибка, оказывается порты с 14 по 21, как-то забавно себя ведут.
Код очень похож на C#, мне моментом стало все понятно.
Вот в электронике пока, ни чего не смылю.
Раз меня не поправили буду считать, что я понял правильно.
Через неделю изучения, уже могу написать программу для простого станочка, рад как ребенок.
nestandart большое спасибо.
Извиняюсь , но я еще не изучал вашу программу.
Занят с срочным заказом. Посмотрю завтра.
Конечное решение на сегодняшний день. Еще появится ручной режим, но это все после того, как станок будет сделан в металле . Может еще какие-то удобства для оператора.
Всем привет!
Народ, подскажите, лучше программно защищаться от дребезга или использовать кондер параллельно кнопке?
Мое мнение, лучше сделать защиту от дребезга аппаратно, тогда для программы места больше будет.
Т.е. кондера параллельно кнопке достаточно? Или надо мастрячить как тут http://creatiff.realax.ru/?cat=spmikro&page=smikr23 ?
Кондер рационален лишь в положительной логике. Программная защита лучше всего. При том что я привел примеры программной защиты .
ну если програмка маленькая и вынуждают габариты то да, но на мой взгляд тригер лучше. Хотя на вкус и цвет.....
это зависит от того кому что ближе, пвяльник или програмный код.
А если куча кнопок - триггеры, обвязка. Места на плате займут много и мороки прибавят.
Народ, привет!
Всё же, разъясните, для аппаратного подавления дребезга какую схему применять?
Всем привет!
изучая arduino наткнулся на проблему "дребезга кнопки". Написал не большой sketch на две тактовые кнопки и две led. Впрочем посмотрите здесь пожалуйста:
На второй кнопке при быстрой перемене "включил-выключил" заметны сбои. Может кто-нибудь сможет объяснить почему так происходит. Заранее спасибо.
Почему происходит что? дребезг?
Дребезг контактов
Да дребезг я так думаю. При быстрой перемене включения кнопки"pin2" второй светодиод даёт сбои. Но ведь этого не должно быть потому как я использовал переменную flag или всё таки нужно использовать функцию delay
В вашем примере нет антидребезга, delay() как один из вариантов устранения дребезга, посмотрите стандартный пример Debounce.
переменная flag не спасает от дребезга.
Всем привет!
изучая arduino наткнулся на проблему "дребезга кнопки". Написал не большой sketch на две тактовые кнопки и две led. Впрочем посмотрите здесь пожалуйста:
На второй кнопке при быстрой перемене "включил-выключил" заметны сбои. Может кто-нибудь сможет объяснить почему так происходит. Заранее спасибо.
ваш скетч не гарантирует программную обработку дребезга, по большому счету у вас получилась "русская рулетка". совпадет считывание значения дребезжащей кнопки с с предполагаемым состоянием флага, меняемого к томуже обеими кнопками или нет
примерно так нужно сделать:
flag не дает полной защиты от дребезга. Он нужен для того чтобы действие запрограмированое на нажатие кнопки не повторялось при удержании кнопки.
Для защиты от дребезга введите временную задержку delay(10); или millis();.
Благодарю за многочисленную помощь. А вот ещё кое-что сам нашёл, работает безукоризненно. Только надо библиотеку "Bounce" в ардуино импортировать. Вот новый скетч:
Всем привет.
Имеется Arduino Uno R3, программы компелирую и гружу через Arduino 1.5.2
Вопрос. Почему фунция setup у меня вызывается постоянно?
Вот код примера
#include <LiquidCrystal.h>
LiquidCrystal lcd(10, 11, 5, 4, 3, 2);
const int buttonPin = 9; // номер входа, подключенный к кнопке
int buttonState = 0; // переменная для хранения состояния кнопки
void setup()
{
pinMode(buttonPin, INPUT);
}
void loop()
{
buttonState = digitalRead(buttonPin);
if (buttonState == LOW) {
lcd.begin(16, 2);
lcd.print("hello, world!");
}
else {
lcd.begin(16, 2);
lcd.print("hello, world33333!");
}
}
Т.е. на экране у меня через раные промежутки времени происходит как бы перезагрузка.
Возможно кнопка подключена неправильно (БЕЗ ПОДТЯЖКИ).
Так же нужно использовать оператор lcd.clear(); иначе у вас постоянно будут выводиться ваши 33333.
Вопрос. Почему фунция setup у меня вызывается постоянно?
А как вы об этом узнали? В ней не производится никаких действий. А если функция "ничего не делает", то как можно было узнать что она "постоянно вызывается"?
Т.е. на экране у меня через раные промежутки времени происходит как бы перезагрузка.
Перезагрузка может происходит по железным причинами (плохой кабель, глючный USB порт, где-то что-то коротит, слишком большая нагрузка), так и по софтовым (например у вас висит какая-то софтина, которая постоянно открывает COM-порт, а это вызывает ребут дуины). Или сами открывает сериал монитор и вызываете "перезагрузку".
Спасибо за ответы.
Даже если тупо вывести один текст, без кнопок, т.е. так
#include <LiquidCrystal.h>
LiquidCrystal lcd(10, 11, 5, 4, 3, 2);
void setup()
{
/* Инициализируем дисплей: 2 строки по 16 символов */
lcd.begin(16, 2);
/* Выводим на дисплей традиционную фразу (: */
lcd.print("hello, world!");
}
void loop()
{
}
То на экране через равне промежутки времени после "!" появляется типа курсор, который заполняет оставшиеся 3 клетки до конца строки. А так же начинает моргать тестовый диод. Хотя на его порт я ничего не подаю.
Если дописать так
void loop()
{
lcd.setCursor(0, 1);
/* Выводим на дисплей число секунд, прошедших с момента старта Arduino */
lcd.print(millis() / 1000);
}
То получается каждые 3 секнду обновляется экран и отсчет идет заново
Может проблема с самим ардуино?
Походу так и есть, перезалей бутлоадер, может он косячит.
Прокомментируйте кто-нибудь, зачем во многих примерах в это теме инвертируют значения и как это помогает с дребезгом контактов?
// плюс защита от "дребезга" 100% - почему?
Инвертация состояния выхода это просто действие. Вместо него может быть все что угодно. В примерах я инвертирую состояние светодиода (вкл или выкл) просто для наглядности. С фильтрацией дребезга кнопки это никик не связано (за исключением приведенной вами переменной flag).
Никак это от дребезга не спасает, просто никто не читал что там понаписал автор этих комментариев, не понимая по каким причинам у него отсутствует дребезг.
Эту тему я прочитал всю, но не смог понять как помогает от дребезга?
Никак это от дребезга не помогает
Что не ясно из этой фразы?