Servo и ошибка при передаче значения 128 градусов
- Войдите на сайт для отправки комментариев
Сб, 20/12/2014 - 17:24
Доброго времени суток! Проблема почти полностью описана в теме. Если подробнее: есть манипулятор с 4мя сервами (база, плече, локоть и кисть). Подключены они к Ардуино Уно. На Уне изначально был примерно такой скетч:
#include <Firmata.h>
#include <Servo.h>
Servo servo8;
Servo servo9;
Servo servo10;
Servo servo11;
void analogWriteCallback(byte pin, int value)
{
if ( pin == 8 ) {
servo8.write(value);
}
if ( pin == 9 ) {
servo9.write(value);
}
if ( pin == 10 ) {
servo10.write(value);
}
if ( pin == 11 ) {
servo11.write(value);
}
}
void setup()
{
Firmata.setFirmwareVersion(0, 2);
Firmata.attach(ANALOG_MESSAGE, analogWriteCallback);
servo8.attach(8);
servo9.attach(9);
servo10.attach(10);
servo11.attach(11);
Firmata.begin(9600);
}
void loop() {
while(Firmata.available())
Firmata.processInput();
}
Отдельная програмка, написанная в Qt, передает через класс Serial значения углов. Примерно так:
#define FRST_PORT 8
#define SRVS_AMOUNT 4
#define DELAY1 10
#define DELAY2 500
void MainWindow::handler() {
if (!outputFile->open(QIODevice::ReadOnly | QIODevice::Text)) {
statusLbl->setText("Can't open file");
}
while ( !outputFile->atEnd()) {
QString str = outputFile->readLine();
QTextStream stream(&str);
QList<int> intList;
for (int i = 0; i < SRVS_AMOUNT; i++) {
int number;
stream >> number;
intList.append(number);
}
uint8_t buf[3];
for (int i = 0; i < SRVS_AMOUNT; i++) {
buf[0] = 0xE0 | (i + FRST_PORT);
buf[1] = intList[i] & 0x7F;
buf[2] = intList[i] >> (i + FRST_PORT) & 0x7F;
serial->Send(buf, 4);
Sleep(DELAY1);
}
Sleep(DELAY2);
statusLbl->setText("Keep moving...");
}
outputFile->close();
statusLbl->setText("Reading is finished");
}
Дальше, serial.Send() отправляет эту красоту в файл (com-порт).
Как я понимаю, проблема в том, что 01111111 = 127 - это обрабатывается, а 10000000 - 128 и больше - нет. То есть, 8й бит отдается под знак.
Внимание вопрос: как обработать эту ошибку?
Всем спасибо:)
Поковырял Firmata
case ANALOG_MESSAGE: if(currentAnalogCallback) { (*currentAnalogCallback)(multiByteChannel, (storedInputData[0] << 7) + storedInputData[1]);значение передается двумя байтами(вначале старший, потом младший), а у вас что-то неясное ограниченное по 127 и не в нужном порядке:
buf[1] = intList[i] & 0x7F; buf[2] = intList[i] >> (i + FRST_PORT) & 0x7F;другой протокол. Наверно нужно что-то вроде этого. И тип беззнаковый QList<uint16_t> intList
buf[1] = (intList[i] >> 7) & 0xFF; buf[2] = intList[i] & 0xFF;а байт команды совмещен с номером порта так:
if(inputData < 0xF0) { command = inputData & 0xF0; multiByteChannel = inputData & 0x0F; } else { command = inputData; // commands in the 0xF* range don't use channel data }С этим в вашем исходнике порядок.
Ух ты. Спасибо) Темный лес пока что работа с COM.
QList<uint16_t> intList ? Данные на на условие i>=0 && i<=180 проверяются на предыдущих этапах. Или я что-то неправильно понял? И какого типа buf? Может это таки он uint16_t?
uint8_t - 8 бит без знака тоесть 0x00...0xFF
uint16_t - 16 бит - 0x0000...0xFFFF
тоесть 8*2=16
2 байта дляпередачи инфы, содержащийся в одной переменной uint16_t.
2 байта, а не бита. Я туплю