Created Sun, 09 Sep 2012 20:45:13 +0000 by educa
Sun, 09 Sep 2012 20:45:13 +0000
Hi,
I can succesfully read from my SD card, but now I would like to read every time 6 bytes from a file.
I do realize that this will have a performance hit and won't be as fast as reading in larger chunks of data at once, but I just need it working, not ultrafast.
So I tried the following code which works perfectly on arduino
#include "plib.h"
#include <SD.h>
const int chipSelect = 53;
#define BUFFER_SIZE 6
uint32_t s1;
uint32_t s2;
void setup()
{
byte buff[BUFFER_SIZE];
Serial.begin(115200);
Serial.print("Initializing SD card...");
pinMode(53, OUTPUT);
//SPI.setClockDivider(SPI_CLOCK_DIV2);
if (!SD.begin(chipSelect)) {
Serial.println("Card failed, or not present");
return;
}
Serial.println("card initialized.");
File dataFile = SD.open("data.txt");
s1=ReadCoreTimer();
if (dataFile) {
dataFile.read((char*)buff,BUFFER_SIZE);
dataFile.close();
s2=ReadCoreTimer();
Serial.println(s1);
Serial.println(s2);
}
else {
Serial.println("error opening data.txt");
}
}
void loop()
{
}
What I try to do here is read in 6 bytes from the datafile (datafile is much bigger then 6 bytes) to the array of byte called buff.
On arduino this compiles, but on chipkit (IDE 0023-20120811) it tells me
[color=#FF0000]error: no matching function for call to 'File::read(char*, int)' [/color]
Anyone have an idea what I have to change to make this work ?
Thanks,
Bart
Sun, 09 Sep 2012 22:32:14 +0000
Hi there!
You will probably need to make this function public (or at least available to the wrapper code):
SdFat.h, row 241: int16_t read(void* buf, uint16_t nbyte);
Sun, 09 Sep 2012 22:39:18 +0000
Hi rasmadrac and would you have any idea how I would have to do that ?
Kind regards,
Bart
PS. I'm using the standard sd library from the mpide
Mon, 10 Sep 2012 01:23:10 +0000
Untested, but compiles and should work:
Insert the following row into file SD.h after the normal read() function:
virtual int16_t read(void* buf, uint16_t nbyte);
Add this to File.cpp
int16_t File:: read(void* buf, uint16_t nbyte) {
return SD.file.read(buf, nbyte);
}
Tue, 11 Sep 2012 15:25:07 +0000
Thank you,
I tried but somehow it didn't work out for me.
I tried the following code
#include <SPI.h>
#include <SD.h>
#define BUFFER_SIZE 512
#define SD_SS 53
long begintijd;
void setup()
{
Serial.begin(115200);
SD.begin(SD_SS);
digitalWrite(SD_SS,HIGH);
}
void loop()
{
byte buff[BUFFER_SIZE];
Serial.print ("START\n");
begintijd=micros();
File f = SD.open("data.bin");
if (f) {
while (true) {
//int16_t n = f.read((char*)buff,BUFFER_SIZE);
int16_t n=f.read();
if (!n)
break;
}
f.close();
Serial.print("STOP(");
Serial.print(micros()-begintijd);
Serial.print(")\n\n");
}
}
The line[color=#FF0000] int16_t n=f.read(); [/color]does compile and reads a 16 bit integer from sd card. Even an int32_t compiles
But
[color=#FF0000]int16_t n = f.read((char*)buff,BUFFER_SIZE);[/color]
gives me the error
[color=#0040FF]sketch_sep11a.cpp:29:53: error: no matching function for call to 'File::read(char*, int)'
C:\chipkit.\hardware\pic32\libraries\SD/SD.h:32:15: note: candidate is: virtual int File::read()[/color]
Tue, 11 Sep 2012 18:47:08 +0000
This row indicates you did not apply the changes to the SD library correctly: sketch_sep11a.cpp:29:53: error: no matching function for call to 'File::read(char*, int)'
Did you change the Chipkit library and not the Arduino?
Basically you could do either the following (works without editing the library):
uint8_t buff[BUFFER_SIZE];
File f = SD.open("data.bin");
for (int i=0; i < BUFFER_SIZE; i++)
{
buff[i] = f.read();
}
This would read one byte at a time from the SD card = very slow.
Or you can modify the SD card library as I wrote above and do the following:
uint8_t buff[BUFFER_SIZE];
File f = SD.open("data.bin");
f.read( &buff[0] , BUFFER_SIZE );
This is much faster and only open the SD card for communication once and reads 32 bytes in one go. This is the way to go.
Look for the pic32 SD-library inside the MPIDE folder. If you're using Mac it's in "Contents/Resources/Java/hardware/pic32/libraries/SD"... If you're using PC or Linux I can't help you, I'm afraid.
Tue, 11 Sep 2012 18:57:19 +0000
I changed \chipkit\libraries\SD and somehow this could indeed be wrong.
I found out now that there is also a \hardware\pic32\libraries\SD map.
Thanks for clarification
Tue, 11 Sep 2012 22:46:11 +0000
I changed the correct libraries now and indeed this compiles.
My code currently looks like this
#include <SPI.h>
#include <SD.h>
#define BUFFER_SIZE 512
#define SD_SS 53
long begintime;
long endtime;
int16_t i;
void setup()
{
Serial.begin(115200);
SD.begin(SD_SS);
digitalWrite(SD_SS,HIGH);
byte buff[BUFFER_SIZE];
Serial.print ("START\n");
File f = SD.open("data.bin");
if (f) {
begintime=micros();
while (true) {
int16_t n = f.read((char*)buff,BUFFER_SIZE);
if (!n)
break;
}
endtime=micros();
f.close();
Serial.print("STOP(");
Serial.print(endtime-begintime);
Serial.print(")\n\n");
}
}
void loop()
{
}
I checked it and it does indeed read data correctly into the byte array
It does 512 bytes in 3.828 milliseconds, which gives me a transfer rate of aprox. 133700 bytes per second. Thats not bad at all, but do you have any idea if I can speedup this by default?
I think I read somewhere that you might be able to speedup the SPI bus? Or am I wrong? I am allready very happy that this works now, just a little speedup would always be nice of course...
I allready tried to change SPI_HALF_SPEED to SPI_FULL_SPEED in sd.cpp , but that did not improve the speed at all. Maybe its just a limit ?
Kind regards, Bart
Wed, 12 Sep 2012 10:55:47 +0000
Glad you got it working!
If you check further inside the SD-library, you'll see that the entire setClockSpeed-function (or something similar) is commented out. So there's no way of changing the speed unless you do it manually by updating the registers. I'm not that experienced in those registers thou.
I gained quite a lot of speed (almost 10x) by doing a simple (pseudo) change in a custom DSPI-based library: set_speed(slow); initialize_sd(); set_speed(high);
Although not the best there is, it gave me around 614 000 bytes/sec, which is roughly one third of what my card is capable of. Not bad, considering this is 1bit transfer and the max speed is achieved using 4bit transfer.
EDIT:
Remember that the card reads sectors of 512B, so if you read less than that you will not get the full speed possible, since the the rest of the bytes are just wasted (more or less). By reading a full 512byte sector you should get the highest possible speed.
Wed, 12 Sep 2012 11:08:41 +0000
OK, as you can see I am reading 512 bytes.
I must say that reading 1 time 512 bytes takes a certain amount of time, but reading
64 times 8 bytes takes ALMOST te same time, so it seems like there is some kind of optimisation allready or maybe the library allready keeps the buffer to speed sequential reads.
Anyway, I think for my application that the speed will be enough. Maybe I could speedup but then I am afraid it would be too much tweaking in stuff I don't know too good yet :)
Thanks anyway for all help. I'm very happy that with chipkit I can make direct connection and that reading is reasonably fast.