Neopixel and SD card

I don't understand how I don't need a buffer.

You read one byte from the file and then you put it in the strip array. You repeat this until you have read 400 * 3 bytes. You do not read all the frame into memory and then transfer it to the strip array.

I need colors though. For me, this is all the data I need for one LED: 4d220d. No?
Also, how do I not need delimiters?

Yes just three bytes no delimiter because you always have three bytes, you don't need anything else to tell you that all the data has been read.

But my variables still use 49% of available SRAM for some reason.

Because that is only an estimate, it will not give you an accurate figure.

You read one byte from the file and then you put it in the strip array.

What is the strip array?

Yes just three bytes no delimiter because you always have three bytes, you don't need anything else to tell you that all the data has been read.

I'm really confused. Hex color 4d220d is 6 bytes, how do I only need 3, and which array do I store it into?

The way I was thinking of doing this is:

while c<400:

	while char_count<6:

		str value+=str char
		char_count+=1

	char_count=1
	setpixelcolor(c, value)
	c+=1

pixels.show()

What way are you thinking of doing this?

What is the strip array?

The array that is set up when you do this:-
Adafruit_NeoPixel pixels = Adafruit_NeoPixel ....

I'm really confused. Hex color 4d220d is 6 bytes,

No it is not it is three bytes 0x4d, 0x22, 0x0d. A byte is 8 bits. It takes two characters to express one byte in hexadecimal but the storage is only one byte.

Your sample code seems to be in Python not C.

What way are you thinking of doing this?

Open a file and get the file pointer and store it in a variable called fileptr
then something like this:-

byte red,green,blue;
int count = 0;
while(count < 400){
  red = fileptr.read();
  green = fileptr.read();
  blue = fileptr.read();
pixels.setPixelColor(count, red,green,blue);
count ++;
}
pixels.show();

Edit this compiles.

It just doesn't work man, this is really annoying.

Just including the libraries messes it all up. This is the official simple test from the Adafruit Neopixel library examples. It works fine, and if I add the 2 includes SD.h and SPI.h, it doesn't work anymore.

// NeoPixel Ring simple sketch (c) 2013 Shae Erisson
// released under the GPLv3 license to match the rest of the AdaFruit NeoPixel library

#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
  #include <avr/power.h>
#endif

#include <SPI.h> // When I add these 2 lines,
#include <SD.h> // it stops working, nothing lights up

// Which pin on the Arduino is connected to the NeoPixels?
// On a Trinket or Gemma we suggest changing this to 1
#define PIN            6

// How many NeoPixels are attached to the Arduino?
#define NUMPIXELS      16

// When we setup the NeoPixel library, we tell it how many pixels, and which pin to use to send signals.
// Note that for older NeoPixel strips you might need to change the third parameter--see the strandtest
// example for more information on possible values.
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

int delayval = 500; // delay for half a second

void setup() {
  // This is for Trinket 5V 16MHz, you can remove these three lines if you are not using a Trinket
#if defined (__AVR_ATtiny85__)
  if (F_CPU == 16000000) clock_prescale_set(clock_div_1);
#endif
  // End of trinket special code

  pixels.begin(); // This initializes the NeoPixel library.
}

void loop() {

  // For a set of NeoPixels the first NeoPixel is 0, second is 1, all the way up to the count of pixels minus one.

  for(int i=0;i<NUMPIXELS;i++){

    // pixels.Color takes RGB values, from 0,0,0 up to 255,255,255
    pixels.setPixelColor(i, pixels.Color(0,150,0)); // Moderately bright green color.

    pixels.show(); // This sends the updated pixel color to the hardware.

    delay(delayval); // Delay for a period of time (in milliseconds).

  }
}

However there is slight change: the Arduino "L" LED does light up. But the LED strip doesn't.

I found a working code on instructables for exactly my setup, except with 256 LEDs.

I read the frame files and it worked just fine. Then, I modified the frames, added 144 pixels to make them 400 pixels, modified the N_PIXEL variable (number of pixels) in the sketch, and it doesn't work anymore. So it is a memory issue.

Here is the working code with 200 pixels:

// NeoBoard

#include <SPI.h>
#include <SD.h>
#include <Adafruit_NeoPixel.h>

String inString = "";    // string to hold input
int char_counter=1;

int N_PIXELS = 200; // Number of pixels

void setup() {
  Serial.begin(9600);
  SD.begin(4);
}

void loop() {
  loadImages("Galaga0.txt");
  loadImages("Galaga01.txt");
}

void loadImages(String imagee) {
  File entry = SD.open(imagee);
  while (true) {
    //File entry =  dir.openNextFile();
    if (!entry) {break;}
    if (!entry.isDirectory() && entry.size() != 4096){
      //Serial.print(entry.name()); Serial.print(" - "); Serial.println(entry.size(), DEC);
      int bright = analogRead(1);
      //Serial.println(bright);
      int dim = map(bright, 0, 1023, 0, 255); //dimmer function
      
      Adafruit_NeoPixel strip = Adafruit_NeoPixel(N_PIXELS, 6, NEO_GRB + NEO_KHZ800);
      strip.begin();
      strip.setBrightness(dim); //insert dimmer function
      int counter = 0; //start at 0

      while(counter<N_PIXELS){
        int inChar = entry.read();
        inString += (char)inChar;
        if (char_counter==6) {
          Serial.println(inString);
          Serial.println(counter);
          
          strip.setPixelColor(counter, strip.Color(0,150,0));
          inString = "";
          counter++;
          char_counter=0;
        }
        char_counter++;
      }
      strip.show();
      delay(5000); // This is how fast the arduino will cycle through the image
    }
    entry.close();
    char_counter=0;
  }
  //dir.close();
}

And if I change N_PIXELS to 400, it doesn't work. Here is what a frame file looks like:

29b29929b29929b29929b29929b29929b29929b29929b29929b29929b29929b29929b29929b29929b29929b29929b299... 400 times

So is my only option to buy a Mega or Zero?

I found a working code on instructables

Instructables are crap, they are mainly written by idiots.

This particular idiot is using String which has problems with memory usage and tends to crash. It also loads in a heap of text files so it needs a large buffer

Here is some short code that will do what I said, I left the print in the code to see what it is doing. The data file is just filled up with some random hex numbers.

// Simple reading neopixels from an SD card by Mike Cook
// released under the GPLv3 license to match the rest of the AdaFruit NeoPixel library

#include <Adafruit_NeoPixel.h>

// Which pin on the Arduino is connected to the NeoPixels?
#define PIN            6

// How many NeoPixels are attached to the Arduino?
#define NUMPIXELS      6

#include <SPI.h>
#include <SD.h>

File fileptr;
  
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

int delayval = 500; // delay for half a second

void setup() {
  Serial.begin(9600);
  pixels.begin(); // This initializes the NeoPixel library.
  wipe();
  pixels.show();
   if (!SD.begin(4)) {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("initialization done.");
    fileptr = SD.open("test.PAT");
  if (fileptr) {
    Serial.println("test.PAT open");
    // fileptr.close();
  }

}

void nextPattern(){
byte red,green,blue;
int count = 0;
while(count < 6){
    Serial.print("LED ");
    Serial.print(count);
    Serial.print(" - ");
  red = fileptr.read();
    Serial.print(red); // for seeing what is happening comment out later
    Serial.print(",");
  green = fileptr.read();
    Serial.print(green);
    Serial.print(",");
  blue = fileptr.read();
    Serial.print(blue);
    Serial.println("");
pixels.setPixelColor(count, red,green,blue);
count ++;
}
pixels.show();
}

void loop() {
  for(int i=0;i<92;i++){
    Serial.println();
    Serial.print("Pattern ");
    Serial.println(i);
    nextPattern();
    delay(delayval);
  }
  fileptr.close();
  Serial.println("file closed");
  wipe();
  pixels.show();
  Serial.println("Finished patterns press reset to repeat");
  while(true) { } // hang here with the file closed
}

void wipe(){
       for(int i=0;i<pixels.numPixels();i++){
       pixels.setPixelColor(i, pixels.Color(0,0,0)); 
       }
  }

This is the print out in the serial monitor

Pattern 89
LED 0 - 48,48,48
LED 1 - 48,48,10
LED 2 - 48,48,48
LED 3 - 48,48,48
LED 4 - 10,48,48
LED 5 - 48,48,48

Pattern 90
LED 0 - 48,10,48
LED 1 - 48,48,48
LED 2 - 48,48,10
LED 3 - 48,48,48
LED 4 - 48,48,48
LED 5 - 10,48,48

Pattern 91
LED 0 - 48,48,48
LED 1 - 48,10,48
LED 2 - 48,48,48
LED 3 - 48,48,10
LED 4 - 48,48,48
LED 5 - 48,48,48
file closed
Finished patterns press reset to repeat

Attached is the test pattern file to put on the SD card.
Change the file type from .TXT to .PAT because the forum won't let me upload strange extensions.
P.S. I just made up the .PAT short for pattern.

test.txt (1.65 KB)

It looks like the limit on this is about 240 LEDs. You can probably get a bit more by taking out the print statements but it will not approach what you want so yes buy a Mega or a Zero.
Note if you go for a Zero then that uses 3V3 signals so you will have to build a buffer to drive the Neopixels.

Note we have knocked on the head your theory that you can't run an SD card and drive Neopixels.

Ok, I will buy a Mega then, the code is the exact same one right? 8K SRAM should be enough?

Thanks a lot for your help. One last question, when I modify the patterns file by adding 6 different colors:

29B299
B22929
000CFF
FBFF00
35AD4D
1EDADF
000000
000000
000000

The LED don't change colors, they're always in the blue spectrum. Why is that? I'm not mistake by saying that this:

29B299
B22929
000CFF
FBFF00
35AD4D
1EDADF

Is one frame of 6 pixels right? So my first pattern should display these pixels.

when I modify the patterns file by adding 6 different colors:

How are you changing this file?

they're always in the blue spectrum.

The blue numbers are much bigger than the other ones.

Ok so I went to the electronics store, they didn't have any Arduino Mega, only a "replica" which the guy said work great. Regardless of what he said I didn't have time to buy one online, so I got this one, and my SD shield does not seem to work with this one. It keeps telling me that the SD initialization failed. One time it detected the card, but said not FAT partition was found. It works great with the Arduino.

The Arduino Mega 2560 replica characteristics are the exact same, what am I doing wrong?

I am using the example sketch from the SD library:

I am guessing this is due to shitty hardware, could be wrong.

// include the SD library:
#include <SPI.h>
#include <SD.h>

// set up variables using the SD utility library functions:
Sd2Card card;
SdVolume volume;
SdFile root;

// change this to match your SD shield or module;
// Arduino Ethernet shield: pin 4
// Adafruit SD shields and modules: pin 10
// Sparkfun SD shield: pin 8
// MKRZero SD: SDCARD_SS_PIN
const int chipSelect = 4;

void setup() {
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }


  Serial.print("\nInitializing SD card...");

  // we'll use the initialization code from the utility libraries
  // since we're just testing if the card is working!
  if (!card.init(SPI_HALF_SPEED, chipSelect)) {
    Serial.println("initialization failed. Things to check:");
    Serial.println("* is a card inserted?");
    Serial.println("* is your wiring correct?");
    Serial.println("* did you change the chipSelect pin to match your shield or module?");
    return;
  } else {
    Serial.println("Wiring is correct and a card is present.");
  }

  // print the type of card
  Serial.print("\nCard type: ");
  switch (card.type()) {
    case SD_CARD_TYPE_SD1:
      Serial.println("SD1");
      break;
    case SD_CARD_TYPE_SD2:
      Serial.println("SD2");
      break;
    case SD_CARD_TYPE_SDHC:
      Serial.println("SDHC");
      break;
    default:
      Serial.println("Unknown");
  }

  // Now we will try to open the 'volume'/'partition' - it should be FAT16 or FAT32
  if (!volume.init(card)) {
    Serial.println("Could not find FAT16/FAT32 partition.\nMake sure you've formatted the card");
    return;
  }


  // print the type and size of the first FAT-type volume
  uint32_t volumesize;
  Serial.print("\nVolume type is FAT");
  Serial.println(volume.fatType(), DEC);
  Serial.println();

  volumesize = volume.blocksPerCluster();    // clusters are collections of blocks
  volumesize *= volume.clusterCount();       // we'll have a lot of clusters
  volumesize *= 512;                            // SD card blocks are always 512 bytes
  Serial.print("Volume size (bytes): ");
  Serial.println(volumesize);
  Serial.print("Volume size (Kbytes): ");
  volumesize /= 1024;
  Serial.println(volumesize);
  Serial.print("Volume size (Mbytes): ");
  volumesize /= 1024;
  Serial.println(volumesize);


  Serial.println("\nFiles found on the card (name, date and size in bytes): ");
  root.openRoot(volume);

  // list all files in the card with date and size
  root.ls(LS_R | LS_DATE | LS_SIZE);
}


void loop(void) {

}

EDIT: CORRECTION. My Arduino is also returning an initialization error now. What the hell happened I didn't change anything? Is it possible that the Mega replica messed with the shield?

EDIT 2: CORRECTION. It is working on the Uno, I got the pins wrong. But it is definitely not working on the Mega replica.

The mega has different pins for the SPI bus than the Arduino. In fact these lines are not on the normal pins but on the header pins. Do a search for the exact details.

I get this once in a while:

Initializing SD card...Wiring is correct and a card is present.

Card type: SD1
Could not find FAT16/FAT32 partition.
Make sure you've formatted the card

But most of the time just could not initialized. How come?

Because the error messages assume you have an SD card connected to the SPI pins. You have not, they are floating pins so they can read back as anything. Hence the error messages make no sense.

I checked online, here is what I found:

MISO on pin 51
MOSI on pin 50
CLK on pin 52
CS on pin 53

I rewired this way, and it does not change anything. I still get card detected but no FAT partition once in 10 times or so.

Because the error messages assume you have an SD card connected to the SPI pins. You have not, they are floating pins so they can read back as anything.

Thanks for your help again. How do I fix this?

Have you changed the software so that the CS pin is pin 53?

I have changed the chipSelect variable.

I found this, but when I try these lines of code I get an error. I guess the library doesn't support that anymore.

Well the code as I posted works on my Mega by just changing the SD.begin(4) to SD.begin(53) and rewiring it:-

SPI Uno Mega
SS 10 53
MOSI 11 51
MISO 12 50
SCK 13 52

It also works when I set the number of pixels to 400.

Ok it is now working, however I dot understand why when I change your test.PAT to my hex colors it doesn't change anything.

As I said before, how are you changing it and how are you checking it?

I insert the micro SD into my computer slot through an adapter, I modify the contents of the file as follows, for instance:

29B299
B22929
000CFF
FBFF00
35AD4D
1EDADF

I save, I insert the micro sd into the arduino shield, and it doesn't change the led values. Just blue.