SD Card Adaptor Timeout Error

Hi Everyone,
I have one of these SD Card adaptors and I’m trying to run the sample code on the same page. I’m using a Pico w for the test.

When I execute the code it sits for over 30 seconds then exits with the following error.
File “sdcard.py”, line 150 in init_card_v2
OSError: time-out waiting for v2 card
From the description on the above page the pins are numbered left to right when the reader is on my bread board.
1 VCC,3v3 → 3v3(out)
2 CS → GP 13
3 MOSI → GP 15
4 CLK → GP 14
5 MISO → GP 12
6 Gnd → Gnd
This appears to be what is specified in the code but CLK is written as sck. I hope that is correct.
I’m using a 32GB SD card formatted with Fat32 file system with only one file in the root directory. It should be a reasonable quality card (Samsung 32 EVO plus) and it reads and writes no problem on my pc.
I also tried a 64GB card but didn’t really expect that to work.
I’m stuck now on what else to try. Anyone got any ideas?

2 Likes

Checked your pic closely and the wiring looks correct as far as I can tell.
Pin labels on the board would help, but then what can you expect for $1.15.
The code looks ok too with correct pin assignments.

Maybe try swapping the MOSI & MISO wires, have found them to be labelled wrong in the past.
Or it could be a dud board being so cheap.

Cheers
Jim

EDIT: It might be worth it to look at the Makerverse SD card reader/writer or something else.

2 Likes

Hi James,
The code is on the product page.
The required library is linked on the product page. It’s just one file. The only thing have changed it to add debugging stuff. I’ll have another look later today. I’ll also try another sd board it’s just the waiting for the mail man that is a bit of a drag. :cowboy_hat_face:

Edit
I have swapped the wires on mosi (pin 15) and miso (pin 12) and the error when I ran the test is “OSError: no SD card” so I swapped them back.

In the library sdcard.py I see lots of commands being sent to the SD card within the method init _card_v2(self).
In one command it expects the result 0 but it receives the result 5
If self.cmd(41, 0x40000000, 0) == 0:
I’m not sure where to find what these commands and results mean.
It basically tests this command 1000 times before it times out.
Thanks
David

PS The fact it returns a 5 and not an error tells me the problem is likely to be in the code. More debugging required. If/when I find the problem I’ll post the solution and how I got there.
I doubt anyone here will crack this one unless they can reproduce the problem on their own device.

3 Likes

I found some great details here on how the conversation between the host computer and the SD card works. Some of the logic is a bit odd, like if it doesn’t understand “this command” then it must be a V1 card. :cowboy_hat_face:
http://www.rjhcoding.com/avrc-sd-interface-3.php

Lots of detail here as well
http://elm-chan.org/docs/mmc/mmc_e.html

Basically after the card receives the ACMD41 cmd it will return a 1 if the card is idle and return a 0 if it’s ready. Keep sending the command until a 0 is returned. My card returns a 5. I can’t find what that means.
I have a 16 GB card on order to see if that will do anything different.
Hopefully that will rule something out.
David

1 Like

Hey @David191372,

This is a bit of a puzzling issue. Your conclusion that the response of 5 may be a cause or symptom of the issue with the SD card seemed correct at first. I used one of our off-the-shelf models to test this exact code, and print the response from that function.

My SD card setup is identical to yours, however the SD card is successfully written to, and I also receive “5” as the output to the function. I can send you pictures of this setup if you would like.

My thoughts for the 5 output are that it could be related to number formatting. I primarily code in C so my immediate assumption when I see a weird number is that it is meant to be in a different format (binary or hex for example). But at the end of the day I am not sure.

You say that your code is identical to the example code, it may help to send your version over. I always get someone to double check my code in this case, since you seem to have ruled everything else out, but you may be right that the board is just a dud.

1 Like

Hi Zach,
Ok here is the code I’m testing with and the debug output Im getting.
I know it seems like overkill but this is how I debug all my code.
sdcard.zip (4.6 KB)
debugLog.zip (2.3 KB)
sdCardTest.zip (2.1 KB) (Updated)
debug.zip (3.2 KB)
sdcard.py is the library with the added debug output.
sdCardTest.py is the test code from the product page with added debug output.
The output is to the console and to a file named debuglog.csv

The 5 in the cmd response could be some bit masked thing but the code clearly expects a 1 which makes it loop and try again and a 0 is success.
I’m keen to hear what you think.
David

Edit
From this link above
http://elm-chan.org/docs/mmc/mmc_e.html
I spotted this section which does indeed describe a bit based response


So a 5 would be 00000101
So that would indicate to me “Illegal Command” and “In Idle State”.

2 Likes

Zach,
I missed your offer of a picture of your set up first time I read through.
That would be great to see.
Thanks
David

Hi @David191372,

Here are some pictures of my setup


It is functionally identical to your setup.

When I tested the basic test code yesterday (on the website, without your debug code), it was working just fine. I tested it again this morning and nothing has changed.

I was going to test your code but I believe I am missing some libraries, as I am getting errors importing. Originally the error was with “import constants”, after installing the constants library it is throwing another error. Could you send a list of libraries/dependencies you’re using? Just saves me the trouble of going through them one by one. Thanks!

One more thing, I noticed in SDCardTest.py that you are still using/uploading the ADC sensor reading. This should work perfectly fine, though in my test code I changed this to an integer value to eliminate some errors, could be worth trying. Likely not the cause of the issue, but who knows, the 0 reading could be somehow decrementing and overflowing. Doesn’t normally happen in python but worth a shot.

Hope this helps!

2 Likes

Hi Zach,
My mistake with the code. I removed the requirement for my constants.py then uploaded the old file.
Here is the correct one. I’ll also try and edit my post above to correct that file as well.
sdCardTest.zip (2.1 KB)

The ADC sensor thing is after the init procedure has already failed so that’s not the problem.
I’m a little confused how you say you are running the same code as me and receiving the same “5” response yet your code succeeds.
Clearly the only success response is a 0.
I’m keen to see your debug output when you get my code to run.
Thanks
David

1 Like

Hi David,

Gald to hear you’ve gotten things working. Let us know if you run into any other bumps in your project, we’re here to help!

Hi Zach,
You must have read my last message with an optimistic eye :cowboy_hat_face:
It’s not working I just fixed the problem that stopped you from running my debug code.
As i said im curious how your works when you also receive the same 5 return code when the only valid code is a 0
David

Hi David,

That was me, I just hadn’t realised that I wasn’t quite signed in.

I’ve had a look at your code and after some small tweaks I think having it at least prints what it is saving. I used 2 different cards. The first one was problematic hence the high count in the debug counter. I am saving values to the card, and the counter hasn’t gone up since.

After importing libraries for ADC and time into your test script, I also changed this line in your edited SD library from

_CMD_TIMEOUT = const(1000)

to

_CMD_TIMEOUT = const(3000)

At 1000 it wasn’t detecting a card, it can probably be lower but this worked for me.
SDPicoW.zip (6.1 KB)

Hi Jack,
That’s interesting, I notice in the debug log you sent in the zip, that your Sd card successfully initialises (returns 0) on the second attempt of cmd 41, on line 25 of the debug log.
So I copied your updated code to my pico and let it run all 3000 iterations with the same 5 result which I was kind of expecting.
Do you have the same Sd card board that I’m using?

I notice this text from the link above and I’m not sure which bits I should be testing. Especially the bit about the pull up resistor or which mode is being used.
Extract…

SPI Mode

Minimal configuration for SPI mode

This document describes about SPI mode to control the MMC/SDCs. The SPI mode is an alternative operating mode that defined to use the MMC/SDCs without a native host interface. The communication protocol of the SPI mode is slightly simple compared to its native operating mode. The MMC/SDC can be attached to the most microcontrollers via a generic SPI interface or some GPIO ports. Therefore the SPI mode is suitable for low cost embedded applications with no native host interface is available. There are four different SPI modes, 0 to 3, depends on clock phase and polarity. The SPI mode 0 is defined for SDC. For the MMC, it is not the SPI spec, both latch and shift operations are defined with rising edge of the SCLK, but it seems to work at mode 0 at the SPI mode. Thus the SPI mode 0 (CPHA=0, CPOL=0) is the proper setting to control MMC/SDC, but mode 3 (CPHA=1, CPOL=1) also works as well in most case. A pull-up on the DO cannot be omited, or some cards will fail initialization process.
IMG_0316
… End Extract

Update:
I tried enabling the internal pull up resistor on GPIO 12 (miso) like this in line 14 sdCardTest.py
Before
spi = SPI(1,sck=Pin(14), mosi=Pin(15), miso=Pin(12))
After
spi = SPI(1,sck=Pin(14), mosi=Pin(15), miso=Pin(12,Pin.IN,Pin.PULL_UP))

But that didn’t make any difference.
I’m running out of ideas now. Next I’ll try a different SD card when it arrives in the post :slight_smile:
If that doesn’t work I’ll try a different card adapter.
David

Hey @David191372,

This issue keeps getting weirder! Jack’s code output is 0 as it successfully initialised the card as you mentioned. I agree that it doesn’t make a whole lot of sense but I can guarantee you my code was outputting a 5 but still successfully initialising the card. Jack tried multiple cards and multiple boards (all the same one, and identical to yours) and had it successfully writing with both a 5 and a 0 (on two separate boards I believe). He also received a 275 as the output at one point, but that unsurprisingly was not working correctly. I’ll see about running that new code and getting the debug uploaded.

I may be able to try the aforementioned pull-up resistor on the MISO pin. Stay tuned.

Hi Zach,
I’d be interested to see how your process is getting past this bit without returning a zero from cmd 41 as everything else is a timeout error.
The debug output should show the programs execution path.

if self.cmd(41, 0x40000000, 0) == 0:
self.cmd(58, 0, 0, 4)
self.cdv = 1
# print(“[SDCard] v2 card”)
return
raise OSError(“timeout waiting for v2 card”)

My replacement SD card has arrived. I’ll test it later on this evening.
Thanks again for your interest.
David

Well my new San Disk Ultra 16GB SD card worked but I don’t understand why.
The CMD 41 succeeded with a result 1 not 0.
I removed the demo sensor stuff and simply wrote “Hello World” to the SD card no problem. Not sure why the original SD card is not compatible but it doesn’t really matter.
This is the non functional Sd

I guess we can call it solved.
For completeness here is the debug output if anyone is interested.
David

Debug Version=1.1
Count Level MethodName Details
==================================================================================
1 01/01/2021 00:36:09 1 sdCCartTest Start
2 01/01/2021 00:36:09 1 main Pre spi=
3 01/01/2021 00:36:09 1 main Pre sc=
4 01/01/2021 00:36:09 1 main Pre sd=
5 01/01/2021 00:36:09 1 __init__() SDCard Start
6 01/01/2021 00:36:09 1 init_card() Start
7 01/01/2021 00:36:09 1 init_spi(self,baudrate) Start
8 01/01/2021 00:36:09 1 init_spi() baudrate=10000
9 01/01/2021 00:36:09 1 init_spi() attributes=['__class__', 'read', 'readinto', 'write', 'LSB', 'MSB', 'deinit', 'init', 'write_readinto']
10 01/01/2021 00:36:09 1 init_spi() AttributeError='SPI' object has no attribute 'MASTER'
11 01/01/2021 00:36:09 1 init_spi() on ESP8266
12 01/01/2021 00:36:09 1 init_card() CMD0 i=0
13 01/01/2021 00:36:09 1 init_card() CMD0 i=1
14 01/01/2021 00:36:10 1 init_card() Idle State=1
15 01/01/2021 00:36:10 1 init_card() Determine Card Version
16 01/01/2021 00:36:10 1 init_card() r=1
17 01/01/2021 00:36:10 1 init_card_v2() Start
18 01/01/2021 00:36:10 1 init_card_v2() _CMD_TIMEOUT=1000
19 01/01/2021 00:36:10 1 init_card_v2() i=0
20 01/01/2021 00:36:10 1 init_card_v2() Capacity CMD 58 Result=1
21 01/01/2021 00:36:10 1 init_card_v2() CMD 55 Init Result1=1
22 01/01/2021 00:36:10 1 init_card_v2() CMD 41 Init Result2=1
23 01/01/2021 00:36:10 1 readinto() Start
24 01/01/2021 00:36:10 1 init_card() csd=bytearray(b'@\x0e\x002[Y\x00\x00v\xb2\x7f\x80\n@@\x13')
25 01/01/2021 00:36:11 1 init_spi(self,baudrate) Start
26 01/01/2021 00:36:11 1 init_spi() baudrate=1320000
27 01/01/2021 00:36:11 1 init_spi() attributes=['__class__', 'read', 'readinto', 'write', 'LSB', 'MSB', 'deinit', 'init', 'write_readinto']
28 01/01/2021 00:36:11 1 init_spi() AttributeError='SPI' object has no attribute 'MASTER'
29 01/01/2021 00:36:11 1 init_spi() on ESP8266
30 01/01/2021 00:36:11 1 main Pre sd mount
31 01/01/2021 00:36:11 1 octl() Start
32 01/01/2021 00:36:11 1 readblocks() Start
33 01/01/2021 00:36:11 1 readinto() Start
34 01/01/2021 00:36:11 1 readblocks() Start
35 01/01/2021 00:36:11 1 readinto() Start
36 01/01/2021 00:36:11 1 readblocks() Start
37 01/01/2021 00:36:11 1 readinto() Start
38 01/01/2021 00:36:11 1 main Post sd mount
39 01/01/2021 00:36:12 1 main Pre listdir
40 01/01/2021 00:36:12 1 readblocks() Start
41 01/01/2021 00:36:12 1 readinto() Start
42 01/01/2021 00:36:12 1 main dirlist=['adcData.txt']
43 01/01/2021 00:36:12 1 writeblocks() Start
44 01/01/2021 00:36:12 1 write() Start

Cut…

1 Like

Look at that. I was using Zach’s setup just with different SD cards. It seems this debugging code is great at picking out errors with our cards more than the code.

Glad to see you’re saving data. Hopefully your project travels more smoothly from here

1 Like

I’m an old programmer but relative new to python.
Can anyone tell me how this code is succeeding?

This is from the debugging output above.

21 01/01/2021 00:36:10 1 init_card_v2() CMD 55 Init Result1=1
22 01/01/2021 00:36:10 1 init_card_v2() CMD 41 Init Result2=1
23 01/01/2021 00:36:10 1 readinto() Start

Time passes……. Ah I see it now!

        if(DEBUG >=1):
            initResult1=self.cmd(55, 0, 0) # Application Specific Command coming up
            initResult2=self.cmd(41, 0x40000000, 0)
            debug.debug(DEBUG, "init_card_v2()", "CMD 55 Init Result1="+str(initResult1), LOGTOFILE)
            debug.debug(DEBUG, "init_card_v2()", "CMD 41 Init Result2="+str(initResult2), LOGTOFILE)

        self.cmd(55, 0, 0) # Application Specific Command coming up
        # Card returns 'in_idle_state=0' when card is ready.
        if self.cmd(41, 0x40000000, 0) == 0:
            self.cmd(58, 0, 0, 4)
            self.cdv = 1
            # print("[SDCard] v2 card")
            return
    raise OSError("timeout waiting for v2 card")

I execute CMD 41 and out put the result
Then I execute CMD 41 again for the “if” statement.
The first time it returns a 1 but the second it must return a 0.
That explains it
David

3 Likes