arduino-libraries / sd Goto Github PK
View Code? Open in Web Editor NEWSD Library for Arduino
Home Page: http://arduino.cc/
License: GNU General Public License v3.0
SD Library for Arduino
Home Page: http://arduino.cc/
License: GNU General Public License v3.0
I was looking for a way to access the last access, creation and read time for a file.
It would be useful to do a few things:
Test platform: Arduino M0 Pro
I try to use the seek() function to move the write pointer to the head of a file, it didn't work. Then I change the version to 1.2.0, and it works with the same code.
There is a typo in a message printed by Serial.print() when the SD card fails to initialize that can misguide new users.
Thanks @per1234, for giving accurate information.
the sketch is restarted whenever the serial monitor is opened
This is only true for the Arduino boards that use an external USB to serial adapter chip that uses the DTR trick you mentioned. It is not true when using a native USB board (e.g., Leonardo, MKR, Nano 33 IoT, Nano 33 BLE). The serial connection with Serial Monitor is also lost when those boards are reset, so you do need to both a reset and a Serial Monitor restart to get the example sketches to start again and show serial output.
At the time those instructions were written, it's likely all Arduino boards had the reset on Serial Monitor open behavior, so they were correct at that time. Most of Arduino's new boards now have native USB, so the existing instructions become even more outdated over time.
Credits: @per1234
SD/examples/ReadWrite/ReadWrite.ino
Line 41 in 0a0aaeb
if (!SD.begin(4)) {
Serial.println("initialization failed. Things to check:");
Serial.println("1. is a card inserted?");
Serial.println("2. is your wiring correct?");
Serial.println("3. did you change the chipSelect pin to match your shield or module?");
Serial.println("Note: press reset or reopen this serial monitor after fixing your issue!");
while (1);
}
It should be Press reset button and reopen serial monitor after fixing your issue.
Also, this message can be added to other examples as well.
Thank you.
The Leonardo and Mega use different hardware SPI pins which make them incompatible with the SD library when using the Datalogger shield.
From @maxcpr on August 18, 2015 18:2
a little bit changed example from IDE (SD listfiles), file listing moved to "loop".
Code stops listing microSD card after 17-20 loops (arduino nano).
(there is similar code, also listing files on microsd, that works fine on the same hardware)
/*
Listfiles
This example shows how print out the files in a
directory on a SD card
The circuit:
* SD card attached to SPI bus as follows:
** MOSI - pin 11
** MISO - pin 12
** CLK - pin 13
** CS - pin 4
created Nov 2010
by David A. Mellis
modified 9 Apr 2012
by Tom Igoe
modified 2 Feb 2014
by Scott Fitzgerald
This example code is in the public domain.
*/
#include <SPI.h>
#include <SD.h>
File root;
void setup()
{
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only
}
Serial.print("Initializing SD card...");
digitalWrite(10, 1); // turn the LED on (HIGH is the voltage level)
digitalWrite(4, 0); // turn the LED on (HIGH is the voltage level)
delay(2000);
while (!SD.begin(4)) {
Serial.println("initialization failed!");
delay(2000);
// return;
}
Serial.println("initialization done.");
}
void loop(){
Serial.println("starting!");
root = SD.open("/");
printDirectory(root, 0);
Serial.println("done!");
delay(2000);
pinMode(10, OUTPUT);
pinMode(4, OUTPUT);
digitalWrite(10, 1); // turn the LED on (HIGH is the voltage level)
digitalWrite(4, 0); // turn the LED on (HIGH is the voltage level)
}
void printDirectory(File dir, int numTabs) {
while(true) {
File entry = dir.openNextFile();
if (! entry) {
// no more files
break;
}
for (uint8_t i=0; i<numTabs; i++) {
Serial.print('\t');
}
Serial.print(entry.name());
if (entry.isDirectory()) {
Serial.println("/");
printDirectory(entry, numTabs+1);
} else {
// files have sizes, directories do not
Serial.print("\t\t");
Serial.println(entry.size(), DEC);
}
entry.close();
}
}
Copied from original issue: arduino/Arduino#3696
There seems to be no direct way to rename a file using the File object in SD.h. Copying a file is the only other costly hack to do this. This is not desirable.
When I add digitalButtons()
, Uno works incorrectly.
void readPushButtons(){
uiStep();
analogButtons();
logicAnalogButtons();
digitalButtons();
//logicDigitalButtons();
spindleSpeedSetting();
}
void initialButtons(){
pinMode(stepPin, INPUT_PULLUP); ///set the pin with internal pullup resistor
pinMode(feedPin, INPUT_PULLUP); ///set the pin with internal pullup resistor
}
void digitalButtons(){
stepState = digitalRead(stepPin); ///record pin state
feedState = digitalRead(feedPin); ///record pin state
}
When I delete digitalButtons()
, correctly.
void readPushButtons(){
uiStep();
analogButtons();
logicAnalogButtons();
//digitalButtons();
//logicDigitalButtons();
spindleSpeedSetting();
}
From @cmaglie on November 15, 2012 19:5
This is Issue 1103 moved from a Google Code project.
Added by 2012-11-07T18:50:46.000Z by [email protected].
Please review that bug for more context and additional comments, but update this bug.
Original labels: Type-Defect, Priority-Medium
What steps will reproduce the problem?
What is the expected output? What do you see instead?
The expected output would be to have the SD card re-initialize itself. Instead, the second initialization fails.
I have tracked the failure cause to SDFile.openRoot method that return failure if the root had been already opened.
What version of the Arduino software are you using? On what operating
system? Which Arduino board are you using?
Arduino IDE 1.0.1
Mac OS X
Custom board
Please provide any additional information below.
A fix can be implemented, for example by calling a method that resets the state of the SDClass object in the initialization routine, making sure we start from a blank state.
I am willing to implement the fix, but just want to make sure I implement it the way people would like it.
Copied from original issue: arduino/Arduino#1103
From @cmaglie on November 15, 2012 18:34
This is Issue 465 moved from a Google Code project.
Added by 2011-01-21T14:26:04.000Z by [email protected].
Please review that bug for more context and additional comments, but update this bug.
Original labels: Type-Defect, Priority-Medium
I am using the new SD wrapper library and find it very simple and useful.
But the following issues make it unusable in some case:
Let's assume someone needs to remove the SD card from the socket (or disables the power to it when system can go idle) and put the same or another card back to the socket while the system is running, the following problems occur:
it seems that the SD object holds a copy of the FAT because
SD.exists(someFile) returns true even if there is no SDCard in the socket or
another one (where this file does NOT exist) is put in. I guess this copy of the FAT won't be refreshed again after SD.begin().
you can not re-initialize the SD-object again. This would be
necessary (for some SPI magic I guess) if you remove the SDCard from the socket and put it back later. There is no SD.close() or something and calling SD.begin() a second time will always return FALSE and not initialize the SD again.
Issue 1 and 2 could be solved by adding a destructor or a function to
re-initialize the SD object.
Copied from original issue: arduino/Arduino#465
Hello,
Any example in library is taking almost 50% global variable memory.
As I am using many other library, I want to reduce the global variable memory of sd library.
I am using few function like, file open, file write, file read and file close so other functions are useless for me.
How can reduce the global variable memory by removing the other global variables???
this fix
#31
https://forum.arduino.cc/index.php?topic=515050.0
actually produce a bug, that every one user of arudino IDE is receiving notification after IDE start that update is available for SD library, but there is nothing to update. SD library is also always under Updateable libraries. Please revert and find a different way.
From @ghost on July 16, 2014 14:17
The SD wrapper does not expose any functions for setting and getting file attributes, creation date and modification date.
Copied from original issue: arduino/Arduino#2184
availableForWrite()
functionContext: I am trying to hunt a bug, similar to #11 - working with older Arduino IDE, I know ;) but going deseperately through SD library's code I found cause for many subtle bugs.
Consider code like this:
void doSomething(File f) {
// does something nice.
f.close();
}
void func() {
File myFile = ....; // obtain a file somehow
doSomething(myFile);
myFile.close();
}
On "normal" File, close()
is idempotent (as expected), so doing close() multiple times is OK and 2nd+ calls do nothing. There seems to be no copy constructor in File
, so when passing by-value to doSomething
, the compiler generates (!) one that copies the fields - that is the _file
pointer becomes shared between myFile
and f
locals.
First close
will deallocate the (shared) _file
pointer and zeroes the pts. The 2nd close
will deallocate the same pointer value again.
This reduced example may seem bad, as the programmer should not do permature close - but lack of the copy/destroy semantics severely limits structuring the code since passing File
values around easily leads to memory corruption. At this time, the only value safe to assign to other variables is File()
.
I would also recommmend to reconsider the decision for #2; while it is true, that the current implementation is simple, it requires extreme caution when passing around File
variables. I'd recommend to have full copy+move constructor semantics.
If unwanted, I'd recommend to disallow generation by the compiler, so the user is warned:
File(const File&) = delete;
library.properties states architectures=* which makes my Arduino IDE choose it over the SD lib included in the esp8266 board package.
This would not be a problem, if Sd2PinMap.h did not contain
#error Architecture or board not supported.
which breaks my build. So I guess the architectures declaration should be more specific.
From @stg on March 25, 2013 14:35
I would like to see a SeekableStream class going between the File class (SD library) and the Stream class (or by adding the seek, position, size functions to the Stream object directly).
This would allow access to arbitrary (SD or other media) seekable streams without the user including the (large) SD library for projects that do not have an SD card reader, while still maintaining full compatibility with the SD card library.
For example, the HypotheticMusicPlayer class could play music from the SD card in a larger project, or from flash-rom in a smaller project via a class that subclasses SeekableStream and accesses PROGMEM data - without needing to include the SD library, which may not even fit on a smaller device.
This would also make it easier to provide standardised file access to other media, where including the SD card library makes no sense.
Copied from original issue: arduino/Arduino#1330
My SD card (4G by Transcend) consumes ~20 mA in idle state between transfers. Author of SdFat library wrote some years ago about this:
'I understand the problem. You are using SD.h and it has a bug that doesn't allow the SD to sleep.
SD.h has not added bug fixes from SdFat for about three years and the Adruino developers have added their own bugs. I tried SD.h with my tests and found cards pulled from 15 to 28 ma when idle.'
(http://forum.arduino.cc/index.php?topic=149504.msg1124464#msg1124464)
After conversion my code from SD to latest SdFat library power consumption in idle state became normal.
From @cmaglie on November 15, 2012 18:50
This is Issue 796 moved from a Google Code project.
Added by 2012-01-17T22:33:27.000Z by [email protected].
Please review that bug for more context and additional comments, but update this bug.
Original labels: Type-Defect, Priority-Medium
What steps will reproduce the problem?
What is the expected output? What do you see instead?
The demo should work from cold start, but the SDcode hangs internally after supplying one file.
However If a warm start (press reset button on mega) is issued then there is no problem.
There is also no problem if you 'upload' a file to the SDcard before downloading a file, then it functions correctly after a cold start.
What version of the Arduino software are you using? On what operating
system? Which Arduino board are you using?
1.0IDE OSX mega V2
Please provide any additional information below.
The SD and ethernet libraries need to be cleaner, leaving the SPI state 'clean' after exiting and not assuming they are the sole owners, the SDcode should also NOT be disabling system interrupts whilst it is performing actions.
Copied from original issue: arduino/Arduino#796
how to change the SD buffer size?
Command: File file = SD.open(target, FILE_WRITE);
How it looked like (version 1.1.1):
Reading file "/logs/log3.txt":
[26.11.17][12:59:03][4893] S: GSM: ready without restart
[26.11.17][12:59:08][9526] I: GSM: IP: "100.90.60.208"
[26.11.17][12:59:17][18051] S: RTC: synced
[26.11.17][12:59:17][18077] Boot successful
Done!
How it looks like (version 1.2.0),
it always write to first line:
Reading file "/logs/log0.txt":
[01.01.04][00:47:39][60621] Boot successful
86.142.157"
Done!
Reading file "/logs/log1.txt":
[01.01.04][00:52:55][32144] I: GSM: IP: "100.90.60.208"
Done!
Reading file "/logs/log2.txt":
[26.11.17][12:40:57][18082] Boot successful
0.60.208"
Done!
This old pull request should be applied here, if anyone cares to fix this long-standing bug.
From @q2dg on June 27, 2015 0:4
Some parts of official Arduino SD library (https://github.com/arduino/Arduino/tree/master/libraries/SD/src) are based in an old version of Greiman's one (https://github.com/greiman/SdFat). The newest versions of the latter has some interesting improvements, as support to long file names, use of multiple cards, etc. I think it could be worthy to valorate if these changes could be merged.
Thanks.
Copied from original issue: arduino/Arduino#3428
https://www.arduino.cc/en/Reference/FileRead states that the read
method returns a character or -1. That however only applies to ::read()
. read(buffer, len)
returns the number of bytes read or -1 on error.
From SDFile.cpp
//------------------------------------------------------------------------------
/**
* Read data from a file starting at the current position.
*
* \param[out] buf Pointer to the location that will receive the data.
*
* \param[in] nbyte Maximum number of bytes to read.
*
* \return For success read() returns the number of bytes read.
* A value less than \a nbyte, including zero, will be returned
* if end of file is reached.
* If an error occurs, read() returns -1. Possible errors include
* read() called before a file has been opened, corrupt file system
* or an I/O error occurred.
*/
int16_t SdFile::read(void* buf, uint16_t nbyte) {
uint8_t* dst = reinterpret_cast<uint8_t*>(buf);
From @cjdg on December 18, 2016 18:34
Hi i been testing many sdcards and i saw a small isue, when i format them as fat32 cannot initialize them, but if i make a fat16 volume all of them work well
Copied from original issue: arduino/Arduino#5736
From @matthijskooijman on November 14, 2014 10:49
Initializing the volume and running the CardInfo example works fine, but reading files does not work. Instead of the actual file contents, I get some random garble (mostly spaces) of the correct length. I tried this using the DumpFile example.
I suspect that the block lookup for FAT16 might be wrong. Looking at this piece of code, I can't imagine that being correct.
Copied from original issue: arduino/Arduino#2443
Is there an ETA on version 1.2.0? I really need #38
While developing a sketch, I was really low on memory and started investigating on which element were taking space. I noticed Serial was being pulled in the final elf even without using it at all.
It appear the SDFile.cpp file contains functions which are embedding Serial.println calls.
Is it possible to add a define which will exclude all print* function and hence reduce memory consumption ?
Thanks
PROBLEM:
with 2 devices on the SPI bus, the SD card library fails when calling the begin() function
the problem is that the library is not prepared to work with other SPI devices, it assumes you only have the SD card basically
SOLUTION:
in the file named SD.cpp, in function begin() (line 345) add this instruction before the return statement:
if(root.isOpen()) root.close();
that should do it.
You should add some #define
to turn on and off the features in the library, so people can remove the features that they don't want so they can have a smaller size of the code.
Hello
Any plan to do it for any Arduino board ?
It is very usefull for any data recorder...
Br
Jp
In Sd2Card.cpp there are a few places where a timeout function is implemented. However, in each of these places the value returend by millis() is truncated to 16 bits. That can't be correct.
SD library seems to have been changed to GPL when it was pointed out that William Greiman's SdFat library was GPL in Apr 2015. arduino/Arduino#2936
In the meantime, in Oct 2017, William Greiman's library was changed to MIT License. greiman/SdFat@e4190e5 and greiman/SdFat@f2424ef
As far as I know, for "the stated INTENT of the arduino folk to allow proprietary software trumps", this library is supposed to be LGPL, since it is not mandatory to keep it GPL anymore. https://forum.arduino.cc/index.php?topic=199627.0 (Sorry for not having clearer source. Correct me if I'm wrong.)
From @cmaglie on November 15, 2012 18:54
This is Issue 885 moved from a Google Code project.
Added by 2012-04-13T15:30:18.000Z by [email protected].
Please review that bug for more context and additional comments, but update this bug.
Original labels: Type-Defect, Priority-Medium
What steps will reproduce the problem?
core.a(new.cpp.o): In function `__cxa_pure_virtual':
/Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/cores/arduino/new.cpp:17: multiple definition of`__cxa_pure_virtual'
SdFat/SdFat.cpp.o:/Users/usename/Documents/Arduino/libraries/SdFat/SdFat.cpp:62: first defined here
/Applications/Arduino.app/Contents/Resources/Java/hardware/tools/avr/bin/../lib/gcc/avr/4.3.2/../../../../avr/bin/ld: Disabling relaxation: it will not work with multiple definitions
sdfatlib20111205 and SdFatBeta20120327
Mac OS X
Copied from original issue: arduino/Arduino#885
I'm stumped regarding why my new Maixduino board won't initialize the SD card with the command "SD.begin(29)". It has this problem for any of the SD(k210) library examples that use this command. I've tried SD cards ranging from 2GB to 32GB and they all fail. I've tried both the SD formatting utility in Windows and the SD Card Formatter program recommended in the forums. I've tried formatting in both FAT 32 and FAT 16. Nothing works.
However, it does initialize fine with the example "Cardinfo" and running this sketch shows all the correct info about the SD card. I see that this sketch does not use SD.begin(), but uses more basic commands from the utility libraries such as "card.init(SPI_HALF_SPEED, chipSelect" where chipSelect = 29 (for the Maixduino board).
Does anyone have any idea or theory why this board fails to initialize the SD card using the SD.begin() command? Thanks!
See https://github.com/ARMmbed/littlefs
Another option is SpifFs https://github.com/pellepl/spiffs but it seems not so maintained
Thanks
From @hammadtq on April 9, 2015 10:31
SD.remove
works fine in the start but would stop functioning on itself, if I give a new file name, it will work perfectly fine again while leaving the old file as it is, the last file I encountered problem was of the 4086 bytes. The issue is very random, such as it will perfectly fine for a few days and then will give problem with one of the files.
I couldn't reproduce the condition under which it would start doing this, however, I tried to debug and trace the issue, here is what I found in SDVolume.cpp
in the method of
uint8_t SdVolume::freeChain(uint32_t cluster)
do {
uint32_t next;
if (!fatGet(cluster, &next)) return false;
// free cluster
if (!fatPut(cluster, 0)) return false;
cluster = next;
} while (!isEOC(cluster));
I noticed that next has a defined value when the first cluster is called such as maybe: 3911516415
However, when it gets through fatGet and fatPut, if we print the next value just before cluster=next, it appears to be 0, making the while to break and false to return on next loop iteration.
What I did to resolve is simple, I just saved the value of next in a new variable 'newnext' before going to fatGet and then assigned that 'newnext' to cluster at the end, this resolved the issue at once and file was deleted.
do {
uint32_t next;
uint32_t newnext = next;
if (!fatGet(cluster, &next)) return false;
// free cluster
if (!fatPut(cluster, 0)) return false;
cluster = newnext;
} while (!isEOC(cluster));
I hope this will help in finding and fixing the issue correctly.
Copied from original issue: arduino/Arduino#2946
Why this library isn't useable for new processors such SAMD21 Cortex-M0+? If I include this library the compiler get an error: The Sd2PinMap.h contains no entrys for this Controller. I did expect, that all new boards, which are add with the board manager, could used with all librarys in the standard IDE, such SD library. Is there any idea how i can use an MKR1000 board with the SD library?
In file included from D:\Arduino\libraries\SD/utility/Sd2Card.h:26:0,
from D:\Arduino\libraries\SD/utility/SdFat.h:27,
from D:\Arduino\libraries\SD/SD.h:20,
from D:\Arduino\Sketches\gpsLogger3\gpsLogger3.ino:6:
D:\Arduino\libraries\SD/utility/Sd2PinMap.h:284:5: error: 'DDRD' was not declared in this scope
From @cmaglie on November 15, 2012 18:55
This is Issue 904 moved from a Google Code project.
Added by 2012-04-29T23:57:46.000Z by [email protected].
Please review that bug for more context and additional comments, but update this bug.
Original labels: Type-Defect, Priority-Medium, Component-Core, Component-SD, Milestone-1.0.2
What steps will reproduce the problem?
Method A:
Method B:
What version of the Arduino software are you using? On what operating
system? Which Arduino board are you using?
Arduino 1.0
Windows 7 x64 Ultimate
Arduino Uno SMD + Ethernet Shield R3
Kingston 1GB MicroSD Card in Ethernet Shield
Please provide any additional information below.
Sample code and sample output attached.
Copied from original issue: arduino/Arduino#904
From @karplus on December 31, 2012 2:39
I tried reading a 32Gbyte card with CardInfo, and got a ludicrous result for the size. The problem is that a 32-bit number can't hold the number of bytes on the card.
Replacing the bytes and kbytes printing with the following code fixed the problem, though only for cards up to a Terabyte:
if (volumesize < (1<<(32-9)))
{ uint32_t num_bytes = volumesize * 512; // SD card blocks are always 512 bytes
Serial.print("Volume size (bytes) : ");
Serial.println(num_bytes);
}
Serial.print("Volume size (Kbytes): ");
volumesize /= 2;
Serial.println(volumesize);
Copied from original issue: arduino/Arduino#1194
Hi, using the default CardInfo sketch causes the SD card to be corrupted if power to the Arduino stops. I have resolves this issues on my end by adding:
"root.close();"
to the end of the setup(); function to ensure that the sd card is fully closed, and ready to be ejected.
From @cmaglie on November 15, 2012 18:48
This is Issue 740 moved from a Google Code project.
Added by 2011-12-05T23:57:52.000Z by [email protected].
Please review that bug for more context and additional comments, but update this bug.
Original labels: Type-Defect, Priority-Medium
I had some problems with repeated initialization of SD cards with Arduino 1.0 (so I can remove them from the Arduino to retrieve the information on them). It would just stop writing to the card after a while. (before writing I initialized the SD card, but somehow this wouldn't work every time)
I got it working by using the latest version of SDFATlib, on which the current SD lib is based I think (a much older version).
The current SD lib works by providing a higher level interface for the old version of the SDFATlib.
With newer versions this is not needed anymore because a higher level interface is included in the SDFATlib itself.
Why don't you integrate this newer library, it also comes with good support for multiple SD cards and more features! :)
You can find the latest (Arduino 1.0 compatible) version on http://code.google.com/p/beta-lib/downloads/list
Copied from original issue: arduino/Arduino#740
From @mcaldwelva on November 9, 2015 23:5
This line of code is overly restrictive:
if (i > n || c < 0X21 || c > 0X7E)return false;
Windows will use extended ASCII in short file names if they are present in the long file name. Based on the Wikipedia entry for FAT 8.3 file naming, something like this seems more appropriate:
if (i > n || c < 0x20 || c == 0x7F) return false;
I hope you will consider making a change along these lines in the future. Thanks!
Copied from original issue: arduino/Arduino#4121
From @blowback on January 17, 2013 13:20
If I take the listfiles.ino example and change the chip select to 4, I can get a directory listing of the contents of my SD card, as expected.
If I modify the code by adding SD.exists("foo);' immediately before the 'root = SD.open("/");' then printDirectory() no longer works - specifically, the first call to dir.openNextFile() fails.
If I move the SD.exists() line to after the SD.open("/") line, then it works again.
I tried wrapping the SD.exists() with its own SD.open().....root.close(), but that caused the directory listing to fail again.
It doesn't matter if the file tested for actually exists or not, the behaviour is the same in both cases (and SD.exists() returns the right result).
Here's the code:
/*
SD card basic file example
This example shows how to create and destroy an SD card file
The circuit:
* SD card attached to SPI bus as follows:
** MOSI - pin 11
** MISO - pin 12
** CLK - pin 13
** CS - pin 4
created Nov 2010
by David A. Mellis
modified 9 Apr 2012
by Tom Igoe
This example code is in the public domain.
*/
#include <SD.h>
void printDirectory(File dir, int numTabs);
File root;
void setup()
{
delay(5000);
// Open serial communications and wait for port to open:
Serial.begin(57600);
while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only
}
Serial.print("Initializing SD card...");
// On the Ethernet Shield, CS is pin 4. It's set as an output by default.
// Note that even if it's not used as the CS pin, the hardware SS pin
// (10 on most Arduino boards, 53 on the Mega) must be left as an output
// or the SD library functions will not work.
pinMode(10, OUTPUT);
if (!SD.begin(4)) {
Serial.println("initialization failed!");
return;
}
Serial.println("initialization done.");
/* ADDED CODE: this SD.exists() call will cause the dir.openNextFile()
* call in printDirectory() to fail, regardless of whether the file
* actually exists or not.
*/
if(SD.exists("META.DAT"))
{
Serial.println("EXISTS");
}
else
{
Serial.println("DOESN'T EXIST");
}
/* END ADDED CODE
*/
root = SD.open("/");
/* ADDITIONAL: if we do our SD.exists() check here, after the SD.open("/"),
* then it all works again.
* HOWEVER id we wrap our SD.exists() with its own SD.open() and root.close(),
* it goes back to being broken!
*/
if(root)
{
Serial.println("root opened");
printDirectory(root, 0);
}
else
{
Serial.println("failed to open root");
}
Serial.println("done!");
}
void loop()
{
// nothing happens after setup finishes.
}
void printDirectory(File dir, int numTabs) {
while(true) {
File entry = dir.openNextFile();
if (! entry) {
// no more files
Serial.println("openNextFile failed");
break;
}
for (uint8_t i=0; i<numTabs; i++) {
Serial.print('\t');
}
Serial.print(entry.name());
if (entry.isDirectory()) {
Serial.println("/");
printDirectory(entry, numTabs+1);
} else {
// files have sizes, directories do not
Serial.print("\t\t");
Serial.println(entry.size(), DEC);
}
}
}
Copied from original issue: arduino/Arduino#1232
Hello,
I am aware that this is not an issue, but I would like to know if reading a file encoded in UTF-8 would work, and what format I should save the resulting text in.
For example, if I had a text file full of fixed width columns like so:
1/你好 /hello \n
with 24 bytes per line,
how can I read the file so that I can save the Unicode characters, preferably as a char* array?
I apologise if this is seemingly simple, but I could not find any sources for reading UTF-8 from an SD card.
Many thanks
From @basti2k on May 4, 2016 14:20
In the File-Class of the SD-Library would been allocated memory with "malloc", but the Class hasn't a destructor to release the allocated memory.
Copied from original issue: arduino/Arduino#4922
From @kylemaes on December 9, 2012 23:56
Any time I use the Ethernet shield and include the SD library my Ethernet doesn't function and the Arduino reboots randomly and does weird things. The SD card can be written to and I have not yet tested reading with the Ethernet on, but the Ethernet once again refuses to function properly (when #include <SD.h> is in the code)...
Copied from original issue: arduino/Arduino#1159
From @nemeier on August 1, 2015 10:26
In some of my Projects I need to change the SD card. There is a simple allow this. I just require a single line in the SD.c library.
boolean SDClass::begin(uint8_t csPin) {
/*
Performs the initialisation required by the sdfatlib library.
Return true if initialization succeeds, false otherwise.
*/
// ----> Line Added
if (root.isOpen()) root.close(); // allows repeated calls
// <--- Line Added
return card.init(SPI_HALF_SPEED, csPin) &&
volume.init(card) &&
root.openRoot(volume);
}
After changing the SD card all you need is to reinitialize the sd card.
Will properly solve ISSUE #1103
Copied from original issue: arduino/Arduino#3607
I think there is i some mistake in exaple ReadWrite. In code below is pointless while loop which burdens CPU. I'll change if for while and "while(1);" remove
if (!SD.begin(4)) { Serial.println("initialization failed!"); while (1); }
Using information from here and here I am having difficulty setting my UHS-1, Type 2 cards into high voltage mode.
Presumably, this step should be accomplished when sending 0x40000000 during ACMD41, but that does not seem to be the case. In fact, according to the SD protocol, the upper 8 bits are ignored when the lower 24 bits are 0. So does this command even have any effect here? What should the value be instead?
Secondly, it asserts that some cards already require CRC. So I updated the CRC portion of cardCommand() to be:
// send CRC
uint8_t crc = 0XFF;
if (cmd == CMD0) crc = 0X95; // correct crc for CMD0 with arg 0
if (cmd == CMD8) crc = 0X87; // correct crc for CMD8 with arg 0X1AA
if (cmd == CMD1) crc = 0xF9;
//if (cmd == ACMD41) crc = 0x77; //correct crc for ACMD41 with arg 0x40000000
if (cmd == ACMD41) crc = 0x17; //correct crc for ACMD41 with arg 0x50000000
if (cmd == CMD58) crc = 0xFD;
spiSend(crc);
Lastly, it recommends sending a dummy byte before CMD0 (aside from the 74 clock pulses), therefore I begin the function:
uint8_t Sd2Card::cardCommand(uint8_t cmd, uint32_t arg) {
// end read if in partialBlockRead mode
readEnd();
// select card
chipSelectLow();
// wait up to 300 ms if busy
waitNotBusy(300);
//send dummy byte before idle
if (cmd == CMD0) spiSend(0xFF);
// send command
spiSend(cmd | 0x40);
...
But for some reason, my cards always remain in low voltage (1.8V) mode, despite being purportedly capable of 2.7-3.3V operation (as evidenced in the OCR).
My full ::init() function looks like this:
uint8_t Sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin) {
errorCode_ = inBlock_ = partialBlockRead_ = type_ = 0;
chipSelectPin_ = chipSelectPin;
// 16-bit init start time allows over a minute
unsigned int t0 = millis();
uint32_t arg;
// set pin modes
pinMode(chipSelectPin_, OUTPUT);
digitalWrite(chipSelectPin_, HIGH);
/* Drive the MISO pin high */
pinMode(SPI_MISO_PIN, OUTPUT);
digitalWrite(SPI_MISO_PIN, HIGH);
#ifndef USE_SPI_LIB
pinMode(SPI_MISO_PIN, INPUT);
pinMode(SPI_MOSI_PIN, OUTPUT);
pinMode(SPI_SCK_PIN, OUTPUT);
#endif
#ifndef SOFTWARE_SPI
#ifndef USE_SPI_LIB
// SS must be in output mode even it is not chip select
pinMode(SS_PIN, OUTPUT);
digitalWrite(SS_PIN, HIGH); // disable any SPI device using hardware SS pin
// Enable SPI, Master, clock rate f_osc/128
SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR1) | (1 << SPR0);
// clear double speed
SPSR &= ~(1 << SPI2X);
#else // USE_SPI_LIB
SDCARD_SPI.begin();
settings = SPISettings(350000, MSBFIRST, SPI_MODE0);
#endif // USE_SPI_LIB
#endif // SOFTWARE_SPI
// must supply min of 74 clock cycles with CS high.
#ifdef USE_SPI_LIB
SDCARD_SPI.beginTransaction(settings);
#endif
for (uint8_t i = 0; i < 10; i++) spiSend(0XFF);
#ifdef USE_SPI_LIB
SDCARD_SPI.endTransaction();
#endif
chipSelectLow();
//Send CMD0
// command to go idle in SPI mode
while ((status_ = cardCommand(CMD0, 0)) != R1_IDLE_STATE) {
unsigned int d = millis() - t0;
if (d > SD_INIT_TIMEOUT) {
error(SD_CARD_ERROR_CMD0);
goto fail;
}
}
//Send CMD8
// check SD version
if ((cardCommand(CMD8, 0x1AA) & R1_ILLEGAL_COMMAND)) {
type(SD_CARD_TYPE_SD1);
} else {
// only need last byte of r7 response
for (uint8_t i = 0; i < 4; i++) status_ = spiRec();
if (status_ != 0XAA) {
if(status_ != 0x01){
error(SD_CARD_ERROR_CMD8);
goto fail;
}
}
type(SD_CARD_TYPE_SD2);
}
//SDHC supported, SDXC maximum performance
arg = type() == SD_CARD_TYPE_SD2 ? 0X50000000 : 0;
while ((status_ = cardAcmd(ACMD41, arg)) != R1_READY_STATE) {
// check for timeout
unsigned int d = millis() - t0;
if (d > SD_INIT_TIMEOUT) {
break;
}
}
/*Try CMD1 before trying ACMD41 again */
if(status_){
while ((status_ = cardCommand(CMD1, 0)) != R1_READY_STATE) {
unsigned int d = millis() - t0;
if (d > SD_INIT_TIMEOUT) {
error(SD_CARD_ERROR_CMD0);
goto fail;
}
}
while ((status_ = cardAcmd(ACMD41, arg)) != R1_READY_STATE) {
// check for timeout
unsigned int d = millis() - t0;
if (d > SD_INIT_TIMEOUT) {
error(SD_CARD_ERROR_ACMD41);
goto fail;
}
}
}
// command to initialize in SPI mode
// initialize card and send host supports SDHC if SD2
// if SD2 read OCR register to check for SDHC card
if (type() == SD_CARD_TYPE_SD2) {
if ((status_ = cardCommand(CMD58, 0))) {
error(SD_CARD_ERROR_CMD58);
goto fail;
}
if ((spiRec() & 0XC0) == 0XC0) type(SD_CARD_TYPE_SDHC);
// discard rest of ocr - contains allowed voltage range
for (uint8_t i = 0; i < 3; i++) spiRec();
}
chipSelectHigh();
#ifndef SOFTWARE_SPI
return setSckRate(sckRateID);
#else // SOFTWARE_SPI
return true;
#endif // SOFTWARE_SPI
fail:
chipSelectHigh();
return false;
}
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.