Wire.endTransmission(); Causes Problems in the Code!

I've been stuck on this code using Arduino 1.0.
My usb port to the arduino device gets disconnected every time I use code Wire.endTransmission();.
Then I have a very hard time uploading new code,
because the current code onboard bounces the port before new code is uploaded.
I literally have to plug in the USB connecter right after compiling for a slim chance of uploading the new code.
This is the example code for the LiPower shield by Sparkfun.
I've taken an excerpt of the code to make troubleshooting easier.
What is wrong with this code or my setup?

============================================================
Comments at SparkFun LiPower Shield - DEV-10711 - SparkFun Electronics -

clang | last year 1

What may happen if I plug the Arduino to USB to upload some sketch with connected LiPower Shield with battery attached?

tim7 | last year 1

That would not be a healthy thing to do. The Uno’s power circuitry connects the 5V pin to USB power whenever Vin is less than 6.6V. The LiPower shield doesn’t supply Vin, so you’d end up with the output of the 5V step-up regulator on the shield shorted to the USB power on the Uno.

Member #338104 | about 6 months ago 1

Doesn’t that mean the example code is inherently dangerous? (Sorry to zombie your reply.)

============================================================

Does the LiPower Sheild need to been stacked on top of Arduino Uno R3 pins for (I2C) SCL and (I2C) SDA?
When I stack the LiPower Sheild on top of Arduino Uno R3 it doesn't connect these 2 pins.
Is that causing my problem?

The 2.5K resistor I purchased from ebay does not fit into the holes meant for it. The resistor is way bigger than expected. A 2.5K resistor is not available from RadioShack. Please provide guidance.

============================================================
My YouTube video shows the problem at hand. The LiPo battery is not attached when uploading this code. Please watch and provide advice if you can. Thank You.

BatteryShield_HELP.ino (2.55 KB)

Here are more pics that go with my questions.

Judging by the Sparkfun page you aren't supposed to upload sketches with the shield attached.

Thanks for that advice, however I just tried the same approach without the LiPo shield attached and I'm still getting the same error/bouncing noise.

The noise sounds like USB enumeration to me.

Without Wire.endTransmission() the other calls don't do much. They just put stuff into a buffer. It's when you call Wire.endTransmission() that the I2C library actually communicates.

Are you saying that you get this noise just with a Uno and nothing else connected? (apart from the USB cable)

That's correct. With just the Arduino board and nothing else connected I still get the bouncing noise. I understand that endTransmission transfers the data from the buffer, but it's that line of code causing problems. I don't know how to fix. thanks again for your help.

What do you mean by 'bouncing noise'?

What board is it? What bootloader?

Any hardware mods that would affect the USB-triggered reset?

LiPower_Sheild.JPG (3108.24 KB, 3680x2760 - viewed 1 times.)
...
SCL_SDA_not_connected.JPG (2108.31 KB, 3680x2760 - viewed 2 times.)
...
Resistor_Too_Big.JPG (1863.42 KB, 3680x2760 - viewed 2 times.)

As a courtesy to other forum users can you size down future photos in your image editor program please? 100K should be plenty to show what is connected to what. Those 3 photos add up to 7 Mb of data you are asking people to download, to help you with your issues.

PeterH:
What do you mean by 'bouncing noise'?

What board is it? What bootloader?

Any hardware mods that would affect the USB-triggered reset?

If you watch my YouTube video you'll hear the noise. Forget that I said bouncing. I hear "do-do" "do-do". This is when I loss my connection to the USB port. I'm using the Arduino Uno R3. Whatever bootloader is default. I haven't played around with the bootloader. No hardware modifications. I'm not at that advance level yet.

Ok, I'll take much lower resolution pics in the future. Those are 10.2 megabytes pics.

Does anyone else have the same problem uploading this code? Thanks.

Haven't tested it yet, but meanwhile on the practical side you could make it much easier to recover from the 'broken' state by putting a delay in setup() before you call the Wire code.

I just ran this code on a UNO R3 with no additional hardware attached other than the USB cable:

/* LiPower Shield Example Code
  by: Jim Lindblom
  SparkFun Electronics
  date: 1/3/12
  
  license: Creative Commons Attribution-ShareAlike 3.0 (CC BY-SA 3.0)
  Do whatever you'd like with this code, use it for any purpose.
  Please attribute and keep this license. And let me know if you
  make any major, awesome changes!
  
  This is example code for the MAX17043G chip on the LiPower Shield.
  The MAX17043G+U is a compact, low-cost 1S LiPo fuel gauge.
  The Arduino talks with the MAX17043 over an I2C (two-wire) interface,
  so we'll use the Wire.h library to talk with it.
  
  It's a silly example. It reads the battery voltage, and its percentage
  full and prints it out over serial. You probably wouldn't care about
  the battery voltage if you had the Arduino connected via USB. But this
  code does show you how to configure the MAX17043G, and how to read and
  manipulate the voltage values.
  
  This file was written to be compatible with Arduino 1.0. If you
  have Arduino 0023 or earlier, you'll need to change the Wire.read()'s
  to Wire.receive() and the Wire.write()'s to Wire.send();. And maybe rename
  the .ino to .pde.
*/

#include <Wire.h>

#define MAX17043_ADDRESS 0x36  // R/W =~ 0x6D/0x6C

// Pin definitions
int alertPin = 2;  // This is the alert interrupt pin, connected to pin 2 on the LiPower Shield


void setup()
{
  pinMode(alertPin, INPUT);
  digitalWrite(alertPin, HIGH);
 
  Serial.begin(9600);  // Start hardware serial
  Serial.println("Hello World");
  
  delay(5000);
  Serial.println("Start I2C");
  
  Wire.begin();  // Start I2C
  delay(100);
  configMAX17043(32);  // Configure the MAX17043's alert percentage
  delay(100);
  Serial.println("Done");
}

void loop()
{}

/* 
configMAX17043(byte percent) configures the config register of
the MAX170143, specifically the alert threshold therein. Pass a 
value between 1 and 32 to set the alert threshold to a value between
1 and 32%. Any other values will set the threshold to 32%.
*/
void configMAX17043(byte percent)
{
  if ((percent >= 32)||(percent == 0))  // Anything 32 or greater will set to 32%
    i2cWrite16(0x9700, 0x0C);
  else
  {
    //byte percentBits = 32 - percent;
    //i2cWrite16((0x9700 | percentBits), 0x0C);
  }
}

/*
i2cWrite16(unsigned int data, unsigned char address) writes 16 bits
of data beginning at an 8-bit address, and continuing to the next.
*/
//                 0x9700 = 38656  0x0C is the config register
void i2cWrite16(unsigned int data, unsigned char address)
{
  Wire.beginTransmission(MAX17043_ADDRESS);
  Wire.write(address);
  Wire.write((byte)((data >> 8) & 0x00FF));
  Wire.write((byte)(data & 0x00FF));
  Wire.endTransmission();
}

The output was:

Hello World
Start I2C
Done

There was no problem with the Arduino resetting or dropping the serial connection. I'm using Arduino 1.0.1 on Windows 7 Pro 64-bit SP1.

that is quite interesting. Well I've copied your code from the forum and I'm still having a problem with the code Wire.endTransmission(); I never make it to my message "you've now made it past Wire.endTransmission();" This happens in both Arduino 1.0 and Arduino 1.0.1. I'm using 64 bit Windows 7 as well. Really weird. What should I do? Backup projects and reinstall Arduino development environment?? :drooling_face: :frowning: :blush:

CODE:

/* LiPower Shield Example Code
  by: Jim Lindblom
  SparkFun Electronics
  date: 1/3/12
  
  license: Creative Commons Attribution-ShareAlike 3.0 (CC BY-SA 3.0)
  Do whatever you'd like with this code, use it for any purpose.
  Please attribute and keep this license. And let me know if you
  make any major, awesome changes!
  
  This is example code for the MAX17043G chip on the LiPower Shield.
  The MAX17043G+U is a compact, low-cost 1S LiPo fuel gauge.
  The Arduino talks with the MAX17043 over an I2C (two-wire) interface,
  so we'll use the Wire.h library to talk with it.
  
  It's a silly example. It reads the battery voltage, and its percentage
  full and prints it out over serial. You probably wouldn't care about
  the battery voltage if you had the Arduino connected via USB. But this
  code does show you how to configure the MAX17043G, and how to read and
  manipulate the voltage values.
  
  This file was written to be compatible with Arduino 1.0. If you
  have Arduino 0023 or earlier, you'll need to change the Wire.read()'s
  to Wire.receive() and the Wire.write()'s to Wire.send();. And maybe rename
  the .ino to .pde.
*/

#include <Wire.h>

#define MAX17043_ADDRESS 0x36  // R/W =~ 0x6D/0x6C

// Pin definitions
int alertPin = 2;  // This is the alert interrupt pin, connected to pin 2 on the LiPower Shield


void setup()
{
  pinMode(alertPin, INPUT);
  digitalWrite(alertPin, HIGH);
 
  Serial.begin(9600);  // Start hardware serial
  Serial.println("Hello World, wait 10 seconds");
  
  delay(10000);
  Serial.println("Start I2C by executing Wire.begin(); now");
  Wire.begin();  // Start I2C
  
 
  Serial.println("Wire.begin(); has executed");
  
  
  
  Serial.println("Start configMax in 5 seconds");
  
  delay(5000);

  configMAX17043(32);  // Configure the MAX17043's alert percentage
  
  
  Serial.println("configMax function has executed");
}

void loop()
{}

/* 
configMAX17043(byte percent) configures the config register of
the MAX170143, specifically the alert threshold therein. Pass a 
value between 1 and 32 to set the alert threshold to a value between
1 and 32%. Any other values will set the threshold to 32%.
*/
void configMAX17043(byte percent)
{
  if ((percent >= 32)||(percent == 0))  // Anything 32 or greater will set to 32%
    Serial.println("made it inside if statement");
    i2cWrite16(0x9700, 0x0C);
  //else
  //{
    //byte percentBits = 32 - percent;
    //i2cWrite16((0x9700 | percentBits), );
  //}
}

/*
i2cWrite16(unsigned int data, unsigned char address) writes 16 bits
of data beginning at an 8-bit address, and continuing to the next.
*/
//                 0x9700 = 38656  0x0C is the config register
void i2cWrite16(unsigned int data, unsigned char address)
{
  Serial.println("made it inside i2cWrite16 function");
  Serial.println("wait 5 seconds to begin transmission");
  delay(5000);
  Wire.beginTransmission(MAX17043_ADDRESS);
  
  Serial.println("beginTransmission has completed");
  Serial.println("wait 5 seconds to write to buffer");
  delay(5000);
  
  Wire.write(address);
  Wire.write((byte)((data >> 8) & 0x00FF));
  Wire.write((byte)(data & 0x00FF));
  Serial.println("write to buffer has completed");
  
  Serial.println("about to end transmission");
  Serial.println("wait 5 seconds");
  delay(5000);
  Wire.endTransmission();
  Serial.println("you've now made it past Wire.endTransmission();");
}

OUTPUT:

Hello World, wait 10 seconds
Start I2C by executing Wire.begin(); now
Wire.begin(); has executed
Start configMax in 5 seconds
made it inside if statement
made it inside i2cWrite16 function
wait 5 seconds to begin transmission
beginTransmission has completed
wait 5 seconds to write to buffer
write to buffer has completed
about to end transmission
wait 5 seconds

//edit::
i just uninstalled Arduino 1.0.1 and deleted folder in My Documents after backing up files. Now I installed Arduino 1.0.3. and still the same problem. I get the disconnect noise on endTransmission();. REALLY STRANGE!

The Wire library can hang if certain interrupts don't arrive. Do you have pull-up resistors on SDA / SCL?

I don't know if I have pull-up resistors on SDA / SCL. I've used many examples on this arduino uno board already. How do I find out? Also, do I need the LiPower shield connected when the code is executed?

I believe I need to add I2C pull-up resistors on the SDA (A4) and SCL (A5) lines. What size resistors should I tie between each line and Vdd (+)? I’m assuming 4.7K ohms for the MAX17043G+U IC. Is that correct?

UPDATE: I just tried tying SDA and SCL to Vdd (+) with 4.7K ohm resistors, then tried a 100K ohm resistors when the prior didn't work. Still same output and noise of usb reset... Agh! =(

Does the alert pin (D3) need to be supplied with Vdd (+) and used with a resistor? I see it is labeled an input in the example code.

encryptor:
Thanks for that advice, however I just tried the same approach without the LiPo shield attached and I'm still getting the same error/bouncing noise.

With no shield attached, what alert pin?

For the c2i bus communication on SDA (A4) SCL (A5), wouldn't it require that I put the battery shield back on after uploading the required software? Should I expect Wire.endTransmission(); to complete without having stacked the board onto of the Arduino Uno? Does someone agree with myself that I may need to tie SDA and SCL to Vdd (+) using a 4.7K resistor? The alert pin D3 is on the Li Power shield to alert when battery power source drops below 32%.

You said initially that Wire.endTransmission(); caused the USB reset, even with nothing attached to the Arduino. I am trying to get past that point for you. Does that happen or not?

Yes that is true. However, I just got past this whole issue now. For the USB reset (noise) not to happen I need the SDA and SCL lines tied to Vdd (+5v) and use of a 4.7K resistor on each line. This is just using the Arduino Uno R3 board and no other boards stacked.

Now that this is working, I'm going to introduce more of the original code. Currently, I'm stuck at the following while loop in the i2cRead16 function. Any help here?

  while (Wire.available() < 2)
     ;

ORIGINAL CODE:

/* LiPower Shield Example Code
  by: Jim Lindblom
  SparkFun Electronics
  date: 1/3/12
  
*/
#include <Wire.h>

#define MAX17043_ADDRESS 0x36  // R/W =~ 0x6D/0x6C

// Pin definitions
int alertPin = 2;  // This is the alert interrupt pin, connected to pin 2 on the LiPower Shield

// Global Variables
float batPercentage;
//float batVoltage;
//int alertStatus;

void setup()
{
  pinMode(alertPin, INPUT);
  digitalWrite(alertPin, HIGH);
 
  Serial.begin(9600);  // Start hardware serial
  
  
  Serial.println("Start Wire.begin() (i2c bus) in 5 seconds");
  delay(5000);
  Wire.begin();  // Start I2C
  Serial.println("Wire.begin() has executed");
 
 
  Serial.println("Start configMax in 5 seconds");
  delay(5000);
  configMAX17043(32);  // Configure the MAX17043's alert percentage
  Serial.println("configMax function has executed");
  
  
  Serial.println("Start qsMAX17043 in 5 seconds");
  delay(5000);
  qsMAX17043();  // restart fuel-gauge calculations
  Serial.println("qsMAX17043 function has executed");
}

void loop()
{
  Serial.println("Start percentMAX17043() in 5 seconds");
  delay(5000);
  batPercentage = percentMAX17043();
  Serial.println("percentMAX17043 function has executed");
  
  //batVoltage = (float) vcellMAX17043() * 1/800;  // vcell reports battery in 1.25mV increments
  //alertStatus = digitalRead(alertPin);
  delay(3000);
  Serial.print(batPercentage, 2);  // Print the battery percentage
  Serial.println(" % battery life");
  // Serial.print(batVoltage, 2);  // print battery voltage
  // Serial.println(" battery's voltage");
  // Serial.print("Alert Status = ");
  // Serial.println(alertStatus, DEC);
  Serial.println();
  delay(1000);
}

/*
vcellMAX17043() returns a 12-bit ADC reading of the battery voltage,
as reported by the MAX17043's VCELL register.
This does not return a voltage value. To convert this to a voltage,
multiply by 5 and divide by 4096.
*/
/*
unsigned int vcellMAX17043()
{
  unsigned int vcell;
  
  vcell = i2cRead16(0x02);
  vcell = vcell >> 4;  // last 4 bits of vcell are nothing
  
  return vcell;
}
*/

/*
percentMAX17043() returns a float value of the battery percentage
reported from the SOC register of the MAX17043.
*/
float percentMAX17043()
{
  unsigned int soc;
  float percent;
  
  Serial.println("made it inside percentMAX17043 function");
  Serial.println("wait 5 seconds to call i2cRead16(0x04)");
  delay(5000);
  
  soc = i2cRead16(0x04);  // Read SOC register of MAX17043
  percent = (byte) (soc >> 8);  // High byte of SOC is percentage
  percent += ((float)((byte)soc))/256;  // Low byte is 1/256%
  
  return percent;
}


/* 
configMAX17043(byte percent) configures the config register of
the MAX170143, specifically the alert threshold therein. Pass a 
value between 1 and 32 to set the alert threshold to a value between
1 and 32%. Any other values will set the threshold to 32%.
*/

void configMAX17043(byte percent)
{
  if ((percent >= 32)||(percent == 0))  // Anything 32 or greater will set to 32%
    i2cWrite16(0x9700, 0x0C);
  else
  {
    byte percentBits = 32 - percent;
    i2cWrite16((0x9700 | percentBits), 0x0C);
  }
}


/* 
qsMAX17043() issues a quick-start command to the MAX17043.
A quick start allows the MAX17043 to restart fuel-gauge calculations
in the same manner as initial power-up of the IC. If an application's
power-up sequence is very noisy, such that excess error is introduced
into the IC's first guess of SOC, the Arduino can issue a quick-start
to reduce the error.
*/
void qsMAX17043()
{
  Serial.println("made it inside qsMAX17043 function");
  Serial.println("wait 5 seconds to call i2cWrite16(0x4000, 0x06)");
  delay(5000);
  
  i2cWrite16(0x4000, 0x06);  // Write a 0x4000 to the MODE register
 
  Serial.println("you've made it thru i2cWrite16(0x4000, 0x06)");
  delay(5000);
}

/* 
i2cRead16(unsigned char address) reads a 16-bit value beginning
at the 8-bit address, and continuing to the next address. A 16-bit
value is returned.
*/

unsigned int i2cRead16(unsigned char address)
{
  int data = 0;
  
  Serial.println("you've made it inside i2cRead16 function");
  
  Serial.println("wait 5 seconds to begin transmission");
  delay(5000);
  Wire.beginTransmission(MAX17043_ADDRESS);
  Serial.println("beginTransmission has completed");
  
  Serial.println("wait 5 seconds to write to buffer");
  delay(5000);
  Wire.write(address);
  Serial.println("write to buffer has completed");
  
  Serial.println("wait 5 seconds to end transmission");
  delay(5000);
  Wire.endTransmission();
  Serial.println("you've made it past Wire.endTransmission()");
  
  //stuck here right now!!!
  
  Serial.println("wait 5 seconds to requestFrom 17043 address 2 bytes");
  delay(5000);
  Wire.requestFrom(MAX17043_ADDRESS, 2);
  Serial.println("you've made it past requestFrom 17043 address 2 bytes");
  
  Serial.println("wait 5 seconds to enter while(Wire.available()<2)");
  delay(5000);
  while (Wire.available() < 2)
    ;
  Serial.println("you've made it past while(Wire.available()<2)");
 
  Serial.println("wait 5 seconds to call Wire.read()");
  delay(5000);     
  data = ((int) Wire.read()) << 8;
  data |= Wire.read();
  Serial.println("you've made it past Wire.read()");
 
  Serial.println("wait 5 seconds to return data");
  delay(5000); 
  return data;
  Serial.println("you've made it past return data");
}


/*
i2cWrite16(unsigned int data, unsigned char address) writes 16 bits
of data beginning at an 8-bit address, and continuing to the next.
*/
//              0x9700 = 38656, 0x0C is the config register (memory)
void i2cWrite16(unsigned int data, unsigned char address)
{
  Serial.println("made it inside i2cWrite16 function");
  Serial.println("wait 5 seconds to begin transmission");
  delay(5000);
  
  Wire.beginTransmission(MAX17043_ADDRESS);
  
  Serial.println("beginTransmission has completed");
  Serial.println("wait 5 seconds to write to buffer");
  delay(5000);
  
  Wire.write(address);
  Wire.write((byte)((data >> 8) & 0x00FF));
  Wire.write((byte)(data & 0x00FF));
  Serial.println("write to buffer has completed");
  
  Serial.println("wait 5 seconds to end transmission");
  delay(5000);
  
  Wire.endTransmission();
  Serial.println("you've made it past Wire.endTransmission()");
}

OUTPUT:

Start Wire.begin() (i2c bus) in 5 seconds
Wire.begin() has executed
Start configMax in 5 seconds
made it inside i2cWrite16 function
wait 5 seconds to begin transmission
beginTransmission has completed
wait 5 seconds to write to buffer
write to buffer has completed
wait 5 seconds to end transmission
you've made it past Wire.endTransmission()
configMax function has executed
Start qsMAX17043 in 5 seconds
made it inside qsMAX17043 function
wait 5 seconds to call i2cWrite16(0x4000, 0x06)
made it inside i2cWrite16 function
wait 5 seconds to begin transmission
beginTransmission has completed
wait 5 seconds to write to buffer
write to buffer has completed
wait 5 seconds to end transmission
you've made it past Wire.endTransmission()
you've made it thru i2cWrite16(0x4000, 0x06)
qsMAX17043 function has executed
Start percentMAX17043() in 5 seconds
made it inside percentMAX17043 function
wait 5 seconds to call i2cRead16(0x04)
you've made it inside i2cRead16 function
wait 5 seconds to begin transmission
beginTransmission has completed
wait 5 seconds to write to buffer
write to buffer has completed
wait 5 seconds to end transmission
you've made it past Wire.endTransmission()
wait 5 seconds to requestFrom 17043 address 2 bytes
you've made it past requestFrom 17043 address 2 bytes
wait 5 seconds to enter while(Wire.available()<2)