Need help w/ TC74
AGCB
Posts: 327
I'm trying to write a code for a TC74 temp sensor. I'm using what I can from other devices but since I'm new to spin, I need a little help. Where does the data that is read, get returned? I also don't understand how the address gets changed to read (lsb of 1).
I added the TC74 to the object device list
Thanks,
Aaron
CON _clkmode = xtal1 + pll16x _xinfreq = 5_000_000 SDA_pin = 12 SCL_pin = 13 Bitrate = 400_000 read = $00 OBJ I2C : "I2C PASM driver v1.3" TV : "TV_TEXT" PUB Main | Idx TV.start(20) waitcnt(clkfreq + cnt) TV.out($00) 'clear screen temperature PUB temperature TV.out($00) 'clear screen tv.str(string("Temperature info 1st in bin",$0D)) '2s compliment value I2C.start(SCL_pin,SDA_pin,bitrate) I2C.command(I2C#TC74,read) tv.bin(result, 8) I2C.stop waitcnt(clkfreq*2+cnt) '2 seconds before next read temperature
I added the TC74 to the object device list
Thanks,
Aaron
Comments
You asked, "Where does the data that is read, get returned?". The data needs to be put into the variable "result", in your temperature method:
result := I2C.Read(I2C#TC74,address)
Then in your Main method, you would have this,
result := temperature
and the call returns the result assigned in the temperature method, and you would go on to show that on the TV. Every method has its own implied result variable. You can also give that variable an alias name, or you can use the return (...) command to explicitly put a value in the result (see the manual).
In your program, I2C.Start and I2C.Stop belong in Main, not in the Temperature method. Those methods start and stop the pasm cog. They are not the start and stop command of the i2c protocol.
There is a remaining issue though. I understand that you added the I2C#TC74 device code. I haven't used the TC74 myself, but it appears to be one of those devices that does not take an address. All it takes is the device ID set to read, and then the next transaction has to be a read of the temperature. It appears that the pasm driver insists on sending an address. It has a mechanism for sending either one or two bytes of address, but not zero bytes. I may well be missing something. Chris?
As to the question of what to put in the ackbit. The pasm driver takes care of that for you and you don't have to deal with it in the Spin methods. During a read operation, the master is supposed to send out an ack after each byte that it receives, until the last one, which it naks to indicate that it has all that it needs. So in a read of many bytes, all but the last one are acked.
Let me decipher this and try it and I'll report back.
Aaron
I think I've made some progress. Getting something different than all zeros, (all ones). Tried a different object, the " jm_i2c" ,which I believe has a better method for the TC74 read. Hope JM sees this!
I still don't know what to enter in the (ackbit). It has to have something put in it or it will not compile. I made it a constant to be able to try different numbers.
This is the latest code. Your help is greatly appreciated! Aaron
You have the TC74-5 device ID 01_1010. Eight bits as those two i2c drivers expect it. That is the 7-bit device ID shifted left by one to make room for the read/write bit.
The following simple one should work... or this as a sequence of low level routines. This is straight off the data sheet diagram. or this abbreviated routine, because the register selection stays pointing to the temperature. This is the 3rd option in the data sheet diagram.
The tc74 is a SMBus/I2C device. Could this be part of the problem? I still get no usable data , even with Tracy's codes, though they look good. I had to modify them slightly for use with the "jm_i2c" object. Maybe I'll try the "i2cobject" again.
Aaron
When I used this with a PIC chip, there was a register setting for the SMBus
I have had great luck with the jm_i2c object for the most recalcitrant sensors (K33 CO2/Temp sensor for one), can you post the entire code you are attempting to use with this device. Snippets are hard to follow.
Here's the latest which gives output of all 1s. I just looked up info on SMBus and it says the max bitrate is 100kHz. Is the bitrate specified anywhere in the program?
I take it you've been playing with the temperature routine, but what you posted just above can't work.
I don't think it is an issue of SMB vs i2c. For most intents and purposes those are the same.
Chris Gadd's pasm driver does have a bitrate option:
start(clk_pin, data_pin, bitrate)
So you could set that to 100_000. Spin versions are intrinsically slow and can't go that fast.
This is one thing I don't like about higher level languages, you don't know what's going on behind the scene. With assembly you do it all and you know exactly what it does and there's no one else to blame. I was hoping spin would be fast and easy but it's introduced a bunch of new problems.
Thanks
Aaron
I've heard somewhere that I2C written in spin runs at about 35kHz when clocking scl. The minimum for SMB (which has a bus timeout feature) is 1kHz, so the Prop is still way above that.
I2C devices are picky about certain things, but when everything is lined up, they are very reliable. You may be left wondering why they gave you so much trouble the first time around. (Been there! ). Problems with i2c or SMB devices come up here on the forum frequently, and they are often resolved with a sheepish admission that the wires were reversed or not making good contact or something like that, or the wrong device ID has been used, say 7 bits/8 bit confusion, or there is a mixup of innumerable register pointers, etc. Manufacturers are given a lot of latitude in how to implement i2c, so there are indeed esoteric variations you might run across.
The TC74 doesn't appear to be exotic though, and either of the objects you have IMHO should be up to the job once you find the trick.
A tool like the Saleae logic analyzer can be a great help in diagnosing I2C protocol issues.
Are you sure you have address #5 version of the TC74?
I used the same device in a PIC assembly program, with that address and it worked fine. I've looked at that program several times to see if I could discover anything, but nothing.
And yes, I am discouraged! But not giving up yet.
Thanks
Aaron
My I2C drivers expect a 7-bit device address, the handler shifts the address and appends the read/write internally, so your device should be addressed at %100_1101 ($4D).
If that's the case, then TV.bin(I2C.read($4D,00),8) should display the reading.
Here's a poller routine to verify that it's awake and on that address.
I got it! Used the "device finder" to make sure it was there and working and then with a little monkeying got it to display binary and decimal Celsius.
Thanks Chris and everyone.
Now how do I convert to Fahrenheit?
And is there a hex code for the degree symbol in full duplex or TV? I tried the ascii code $DF but got something else.
If anyone is interested in the not quite final code, say so.
Aaron
Under the Propeller tool Help menu you can view the character chart and select the ° symbol directly, and can see that it's actually at hex $B0.
For converting Celsius to Fahrenheit, the formula is F := C * 9/5 + 32. That'll give you the integer degrees, and c * 9 // 5 gets the remainder.
Next week I'll display it on a LCD before I move on to another project.
Feels like post pardom depression now that the big push is over LOL
Aaron
Sorry, I've been out of town for a few days.
It was 2 things that both you and Chris said but it took time to sink in to my old head.
The way of writing a 7 bit address goofed me up and the 'way too simple' read device and collect data all in one line command.
Thanks
Aaron