Почему игнорируется параметр чувствительности (порог)
Аналоговый потенциометр, подключенный к Arduino. простейшая возможная установка.
Цель состоит в том, чтобы отправлять сообщение через Serial
всякий раз, когда значение изменяется.
Я не хочу сильно спамить последовательное соединение, поэтому значение должно измениться как минимум на 20
(порог чувствительности) перед отправкой пакета сообщения.
Однако на самом деле пакет сообщения отправляется, даже если значение изменилось только на 1
. Почему игнорируется параметр чувствительности?
Обновлено: После отладки я вижу, что он вводит первый оператор IF в read()
. Оператор IF оценивается как 0
, что очень странно. Он не должен был входить в этот оператор IF!
MagicPot.h:
#define MAGIC_POT_MAX_RAW_VALUE_10B 1023
#define MAGIC_POT_MAX_RAW_VALUE_12B 4095
#define MAX_RAW_VALUE_DEFAULT (MAGIC_POT_MAX_RAW_VALUE_10B)
class MagicPot
{
public:
typedef void (*callback_fn)();
MagicPot(uint8_t pin, uint16_t minRead = 0, uint16_t maxRead = MAX_RAW_VALUE_DEFAULT, uint16_t maxRawRead = MAX_RAW_VALUE_DEFAULT): pin(pin), minRead(minRead), maxRead(maxRead), maxRawRead(maxRawRead) {};
void begin();
bool read(uint8_t sensitivity = 5);
uint16_t getValue();
uint16_t getRawValue();
uint8_t pin;
private:
uint16_t minRead;
uint16_t maxRead;
uint16_t maxRawRead;
callback_fn onChangeCallback;
uint16_t value;
uint16_t rawValue;
};
MagicPot.cpp:
void MagicPot::begin()
{
this->onChangeCallback = nullptr;
this->value = 0;
this->rawValue = 0;
pinMode(this->pin, INPUT);
this->read(0);
}
bool MagicPot::read(uint8_t sensitivity)
{
this->rawValue = analogRead(this->pin);
uint16_t value = map(this->rawValue, 0, this->maxRawRead, this->minRead, this->maxRead);
if (abs(value - this->value) > sensitivity)
{
this->value = value;
return true;
}
else if (value < sensitivity && this->value != this->minRead)
{
this->value = minRead;
return true;
}
else if (value + sensitivity > maxRead && this->value != this->maxRead)
{
this->value = this->maxRead;
return true;
}
return false;
}
Код Arduino:
MagicPot analogPots[] =
{
MagicPot(A0),
}
void setup() {
for (MagicPot& x : analogPots) //arr содержит только 1 элемент
x.begin();
}
void loop() {
for (MagicPot& pot : analogPots) //arr содержит только 1 элемент
{
if(true == pot.read(20))
{
CPPacket* analogPotChangedPacket = new CPPacket(HWEvent::Switch, pot.pin, pot.getValue());
SendPacket( &myPacketSerial, analogPotChangedPacket);
delete analogPotChangedPacket;
}
}
}
Фактический вывод: (чтение с компьютера(подключение через последовательный порт))
Тип | Ошибка | Цель | Значение |
---|---|---|---|
Переключить | НЕТ | 54 | 516 |
Переключить | НЕТ | 54 | 515 |
Переключить | НЕТ | 54 | 514 |
Переключить | НЕТ | 54 | 513 |
Ожидаемый результат:
Тип | Ошибка | Цель | Значение |
---|---|---|---|
Переключить | НЕТ | 54 | 516 |
Переключить | НЕТ | 54 | 496 |
Переключить | НЕТ | 54 | 456 |
Переключить | НЕТ | 54 | 436 |
@David, 👍2
Обсуждение1 ответ
Лучший ответ:
Рассмотрите это вычитание:
value - this->value
Как и в любой арифметической операции, операнды подвергаются интегральному преобразованию.
продвижение, затем обычные арифметические преобразования.
Немного упрощая, «интегральное продвижение» означает, что типы меньше
чем int
повышается до int
, тогда как «обычные арифметические преобразования»
означает, что меньший операнд повышается до типа большего. Если
оба типа имеют одинаковый размер, выигрывает тип без знака.
На Arduino Mega int
составляет 16 бит. Так как операнды
вычитание оба uint16_t
, типы не изменяются этими
неявные преобразования. Вычитание выполняется с помощью uint16_t
введите и оберните по модулю 216. Если вы ожидаете −1, вы получаете
65535.
Если вы приведете один из операндов к int16_t
, он будет неявно
преобразуется обратно в uint16_t
с помощью обычных арифметических преобразований и
вы получите тот же результат.
На вашем ПК int
имеет длину 32 бита, поэтому оба операнда получаются неявно.
преобразуется в int
путем интегрального продвижения, и вы получаете ожидаемый
подписанный результат.
Простое решение вашей проблемы – преобразовать все ваши переменные в
int16_t
. Я предлагаю вам всегда использовать подписанные типы по умолчанию и возвращать
к беззнаковым типам, когда вам нужна циклическая семантика
арифметические операции (иногда полезно).
- Как использовать SPI на Arduino?
- esp32, platformio A fatal error occurred: Packet content transfer stopped (received 8 bytes) *** [upload] Error 2
- Подключение HX711 к трехпроводному датчику нагрузки
- Правильное использование * и & при передаче объектов в методах.
- Ошибка "collect2.exe: error: ld returned 1 exit status"
- ISO C++ запрещает принимать адрес неквалифицированной или заключенной в скобки нестатической функции-члена для формирования указателя на функцию-член
- Разница между массивом char и массивом unsigned char
- Печать содержимого файла SD - карты на ЖК-дисплее
вы вычитаете два неподписанных типа, поэтому результат также сохраняется во временном беззнаковом типе. попробуйте
abs((int16_t) value - this->value)
, @Juraj@Juraj: это должно быть либо
abs((int16_t) (value - this->value))
, либоabs((int16_t) value - (int16_t) this->value)
. Или, еще лучше, сделать все подписанным. В противном случае, если только один член вычитания знаковый, беззнаковый тип выигрывает в игре «обычные арифметические преобразования»., @Edgar Bonet@EdgarBonet Спасибо, странное поведение было вызвано uint16. Я протестировал запуск кода (с **uint**) в VisualStudio, и он сработал. Знаете, почему это работало в VS/Win11, но не в Arduino? Отличается ли версия С++? Компилятор? И почему компилятор не предупредил меня? P.s. я совсем новичок в с++, @David