New fast data logging sketches

Every SPI device has its own select pin and these should differ! You can only have one device selected simultaneously otherwise there will be interference. The most robust way is to wrap every SPI action with a device select/deselect.

some pseudocode

digitalWrite(ADC_SS, HIGH);
ADC.start();
digitalWrite(ADC_SS, LOW);

....

digitalWrite(ADC_SS, HIGH);
x = ADC.read();
digitalWrite(ADC_SS, LOW);

...

digitalWrite(SD_SS, HIGH);
SD.write (x)
digitalWrite(SD_SS, LOW);

But when you have interrupts using adc, you don't know if you are no gone get interrupt call during sd.write(x). And if you use sei() cli() around sd.write(x) you can drop samples in your adc. That was my assumption for my wrong readings. And I wanted to be sure there was no over option than using soft spi and bit banging for adc.
I switched to soft spi for adc and the sketch is working nicely. But I'm still interested to know if there is not another way to do it, perhaps by forcing SS pin of other spi device when getting into the adc interrupt.

But when you have interrupts using adc, you don't know if you are no gone get interrupt call during sd.write(x)

Then sd.write() should block IRQ's ?

... and the sketch is working nicely ...

Can you post your code ...

setup is calling this function to setup SPI for MCP3208:

void setupExternalADC(){ 
 pinMode(SELPIN, OUTPUT); 
 pinMode(DATAOUT, OUTPUT); 
 pinMode(DATAIN, INPUT); 
 pinMode(SPICLOCK, OUTPUT); 
 //disable device to start with 
 digitalWrite(SELPIN,HIGH); 
 digitalWrite(DATAOUT,LOW); 
 digitalWrite(SPICLOCK,LOW); 
}

there is an header file for pin configuration

#define SELPIN 25 //Selection Pin 
#define DATAOUT 24//MOSI 
#define DATAIN  26//MISO 
#define SPICLOCK  22//Clock

interrupt call this function (the MCP3208 from playground):

int read_adc(int channel){
  int adcvalue = 0;
  byte commandbits = B11000000; //command bits - start, mode, chn (3), dont care (3)

  //allow channel selection
  commandbits|=((channel-1)<<3);

  digitalWrite(SELPIN,LOW); //Select adc
  // setup bits to be written
  for (int i=7; i>=3; i--){
    digitalWrite(DATAOUT,commandbits&1<<i);
    //cycle clock
    digitalWrite(SPICLOCK,HIGH);
    digitalWrite(SPICLOCK,LOW);    
  }

  digitalWrite(SPICLOCK,HIGH);    //ignores 2 null bits
  digitalWrite(SPICLOCK,LOW);
  digitalWrite(SPICLOCK,HIGH);  
  digitalWrite(SPICLOCK,LOW);

  //read bits from adc
  for (int i=11; i>=0; i--){
    adcvalue+=digitalRead(DATAIN)<<i;
    //cycle clock
    digitalWrite(SPICLOCK,HIGH);
    digitalWrite(SPICLOCK,LOW);
  }
  digitalWrite(SELPIN, HIGH); //turn off device
  return adcvalue;
}

datalogging on the sd card is not done with interrupt but just link in this tutorial the http://www.arduino.cc/en/Tutorial/BlinkWithoutDelay

Hello,

thank you fat16lib for your time which you are putting to open-source code and helping others! I am a beginner with Arduino and I appreciate it a lot...

I am using your mcpLogger.pde with ADC MCP3201, but for some reason it save only first two lines to the file. First ,,Log Interval usec: 250" and second ,,4095" or ,,0". I was trying to put different voltage at the input or put it to the ground, but it lives by itself live and always save one of those values.
On the serial communication it writes only this:

Type any character to start.
FreeRam: 308
Log Interval: 250 usec
Logging to: FAST

and then it get stacked. Sometime it ends with FAST08. and sometime just with F. Here comes my question. Do you know, please, where can be the problem? I have Arduino Ethernet and saving it to uSD card. Firstly I thought, that it is because small ram, but this doesnt seem to be the problem. Every time I reset the Arduino board it writes one letter less.

I change the code this way:

// SD chip select pin
const uint8_t chipSelect = 4;

#else  // MEGA_TEST
const int8_t MCP_SAR_CLK_PIN   = 0;  // analog pin 0
const int8_t MCP_SAR_DOUT_PIN  = 1;  // analog pin 1
const int8_t MCP_SAR_DIN_PIN   = -1;
const int8_t MCP3201_CS_PIN    = 2;  // analog pin 2
#endif  // MEGA_TEST

I will appreciate any idea where I can look. I spend more than week trying to find out the problem.

Thank you in advance,
Maslo

masloo,

Which pins is the ADC connected to?

I set again the inputs like that:

const int8_t MCP_SAR_CLK_PIN   = A0;  // analog pin 0
const int8_t MCP_SAR_DOUT_PIN  = A1;  // analog pin 1
const int8_t MCP_SAR_DIN_PIN   = -1;
const int8_t MCP3201_CS_PIN    = A2;  // analog pin 2

and it acquire 2863 on the SD card, that is quite accurate to 3,3 volts which I am sending to the ADC.

In the log file is only:

Log Interval usec: 250
2863

very rare happened that it save 2 values. Anyways it sends over serial communication just this:

Type any character to start.
FreeRam: 308
Log Interval: 250 usec
Logging to: FAS

and then I have to reset the Arduino to make new measurement. It doesnt look like the problem is with PINs. For some reason the program get stacked after saving first value.

Here is the picture of my boards:

Can you please give me an advice how to get rid of this problem? Thank you in advance.

Yours sincerely,
Maslo

I changed the code for ADC MCP3204 one channel. The serial communication works, but it saves one value to the file and without waiting for user input it automatically stops.

Type any character to start.
FreeRam: 294
Log Interval: 250 usec
Logging to: FAST03.CSV
Type any character to stop.
Stopped!

Please, any help or advice is more than welcome.
Maslo

Arduino 1.0 changed the functionality of Serial.flush(). Serial.flush() no longer flushes input. In 1.0 Serial.flush() waits for output to finish.

Change this:

 PgmPrintln("Type any character to start.");
  while (!Serial.available());
  Serial.flush();

to this:

PgmPrintln("Type any character to start.");
  while (!Serial.available());
  delay(10);
  while (Serial.read() >= 0);

If your chip is a MCP3201 you should use the code for that chip.

Oh my... Now it works great! Thank you very, very much! No more sleepless nights XD At least for this problem...

Hopefully soon I will be able to help you too.

Take care fat16lib,
Maslo

Fat16Lib,

How are you?

I am a beginner at Arduino programming, I have mostly been using the Lab View Interface to run simple projects. Now I am trying to use a MCP3201 to send info to the Arduino using the SPI.

Can you help me out with a simple code for reading the SPI from the MCP3201?

I am using a Duemilanove 328p connecting SPI using 10 to 13 pins.

I really don't need any fancy speed or logging. I would like to debug a board that we have built for a PT100, but I haven't been able to connect it through SPI.

I am reading your code for the datalogger, but it gets me more confused.

If you can I will appreciate.
Thanks

Fefas

If you just want simple hardware SPI access, read section 6.1 of the datasheet http://ww1.microchip.com/downloads/en/DeviceDoc/21290e.pdf.

Hey fat16Lib,

Thanks, I read that. I am trying to write the program, but I don't have a lot of experience on programming, just started.
From what I understood I got to receive 2 bytes, shift the 2nd byte 1 bit to the right and shift the 1st byte 7 bits to the left. Is that correct?
Can you help with the code for that?

Thanks

Sorry, I get way too many requests to help with code for things like this.

I am sorry to hear about that. Thanks anyway.

Fefas, You are more likely to get help on your problem, if you post your programming question (about bit-shifting) in the Programming Questions section of the forum:
http://arduino.cc/forum/index.php/board,4.0.html

Hi,
just did some measurements using this lib and put the results here:
Arduino writing to SD Card – Next test based on Fat16Libs fast data logging sketches
http://robertgetzner.com/PersonalWordpress/?cat=37
If you think that this is useful, just copy where it´s better placed (don´t know this forum/etc well enough).
THanks, Robert

@Robert Getzner:
This is great. Thanks for the detailed analysis!
And I wish there was some wiki where information like this were made permanent (Perhaps the Arduino playground?).
Until then, could you please create a separate new thread/topic on the "Storage" section of the forum, and either link to, or copy and paste, the information from your webpage.
You could perhaps title the thread something generic enough (e.g., "SD card writing at high speed / sample rate") so that future searchers can find it easily.

@giantsfan3: thanks :slight_smile:
ok for the post, but can´t do it today. Maybe with a title like '[Info] Example measurement for high speed ADC & SD Card writing' and maybe asking interested folks what the would be interested in to be measured further.

I looked at playground -> storagy....am unsure if my post already qualifies for the playground olymp :wink: For example I didn´t add the info, which hardware I used, which SD card etc. So it´s no qualified measurement in the sense.

I´m wondering more if a kind of 'getting started with Ardiuno & SD' would help people more (After reading some of the topics in this forum....). Something along these lines

  • Working example of setting up the hardware + simple sketch to basically test if it works in principle (people could also be asked to try this before posting questions :wink: ) ; could be complemented over time with 'proven SD cards'
  • Basic steps to analyze issues (memory consumption, frequency/data volume of updates to/read from SD)
  • Decision tree along some questions ( a) volume of data to be written (b) which frequency to you want to log with...). There will also be some ends in the decision tree that end in 'Do not use an arduino, better get a digital scope...')

Opinions?

Robert, As the site (http://playground.arduino.cc) states, "This is the place to post and share your own code, circuit diagrams, tutorials, DIY instructions, tips and tricks, and after all the hard work, to show off your projects."

So I think your post more than qualifies, especially because, based on seeing your blog, you have a very clear, organized writing style!

I'm sure most of the community would back you up on that.

And, if you would make a tutorial regarding Arduino & SD covering the various aspects that you mentioned, it could become a much-needed accumulation/bible of all things data-logging-related for Arduino-users. If something like that exists, at least 25% of the SD-storage-related questions on this forum could probably be avoided :slight_smile:

There are numerous questions coming up all the time regarding data logging, especially faster logging (you have seen the "Storage" section of the forum already). And one of the sadly missing things is that a lot of the knowledge from the forum answers is never accumulated into a permanent page of wisdom that future users can refer to.

While a lot of the blogs on the Internet, e.g., Ladyada's site, cover basic hardware setup of Arduino-to-SDcard, however there is a big need for authoritative tutorials on the software side of SD logging.

Fat16lib's library of course has been an enormous step, and a tutorial like the one you want to write could be a very useful instructive contribution to lots of people.

I remember I spent nearly a few weeks in my early Arduino days to achieve faster logging than a few hundred points a second; of course, now the target has been extended further!