Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
Discussion options

Hello everybody,

I was doing some acquisition tests, real-time audio processing and saving the resulting files (raw and processed data)
Thanks to recent help from the community, I was able to acquire the frequencies of interest.

As for the SPI protocol, I'm having a lot of difficulty on the Sparkfun Samd51 Thing Plus microcontroller, as I'm not able to mount the SPI.

This was the code that I'm using with Samd51 Thing Plus (only working with SoftSPI, didn't work with SPI):

from machine import Pin, SoftSPI

def MountSD():
     # Configure the pins -- 3.3V(OUT) red / GND black
     SD_MOSI = Pin('D11', Pin.OUT) # yellow
     SD_SCK = Pin('D13', Pin.OUT) # green
     SD_CS = Pin('D10', Pin.OUT) # blue
     SD_MISO = Pin('D12', Pin.IN) # white
    
     # Start SPI bus - only SoftSPI worked
     spi = SoftSPI(baudrate=500_000, polarity=1, phase=0, sck=SD_SCK, mosi=SD_MOSI, miso=SD_MISO)
    
     # Configuration of the CS (Chip Select) pin for the SD card
     cs = SD_CS

     # Mount SD card
     sd = sdcard.SDCard(spi, cs)
     vfs = os.VfsFat(sd)
     os.mount(vfs, '/sd')

What surprised me was the time it took to save the array on the micro SDCard, using SPI. From my tests, it took 7s to save twelve ".npy" arrays, being in total 23.2kb, being far from the speed of the Class 10 SDCard (10Mb/s).

SPI in Teensy 4.1:
I also had proportional performance on a Teensy4.1, taking 700ms to save the same amount of data.

    spi = SPI(0,
              baudrate=10_000_000,
              polarity=0,
              phase=0,
              bits=8,
              firstbit=SPI.MSB)

From what I saw the SoftSPI method would be limiting the baudrate to 500_000, while the SPI could be possible to save at 10_000_000 for a Class 10 card or up to the limit of 24_000_000. (SPI protocol in Teensy 4.1 also not reaching the expected speed?)

Question 1, how should I made the SPI protocol correctly?
(I tried to repeat some codes I found, but they didn't work, https://docs.micropython.org/en/latest/samd/quickref.html#software-spi-bus)

Question 2: would these speeds in the order of Mb/s be possible with the SDCard + SPI or would I need another protocol and wiring to reach these speeds?

Question 3: would even higher speeds be possible? Using a V90 card? Like 90 to 300Mb/s for writing?

Question 4
Something that I really don't understand, inspecting the files, it displays 23.2kB in size and 384kB in "size on disk", almost 15 time more than the expected (real) size. (Teensy 4.1 also used up this much larger disk space, of the same size)
Would I need to adjust something in the micropython firmware to avoid what appears to be an additional expense in terms of size?

I Thank to anyone who can clarify a little more about this subject.

You must be logged in to vote

This little script works here with a Sparkfun SAMD51 Things Plus and a simple SD card breakout. You do not have to initialize the Pin objects or the baud rate, because that will be done by sdcard.py. So you can as well write:
spi = SPI(1, sck="D13", mosi="D11", miso="D12"). Only cs must be provided as Pin object, but will be set up by the driver.

You can however specify a baudrate in the SDCARD constructor, which will be used by the driver. The highest value you can use with SAMD51 is 24MHz. I achieved a data rate of up to 0.5 MByte/s with 50k data blocks.

from machine import Pin, SPI
import sdcard
import os

if 1:
     # Configure the pins -- 3.3V(OUT) red / GND black
     SD_MOSI = Pin(…

Replies: 2 comments · 6 replies

Comment options

With the selected pins for MOSI/MISO/SCK, Hard SPI device 1 works.
spi = SPI(1, baudrate=500_000, polarity=1, phase=0, sck=SD_SCK, mosi=SD_MOSI, miso=SD_MISO)
See https://docs.micropython.org/en/latest/samd/pinout.html#sparkfun-samd51-thing-plus-pin-assignment-table.

The MIMXRT port has built-in SD card support. So no need to use the Python SD card driver. When the SD card is inserted, it mounts the SD card on boot. Depending on the block size and card type, I get transfer rates up to 10 MByte/s. Using sdcard.py and SPI bus, the speed will stay limited.

Question 3: Possibly no

Question 4: That seems to be related to the FAT file system on not the respective ports. How did you inspect the files? Which block size has the file system on the card you use? With FAT, each file allocates at least one block.

You must be logged in to vote
3 replies
@LeandroFernandes88
Comment options

robert-hh, Thanks for the quick response.

py spi = SPI(1, baudrate=500_000, polarity=1, phase=0, sck=SD_SCK, mosi=SD_MOSI, miso=SD_MISO)
It hasn't worked yet, I'll test with other firmwares for samd51 to try to achieve the highest speed supported by the class 10 sdcard.

In Teensy4.1, I used the SD card slot, I didn't know it would mount automatically nor how to configure it, it was actually much faster!!

Below is a printout with an example of the problem with both microcontrollers, each saved file is taking up 32kb, even though it is substantially smaller.
One possibility I thought of to minimize the problem, was to combine the 3 arrays into 1 (appended) and then separate them in the computer's Python when analyzing the data.
Another alternative would be to control this "minimum" disk size, for example to 1kb, would this be possible? Would it have an adverse impact when saving files?

Print File Size

Once again, thank you for the clarity in your response.

@LeandroFernandes88
Comment options

If you have any tips on saving file size when writing the sdcard.
Thank you in advance.

@robert-hh
Comment options

It seems that the SD card is formatted with a allocation unit size of 32k. When you format the SD card, you can at least with Windows select the size of the allocation unit. There you can try to select a smaller size.

Comment options

This little script works here with a Sparkfun SAMD51 Things Plus and a simple SD card breakout. You do not have to initialize the Pin objects or the baud rate, because that will be done by sdcard.py. So you can as well write:
spi = SPI(1, sck="D13", mosi="D11", miso="D12"). Only cs must be provided as Pin object, but will be set up by the driver.

You can however specify a baudrate in the SDCARD constructor, which will be used by the driver. The highest value you can use with SAMD51 is 24MHz. I achieved a data rate of up to 0.5 MByte/s with 50k data blocks.

from machine import Pin, SPI
import sdcard
import os

if 1:
     # Configure the pins -- 3.3V(OUT) red / GND black
     SD_MOSI = Pin('D11', Pin.OUT) # yellow
     SD_SCK = Pin('D13', Pin.OUT) # green
     SD_CS = Pin('D10') # blue
     SD_MISO = Pin('D12', Pin.IN) # white

     # Start SPI bus
     spi = SPI(1, sck=SD_SCK, mosi=SD_MOSI, miso=SD_MISO)

     # Configuration of the CS (Chip Select) pin for the SD card
     cs = SD_CS

     # Mount SD card
     sd = sdcard.SDCard(spi, cs, baudrate=24_000_000)
     vfs = os.VfsFat(sd)
     os.mount(vfs, '/sd')

The Sparkfun SAMD51 Thing Plus has as well three pins labeled MOSI, MISO, and SCK between D0 and A4 . The labels are somewhat hard to read. For these the SPI object can be created with:
spi=SPI(4, sck="SCK", mosi="MOSI", miso="MISO")

You must be logged in to vote
3 replies
@LeandroFernandes88
Comment options

Setting 1 provided a much more viable write speed. Thank you very much.
(SPI4 works as well, but if less speed)

@robert-hh
Comment options

The if 1 is a subtle change. I replaced it for def MountSD() during my tests. It may be important, because otherwise the sd, vfs, spi and cs objects are subject to garbage collection once the function MountSD is finished.
SPI1 and SPI4 should run at the same speed.

@LeandroFernandes88
Comment options

robert-hh

Please, could I ask you something again?

I am encountering a lot of problems accessing the SD card from different microcontrollers.
My first approach was to create a function to establish the pinout, SPI communication and mount '/sd'. I left the card open while I created folders and saved files for testing.
In the future, I intend to leave the microcontroller running the code in an infinite loop, until it has enough energy.

Would it be appropriate to leave the card open like this, or does it have an impact on energy consumption and even damage the card or the microcontroller itself?
I stopped Thonny and removed the USB cable, but I realized that even though I stopped, the wiring in the microcontroller was still powered and as I hadn't given the command to disassemble the drive, could this cause a problem in future executions of the code?
os.umount('/sd')

Or would the best approach be to insert the mounting of the SD card into the main code (to avoid the problem of data being lost by gc etc.), and mount and dismount as needed? ex:

SD_MOSI = Pin('MOSI', Pin.OUT) # yellow - D11 config SPI(1...)
SD_SCK = Pin('SCK', Pin.OUT) # green - D13
SD_CS = Pin('D10') # blue - D10
SD_MISO = Pin('MISO', Pin.IN) # white - D12

# Start SPI bus
#spi = SPI(1, sck=SD_SCK, mosi=SD_MOSI, miso=SD_MISO)
spi = SPI(4, sck=SD_SCK, mosi=SD_MOSI, miso=SD_MISO)
#spi = SoftSPI(baudrate=500_000, polarity=1, phase=0, sck=SD_SCK, mosi=SD_MOSI, miso=SD_MISO)

# Configuration of the CS (Chip Select) pin for the SD card
cs = SD_CS

# Mount SD card
sd = sdcard.SDCard(spi, cs, baudrate=10_000_000)
vfs = os.VfsFat(sd)
os.mount(vfs, '/sd')

# do something, create a folder and save files

os.umount('/sd')

whileTrue:
     if button_pin.value():
         ...
         os.mount(vfs, '/sd')
         # do something, create a folder and save files
         os.umount(vfs, '/sd')

Once again I thank you for your help.

Answer selected by LeandroFernandes88
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Category
🔌
SAMD
Labels
None yet
2 participants
Morty Proxy This is a proxified and sanitized view of the page, visit original site.