Can anyone tell me how to write a sequence of 5 bytes to an I2C device? I have a TEA5767 FM Radio module that I’d like to control from Xojo. It resides at I2C address &h60. When I use the GPIO.I2CWrite() function, it appears that what I’m doing is creating 5 separate 1 byte transactions with the radio.
What I want to do is create a single 5 byte transaction with the radio. But I don’t see any way to do this with Xojo’s implementation of the I2C interface.
I’ve found several pieces of code writen in C and Python that are able to successfully control the radio but I can’t seem to find any way to replicate their code in Xojo. They essentially open the I2C device as a file and write 5 bytes to the file handle and then close the file.
I would be really thankful for any help you can provide. I’ve been searching/reading/experimenting for a couple of days now and have pretty much tried anything and everything that I could. What am I missing?
I have no hardware to test with, but after reviewing several examples found by Google, which look similar to what you showed as python code (they are sending a 5 byte array) I recalled that Einhuger was/is into using the Pi’s of different varieties. I found this on his website with xojo code that is slightly different than the sample xojo code.
With that method you cannot and do not have to tell it how many bytes to send correct? In some cases not all bytes should be sent. But the method you used here is very cool! Using a Memory Block. Nice, efficient too!
Let us know Wes which solution works, and works best please!
Thanks for the link. The code there didn’t seem to address my situation so I decided to look at the source code to the wiringPi library for some clues. After digging around in the wiringPi code for a while, I didn’t find anything that addressed sending a data payload larger than either a byte or a word. Although I did find evidence that I2C supports sending a data payload of up to 32 bytes. It looks like the wiringPi library omitted support for that option.
I just emailed the wiringPi author and maybe I’ll get a definitive answer soon. Hopefully, he’ll tell me how to do what I need within the constraints of library as it currently works or he’ll add that feature.
Or maybe someone here on the Xojo forum has already cracked this nut. I hope so.
I though about using a pointer to a MemoryBlock but without a way to specify how much data is in the MemoryBlock the underlying function won’t know how much data to send.
Looking at the wiringPi source code, it appears that there is a particular version of I2C call that can be made where you provide a pointer to a data structure as the payload instead of a byte or integer using the I2C_SMBUS_BLOCK_DATA option.
In this scenario, the first byte of the payload contains the length of the data structure. This would address the issue of knowing how much data is being passed in the payload. But the currently defined wiringPi functions
wiringPiI2CWrite(int fd, int data);
wiringPiI2CWriteReg8(int fd, int reg, int data);
wiringPiI2CWriteReg16(int fd, int reg, int data);
don’t appear to use the I2C_SMBUS_BLOCK_DATA option. If I’m reading the C code correctly (and I may not be) it looks like the above functions are receiving the int data on the stack instead of as pointers to the data. So passing a pointer into these functions wouldn’t work as desired.
I may be way off base with all of this. I’ve been messing with this issue for two days now and I’m pretty tired. I probably should step away and try again later.
From what I’ve read, the setup call returns a file descriptor.
You should be able to create a BinaryStream using the fd returned.
Then a standard write should work.
Assign your data to a string, then something like this:
dim b as BinaryStream(fd, binarystream.HandleTypeFileNumber)
should write multiple bytes at once.
I’ve used wiringPI, but not the I2C parts so this is not tested.
I managed to get the problem handled and now I can read and write 5 byte data blocks to and from the TEA5767.
I just want to say thank you to Tim S. for jogging my stalled thought process, Tim H. for suggesting the use of memory blocks and John for providing the idea of writing to the file descriptor.
This is essentially the code did the trick for me:
Dim mbRadioOut As MemoryBlock
Dim fdRadio As Integer
Dim bsRadio As BinaryStream
mbRadioOut = New MemoryBlock(5)
' Initialize the radio.
mbRadioOut.Int8Value(0) = Integer.FromBinary("10101001")
mbRadioOut.Int8Value(1) = Integer.FromBinary("11010100")
mbRadioOut.Int8Value(2) = Integer.FromBinary("10110000")
mbRadioOut.Int8Value(3) = Integer.FromBinary("00010000")
mbRadioOut.Int8Value(4) = Integer.FromBinary("00000000")
' Get file descriptor of radio.
fdRadio = GPIO.I2CSetup(&h60)
' Open a binary stream to the radio.
bsRadio = New BinaryStream(fdRadio,BinaryStream.HandleTypeFileNumber)
' Write data to radio.
Reading the data from the radio was essentially the reverse of the above.
Wes, your solution helped me make progress with reading and writing to a Sensiron SHT31D humidity sensor on I2C. But only for one read/write cycle. After that there is no further response until I quit the app and try again. If, while my software is still running but not getting a response, I interrogate it with a simple Python program, it responds. Hmmm.
Did you get yours working for several read/write cycles, or just the one?