Попытка разрешить недопустимое преобразование из «байта» {он же «беззнаковый символ»} в
Я пытаюсь использовать существующую библиотеку Arduino на Raspberry Pi Pico. Библиотека находится здесь:
https://github.com/j-bellavance/EdgeDebounce/tree/master
Это основано на интересной идее из блога Джека Ганселя: http://www.ganssle.com/debouncing.htm
Библиотека отлично работает на ATMega 328, но при переходе на Raspberry Pi Pico возникли две ошибки.
Первая проблема была решена путем редактирования последней строки EdgeDebounce.h следующим образом:
//#endif; // Версия Arduino ATMega
#endif // Версия Pico, также работает на ATMega
Второй вариант немного сложнее. Вот соответствующий раздел кода, это строки 78–102 в EdgeDebounce.cpp:
byte EdgeDebounce::debounce(byte pin) {
unsigned long pinStatus;
do {
pinStatus = 0xffffffff;
for (byte i = 1; i <= MYsensitivity; i++) pinStatus = (pinStatus << 1) | digitalRead(pin);
} while ((pinStatus != debounceDontCare) && (pinStatus != 0xffffffff));
return byte(pinStatus & 0x00000001);
}//debounce----------------------------------------------- --------------------------------------------------
//updateStatus============================================= ====================
//После выпуска EdgeDebounceLite я понял, что EdgeDebounce может больше
//С помощью этого небольшого фрагмента кода EdgeDebounce может вернуться, если переключатель
// .закрыто(); //Проведение тока
// .открыт(); //Не проводит ток
// .Роза(); //Просто перешел из открытого состояния в закрытое
// .упал(); //только что перешёл из закрытого состояния в открытое
//------------------------------------------------ -------------------------------
void EdgeDebounce::update() {
byte newStatus = debounce();
if (MYmode == PULLUP) newStatus = !newStatus;
if (MYstatus == OPEN && newStatus == CLOSED) MYrose = true;
else MYrose = false;
if (MYstatus == CLOSED && newStatus == OPEN) MYfell = true;
else MYfell = false;
MYstatus = newStatus;
}//обновлять---------------------------------------------- ---------------------------
Когда я пытаюсь скомпилировать, я получаю следующую ошибку:
c:\Users\thisuser\Documents\Arduino\libraries\EdgeDebounce\EdgeDebounce.cpp: In member function 'void EdgeDebounce::update()':
c:\Users\thisuser\Documents\Arduino\libraries\EdgeDebounce\EdgeDebounce.cpp:102:14: error: invalid conversion from 'byte' {aka 'unsigned char'} to 'pinStatus' [-fpermissive]
102 | MYstatus = newStatus;
| ^~~~~~~~~
| |
| byte {aka unsigned char}
exit status 1
Compilation error: exit status 1
Итак, я вижу, что байт "newStatus" не преобразуется в "pinStatus" который является беззнаковым длинным. Я выполнил несколько поисковых запросов в Google, но так и не смог понять, что можно исправить.
@Jeff Haas, 👍4
Обсуждение2 ответа
Лучший ответ:
В C и во многих достандартных C++ ничто не мешает вам просто присвоить целочисленное значение переменной перечислимого типа. В стандарте C++ (начиная с 1998 года) это требует явного преобразования типов («приведение»).
Ядро AVR Arduino
расходные материалы
опция -fpermissive
для компилятора, которая, среди прочего, позволяет неявно
преобразование, которое они выполняют, несмотря на то, что они не соответствуют стандартам C++. Что бы вы ни использовали (вероятность: это или это) для RPI Pico Ядро Arduino не предоставляет опцию -fpermissive
. Многие ядра Arduino этого не делают и, вероятно, не должны этого делать.
Вы можете изменить файл Platform.txt ядра RPI Pico, чтобы предоставить параметр -fpermissive
для g++, но, вероятно, лучше сделать код совместимым.
Минимальные изменения
Вероятно, существуют десятки способов сделать это, но комбинация минимального и приятного для любителей C++, вероятно, выглядит так:
MYstatus = static_cast<pinStatus>(newStatus);
Альтернативные варианты
MYstatus = static_cast<decltype(MYstatus)>(newStatus); // любитель
MYstatus = (pinStatus)newStatus; // традиционный состав
MYstatus = pinStatus(newStatus); // приведение в стиле функции
MYstatus = (decltype(MYstatus))newStatus; // уххх
MYstatus = (decltype(MYstatus))(newStatus); // конечно... почему бы и нет?
static_cast
объявляет намерение так, как этого не делают другие типы приведения. decltype
позволит этой строке лучше пережить изменения типа MYstatus, но decltype
не так широко известен.
Альтернативно без преобразования типов
Вы также можете заметить, что возвращаемый байт(pinStatus & 0x00000001);
— это единственный пункт возврата из
byte EdgeDebounce::debounce(byte pin)
. Итак, вы знаете, что эта функция возвращает либо 0 (ложь), либо 1 (правда). Именно это и произойдет при применении & 1
.
Они определили тип перечисления:
enum pinStatus {OPEN, CLOSED};
Правила C и C++ (даже предстандартных C++) присваивают эти константы числовые значения 0 и 1, где им не были явно заданы значения и они были перечислены в указанном порядке.
Итак, вы можете заменить MYstatus = newStatus;
на:
{
if (newStatus) {
MYstatus = CLOSED;
} else {
MYstatus = OPEN;
}
}
Или используйте тернарный оператор, если хотите не возражать против того, чтобы люди пытались с вами спорить:
MYstatus = newStatus ? CLOSED : OPEN;
Очевидно, также возможно использовать фигурные скобки для приведения в стиле функции без диагностики сужающего преобразования, чего я не ожидал в этом случае. Но я не буду редактировать это снова, просто чтобы упомянуть об этом., @timemage
Спасибо, что нашли время написать такой подробный ответ! - Я использую ядро Earle Philhower RP2040. - Я читал (и перечитываю) ваши комментарии, пока не понял их все. - Я протестировал все предложенные вами выше исправления, и все они работают. Я не возражаю против тернарного оператора, но я приму первое предложенное вами изменение. Еще раз спасибо., @Jeff Haas
pinStatus
— это перечисление:
enum pinStatus {OPEN, CLOSED};
Опубликованный вами pinStatus — это локальная переменная, не имеющая ничего общего с pinStatus
в файле EdgeDebounce.h.
Ошибка указывает на то, что вы не можете назначить беззнаковый символ перечислению, которое может содержать только OPEN и CLOSED. Беззнаковый символ может содержать и другие значения.
Тот, кто это написал, создал какой-то запутанный код.
- Запуск 7-контактного OLED-дисплея с 4 контактами (I2C)
- Какие Arduino поддерживают ATOMIC_BLOCK?
- Как определить, было ли нажато более одной кнопки
- Как масштабировать растровое изображение (массив uint8_t) в Arduino?
- Как использовать существующую (не специфичную для Arduino) библиотеку с вложенными папками в Arduino IDE?
- Выбор PIN для подключения радиочастотного приемника
- Попытка прочитать разные уровни газа с помощью датчика газа MQ2
- Используйте ISR внутри библиотеки более элегантно
Где объявлен «pinStatus»? Не внутри EdgeDebounce::debounce — это локальное объявление., @Nick Gammon