Simultaneous Use of Ethernet & Wire Libraries

Is there a problem with trying to use the Ethernet and Wire libraries at the same time?

I have a sketch that waits for an incoming UDP message which contains a command. In response to the command my Uno needs to communicate to a Smart Battery using the I2C bus. The data obtained from the Smart Battery is then packaged up into a UDP message and the message is sent back to the client via Ethernet. When the Sketch is run, I can see the incoming UDP message is decoded properly, but the call to Wire.write just hangs.

Note that I have another Sketch that does NOT use the Shield and uses the Wire library to talk to a Smart Battery with no issue (similar Wire lib code).

I use the Ethernet shield and I2C together no problems. Post your code.

Here is a stripped-down version of the code that exhibits the problem.

See function sendCmd. The calls to Wire.beginTransmission, Wire.write return OK. The call to Wire.endTransmission never returns.

//       1         2         3         4         5         6         7         8
//345678901234567890123456789012345678901234567890123456789012345678901234567890
/*
 SmartBatMon.ino
 
 1. Wait for UDP message from client
 2. Parse command
 3. Create message containing response to command
 4. Send UDP message back to client
 
 Incoming Message syntax:
   "?Static"
 
 Outgoing (returned) Message syntax:
   In response to ?Static command:
     "S," followed by a comma separated list of text values that I determined
     need to be read 1 time. In this Sketch, only the Smart Battery's
     manufacturer and device name are queried.

/*****************************************************************************/

#include <SPI.h>          // needed for Arduino versions later than 0018
#include <Ethernet.h>
#include <EthernetUdp.h>  // UDP library from: bjoern@cs.stanford.edu 12/30/2008
#include <Wire.h>

const int batAddr = 0x0B;  // Smart Battery slave address

byte mac[] = {0x90, 0xA2, 0xDA, 0x0D, 0x9B, 0x4A};  // MAC address of Arduino

unsigned int localPort = 8888;      // local port to listen on

// Room for entire contents of static or dynamic message response
const unsigned int ReplyBufferSize = 256;    // Size of reply buffer

// ****** Smart Battery Commands & Returned Data Type ******
const byte cmdManufName        = 0x20;  // string, Manufacturer's name
const byte cmdDevName          = 0x21;  // string, Device name
const byte cmdDevChem          = 0x22;  // string, Device chemistry

// buffers for receiving amd sending data
char cPacketBuffer[UDP_TX_PACKET_MAX_SIZE]; //buffer to hold incoming packet
char cReplyBuffer[ReplyBufferSize];

// An EthernetUDP instance to let us send and receive packets over UDP
EthernetUDP Udp;

// Debug mode
boolean debug;

// Simulation mode (1 = On (no battery connected), 0 = Off (battery connected)
int simMode;


void setup()
{
  // start the Ethernet and UDP:
  Ethernet.begin(mac);  // Using DHCP
  Udp.begin(localPort);

  Serial.begin(9600);
  Serial.println("SmartBatMon sketch executing...");
  Serial.println();

  debug = false;
  
  // Set simMode Off (battery connected)
  // Set simMode = 1 to just return canned buffer when no battery is connected.
  simMode = 0;
}


void loop()
{
  const char comma = ',';
  
  String    strTempString = "";
  

  // if there's data available, read a packet
  int packetSize = Udp.parsePacket();

  if (packetSize)
  {
    Serial.print("Received ");
    Serial.print(packetSize);
    Serial.print(" byte packet from ");

    IPAddress remote = Udp.remoteIP();

    for (int i =0; i < 4; i++)
    {
      Serial.print(remote[i], DEC);
      if (i < 3)
        Serial.print('.');
    }

    Serial.print(", port ");
    Serial.println(Udp.remotePort());

    // read the packet into cPacketBufffer
    Udp.read(cPacketBuffer, UDP_TX_PACKET_MAX_SIZE);
    cPacketBuffer[packetSize] = 0;  // Null-terminate the buffer

    Serial.print("Contents: ");
    Serial.print('"');
    Serial.print(cPacketBuffer);
    Serial.println('"');

    // Parse the command
    String Spb = String(cPacketBuffer);
    
    // Convert to upper case
    Spb.toUpperCase();

    if (Spb.substring(0,7) == "?STATIC")  // ENDING index NOT included!
    {
      getStatic();
    }
    else
    {
      sprintf(cReplyBuffer, "ERROR: Unknown command!");
      sendReply();
    }

    Serial.println("----------------------------------------");
  }
  delay(10);
}

//******************************************************************************
//
// function sendCmd()
//
// Purpose:
//   Sends a command to Smart Battery. Checks for transmission error.
//
// Parameters:
//   byte cmd:  SB spec command value
//
// Returns:
//   unsigned int: Transmission error code
//
//******************************************************************************
unsigned int sendCmd(byte cmd)
{
  byte errorCode = 0;

  Serial.println("Call Wire.beginTransmission"); // See this
  Wire.beginTransmission(batAddr);
  
  Serial.println("Call Wire.write");  // See this
  Wire.write(cmd);
  
  Serial.println("Call Wire.endTransmission");  // See this
  errorCode = Wire.endTransmission();
  Serial.println("Ret from Wire.endTransmission");  // NEVER see this

  if (errorCode)
  {
    Serial.print("Wire.write returned errorCode 0x");
    Serial.println(errorCode, HEX);
  }

  return(errorCode);
}

//******************************************************************************
//
// function readDataWord()
//
// Purpose:
//   Reads a 16-bit integer from the Smart Battey
//
// Parameters:
//   None
//
// Returns:
//   int: 16-bit value returned in response to command
//
//******************************************************************************
int readDataWord()
{
  byte data1, data2;
  int retWord;
  
  Wire.requestFrom(batAddr, 2);
  data1 = Wire.read();
  data2 = Wire.read();
  retWord = (256 * data2) + data1;
  
  if (debug)
  {
    Serial.print("Returned word = 0x");
    Serial.println(retWord, HEX);
  }
  
  return(retWord);
}

//******************************************************************************
//
// function readDataString()
//
// Purpose:
//   Reads a character string from Smart Battery
//
// Parameters:
//   None
//
// Returns:
//   String: character string returned in response to command
//
//******************************************************************************
String readDataString()
{
  // From the Smart Battery spec:
  // When a command returns "string", the first byte is a count (up to 32) of
  // the characters that follow.

  String dataString = "";
  
  Wire.requestFrom(batAddr, 15);
  
  // Get the number of characters in the returned string
  int blkCnt = Wire.read();
  
  while (blkCnt > 0)
  {
    dataString += (char)Wire.read();
    blkCnt--;
  }

  return(dataString);
}

//******************************************************************************
//
// function sendReply()
//
//******************************************************************************
void sendReply()
{
  // send reply to IP address and port that sent us the packet we received
  //Serial.println(Udp.remotePort());
  Serial.println("Reply Buffer:");
  Serial.println(cReplyBuffer);
  delay(100);
  
  // NOTE: Port number used here MUST match recvPort in VB code!
  Udp.beginPacket(Udp.remoteIP(), 9898);
  Udp.write(cReplyBuffer);
  Udp.endPacket();
}

//******************************************************************************
//
// function sendCmdGetResponse()
//
// Parameters:
//   byte cmdCode: Command to send
//
// Returns: Response to command or "ERROR"
//
//******************************************************************************
String sendCmdGetResponse(byte cmdCode)
{
  String strReturnData = "ERROR";
  
  unsigned sendStatus = sendCmd(cmdCode);
  
  if (sendStatus == 0)
  {
    if ((cmdCode >= cmdManufName) && (cmdCode <= cmdDevChem))
      strReturnData = readDataString();
    else
      strReturnData = String(readDataWord());
  }

  return(strReturnData);
}

//******************************************************************************
//
// function getStatic()
//
//******************************************************************************
void getStatic()
{
  const char comma = ',';
  
  String    strStaticBuff = "";

  // Returns the following information. Each item is comma separated string.
  // 1.  Manufacturer name
  // 2.  Device name

  // Indicate static data being returned
  strStaticBuff = "S";
  strStaticBuff += comma;
  
  // *********************** Manufacturer name ***********************
  if (simMode == 0)
  {
    strStaticBuff += sendCmdGetResponse(cmdManufName);
  }
  else
  {
    strStaticBuff += "Panasonic";
  }
  strStaticBuff += comma;

  // *********************** Device name ***********************
  if (simMode == 0)
  {
    strStaticBuff += sendCmdGetResponse(cmdDevName);
  }
  else
  {
    strStaticBuff += "MyBat";
  }
  
  // Convert String to char and send it to client
  strStaticBuff.toCharArray(cReplyBuffer, ReplyBufferSize);
  sendReply();
}

Where is your Wire.begin() call in setup?

Oh crap! Chalk this up a to a copy/paste error. Sketch seems to be working fine now.

Thank you, Surfer Tim, for taking the time to help! :slight_smile:

However, you would think the very FIRST call to the Wire library would be the one to hang, not the 3rd one.