2009-12-28 4 views
4

J'ai pris le code existant de this project, et j'en suis très content.Capteurs Lego Mindstorm NXT, Cocoa et HiTechnic

Je suis maintenant dans une position où je dois utiliser des capteurs tiers que j'ai achetés chez hitechnic, comme un accéléromètre, un gyroscope et une boussole 3D - pour n'en citer que quelques-uns. Je ne sais pas par où commencer maintenant, mais ce que je dois faire est d'ajouter à ma base de code existante (qui est basée sur le this), et de coller efficacement mon infrastructure sur le nouveau matériel.

Quelqu'un peut-il me diriger dans la bonne direction? Je ne trouve aucune API du fabricant de l'appareil (mais je les ai envoyé par e-mail et j'ai demandé - pas encore de réponse).

J'ai également commencé à documenter mes résultats sur la page this.

Répondre

3

D'accord, j'ai eu un coup d'oeil. Les capteurs analogiques, comme le Gyro, sont morts facile ...

je à peu près juste réutilisai celle d'un autre capteur analogique - capteur de lumière ...

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

Pour polling, j'ai utilisé le générique méthode d'interrogation ...

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

... à partir du code LegoNXTRemote.

Les numériques ne sont pas aussi faciles - spécialement pour quelqu'un qui n'a pas d'expérience sw/hw. Voici le code du capteur à ultrasons, la configuration et l'interrogation. Je vais seulement écrire le prototype de ces méthodes et un clone git pour ceux qui sont intéressés par le code complet à la fin.

- (void)setupUltrasoundSensor:(UInt8)port continuous:(BOOL)continuous; 
- (void)getUltrasoundByte:(UInt8)port byte:(UInt8)byte; 
- (void)pollUltrasoundSensor:(UInt8)port interval:(NSTimeInterval)seconds; 

Notez qu'il possède sa propre méthode dédiée pour l'interrogation. Donc, maintenant la question est de savoir comment en écrire un pour l'accéléromètre.

Les informations que vous obtenez lors de l'achat du capteur est une adresse de mappage de table au contenu:

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 

... regardant le capteur à ultrasons, je peux voir les références à 0x42 - que je devine est là la adresse va, mais c'est tout ce que je peux devinez dès maintenant. Je vous ferai savoir si je progresse dans ce domaine.


Bon, voici où est l'accéléromètre.

Je Transmettez d'abord l'appareil le message suivant ...

0x07, 0x00, 0x00, 0x0f, 0x03, 0x02, 0x08, 0x02, 0x42 

Qu'est-ce que cela signifie respectivement (je suis pourrait bien être mal) est ...

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 

Ensuite, nous envoyons un lire demande ...

0x03, 0x00, 0x00, 0x0e, 0x03 

Et que nous obtenons une réponse ...

0x03, 0x00, 0x02, 0x0f, 0xe0 

... et qui se termine par une erreur.

Voici un morceau de journal ...

  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 

C'est basé sur le code exemple de here, qui est la suivante ...

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

} 

Impressionnant! On dirait que ça marche maintenant - j'ai juste besoin de jouer avec la sortie pour extraire les lectures X, Y et Z réelles. Si cela fonctionne, je vous le ferai savoir, mais jusqu'à ce que je l'aie prouvé, je laisserai ce ticket ouvert.


Ok, on dirait qu'il travaille maintenant, mais il y a erreur assez dans le capteur, et je l'ai encore pour prouver que je suis vraiment résolu cela. Voici l'extrait de code:

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

Si quelqu'un est intéressé, je vous invite à télécharger la source et l'essayer - je suis encore à prouver scientifiquement que c'est en fait correcte, même si la première vue, il semble D'accord.


Bon, j'ai fait quelques tests - ça a l'air bien. J'ai converti les valeurs à G, selon les instructions fournies avec l'appareil - indiquant que 1 G ~ 200 unités (je souhaite qu'ils ont fait un peu mieux que ~ 200, une indication de l'erreur aurait été agréable).

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

Si vous placez l'appareil selon la page du fournisseur, vous pouvez voir chaque accès a frappé une lecture d'accélération de ~ 1.02f.

Je pense que je peux fermer ceci maintenant et travailler sur nettoyer le cadre.


Le code peut être consulté à l'adresse:

git clone git://git.autonomy.net.au/nimachine Nimachine 
2

J'ai reçu des nouvelles de HiTechnic aujourd'hui, et avec leur permission, je poste leur réponse pour tout le monde ici.

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 

Références:

+0

Bien que cela ne répond pas à ma question, il est un bon début - dès que je reçois le temps de suivre sur le sujet, et obtenir des résultats, je vais poster ici et mettre à jour tout le monde. – Cyrus

Questions connexes