Here’s a rough draft of some code I’m working on to store variables on an SD card:
#include <SD.h>
#include <string.h>
#include <SdFile.cpp>
Sd2Card card;
SdVolume volume;
SdFile root;
/*
ENCODING OF "TheJohnson" MUST BE UTF8!!!!!
*/
void setup() {
Serial.begin(9600);//Baud = 9600 for serial :)
Serial.print(F("Total RAM available: "));
Serial.println(FreeRam()); //this line can be placed anywhere in the code.
//if the number printed is less than 5% of total, we're doomed
//the following two lines are necessary for some reason.
pinMode(10,OUTPUT);
//digitalWrite(10,HIGH);
//I actually have a 10,000 v actuator tied to pin 10... so I'm gonna have to fix that library somehow
digitalWrite(A1,HIGH);
digitalWrite(A0,LOW);
if (!card.init(SPI_HALF_SPEED,A0)) //we're using pin A0 for the SD_CE, baby
Serial.println(F("failure to initialize card."));
if (!volume.init(&card)) //Just making sure it's fat.
Serial.println(F("failure to initialize volume."));
Serial.print(F("It's really FAT")); //in case you were wondering...
Serial.println(volume.fatType(),DEC); //this is the fat type.
//root.ls(LS_R); //Built in arduino function for printing all folders/subdirectories
Serial.println(F("Finished with setup."));
}
//Store indecies as uint8_t.
//The goal is to trim all my "long"s to just 1 byte each in ROM
//these will be like "reference variables" for our SD card stuff
//Here's an example var:
//int8_t dloca = 0; //10
//Here's an example file contents:
/*
,10,44,100000000,3,it's a string!,somestuff,9,0,a,
*/
//in that file, all the numbers will be accessible, but the strings will return -1.
void loop() {
float TestVariable;
if (!root.openRoot(&volume)) //opening root
Serial.println(F("failure to open the root"));
for (uint8_t i = 0; i <= 8; i++)
{
Serial.print("Index ");
Serial.print(i);
Serial.print(": ");
TestVariable = getMyFloat(i);
Serial.println(TestVariable);
}
while(true);
}
//Trying to get variables from the SD card...
//The first character in the file will be the delimiter, so don't screw that up.
//this function is heavily dependent on careful handling of MAINCONF.ZAC,
// hereafter known as TheJohnson
//The argument, "offset", is the number of delimiter characters to pass before
// reaching the desired value (first character not included)
//The function will return the desired value, or -1 if there was a datatype error,
// or something else if there was a worse error
//Right now, only positive integers work.
long getMyFloat(uint8_t offset)
{
SdFile TheJohnson;
int16_t delimiter;
uint32_t Startpos;
uint8_t numDigits = 0;
long ThePower;
long desiredValue = 0;
if (!TheJohnson.open(root, "MAINCONF.ZAC", O_READ))
Serial.println(F("Failure to open The Johnson"));
else
{
TheJohnson.rewind();
delimiter = TheJohnson.read();
//Serial.print(F("Delimiter:")); Serial.println((char)delimiter); //for debugging
int16_t c = 0;
for (uint8_t n = 0; n < offset; n++)
while (((c = TheJohnson.read()) > -1 && (c != delimiter)));
Startpos = TheJohnson.curPosition();
//we're at the first byte of the thing we want.
//First we need to know how many digits it has.
while (((c = TheJohnson.read()) > 0) && (c != delimiter))
{
++numDigits;
}
TheJohnson.rewind(); //going back to the top of TheJohnson
TheJohnson.seekSet(Startpos); //going back to previous spot on TheJohnson
//Time to try to concatenate some single-digit numbers:
for (uint8_t n = numDigits-1; n >= 0; n--)
{ //n goes to zero to make powers easier to calculate
c = TheJohnson.read();
if ((c < 0) || (c == delimiter)) {
Serial.println(F("Delimiter detected prematurely. Make sure text encoding is UTF8"));
return(-1);
}
if ( c >= 48 && c <= 57 )
{
c = c - 48;
}
else
{
Serial.println(F("A bad character was detected. Values MUST be positive integer."));
return(-1);
}
ThePower = 1;
for (uint8_t pow = n; pow > 0; pow--) //this is where we calculate the power
ThePower *= 10; //i did it this way so I wouldn't have to include math.
desiredValue = desiredValue + ((float)c * ThePower);
}
return(desiredValue);
}
return(-1);
}
It’s pretty long… Sorry about that. The initialization is on top, where it should be.
I’ve got pin 10 set to output, and I’ve tried setting it high. I am using pin A0 as my CS, and it’s being driven low. I have another device on A1, which is being deselected for this code. My SD card is FAT32 with 16kb allocation, and works on Windows. I’m not using a breakout. The whole board is custom and has a little SD reader thingy on the side; I’m just using the Arduino IDE and bootloader to make programming my Atmega easier.
I get:
“Failed to initialize SD card.”
followed by multiple subsequent failures.
I put a couple error flags in Sd2Card.cpp. My SD card fails the first check for entering IDLE state. (library line ~245)
The code worked perfectly up until about an hour ago, no errors, and now it just doesn’t work. I’m really hoping I didn’t break something.
Give it to me straight, doc. Is she gonna live?