Problem with Wire.h

Hello people,

I have strange problem and being quite the noob I run out of theories to test quite quickly. Here is the problem I hope someone can help me figure this out.

My code reads files stored on an SD card that contains delay and intensity information that I send via a DMX interface to dimmers. I now want to use a LCD to print messages but when I add #include <Wire.h> the whole thing falls apart.

Thanks for the help

Here is the code:

#include <SD.h>
#include <String.h>
#include <DmxSimple.h>
//#include <Wire.h>
#include <Adafruit_MCP23017.h>
#include <Adafruit_RGBLCDShield.h>

// Defines to set the backlight color
#define RED 0x1
#define YELLOW 0x3
#define GREEN 0x2
#define TEAL 0x6
#define BLUE 0x4
#define VIOLET 0x5
#define WHITE 0x7

//Set by default for the SD Card Library
//MOSI = Pin 11
//MISO = Pin 12
//SCLK = PIN 13
//We always need to set the CS Pin
const byte CS_Pin = 10;
//Simple Status Pin. May be removed
const byte SWStatusPin = 8;
//DMX pins
const byte DMXOutPin = 2;
const byte DMXDirectionPin = 4;
//Analog Switch Pin
const byte SWAnalogInPin = A1;
//Interrupt Input Pin
const byte SWDownInterruptPin = 3;

// Declare DMXValues Array and DMXValueIndex Counter. Keep Unsigned Integers below 65535
unsigned int DMXValues[15] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
byte DMXValueIndex = 0;
//Global Iteration Counter
byte IterationCounter = 0;
byte AvailableCounter = 0;
//Digital Conversion of Switch Value
volatile int SWAnalogValue = 0;
//If LightsOn == 0 --> Indicates that Ligths are OFF. Every Passage to any Command Files other than AllOFF00 turns on Flag
volatile byte LightsOnFlag = 0;

// Declare CSVStringBuffer Input Character Buffer, SimpleToken "container" and
// IntermediateBuffer Temporary Location for Read char from File
char CSVStringBuffer[80];
char *SimpleToken = NULL;
char IntermediateBuffer = NULL;

//Special character to indicate special handling of parsed strings
const byte LoopLastLine = 0x7E;
const byte Print2LCD = 0x40;

//Global DMX Command File Name Intermediate Variable
const char *InterruptCommandFilename = NULL;

//Expected file names on the SD card each associated with particular pattern
const char DMXInitialize[] = "DMXInit0.csv";
const char CommandFileOn[] = "AllOn100.csv";
const char CommandFileOff[] = "AllOff00.csv";
const char CommandFile1[] = "CSVTest2.csv";
const char CommandFile2[] = "Wave10ms.csv";
const char CommandFile3[] = "CSVTest4.csv";
const char CommandFile4[] = "Wave25ms.csv";
const char CommandFile5[] = "CSVTest6.csv";
const char CommandFile6[] = "WaveOpen.csv";
//const char CommandFile7[] = "CSVTest7.csv";

File CSVCommandFile;
const char *CommandFileName = NULL;

//Adafruit_RGBLCDShield lcd = Adafruit_RGBLCDShield();

void setup()
{
  //SetUp Serial Port for Debug
  Serial.begin(9600);
  //SetUp LCD as 16 characters and 2 rows
  //lcd.begin(16,2);
  
  //CS Pin is an output
  pinMode(CS_Pin, OUTPUT);
  pinMode(DMXOutPin, INPUT);
  
  //Set pinMode for DMXDirectionPin and set it HIGH;
  pinMode(DMXDirectionPin, OUTPUT);
  digitalWrite(DMXDirectionPin, HIGH); 
  
  //Set Pin Mode on Interrupt Pin
  pinMode(SWDownInterruptPin, INPUT);
  
  //Card will Draw Power from Pin 8, so set it high
  //Strange Arduino Idea... Arrrrggghhh them Software Designer they're so naughty!
  //This May not survive in Final Design
  pinMode(SWStatusPin, OUTPUT);  
  digitalWrite(SWStatusPin, HIGH);
  
  if (!SD.begin(CS_Pin))
  {
      return;
  }

  InterruptCommandFilename = DMXInitialize;
  attachInterrupt(1, SelectFile, FALLING);
  //lcd.print(F("Hello Earthling!"));
}

void loop()
{
  //If an interrupt has changed the value of the intermediate buffer then use it by assigning it to the CommnadFileName variable
  if(InterruptCommandFilename != NULL)
  {
    CommandFileName = InterruptCommandFilename;
    // Reset Index for Values Array before re-looping with new CSVCommandFile
    DMXValueIndex = 0;
    // Reset Index for CharBuffer before re-looping with new CSVCommandFile
    IterationCounter = 0;
    //Reset Intermediate Char Buffer re-looping with new CSVCommandFile
    IntermediateBuffer = 0x00;
    //Reset InterruptCommandFilename to NULL
    InterruptCommandFilename = NULL;
  }
  CSVCommandFile = SD.open(CommandFileName);
  if (CSVCommandFile)
  {
    // As long as there are characters and that the Index is less than 80 characters read the file 
    while(CSVCommandFile.available() && (IterationCounter <= 79) && !InterruptCommandFilename)
    {
      IntermediateBuffer = CSVCommandFile.read();
      // Look for the first exception, 0x0D or carriage return. May be absent in a Mac generated CSV file
      if (IntermediateBuffer == 0x0D)
      {
        continue; // If found, re-iterate the while loop
      }
      // Look for the second exception, 0x0A or line feed 
      else if (IntermediateBuffer == 0x0A)
      {
        CSVStringBuffer[IterationCounter] = NULL;
        if(CSVStringBuffer[0] == LoopLastLine)
        {
          break;
        }
        // Actual Parsing of CSVStringBuffer to find Tokens
        // This is where the magic happens :-)
        SimpleToken = strtok(CSVStringBuffer, ",");
        while(SimpleToken)
        {
          // Do something with this token
          DMXValues[DMXValueIndex] = atoi(SimpleToken);
          DMXValueIndex++;
          // Get the next token...
          SimpleToken = strtok(NULL, ",");
        }
        // Reset Index for Values Array before exiting and re-looping for the next line in CSVCommandFile
        DMXValueIndex = 0;
        // Reset Index for CharBuffer before exiting and re-looping for the next line in CSVCommandFile
        IterationCounter = 0;
       
        //Actual DMX Commands
        DmxSimple.usePin(DMXOutPin);
        DmxSimple.maxChannel(14);
        DmxSimple.write(1, DMXValues[1]);
        DmxSimple.write(2, DMXValues[2]);
        DmxSimple.write(3, DMXValues[3]);
        DmxSimple.write(4, DMXValues[4]);
        DmxSimple.write(5, DMXValues[5]);
        DmxSimple.write(6, DMXValues[6]);
        DmxSimple.write(7, DMXValues[7]);
        DmxSimple.write(8, DMXValues[8]);
        DmxSimple.write(9, DMXValues[9]);
        DmxSimple.write(10, DMXValues[10]);
        DmxSimple.write(11, DMXValues[11]);
        DmxSimple.write(12, DMXValues[12]);
        DmxSimple.write(13, DMXValues[13]);
        DmxSimple.write(14, DMXValues[14]);
        delay(DMXValues[0]);
      }
      // This section is where the CSVStringBuffer is filled with the characters from the file
      else
      {
        CSVStringBuffer[IterationCounter] = IntermediateBuffer;
        IterationCounter++;
      }
    }
  }

  CSVCommandFile.close();
  if(CSVStringBuffer[0] == LoopLastLine)
  {
    CommandFileName = NULL;
    DmxSimple.usePin(DMXOutPin);
    DmxSimple.maxChannel(14);
    DmxSimple.write(1, DMXValues[1]);
    DmxSimple.write(2, DMXValues[2]);
    DmxSimple.write(3, DMXValues[3]);
    DmxSimple.write(4, DMXValues[4]);
    DmxSimple.write(5, DMXValues[5]);
    DmxSimple.write(6, DMXValues[6]);
    DmxSimple.write(7, DMXValues[7]);
    DmxSimple.write(8, DMXValues[8]);
    DmxSimple.write(9, DMXValues[9]);
    DmxSimple.write(10, DMXValues[10]);
    DmxSimple.write(11, DMXValues[11]);
    DmxSimple.write(12, DMXValues[12]);
    DmxSimple.write(13, DMXValues[13]);
    DmxSimple.write(14, DMXValues[14]);
    delay(DMXValues[0]);
  }
}

void SelectFile()
{
  SWAnalogValue = analogRead(SWAnalogInPin);
  
  if((SWAnalogValue > 183) && (SWAnalogValue < 225))
 {
   if(LightsOnFlag == 0)
   {
     LightsOnFlag = 1;
     InterruptCommandFilename = CommandFileOn;
   }
   else
   {
     LightsOnFlag = 0;
     InterruptCommandFilename = CommandFileOff;
   }
 }
 else if((SWAnalogValue > 286) && (SWAnalogValue < 329))
 {
   LightsOnFlag = 1;
   InterruptCommandFilename = CommandFile1;
 }
 else if((SWAnalogValue > 388) && (SWAnalogValue < 431))
 {
   LightsOnFlag = 1;
   InterruptCommandFilename = CommandFile2;
 }
 else if((SWAnalogValue > 490) && (SWAnalogValue < 533))
 {
   LightsOnFlag = 1;
   InterruptCommandFilename = CommandFile3;
 }
 else if((SWAnalogValue > 593) && (SWAnalogValue < 636))
 {
   LightsOnFlag = 1;
   InterruptCommandFilename = CommandFile4;
 }
 else if((SWAnalogValue > 695) && (SWAnalogValue < 738))
 {
   LightsOnFlag = 1;
   InterruptCommandFilename = CommandFile5;
 }
 else if((SWAnalogValue > 798) && (SWAnalogValue < 841))
 {
   LightsOnFlag = 1;
   InterruptCommandFilename = CommandFile6;
 }
 else
 {
   //Do Nothing
 }
 CSVCommandFile.close();
}

I forgot to tell you that I ran avr-size on the .cpp.elf file and here is the result:

   text    data     bss     dec     hex filename
  15362     176    1448   16986    425a SDCardtoDMX.cpp.elf

It does not appear that I am running out of RA, well i don't think so

Thanks

Simon

pshoule:
the whole thing falls apart.

Are pieces actually breaking off from the Arduino?

Arrch: Very funny Mister :slight_smile:

Actually nothing physical falls apart LOL

Simon

Without knowing what "the whole thing falls apart" means, I guess you're running out of memory.

ok, let me clarify:

When I add the Wire.h include the system starts to be quite erratic: It seems to read the first CSV file and then deos not respond but it still seems to send DMX information but not continuously anymore and it does not respond to button presses.

Thanks

Simon

pylon:

Like I said earlier, I don't seem to run out of memory. I am using 1831 byes out of a possible 2048. Have I reached some kind of "practical" limit on the RAM?

Thanks

Simon

Where do you have that value from? avr-size? RAM is also consumed during the run of the program. If you're using 1.8kB of 2kB RAM without even having one running value (stack for example) you definitely have a problem with memory.

Thanks pylon. Yes I got the values from avr-size and you're right those are "static values". I'll try and reduce my memory usage and let you know.

Thanks again for the tip.

Simon
ps: I just may decide to be lazy and run this on a larger arduino :slight_smile:

I now want to use a LCD to print messages but when I add #include <Wire.h> the whole thing falls apart.

I'm confused about the need to include Wire.h in order to use an LCD. Perhaps you could clarify?

ps: I just may decide to be lazy and run this on a larger arduino

That may be necessary. The SD library needs a 512 byte buffer to read/write data. That's 1/4 of the memory on most Arduinos.

On the other hand, dumping the String library and using strings (NULL terminated arrays of chars) instead may be all that is required.