NeoPixel Library and EEPROM

by Marcel2013 on Fri Sep 20, 2013 5:17 pm

Hi All,

I've written a sketch that uses the Adafruit NeoPixel library for my NeoPixel Digital 60 strip. Everything worked as expected until I've added the EEPROM library and perform a single read. Everything else in the sketch (IE. reading out sensors and communicating via serial and I2C) is running fine with EEPROM loaded, except for the NeoPixel library.

I'm using this all on a Arduino Uno 328P.

Does anyone know what is going on here and how to solve it. If you need more info, just let me know.

I've also tried to use the 'eeprom_read_byte'-function from the <avr/eeprom.h> library.. Same result.

Thanks in advance

Marcel
Marcel2013
 
Posts: 5
Joined: Fri Sep 20, 2013 4:00 pm

Re: NeoPixel Library and EEPROM

by adafruit_support_rick on Fri Sep 20, 2013 5:33 pm

Please post the code you're using - we'll have a look.
User avatar
adafruit_support_rick
 
Posts: 8585
Joined: Tue Mar 15, 2011 10:42 am
Location: Buffalo, NY

Re: NeoPixel Library and EEPROM

by Marcel2013 on Fri Sep 20, 2013 5:50 pm

Hi,

Here is my full sketch I'm using:

Code: Select all
/*************** INCLUDES ***************/
#include <avr/eeprom.h>
#include <Wire.h>
#include <Adafruit_NeoPixel.h>


/*************** DEFINE CONSTANTS ***************/
#define  AREF_VOLTAGE       5.0
#define  I2C_ADDR           0x40
#define  REG_MAP_SIZE       46
#define  MAX_SENT_BYTES     1
#define  IDENTIFICATION     0x46

#define  LEDPIN             3
#define  TEMPPIN            A0
#define  LUXPIN             A1

/*************** GLOBAL VARIABLES ***************/
int EEPROM_transitiondelay, EEPROM_numLEDS, EEPROM_USED;
int EEPROM_LKCRed, EEPROM_LKCGreen, EEPROM_LKCBlue;

int numLEDS = 60;

byte registerMap[REG_MAP_SIZE];
byte receivedCommands[MAX_SENT_BYTES];

byte validSETCommands[] = {0x15, 0x19, 0x23, 0x27, 0x31, 0x35, 0x37, 0x39, 0x41, 0x43};   // The valid SET commands

byte registerMapTemp[4];
boolean newTmpDataAvailable = false;
float TEMP_collector = 0;
int TEMP_counter = 0;
byte LKTemp[4];

byte registerMapLux[4];
boolean newLuxDataAvailable = false;
float LUX_collector = 0;
int LUX_counter = 0;
byte LKLux[4];
float lightResistance;
float currentLightInLux;
float lightInputVoltage;
float hardResistance = 1.8;

int endRed, endGreen, endBlue;        // Set the end color from the command received
int LKCRed, LKCGreen, LKCBlue;        // Last Known Color Setting

int rndArray[256];

byte queueCommand = 0x00;
boolean newQueueData = false;
boolean runQueue = false;
byte queueRed = 0x00;
byte queueGreen = 0x00;
byte queueBlue = 0x00;
int queueSteps = 0;
int queueCurrentStep = 0;
int transitiondelay = 15;

boolean stringComplete = false;
String inputString = "";
int charcounter = 0;

int counter = 0;

Adafruit_NeoPixel strip = Adafruit_NeoPixel(255, LEDPIN, NEO_GRB + NEO_KHZ800);

/*************** GENERAL FUNCTIONS ***************/
void setup() {
  analogReference(EXTERNAL);
  Serial.begin(115200);
  strip.begin();                                    // Initialize ledstrip
  strip.show();                                     // Set all pixels to 'off'
  //readEEPROM();
  startWire();
  registerMap[REG_MAP_SIZE - 1] = IDENTIFICATION;   // Set ID register         
  Serial.println(F("Ready"));
}

void loop() {
  TEMPreadSignal();
  newTmpDataAvailable = false;
  storeTmpData();
  newTmpDataAvailable = true;
  setLKTemp();
 
  LUXreadSignal();
  newLuxDataAvailable = false;
  storeLuxData();
  newLuxDataAvailable = true;
  setLKLux();
 
  if (newQueueData == true) {
    newQueueData = false;
    queueCommand = receivedCommands[0];
    switch (receivedCommands[0]) {
      case 21:          // (0x15) (n) Set color immediatly for whole strip.
        queueSteps = 1;
      break;
      case 25:          // (0x19) (c) Set color using fade for whole strip.
        queueSteps = 200;
      break;
      case 35:          // (0x23) (l) Whipe strip from left to right (no fade)
        queueSteps = numLEDS;
      break;
      case 39:          // (0x27) (r) Whipe strip from right to left (no fade)
        queueSteps = numLEDS;
      break;
      case 49:          // (0x31) (x) Set strip to color with random leds (no fade)
        queueSteps = numLEDS;
        for (int x = 0; x < numLEDS; x++) {
          rndArray[x] = x;
        }
      break;
      case 53:          // (0x35) (y) Turn entire LED-strip on to last known color
        queueSteps = 1;
        endRed = LKCRed;
        endGreen = LKCGreen;
        endBlue = LKCBlue;
      break;
      case 55:          // (0x37) (z) Turn entire LED-strip off
        queueSteps = 1;
        endRed = 0;
        endGreen = 0;
        endBlue = 0;
      break;
    }
    runQueue = true;
  }
  takeQueueStep();
  readSerial();
  serialEvent();
}
/**************** WIRE FUNCTIONS ***************/
void startWire() {
  Wire.begin(I2C_ADDR);
  Wire.onRequest(requestEvent);                     // Set interrupt - master requesting data from slave
  Wire.onReceive(receiveEvent);                     // Set interrupt - master sending data to slave
}

/*************** QUEUE FUNCTIONS ***************/

void takeQueueStep() {
  if (runQueue == true) {                    // Is the queue running?
    if (queueCurrentStep <= queueSteps) {
      switch(queueCommand) {
        case 21:      // 0x15 Direct
        case 53:      // 0x35 Turn on strip
        case 55:      // 0x37 Turn off strip
          setEntireStrip();
          queueRed = endRed;
          queueGreen = endGreen;
          queueBlue = endBlue;
        break;
        case 25:      // 0x19 fade
          calculateColor();
          for (int x=0; x < numLEDS; x++) {
            strip.setPixelColor(x, strip.Color(queueRed, queueGreen, queueBlue));
          }
          strip.show();
        break;
        case 35:          // (0x23) (l) Whipe strip from left to right (no fade)
          strip.setPixelColor(queueCurrentStep, strip.Color(endRed, endGreen, endBlue));
          strip.show();
          queueRed = endRed;
          queueGreen = endGreen;
          queueBlue = endBlue;
        break;
        case 39:          // (0x27) (r) Whipe strip from right to left (no fade)
          strip.setPixelColor((queueSteps-queueCurrentStep), strip.Color(endRed, endGreen, endBlue));
          strip.show();
          queueRed = endRed;
          queueGreen = endGreen;
          queueBlue = endBlue;
        break;
        case 49:          // (0x31) (x) Set strip to color with random leds (no fade)
          int rndNumber;
          rndNumber = random(0, (queueSteps - queueCurrentStep));
          int pixel;
          pixel = rndArray[rndNumber];
          int cnt = 0;  // shift array and fill last value with a 0
          for (int y = 0; y < numLEDS; y++) {
            if (y != rndNumber) {
              rndArray[cnt] = rndArray[y];
              cnt++;
            }
          }
          cnt++;
          rndArray[cnt] = 0;
          strip.setPixelColor(pixel, strip.Color(endRed, endGreen, endBlue));
          strip.show();
          queueRed = endRed;
          queueGreen = endGreen;
          queueBlue = endBlue;
        break;
      }
      LKCRed = queueRed;
      LKCGreen = queueGreen;
      LKCBlue = queueBlue;
      queueCurrentStep++;
    } else {
      resetQueue();
    }
    startWire();
    delay(transitiondelay);
  }
}

void resetQueue() {
  queueCurrentStep = 0;
  queueSteps = 0;
  runQueue = false;
}
/*************** RGB-STRIP FUNCTIONS ***************/
void setEntireStrip() {
  for (int x=0; x < numLEDS; x++) {
    strip.setPixelColor(x, strip.Color(endRed, endGreen, endBlue));
  }
  strip.show();
}
void calculateColor() {
  queueRed = queueRed + (endRed - queueRed) * queueCurrentStep / queueSteps;
  queueGreen = queueGreen + (endGreen - queueGreen) * queueCurrentStep / queueSteps;
  queueBlue = queueBlue + (endBlue - queueBlue) * queueCurrentStep / queueSteps;
}

/*************** I2C-HANDLER FUNCTIONS ***************/
void requestEvent() {  // The master requests data, so lets send it
  switch(receivedCommands[0]) {
    case 1:  // (0x01) Store temperature in memory spots (4 bytes = float)
      if(newTmpDataAvailable == true) {
        newTmpDataAvailable = false;
        Wire.write(registerMapTemp, 4);
      } else {
        Wire.write(LKTemp, 4);
      }
    break;
    case 6:  // (0x06)  Store the current Lux value in memory spots (4 bytes = float)
      if (newLuxDataAvailable == true) {
        newLuxDataAvailable = false;
        Wire.write(registerMapLux, 4);
      } else {
        Wire.write(LKLux, 4);
      }
    break;
    case 17:  // (0x11) Store current RGB color in memory spots (3 bytes = 3x int)
      registerMap[0] = LKCRed;
      registerMap[1] = LKCGreen;
      registerMap[2] = LKCBlue;
      Wire.write(registerMap, 3);
    break;
  }
}
void receiveEvent(int bytesReceived) {  //The master sends data, lets handle it
  for (byte a = 0; a < bytesReceived; a++) {    // Read the bytes
    receivedCommands[a] = Wire.read();
  }
  resetQueue();
  switch(receivedCommands[0]) {
    case 21:                  // 0x15
    case 25:                  // 0x19
    case 35:                  // 0x23
    case 39:                  // 0x27
    case 49:                  // 0x31
      endRed = receivedCommands[1];
      endGreen = receivedCommands[2];
      endBlue = receivedCommands[3];
      newQueueData = true;
    break;
    case 53:                        // 0x35
    case 55:                        // 0x37
      newQueueData = true;
    break;
    case 57:                        // 0x39
      transitiondelay = receivedCommands[1];
    break;
    case 65:                        // 0x41
      numLEDS = receivedCommands[1];
    break;
    case 67:
      writeEEPROM();
    break;
    default:                        // All others
      newQueueData = false;
    break;
  }
}
boolean isValidSetCommand(byte cmd) {
  for (int x=0; x<(sizeof(validSETCommands))-1; x++) {
    if (cmd == validSETCommands[x]) {
      return true;
    }
  }
  return false;
}
/***************** EEPROM FUNCTIONS ******************/
void readEEPROM() {
  EEPROM_transitiondelay = eeprom_read_byte((unsigned char *) 0);
  EEPROM_numLEDS = eeprom_read_byte((unsigned char *) 1);
  EEPROM_LKCRed = eeprom_read_byte((unsigned char *) 2);
  EEPROM_LKCGreen = eeprom_read_byte((unsigned char *) 3);
  EEPROM_LKCBlue = eeprom_read_byte((unsigned char *) 4);
  EEPROM_USED = eeprom_read_byte((unsigned char *) 5);
  if (EEPROM_USED == 0xFF) {
    EEPROM_transitiondelay = 15;
    EEPROM_numLEDS = 60;
    EEPROM_LKCRed = 0;
    EEPROM_LKCGreen = 0;
    EEPROM_LKCBlue = 0;
    Serial.println(F("Using defaults"));
  } else {
    Serial.println(F("Using stored values"));
  }
}

void writeEEPROM() {
  Serial.println("En we rossen data in de banken");
}

/*************** TEMPERATURE FUNCTIONS ***************/
void TEMPreadSignal() {
    int TEMP_signal = analogRead(TEMPPIN);
    TEMP_collector += ((((TEMP_signal * AREF_VOLTAGE) / 1024) - 0.5) * 100);
    TEMP_counter++;
    if (TEMP_counter >= 1000) {
      TEMP_collector = TEMP_collector / TEMP_counter;
      TEMP_counter = 1;
    }
}
void storeTmpData() {
  byte * byteTmpPointer;                              // We declare a pointer as type byte
  byte arrayTmpIndex = 0;                             // We need to keep track of where we are storing data in the array
  float TEMP = TEMP_collector / TEMP_counter;
  byteTmpPointer = (byte*)&TEMP;                      // Temperature is 4 bytes
  for (int i = 3; i > -1; i--) {
    registerMapTemp[arrayTmpIndex] = byteTmpPointer[i];  // Increment pointer to store each byte but MSB first
    arrayTmpIndex++;
  }
}
void setLKTemp() {
  for (int i =0; i < 4;i++) {
    LKTemp[i] = registerMapTemp[i];
  }
}

/*************** LUX FUNCTIONS ***************/
void LUXreadSignal() {
    float LUX_signal = getLux(analogRead(LUXPIN));
    LUX_collector += LUX_signal;
    LUX_counter++;
    if (LUX_counter >= 1000) {
      LUX_collector = LUX_collector / LUX_counter;
      LUX_counter = 1;
    }
}
float getLux(int reading) {
  float lightADCReading = reading;
  lightInputVoltage = 5.0 * ((float)lightADCReading / 1024.0);   // Calculating the voltage of the ADC for light
  lightResistance = (hardResistance * 5.0) / lightInputVoltage - hardResistance;     // Calculating the resistance of the photoresistor in the voltage divider
  currentLightInLux = 255.84 * pow(lightResistance, -10/9);    // Calculating the intensity of light in lux
  return currentLightInLux;
}
void storeLuxData() {
  byte * byteLuxPointer;                              // We declare a pointer as type byte
  byte arrayLuxIndex = 0;                             // We need to keep track of where we are storing data in the array
  float LUX = LUX_collector / LUX_counter;
  byteLuxPointer = (byte*)&LUX;                       // Lux is 4 bytes
  for (int i = 3; i > -1; i--) {
    registerMapLux[arrayLuxIndex] = byteLuxPointer[i];  // Increment pointer to store each byte but MSB first
    arrayLuxIndex++;
  }
}
void setLKLux() {
  for (int i =0; i < 4;i++) {
    LKLux[i] = registerMapLux[i];
  }
}
/*************** SERIAL FUNCTIONS ***************/
void readSerial() {
  if(stringComplete==true) {
    if(inputString == "T") {  // Get the current temperature
      Serial.println(TEMP_collector / TEMP_counter);
    } else if (inputString == "L") {  // Get the current Lux value
      Serial.println(LUX_collector / LUX_counter);
    } else if (inputString == "C") {  // Get the current RGB value
      Serial.print(LKCRed);Serial.print(F(":"));Serial.print(LKCGreen);Serial.print(F(":"));Serial.println(LKCBlue);
    }
    charcounter=0;
    inputString="";
    stringComplete = false;
  } 
}
void serialEvent() {
  while (Serial.available()) {
    char inChar = (char)Serial.read();
    if (inChar == '\n') {
      stringComplete = true;
    } else {
      inputString += inChar;
    }
  }
}
Marcel2013
 
Posts: 5
Joined: Fri Sep 20, 2013 4:00 pm

Re: NeoPixel Library and EEPROM

by adafruit_support_rick on Sat Sep 21, 2013 8:14 am

Your eeprom read function and the NeoPixel library should not be interfering with each other. I think that the likely explanation is a memory space problem. This kind of issue can create some very strange-looking symptoms.

Have a look at our Arduino Memories tutorial for some tips on solving this problem:
http://learn.adafruit.com/memories-of-an-arduino
User avatar
adafruit_support_rick
 
Posts: 8585
Joined: Tue Mar 15, 2011 10:42 am
Location: Buffalo, NY

SOLVED Re: NeoPixel Library and EEPROM

by Marcel2013 on Sat Sep 21, 2013 9:31 am

Hi Rick,

Thanks for the info. I have found my memoryleak using the handy freeRam function.
I changed the typecasting for serveral variables (from int to byte). That fixed the problem.

Kind regards,

Marcel
Marcel2013
 
Posts: 5
Joined: Fri Sep 20, 2013 4:00 pm

Re: NeoPixel Library and EEPROM

by adafruit_support_rick on Sat Sep 21, 2013 3:30 pm

Nice work! :D
User avatar
adafruit_support_rick
 
Posts: 8585
Joined: Tue Mar 15, 2011 10:42 am
Location: Buffalo, NY

Re: NeoPixel Library and EEPROM

by Marcel2013 on Sun Sep 22, 2013 9:48 am

Hi,

After solving the memory problem. I'd like to share with you all the result of what we've made.

Here is a link to the video: http://pidome.org/2013/09/22/little-video-showing-pidome-controlling-a-led-strip-with-an-arduino/

Marcel
Marcel2013
 
Posts: 5
Joined: Fri Sep 20, 2013 4:00 pm

Re: NeoPixel Library and EEPROM

by adafruit_support_rick on Sun Sep 22, 2013 11:25 am

Very nice - Thanks for the link! :D
User avatar
adafruit_support_rick
 
Posts: 8585
Joined: Tue Mar 15, 2011 10:42 am
Location: Buffalo, NY

Re: NeoPixel Library and EEPROM

by Marcel2013 on Sun Oct 06, 2013 6:03 pm

Hi All,

It's been a little while since I've been here, working on my project. After my last post of the video, I've rounded up the project and written a 'Howto' for building this little project. It can be found on http://pidome.wordpress.com/2013/10/06/control-your-led-strip-with-your-own-build-i2c-lts-lc-controller/. Because I couldn't find a Fritzing part for the NeoPixel Digital RGB Led Strip, I created one, which can also be found on the same page. Maybe other users may find it usefull.

Kind regards,
Marcel
Marcel2013
 
Posts: 5
Joined: Fri Sep 20, 2013 4:00 pm