Датчики Lego Mindstorm NXT, Какао и HiTechnic
Я взял существующий код из этого проекта и очень доволен им до сих пор.
Однако сейчас я нахожусь в положении, когда мне нужно использовать некоторые сторонние датчики, которые я приобрел у Hitechnic, такие как акселерометр, гироскоп и 3D-компас - чтобы упомянуть некоторые.
Я не уверен, с чего начать, но что мне нужно сделать, это добавить к моей существующей базе кода (которая основана на этом), и эффективно приклеить мою платформу к новому оборудованию.
Может кто-то указать мне верное направление? Я не могу найти какие-либо API от производителя устройства (но я отправил их по электронной почте и спросил - пока нет ответа).
Я также начал документировать свои выводы на этой странице.
2 ответа
Хорошо, я посмотрел Аналоговые датчики, такие как гироскоп, очень просты...
Я в значительной степени только что использовал другой аналоговый датчик - датчик освещенности...
- (void)setupGyroscopicSensor:(UInt8)port {
[self setInputMode:port
type:kNXTGyroscope
mode:kNXTRawMode];
}
Для опроса я использовал общий метод опроса...
- (void)pollSensor:(UInt8)port interval:(NSTimeInterval)seconds;
... из кода LegoNXTRemote.
Цифровые не так просты - особенно для тех, кто не имеет опыта работы с программным обеспечением. Вот рабочий код ультразвукового датчика, настройка и для опроса. Я напишу только прототип этих методов и git clone для тех, кто интересуется полным кодом в конце.
- (void)setupUltrasoundSensor:(UInt8)port continuous:(BOOL)continuous;
- (void)getUltrasoundByte:(UInt8)port byte:(UInt8)byte;
- (void)pollUltrasoundSensor:(UInt8)port interval:(NSTimeInterval)seconds;
Обратите внимание, что у него есть собственный метод опроса. Итак, теперь вопрос в том, как написать один для акселерометра.
Информация, которую вы получаете при покупке сенсора, представляет собой таблицу сопоставления адресов с контентом:
42H (byte) -> X-axis upper 8 bits
43H (byte) -> X-axis upper 8 bits
44H (byte) -> X-axis upper 8 bits
45H (byte) -> X-axis lower 8 bits
46H (byte) -> X-axis lower 8 bits
47H (byte) -> X-axis lower 8 bits
... глядя на ультразвуковой датчик, я вижу ссылки на 0x42
- я предполагаю, что адрес куда идет, но это все, что я могу догадаться прямо сейчас.
Я дам вам знать, если я получу какой-либо прогресс в этом.
Хорошо, вот где это с акселерометром.
Я сначала отправляю устройству следующее сообщение...
0x07, 0x00, 0x00, 0x0f, 0x03, 0x02, 0x08, 0x02, 0x42
Что это значит соответственно (я вполне могу ошибаться) это...
kNXTRawMode
kNXTGetInputValues
kNXTRet //. Meaning we expect a return value
kNXTLSWrite //. As opposed to read
port //. Port 0x03 --> Port 4
txLength
rxLength
//. message...
0x02 //. Set the I2C slave address
0x42 //. Set the register we're interested in
Далее мы отправляем запрос на чтение...
0x03, 0x00, 0x00, 0x0e, 0x03
И на это мы получаем ответ...
0x03, 0x00, 0x02, 0x0f, 0xe0
... и это заканчивается ошибкой.
Вот кусок журнала...
libNXT[0x02]: Attempting to connect to NXT...
libNXT[0x02]: Open sequence initiating...
libNXT[0x02]: Channel Opening Completed
libNXT[0x08]: >>> :0x06, 0x00, 0x80, 0x03, 0x0b, 0x02, 0xf4, 0x01,
libNXT[0x08]: >>> :0x02, 0x00, 0x00, 0x0b,
libNXT[0x08]: <<< :0x05, 0x00, 0x02, 0x0b, 0x00, 0x82, 0x1e,
libNXT[0x08]: @selector does NOT respond to NXTOperationError:operation:status:
libNXT[0x08]: @selector responds to NXTBatteryLevel:batteryLevel:
startPollingSensor: setup sensor
startPollingSensor: start polling
libNXT[0x02]: Polling Port 3
libNXT[0x08]: >>> :0x07, 0x00, 0x00, 0x0f, 0x03, 0x02, 0x08, 0x02, 0x42,
libNXT[0x08]: >>> :0x03, 0x00, 0x00, 0x0e, 0x03,
libNXT[0x08]: <<< :0x03, 0x00, 0x02, 0x0f, 0xe0,
libNXT[0x08]: @selector responds to NXTOperationError:operation:status:
nxt error: operation=0xf status=0xe0
libNXT[0x08]: <<< :0x04, 0x00, 0x02, 0x0e, 0xe0, 0x00,
libNXT[0x08]: @selector responds to NXTOperationError:operation:status:
nxt error: operation=0xe status=0xe0
libNXT[0x08]: @selector does NOT respond to NXTOperationError:operation:status:
libNXT[0x02]: Polling Port 3
libNXT[0x08]: >>> :0x07, 0x00, 0x00, 0x0f, 0x03, 0x02, 0x08, 0x02, 0x42,
libNXT[0x08]: >>> :0x03, 0x00, 0x00, 0x0e, 0x03,
libNXT[0x08]: <<< :0x03, 0x00, 0x02, 0x0f, 0xe0,
libNXT[0x08]: @selector responds to NXTOperationError:operation:status:
nxt error: operation=0xf status=0xe0
libNXT[0x08]: <<< :0x04, 0x00, 0x02, 0x0e, 0xe0, 0x00,
libNXT[0x08]: @selector responds to NXTOperationError:operation:status:
nxt error: operation=0xe status=0xe0
libNXT[0x08]: @selector does NOT respond to NXTOperationError:operation:status:
libNXT[0x02]: Polling Port 3
libNXT[0x08]: >>> :0x07, 0x00, 0x00, 0x0f, 0x03, 0x02, 0x08, 0x02, 0x42,
libNXT[0x08]: >>> :0x03, 0x00, 0x00, 0x0e, 0x03,
libNXT[0x08]: <<< :0x03, 0x00, 0x02, 0x0f, 0xe0,
libNXT[0x08]: @selector responds to NXTOperationError:operation:status:
nxt error: operation=0xf status=0xe0
libNXT[0x08]: <<< :0x04, 0x00, 0x02, 0x0e, 0xe0, 0x00,
libNXT[0x08]: @selector responds to NXTOperationError:operation:status:
nxt error: operation=0xe status=0xe0
libNXT[0x08]: @selector does NOT respond to NXTOperationError:operation:status:
Error while running hook_stop:
libNXT[0x08]: >>> :0x03, 0x00, 0x00, 0x0e, 0x03,
libNXT[0x08]: <<< :0x03, 0x00, 0x02, 0x0f, 0xe0,
libNXT[0x08]: @selector responds to NXTOperationError:operation:status:
nxt error: operation=0xf status=0xe0
libNXT[0x08]: <<< :0x04, 0x00, 0x02, 0x0e, 0xe0, 0x00,
libNXT[0x08]: @selector responds to NXTOperationError:operation:status:
nxt error: operation=0xe status=0xe0
Все это основано на примере кода отсюда, который выглядит следующим образом...
SetSensorLowspeed(IN_1);
int count;
int xval;
int yval;
int zval;
byte inI2Ccmd[];
byte outbuf[];
while (TRUE) {
ArrayInit(inI2Ccmd, 0, 2); // set the buffer to hold 10 values (initially all are zero)
inI2Ccmd[0] = 0x02; // set values in the array
inI2Ccmd[1] = 0x42;
count=8; //read count set to 8 bytes
I2CBytes(IN_1, inI2Ccmd, count, outbuf); //read the acceleration sensor on port 1
xval=outbuf[0]; //load x axis upper 8 bits
yval=outbuf[1]; //load Y axis upper 8 bits
zval=outbuf[2]; //load z axis upper 8 bits
if (xval > 127) xval-=256; //convert x to 10 bit value
xval=xval*4 + outbuf[3];
if (yval > 127) yval-=256; //convert y to 10 bit value
yval=yval*4 + outbuf[4];
if (zval > 127) zval-=256; //convert z to 10 bit value
zval=zval*4 + outbuf[5];
...
}
Потрясающие! Похоже, это работает сейчас - мне просто нужно поиграть с выводом, чтобы извлечь фактические значения X, Y и Z.
Если это сработает, я дам вам знать, но пока я не докажу, я оставлю этот билет открытым.
Хорошо, похоже, что он сейчас работает, но в датчике достаточно ошибки, и мне еще предстоит доказать, что я действительно решил эту проблему. Вот фрагмент кода:
SInt8 *outbuf = malloc(48);
[data getBytes:outbuf length:6];
SInt16 x = outbuf[0]; x <<= 2; x += outbuf[3];
SInt16 y = outbuf[1]; y <<= 2; y += outbuf[4];
SInt16 z = outbuf[2]; z <<= 2; z += outbuf[5];
free(outbuf);
[self setSensorTextField:port
value:[NSString stringWithFormat:@"<%d, %d, %d>",
x, y, z]];
Если кому-то это интересно, я приглашаю вас скачать исходный код и опробовать его - мне еще предстоит научно доказать, что это действительно правильно, хотя на первый взгляд все выглядит хорошо.
Хорошо, я провел некоторое тестирование - это выглядит хорошо. Я преобразовал значения в G согласно инструкциям, которые прилагаются к устройству - заявив, что 1 G ~ 200 единиц (хотелось бы, чтобы они работали немного лучше, чем ~200, некоторые признаки ошибки были бы хорошими).
//. Acceleration in G's
SInt8 *outbuf = malloc(48);
[data getBytes:outbuf length:6];
SInt16 x = outbuf[0]; x <<= 2; x += outbuf[3]; float gX = x/200.f;
SInt16 y = outbuf[1]; y <<= 2; y += outbuf[4]; float gY = y/200.f;
SInt16 z = outbuf[2]; z <<= 2; z += outbuf[5]; float gZ = z/200.f;
free(outbuf);
[self setSensorTextField:port
value:[NSString stringWithFormat:@"%0.2f, %0.2f, %0.2f",
gX, gY, gZ]];
Если вы расположите устройство в соответствии со страницей поставщика, вы увидите, что при каждом обращении к нему ускоряется показание ~ 1,02f.
Я думаю, что могу закрыть это сейчас и заняться очисткой фреймворка.
Код можно проверить по адресу:
git clone git://git.autonomy.net.au/nimachine Nimachine
Я получил ответ от HiTechnic сегодня, и с их разрешения я публикую их ответ для всех здесь.
Hi Nima,
There are two types of sensors, digital and analog. The Analog sensors you
can basically read like you would the LEGO light sensor. If you have that
working then you can read the HiTechnic analog sensors. These include the
EOPD, Gyro as well as the Touch Multiplexer.
For the TMUX there is [sample NXC code][1] on the product info page.
You should be able to use that as a basis if you want to support this device.
The other sensors are digital I2C sensors. Most of these sensors have I2C
register information on their respective product information page and/or it
was included on a sheet that came with the sensor. First of all, to make
these sensors work with your framework you need to have I2C communications
working. After that it will be a matter of creating your own API that uses
the I2C interface with the sensors. I recommend that you download and look
at Xander Soldaat's RobotC driver suite for the HiTechnic sensors. You will
find this near the bottom of the HiTechnic downloads page.
Regards,
Gus
HiTechnic Support
Рекомендации: