Неожиданное поведение энкодера при увеличении оборотов в минуту
Я использую двигатель постоянного тока с энкодером и пытаюсь вычислить, сколько импульсов записывается в каждом секундном интервале. (обратите внимание, что источник питания 12 В для двигателя)
Схема и код:
int encpin=3;
volatile long npc=0; //new pulse count
volatile long opc=0; //original pulse count
volatile long pulsecount;
unsigned long int newtime;
unsigned long int prevtime=0;
unsigned long int time;
void setup()
{
pinMode(encpin, INPUT_PULLUP);
Serial.begin(9600);
attachInterrupt(digitalPinToInterrupt(encpin),function,RISING);
}
void function(){
npc++;
}
void loop()
{
newtime=millis();
time=newtime-prevtime;
pulsecount=npc-opc;
if(time==1000){
Serial.println(pulsecount);
prevtime+=1000;
opc=npc;
}
}
Кажется довольно интуитивным, что увеличение оборотов должно увеличить количество импульсов, записанных за одну секунду. Однако результаты довольно неустойчивы:
RPM PULSECOUNT
26 2365
32 2367
38 2400
44 2375
52 2400
116 2412
142 2384
195 2416
280 2406
350 3008
416 1580
520 1975
624 2370
730 2334
2737 2188
Увеличение оборотов в минуту иногда увеличивает количество импульсов, но иногда уменьшает его....в чем может быть причина такого поведения?
@satan 29, 👍1
Обсуждение2 ответа
Я думаю что проблема заключается в симуляции tinkercad: Энкодер присоединен к двигателю, и двигатель всегда вращается с одной и той же скоростью. Выбор другой частоты вращения компонента изменяет передаточное число и частоту вращения вала, но не двигателя. Это означает, что число, выводимое через 1 с, всегда должно быть одним и тем же. Почему это не совсем то же самое, могут сказать только программисты моделирования. Возможно, это связано со скоростью моделирования, потому что там я получаю совершенно другие цифры.
Чтобы точно сказать, что происходит, необходима документация компонентов моделирования и самой симуляции.
какие цифры вы получаете с вашей стороны? И что еще более важно, следуют ли они ожидаемой тенденции: то есть растут ли вместе с оборотами?, @satan 29
они находятся в диапазоне ~1600 и изменяются случайным образом в зависимости от настройки оборотов двигателя, но они также не согласованы во время 1 запуска, @Kerbolosh
Одним из важных принципов, которые следует усвоить при работе с прерываниями, является принцип атомарных операций. При работе с любыми данными, которые не могут быть обработаны одной инструкцией по сборке, крайне важно защитить их от изменения на полпути при любом чтении.
В вашей ситуации вы работаете с 32-битными значениями. На 8-битном микроконтроллере для манипулирования ими требуется много-много команд, и в любой момент во время этой манипуляции может сработать прерывание и изменить значение, испортив ваши показания.
В программировании существует понятие, называемое критическими секциями. Это "заблокированные" биты кода, где никакие прерывания не допускаются, пока вы делаете все необходимое с вашими общими переменными. По понятным причинам вы хотите, чтобы эти разделы были как можно более краткими.
Кроме того, вам не нужно вычислять количество импульсов, сравнивая его с предыдущим количеством - просто начинайте с 0 каждую секунду. А что касается секунды, то лучше всего проверить, прошла ли хотя бы секунда. Всегда есть шанс, что вы увидите 1001 мс вместо 1000 мс. Слабый шанс, но лучше перестраховаться.
Вот пример использования вашего кода в качестве базы:
void loop() {
if (millis() - prevtime >= 1000) { // you should check for more time passing than you expect
prevtime += 1000; // Don't assume you always had 1 second, force it instead
// This block is the "critical section". Keep it as short as possible
// so just grab the data and reset the count.
noInterrupts(); // Stop any interrupts happening
uint32_t currentCount = npc; // Grab this second's count
npc = 0; // And reset the count to zero
interrupts(); // Release the block on interrupts
// And output the results.
Serial.println(currentCount);
}
}
- Считывание нескольких поворотных энкодеров
- Использование поворотных энкодеров с прерываниями смены контактов
- Выводы прерываний Arduino Mega 2560 и отображение портов с помощью поворотного энкодера
- Взаимодействие с датчиком SSI?
- Будет ли простой RC-фильтр работать с механическим поворотным энкодером или понадобится триггер Шмитта?
- Проблема с преобразованием выходного сигнала поворотного энкодера в угол.
- Чтение двух квадратурных кодировщиков с помощью одного ардуино
- Поворотный энкодер KY-040 пропускает шаги
Вы все еще проверяете "время==x"? Серьезно??!, @Sim Son