Последовательная связь с Optotune Lense Driver 4 - PullRequest
0 голосов
/ 30 января 2020

У меня есть вопрос о том, как работает связь с настраиваемыми объективами с оптотонностью. Я прочитал руководство о том, как отправлять и получать информацию на / с аппаратного обеспечения с помощью драйвера Optotune Lense 4. Но я столкнулся с некоторыми проблемами на стороне get при попытке получить ответы. Никаких проблем (вообще - пока -) на стороне set.

optotune lense driver 4 manual - calibration commands

Вот документация, которая у меня есть для драйвера 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, чтобы увидеть то, что видит моя камера, и посмотреть, как действия влияют на получение (то есть на резкость)

Настройка: Hardware setup

Результаты:

result 3x getUpperCurrentLimit calls

Чтобы получить эти результаты, я нажал три (да три) раза привязку клавиши к getUpperCurrentLimit, что мы видим, что в первый раз, когда я получаю ответ, это происходит ошибка, то я тоже, наконец, получил правильный ответ. Если я переделываю (сразу после этого) запрос к getUpperCurrentLimit, мне нужно go через тот же процесс (3 нажатия), чтобы получить другой правильный ответ. Более того, если я хочу получить верхнее значение, то нижнее значение, я должен нажать 3 раза верхнюю клавишу, чтобы получить значение, затем 9 раз (3 * 3) нижнюю клавишу, чтобы получить более низкое значение, но сначала 2 действительный ответ - это ответ на предыдущий запрос, который был getUpperCurrentLimit, поэтому я получаю ошибки там, где не должен (т. е. байты такие же, как в ручном, CR C проверен и перепроверен - связь работает - наверняка !)

Таким образом, я изменил (на догадку) функцию getResponse, чтобы попытаться «исправить» проблему.

я сделал замену return false; на return getResponse(); (в конец случая переключения)

Теперь, когда я получил ошибку от Serial, я считаю, что это не совсем ошибка, и я прошу другой ответ ... который не логичен и не практичен, так как, если я посылаю неправильную команду, я Я получу сообщение об ошибке, но затем я снова попрошу о readline, и поскольку ответа не осталось ... Я введу бесконечное число l oop или получу ошибку повышения или еще что-нибудь.

Но в Basi c случай, когда все замечательно и команда верна. Я получил вывод, похожий на этот:

getMaxCurrentInput results

Я знаю, что я не вызывал ту же функцию, что и при получении ошибки ранее. Но я могу заверить вас, что поведение обеих команд одинаково. Если это имеет значение, getTempera делает то же самое (с ответом) (поскольку у меня сегодня нет аппаратного обеспечения, я не могу показать другие результаты, как снимки экрана, сделанные для иллюстрации этой проблемы. Извините)

Как вы можете видеть, я дважды получал «неизвестную команду» (как и раньше), но поскольку мы сбрасывали байты команды только один раз, это означает, что она была вызвана только один раз. И затем контрольная сумма действительна, а затем получил ответ на вопрос, который мы задали.

Итак ... вот мой вопрос ... почему так происходит? Есть ли «простое» решение для преодоления этой проблемы? Является ли способ, которым я обработал это, правильный путь и затем проверка на броски или тайм-аут или что-то еще для обработки допустимых ошибок?

Вызов функции getResponse при ошибке, когда не отправляется никакая другая команда, кажется ужасным способом решения проблемы «ошибка-ответ-не-действительно-ошибка»

Что ж, спасибо, что получили любое решение / совет / объяснение

Если вам нужна какая-либо другая информация, у вас есть какие-либо вопросы, не стесняйтесь спрашивать:)

-Nicolas

Примечание: если вам нужна спецификация Об оборудовании - как оно подключено, версия драйвера, модель - спросите об этом тоже. Напоминание: у меня их нет сегодня, я собираюсь обновить этот пост, как только я их получу.

PS: если есть способ скрыть изображения в теге или что-то еще. Но не этот большой желтый блок. Я хочу не брать слишком много постов с изображениями ...

...