Удерживайте кнопку/нажмите кнопку/нажмите кнопку
Я хочу управлять серводвигателем таким образом, чтобы
- Если вы нажмете кнопку, вы сможете управлять ею с помощью потенциометра a.
- Если вы нажмете двойное время, вы сможете управлять сервоприводом через инфракрасный порт.
- если удерживать кнопку, шаговый двигатель начнет вращаться из одного положения в другое.
У меня проблема: когда я нажимаю кнопку, происходит бесконечный цикл, и я не могу его остановить. Я пробую другую библиотеку кнопок, но проблема все равно остается. Вот мой код:
// включает библиотеку Servo
#include <Servo.h>
#include <IRremote.h>
#include <OneButton.h>
int state = 0;
int RECV_PIN = 12;
const char type ='W';// W для белого, B для черного. Необходимо сохранять одинарные кавычки, например «B» или «W».
const boolean PCB = 0;// если на плате приемника установлено значение 1, если не установлено значение 0. Подробности смотрите в видео
boolean displayCode = true;// для отображения удаленного кода. если нет, установите значение false
const int SERVO_PIN = 8; // аналоговый вывод, используемый для подключения потенциометра
int angle =90; // начальный угол для сервопривода
int angleStep =10;
const int ANGLE_CENTRE =90;// центр/угол сброса вашего сервопривода
//**** Настройка сервоприводов заканчивается
// удаленные настройки
const String RIGHT="CH+";// перемещаем сервопривод вправо с помощью этой клавиши на пульте дистанционного управления
const String LEFT ="CH-";// перемещаем сервопривод влево с помощью этой клавиши на пульте дистанционного управления
const String CENTRE ="CH";// перемещаем сервопривод в центр с помощью этой клавиши на пульте дистанционного управления
// завершение удаленных настроек
IRrecv irrecv(RECV_PIN);
// Определяет контакты Tirg и Echo ультразвукового датчика
const int trigPin = 10;
const int echoPin = 11;
const int potPin = 0;
const int pushButton = 8;
OneButton button(A1, true);
int value;
// Переменные длительности и расстояния
long duration;
int distance_cm;
Servo myServo; // Создает сервообъект для управления серводвигателем
// это коды хранения массива для White Remote при использовании с версией приемника, отличной от печатной платы
unsigned int whiteRemote[] ={
0xFFA25D, // СН-
0xFF629D, // СН
0xFFE21D, // канал+
0xFF22DD, // |<<
0xFF02FD, // >>|
0xFFC23D, // >||
0xFFE01F, // -
0xFFA857, // +
0xFF906F, // эквалайзер
0xFF6897, // 0
0xFF9867, // 100+
0xFFB04F, // 200+
0xFF30CF, // 1
0xFF18E7, // 2
0xFF7A85, // 3
0xFF10EF, // 4
0xFF38C7, // 5
0xFF5AA5, // 6
0xFF42BD, // 7
0xFF4AB5, // 8
0xFF52AD // 9
};
// бирки клавиш белого пульта
String whiteRemoteKey[] ={
"CH-",
"CH",
"CH+",
"|<<",
">>|",
">||",
"-",
"+",
"EQ",
"0",
"100+",
"200+",
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9"
};
// это коды хранения массива для Black Remote при использовании с версией приемника, отличной от печатной платы
unsigned int blackRemote[] ={
0xFF629D, // ^
0x38D3975C, // <
0x9334F738, // ОК
0x320412D8, // >
0xFFA857, // v
0xFF6897, // 1
0xFF9867, // 2
0xF0C41643, // 3
0xFF30CF, // 4
0xFF18E7, // 5
0xFF7A85, // 6
0xFF10EF, // 7
0xFF38C7, // 8
0xFF5AA5, // 9
0xFF42BD, // *
0xFF4AB5, // 0
0xFF52AD // #
};
// Имена черных удаленных клавиш
String blackRemoteKey[] ={
"^",
"<",
"OK",
">",
"v",
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"*",
"0",
"#"
};
decode_results results;
void setup() {
pinMode(trigPin, OUTPUT); // Устанавливает trigPin как выход
pinMode(echoPin, INPUT); // Устанавливает echoPin в качестве входных данных
Serial. begin(9600);
irrecv.enableIRIn(); // Запускаем приемник
myServo.attach(SERVO_PIN); // Определяет, к какому выводу подключен серводвигатель
button.attachDoubleClick(doubleClick); // связываем функцию, вызываемую с событием doubleClick.
button.attachClick(singleClick); // связываем функцию, вызываемую с событием SingleClick.
button.attachLongPressStop(longClick); // связываем функцию, которая будет вызываться при длительном нажатии.
}
void loop() {
button.tick(); // проверяем статус кнопки
delay(10); // небольшое ожидание между проверкой кнопки
}
// Функция расчета расстояния, измеренного Ультразвуковым датчиком
int calculateDistance(){
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
// Устанавливает trigPin в состояние HiGH на 10 микросекунд
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
duration = pulseIn(echoPin, HIGH); // Считывает echoPin, возвращает время прохождения звуковой волны в микросекундах
//Комментарий от меня!
//расстояние= продолжительность*0.034/2;
//
distance_cm = (duration/2) / 29.1;
return distance_cm;
}
void doubleClick() { // что происходит при двойном щелчке по кнопке
while(1) {
if (irrecv.decode(&results)) {
if(displayCode)Serial.println(results.value, HEX);
validateCode(results.value);// ниже используется "robojaxValidateCode"
irrecv.resume(); // Получаем следующее значение
}
delay(50);// задержка 50 миллисекунд
break;
}
}
void singleClick(){ // что происходит при нажатии кнопки
while(1) {
value = analogRead(potPin);
value = map(value, 0, 1023, 15, 165);
myServo.write(value);
delay(30);
distance_cm = calculateDistance();
Serial.print(value); // Отправляет текущую степень в последовательный порт
Serial.print(","); // Отправляет дополнительный символ рядом с предыдущим значением, который понадобится позже в среде обработки данных для индексации
Serial.print(distance_cm); // Отправляет значение расстояния в последовательный порт
Serial.print("."); // Отправляет дополнительный символ рядом с предыдущим значением, который понадобится позже в среде обработки данных для indexin
}
}
void longClick(){ // что происходит при длительном нажатии кнопки
for(int i=15;i<=165;i++){
myServo.write(i);
delay(30);
distance_cm = calculateDistance();// Вызывает функцию расчета расстояния, измеренного Ультразвуковым датчиком для каждого градуса
Serial.print(i); // Отправляет текущую степень в последовательный порт
Serial.print(","); // Отправляет дополнительный символ рядом с предыдущим значением, который понадобится позже в среде обработки данных для индексации
Serial.print(distance_cm); // Отправляет значение расстояния в последовательный порт
Serial.print("."); // Отправляет дополнительный символ рядом с предыдущим значением, который понадобится позже в среде обработки данных для indexin
}
// Повторяет предыдущие строки от 165 до 15 градусов
for(int i=165;i>15;i--){
myServo.write(i);
delay(30);
distance_cm = calculateDistance();
Serial.print(i);
Serial.print(",");
Serial.print(distance_cm);
Serial.print(".");
}
}
/*
* function: validateCode
* validates the remote code and prints correct key name
* cd is code poassed from the loop
* Written by A. S. for Robojax
*/
void validateCode(int cd)
{
// Декодер Robojax IR Remote
int found=0;
if(type =='W' && !PCB)
{
// Robojax IR White Дистанционный декодер
// если тип установлен на «W» (белый пульт) и PCB=0, тогда проверьте черный код пульта
for(int i=0; i< sizeof(whiteRemote)/sizeof(int); i++)
{
if(whiteRemote[i] ==cd)
{
Serial.print("Key pressed:");
Serial.println(whiteRemoteKey[i]);
servoAction(whiteRemoteKey[i]);// выполняем действие
found=1;
}// если совпадение
}// для
}else{
// если тип установлен на «B» (черный пульт) и PCB = 0, тогда проверьте код черного пульта
for(int i=0; i< sizeof(blackRemote)/sizeof(int); i++)
{
// Robojax IR черный Дистанционный декодер
if(blackRemote[i] ==cd)
{
Serial.print("Key pressed:");
Serial.println(blackRemoteKey[i]);
servoAction(blackRemoteKey[i]);// выполняем действие
found=1;
}// если совпадение
}// для
}// еще
if(!found){
if(cd !=0xFFFFFFFF)
{
Serial.println("Key unkown");
}
}// найденный
}// конец validateCode
/*
*
* servoAction()
* receives string "value" as input and based on the settings,
* sends translates it to servo value and controls servo
* either
* rotates servo to right
* rotates servo to left
* moves the servo to middle
*
*/
void servoAction(String value){
// Демонстрация сервокнопки с ИК-пультом от Robojax.com
while(value == RIGHT){
if (angle > 0 && angle <= 180) {
angle = angle - angleStep;
if(angle < 0){
angle = 0;
}else{
myServo.write(angle); // перемещаем сервопривод на нужный угол
Serial.print("Moved to: ");
Serial.print(angle); // печатаем угол
Serial.println(" degree");
}
}// если
value =".";
delay(100);
}// пока для ПРАВА
while(value == LEFT){
// Демонстрация сервокнопки с ИК-пультом от Robojax.com
if (angle >= 0 && angle <= 180) {
angle = angle + angleStep;
if(angle >180){
angle =180;
}else{
myServo.write(angle); // перемещаем сервопривод на нужный угол
Serial.print("Moved to: ");
Serial.print(angle); // печатаем угол
Serial.println(" degree");
}
}
value =".";
delay(100);
}// пока для LEFT
if(value == CENTRE)
{
angle = ANGLE_CENTRE;
myServo.write(angle); // перемещаем сервопривод в центр под углом 90 градусов
}
// Управление Robojax IR Servo
}//конец действия реле
извините за мой английский. Надеюсь, кто-нибудь мне поможет.
1 ответ
Лучший ответ:
У вас есть бесконечные циклы в функциях вызова события нажатия, после события кнопки вы никогда не возвращаетесь к основному циклу.
Используйте функции событий только для установки переменной состояния, а затем в основном цикле используйте переключатель Case Case, чтобы выбрать код, используемый сервоуправлением, следующим образом:
....
unsigned int status = 0;
....
void doubleClick(){
status = 0;
}
void singleClick(){
status = 1;
}
void longClick(){
status = 2;
}
void setup() {
....
}
void loop {
button.tick(); // проверяем статус кнопки
//задержка(10); // это не нужно.
switch (status){
case 0:{
//действие по двойному клику
}
case 1:{
//действие по одиночному клику
}
case 2:{
//действие при длинном клике
}
}
Внутри каждого случая вставьте соответствующий код, который у вас есть в циклах while(1) функций событий кнопки.
Другой вариант — вставить внутри бесконечных циклов возврат при нажатии кнопки следующим образом:
если (кнопка нажата) возврат;
- Нет функции сопоставления для вызова 'DS3231 (const uint8_t &, const uint8_t &)
- Управлять 2 сервоприводами с последовательным считыванием
- Как запрограммировать 2 ультразвуковых датчика, один на серводвигателе и один прикрепленный на передней стороне автомобиля?
- Arduino ждет, пока кнопка не будет отпущена для активации
- Для сервопривода с непрерывным вращением требуется другой код
- avrdude ser_open() can't set com-state
- Float печатается только 2 десятичных знака после запятой
- ошибка: espcomm_upload_mem failed при загрузке скетча
Пожалуйста, используйте Enum вместо «магического числа»., @Filip Franik
Спасибо за ваш ответ. Но мне нужно, чтобы это действие происходило бесконечно, пока статус кнопки не изменится, например, с одного нажатия на двойное нажатие. Когда я использую оператор if, он не работает должным образом., @Amir Hossein Jobeiri
@AmirHosseinJobeiri Цикл while(1) заменяется основным циклом, поэтому он происходит вечно, пока вы не нажмете кнопку и не измените переменную состояния. Или просто используйте кнопку возврата, нажатую внутри цикла while(1), но дальнейшее расширение кода довольно сложно., @Dorian