I2c & Spin How to
JBWolf
Posts: 405
Hello,
I was hoping to find information on how to communicate & store returned data values with spin from an IC using I2c.
I am using an MPU6050 gyro, the registers & more can be found here: RM-MPU-6000A.pdf
And more info from here: http://www.i2cdevlib.com/devices/mpu6050#registers
I am more familiar with analog components and just do not understand how to go about this.
How do I request & store data from an I2c register using spin?
Thanks
I was hoping to find information on how to communicate & store returned data values with spin from an IC using I2c.
I am using an MPU6050 gyro, the registers & more can be found here: RM-MPU-6000A.pdf
And more info from here: http://www.i2cdevlib.com/devices/mpu6050#registers
I am more familiar with analog components and just do not understand how to go about this.
How do I request & store data from an I2c register using spin?
Thanks
pdf
650K
Comments
As a generalization, in I2C you tend to have the following event sequence
Write:
START
WRITE Slave ID (write mode)
WRITE Address
WRITE Data
STOP
Note that in some devices you'll need two bytes for the address, and the writing data will also depend on how many bytes are to be written.
Read:
START
WRITE Slave ID (write mode)
WRITE Address
START
WRITE Slave ID (read mode)
READ Data
STOP
The first part of the read process writes the address pointer into the device. The slave ID is re-written with the read bit (bit0) set and the reads commence after that. The Ack/Nak bit is set to ACK for all reads except the last, which is set to NAK.
There are lots of I2C tutorials on the Internet. Between those and the attached object (or one of the others in ObEx) you'll be connected in short order. It's worth learning I2C if you'll take a bit of time
I see, so I just pass the pins from the main routine call correct?
i.e. i2c.setupx(sclpin, sdapin)
Thanks for the help btw
Is $68 a hex value? = 104 decimal = register name (SIGNAL_PATH_RESET)?
So just trying to get around the very basics... the I2c uses pwm high/low bits to create hex values, these hex values correspond to the registers and it replies in kind? correct?
How do I assign the 'value' variable for the register desired? Can I just do this: I see a high & low bit register for the X-axis gyro which means 2 values (43 & 44).
Sorry, I just do not understand this well enough to immediately utilize the i2c object.
I sincerely appreciate you taking the time to help and look forward to any more you have to offer
I am more than willing to study on this, just cannot find much about using i2c with spin.
It was not easy to find. It's almost at the very end of the document: page 46, discussing the "Who Am I" register which contains the default I2C address of the device.
The is a TON of information on using I2C available on the Internet -- as you have a working computer and Internet connection, a little research and reading is in order. To be honest, that document is not helpful. Have a look at an EEPROM data sheet and you'll get much more information vis-a-vis the I2C transaction process.
Read this: http://ww1.microchip.com/downloads/en/devicedoc/21754m.pdf
If you will take the time to study, you'll get a really good hand on using I2C with the 24LC512 (64K EEPROM that many of us use with the Propeller). You can even experiment with the EEPROM you have -- just make sure you don't write to an address where program data is being stored.
You're not going to find a specific tutorial on I2C with Spin (unless it's from Parallax) -- nor should you, really. I2C is a process that is not language dependent; it can be implemented in any language that has hardware connection features. If you don't understand how to manipulate IO pins on the hardware and with the language you're using, you cannot implement I2C. It's all about bit twiddling, and you have to start with the bits. Luckily for you, many of us DO understand the bit twiddling and have written easy-to-use objects. It's up to you now to learn the basics of I2C so you can successfully put that code to work. I've used my I2C object in a number of commercial projects so I'm very confident in it. That said, others have come before and after me with I2C objects as you'll find with a quick search of ObEx.
You can do either, but it is very convenient to use the existing P28 and P29 shared with the eeprom as that leaves more of the other propeller pins free for other things. All sorts of clever things can be added onto P28 and P29 - analog to digital, digital to analog, digital i/o ports, gyros, temp sensors, real time clocks, other memory chips. All shared on the one bus. The I2C bus is very useful.
The data sheet seems to only have the raw/analog method for communicating (high/low states & timing), but I cannot correlate this information into a spin command(s) to generate a desired data set or how to receive a reply.
The only way I can think of right now is to make a literal pwm pulse:
outa[28..29] := %1000000
but this wont work since the timing on the sda pin will not be in sync with the pulses on the scl pin right?
So far I have learned I should use pins 28 & 29 for bus communication and the pulse format the data has to be packaged in.
It seems as if the i2c object you attached above will produce the data packages for me, but I cannot use the information from the datasheet regarding pulse formatting to make any more sense out of using the object.
what is the next step?
With a tiny bit of effort you should be able to use the I2C object I provided to read bytes from the EEPROM. You can use F8 to determine an address and what's in it -- that way you'll know the read process worked. And here... I'll write a method for you to write to the EEPROM; try it and then see if you can create a complimentary write method. Programming is kind of like going to the gym: you have to do the workout to benefit from it; watching others is not enough.
I've attached my starter program so that you don't have to type to see that it works.
To second what JonnyMac says, the good news is that someone else has already written the code for you. So instead of worrying about highs and lows, you can talk to an 'object' (code written by someone else). The 'object' has PUB methods, which is essentially public routines that you interact with. Say you want to print 'hello world' on the screen. Someone has already written a display object and called it 'Display'. So to interact with that you might write "Display.Print("Hello World")).
I2C is similar. All I2C code is going to need a "start" to wake up the chip. So the code is "I2C.Start" Now it becomes much simpler because someone else has done the high / low code inside the i2c object. You can read the code if you like, and you can rewrite it if you really want, but generally it is ready to go and do just what you want.
JonnyMac posted the code earlier with this and can be truly this simple (I once wrote a movie player for the propeller using objects written by someone else and it ended up being two lines of code!)
I was worried you were going to consider me too far behind and give up, relieved to hear it's not as complicated as I worried it would be... feels like im just missing something basic thats throwing me off so far.
Hopefully everything will be cleared up tomorrow when I get a chance to do more reading.
Hope you guys had a good weekend
None of us learned this stuff in a day. Take it easy, it will come.
I have searched through the PE book but cannot find a reference to this other than min/max limiter... what is the # doing in the con sections?
I will be working on this again over the weekend, looking forward to it
You mean enumerations? Check the manual (v1.2) around page 87 (CON section & Co). Basically it lets you define a number of constants in a single line, optionally with gaps:
Unfortunately I got nowhere in the book regarding the enumerations.... there is no mention to the word enumeration in v1.2 of the PE book, p.87 is about variables called from dot notation methods and looking at memory.
Was a good lesson to go back over, but I could not get anywhere regarding the enumerations.
So I just tried to figure it out myself.... it looks as if you are associating those names with a number value? So a call to 'home' or 'gotoxy' returns a value of 1?
Ok so let me see if I'm following:
The 'main' method calls rd_byte and passes $004C.
The main method then prints to PST the value in the variable unless it equals 0 where it would quit the loop and enter an endless null loop.
The rd_byte method calls the 'write' method in jm_i2c and passes values ($004C, "JonnyMac's Propeller Programming Attack!") for (address.byte[0])
what I dont get is why there is a ++ after the $004C... wouldnt that make it increment and equal $004D?
I also dont understand about the msb ID write, is it basically a standard required for use or do I need to figure out how to identify ID's? i2c.write(address.byte[1]) ' write address (msb first)
For some reason in PST I just get a repeating letter 'y' and nothing else. I have tried speeds 57600 and 115200 but get same results.
Not quite, the value auto-increments, so HOME will be 1, GOTOXY is 2, then the enumeration is reset to 8 (BKSP), TAB will be 9, CLS finally 16. Does that make sense? In the PropTool (after a successful compile) you can place the cursor on a constant and see its value in the status line.
For this to work you have to put the program into EEPROM because the loop only reads from there (the Msg string ends up at $4C in EEPROM). The loop itself reads one byte at a time which is why the address is post incremented (p_str++), i.e. for the first pass it will be $4C for the second $4D etc. As for talking to an I2C device, that's just the way it is. You send (write) a start condition, a device ID then an address (which may differ in length depending on the device). For a read you then change direction (another start followed by ID with the read bit set). Then you read one or more bytes and stop the transfer.
I can see the text in memory starting at $004c after loading.
I'm still getting a repeating letter 'y' in PST though.
It seems to load to ram just fine... but when I try to load to eeprom, the propeller tool fails with "eeprom programming error on COM3".
I wonder if this is because both the i2c device and the eeprom is on pins 28 & 29?
ok I removed the i2c device from pins 28 & 29, the F11 eeprom load works fine now.... but I get nothing at all from PST.
I have tried both 57600 & 115200 speeds, reset several tiemes, reloaded several times, added a 5-sec delay before the program starts... but still nothing on PST at all.
do I need to re-connect the i2c device?
Fixed now and it does give a good readout in PST.
sorry, my protoboard is setup for 3 different project so it's kinda a mess lol