Show Posts
Pages: 1 ... 3 4 [5] 6
61  Forum 2005-2010 (read only) / Exhibition / Re: SD/MMC From the ground up on: March 17, 2009, 05:01:38 pm
This should help. please bear in mind it's fresh off my fingertips and I haven't had a chance to try it out..  :o

I _think_ it kind-of does what you need.. you should develop the interrupt pulse counter and get that all working printing its results to the serial port, then transplant the counting code into here. Add the stop button and you're good to go.

Code:
// !! use the device print demo, and delete the setup & main from it
// !! replacing it with what you see here.


 // or whatever
#define STOP_PIN 3

void setup(void)
{
  Serial.begin(115200);

  // some users have reported cards which won't initialise 1st time
  //
  int n = 0;
  while (mmc::initialize() != RES_OK)
  {
    if (++n == 10)
    {
      error_P(PSTR("Couldn't initialise card"));
    }
    delay(500);
  }

  if (!microfat2::initialize(sectorBuffer, &mmc::readSectors))
  {
    error_P(PSTR("Couldn't initialise microfat"));
  }

  // find the start sector and length of the data we'll be overwriting

  unsigned long sector, fileSize;

  if(!microfat2::locateFileStart(PSTR("DATA    TXT"), sector, fileSize))
  {
    error_P(PSTR("Couldn't find data.txt on the card"));
  }
  
  // The dp library won't write past the end of the allowed space.
  // Indeed, it will only write up to the nearest sector boundary at
  // the end of the file on the card. If your target file is 1000 bytes,
  // only 512 will be written over. The remaining will be left as they
  // were when written to the card.

  dp.initialize(sector, fileSize / 512, sectorBuffer, proxyWriter);
  
  memset(sectorBuffer, '.', 512);

  // get pulses
  //
  attachInterrupt(0, interruptHandler, RISING);

  // make the stop button pin an input, and set it's pull-up resistor
  // the switch should be push-to-make, and connect the pin to ground.
  //
  pinMode(STOP_PIN,INPUT);
  digitalWrite(STOP_PIN,HIGH);

  print_P(PSTR("All initialised OK!\nWriting..."));
}



// this variable is set by the interrrupt routine once a second.
//
// the volatile keyword instructs the compiler that the value
// can change at any time, and should therefore not be cached
// or otherwise involved in optimisations.
//
volatile int counts;

// this variable gets set to true by the interrupt routine when
// a second has elapsed and the count is ready. it's set to false
// by the main loop when the data has been written to the card.
//
volatile bool dataIsAvailable = false;


// every time the sensor pulses low to high, we get called here.
// static variables retain the value they're given between calls.
//
void interruptHandler()
{
  static int ct = 0;
  static long lastMillis = millis();

  ++ct;

  long now = millis();
  if(now - lastMillis > 1000)
  {
    ct = 0;
    counts = ct;
    lastMillis = now;
    dataIsAvailable = true;
  }
}


void loop(void)
{
  if(dataIsAvailable && dp.m_sectorsAvailable > 0)
  {
    // reset the flag variable so we don't keep writing the vale over and over...
    // put the count value into the file. we don't _need_ to flush here, but it
    // will ensure that we don't lose any values as we can stop logging at any time.
    //
    dataIsAvailable = false;
    dp.println(counts, DEC);
    dp.flush();
  }

  // attach a button to some pin and define this variable to let the compiler
  // know which one it's on :)
  //
  if(digitalRead(STOP_PIN)==LOW)
  {
    // switch on the on-board LED to say that the sketch is stopped
    digitalWrite(13,HIGH);

    for(;;) // ever
    {
      // this simply stops the sketch dead, so the card can be removed.
    }
  }
}

Charlie

62  Forum 2005-2010 (read only) / Exhibition / Re: SD/MMC From the ground up on: March 17, 2009, 04:09:28 am
Looks like I got back just in time! Don't Jump!!

Unfortunately you can't pick up a violin and instantly play like Yehudi Mehuhin.  If programming was easy I'd be out of a job...
;D

I'm sorry to hear you're having a hard time with this. I think if you just  keep plugging away all those strange sounding terms will become familiar and slot into some order. It won't happen overnight but it's like building a lot of little bridges, you need the keystones in place to get any further.

You should be able to get from my demo app to a fully fledged data logger in very few steps. Would it help if I provided a new sketch which did the grunt work leaving only the bits needed to gather the data?
63  Forum 2005-2010 (read only) / Exhibition / Re: SD/MMC From the ground up on: March 14, 2009, 02:41:06 am
Yes you're in good shape. How big are your sample sets? Counts per second implies you have 1 second resolution over 15 seconds. That's not exactly a google-smashing database, you should be able to pick and choose your method of saving. There are many ways to do this.
  • store output variables in Arduino's EEPROM between runs
  • write the code so that the data is written over a session which consists of many runs
  • make sure all the target files are named sequentially, empty or filled with a known value and scan each in turn at the start of a run to find an 'empty' one
  • scan the file after a run to find the end and begin writing there
And I'm sure there are many others. Just use your imagination!

If there's some time between runs I'd plump for something that's fail-safe, like the last option above.
C
64  Forum 2005-2010 (read only) / Exhibition / Re: SD/MMC From the ground up on: March 13, 2009, 05:27:28 am
If you're using Linux you're on your own I'm afraid - unless there's anyone reading that would care to share the power??!

On Windows it's easy - open MyComputer and right-click the drive allocated to the card. Select Format from the context menu. For the filesystem select FAT. Not FAT32, plain ol' FAT. Click start and a few seconds later you're done.

Now imagine how much data you're going to write. Find or create a 'donor' file on your harddrive. The contents are irrelevant - you'll be overwriting them. It's the size of the donor file which is important. Too small and you'll lose data 'off the end' when you read it back in the desktop computer. Once the donor file is ready, make sure it's named in 8.3 fashion and copy it to the card. Put the card to the arduino.

You can store whatever you like on the card. I recommend strings because they're the most portable format. Use DevicePrint and putting strings in the file is as easy as using the Serial.print functions.

Remember though: Every time the program runs it will start writing at the start of the file. If you don't want this to happen, then you'll have to think awhile and imagine a scheme to help!

 smiley-wink
65  Forum 2005-2010 (read only) / Exhibition / Re: SD/MMC From the ground up on: March 13, 2009, 02:18:42 am
Hi there,

yes - you're getting it right.

uFat allows you to find the start sector of a file on a card. Deviceprint allows you to write strings to sectors belonging to a file the card.

All you need to do to read and write to the card is make sure it's formatted as FAT16 and copy a big old file on there in order to write into it.
66  Forum 2005-2010 (read only) / Exhibition / Re: SD/MMC From the ground up on: March 12, 2009, 01:53:01 am
I haven't got the time to play ATM, but you need to do the inverse of devicePrint.

Code:
initialise()
{
  bytesInBuffer = 0;
}

char getCharFromBuffer()
{
  if (bytesInBuffer == 0)
  {
     readSectors(sector, buffer, 1);
     ++sector;
     bytesInBuffer = 512;
  }

  --bytesInBuffer;
  return buffer[bytesInBuffer];
}

A byte is an 8-bit wide data type. So is a char. The distinction is _usually_ whether the value is treated as signed or not. The ansi character set only uses 127 values because logically it's unsigned.

Do you really need SD for characters for an LCD display? Just how much text are you wanting to display??? Wouldn't it be better to store the strings in PROGMEM?

C
67  Forum 2005-2010 (read only) / Exhibition / Re: SD/MMC From the ground up on: March 06, 2009, 04:50:18 am
@johanzebin: I don't know about this. The information would be great to add to the article though, so please let us kn ow how you get on. I think your best approach is to stick a frequency meter or oscilloscope on the PWM pin and look at what happens when you run the SPI code. You could write a little loop which writes or reads from the card and display the timings with and without tweaking the PWM rate. Experiment, have fun smiley

@jluciani: thanks! I looked into putting this up in the playground, but  I don't have the time to learn wikispeak right now smiley-sad Any volunteers?? smiley-wink
68  Forum 2005-2010 (read only) / Exhibition / Re: SD/MMC From the ground up on: March 03, 2009, 02:55:32 pm
@koetting:

Have you installed the mmc & microfat2 libraries properly? It sounds like the compiler isn't finding the code. The folders need to be in arduino\hardware\libraries.

@New Colin:

Problems like this are usually related to memory depletion. Have a look and see if any memory allocations or large static buffers are being declared.

69  Forum 2005-2010 (read only) / Exhibition / Re: SD/MMC From the ground up on: February 25, 2009, 02:50:02 pm
Excellent!

As for the multiple SPI slave situation - indeed, this is something that I've thought about but, like most things, I don't do anything about until it bites me smiley-grin

So every device in the SPI chain needs its own /CS line. The only time you need to do anything funky with the one allocated to the MMC card is during initialisation. In order to 'wake it up' and put it in SPI mode you need to send it at least 72 clocks with CS high. I don't think that would cause too much of a problem in a multiple device chain as long as your other devices also have their select lines de-asserted.

If however the MMC will respond even with /CS high.. Oh oh. I've never investigated this. If this _is_ the case then it's time for SoftSPI! This is something I've dabbled with when I was debugging something or other. It's a software implementation of SPI mode 0. You can allocate whichewver pins you like so there's no need to share any lines. I hope it doesn't come to this though... It's comparatively slow.

In practice it doesn't matter too much where the CS pin is defined if you use the MMC code as a library. It would have to be recompiled for every sketch that used it. A way around this would be to allow the CS pin be specified in a variable. It would need this facility in the libraries for each device though... Or not use a true library, instead copying the code to each sketch folder that required it.

C
70  Forum 2005-2010 (read only) / Exhibition / Re: SD/MMC From the ground up on: February 25, 2009, 03:19:08 am
You're right, my bad! I'll amend the code asap.

You should be able to drive the card as fast as Arduino can go without any problems.

71  Forum 2005-2010 (read only) / Exhibition / Re: SD/MMC From the ground up on: February 20, 2009, 09:54:34 am
Thanks! I looked today and I think I'll have to spend some time working out how to edit the wiki..!
72  Forum 2005-2010 (read only) / Exhibition / Re: SD/MMC From the ground up on: February 20, 2009, 08:19:12 am
It works without a problem on lady ada's wave and GPS shields. I haven't experienced the official ethernet shield but I'd be very surprised if it used different pins, as the connections are defined by the Arduino's hardware SPI pin-out which is fixed.

I will put this up in the playground, I think.

73  Forum 2005-2010 (read only) / Exhibition / Re: SD/MMC From the ground up on: February 20, 2009, 06:34:00 am
You're right! I should have mentioned that I'm taking MMC to mean all varieties: maxi, midi, mini, micro, nano, femto, and bob.

If you're feeling pushed for time and/or cash then you could also  solder directly to the card, wires or a pin header - its connectors have standard .1" pitch. I feel dirty for just saying that.

Hello World coming up. I'll try to abstract it to show the required software components as opposed to the use of a library.

74  Forum 2005-2010 (read only) / Exhibition / Re: SD/MMC From the ground up on: February 20, 2009, 05:24:41 am
Links:

Original thread: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1206874649

MMC Product Manual: http://www.sandisk.com/Assets/File/OEM/Manuals/ProdManRS-MMCv1.3.pdf

MMC/uFat2 and Deviceprint: http://arduinonut.blogspot.com/2009/02/libraries.html

The Roland: http://www.roland-riegel.de/sd-reader/index.html

AdaFruit: http://www.ladyada.net/make/waveshield/download.html

SD2IEC: http://sd2iec.de/

SPI introduction: http://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus

MMC card information at Elm: http://elm-chan.org/docs/mmc/mmc_e.html

Fat module at Elm: http://elm-chan.org/fsw/ff/00index_e.html

MMC card information at retroleum: http://www.retroleum.co.uk/mmc_cards.html

Voltage divider theory: http://en.wikipedia.org/wiki/Voltage_divider

Floppy-connector socketry: http://uanr.com/sdfloppy/

Thanks for reading!  8-)
75  Forum 2005-2010 (read only) / Exhibition / Re: SD/MMC From the ground up on: February 20, 2009, 05:24:05 am
<Continued>

Once the hardware is in place you'll need some software to drive it. As I said previously I'm hoping that people will contribute their code and experiences to this thread - I have only ever used one library to drive the card transfers. This was something that I adapted from the wonderful code of the SD2IEC project. I can't talk about 'The Roland Library' or any other as I don't know them. They should all be pretty much interchangable though.

For persistent storage on a card feel free to invent your own system. Reading and writing to the raw sectors is usually only a function call away. This is the least-cost entry into the storage arena. It's simple and reliable and you are in full control. But you will pay the price when it comes to moving the data around. You'll require raw sector access to the card from your computer which is certainly possible but inconvenient.

If you want to be able to log data and have it transferrable to your computer, then you'll need to  be able to use the file system to some extent or other. This is a whole order of magnitude more complex than even the low level card protocols. Cards may be formatted with a number of filing systems, though generally you'll see one of the FAT (tm, probably) family.

This format uses tables of linked lists of cluster offsets (the File Allocation Tables or FATs) which can be used in turn to locate sectors. Clusters are a collection of multiple sectors, and the sectors per cluster count can vary depending on the formatting.
  • FAT12 is the oldest format out there. I still see cards formatted like this though, even today. It uses 12 bits to describe cluster offsets in the tables. It's limited to cards of up to 32Mb.
  • FAT16 is the most common. So common it's usually referred to as just FAT. It uses 16 bit tables and can describe the layout of cards up to 2Gb.
  • FAT32 is the daddy. If you need a 2Tb card, you'll need FAT32. As you've probably guessed it uses 32bit values for cluster offsets.
Libraries do exist for talking to a FAT formatted device in the language of files. These are excellent for the times when you need that level of access and ease of use. They do tend to weigh in quite heavily though. In order to use a full filesystem approach you'll more than likely need one of the new ATMega328s, with their upgraded RAM and flash quotas, in your board.

Another approach is to swallow some small restrictions and use the very minimum of file system in order to use raw sector access to access your data whilst still retaining the ability to move files between Arduino and computer. uFat is a library that I wrote to do just this.

Just what restrictions might be necessary to go the low FAT route?
  • The donor/target file must be contiguous. When you delete or truncate files on a computer the sectors allocated to them are returned to a pool to be re-used when you next create or expand a file. This can mean that a file occupies sectors scattered all over the card. This is known as fragmentation, and it's why we have drive defragmenters. If you write to a fragmented file using raw sector access you might write over other unrelated data on the filesystem. Or the data you wrote won't be visible when you read the file on your computer. How to get around this? Format the card, create the donor/target file on the computer containing enough data to satisfy your needs and then copy it over to the card.
  • Target files should reside in the card root directory. No subdirectories are allowed - the code to traverse subdirectories is huge compared to the rest of the library and its inclusion is largely unneccessary. The root directory can hold 512 files, more than enough for most datalogging applications I suspect.
  • No long filenames. Stick to 8.3 and all will be well. Just like directories, the LFN system is built (some may say hacked, I couldn't possibly comment, ahem) upon the existing directory structure using other directory entries to hold the additional information. Again, I don't think the additional memory usage is contributing to anything sufficiently valuable.
If you recall MMC sector transfers happen in bursts of 512 bytes. This isn't much fun if the data you're writing is of differing length packets. You'd have to keep track of your buffer usage and flush it to card at the right time. Plus, you'll need some extra help to get string output into a file instead of raw binary.

On top of (to the side of?) uFat I've reworked some code by bobemoe and produced DevicePrint, a hardware-agnostic library which enables formatted string output to any sector-based device. This library uses the newly-abstracted Print class available in Arduino-0012 and above. You get the same useful interface that you're used to using with the Serial class.

These libraries should provide you with most of your required daily intake of vitamins and minerals. If in doubt call your medical practitioner.

I think that's as much as I can say on this matter, I look forward to the conversations ahead. Huge thanks go to everyone who's contributed to my understanding of this subject and those who have helped me develop this code by using it!

Charlie

<Next>
Pages: 1 ... 3 4 [5] 6