Основные сомнения относительно кодеров с Arduino

Я создал программу, которая измеряет импульсы, заданные энкодером (частью двигателя постоянного тока со встроенным энкодером), и использует значение ppr (импульсы на оборот) для вычисления оборотов в минуту (об / мин).

Однако последовательный монитор непрерывно показывает 0 для переменной "pulsecount", которая поддерживает общее количество отправленных импульсов.

код:

float ppr=512.0;
int encpin=3;
volatile long pulsecount=0;
float revs;
float rps;
float rpm;
unsigned long time;


void setup()
{
  pinMode(encpin,INPUT);
  Serial.begin(9600);
  attachInterrupt(digitalPinToInterrupt(encpin),function,RISING); //when pulse is detected
                                           //interrupt triggered,
                                           //function callled  
}
void function(){
  pulsecount+=1;
}

void loop()
{
 revs= pulsecount/ppr ;
 time=millis()/1000;
 rps=revs/time ;
 rpm=revs*60;
 Serial.println(pulsecount);
}

, 👍-1

Обсуждение

Почему вы определяете "функцию() между" настройкой() и `циклом ()"? Если он компилируется, это может быть нормально, но я никогда этого не видел... Попробуйте вывести каждое значение на последовательный монитор, и, возможно, вы увидите переменную, которая вызывает такое поведение., @Python Schlange

Что произойдет, если вы используете "INPUT_PULLUP`, а не "ВВОД"?, @timemage


2 ответа


Лучший ответ:

2

Ваш код считает импульсы просто отлично, когда тестируется здесь.

Выходы тахометра вентилятора/двигателя и энкодеры часто настроены на переключение вашего сигнального контакта на землю либо с помощью транзистора, либо механически. Когда контакт заземления не осуществляется, сигнальное соединение плавает и не является надежно ВЫСОКИМ. Итак, вам нужен подтягивающий резистор на выводе, точно так же, как и для обычного кнопочного выключателя, настроенного на заземление.

Мой комментарий по этому вопросу:

Что произойдет, если вы используете INPUT_PULLUP вместо INPUT?

я имел в виду сделать это в вашем коде:

pinMode(encpin, INPUT_PULLUP);

При более высоких частотах и более высоких оборотах вам может потребоваться использовать внешний резистор, чтобы получить более низкое значение сопротивления, чем 20k-50k внутреннего подтягивающего резистора, включенного INPUT_PULLUP.

Лучше всего отключать прерывания при извлечении изменчивой переменной счетчика импульсов, чтобы не было разрыва значения, когда ISR прерывает ваш код на середине чтения и обновляет вторую половину значения.

например:

// Обратите внимание, что я переключил вашу переменную pulsecount
// to unsigned long для этого примера.
unsigned long get_pulsecount() {
  noInterrupts();
  const auto r = pulsecount;
  interrupts();
  return r;
}

Обратите внимание, что вы, вероятно, можете вообще избежать использования float и должны это сделать, если сможете.

,

0

Трудно найти ошибку в этих примерах TinkerCad, потому что я не знаю, где найти таблицу данных используемых там компонентов, и я никогда не уверен, что я отлаживаю, программу или Tinkercad?

Во всяком случае, кодер, имитируемый там, должен быть подключен к подтягивающему резистору. Arduino имеет встроенный pullup и вы можете активировать через функцию pinmode ():

void setup()
{
  pinMode(encpin,INPUT_PULLUP); // до этого здесь был pinMode(encpin,INPUT); 
  Serial.begin(9600);
  attachInterrupt(digitalPinToInterrupt(encpin),function,RISING); //при обнаружении импульса
                                           //срабатывает прерывание,
//вызывается функция  
}

Но обратите внимание: ваши типы повсюду, и я ожидаю, что вы получите некоторые ошибки из-за этого. Избегайте делить переменные float и int без преобразования, особенно это может вызвать проблемы, потому что вы можете разделить на 0:

 time=millis()/1000;
 rps=revs/time ;

Кроме того, это большой шанс, чтобы иметь основные сомнения относительно кодеров и arduino, просто потому, что какой-то код не работает. Многие люди используют кодеры все время и бесчисленные библиотеки кодеров были опубликованы для arduino.

,