Shop OBEX P1 Docs P2 Docs Learn Events
SD Card Speed - Page 8 — Parallax Forums

SD Card Speed

1456810

Comments

  • There are a couple things you're doing that are probably unintentional:
    int val[1000];   // This is declaring an array of integers (4-bytes per int)
    
    [[ snip ]]
    
      // This loop is counting from 1, but should be counting from zero, or you'll write past the end of the array
      for(i=1; i<1000+1; i+=2)
      {
        val[i]=1;
        val[i+1]=0;
      }
    
      [[ snip ]]
      // this loop is writing 1000 4-byte quantities to the file
      for(i=1;i<1000+1;i++)
      {
        fwrite(&val[i], sizeof(val[i]),1,fp);
      }    
      fclose(fp);
    

    Try pasting this into your code in place of your SD file create part and see what happens:
    //Generate the file data a clock for the ClearPath motor
    
      for(i=0; i<512; i++ )
      {
        Buffer[0][i] = i & 15;  // write the low 4 bits of the loop index into one of our temp buffers
      }
    
      print("Start Program.\n");
    
    //Write data to SD memory      
    
      FILE* fp = fopen("test.txt", "wb"); // Open a file for writing
    
      for(i=0;i<1024;i++)    // write 512 bytes per iteration to the SD file, for a total of 512kb
      {
        fwrite(Buffer[0], 1, 512, fp);
      }    
      fclose(fp);
    
    //End writing data to the SD Memory 
    

    I do notice one issue in the code that's mine - Once the reader finishes pushing data into the buffer, it sets a flag telling the other thread that it's finished. The other thread will stop running the next time it finishes writing a buffer, even if there is still data to send. Padding the file with 2048 zero bytes will fix that. Replacing these lines in the OutputDataThread function should fix it too, but I'll have to double check when I get home.
      // the output loop - keep going until we're told not to, and have no more data to send
      while( StopSending == FALSE || BufferFull[bufferToSend] == TRUE )
      {
    
  • Jason...I made the changes you requested in my memory data write portion of the program and made the change to the "while" instruction in your program.

    The scope is monitoring p0 and the signal is also sent to the motor. Everything compiled properly but there are no pulses on the scope and no rotation of the motor.

    Discovery
  • I'll try to take a look at it this evening.
  • Okay...Thanks.

    Discovery
  • Ok, this one works, tested on a scope.

    I think there were two different problems here - One, you were initially testing with very short data bursts that didn't even cycle the buffers once, and I never expected that case would happen in real life, so I didn't code for it.

    The second was harder to fix - I think the timing in the inner loop is so tight at 53khz in CMM mode that adding even an extra check was pushing it over the limit and causing it to stall. Compiling as LMM code should fix that, and I changed the print() commands to printi() because they take less code space.

    The way I set up the test file, it toggles pins 0, 1, and 2 at different rates, and pin 3 is toggled once per buffer (low, then high) making it easy to see how many 512-byte chunks are being emitted if you have a capture scope.
    c
    c
  • Jason...Very good, thank you. I will load the code and test it on my equipment.

    I imagine you would save data to the SD memory differently as opposed to the Parallax\Learn\SD memory code. Is there an easy way to write data to the SD memory faster?

    Discovery
  • Jason...The results of the test are:
    (1) p3 output immediately goes HIGH
    (2) 0123 are printed to the screen
    (3) After 1 minute and 48 seconds p0 output goes HIGH
    (4) After 2 minutes 42 seconds p1 goes HIGH and p0 goes LOW
    (5) After 4 minutes and 44 seconds p2 goes HIGH and p0 goes LOW
    (6) After 5 minutes and 36 seconds p0 goes HIGH
    (7) As time goes by p0, p1, and p2 change state with several minutes between state changes
    (8) LED p26 never illuminates
    (9) p3 never goes LOW
    (10) Symbols "X" and "E" are never printed

    Discovery
  • You're going to have to figure out how to put SimpleIDE into "project view mode" then, because you probably need to change a compiler option to enable the optimizer.

    As a simpler test, try lowering the output rate to 20000 and see if that behaves as expected. (Just change the 53000 in the output thread to 20000)
  • Jason...Results are the following:
    20000 p0,1,2,3 HIGH p26 HIGH

    10000 Signal output on p0,1,2
    01230123E p26 pulsed

    15000 Same results as 10000

    17000 Signal pulses on p0,1,2 p3 always HIGH p26 HIGH
    after 2 minutes pulses on p0,1,2 p26 pulsed
    01230123E

    16000 Same results as 17000

    18000 Pulses on p0,1,2 p3 HIGH always
    pulsed p26
    0123
    01230
    012301
    0123012
    01230123
    01230123E All occurring about 2 minutes apart
    After 10 minutes p0,1,2 went LOW while p3 remained HIGH

    After examining all the pop up windows on SimpleIDE, I could not find any way in the world to switch to "project view mode" or change the compiler option to enable the optimizer. They apparently do not exist on this SimpleIDE. Could it be that you have a more sophisticated SimpleIDE than mine?

    Discovery
  • Hi
    On my setup you...

    In SimpleIDE select tools menu
    top of the dropdown menu select project view

    Dave

  • JasonDorieJasonDorie Posts: 1,930
    edited 2017-04-11 17:24
    Here: http://forums.parallax.com/discussion/comment/1363603/#Comment_1363603

    Do that, then on the compiler options tab you can pick CMM with -O2 (speed), or LMM (faster, but bigger). LMM is probably your best choice, but it eats code space pretty quick.

    What's happening is that the loop in the output thread isn't able to run fast enough the way you're compiling it. I record the current clock time, then add the amount of time required for whatever frequency you've chosen. Then I wait for that computed clock time to come around. If the frequency is high enough, the wait time can be quite low. The amount of time to wait before sending the next pulse could be less than the time it takes to complete the loop. If that happens, you miss the computed clock time - it passes before you start waiting, and so you end up waiting for the clock to wrap all the way around. That takes 53 seconds at 80MHz, which explains the super long delays you're seeing.

    If you compile the code in LMM, or in CMM with "optimize for speed", it should be fast enough to run 53khz (I had no issues) with those settings.
  • 1 minute 48 seconds (actually 1 minute 47.37 seconds) is the time it takes for the system counter to wrap 2 times at 80 MHz. You must be compiling without optimization. Look at the bottom of the "Project Manager" window, and it shows the optimization level that you are using. You can view the project window by clicking on the icon in the lower left corner of the SimpleIDE window. You should be using -Os or -O2.
  • I've been following this thread with bewilderment. FSRW and the simple techniques used in .wav players have been mentioned in this thread, even with conversions to C. I'm curious, Jason, on topic of SD card speed, how do these routines you've bitten off for Discovery compare with FSRW/Spin access speeds as achieved in .wav players using pread to fill two buffers and pasm to flip flop between them ?

    Attached: typical result from the speed test that comes along with the OBEX version of FSRW 2.6, clkfreq=80MHz.
    432 x 137 - 29K
  • Guys...
    Under SimpleIDE
    Tools
    Next Tab
    Font
    Bigger Font
    Smaller Font
    Update Workspace
    Properties

    Please note that in this drop down menu THERE IS NO PROJECT VIEW

    In the Properties tab there is:
    GCC Folders (Browers)
    Spin
    General Settings (no view options)
    Highlight (only colors)

    Since I cannot get the settings used in Jason's program...my results don't match his.

    Discovery
  • Guys...My sincere apologies!

    That little icon at the bottom left corner is so faint that I kept miss seeing it.

    I was able to set the speed at twice and the program runs properly.

    I also see where I could have called for compiling in C++.

    Thank you very much.

    Discovery
  • Jason...This is really excellent work! I and my company would like to pay you for your effort. How can we communicate one-to-one rather than to the whole world?

    Discovery
  • JasonDorieJasonDorie Posts: 1,930
    edited 2017-04-11 20:20
    JasonDorie at gmail is the most direct way. Happy to hear you've finally gotten it working.

    Tracy Allen: the reading part is plenty fast enough as is - clocking the data out to the pins in actually the timing sensitive bit - that was the part that was stalling. I was trying to code something simple, without a requirement for Spin or PASM, because the user was trying to use C & SimpleIDE. I'm absolutely sure than something in PASM would be able to push data dramatically faster, but the code posted here is (I hope) relatively simple to understand and modify.

    In CMM, compiled with optimizations, the code hits 53khz output with a bit of time left over. At 53khz, there are ~1500 clock cycles between output pulses, which should be enough time to do a decent amount of work. The inner loop is simple enough that it should easily fit in FCache, though I haven't looked to see if it actually gets compiled that way.
  • Dave HeinDave Hein Posts: 6,347
    edited 2017-04-11 20:59
    Discovery wrote: »
    That little icon at the bottom left corner is so faint that I kept miss seeing it.

    I was able to set the speed at twice and the program runs properly.

    I also see where I could have called for compiling in C++.
    Discovery, glad you found the project window. In trying to make SimpleIDE as simple as possible, Parallax intentionally made it difficult to enable the project window. I think they were concerned it would confuse novices. The result was that it made it more difficult for anyone beyond the novice stage. Maybe a future version of SimpleIDE will make the icon a little more obvious, and allow SimpleIDE to start up with the project window enabled.


  • jmgjmg Posts: 15,148
    Dave Hein wrote: »
    Discovery, glad you found the project window. In trying to make SimpleIDE as simple as possible, Parallax intentionally made it difficult to enable the project window. I think they were concerned it would confuse novices. The result was that it made it more difficult for anyone beyond the novice stage. Maybe a future version of SimpleIDE will make the icon a little more obvious, and allow SimpleIDE to start up with the project window enabled.

    Yes, I completely missed that bizarre lower-left icon placement too. Quite unexpected.
    I've no idea how anyone can have imagined that was 'a good idea'.


  • Jason...I sent you an email but I received an undelivered response. Is there something else required in your address?

    Discovery
  • I sent you a pm.
  • Jason...What is a pm?

    The short burst of data on p0 turns the ClearPath motor quickly but for only a couple of revolutions.

    How can I load the SD memory with say a full load of 2 gigabytes and turn a few more revolutions?

    Discovery
  • Jason...I changed the limit on the "for" loop for generating data from 512 to 2048 and the "fwrite" statement from 512 to 2048 and the ClearPath motor turned four times longer.

    If I increase those two numbers beyond 2048 the program stalls.

    Discovery
  • kwinnkwinn Posts: 8,697
    edited 2017-04-12 18:26
    Discovery wrote: »
    Jason...What is a pm?



    Discovery

    A pm is a private message sent from one forum member to another. Click on the letter icon on the home page.
  • Jason...In addition, I increased the output data rate from 53kHz to 100kHz and the ClearPath motor works fine. An output data rate of 150kHz is detected by the motor processor as a fault. So, I will run the motor at 100kHz.

    Discovery
  • JasonDorieJasonDorie Posts: 1,930
    edited 2017-04-12 19:03
    The for loop filing the data is writing to a temporary buffer that is 512 x 4 bytes in size. Changing the loops larger than that will write outside the buffer and wreak havoc. You could increase the number of times the buffer is written to the disk, but don't change the "512" value.

    I was under the impression that you had a mechanism already to generate these pulses and were simply looking for a way to play them back. Use your existing path generation to produce step and direction pulses, pack those 4 bits into a byte, write a stream of bytes to the SD card.

    It should be noted that writing 2Gb to the SD card is going to take a considerable amount of time if you're doing it from a Propeller chip. Write speed is going to be comparable to read speed, which is about 250kb/sec, or 1mb in 4 seconds.
  • Jason...The mechanism for generating the nibbles was just a test. I may need some help to pack my data into 512 nibbles.

    Discovery
  • JasonDorieJasonDorie Posts: 1,930
    edited 2017-04-12 20:30
    The simplest way to make the test longer is to change this loop:
      //Write data to SD memory      
      fp = fopen("test.txt", "wb"); // Open a file for writing
    
      //CHANGE BELOW
      for(i=0;i<8;i++)    // write 512 bytes per iteration to the SD file, for a total of 64kb
      {
        fwrite(Buffer[0], 1, 512, fp);
      }
      fclose(fp);
    

    That for loop currently does 8 iterations, writing 512 bytes per loop. Increase the loop count from 8 to 2048 to produce a 1Mb file, or to 20480 to produce a 10Mb file, and so on. 512 bytes is the block size for an SD card, so it doesn't really gain you anything to write in larger chunks.

    The C# test app I wrote for the PC ingested GCode and output step and direction pulses based on that. It's very simplistic and doesn't do any motion planning or acceleration handling, but it got the job done.

    For your own purposes, you don't really need to pack the data into packets of 512 bytes at a time. The underlying file code will take care of that for you. You get somewhat better throughput if you make fewer calls to the file code, but that's about it.

    Your code would need to do something like this:
      // Open the file for writing here
      FILE * fp = fopen( "movedata.bin", "wb" );
    
      while( ... )
      {
        // Code to compute motor step / direction values goes here
        // [[[ code ]]]
        // assuming you now have motorXStep, motorXDir, motorYStep, motorYDir values:
        // Step and Dir values are either 0 or 1 - code will fail if other values are used.
    
        char byteToOutput = (motorXStep << 0) | (motorXDir << 1) | (motorYStep<<2) | (motorYDir<<3);
        fputc( byteToOutput, fp );
      }
    
      fclose( fp );
    
  • tritoniumtritonium Posts: 540
    edited 2017-04-13 23:50
    @JasonDorie

    I like the look of the plotter you showed a while ago- mind posting the link to a supplier?
    I have seen some similar, but not quite like that.
    Thanks

    Dave

    ps: after searching ebay it looks like a makeblock, but with your own controller?
  • Jason...Great, thank you. That should do the job nicely.

    Discovery
Sign In or Register to comment.