Program no longer compiles under 0012

I have a simple demonstration arduino program that used to compile and work prior to the 0012 release. Now it will not compile but I get no useful error messages. The program is split into a main program and an include file that has several functions. The program uses the Wire.h library. It will compile if I physically copy the include file into the main program and have only a 1-file sketch.

The main program, arduino_simple:
/*

  • Simple Arduino-based program to read values from the HRMI using the I2C interface
  • Connections
  • Arduino HRMI

  • +5 +5 (Power for the HRMI)
  • GND GND
  • Analog In 5 TX (I2C SCL) (recommend 4.7 kOhm pullup)
  • Analog In 4 RX (I2C SDA) (recommend 4.7 kOhm pullup)
  • Note: By default the Arduino Wiring library is limited to a maximum
  • I2C read of 32 bytes. The Get Heartrate command is limited
  • by this code to a maximum of 30 values (for a max I2C packet
  • of 32 bytes).

*/

#include "Wire.h"
#include "hrmi_funcs.h"

/*

  • Configuration Information
  • Change these constants to match your specific configuration. These
  • values are the factory default (no OP1-OP7 jumpers installed). Jumper
  • OP1 should be installed and jumper SJ1 removed.
  • HRMI_HOST_BAUDRATE should be set to the baudrate the host will use
  • to communicate with the Arduino over the serial interface.
  • HRMI_I2C_ADDR should be set to the I2C address the HRMI is configured
  • with.
    */
    #define HRMI_HOST_BAUDRATE 9600
    #define HRMI_I2C_ADDR 127

/*

  • Program constants
    */
    #define MAX_IN_BUFFSIZE 16

/*

  • Global variables
    */
    char serInStr[MAX_IN_BUFFSIZE]; // Serial input string array
    int numEntries = 0; // Number of HR values to request
    int numRspBytes; // Number of Response bytes to read
    byte i2cRspArray[34]; // I2C response array, sized to read 32 HR values
    byte hrmi_addr = HRMI_I2C_ADDR; // I2C address to use

/*

  • Arduino initialization code segment
    */
    void setup()
    {
    // Initialize the I2C communication
    hrmi_open();

// Initialize the serial interface
Serial.begin(HRMI_HOST_BAUDRATE);
}

/*

  • Arduino main code loop
    */
    void loop()
    {
    // Request a set of heart rate values
    hrmiCmdArg(hrmi_addr, 'G', (byte) numEntries);

// Get the response from the HRMI
numRspBytes = numEntries + 2;
if (hrmiGetData(hrmi_addr, numRspBytes, i2cRspArray) != -1) {
// send the results back on the serial interface in ASCII form
Serial.print("Request "); Serial.print(numEntries); Serial.print(" => ");
for (int i=0; i<numRspBytes; i++) {
Serial.print(i2cRspArray*, DEC);*

  • Serial.print(" ");*

  • }*

  • Serial.println();*

  • }*

  • // Setup to do it again*

  • if (++numEntries > 30)*

  • numEntries = 0;*

  • delay(1000); // Delay 1 second between commands*
    }[/font]
    The include file, hrmi_funcs.h:
    /*
    * hrmi_funcs.h
    *
    * Arduino library to communicate with a HRMI using I2C
    *
    * Written by Dan Julio
    * Version 1.0, 03/27/2008
    *
    */
    //#include <Wire.h>
    /*
    * hrmi_open: Initialize the I2C library
    * This routine must be called before attempting to communicate with I2C
    */
    static void hrmi_open()
    {

  • Wire.begin();*
    }
    /*
    * hrmiCmdArg: Send a Command followed by a single Argument
    */
    static void hrmiCmdArg(byte addr, byte cmd, byte arg)
    {

  • Wire.beginTransmission(addr);*

  • Wire.send(cmd);*

  • Wire.send(arg);*

  • Wire.endTransmission();*
    }
    /*
    * hrmiCmd: Send a Command with no argument
    */
    static void hrmiCmd(byte addr, byte cmd)
    {

  • Wire.beginTransmission(addr);*

  • Wire.send(cmd);*

  • Wire.endTransmission();*
    }
    /*
    * hrmiGetData: Get the specified number of data bytes from the HRMI into
    * an array.
    */
    static int hrmiGetData(byte addr, byte numBytes, byte* dataArray)
    {

  • Wire.requestFrom(addr, numBytes);*

  • if (Wire.available()) {*

  • for (int i=0; i<numBytes; i++)*
    _ dataArray = Wire.receive();_
    * return(0);*
    * }*
    * return(-1);*
    }
    [/font]

It's not usual practice to include C code in an include file and perhaps the Arduino build process doesn't handle this.

You could put your C code in a separate tab by renaming the current hrmi_funcs.h file to hrmi_funcs.cpp and create a header file for this called hrmi_funcs.h that you would include in the sketch:

/*
* hrmi_funcs.h
*
* Arduino library to communicate with a HRMI using I2C
* 
* Written by Dan Julio 
* Version 1.0, 03/27/2008
*
*/

//#include <Wire.h>

/*
* hrmi_open: Initialize the I2C library
*            This routine must be called before attempting to communicate with I2C
*/
static void hrmi_open();

/*
* hrmiCmdArg: Send a Command followed by a single Argument
*/
static void hrmiCmdArg(byte addr, byte cmd, byte arg);

/*
* hrmiCmd: Send a Command with no argument
*/
static void hrmiCmd(byte addr, byte cmd);

/*
* hrmiGetData: Get the specified number of data bytes from the HRMI into
*              an array.
*/
static int hrmiGetData(byte addr, byte numBytes, byte* dataArray);

Thanks Mem. I realize my code is non-standard. I wrote it when new to Arduino and had used someone else's code as an example. I may have been lucky it would compile under 0010 and 0011.

I tried what you suggested without luck. It's probably my misunderstanding of C++. I copied the hrmi_funcs.h to hrmi_funcs.cpp and created the new hrmi_funcs.h file exactly as you showed.

With 0011 I get the error message "error: 'void hrmi_open()' used but never defined". This message is shown in both the bar below the edit window and in the message area at the bottom of the window.

With 0012 I get the error message "In function 'void loop()':" in the message area at the bottom of the window and nothing in the bar above the output area (although it turns the burnt orange).

In the hrmi_funcs.cpp and hrmi_funcs.h files, remove the word static from all the functions and prototypes.

Also, you probably need to include #include <wprogram.h> in hrmi_funcs.h and #include <Wire.h> in hrmi_funcs.cpp

Unfortunately no go.

Arduino 0011 - with wprogram.h in hrmi_funcs.h I get errors in it. Without it I get "18: error: Wire.h: No such file or directory In function 'void hrmi_open()': At global scope:" in hrmi_funcs.cpp.

Arduino 0012 - With wprogram.h in hrmi_funcs.h I get "18: error: Wire.h: No such file or directory In function 'void hrmi_open()': At global scope:" in hrmi_funcs.cpp. Without it I get "In function 'void loop()'".

Although my original code was probably structured incorrectly why would it work in 0011 and not in 0012?

I did a check with the changes suggested in my previous post and it compiles without errors for me under 0012. I created a new sketch with your main sketch file (the first file below) I then added two tabs, pasting in the .cpp and .h files

Good luck!

this is the main sketch file:

/*
* Simple Arduino-based program to read values from the HRMI using the I2C interface
*
* Connections
*    Arduino            HRMI
*    -----------------------
*      +5                +5 (Power for the HRMI)
*      GND               GND
*      Analog In 5       TX (I2C SCL) (recommend 4.7 kOhm pullup)
*      Analog In 4       RX (I2C SDA) (recommend 4.7 kOhm pullup)
*
*
* Note: By default the Arduino Wiring library is limited to a maximum
*       I2C read of 32 bytes.  The Get Heartrate command is limited
*       by this code to a maximum of 30 values (for a max I2C packet
*       of 32 bytes).
* 
*/

#include "Wire.h"
#include "hrmi_funcs.h"

/*
* Configuration Information
*
* Change these constants to match your specific configuration.  These
* values are the factory default (no OP1-OP7 jumpers installed).  Jumper
* OP1 should be installed and jumper SJ1 removed.
*
* HRMI_HOST_BAUDRATE should be set to the baudrate the host will use
*   to communicate with the Arduino over the serial interface.
*
* HRMI_I2C_ADDR should be set to the I2C address the HRMI is configured
*   with.
*/
#define HRMI_HOST_BAUDRATE 9600
#define HRMI_I2C_ADDR      127


/*
* Program constants
*/
#define MAX_IN_BUFFSIZE 16


/*
* Global variables
*/
char serInStr[MAX_IN_BUFFSIZE];   // Serial input string array
int numEntries = 0;               // Number of HR values to request
int numRspBytes;                  // Number of Response bytes to read
byte i2cRspArray[34];                // I2C response array, sized to read 32 HR values
byte hrmi_addr = HRMI_I2C_ADDR;   // I2C address to use


/*
* Arduino initialization code segment
*/
void setup()
{
 // Initialize the I2C communication
 hrmi_open();

 // Initialize the serial interface
 Serial.begin(HRMI_HOST_BAUDRATE);
}


/*
* Arduino main code loop
*/
void loop()
{
 // Request a set of heart rate values
 hrmiCmdArg(hrmi_addr, 'G', (byte) numEntries);
     
 // Get the response from the HRMI
 numRspBytes = numEntries + 2;
 if (hrmiGetData(hrmi_addr, numRspBytes, i2cRspArray) != -1) {
   // send the results back on the serial interface in ASCII form
   Serial.print("Request "); Serial.print(numEntries); Serial.print(" => ");
   for (int i=0; i<numRspBytes; i++) {
     Serial.print(i2cRspArray[i], DEC);
     Serial.print(" ");
   }
   Serial.println();
  }
   
 // Setup to do it again
 if (++numEntries > 30)
     numEntries = 0;
 delay(1000);                  // Delay 1 second between commands
}

This is hrmi_funcs.h (added as a tab in the same directory as the sketch

/*
* hrmi_funcs.h
*
* Arduino library to communicate with a HRMI using I2C
*
* Written by Dan Julio
* Version 1.0, 03/27/2008
*
*/

//#include <Wire.h>
#include <wprogram.h>

/*
* hrmi_open: Initialize the I2C library
*            This routine must be called before attempting to communicate with I2C
*/
void hrmi_open();

/*
* hrmiCmdArg: Send a Command followed by a single Argument
*/
void hrmiCmdArg(byte addr, byte cmd, byte arg);

/*
* hrmiCmd: Send a Command with no argument
*/
void hrmiCmd(byte addr, byte cmd);

/*
* hrmiGetData: Get the specified number of data bytes from the HRMI into
*              an array.
*/
int hrmiGetData(byte addr, byte numBytes, byte* dataArray);

hrmi_funcs.cpp in the same directory added as a tab

/*
* hrmi_funcs.cpp
*
* Arduino library to communicate with a HRMI using I2C
* 
* Written by Dan Julio 
* Version 1.0, 03/27/2008
*
*/

#include <Wire.h>


#include  "hrmi_funcs.h"
/*
* hrmi_open: Initialize the I2C library
*            This routine must be called before attempting to communicate with I2C
*/
void hrmi_open()
{
 Wire.begin();
}


/*
* hrmiCmdArg: Send a Command followed by a single Argument
*/
void hrmiCmdArg(byte addr, byte cmd, byte arg)
{
 Wire.beginTransmission(addr);
 Wire.send(cmd);
 Wire.send(arg);
 Wire.endTransmission();
}


/*
* hrmiCmd: Send a Command with no argument
*/
void hrmiCmd(byte addr, byte cmd)
{
 Wire.beginTransmission(addr);
 Wire.send(cmd);
 Wire.endTransmission();
}


/*
* hrmiGetData: Get the specified number of data bytes from the HRMI into
*              an array.
*/
int hrmiGetData(byte addr, byte numBytes, byte* dataArray)
{
 Wire.requestFrom(addr, numBytes);
 if (Wire.available()) {
   for (int i=0; i<numBytes; i++)
     dataArray[i] = Wire.receive();
   return(0);
 }
 return(-1);
}

Dan,

0012 changed some things about the way code is organized. It's not too surprising that things have changed. To get your code to compile, do this:

  1. Create a new tab. Call it hrmi_funcs.cpp and insert all the code from the post's hrmi_funcs.h.
  2. Per mem's suggestion, remove all the "static" qualifiers from the functions.
  3. Put the main body of code on the main tab.
  4. Remove #include "hrmi_funcs.h" from the main tab.
  5. Add #include <Wire.h> and #include <WProgram.h> to the top of hrmi_funcs.cpp tab.
  6. Lastly, in the main tab, add the following right after the #include <Wire.h> line:
extern void hrmi_open();
extern void hrmiCmdArg(byte addr, byte cmd, byte arg);
extern void hrmiCmd(byte addr, byte cmd);
extern int hrmiGetData(byte addr, byte numBytes, byte* dataArray);

If this is too confusing, I can post the code as I got it to compile.

Mikal

Hope this isn't getting confusing, I guess Mikal was composing when I posted. We are both suggesting more or less the same thing.

We are both suggesting more or less the same thing.

Yes, but mem's suggestion is superior because it uses a header file to define the function prototypes in a common place.