In eeprom datasheet (e.g. AT24C256) I can read memory chip needs some time (usually 5ms) to write data to nonvolatile memory and eeprom will not respond to any i2c commands until the internal write is complete.
In another place of the datasheet is described we ca run acknowledge polling to determine is eeprom ready for next operation or not.
For Adruino I found something as below:
void write_function(...){ //write commands... while(isBusy()){ delayMicroseconds(50); } } bool isBusy(){ Wire.beginTransmission(I2C_ADDRESS); return Wire.endTransmission(); }
I wonder how can I implement something similar via python smbus module.
gorek
In eeprom datasheet (e.g. AT24C256) I can read memory chip needs some time (usually 5ms) to write data to nonvolatile memory and eeprom will not respond to any i2c commands until the internal write is complete.
In another place of the datasheet is described we ca run acknowledge polling to determine is eeprom ready for next operation or not.For Adruino I found something as below:
void write_function(...){ //write commands... while(isBusy()){ delayMicroseconds(50); } } bool isBusy(){ Wire.beginTransmission(I2C_ADDRESS); return Wire.endTransmission(); }I wonder how can I implement something similar via python smbus module.
gorek
I am NOT a Python guy, but I bet the Python equivalent of smbus has beginTransmission and endTransmission. If it does then the above code just needs to be rewritten using Python syntax. Maybe one of the Python guys will answer your query as well.
First computer 1959. Retired from my own computer company 2004.
Hardware - Expert in 1401, and 360, fairly knowledge in PC plus numerous MPU's and MCU's
Major Languages - Machine language, 360 Macro Assembler, Intel Assembler, PL/I and PL1, Pascal, Basic, C plus numerous job control and scripting languages.
My personal scorecard is now 1 PC hardware fix (circa 1982), 1 open source fix (at age 82), and 2 zero day bugs in a major OS.
something like the python in the link below will probably do the job.
https://gist.github.com/CRImier/b3922e0656825746a801594a7ccba8af
But if you were using micropython on a rpi Pico or an ESP32 etc then you cant do better than use the libraries from the excellent Peter Hinch repositories.
https://github.com/peterhinch/micropython_eeprom/blob/master/eeprom/i2c/eeprom_i2c.py
@byron @gorek Those are interesting links. I am surprised that the C code is at least an order of magnitude less code and more easily understood. Perhaps my idea of Python is mistaken, I thought it was an easier higher-level language which generally means less code. How come it is more complex?
First computer 1959. Retired from my own computer company 2004.
Hardware - Expert in 1401, and 360, fairly knowledge in PC plus numerous MPU's and MCU's
Major Languages - Machine language, 360 Macro Assembler, Intel Assembler, PL/I and PL1, Pascal, Basic, C plus numerous job control and scripting languages.
My personal scorecard is now 1 PC hardware fix (circa 1982), 1 open source fix (at age 82), and 2 zero day bugs in a major OS.
How come it is more complex
Think of the C code snippet as a brick, whereas the linked examples showed a whole blooming house. 😀 As you may see the micropython library covered a whole bunch of eeproms and more.
And you probably missed the //write commands... comment in the C snippet.
But C is more terse and python is generally more verbose, and thus more easily read and followed. One usually spends 10 times the amount of time reading and amending ones code than the initial write, so I like a bit of verbosity.
@byron I knew the write statement needed to be there. I was just surprised at how much Python code was needed.
I had to look up Terse since my expectations were getting ahead of what I thought you were writing.
In a language hierarchy, the least 'terse' code is machine code, followed by ASM, followed by C. C++ is mostly C with some data abstraction concepts, so it is both less terse in some areas and more terse in others. Library creators do need C++ to create their Classes and methods but that is rare in this forum.
First computer 1959. Retired from my own computer company 2004.
Hardware - Expert in 1401, and 360, fairly knowledge in PC plus numerous MPU's and MCU's
Major Languages - Machine language, 360 Macro Assembler, Intel Assembler, PL/I and PL1, Pascal, Basic, C plus numerous job control and scripting languages.
My personal scorecard is now 1 PC hardware fix (circa 1982), 1 open source fix (at age 82), and 2 zero day bugs in a major OS.
I knew the write statement needed to be there. I was just surprised at how much Python code was needed.
You are not really comparing like for like. For example in the following code that is a method (a function of a class) to wait for i2c, the sort of thing the OP was asking:
def _wait_rdy(self): # After a write, wait for device to become ready self._buf1[0] = 0 while True: try: if self._i2c.writeto(self._i2c_addr, self._buf1): # Poll ACK break except OSError: pass finally: time.sleep_ms(1)
The only real pertinent bit of code is - self._i2c.writeto(self._i2c_addr, self._buf1) - if you want terse 😀.
As you can see the function is defined, the buffer to use is identified and the code loops until a condition is met. The pertinent bit of code is also put into a try except clause for error handling, such as the eeprom finally giving up the ghost on a write too far for it meagre life expectancy. The linked code is, as said, a library that can read/write to a number of different eeproms thus necessesitaking a bunch if if's etc. and, as the author of the lib should, has provided much error checking and comments which all add to the perceived code glut.
I hope you a good boy and put in lots of error handling code into you programs 😎
@byron I have some code now running for over 40 years. I have code in IBM mainframe OS and in dozens of corporate internet situations. I have always noticed that my code has far less error-checking than many of my peers. At least a part of the reason for that is other people do what can only be described as stupid error-checking. For example, I have seen numerous cases where a programmer did a hard-coded sequence check of a master file after being sorted by the vendor's utility. NOT ONCE was an error found. Also, many programmers do not study their compiler to learn what it can do. I have seen a lot of code checking for if an input field is 0 or blank. That is also the most common run time error, except for a bad pointer. HOWEVER, there are either compiler or language tools that prevent both of those in a way that either corrects or at least traps the error.
Keep in mind I worked for Big Blue (trained on hardware, firmware, and OS) and was the master of the OS and compiler. The IBM system engineers, when stumped, would call on me to go to the customer site either physically or via the net (we had that internally long before the internet) to solve the problem they were having. I have occasionally thought of writing a book about my activities, but I can't do it without getting IBM legal involved, and I am just too old to suffer through that amount of administrivia. Some security and NDAs are still in effect, but I don't know which are and am too tired to go through the discovery process.
So the bottom line is I didn't put much 'error checking' in my code because it wasn't needed. Since I have decades of constant use of that code with NO failures, I think I had the right amount.
First computer 1959. Retired from my own computer company 2004.
Hardware - Expert in 1401, and 360, fairly knowledge in PC plus numerous MPU's and MCU's
Major Languages - Machine language, 360 Macro Assembler, Intel Assembler, PL/I and PL1, Pascal, Basic, C plus numerous job control and scripting languages.
My personal scorecard is now 1 PC hardware fix (circa 1982), 1 open source fix (at age 82), and 2 zero day bugs in a major OS.
I am NOT a Python guy, but I bet the Python equivalent of smbus has beginTransmission and endTransmission.
After long study smbus source code I found unfortunately smbus hasn't equivalent of these functions. Smbus just wrap linux kernel's i2c commands in python.
In Arduino you can create i2c message from scratch by adding any write/read commands sequence between start and stop (or even send stop and start sequences again inside message payload).
In smbus you can only send to device one of complete i2c message (beginning with start sequence, certain read/write command and end sequence). You can't edit message payload (except rdwr mode but it is out of scope of this post). List of these messages is described in https://docs.kernel.org/i2c/smbus-protocol.html .
Equivalent of message created by beginTransmission and endTransmission in Python is just write_quick(i2c_addr).
So python's isBusy could looks like:
isBusy(bus, deviceAddress): timeout = 100 while timeout: try: bus.write_quick(deviceAddress) break except OSError as expt: timeout -= 1 sleep(0.0001)
timeout is not necessary but it avoid to infinite loop when for example device is accidentally unplugged.
Maybe it will be helpful for someone else in future.