Lego Mindstorm NXT、Cocoa和HiTechnic传感器

4
我从这个项目中复制了现有的代码,并对其感到很满意。
我现在需要使用一些来自hitechnic购买的第三方传感器,比如加速度计、陀螺仪和3D指南针等。
现在我不确定该从哪里开始,但我需要添加到现有的代码库中(基于这个),并将我的框架有效地与新硬件连接。
有人能指点我吗?我找不到设备制造商的任何API(但我已经给他们发了电子邮件并询问了 - 还没有回复)。
我还开始在这个页面上记录我的发现。
2个回答

3

好的,我看了一下。像陀螺仪这样的模拟传感器非常容易处理...

我基本上只是重新使用了另一个类似的模拟传感器 - 光线传感器的处理方式...

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

对于轮询,我使用了通用的轮询方法...

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

...来自LegoNXTRemote代码。

数字传感器的编程并不容易,尤其是对于那些没有软硬件经验的人来说。以下是工作中的超声波传感器代码、设置和轮询方法的原型。感兴趣的人可以在结尾处克隆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

这是基于此处的示例代码(链接)开发的,代码如下:
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

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

参考资料:


虽然这并没有回答我的问题,但这是一个好的起点 - 一旦我有时间跟进,并得到一些结果,我会回来在这里发布更新给大家。 - khosrow

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接