Всем привет. Стандартно - нуб. Причем полный. Но есть желание учиться. Поэтому прошу не код написать, а так сказать в стиле "для чайника" объяснить принцип. Код я попытаюсь сам написать. Имеем числовой ряд, пусть будет от 0 до 255. В данном ряду имеем число А (0<=A<=255). К числу А можем подойти как приращением от нуля, так и уменьшением от 255. При достижении А снизу (т.е. от нуля к А) необходимо выполнить функцию 1, при достижении А сверху (т.е. от 255 к А) необходимо выполнить фунцкию 2. Надеюсь понятно написал. Собственно, как образом определить с какой стороны мы подошли к А?
Иметь и изучать предыдущее значение А : если А == требуемому значению если А(старое) меньше чем А (новое) то выполняем функцию 1иначе выполняем функцию 2конец
Я так понимаю, что старое значение для первой проверки надо заранее задать. А после функции 1 и функции 2 надо старому значению присвоить текущее значение А. Код (Text): int val = 0; int oldA = 0; int A = 58; if (val == A && oldA < A) { function 1; // здесь любой код val++; oldA = A; } else if (val == A && oldA > A) { function 2; // здесь любой код val++; oldA = A; } else {oldA=0}; } Поправьте пожалуйста, если что-то не так. У меня большие сомнения по поводу else {oldA=0};
Оно не может не быть известно, если у Вас А меняется. Это А откуда то же берется? Откуда? Первый раз, возможно, А не имеет истории, но в следующий и все последующие разы - имеет. Для первого раза, включения следует сделать отдельное решение. Но все зависит от конкретики. Код (C): #define CHECK 127 // Постоянное число, с которым нужно сравнивать byte oldA = 0; byte A; while (1) { A = ... получли данные; if ( A == CHECK ) { if (A > oldA) { function 1 ... } else { function 2 ... } } oldA = A; }
Ладно, открою карты. Числовой ряд - скорость авто. А - значение скорости, при подходе к которому снизу надо выполнить функцию 1. Есть еще значение В - при подходе к нему сверху надо выполнить функцию 2. Вот полный скетч. Там моего практически нет ничего, сплошной копипаст. Но вот блок обработки скорости хотел сам написать, да что-то застопорился. Если не сложно - посмотрите, пожалуйста. Код (Text): /* created Tomasina, forum.amperka.ru created Frud, drive2.ru modified Andrew 'funakoshi' Ryabov 8 April 2015 */ #define BUTTON_PIN 7 #define BUZZER_PIN 4 #define RELAY_PIN 9 #define DISPLAY_PIN 5 int bounceTime = 10; // задержка для подавления дребезга int holdTime = 500; // время, в течение которого нажатие можно считать удержанием кнопки int doubleTime = 1000; // время, в течение которого нажатия можно считать двойным int frequency = 3500; //частота звука "пищалки" int speedMode = 0; //просто чтобы не ругался компилятор int previousSpeed = 0; //скорость в настоящий момент boolean lastReading = false; // флаг предыдущего состояния кнопки boolean buttonSingle = false; // флаг состояния "краткое нажатие" boolean buttonDouble = false; // флаг состояния "двойное нажатие" boolean buttonHold = false; // флаг состояния "долгое нажатие" boolean dispState = false; //флаг "включенности" дисплея парктроника long onTime = 0; // переменная обработки временного интервала long lastSwitchTime = 0; // переменная времени предыдущего переключения состояния volatile unsigned long micros_sp = 0; volatile byte sz = 0; //счетчик обнуления volatile unsigned int sp = 0; //скорость int regim = 1; // текущий режим volatile unsigned int speedUp = 0; //набор скорости volatile unsigned int speedDown = 0; //снижение скорости volatile unsigned int speedLimit = 0; //предел превышения скорости volatile boolean st = false; void setup() { pinMode(BUTTON_PIN, INPUT); // INPUT_PULLUP подключит кнопку через внутренний резистор attachInterrupt(1, speedometr, RISING); pinMode(DISPLAY_PIN, INPUT); //подключаем дисплей парктроника к пину } void loop() { if (sz != 0) { sz--; } else { sp = 0; }; // ================ обработчик состояния кнопки ==================== boolean reading = digitalRead(BUTTON_PIN); /* читаем состояние пина кнопки. Если подключен через внутренний резистор (см. pinMode(BUTTON_PIN, INPUT_PULLUP)), перед digitalRead(BUTTON_PIN) нужен !. */ // проверка первичного нажатия if (reading && !lastReading) { onTime = millis(); } // проверка удержания if (reading && lastReading) { if ((millis() - onTime) > holdTime) { buttonHold = true; } } // проверка отпускания кнопки if (!reading && lastReading) { if (((millis() - onTime) > bounceTime) && !buttonHold) { if ((millis() - lastSwitchTime) >= doubleTime) { lastSwitchTime = millis(); buttonSingle = true; } else { lastSwitchTime = millis(); buttonDouble = true; buttonSingle = false; isButtonDouble(); buttonDouble = false; // сброс состояния после выполнения команды } } if (buttonHold) { buttonDouble = false; isButtonHold(speedMode); buttonHold = false; // сброс состояния после выполнения команды } } lastReading = reading; if (buttonSingle && (millis() - lastSwitchTime) > doubleTime) { buttonDouble = false; isButtonSingle(); buttonSingle = false; // сброс состояния после выполнения команды } // ================ конец обработчика состояния кнопки ================== // ================ обработчик скорости ================================= int val = 0; dispState = digitalRead(DISPLAY_PIN); // если экран включен и скорость поднялась до speedUP снизу, то вкл выкл реле if (sp == speedUp && (speedUp - previousSpeed) > 0 && dispState) { isButtonSingle(); previousSpeed = sp; val++; } else { val = 0; } // если экран выключен и скорость упала до speedDown сверху, то вкл выкл реле if (sp == speedDown && (speedDown - previousSpeed) < 0 && !dispState ) { isButtonSingle(); previousSpeed = sp; val++; } else { val = 0; } // если скорость поднялась до speedLimit снизу, то пробибикать несколько раз //================= конец обработки скорости ================= } // конец loop void isButtonSingle() // действия после одиночного нажатия кнопки { //При однократном "коротком" нажатии кнопки реле замкнётся на 0,5 сек. digitalWrite(RELAY_PIN, HIGH); delay(500); digitalWrite(RELAY_PIN, LOW); } void isButtonDouble() // действия после двойного нажатия кнопки. Автор X-Dron arduino.ru { //Выбрать активный режим (всего 3 режима: speedUp, speedDown, speedLimit) //Просигнализировать о выбранном режиме n-ым количеством бипов (n зависит от активного режима) speedMode = (++speedMode) % 4; if (speedMode == 0) speedMode = 1; for (int i = 0; i < speedMode; i++) { tone(BUZZER_PIN, frequency, 50); delay(200); } } void isButtonHold(int x) // действия после удержания кнопки { //Запомнить значание активному режиму. Об запоминании сигнализировать звуком switch (x) { case 1: //speedUp speedUp = sp; tone(BUZZER_PIN, frequency, 150); break; case 2: //speedDown speedDown = sp; tone(BUZZER_PIN, frequency, 150); break; case 3: //speedLimit speedLimit = sp; tone(BUZZER_PIN, frequency, 150); break; } } void speedometr() { //измеряем частоту на входе спидометра по прерыванию if (!st) { micros_sp = micros(); } else { sp = (1600000 / (micros() - micros_sp)); } st = !st; sz = 30; }
Ну во первых: if (sp == speedUp && (speedUp - previousSpeed) не совсем корректно. ведь sp может и проскочить speedUp. то есть на одной итерации sp<speedUp, а на следующей уже может быть sp>speedUp, то есть порог пройден, а условие не выполнилось думаю вернее так: if (sp >= speedUp && (speedUp - previousSpeed) Логика такая если скорость больше порога или равна ему, а раньше была меньше, значит она прошла порог снизу. С обратным проходом порога - тоже самое.
В принципе, учитывая, что есть еще 2 доп проверки, наверное соглашусь. В идеале, конечно, надо sp == speedUp. P.S. Хотя нет, соглашусь с вами. Мне "==" не принципиально, было бы достаточно точности +- 5 км/ч от speedUp.
Идеал, на то и идеал, что он недостижим техническими средствами В данном случае, имхо лучше получить событие с небольшим опозданием, чем пропустить его совсем.