У меня есть вопрос о том, как работает связь с настраиваемыми объективами с оптотонностью. Я прочитал руководство о том, как отправлять и получать информацию на / с аппаратного обеспечения с помощью драйвера Optotune Lense 4. Но я столкнулся с некоторыми проблемами на стороне get
при попытке получить ответы. Никаких проблем (вообще - пока -) на стороне set
.
Вот документация, которая у меня есть для драйвера Optotune: здесь
Отсюда я понял, что связь осуществляется через последовательный порт, и при установке нового значения на (любой) канал ответа не возникает, кроме ошибок.
С другой стороны, при получении данных есть либо ошибка, либо действительный ответ.
Команда / ответ описаны для каждого (возможных) действий, как показано для команд калибровки.
int SerialLense::getUpperCurrentLimit(void) {
if (max_focus_ != std::numeric_limits<int>::max()) return max_focus_;
std::cout << "Get upper current limit" << std::endl;
int8_t *command = new int8_t[6];
double upper_limit = 0;
// casting is (maybe) pointless || 0x43 & 0xFF works too ?
// or none since command type is int8_t*
command[0] = 'C'; // static_cast<int8_t>(0x43); // 'C'
command[1] = 'r'; // static_cast<int8_t>(0x72); // 'r'
command[2] = 'U'; // static_cast<int8_t>(0x55); // 'U'
command[3] = 'A'; // static_cast<int8_t>(0x41); // 'A'
command[4] = static_cast<int8_t>(0x00); // dummy
command[5] = static_cast<int8_t>(0x00); // dummy
uint8_t length = 6;
int8_t *crc_command(getCommandCrc(command, length));
length += 4;
dumpCommandBytes(crc_command, length);
sendCommand(crc_command, length);
if (getResponse()) {
std::string temp = response_.substr(0, response_.length() - 2);
int8_t first_byte = temp[temp.length() - 2];
int8_t second_byte = temp[temp.length() - 1];
int16_t result = (first_byte << 8) + second_byte;
upper_limit = result;
std::cout << "Value retrieved : " << upper_limit << std::endl;
// TODO(Nicolas) : once every input got a valid Answer
// store upper_limit in class
// this function should be called on initialization
// & upper_limit is updated when we set a new value;
}
std::cout << std::endl;
max_focus_ = upper_limit;
return upper_limit;
}
Вот функция, используемая для связи с объективом и получения максимального входного тока, который мы можем установить для аппаратного обеспечения. Как сказано в руководстве, он только отправляет байты через последовательный порт, а затем получает ответ. Если ответ действителен, то мы собираем данные и показываем их на -terminal- screen (еще не использовался в другой части программы).
bool SerialLense::sendCommand(std::string command) {
if (!is_open_) {
std::cerr << "Attempt to command without opening the serial port."
<< std::endl;
return false;
}
mutex_.lock();
try {
command += "\r\n";
writeString(command);
} catch (boost::system::system_error &e) {
std::cout << "Error : " << e.what() << std::endl;
close();
return false;
}
mutex_.unlock();
return true;
}
Вот функция, которую я использую для отправки команды через последовательный порт порт (связь работает - без проблем на этой стороне)
inline void writeString(std::string s) {
boost::asio::write(serial_, boost::asio::buffer(s.c_str(), s.size()));
}
inline void writeBytes(int8_t *command, int8_t length) {
boost::asio::write(serial_, boost::asio::buffer(command, length));
}
Существует способ записи команды в последовательный порт.
bool SerialLense::getResponse(void) {
response_ = readLine();
if (response_[0] == 'E') {
switch (response_[1]) {
case 1:
std::cerr << "CRC incorrect." << std::endl;
break;
case 3:
std::cerr << "Unknown command." << std::endl;
break;
default:
std::cerr << "Got error cannot say what it is." << std::endl;
break;
}
return false;
} else {
int8_t *response = new int8_t[response_.length()];
for (int i = 0; i < response_.length(); i++) {
response[i] = static_cast<int8_t>(response_[i]) & 0xFF;
}
uint16_t crc = checkSum(response_);
std::cout << "Answer checksum should be zero (0) : " << crc
<< std::endl;
dumpResponseBytes(response, response_.length());
return true;
}
}
Эта функция используется для получения ответа (если есть) от оборудования через serialPort. Функция readLine примерно такова: [get char; если! = \ n || \ r затем добавьте к переменной out else, если \ r продолжите иначе, если \ n останавливается и верните переменную out]
Об проверке ошибок У меня нет документации по этому вопросу, но согласно другой «обертке», например: здесь
Ошибка возникает, когда первый байт ответа равен 'E', а второй байт соответствует типу ошибки: 1 соответствует CR C несоответствие (c .f. руководство)
Затем мы проверяем на несоответствие, потому что .. почему бы и нет (я пытаюсь заставить его работать, поэтому я много перерабатываю, я прохожу .. nvm)
Так, как я сделал мой тест? Я привязываю свой ввод с клавиатуры к функциям. Я использую opencv, чтобы увидеть то, что видит моя камера, и посмотреть, как действия влияют на получение (то есть на резкость)
Настройка:
Результаты:
Чтобы получить эти результаты, я нажал три (да три) раза привязку клавиши к getUpperCurrentLimit, что мы видим, что в первый раз, когда я получаю ответ, это происходит ошибка, то я тоже, наконец, получил правильный ответ. Если я переделываю (сразу после этого) запрос к getUpperCurrentLimit, мне нужно go через тот же процесс (3 нажатия), чтобы получить другой правильный ответ. Более того, если я хочу получить верхнее значение, то нижнее значение, я должен нажать 3 раза верхнюю клавишу, чтобы получить значение, затем 9 раз (3 * 3) нижнюю клавишу, чтобы получить более низкое значение, но сначала 2 действительный ответ - это ответ на предыдущий запрос, который был getUpperCurrentLimit, поэтому я получаю ошибки там, где не должен (т. е. байты такие же, как в ручном, CR C проверен и перепроверен - связь работает - наверняка !)
Таким образом, я изменил (на догадку) функцию getResponse, чтобы попытаться «исправить» проблему.
я сделал замену return false;
на return getResponse();
(в конец случая переключения)
Теперь, когда я получил ошибку от Serial, я считаю, что это не совсем ошибка, и я прошу другой ответ ... который не логичен и не практичен, так как, если я посылаю неправильную команду, я Я получу сообщение об ошибке, но затем я снова попрошу о readline, и поскольку ответа не осталось ... Я введу бесконечное число l oop или получу ошибку повышения или еще что-нибудь.
Но в Basi c случай, когда все замечательно и команда верна. Я получил вывод, похожий на этот:
Я знаю, что я не вызывал ту же функцию, что и при получении ошибки ранее. Но я могу заверить вас, что поведение обеих команд одинаково. Если это имеет значение, getTempera делает то же самое (с ответом) (поскольку у меня сегодня нет аппаратного обеспечения, я не могу показать другие результаты, как снимки экрана, сделанные для иллюстрации этой проблемы. Извините)
Как вы можете видеть, я дважды получал «неизвестную команду» (как и раньше), но поскольку мы сбрасывали байты команды только один раз, это означает, что она была вызвана только один раз. И затем контрольная сумма действительна, а затем получил ответ на вопрос, который мы задали.
Итак ... вот мой вопрос ... почему так происходит? Есть ли «простое» решение для преодоления этой проблемы? Является ли способ, которым я обработал это, правильный путь и затем проверка на броски или тайм-аут или что-то еще для обработки допустимых ошибок?
Вызов функции getResponse при ошибке, когда не отправляется никакая другая команда, кажется ужасным способом решения проблемы «ошибка-ответ-не-действительно-ошибка»
Что ж, спасибо, что получили любое решение / совет / объяснение
Если вам нужна какая-либо другая информация, у вас есть какие-либо вопросы, не стесняйтесь спрашивать:)
-Nicolas
Примечание: если вам нужна спецификация Об оборудовании - как оно подключено, версия драйвера, модель - спросите об этом тоже. Напоминание: у меня их нет сегодня, я собираюсь обновить этот пост, как только я их получу.
PS: если есть способ скрыть изображения в теге или что-то еще. Но не этот большой желтый блок. Я хочу не брать слишком много постов с изображениями ...