Время выполнения функции Arduino
У меня есть Arduino и беспроводной трансивер APC220. Я пишу библиотеку, которая считывает данные с APC, используя класс SoftwareSerial. Первоначально я начал с (неправильного) кода ниже, который вызывал ошибку сегмента, потому что i
переменная увеличивается, даже если нет доступных данных для чтения. В тех случаях, когда это работало (случайно, когда данные были немедленно доступны), выполнение этой функции занимало приблизительно 6 миллисекунд. Когда я ставлю i++;
Если оператор находится на своем месте (над закрывающей скобкой непосредственно над ним), выполнение функции занимает более 270 мс. Скорость имеет решающее значение для этой функции, поэтому мне интересно, что именно в размещении этого оператора вызывает столь резкое увеличение времени.
Для кода ниже, buff
объявлен как char buff[10];
и sSerial является примером SoftwareSerial
unsigned long updateLocation(Marker* marker) {
this->sSerial->print('~');
//initiate request from vision system
this->sSerial->flush();
this->sSerial->print('#');
this->sSerial->print(marker->num);
this->sSerial->print('*');
this->sSerial->flush();
unsigned long start = millis();
int state = 0, i = 0;
while((millis() - start) < 600) {
if(this->sSerial->available()) {
buff[i] = this->sSerial->read();
if(buff[i] == ',') {
buff[i] = 0;
switch(state) {
case 0:
i = -1;
state++;
break;
case 1:
marker->x = atof(buff);
i = -1;
state++;
break;
case 2:
marker->y = atof(buff);
i = -1;
state++;
break;
case 3:
marker->theta = atof(buff);
i = -1;
return (millis() - start);
break;
default:
return 0;
break;
}
}
// Correct location for i++; takes 270 ms to execute
}
// Incorrect location for i++; Takes 6 ms to execute
i++;
}
this->sSerial->print('~');
this->sSerial->flush();
return 0;
}
1 ответ
Предполагая, что есть данные, готовые и ожидающие от sSerial
нет эффективной разницы в размещении i++
,
Вы сказали сами, в большинстве случаев данные не готовы. При неправильном размещении i++
, i
быстро становится больше, чем размер buff
который вызывает segfault.
При правильном размещении ваш код блокируется до 600 мс, ожидая достаточного количества данных для достижения case 3
и вернуться. В среднем вы видите, что для этого требуется 270 мс.
Вы можете проверить эту теорию самостоятельно, синхронизировав ту же функцию, работающую непосредственно со строкой, а не считывая данные из последовательного интерфейса.
Возможно, вы захотите: а) увеличить скорость вашего бода; б) проверить, есть ли более эффективная последовательная программная реализация, которую вы можете использовать; в) переключиться на аппаратную последовательную реализацию. Если вы в настоящее время используете только аппаратный последовательный порт для отладки вывода, вы можете переключить его. Используйте адаптер FTDI ($6-10 на eBay), чтобы передать программный последовательный порт на USB и зарезервировать аппаратный последовательный для вашей функции, чувствительной ко времени.
Вы также можете перенастроить свой код, чтобы он не блокировал все время ожидания. Вы можете прочитать то, что доступно, сохранить его в глобальном и вернуться к своему основному циклу, чтобы сделать что-то еще, пока данные снова не станут доступны.
редактировать: теперь я вижу, что APC220 макс 9600 бод. Это довольно медленно, поэтому горлышко бутылки может не быть последовательным программным обеспечением (но вы должны проверить это). Если горлышко бутылки - просто скорость передачи, вам нужно будет оптимизировать код, чтобы не блокировать ожидание ввода, если есть другие вещи, над которыми ваша система может работать, пока она ожидает.