NXC - Reading temperature from TPA81

Discussion specific to NXT-G, NXC, NBC, RobotC, Lejos, and more.
afanofosc
Site Admin
Posts: 1256
Joined: 26 Sep 2010, 19:36
Location: Nashville, TN
Contact:

Re: NXC - Reading temperature from TPA81

Post by afanofosc »

There are many I2C devices which do not support "burst" mode for reading data from the device. I.e., you have to read 1 byte at a time. I do not know if that is the case for your device.

If you want to read 1 byte from a register address other than 0x00 you can simply use my code (recommended rather than using yours or Matt's) and change count to 1 and the second byte in inbuf[] to be 0x03 if you want to read the temperature value from register 0x03. Or you can leave the inbuf as it is and see what happens when you change count to 1. If you get a non-zero result from I2CBytes then the communication was successful and outbuf will contain the byte that was read from the specified device register.

John Hansen
Multi-platform LEGO MINDSTORMS programming
http://bricxcc.sourceforge.net/
mattallen37
Posts: 1818
Joined: 02 Oct 2010, 02:19
Location: Michigan USA
Contact:

Re: NXC - Reading temperature from TPA81

Post by mattallen37 »

Are you sure you have the pins connected properly? NXT sensor pin 1 is analog in (you won't be using it), 2 and 3 are Gnd, 4 is bus supply (about 4.7v), 5 is SCL, and 6 is SDA.

Can you post your PICAXE program?
Matt
http://mattallen37.wordpress.com/

I'm all for gun control... that's why I use both hands when shooting ;)
salgfrancisco
Posts: 10
Joined: 21 Oct 2011, 15:25

Re: NXC - Reading temperature from TPA81

Post by salgfrancisco »

I have already checked the pins many times. Here's the code I am using in Picaxe

Code: Select all

hi2csetup i2cmaster, $D0, i2cfast, i2cbyte 

main:
	
	do
		hi2cin 2,(b0, b1, b2, b3, b4, b5, b6, b7)
		pause 50
		debug
		loop
It seems to do the job
afanofosc
Site Admin
Posts: 1256
Joined: 26 Sep 2010, 19:36
Location: Nashville, TN
Contact:

Re: NXC - Reading temperature from TPA81

Post by afanofosc »

Did you try what I asked you to try in my previous post?

With the NXT i2c is slow by default, so maybe compare the NXT with a PICAXE program using i2cslow rather than i2cfast.

I2C transactions involve I2CWrite, I2CCheckStatus in a loop, then I2CRead. I2CBytes hides these details from users and simply returns a boolean value. To better understand what is going wrong we can use these 3 functions directly.

Code: Select all

task main()
{
  byte inbuf[] = {0xD0, 0x00}; // tpa81 read from register 0
  byte outbuf[];

  SetSensorLowspeed(S1, false); // uses LOWSPEED rather than LOWSPEED_9V
  while( true )
  {
    ClearScreen();
    char result;
    result = I2CWrite(S1, 10, inbuf);
    NumOut(0, LCD_LINE1, result);
    if (result == NO_ERR)
    {
      // now wait for the bus to be ready
      byte cnt=0;
      result = I2CCheckStatus(S1);
      NumOut(0, LCD_LINE2, result);
      NumOut(40, LCD_LINE2, cnt);
      while ((result != NO_ERR) && (cnt < 50)) {
        Wait(MS_1);
        result = I2CCheckStatus(S1);
        NumOut(0, LCD_LINE2, result);
        cnt++;
        NumOut(40, LCD_LINE2, cnt);
      }
      if (result == NO_ERR)
      {
        // data should be available to read.  Let's check
        result = I2CBytesReady(S1);
        NumOut(0, LCD_LINE3, result); // should be 10
        if (result > 0)
        {
          result = I2CRead(S1, result, outbuf);
          NumOut(0, LCD_LINE3, result);
          byte len = ArrayLen(outbuf);
          NumOut(40, LCD_LINE3, len);
          if (result == NO_ERR)
          {
            if (len > 0)
            {
              int line = 0;
              for (int i = 0; i < len; i++)
              {
                NumOut(0+((i%4)*20), LCD_LINE4-(line*8), outbuf[i]);
                if (i%4 == 0) line++;
              }
            }
            else
              TextOut(0, LCD_LINE8, "Unable to read bytes");
          }
          else
            NumOut(0, LCD_LINE8, result);
        }
        else
          TextOut(0, LCD_LINE8, "Unable to read bytes");
      }
      else
        NumOut(0, LCD_LINE8, result);
    }
    else
      NumOut(0, LCD_LINE8, result);
  }
}
Please be certain that you have your device hooked to port 1 and if reading 10 bytes doesn't work try reading 1 byte. Try also reading 1 byte from different registers. Please report back what sort of errors you get, if any.

John Hansen
Multi-platform LEGO MINDSTORMS programming
http://bricxcc.sourceforge.net/
salgfrancisco
Posts: 10
Joined: 21 Oct 2011, 15:25

Re: NXC - Reading temperature from TPA81

Post by salgfrancisco »

I just tried the new code you (afanofosc) provided and I got this output:
0
-35 ...




where ... is the cnt variable
So I2CCheckStatus() is returning -35, which corresponds to ERR_COMM_BUS_ERR (Something went wrong on the communications bus).
But as I2CWrite() returned no error, doesnt that mean that at least it is finding the sensor.
afanofosc
Site Admin
Posts: 1256
Joined: 26 Sep 2010, 19:36
Location: Nashville, TN
Contact:

Re: NXC - Reading temperature from TPA81

Post by afanofosc »

Unfortunately, the call to I2CWrite will return NO_ERR (0) in all cases except 3:

1. The specified port is not between 0 and 3. ERR_COMM_CHAN_INVALID (-33)
2. The buffer contains too many bytes. ERR_INVALID_SIZE (-19)
3. Either the port is not configured with the correct type (LOWSPEED or LOWSPEED_9V) or port is still switching types (InvalidData == true), or the Comm module's ChannelState for the specified port is neither LOWSPEED_IDLE (0) nor LOWSPEED_ERROR (4). Other possible ChannelState values are LOWSPEED_INIT (1), LOWSPEED_LOAD_BUFFER (2), LOWSPEED_COMMUNICATING (3), and LOWSPEED_DONE (5). ERR_COMM_CHAN_NOT_READY (-32).

Basically, this call just sets up the Comm module to commence an I2C transaction but it is asynchronous (i.e., the call returns long before the firmware actually starts talking to the device).

I2CCheckStatus returns ChannelState values mapped to a simpler set of values: NO_ERR (LOWSPEED_IDLE), STAT_COMM_PENDING (for all other ChannelState values except LOWSPEED_ERROR), and ERR_COMM_BUS_ERR (LOWSPEED_ERROR).

You could monitor ChannelState values directly but I'm not sure that will help us figure out what is going wrong. Almost certainly it is an issue with the circuit that affects the NXT because of the way the NXT requires certain additional components outside of the I2C device itself, where your picaxe circuit does not have those requirements.

Perhaps Xander will chime in with his homebrew I2C device expertise. When it comes to hardware I'm clueless.

John Hansen
Multi-platform LEGO MINDSTORMS programming
http://bricxcc.sourceforge.net/
tcwan
Posts: 186
Joined: 30 Sep 2010, 07:39

Re: NXC - Reading temperature from TPA81

Post by tcwan »

(It is rather difficult to debug hardware issues remotely.)

If you have access to an oscilloscope, it would be a good idea to check if you can see the I2C communications pulses and replies on the I2C lines.
I'd check first that the levels are correct (i.e., interfacing between the two did not result in high/low voltages that exceeded the range that the NXT or the TPA81 can recognize. Secondly, that the binary values are shaped like square waves rather than sine or sawtooth shaped. If this checks out then we can suspect protocol level issues.
mightor
Site Admin
Posts: 1079
Joined: 25 Sep 2010, 15:02
Location: Rotterdam, Netherlands
Contact:

Re: NXC - Reading temperature from TPA81

Post by mightor »

This video obviously proves it works with the NXT: http://www.youtube.com/watch?v=vroJ6gT-aoQ

The guy you're looking for is Tiago Caldeira. I have him on my FB, I'll ask him to take a look at this thread.

Regards,
Xander
| My Blog: I'd Rather Be Building Robots (http://botbench.com)
| RobotC 3rd Party Driver Suite: (http://rdpartyrobotcdr.sourceforge.net)
| Some people, when confronted with a problem, think, "I know, I'll use threads,"
| and then two they hav erpoblesms. (@nedbat)
docilio
Posts: 5
Joined: 16 Jan 2012, 10:00

Re: NXC - Reading temperature from TPA81

Post by docilio »

TPA81.c

Code: Select all

/*

	This Code was created by Tiago Caldeira (docilio)
	Any information or questions, visit:
	
			www.nxt4you.com

*/

#define TPA_CMD   0x00
#define TPA_AMB   0x01
#define TPA_P01    0x02
#define TPA_P02    0x03
#define TPA_P03    0x04
#define TPA_P04    0x05
#define TPA_P05    0x06
#define TPA_P06    0x07
#define TPA_P07    0x08
#define TPA_P08    0x09

/* Variaveis Globais */
ubyte Read[] = {0x02, 0xB0, 0x00};
ubyte Write[] = {0x03, 0xB0, 0x00, 0x00};
ubyte outbuf[10];

/* Prototipos */

int i2c_read(tSensors port, byte addr , byte regs);
int i2c_read(tSensors port, byte addr , byte regs, int n );
void i2c_write(tSensors port, byte addr , byte regs, byte cmd);
int ubyteToInt(ubyte _byte);
int TPA_Ambiente(tSensors port, byte addr);

/* Funcoes */
int ubyteToInt(ubyte _byte) {
    int _ret = 0;
    _ret = (_byte & 0x80) ? (_byte & 0x7F) + 0x80 : _byte;
    return _ret;
}

void i2c_write(tSensors port, byte addr , byte regs, byte cmd)
{

	Write[1] = addr;
	Write[2] = regs;
	Write[3] = cmd;
	while (nI2CStatus[port] == STAT_COMM_PENDING); // Wait for I2C bus to be ready
  sendI2CMsg(port, Write[0], 0);
}

int i2c_read_multi(tSensors port, ubyte addr , ubyte regs, int n )
{
	int out=0;
	const int count = n;

	Read[1] = addr;Read[2] = regs;

	while (nI2CStatus[port] == STAT_COMM_PENDING); // Wait for I2C bus to be ready

  sendI2CMsg(port, Read[0], count);

  while (nI2CStatus[port] == STAT_COMM_PENDING); // Wait for I2C bus to be ready
  if(nI2CBytesReady[port] == count)
  {
  	readI2CReply(port, outbuf[0], count);
    if( n== 1) out=ubyteToInt(outbuf[0]);
    else
    {
    	int i;
    	for(i=0;i<n;i++)
    	{
    	  TEMPERATURA[i] = outbuf[i];
     	  //out += outbuf[i];
    	}
    }
  }
  else {
      memset(outbuf, 0, 0);       //RobotC
  }
  return out;
}


int i2c_SRF_read(tSensors port, byte addr , byte regs)
{
	int out=0;
	const int count = 2;

	Read[1] = addr;Read[2] = regs;

	while (nI2CStatus[port] == STAT_COMM_PENDING); // Wait for I2C bus to be ready

  sendI2CMsg(port, Read[0], count);

  while (nI2CStatus[port] == STAT_COMM_PENDING); // Wait for I2C bus to be ready
  if(nI2CBytesReady[port] == count)
  {
  	readI2CReply(port, outbuf[0], count);
    out = ubyteToInt(outbuf[0])*256;
  	out+= ubyteToInt(outbuf[1]);

  }
  else {
      memset(outbuf, 0, 0);       //RobotC
  }
  return out;
}


int i2c_read(tSensors port, byte addr , byte regs)        {return i2c_read_multi(port,addr,regs,1);}
int i2c_read(tSensors port, byte addr , byte regs, int n ){return i2c_read_multi(port,addr,regs,n);}


int TPA_Sofware(tSensors port, byte addr)
{
  return i2c_read(port,addr,TPA_CMD);
}

int TPA_Ambiente(tSensors port, byte addr)
{
  return i2c_read(port,addr,TPA_AMB);
}

int TPA_Px(tSensors port, byte addr,int x)
{
  return i2c_read(port,addr,TPA_P01+x-1);
}

void TPA_ALL(tSensors port, byte addr)
{
  i2c_read_multi(port,addr,TPA_AMB,9);
}

int TPA_Max(tSensors port, byte addr)
{
  i2c_read_multi(port,addr,TPA_AMB,9);
  int i=0;int max=0;
  for( i = 1 ; i < 9 ; i++ )
  {
    if (max < TEMPERATURA[i] )
      max = TEMPERATURA[i];
  }
  return max;
}


int TPA_DELTA(tSensors port, ubyte addr)
{
  i2c_read_multi(port,addr,0x00,10);
  int i=0;int max=0;
  for( i = 2 ; i < 10 ; i++ )
  {
    if (max < TEMPERATURA[i] )
      max = TEMPERATURA[i];
  }
  return max - TEMPERATURA[1];
}

void TPA_Servo(tSensors port, ubyte addr, ubyte pos)
{
  i2c_write(port, addr ,0x01,pos);
}

Test_TPA81.c

Code: Select all

#pragma config(Sensor, S2,     MD25,                sensorI2CCustom)
//*!!Code automatically generated by 'ROBOTC' configuration wizard               !!*//

/*

	This Code was created by Tiago Caldeira (docilio)
	Any information or questions, visit:
	
			www.nxt4you.com

*/

#pragma fileExtension("rtm")
#pragma platform("NXT")

#define TPA81_Port 0xD0

int TEMPERATURA[10];

#include "TPA81.c"

void  ChangeADDR(tSensors port, int addr, int newadd)
{
	i2c_write(port,addr,SRF_Comands,CHANGE_ADD_1);wait1Msec(10);
	i2c_write(port,addr,SRF_Comands,CHANGE_ADD_2);wait1Msec(10);
	i2c_write(port,addr,SRF_Comands,CHANGE_ADD_3);wait1Msec(10);
	i2c_write(port,addr,SRF_Comands,newadd);wait1Msec(10);
}

void init()
{

}

task main()
{
  init();

  TPA_Servo(MD25,TPA81_Port,15);

  wait1Msec(1000);
  while(1)
  {
    int xD = TPA_DELTA(MD25,TPA81_Port);
    nxtDisplayTextLine(0,"SFTW = %d",TEMPERATURA[0]);
    nxtDisplayTextLine(1,"Ambiente = %d",TEMPERATURA[1]);
    nxtDisplayTextLine(2,"P1 = %d , P2 = %d",TEMPERATURA[2],TEMPERATURA[3]);
    nxtDisplayTextLine(3,"P3 = %d , P4 = %d",TEMPERATURA[4],TEMPERATURA[5]);
    nxtDisplayTextLine(4,"P5 = %d , P6 = %d",TEMPERATURA[6],TEMPERATURA[7]);
    nxtDisplayTextLine(5,"P7 = %d , P8 = %d",TEMPERATURA[8],TEMPERATURA[9]);
    nxtDisplayTextLine(7,"DELTA = %d",xD);

    if( xD > 10)
    {
      PlayImmediateTone(20*xD,10);
      wait1Msec(100);
    }
  }
}
=> DO NOT USE PULL-UP RESISTORS!
=> THIS CODE IS FOR ROBOT-C
Tiago Caldeira
www.nxt4you.com
RobocupJunior Rescue TC for 2012
RobocupJunior Rescue OC Co-Chair for Mexico2012
docilio
Posts: 5
Joined: 16 Jan 2012, 10:00

Re: NXC - Reading temperature from TPA81

Post by docilio »

Just a question.

Can you download and install RobotC for testing ?
http://www.robotc.net/

Let me know if you need extra help
Tiago Caldeira
www.nxt4you.com
RobocupJunior Rescue TC for 2012
RobocupJunior Rescue OC Co-Chair for Mexico2012
Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest