Hi,
I am using Arduino Mega 2560.
I am trying to approach the SD card for reading a text file that stores >10^6 lines of 2 or 3 digits strings (e.g. 125\n 145\n 200\n... 170\n 99\n 3n 145\n...) .
The strings indicates the brightness level of the LEDs strip.
I would like to control the brightness in accordance with the data in the SD card, at a frequency of 8K [Hz], i.e. every 125 microseconds I need to read the SD card, and adjust the LEDs brightness accordingly (and then read the SD card again, and play the LED again).
Is there any way to accomplish these requirements?
Do you already have a suitable SD card adapter/breakout?
I’d suggest that it would be best not to read the SD card as frequently as you update your LED outputs, i.e. just read in much larger batches.
Also, how many outputs do you need to update for your LED strip? How will you connect to it?
Sounds like an interesting project - I’m just trying to imagine why you’d want to update LEDs at such a high frequency
EDIT: actually, scrap what I said about reading in a large buffer. Looking at the SD Arduino library, its read() function just reads a byte at a time, so maybe it would be best to do what you said and read until you get the new line character (or the number of LED values you need per cycle), then update the output.
I’m still not clear how many LEDs you need to update. How many values do you need to read in each 125 microsecond cycle?
Hello
May you might make within the sketch setup() a copy of the contents of the SD card to an additional either FRAM or EEPROM memory shield. I guess the read timing would be much better.
Is each line in the file a single integer? If so, do not store the data in the file as ASCII characters, store it as binary data, two bytes if you need an int, one if an 8-bit unsigned int is sufficient (value is limited to 0 through 255), that will allow for much faster data transfer per value, and eliminates the ASCII to integer conversion.
The process is: read the number from the SD card, turn it into an integer, set the LEDs' strip brightness to the integer level (any number between 0 and 255), turn on the LEDs in the strip.
I need to do all that in 125microseconds (actually, even faster, as in certain point, I will have to add some audio capabilities. But let's put this aside for now).
Any ideas? how can I improve the SD card data reading?
How fast is your read speed with your current method? If you haven't tried yet, maybe you could do what @wildbill suggested.
I'm sure you're aware that the human eye can resolve something much less than 100 changes per second (more like 30 to 60). Would it be worth considering implementing something like an averaging filter and just updating the LEDs more like 24 times a second, if the intention is for it to be viewed by humans?
And, since you have 60 LEDs, do you want to update them all together, or do you want to update each one individually? Something like shifting each value along the strip each time you read a new value?
Do you even have time to strip.show the number of LEDs you pan on? At that rate?
Neopixels require that the entire strip on a single pin be totally told along what to do, there is no changing a particular one w/o making it necessary to set them all.
You could use multiple strips and logic to dicide which one needs updating, still you might not have time to do that.
So I would see if you can do anything with the pixels at that rate, and if
Since AFAIK brain waves are very low frequency I am yet unconvinced you need 8 kHz. Maybe for the big doctors to get a ridiculously faithful digital representation they can study or analyze, not for pretty lights meant for human consumption.
In any case that's overkill as far as human response is concerned as has been noted.
You could somehow reduce the data as it seems vastly over sampled.
Still wondering.
Oh, and how many LEDs in total?
Wait wait wait, are you saying that the entire strip is one color and you are changing the brightness of all of them identically?
Each neopixel needs 24 bits of data, sent at a rate of 800,000 bits/second. At an 8KHz update rate, you could do a maximum of 4 LEDs, during which time the arduino can do nothing else. Also note that neopixels use PWM (pulse width modulation) to control the brightness, at a frequency much lower than your sample rate.
You may get the desired rate using a strip of RGB LEDs, but that would restrict you to a single color for the entire strip.
Thank you david_2018, alto777, and R11K.
Few answers first:
I tested my read speed - it is 2.236 milliseconds for reading a single character.
I am currently using a single strip of 60x LEDs.
The entire strip is one color (Red) - I read a number at a time (numbers range 0 to 255) , from the txt file. the number indicate the strip's brightness (from no light, to very bright red).
The 8K Hz sampling is an overkill. I will probably reduce it in the future, but at the moment I would like to use the data as is. Therefore I would like to focus on how to decrease the SD-card reading time and turning on the LEDs strip.
Questions:
alto777 mentioned that the smart LEDs (e.g. Neopixel) are a bad choice. Eventually, I will need an Near-Infra-Red (NIR) LED. Do you have other recommended LED? NIR LED?
The original data is stored in a WAV file. I turned (pre-processing, i.e. by Python and not by the Arduino) it into a .txt file (ASCIIs) - do you think that I better read the original WAV file (by Arduino) instead of the .txt file? (from memory-reading pace perspective)
Since you have control over the pre-processing code, and the values are limited to 0-255, save the data as an 8-bit unsigned int, that way you only need to read one byte per sample instead of the two to four characters per sample using ASCII.
This will be impossible with addressable LEDs (neopixel is Adafruit's branding), just updating 60 LEDs takes 1.8mS. If you used a buffer chip and wired the LEDs as sixty strips of one LED each that would take 30uS to update, but would be a nightmare to wire. There is a variety of addressable LED that uses SPI and is faster, but all the addressable LEDs that I know of use a form of PWM to control brightness, so will not be suitable for your application - the LED is not dimmed by reducing the voltage across it, but by rapidly switching the voltage on and off, at a rate of around 400Hz for the common ws2812. Any affect you are looking for from varying the brightness at an 8KHz rate will be interfered with by the underlying variable-width 400Hz frequency, and you will be trying to change the PWM pulse width twenty times per cycle.
What is the lowest frequency from the WAV file? Since you have an audio shield the simplest method would be to use the audio output to drive a suitable amplifier that has an analog LED as its load, although you may need to make some adjustments to the audio to compensate for the non-linear characteristics of the LED.
Thanks. few comments/questions (might worth another thread):
SD card reading time: When using a binary file instead of the text file I initially had, I manage to reduce a single-byte reading time to 36 microseconds (!). I can add the code if this is of interest to anyone, is it?)
I intend to look for a non-addressable LEDs, as all LEDs should have the same brightness (and all are RED, and preferably Near Infra Red).
I understand that the 490Hz PWM limits the LED brightness cycle to ~2 [ms] cycle. Also I noticed that there are two pins on the MEGA (4 and 13) that allows 980Hz PWM. The problem that these specific two pins are used by the adafruit music maker. Any idea how to bypass this issue?
Also, I intend to reduce the initial (pre-processing) sampling rate by an order of magnitude (to 800Hz or even 400Hz) in order to leave me time for flashing the LEDs and play the sound frequencies.
Thank you all
Do a reality test, read the ENTIRE file and pick the longest time to read a single byte. Your current speed will go to hell when a new 512 byte block needs to be physically read from the SD card.
Paul
I save the time (used micros()) before and after reading each byte and printed to the screen. It consistently printed 36 (and rarely 40) microseconds.
Am I missing something?
Here is the relevant part of the code:
while (myFile.available()) {
time1 = micros();
number = myFile.read();
time2 = micros();
time_laps1 = (time2 - time1);