4

我已经从这个项目中获取了现有的代码,到目前为止我对它非常满意。

但是,我现在需要使用从hitechnic购买的一些第三方传感器,例如加速度计、陀螺仪和 3D 罗盘 - 仅举几例。

我不确定现在从哪里开始,但我需要做的是添加到我现有的代码库(基于this),并将我的框架有效地粘合到新硬件上。

谁能指出我正确的方向?我找不到设备制造商提供的任何 API,(但我已通过电子邮件向他们发送电子邮件并询问 - 尚未回复)。

我也开始在这个页面上记录我的发现。

4

2 回答 2

3

好的,我已经看过了。陀螺仪等模拟传感器非常容易......

我几乎只是重复使用了另一个模拟传感器——光传感器......

- (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
于 2009-12-29T06:54:38.040 回答
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

参考:

于 2009-12-29T02:45:17.280 回答