Pages: [1]   Go Down
Author Topic: debugging i2c/serial problem  (Read 1083 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Newbie
*
Karma: 0
Posts: 6
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm attempting to interface both a TPA81 thermopile device using the Wire I2C library and a 4D systems uOLED device using the HardwareSerial library. Both of the devices work fine independently -- I can read the temperatures coming off the TPA81 and send them to my PC over the serial port and I can display arbitrary text and graphics on the uOLED just fine. But when I try to read the TPA81 and send the temperatures directly to the uOLED (Arduino only, no PC) I get wildly fluctuating temperature readings. I've tried reducing the serial baud rate, adding arbitrary delays in reading the thermal data over the I2C channel, reducing complexity of the code, etc. Nothing seems to work. I will post example code as a followup but if anybody has seen this kind of maddening behavior I'd appreciate whatever ideas you might have to figure this out.
« Last Edit: August 26, 2010, 02:36:49 pm by bruceba » Logged

Manchester (England England)
Offline Offline
Brattain Member
*****
Karma: 514
Posts: 31543
Solder is electric glue
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I think you need to post both the code and a schematic of how you have wired things up before we stand a chance on this one.
Logged

0
Offline Offline
Faraday Member
**
Karma: 7
Posts: 2526
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

wild guess: out of RAM

but like Mike says, we need more data.

-j
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 6
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I will post the offending code ASAP -- I don't have a simple way to make a schematic available but I'll try to do some ascii art or just a connection list if that will help.
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 6
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Schematic is roughly similar to the diagram at http://www.robot-electronics.co.uk/htm/arduino_examples.htm (click on the TPA81 link) substituting the uOLED for the LCD03 and adding a line from the arduino digital pin 8 to the reset pin on the uOLED.  Simplified code follows.
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 6
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
#include <Wire.h>

#define TPA81ADDR 0x68
#define TPA_AMBIENT 0x01
#define TPA_BASE_TEMP 0x02
#define PIN_RESET 8

void initOLED(int baud, HardwareSerial *serial) {
  pinMode(PIN_RESET, OUTPUT);
  // reset display
  digitalWrite(PIN_RESET, LOW);
  delay(30);
  digitalWrite(PIN_RESET, HIGH);
  delay(1000);
  serial->begin(baud);
  serial->write(0x55);  // establish baud rate
  getOLEDResponse(serial);
}

int getOLEDResponse(HardwareSerial *serial) {
  long starttime = millis();
  while(! serial->available()) {
    if (millis() - starttime > 4000) {  // timeout of 4 secs
      return 0;
    }
  }
  return serial->read();
}

void writeOLEDText(HardwareSerial *serial,
                   char col,
                   char row,
                   char font,
                   int color,
                   char *text,
                   char transparent) {
  // set text mode
  serial->write(0x4f);
  serial->write(transparent);
  getOLEDResponse(serial);

  // write text
  serial->write(0x73);
  serial->write(col);
  serial->write(row);
  serial->write(font);
  serial->write(color >> 8);
  serial->write(color & 0xff);
  for (int i=0; i<strlen(text); ++i) {
    serial->write(text[i]);
  }
  serial->write(byte(0x00));
  getOLEDResponse(serial);
}

int getData(int reg) {
  Wire.beginTransmission(TPA81ADDR);
  Wire.send(reg);
  Wire.endTransmission();
  Wire.requestFrom(TPA81ADDR, 1);
  while (Wire.available() < 1) ;
  int data = Wire.receive();
  return data;
}

void setup() {
  Wire.begin();
  initOLED(19200, &Serial);
  delay(2000);
}

void loop() {
  int temps[10];
  int ambient = getData(TPA_AMBIENT);
  for (int i = 0; i < 8; i++) {
    char str[5];
    temps[i] = getData(i + TPA_BASE_TEMP);
    sprintf(str, "%02d ", temps[i]);
    if (i < 4) {
      writeOLEDText(&Serial, i * 4, 8, 0, 0xffff, str, 1);
    }
    else {
      writeOLEDText(&Serial, (i - 4) * 4, 10, 0, 0xffff, str, 1);
    }
  }
}
Logged

Manchester (England England)
Offline Offline
Brattain Member
*****
Karma: 514
Posts: 31543
Solder is electric glue
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
But when I try to read the TPA81 and send the temperatures directly to the uOLED (Arduino only, no PC) I get wildly fluctuating temperature readings.

That would suggest to me that your display is OK but the temperature sensor is not. If the display was at fault then you would be seeing rubbish symbols not numbers all be it the wrong numbers. I would not use 1K8 resistors for the I2C pullups they are a bit too low, change them to 4K7. The other thing is the decoupling of the supplies have you got any? Finally the display might be taking just too much current for your supply and upsetting the temperature sensors, you could try powering the display of a separate 5V supply just to see. (make the grounds common of course)
Logged

0
Offline Offline
Edison Member
*
Karma: 0
Posts: 1103
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I understand that the 1k8 are part of the break-out board.
In any case their value is quite fine. Anybody who has seen the signal shape in case of two or three devices and a (recommended) 10k will never do that again :-) The I2C bus is power hungry... I have seen designs with even 220 ohms...

But of course ALL pull-ups have to be added together ... no, subtracted... no ... well you know what I mean ;-)
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 6
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

OK -- now can anybody suggest the best (read "safest") way to separately power the OLED and TPA81 devices? I'm pretty hardware ignorant but I'm trying to learn. Something on the order of "connect the +5V lead from supply A to the VCC of the TPA81 and hook the ground lead to <fill in blank>." Also, should I try replacing the 1k pullup resistors with higher/lower values?

Thanks for all the help.
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 14
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Try to power just the OLED independently from an external 5V supply. GND should be connected to arduino, OLED and external supply.

I would keep the pull-ups as they are except if there are additional pull-ups on the TPA81. We're using pull-ups in the 2k-3k range on our designs with no issues, but if you have multiple pull-ups in parallel you may have problems.

If you really want to see how the pull-ups are calculated take a look in the I2C standard:
http://www.standardics.nxp.com/support/documents/i2c/pdf/i2c.bus.specification.pdf
Logged

Offline Offline
Edison Member
*
Karma: 3
Posts: 1001
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

In the code below you send a 16-bit variable to the thermopile device when a single byte is expected.

Code:
int getData(int reg) {
  Wire.beginTransmission(TPA81ADDR);
  Wire.send(reg);
  Wire.endTransmission();
  Wire.requestFrom(TPA81ADDR, 1);
  while (Wire.available() < 1) ;
  int data = Wire.receive();
  return data;
}

Change the "int reg" parameter to "uint8_t reg" and try again.
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 6
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks to Grumpy_Mike for the solution -- the circuit wasn't getting enough current. I added a second power supply and magically the TPA81 stabilized.

So, a better solution would probably be to use a power supply that can provide sufficient juice for both the uOLED and the TPA81 (as well as the Arduino). From the spec sheet it looks like the uOLED should average around 50ma. I can't find anything on the TPA81's current requirements; maybe 250ma on the Arduino (Duemilanove/ATMega328). This doesn't seem like much (less than an amp) -- should I be able to use (for instance) a wall wart to power everything through the Arduino external power supply socket?


Logged

Manchester (England England)
Offline Offline
Brattain Member
*****
Karma: 514
Posts: 31543
Solder is electric glue
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
should I be able to use (for instance) a wall wart to power everything through the Arduino external power supply socket?

If it is going through the on board regulator there is a limit on the amount of current you can get due to heat dissipation. It is discussed here:-
http://www.thebox.myzen.co.uk/Tutorial/Power_Examples.html
Logged

Pages: [1]   Go Up
Jump to: