好的,我看过了。陀螺仪等模拟传感器非常容易......
我几乎只是重复使用了另一个模拟传感器 - 光传感器...
- (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
这都是基于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];
...
}
太棒了!看起来它现在可以工作了 - 我只需要调整输出来提取实际的 X、Y 和 Z 读数。
如果它确实有效,我会告诉你们所有人,但在我证明它之前,我会保留这张票。
好的,看起来它现在可以工作了,但是传感器中的错误已经足够多,我还没有证明我真的解决了这个问题。这是sn-p的代码:
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