Page 1 of 3

US sensors in single shot mode (ping mode)

Posted: 11 Oct 2010, 18:13
by HaWe
from a former nxtasy thread:
reading US sensors in single shot mode (ping mode; original code modified):

Code: Select all

//multi US single shot

// 1 US sensor at port 0=S1
// 1 US sensor at port 1=S2

#define printf2( _x, _y, _format1, _format2, _value1, _value2) { \
  string sval1 = FormatNum(_format1, _value1); \
  string sval2 = FormatNum(_format2, _value2); \
  string s =sval1+sval2; \
  TextOut(_x, _y, s); \
}



void USSingleShot(byte port, int &echo)
{
   byte ping_cmnd[] = {0x2, 0x41, 0x1};  // sensor one-shot-mode command
   byte register_select[] = {0x2, 0x42}; // sensor data register

   byte data_size=4;
   byte data[4];                 // =data_size, up to 4 echoes

   I2CWrite(port, 0, ping_cmnd);
   Wait(40);                     // waiting time shortened!
   if (I2CBytes(port, register_select, data_size, data)) {
      echo=data[0]; }            // 1st echo

}

task main()
{
   int
   e_left,   // US-Echodaten von US Sensor an port 0 (S1)
   e_right;  // US-Echodaten von US Sensor an port 1 (S2)

   SetSensorLowspeed(0);
   SetSensorLowspeed(1);

   while(true)
   {
      USSingleShot(0, e_left);
      Wait(40);
      USSingleShot(1, e_right);

      printf2( 0, 0, "%4d", "       %4d",  e_left, e_right);

      Wait(40);
   }
}

Re: US sensors in single shot mode (ping mode)

Posted: 08 Nov 2010, 05:12
by muntoo
Alternatively, you can use:

Code: Select all

void USSingleShot(byte port, int &e1)
{
	WriteI2CRegister(port, I2C_ADDR_DEFAULT, I2C_REG_CMD, US_CMD_SINGLESHOT);
	e1 = SensorUS(port);
	//byte values[];
	//ReadSensorUSEx(port, values);
	//e1 = values[0];
}
OR

Code: Select all

byte USSingleShot(byte port)
{
	WriteI2CRegister(port, I2C_ADDR_DEFAULT, I2C_REG_CMD, US_CMD_SINGLESHOT);
	//byte values[];
	//ReadSensorUSEx(port, values);
	//return(values[0]);
	return(SensorUS(port));
}

Re: US sensors in single shot mode (ping mode)

Posted: 08 Nov 2010, 10:20
by HaWe
is that newly added to the API recently?

US_CMD_SINGLESHOT
surely is predefined in the internal Nxtdefs.h,

but what are the values of
I2C_ADDR_DEFAULT,
I2C_REG_CMD
?

Re: US sensors in single shot mode (ping mode)

Posted: 08 Nov 2010, 10:27
by mightor
The default I2C address for an NXT sensor is 0x02 and the default command register is 0x41. This can be found in the official Lego specification documents.

Regards,
Xander

Re: US sensors in single shot mode (ping mode)

Posted: 08 Nov 2010, 15:34
by mattallen37
Just to clarify, those are the LEGO defaults. Most of the HT sensors also conform the the defaults, but some of the mindsensors products do not.

Re: US sensors in single shot mode (ping mode)

Posted: 08 Nov 2010, 18:50
by HaWe
thx, so the code is always equal to this ( just to clarify):

Code: Select all

byte USSingleShot(byte port)
{
   WriteI2CRegister(port, 0x02, 0x41, US_CMD_SINGLESHOT);
   //byte values[];
   //ReadSensorUSEx(port, values);
   //return(values[0]);
   return(SensorUS(port));
}

Re: US sensors in single shot mode (ping mode)

Posted: 08 Nov 2010, 21:57
by mattallen37
That looks right.

Since the macros are constants, you can easily find the value yourself, like this (note, this displays in decimal format).

Code: Select all

task main()
{
  NumOut(0,LCD_LINE1,I2C_ADDR_DEFAULT); //display the value of the macro
  NumOut(0,LCD_LINE2,I2C_REG_CMD);      //display the value of the macro
  NumOut(0,LCD_LINE3,US_CMD_SINGLESHOT);//display the value of the macro
  while(true);  //Wait forever
}

Re: US sensors in single shot mode (ping mode)

Posted: 08 Nov 2010, 22:10
by HaWe
thx, but I never heard of those parameters before, and I assumed they might be variables, not universal / general constants.

I couldn't imagine that e.g. I2C_ADDR_DEFAULT always is 0x02 because I assumed each single sensor could have it's specific default address.
The same it's with I2C_REG_CMD.

But:
I2C_US_ADDR_DEFAULT (0x02)
and
I2C_US_REG_CMD (0x41)
instead would have been unambiguously (unequivocally?).

But now I see, thx again!

ps
And so I guess that
US_CMD_SINGLESHOT
is 0x42...(?)

Code: Select all

byte USSingleShot(byte port)
{
   WriteI2CRegister(port, 0x02, 0x41, 0x42);
   //byte values[];
   //ReadSensorUSEx(port, values);
   //return(values[0]);
   return(SensorUS(port));
}

Re: US sensors in single shot mode (ping mode)

Posted: 08 Nov 2010, 22:20
by mightor
Doc,

Almost all of Lego's sensors use 0x02, with the exception of the temp sensor (that uses 0x98 and is -nothing- like the normal Lego sensors). There is a default memory (register) layout, which usually looks like this:
0x00 : Version
0x08 : Product ID
0x10 : Sensor Type
0x41 : command register
0x42 : start of data registers

There are exceptions, but this tends to be the layout most sensor use. Mindsensors does deviate from this a lot more than HiTechnic does but both companies play by different rules.

The reason the Lego temp sensor is different is because it doesn't use a custom chip in it made by Lego itself, rather an off-the-shelf Texas Instruments temp sensor. So Lego had no say in how it should function.

Edit: added PDF with I2C commands for Sonar Sensor.

- Xander

Re: US sensors in single shot mode (ping mode)

Posted: 08 Nov 2010, 22:25
by HaWe
Xander,
thx, very interesting indeed.
Comparing matt's code with the one I posted I found that in "mine" one had to declare the lenght of the data registers (count of bytes).
That's not in matt's code.
Why does it work though?

edit:
thx for your appendix, but to be honest: I don't understand a single line ;)