OSError: [Errno 22] EINVAL at writing to SD-card



  • Hi all,

    I've made a simple python program to log the data of the accelerometer of my pytrack.

    the program works as follows.
    when i push the button on the pytrack it starts reading the accelerometer data and writs this to a .txt file on the sd card.

    if i just measure for a very short amount of time ( 100 ms) everything works fine. if i measure longer i get the following error

    Traceback (most recent call last):
      File "main.py", line 70, in <module>
    OSError: [Errno 22] EINVAL
    

    the file is filled with measurements and is on the sd-card

    the piece of code that is involved

    pitch = acc.pitch()
    		roll = acc.roll()
    		f.write(str(pitch)+';'+str(roll)+'\n')
    		time.sleep(0.05)
    		switch_value = P_in()  #this is line 70
    		if switch_value ==0:
    			if start==1:
    				start=0
    				pycom.rgbled(0xFF0000)
    				time.sleep(1)
    				f.close()
    			else:
    				start=1
    				time.sleep(1)
    				pycom.rgbled(0x0000FF)
    

    the error suggests there is an invalid argument but that seems not to be the case

    any thoughts ?



  • @timh
    Well in embedded programming for example one of the lpc4000 series with a proper debugger you can "walk" through the code and see at any given point in the code what value any given variable has.
    That's the real thing i'm missing with python: a decent debugger where i can set breakpoints, evaluate and and manipulate RAM variables and cycle through lines of code. this

    And i believe that wrapping everything in try and catch can make you a lousy/lazy programmer. For myself i only add try and catch if everything works as it should. Than add them to give the option to continue running with less functionality or save some variables and reboot.

    As for now i'm liking C much more. But there is also an enormous difference in experience. I've been programming all kinds of embedded microcontrollers in C for years, and probably python is never gonna catch up. I have to get more used to coding in python and i will. I guess i'm not so used anymore to make beginner mistakes ;)



  • @eric-waai

    debugging in python is a lot more complicated than in just embedded C. there you get a return 0 or something and the program still runs

    This is where you should consider try/catch blocks to trap these sort of things.

    SD card failure could occur for many reasons. By considering failure points, and when you can't run vs can but in some reduced capacity (ie no logging to an SD card ) needs to be part of your design.

    If you like the notion of return codes then wrap all of the SD card interaction in a function or method which has the try/catch block in it. The return None, or a valid response. Then you can use a simple if not result comparison. Like you would in C.

    Though explicit exceptions means you can catch specific errors and deal with them appropriately rather than having to keep a table of all sorts of different possible error return codes.

    Personally I find debugging in Python easier than C ;-) but it is requires a different design philosophy.



  • @eric-waai Good. But that indicates a bug somewhere in the firmware or the Pytrack library. Maybe someone at Pycom can have a look at it.



  • @robert-hh

    strangely that seems to be the answer thanks a lot!
    i try to figure out why but not at this time

    [rant]
    the cases like this is when i don't like python.
    i experience debugging in python is a lot more complicated than in just embedded C.
    there you get a return 0 or something and the program still runs. it adds loads of debugging options after the error occurs.
    of coarse there can be done much more harm(unlimited writing to flash and RAM when something goes wrong but still i can't get used to debugging with python)
    [/rant]
    on the other side it is quite a powerful language



  • @eric-waai That's a strange interaction, seeming like the Pin mode is changed on the fly. Could you try to re-init P-in before reading it, with

    P_in.init(mode=Pin.IN, pull=Pin.PULL_UP)
    switch_value = P_in()



  • @robert-hh
    thanks for the help so far!

    some more testing
    tested writing without the delay
    got a file from 107 measurements before crashing (2047 bytes)

    Insert Code Here
    f.write(str(pitch)+';'+str(roll)+'\n')
    #time.sleep(0.05) # this is line 70 now
    switch_value = P_in()   # sample the switch at end of delay
    

    and i get this error

    Traceback (most recent call last):
      File "main.py", line 70, in <module>
    OSError: [Errno 22] EINVAL
    Pycom MicroPython 1.18.0.r1 [v1.8.6-849-46a2425] on 2018-07-17; FiPy with ESP32
    Type "help()" for more information.
    

    the pin is initialized as follows:

    P_in= Pin('P14', mode=Pin.IN, pull=Pin.PULL_UP)
    

    i changed the code a bit and it seems to happen only if i write to the sd-card and use the pin() to stop writing.

    if i let the code always log to the txt and don't read the pin it doesn't crash.

    if i don't log to the txt file and red the pin() it doesn't crash.

    so independent it goes well if i use both it crashes

    edit: i changed the code a bit more. and got a file of 6.5mb before crashing.



  • @eric-waai The offset of the line numebr is typically +1 (flagge don the following line). And the data is written.
    So you initialized P_in with something like:

    P_in = Pin ("P14", mode=Pin.IN, pull=Pin.PULL_UP)



  • @robert-hh said in OSError: [Errno 22] EINVAL at writing to SD-card:

    uos.uname()

    (sysname='FiPy', nodename='FiPy', release='1.18.0.r1', version='v1.8.6-849-46a2425 on 2018-07-17'

    and yes P_in() just samples the switch on the pytrack.

    the line number is often not 100% correct. it happens more than once that when you have a syntax error on a certain line it reports it for the next line.

    That would be at about the time, when the first sector of 512 Bytes is to be written.

    that seems about right. the file is always just a bit bigger than 512 bytes. (525 or so)



  • @eric-waai That would be at about the time, when the first sector of 512 Bytes is to be written. Am I right to assume that P_in() just reads the value form a GPIO port? I'm still a little bit puzzled that the error is flagged at that line.
    B.t.w.: Which board and firmware version are you using? Best tell us the result of:
    import uos
    uos.uname()



  • @robert-hh
    the error does not occur when i comment this line

    f.write(str(pitch)+';'+str(roll)+'\n')
    

    it still opens and closes the file

    the amount of samples is around 27. varying +-5

    edit: @



  • @eric-waai Since the line you marked as line 70 is not related to SD writing, does the error also happen when you do not write?
    And if it is related to writing, after which amount of data to be written the error occurs?



Pycom on Twitter