2009-12-28 5 views
4

Я взял существующий код от this project и очень доволен им до сих пор.Lego Mindstorm NXT, Cocoa и HiTechnic Sensors

Теперь я вхожу в такое положение, когда мне нужно использовать некоторые сторонние датчики, которые я приобрел у hitechnic, такие как акселерометр, гироскоп и 3D-компас - чтобы упомянуть некоторые из них.

Я не уверен, с чего начать, но что мне нужно сделать, это добавить к моей существующей базе кода (которая основана на this) и эффективно приклеить мою инфраструктуру к новому оборудованию.

Может ли кто-нибудь указать мне правильное направление? Я не могу найти никаких API от производителя устройства (но я отправил их по электронной почте и спросил - ответа еще нет).

Я также начал документировать свои выводы на странице this.

ответ

3

Ладно, я имел взгляд. Аналоговые датчики, такие как гироскоп, мертвы легко ...

Я довольно много раз повторно, что другого аналогового датчика - датчик освещенности ...

- (void)setupGyroscopicSensor:(UInt8)port { 
    [self setInputMode:port 
        type:kNXTGyroscope 
        mode:kNXTRawMode]; 
} 

Для опроса, я родовое метод опроса ...

- (void)pollSensor:(UInt8)port interval:(NSTimeInterval)seconds; 

... из кода LegoNXTRemote.

Цифровые не такие легкие - особенно для тех, у кого есть нулевой опыт работы в режиме sw/hw. Вот рабочий код ультразвукового датчика, настройка и опрос. Я напишу только прототип этих методов и клон git для тех, кто интересуется полным кодом в конце.

- (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 

Это основано на примере кода из here, который, как следует все ...

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]; 
    ... 

} 

Awesome! Похоже, он работает сейчас - мне просто нужно возиться с выходом, чтобы извлечь фактические показания 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 
2

Сегодня я услышал от 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 

Ссылки:

+0

Хотя это не ответ на мой вопрос, это хорошее начало - как только я получаю время, чтобы следить за ним, и получить некоторые результаты, я опубликую здесь и обновить все. – Cyrus