Измерение скорости двигателя постоянного тока с помощью поворотного энкодера
Я написал следующий код для измерения скорости однонаправленного двигателя постоянного тока.Я попытался измерить время между последовательными прерываниями, чтобы рассчитать скорость.
boolean check;
boolean start;
unsigned int angle = 5; //angle moved per encoder tick
unsigned long volatile time1;
unsigned long volatile time_11;
unsigned long interrupt_time;
void setup() {
Serial.begin(9600);
while (!Serial) ;
pinMode(21, INPUT); //Pin#21=interrupt pin, matched to interrupt#2
attachInterrupt(digitalPinToInterrupt(2), speed, FALLING);
time1 = 0;
time_11 = 0;
interrupt_time = 0;
check = true;
start = false;
time_11 = millis(); //Start Clock
}
void loop() {
if(time1 == interrupt_time && start) //Both times same , hence bool start.
{
if(check)
{
Serial.print(millis()); //Time taken to rise to steady speed.
check = false;
}
Serial.println((angle/time1)*1000); //Display Speed.
}
interrupt_time = time1;
start = false;
while(!start)
{}
}
void speed(void) {
start = true;
time1 = millis()-time_11;
time_11 = millis();
}
Я хочу, чтобы код был как можно более эффективным.У меня есть около 100 тиков на 360 градусов от моего кодера.Есть ли вероятность "пропустить" прерывание?
@TechPakoray, 👍5
Обсуждение2 ответа
▲ 1
Всего пара замечаний:
начало
должно быть изменчивым, но вы можете удалить его и просто проверить , чтоtime1 != 0
.нет смысла дважды вызывать
millis()
внутри процедуры обслуживания прерываний:
void speed(void) {
unsigned long now = millis();
time1 = now - time_11;
time_11 = now;
}
,
@Edgar Bonet
▲ 1
Спасибо вам за отзывы! Это моя попытка рассчитать скорость с помощью метода усреднения.
unsigned long volatile encodercount;
unsigned long encodercount_previous;
unsigned long volatile timer;
unsigned int angle;
boolean first;
boolean firstencodertick;
void setup() {
angle=3;
encodercount=0;
encodercount_previous=0;
Serial.begin(9600);
while (!Serial);
pinMode(21,INPUT); //Pin#21=interrupt pin, matched to interrupt#2
attachInterrupt(digitalPinToInterrupt(2),speed,FALLING);
first=true;
firstecnodertick=true;
}
void loop() {
delay(100);
if(encodercount==encodercount_previous&&encodercount!=0)
{
if(first)
{
Serial.println(millis()-timer); //Steady State Time Taken
first=false;
}
Serial.println((encodercount); //Angle Moved in 0.1second.
}
encodercount_previous=encodercount;
encodercount=0;
}
void speed(void)
{
if(firstencodertick)
{
timer=millis();
firstencodertick=false;
}
encodercount++;
}
,
@Ahmed Ali Abbasi
Смотрите также:
- Управление скоростью вентилятора с помощью библиотеки Arduino PID
- Выводы прерываний Arduino Mega 2560 и отображение портов с помощью поворотного энкодера
- Как управлять 4 двигателями постоянного тока с помощью Arduino?
- Почему Arduino сбрасывается во время управления двигателями?
- Сообщение об ошибке: "exit status 1 expected initializer before 'void'."
- Запуск нескольких двигателей одновременно
- Arduino Mega TIMER1 интервал в одну секунду
- Переменная скорость разгона для двигателей, управляемых джойстиком
Я думаю, что вам было бы лучше рассчитать скорость на основе количества импульсов в течение определенного промежутка времени, а не времени одного импульса. Во-вторых, вы должны использовать атомарные операции над многобайтовыми переменными, которые изменяются подпрограммой прерывания. Например, во время сравнения "time1" в " цикле
может быть вызван ISR, и значение
time1` изменится. Оператор if мог бы сравнить первые два байта long, но затем проверяет последние два байта нового значения. Надеюсь, в этом есть смысл., @Gerbenmillis (), вероятно, не будет работать для этого, если только ваш двигатель не работает медленно и ваш кодер низкого разрешения, как правило, между событиями кодера будет меньше миллисекунды. Если вы действительно хотите засечь отдельные события, научитесь использовать аппаратный таймер и соответствующим образом подключайте входы. В противном случае лучше подсчитывать события за определенный период времени. В зависимости от проводки и деталей вы можете подсчитывать события в режиме счетчика аппаратного таймера., @Chris Stratton
Однако режим счетчика таймера HW плохо масштабируется. Взятие временной метки четного и вычисление дельты от предыдущего позволяет использовать даже контакты PCINT., @Igor Stoppa
Serial.println((angle/time1)*1000);
Будьте осторожны, чтобы не делить на 0. Также имейте в виду, что это целочисленное деление, и поэтому оно будет усечено (перед умножением на 1000)., @Adrian McCarthyКак быстро, по-вашему, будет работать мотор? И как быстро вы хотите отчитаться о скорости?, @Dave X