Embedded Eye

Give your gizmo the gift of sight

I'm happy to be playing with the CYE8 sensor that I finally got wired up, and it's all connected to the I2C/SMBus interface on the linux PC/104 system and merrily blinking the LED when there's motion in front of the sensor.
However, even though I've read countless times how the protocol works from a physical standpoint, and I'm looking at the CYE8 documentation for what commands to send to get it to do things, I'm still at a loss as to where to start writing the code on the computer side to talk to the sensor. I know it's a really basic thing and is probably extremely simple, but could someone post some example code that just connects to the device, sends the commands to tell it to send OF info, and then read a few samples to stdout or a file? Just the basic framework and syntax really, I'll be able to expand it on my own.

Since the end use will be on said PC/104 and it will be running linux (Ubuntu 10.04 with rtai), I'm looking to use either the kernel module interface or the user space /dev/i2c-0 interface (with the i2c-dev package). For now since I'm just testing I'd like to make use of the python-smbus package so I can throw commands at it from an interactive command line or an interpreted script instead of compiling every time, but that has seemingly even less documentation.

Once the AVR ISP comes in and/or the USB/I2C adapter (both on order) I'll be able to use it from my windows machine, but that will be reserved for fiddling with firmware and testing, the end application is still on linux.

Thanks for any help!

Views: 338

Reply to This

Replies to This Discussion

Hi Chris,

I've never used I2C from a linux or PC/104 so I can't really help you there. Can you find code examples for communicating with I2C devices in general? I'm sure they exist somewhere. If so, it should be pretty easy to adapt those code examples to the commands for reading basic optical flow.


After another day of searching, I managed to find some examples to piece together into an I2C interface. However, I have now found that the I2C controller built into the embedded computer we're using is in fact a SMBus controller, that only supports that superset of all the I2C commands. I am able to do the simple 2-byte Command/Value writes, and simple single-byte reads, but the crossover appears to end there. Both methods I tried for manually specifying the transaction order resulted in "operation not permitted" errors.

For more info on the functions it's letting me use: http://www.mjmwired.net/kernel/Documentation/i2c/smbus-protocol


In essence, the SMBus protocol adds a few things to the communication procedure. The control bits (Start, Stop, Ack, NAck, Address, Rd/Wr) are identical, it just switches up the order a bit of the data being sent.

For the following info I'll be using the abbreviations from the above link. Right now the CYE8 Firmware (as well documented) has the following procedure to read out optical flow values:

S Addr Wr [A] Comm [A] Data [A] P - where Comm is 2 and Data is 65, this sets it to send the 6-byte OF array, then it is read by subsequent sequences of:

S Addr Rd [A] [Data] A [Data] A [Data] A [Data] A [Data] A [Data] NA P


This is simple, easy, and works great, but unfortunately the "i2c_smbus_read_block_data()" function (the only function that reads more than 2 bytes in a transaction that my adapter supports) specifies that reads are combined messages that include a preliminary write of a single Command byte to tell the device where to read from. They also expect that the first byte of the response is the number of total bytes to read, i.e.:

S Addr Wr [A] Comm [A] S Addr Rd [A] [Count] A [Data] A [Data] A ... A [Data] NA P


So, primarily for myself, and if it works I'll commit changes, I plan to make the CYE8 firmware compatible with SMBus transactions (at least the message order, not CRC checking yet)
My idea for the change here is simply to add a few COMM constants (in the 60+ range) that, when received, will change the order of output to be compatible with the SMBus superset of the I2C protocol. The only real change will be adding handlers for the command byte, then putting another switch in the TWI_STX_ADR_ACK case that makes it send the length of the output array and break instead of continuing to the TWI_STX_DATA_ACK case.

When reading more into the protocol specification it seems to assume that any time you're doing a block read (more than 2 bytes) from an I2C device, even one not using SMBus, it does a combined write/read by sending a command byte first to tell the device (usually an EEPROM) where to start reading from.

Of course it will probably end up being more complicated, but I don't see it adding any extra overhead in terms of processing or memory. The only downside I see right now is that SMBus by definition doesn't support transmitting more than 32 bytes in a transaction, so if I'm going to dump the raw image I'll have to find some way of doing it in 32 byte chunks, probably by using a command byte for "resume".



Hi Chris,

It looks like you've done your homework! I wonder though if in your case an Arduino located between the sensor(s) and the PC104 could also serve as a "glue" board. Of course this assumes weight is not an issue. But otherwise your suggestion sounds great and I encourage you to at least share your results if this works out well. (We should test the code with simple I2C first as well to verify we don't break that.) I'd suggest placing those changes into the "OS" side of the code- the associated command headers should be <30.

We actually have a much more sophisticated comm handler (written by Craig Neely) that can be adapted to handle the issue you are talking about. It is a powerful and robust handler. We opted however to not include it in the CYE8 sensor since it can be difficult to understand how it works, and it adds another layer of complexity to the packaging of bytes being sent, but it is there.



© 2022   Created by Geoffrey L. Barrows.   Powered by

Badges  |  Report an Issue  |  Terms of Service