Arduino and Writing SD

Hello everyone, I am a novice in this forum! My project is to collect data about wind (speed and direction) through 2 sensors (anemometer and wind vane), point out the date, time and coordinates of the system (with GPS) and write txt daily files on SD card. The best would be that these daily data are then sent via a GSM modem ... but now I am concentrating on the first part: I solved the question about velocity, direction and GPS, and now I have to concentrate in the writing of SD! Now comes the fun!

I have seen so many posts, and all more or less refer to the same picture to connect the Arduino to SD, the one with 3 resistors 1.8k and 3 of 3.3k; first question ... having the Arduino mega, do the pinout remains the same?

Second question ... I read that the SD needs the voltage to 3.3V, and that's why you build the circuit ... but if I feed it with the release directly from 3.3V Arduino, is not good?

Third question ... I saw the library from GPSShield for Arduino, which in theory should create several text files, so it should do just for me ... someone has ever used?

Do you have any suggestions on writing the data? For example, write on file the data as soon as they've been taken, or record them, for example every 20 seconds, and then write them on file?

I apologize in advance for questions may be too trivial, but unfortunately, I do not understand much electronics and several circuits

Thanks to all those who want to help me in some way ... I hope that you'll take part!

Bye Angelo

If you want to avoid working with the resistors for level shifting, I would suggest this SD board . . . There's a SD and a mini SD model. They also have their own 3.3V reg. It's the easiest way to add the SD hardware IMO.

If you only want to write to the card, I found the Filelogger lib easy to work with . . . but there are other choices.

I've found that writes to the card are pretty fast. I don't know how fast you're polling but you might be able to write and close the file in realtime. You can start out that way and see how it performs and add the buffer later if you need it.

Good luck with your project.

So, with the FileLogger library could i create more than one file?

Yes, you can. In fact, not with filelogger. For the moment, you must create an ascii file (8 characteres in name + 3 characters in extension), with at least one character inside (an space is enough). Save the file (or files in the SD or microSD card), an that is all. You only need to call them from the sketch to save data inside. So the number of files is your choice.

For example, i am working on save (although i am still don´t know how) data inside a file names data.log (it could be read with notepad or wordpad, as well as other txt files), and a log with problems in sensors and things like that into a syslog.log file.


My requirement is that my system should work alone, without the files should be created everyday automatically! :-?

I've read that it would be better using a Usb flash memory than an SD card, which is more difficult to interface...did anybody get experience with Usb memory and could help me?

this works perfectly for me

it can use both 32 and 16 fats up to 2 gb - tested and works perfectly with some modifications on the sd adptor on the ethernet shield...


Do you mean hardware or software changes? If I understand it correctly it should be a little more than changing the pin settings in software, since you can't use the ATMegas SPI Core. Can you give me some hints?


I've used the Fat16lib's very cool! I create txt files, write on them and close them...with some simple istructions! I raccomend this library to write on SD card!

@Duckula: after you aply the hacks in the ethernet library for use with the MEGA and after you change all ss pins to other than 53, use the sdfat sdi configuration disable w5100 spi by driving the sen (prog) jumper LOW. I also drive 53 always HIGH no matter if |I don't have it connected... this way there is no conflict with the buged w5100 spi pins... I include my changed sdfat and ethernet libs

I use pin 4 to drive the prog jumper LOW-HIGH wired to the jumper...

also read this

I hope I helped you

Thanks bioactive712, you helped me figure this out. I wrote a little tutorial how to get this working with the normal arduino.


I wonder if there is a reason why you do not use pin 53 of the Mega for CS of the SD card or the Wiznet (or for driving the prog-pin).

I want to know this because I'm going to try this with a Seeeduino Mega. It is smaller (SMD, mini USB) and board-size is a big issue in my project. It is not 100% pin compatible with an Arduino Mega - it has all ports routet to IO-pins but a different pinout on digital IO 22-53, i2c, analog in 8-15 and serial interface. (means 70 digital IOs totally instead of 54)

My idea is to use pin 53 for disabling the Wiznet. So I can use 6 pins of the Seeeduino inline (48-53) for interfacing the ethernet shield with SD-card.

BTW: excellent work!

Latest results:

Pin 53 of the mega has to be set to output (it doesn't matter if high or low), then the mega becomes SPI-master, otherwise hardware SPI will not work.

It is used for Slave Select (SS) but I want to control two slaves (SD-card and ethernet), so I use two digital IO pins (48, 49) instead - like the way bioactive712 did it. I fiddled around with the modified libraries, but I had no success in disabling the Wiznet via the prog-pin. (@bioactive712: please, can you change your drawing? - The other prog-pin is the right one!)

I came up with a different solution: I use the SS signal of the SD-card (pin 6 on the shield) for enabling the Wiznet. Only the Mega-hack has to be implemented in the Ethernet and SDFat libraries and the definition of the SS-pins has to be changed.

Seems to work so far, I'm going to test it in the next days.

Correction for the last post (sorry):
I came up with a different solution: I use the SS signal of the SD-card (pin 6 on the shield) for disabeling the Wiznet. Only the Mega-hack has to be implemented in the Ethernet and SDFat libraries and the definition of the SS-pins has to be changed.

The Test was ok.

I also tried to use the standard SS (pin 53) for selecting the Wiznet, so that i am able to use the standard spi_mega.h instead of a hacked version now. Only the SS pin in the SDFat library has to be changed.

Test was ok, too.

Result: Only one additional pin (49 in my case) has to be used to make Ethernet and SD-card work together.

But: If you are going to stack another shield ontop of the arduino which also needs SPI, you have to connect this SS signal also to the prog pin of the Wiznet.

There occoured stability problems, somtimes everything went ok but often not.

The origin SS pin seems to be automatically controlled by the SPI hardware (did some hacks on the different spi sourcecodes and some testing). That leads to corrupted data on the bus when two devices are on the same bus and pin 53 is used for Slave Select.

Conclusion: Pin 53 of the mega cannot be used for SS (slave select) with multiple SPI slaves.

So my current solution is:

mega signal shield

pin53 NC not connected but must be configured as output pin52 SCLK pin 9 & 13 pin51 MOSI pin 8 & 11 pin50 MISO pin 3 & 12 pin49 SS_Eth pin 11 pin48 SS_SD pin 6 & prog

The main difference compared to bioactive712's solution is to use SS_SD for disabling the wiznet automatically.

I have modified the spi.h so that it works with both mega and duemillanove (not tested yet). Additionally you can choose to use a dedicated WD (Wiznet Disable) pin or to use a hardwired solution by connecting the prog pin with CS of the SD-card (pin 6)

//AVR Mega168 SPI HAL
#define BIT0                              0x01
#define BIT1                              0x02
#define BIT2                              0x04
#define BIT3                              0x08
#define BIT4                              0x10
#define BIT5                              0x20
#define BIT6                              0x40
#define BIT7                              0x80

// this part can be commented out if the prog pin
// of the Wiznet is hardwired to CS of the SD card (pin 6)
#if defined(__AVR_ATmega1280__)
  // pin 47
  #define SPI0_WD_BIT                        BIT2
  #define SPI0_WD_DDR                        DDRL
  #define SPI0_WD_PORT                        PORTL
  // pin 7
  #define SPI0_WD_BIT                        BIT7
  #define SPI0_WD_DDR                        DDRD
  #define SPI0_WD_PORT                        PORTD

#if defined(__AVR_ATmega1280__)
  // pin 48
  #define SPI0_SS_BIT                        BIT1      
  #define SPI0_SS_DDR                        DDRL
  #define SPI0_SS_PORT                        PORTL
  #define SPI0_SS_BIT                        BIT2
  #define SPI0_SS_DDR                        DDRB
  #define SPI0_SS_PORT                        PORTB

// origin SS pin on mega (pin 53) cannot be used for CS signaling
// it produces corrupt data on SPI bus, but it has to be configured as output
// not tested on duemillanove!
#if defined(__AVR_ATmega1280__)
  #define SPI0_SE_BIT                        BIT0
  #define SPI0_SE_BIT                        BIT2
#define SPI0_SE_DDR                        DDRB
#define SPI0_SE_PORT                        PORTB

#if defined(__AVR_ATmega1280__)
  #define SPI0_SCLK_BIT                        BIT1
  #define SPI0_SCLK_BIT                        BIT5
#define SPI0_SCLK_DDR                        DDRB
#define SPI0_SCLK_PORT                        PORTB

#if defined(__AVR_ATmega1280__)
  #define SPI0_MOSI_BIT                        BIT2
  #define SPI0_MOSI_BIT                        BIT3
#define SPI0_MOSI_DDR                        DDRB
#define SPI0_MOSI_PORT                        PORTB

#if defined(__AVR_ATmega1280__)
  #define SPI0_MISO_BIT                        BIT3
  #define SPI0_MISO_BIT                        BIT4
#define SPI0_MISO_DDR                        DDRB
#define SPI0_MISO_PORT                        PORTB

#define SPI0_WaitForReceive()                        
#define SPI0_RxData()                         (SPDR)

#define SPI0_TxData(Data)                  (SPDR = Data)
#define SPI0_WaitForSend()                  while( (SPSR & 0x80)==0x00 )

#define SPI0_SendByte(Data)                  SPI0_TxData(Data);\
#define SPI0_RecvByte()                        SPI0_RxData()

// PB4(MISO), PB3(MOSI), PB5(SCK), PB2(/SS)         // CS=1, waiting for SPI start // SPI mode 0, 4MHz
#if defined (SPI0_WD_BIT)
      #define SPI0_Init()                        SPI0_WD_DDR    |= SPI0_WD_BIT;\
                                          SPI0_SS_DDR    |= SPI0_SS_BIT;\
                                          SPI0_SE_DDR    |= SPI0_SE_BIT;\
                                          SPI0_SCLK_DDR  |= SPI0_SCLK_BIT;\
                                          SPI0_MOSI_DDR  |= SPI0_MOSI_BIT;\
                                          SPI0_WD_PORT   |= SPI0_WD_BIT;\
                                          SPI0_SS_PORT   |= SPI0_SS_BIT;\
                                          SPI0_SCLK_PORT &= ~SPI0_SCLK_BIT;\
                                          SPI0_MOSI_PORT &= ~SPI0_MOSI_BIT;\
                                          SPCR = 0x50
      #define SPI0_Init()                        SPI0_SS_DDR    |= SPI0_SS_BIT;\
                                          SPI0_SE_DDR    |= SPI0_SE_BIT;\
                                          SPI0_SCLK_DDR  |= SPI0_SCLK_BIT;\
                                          SPI0_MOSI_DDR  |= SPI0_MOSI_BIT;\
                                          SPI0_SS_PORT   |= SPI0_SS_BIT;\
                                          SPI0_SCLK_PORT &= ~SPI0_SCLK_BIT;\
                                          SPI0_MOSI_PORT &= ~SPI0_MOSI_BIT;\
                                          SPCR = 0x50

#define IINCHIP_SpiInit                        SPI0_Init
#define IINCHIP_SpiSendData                  SPI0_SendByte      
#define IINCHIP_SpiRecvData                  SPI0_RxData

#define IINCHIP_CS_BIT                        SPI0_SS_BIT
#define IINCHIP_CS_DDR                        SPI0_SS_DDR
#define IINCHIP_CS_PORT                        SPI0_SS_PORT

#define IINCHIP_CSInit()                  (IINCHIP_CS_DDR |= IINCHIP_CS_BIT)
#if defined (SPI0_WD_BIT)
      #define IINCHIP_CSon()                  (IINCHIP_CS_PORT |= IINCHIP_CS_BIT);\
                                    (SPI0_WD_PORT &= ~SPI0_WD_BIT)
      #define IINCHIP_CSoff()                  (IINCHIP_CS_PORT &= ~IINCHIP_CS_BIT);\
                                    (SPI0_WD_PORT |= SPI0_WD_BIT)
      #define IINCHIP_CSon()                  (IINCHIP_CS_PORT |= IINCHIP_CS_BIT)
      #define IINCHIP_CSoff()                  (IINCHIP_CS_PORT &= ~IINCHIP_CS_BIT)