My hardware is: OSEPP Uno rev1.1 with an Adafruit Ethernet shield rev3 and a 4 gig sandisk SDHC memory card.
I am able to write to the SD card and read back what was written. I used SDfat to format the SD card. My problem is that every byte written to the SD card is duplicated on the SD card. For example, If I write a 0 it will read back as 0 0 on two lines (not side by side). If I write ten 1's it will read back as twenty 1's. For testing I also write the byte to the serial monitor and it shows that there are no duplicates. If I write ten 1's the serial monitor will show exactly ten 1's. I'm using an uint8_t variable for writing to the SD card which I believe means that I am sending a single 8 bit byte each time I write to the SD card.
Can anyone explain why I have duplicates on the SD card? I really appreciate your time to look into this.
Here is the full code:
/*
This program is a modified version of the three analog sensor data
logger in the Arduino examples. It logs the input from only 1 digital pin.
The circuit:
* analog sensors on analog ins 0, 1, and 2
* SD card attached to SPI bus as follows:
** MOSI - pin 11
** MISO - pin 12
** CLK - pin 13
** CS - pin 4
created 24 Nov 2010
modified 9 Apr 2012
by Tom Igoe
modified 7 Nov 2013
by Dan Johnson
This example code is in the public domain.
*/
#include <SD.h>
// On the Ethernet Shield, CS is pin 4. Note that even if it's not
// used as the CS pin, the hardware CS pin (10 on most Arduino boards,
// 53 on the Mega) must be left as an output or the SD library
// functions will not work.
const int chipSelect = 4;
//REMEMBER TO SET CHIP SELECT AS AN OUPUT SEE BELOW!!!!!!
//name the data and clock pins and create a variable for the data
const int dataPin = 5;
const int clockPin = 6;
void setup()
{
//set up data and clock pins as input pins
pinMode(dataPin, INPUT);
// Open serial communications and wait for port to open:
Serial.begin(115200);
while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only
}
Serial.print("Initializing SD card...");
// make sure that the default chip select pin is set to output, even if you don't use it:
pinMode(10, OUTPUT); //pin 53 for Mega2560 and 10 for Uno
// see if the card is present and can be initialized:
if (!SD.begin(chipSelect)) {
Serial.println("Card failed, or not present");
// don't do anything more:
return;
}
Serial.println("card initialized.");
}
void loop()
{
//declare 8 bit variable to hold dataPin input
uint8_t dataByte = 0;
//open the file on the SD card
Serial.println("Opening the data file...");
File dataFile = SD.open("datalog.txt", O_CREAT | O_WRITE);
//display a status message for opening the data file
if (dataFile) {
Serial.println("Data file is open and ready to use...");
}
else {
Serial.println("error opening the data file on the SD card...");
return;
}
//read the dataPin to dataByte (dataByte is a uint8_t variable)
dataByte = digitalRead(dataPin);
//print dataByte to the SD card
dataFile.println(dataByte);
//also print dataByte to the serial monitor:
Serial.println(dataByte);
dataFile.close();
while(1){
//loop forever;
}
}
Maybe someone can run my code with their SD card and verify that it does the same thing for them? That would help point me in the right direction for determining why this is happening.
I would first use the correct parameter for the open call. You have a choice of FILE_READ or FILE_WRITE for the mode. FILE_WRITE sets the file pointer to the end of the file (append). Use seek() to change that file pointer if you wish.
// change this
File dataFile = SD.open("datalog.txt", O_CREAT | O_WRITE);
// to this
File dataFile = SD.open("datalog.txt", FILE_WRITE);
You have two "return" statements in your code, one in setup() and one in loop(). They should both be "while(1)" so that the code hangs if the error condition occurs.
I changed it to FILE_Write and I'm still seeing the double entries on the SD card. Maybe my SD read sketch is showing double entries but there really aren't 2 entries on the card? I don't have a card reader on my computer so I have to rely on a sketch to do it.
Here is my code for reading the contents of my file on the SD card. It's modified from the Arduino examples. I commented out the code for writing a file and changed the text file name.
/*
SD card read/write
This example shows how to read and write data to and from 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>
File myFile;
void setup()
{
// Open serial communications and wait for port to open:
Serial.begin(115200);
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.");
// // open the file. note that only one file can be open at a time,
// // so you have to close this one before opening another.
// myFile = SD.open("test.txt", FILE_WRITE);
//
// // if the file opened okay, write to it:
// if (myFile) {
// Serial.print("Writing to test.txt...");
// myFile.println("testing 1, 2, 3.");
// // close the file:
// myFile.close();
// Serial.println("done.");
// } else {
// // if the file didn't open, print an error:
// Serial.println("error opening test.txt");
// }
// re-open the file for reading:
myFile = SD.open("datalog.txt");
if (myFile) {
Serial.println("datalog.txt:");
// read from the file until there's nothing else in it:
while (myFile.available()) {
Serial.write(myFile.read());
}
// close the file:
myFile.close();
} else {
// if the file didn't open, print an error:
Serial.println("error opening test.txt");
}
}
void loop()
{
// nothing happens after setup
}
So if you write 1 byte to the SD card the SD read sketch reports back 1 byte? I wonder why mine reports 2 duplicate bytes? I'm going to buy a card reader tonight so I can read it directly.
Thanks for running my code Pete.
When you upload the code or power up the Arduino, the program runs. It puts one entry in your file.
When you open the serial monitor, the Arduino resets and the program runs again. It puts another entry in your file.
SurferTim:
When you upload the code or power up the Arduino, the program runs. It puts one entry in your file.
When you open the serial monitor, the Arduino resets and the program runs again. It puts another entry in your file.
That was it. I added an enter any character to start routine and no more duplicates.
Thanks Tim.
On a side note I bought a Sandisk Extreme micro SDHC 16Gig memory card that is rated for 80MB/s and it wasn't any faster for writing than the plain jane 4gig Sandisk card was. They both can write 75000 bytes in 12 seconds on my Arduino Uno. I used no buffers for writing and I opened the file only once to write the 75000 bytes. Each byte was loaded with 255.
danieljohnsonk:
On a side note I bought a Sandisk Extreme micro SDHC 16Gig memory card that is rated for 80MB/s and it wasn't any faster for writing than the plain jane 4gig Sandisk card was. They both can write 75000 bytes in 12 seconds on my Arduino Uno. I used no buffers for writing and I opened the file only once to write the 75000 bytes. Each byte was loaded with 255.
The limit is the SPI bus speed. Normal SPI clock speed on the Arduinos is 4MHz.
edit: I am currently running a web server test. It uploads to a client (reads from SD) a 230,000 byte jpg file in 12 seconds. http://68.99.58.119/img/wolver.jpg
Bear in mind that both the SD and the w5100 ethernet IC use the SPI bus, so for that speed test, the SD card is sharing the SPI bus with the w5100. The code reads 64 bytes from the SD, then sends those to the client over the w5100.