Run code.py from SD card
Moderators: adafruit_support_bill, adafruit
Please be positive and constructive with your questions and comments.
- blakebr
- Posts: 959
- Joined: Tue Apr 17, 2012 6:23 pm
Run code.py from SD card
Hello,
Is there a way to run programs from an SD card?
Run them directly from the SD card or delete code.py from flash,
copy a program from the SD card on to flash, then reboot the microcontroller.
Bruce
Is there a way to run programs from an SD card?
Run them directly from the SD card or delete code.py from flash,
copy a program from the SD card on to flash, then reboot the microcontroller.
Bruce
- mikeysklar
- Posts: 13945
- Joined: Mon Aug 01, 2016 8:10 pm
Re: Run code.py from SD card
Oddly enough there is a guide for this. It looks like it was influenced from the early CircuitPython boards that were not Express based and were tight on flash.
Let us know if this meets your needs.
https://learn.adafruit.com/micropython- ... on-sd-card
Let us know if this meets your needs.
https://learn.adafruit.com/micropython- ... on-sd-card
- blakebr
- Posts: 959
- Joined: Tue Apr 17, 2012 6:23 pm
Re: Run code.py from SD card
Mike,
I have been able to replicate the REPL results shown in the article.
However I have not been able to use the results in a code.py program.
I can execute a code.py in /sd/ from REPL.
These are some of my failures:
1) I can't import a program in the / directory from a code.py in the /sd/ directory.
2) I can't import a program in the /sd/ directory from a code.py in the / directory.
3) I can't call library functions from the /sd/lib/ directory. Ports etc. opened in the sdmount.py file don't seem to carry into the /code.py file. However they seem to be busy (can't open pin, it is busy from sdmount.py)
4) I can't access the library files in /sd/lib/ directory before I open SD card access requiring some of the files in /sd/lib/. Catch 22!
My sdmount.py file:This is Maker_Pi_Pico_Base.py. The file adds port definitions.I am open to suggestions. TIA
Bruce
I have been able to replicate the REPL results shown in the article.
However I have not been able to use the results in a code.py program.
I can execute a code.py in /sd/ from REPL.
These are some of my failures:
1) I can't import a program in the / directory from a code.py in the /sd/ directory.
2) I can't import a program in the /sd/ directory from a code.py in the / directory.
3) I can't call library functions from the /sd/lib/ directory. Ports etc. opened in the sdmount.py file don't seem to carry into the /code.py file. However they seem to be busy (can't open pin, it is busy from sdmount.py)
4) I can't access the library files in /sd/lib/ directory before I open SD card access requiring some of the files in /sd/lib/. Catch 22!
My sdmount.py file:
Code: Select all
# SPDX-FileCopyrightText: 2018 Jerry Needell for Adafruit Industries
# Modified by B.B.Blake 9/23/2022
# SPDX-License-Identifier: MIT
import sys
import board
import busio
import storage
import digitalio
import adafruit_sdcard
import builtins
# Import the devices and I/O ports on the Maker Pi Pico Board as MPPio
if True: import Maker_Pi_Pico_Base as MPPio
else: MPPio = builtins.__import__(board.board_id)
print("Start")
SCK = MPPio.SCK # board.GP10
MOSI = MPPio.MOSI # board.GP11
MISO = MPPio.MISO # board.GP12
SD_CS = MPPio.SD_CS # board.GP15
# Connect to the card and mount the filesystem.
spi = busio.SPI(SCK, MOSI, MISO)
cs = digitalio.DigitalInOut(SD_CS)
cs.direction = digitalio.Direction.OUTPUT
sdcard = adafruit_sdcard.SDCard(spi, cs)
vfs = storage.VfsFat(sdcard)
storage.mount(vfs, "/sd")
sys.path.append("/sd")
sys.path.append("/sd/lib")
print("Stop")
# Saved code
#sdcard = adafruit_sdcard.SDCard(spi, cs)
#vfs = storage.VfsFat(sdcard)
Code: Select all
#
# Maker_Pi_Pico_Base.py extensions Rev.2
#
# e.g. import Maker_Pi_Pico_Base as MPPio
# e.g. SCK = MPPio.SCK
import board
#
# grove ports (based on port numbers on the silkscreen)
GROVE_1 = (board.GP1, board.GP0)
GROVE_2 = (board.GP3, board.GP2)
GROVE_3 = (board.GP5, board.GP4)
GROVE_4 = (board.GP7, board.GP6)
GROVE_5 = (board.GP9, board.GP8)
GROVE_6 = (board.GP27, board.GP26)
# on-board default SPI for SD card
SCK = board.GP10
MOSI = board.GP11
MISO = board.GP12
SD_CS = board.GP15
# alternate SD card pins names
SD_CMD = board.GP11
SD_DAT0 = board.GP12
SD_DAT1 = board.GP13
SD_DAT2 = board.GP14
SD_DAT3 = board.GP15
# ESP-01 connector (TX on the board is RX on the ESP-01)
ESP_TX = board.GP16
ESP_RX = board.GP17
# buzzer
BUZZER = board.GP18
# headphone connector
AUDIO_LEFT = board.GP18
AUDIO_RIGHT = board.GP19
# buttons
BUTTON_20 = board.GP20
BUTTON_21 = board.GP21
BUTTON_22 = board.GP22
# neopixel
NEOPIXEL = board.GP28
Bruce
- mikeysklar
- Posts: 13945
- Joined: Mon Aug 01, 2016 8:10 pm
Re: Run code.py from SD card
The Maker Pi Pico pin abstractions might be adding a level of complexity at this point. Can you just simplicity to the basics for initial testing? Otherwise your sdmount.py file looks good. As shown with the sdmount_lib.py you should be able to load just the SD module and have access to the entire python library bundle if it is on your SD card.
Code: Select all
spi = busio.SPI(board.GP10, MOSI=board.GP11, MISO=board.GP12)
cs = digitalio.DigitalInOut(board.GP15)
sdcard = adafruit_sdcard.SDCard(spi, cs)
- blakebr
- Posts: 959
- Joined: Tue Apr 17, 2012 6:23 pm
Re: Run code.py from SD card
Mike,
This version of sdmount.py does not work either:When I load it from REPL I get the Start/Stop and the 10 second delay. When I pull and restore power, I do not see the 10 second delay. I can't get putty.exe up on the com: port fast enough to see the Start/Stop. It's like sdmount.py is ignored at power application. What is the boot sequence (boot.py, sdmount.py, code.py, etc.) This is all on a RPi Pico. Looking to put all or most libraries on /sd/lib/.
Bruce
This version of sdmount.py does not work either:
Code: Select all
# SPDX-FileCopyrightText: 2018 Jerry Needell for Adafruit Industries
# Changes by B.B.Blake 9/23/2023
# SPDX-License-Identifier: MIT
import sys
import time
import board
import busio
import storage
import digitalio
import adafruit_sdcard
print("Start")
spi = busio.SPI(board.GP10, MOSI=board.GP11, MISO=board.GP12)
cs = digitalio.DigitalInOut(board.GP15)
cs.direction = digitalio.Direction.OUTPUT
sdcard = adafruit_sdcard.SDCard(spi, cs)
vfs = storage.VfsFat(sdcard)
storage.mount(vfs, "/sd")
sys.path.append("/sd")
sys.path.append("/sd/lib")
print("Stop")
time.sleep(10)
Bruce
- mikeysklar
- Posts: 13945
- Joined: Mon Aug 01, 2016 8:10 pm
Re: Run code.py from SD card
I suspect the guide is missing the key point here which is the sdmount_lib.py example needs to be renamed to “boot.py” for everything to work. Can you give that a try?
boot.py always runs first on startup and is run once.
code.py or main.py follows.
boot.py always runs first on startup and is run once.
code.py or main.py follows.
- blakebr
- Posts: 959
- Joined: Tue Apr 17, 2012 6:23 pm
Re: Run code.py from SD card
Mike,
Renamed sdmount.py to boot.py. No joy in Muddville.
boot.py is opened because it complained it could not find simplio.py and adafruit_sdcard.py.
I put a copy of each in the root directory.
Then I get a error that code.py can't find adafruit_ntp.py. It is in /sd/lib/.
Bruce
Renamed sdmount.py to boot.py. No joy in Muddville.
boot.py is opened because it complained it could not find simplio.py and adafruit_sdcard.py.
I put a copy of each in the root directory.
Then I get a error that code.py can't find adafruit_ntp.py. It is in /sd/lib/.
Bruce
- mikeysklar
- Posts: 13945
- Joined: Mon Aug 01, 2016 8:10 pm
Re: Run code.py from SD card
Bruce,
New approach. Remove the sdmount_lib.py, code.py and boot.py. Let the controller boot to the REPL prompt and manually paste in the sdmount_lib.py line by line. Let’s understand where things are not working.
New approach. Remove the sdmount_lib.py, code.py and boot.py. Let the controller boot to the REPL prompt and manually paste in the sdmount_lib.py line by line. Let’s understand where things are not working.
Code: Select all
import adafruit_sdcard
import busio
import digitalio
import board
import storage
import sys
# Connect to the card and mount the filesystem.
spi = busio.SPI(board.GP10, MOSI=board.GP11, MISO=board.GP12)
cs = digitalio.DigitalInOut(board.GP15)
sdcard = adafruit_sdcard.SDCard(spi, cs) sdcard = adafruit_sdcard.SDCard(spi, cs)
vfs = storage.VfsFat(sdcard)
storage.mount(vfs, "/sd")
sys.path.append("/sd")
sys.path.append("/sd/lib")
- blakebr
- Posts: 959
- Joined: Tue Apr 17, 2012 6:23 pm
Re: Run code.py from SD card
Mike,
boot.py is now boot.py.mike and code.py is code.py.mike ;-) I do not have a boot.txt or code.txt.
Worked without error after I fixed the line:to read:I then got:also this imported without error after a reboot:
If I power reboot, import sdmount, import code.py, code.py works as long as I do not where I get an error. If I don't try to open a connection to /sd, code.py runs just fine. Just very slow (15 seconds) to start.
Bruce
boot.py is now boot.py.mike and code.py is code.py.mike ;-) I do not have a boot.txt or code.txt.
Worked without error after I fixed the line:
Code: Select all
sdcard = adafruit_sdcard.SDCard(spi, cs) sdcard = adafruit_sdcard.SDCard(spi, cs)
Code: Select all
sdcard = adafruit_sdcard.SDCard(spi, cs)
Code: Select all
>>> sys.path
['', '/', '/lib', '/sd', '/sd/lib']
>>>
Code: Select all
import sdmount
Code: Select all
storage.mount(vfs, "/sd")
Bruce
- mikeysklar
- Posts: 13945
- Joined: Mon Aug 01, 2016 8:10 pm
Re: Run code.py from SD card
Bruce,
Paste in the error message you see when you hit this line:
Can you run this command and share the output?
Paste in the error message you see when you hit this line:
Is it this message:storage.mount(vfs, "/sd")
Code: Select all
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
OSError: [Errno 19] ENODEV
Code: Select all
>>>dir(vfs)
- blakebr
- Posts: 959
- Joined: Tue Apr 17, 2012 6:23 pm
Re: Run code.py from SD card
Mike,
The error:Line 148 in code.pyIt looks like vfs, etc. does not carry into code.py. However the board.GPxx definitions leave some residual configuration behind. The question remains why can I read library stuff, but not open to access the SD card?
Also without storage.mount(vfs, "/sd") everything works from REPL.
Bruce
The error:
Code: Select all
Traceback (most recent call last):
File "code.py", line 148, in <module>
NameError: name 'vfs' is not defined
Code: Select all
storage.mount(vfs, "/sd")
Code: Select all
>>> dir(vfs)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'vfs' is not defined
>>>
Also without storage.mount(vfs, "/sd") everything works from REPL.
Bruce
- mikeysklar
- Posts: 13945
- Joined: Mon Aug 01, 2016 8:10 pm
Re: Run code.py from SD card
One minor difference I see in some example code is the switch to single quotes around paths. I don't think will change anything, but why not give it a try since the code is erroring out on the mount line about vfs not being defined.
https://docs.circuitpython.org/projects ... tion-notes
https://docs.circuitpython.org/projects ... tion-notes
Code: Select all
vfs = storage.VfsFat(sdcard)
Code: Select all
import adafruit_sdcard
import busio
import digitalio
import board
import storage
import sys
# Connect to the card and mount the filesystem.
spi = busio.SPI(board.GP10, MOSI=board.GP11, MISO=board.GP12)
cs = digitalio.DigitalInOut(board.GP15)
sdcard = adafruit_sdcard.SDCard(spi, cs)
vfs = storage.VfsFat(sdcard)
storage.mount(vfs, '/sd')
sys.path.append('/sd')
sys.path.append('/sd/lib')
- blakebr
- Posts: 959
- Joined: Tue Apr 17, 2012 6:23 pm
Re: Run code.py from SD card
Mike,
I changed all the " to ', no change. import boot.py, import code.py only works from REPL.
At RESET/Power On boot.py may not be running or all/some settings created by boot.py are dropped when boot.py exits. I have noticed that after running boot.py from REPL, I must run import sys to be able to run sys.path. sys can be imported before or after boot.py.
The vfs = storage.VfsFat(sdcard) error was a red herring. I fat-fingered an extra character into boot.py.
What is different between RESET and REPL import boot.py/import code.py? That is the issue.
Bruce
I changed all the " to ', no change. import boot.py, import code.py only works from REPL.
At RESET/Power On boot.py may not be running or all/some settings created by boot.py are dropped when boot.py exits. I have noticed that after running boot.py from REPL, I must run import sys to be able to run sys.path. sys can be imported before or after boot.py.
The vfs = storage.VfsFat(sdcard) error was a red herring. I fat-fingered an extra character into boot.py.
What is different between RESET and REPL import boot.py/import code.py? That is the issue.
Bruce
- mikeysklar
- Posts: 13945
- Joined: Mon Aug 01, 2016 8:10 pm
Re: Run code.py from SD card
Glad the vfs line was just a typo issue.
Are you able to achieve your goal of running the sdmount_lib.py example code as 'code.py' and adding your user code to the same script?
Looking at a somewhat related issue from the CircuitPython forum makes me think that boot.py is not going to be helpful and using 'code.py' to initialize the mount and access the libraries will be necessary. You will have to have your user code appended to the same script to keep the filesystem accessible.
https://github.com/adafruit/circuitpython/pull/6555
Are you able to achieve your goal of running the sdmount_lib.py example code as 'code.py' and adding your user code to the same script?
Looking at a somewhat related issue from the CircuitPython forum makes me think that boot.py is not going to be helpful and using 'code.py' to initialize the mount and access the libraries will be necessary. You will have to have your user code appended to the same script to keep the filesystem accessible.
https://github.com/adafruit/circuitpython/pull/6555
- blakebr
- Posts: 959
- Joined: Tue Apr 17, 2012 6:23 pm
Re: Run code.py from SD card
Mike,
Great idea!! This is my new code.py. It then imports the program.py I want to run, and it works!The downside is it takes 75 seconds for the 700 line program.py to start. What is CircuitPython doing during those 75 seconds that takes that long? If I don't use the libraries on /sd/lib/ it still takes 75 seconds. The wait is after Stop is printed to REPL. ???
Bruce
Great idea!! This is my new code.py. It then imports the program.py I want to run, and it works!
Code: Select all
import sys
import time
import board
import busio
import storage
import digitalio
import adafruit_sdcard
print("\f", end="")
print("\t\t#####################")
print("\t\t## Program Start ##")
print("\t\t#####################")
for x in range(5, -1, -1):
print("\t\t\t ", x, end=' \r')
time.sleep(1)
print("\r\t\t## Run Program ##")
print("\t\t#####################")
print("")
time.sleep(0.1)
import Maker_Pi_Pico_Base as MPPio
print('Start')
SCK = MPPio.SCK # board.GP10
MOSI = MPPio.MOSI # board.GP11
MISO = MPPio.MISO # board.GP12
SD_CS = MPPio.SD_CS # board.GP15
# Connect to the card and mount the filesystem.
spi = busio.SPI(SCK, MOSI, MISO)
cs = digitalio.DigitalInOut(SD_CS)
cs.direction = digitalio.Direction.OUTPUT
sdcard = adafruit_sdcard.SDCard(spi, cs)
vfs = storage.VfsFat(sdcard)
storage.mount(vfs, '/sd')
sys.path.append('/sd')
sys.path.append('/sd/lib')
print('Stop')
_ = 2
if _ == 1: import Demo_code
elif _ == 2: import NTP_Clock_code
elif _ == 3: import IR_code
elif _ == 4: import FRAM_code
elif _ == 5: import asyncioo
elif _ == 6: import fixed_ip
elif _ == 7: import Thonny
Bruce
Please be positive and constructive with your questions and comments.