I2C I/O expander (IOWizard) with BS2p speed question
Hi all,
Just wandering if anyone had any experience with a Basic Stamp (BS2p) and an I/O expander from Robotics Connection - it's an I2C board called IOWizard, it has 5 ADC ports and 10 GPIO ports. It's made for their Serializer line, but it looks like a generic I2C board and I don't see why it wouldn't work with a Basic Stamp.
My question is really about speed - the idea is to hook up a bunch of bumper switches and all the digital IR sensors on a robot to the 10 GPIO ports, add some Sharp analog IR rangers and read them all at once via a I2CIN command on a BS2p. The IOWizard sends 20 bytes when queried - first 10 bytes are double 10 bit analog readings and the last 10 are the status of the digital ports.
It seems to me a lot of data is being transmitted and I read somewhere in the forums that the I2CIN/I2COUT commands are quite slow and have some reliability issues.
So, is it practical from a speed stand point to rely on this I2C expansion board to read critical sensors such as bump and proximity?
Also, how would I format the I2CIN command to read all the info, or a portion of the info (for example only the GPIO status, which is at the very end of the 20 bytes), with the minimum amount of calculation/translation overhead - I'm referring to how to optimally define my variables and how to optimally use the "Conversion Formatters" in PBasic?
Thanks in advance.
PS: No intention of promoting non-Parallax products (love Parallax!), just being curious and trying to explore and learn...
PPS: Looks like the board is made with a PIC18F2221, so there's code and memory and all sorts of things in there.... just answering some of my own questions out loud...
Post Edited (modemman) : 5/6/2009 10:58:30 PM GMT
Just wandering if anyone had any experience with a Basic Stamp (BS2p) and an I/O expander from Robotics Connection - it's an I2C board called IOWizard, it has 5 ADC ports and 10 GPIO ports. It's made for their Serializer line, but it looks like a generic I2C board and I don't see why it wouldn't work with a Basic Stamp.
My question is really about speed - the idea is to hook up a bunch of bumper switches and all the digital IR sensors on a robot to the 10 GPIO ports, add some Sharp analog IR rangers and read them all at once via a I2CIN command on a BS2p. The IOWizard sends 20 bytes when queried - first 10 bytes are double 10 bit analog readings and the last 10 are the status of the digital ports.
It seems to me a lot of data is being transmitted and I read somewhere in the forums that the I2CIN/I2COUT commands are quite slow and have some reliability issues.
So, is it practical from a speed stand point to rely on this I2C expansion board to read critical sensors such as bump and proximity?
Also, how would I format the I2CIN command to read all the info, or a portion of the info (for example only the GPIO status, which is at the very end of the 20 bytes), with the minimum amount of calculation/translation overhead - I'm referring to how to optimally define my variables and how to optimally use the "Conversion Formatters" in PBasic?
Thanks in advance.
PS: No intention of promoting non-Parallax products (love Parallax!), just being curious and trying to explore and learn...
PPS: Looks like the board is made with a PIC18F2221, so there's code and memory and all sorts of things in there.... just answering some of my own questions out loud...
Post Edited (modemman) : 5/6/2009 10:58:30 PM GMT
Comments
1. The board sends 20 bytes when queried, can't handle that with old-school BS2 programming, not enough variable space.
2. I want to read data selectively, for example, if I use only 3 GPIO ports and one analog, I want to be able to read just that data, and not have to read 20 bytes of data and then worry about parsing.
3. The GPIO data is all the way at the end of the string - I see this as a design issue, it makes no sense to have to read 20 bytes of data just to see if a digital input is 0 or 1, seems that if it was the other way around one could 'cheat' and read just the beginning of the stream into an old school byte size variable (and ignore the rest, if one chooses to do so).
4. Plugged an analog Sharp sensor and don't see any changes in received data, everything comes in as 255s or 11111111s. Do I need to reset/initialize this board? Documentation is stingy - I wish this was a Parallax product [noparse]:)[/noparse]
5. How does the I2C transmission speed get controlled? Will any I2C board talk to a BS2? Are some faster, some slower? Is there a "baud rate" command I missed in the PBasic syntax?
6. I thought I can add a gazillion of I2C boards to the same pins (I use 8 and 9), as long as they have different "slave" addresses. Well, I think there's some limit - 8 or so. When I put my 2 I2C boards together, my data from the old one (which works fine on its own) comes as all 1s (or 255s). If I take the new board out, everything works fine again. Maybe the new board is just fried? Nah, I don't think so.
So I'm back to reading the PBasic manual in order to answer all this. I found this, but can't figure out how to do it yet - and again, seems like extra steps are needed, isn't this going to be painfully slow? Never used SP-RAM, no idea how slow that is and what it involves:
"In the BS2p there is a new modifier, SPSTR, for serial input commands (SERIN,
I2CIN, OWIN, LCDIN). This modifier will let you "buffer" data from the input
device into the SP-RAM (starting at location 0). Many have found this useful
for reading long strings (i.e., from a GPS device). Once the data is in
SP-RAM, you can parse through it manually with GET. By buffering to SP-RAM,
you don't use any variable space for your raw input. "
Dump it to SPRAM, plenty of space on a BS2p
Are you sure you can't set the address you want to read so you can just get the byte(s) you want?
The master generates the clock pulse. The "normal" I2C clock speed is 100khz; the Stamp I2C clock speed is actually quite a bit slower, so this is not an issue at all. And since the Stamp I2C commands support clock stretching, again no issues there.
It's not slow. Just convenient.
Post your code and/or schematic. Also a datasheet for the IO expander?
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
When the going gets weird, the weird turn pro. -- HST
1uffakind.com/robots/povBitMapBuilder.php
1uffakind.com/robots/resistorLadder.php
The datasheet for the board is here:
www.roboticsconnection.com/multimedia/docs/IOWizardUserGuide.pdf
I connect the board to pins 8 and 9, with pullup resistors. The slave address is $64. I hooked up 4 digital IR sensors to the first 4 GPIO inputs, for testing.
I finally figured out how to use the scratchpad, and my new code looks like this:
I'm clearly reading something, but here are the issues:
1. After I turn the power on to the BOE board, I seem to be able to read sstuff (I don't know what though - in some spots, there are 1s and 0s dancing, I assume the analog outputs are jittery?). After I fiddle with the program, or rerun it, or soft-reset, but only sometimes, all output turns to constant 1s (or 255s in decimal) and the only way to fix this is to shut everything down and restart.
2. While testing the GPIOs, I do see a few 1s turn into 0s (which is what the digital IR sensors are supposed to do), but in weird places, not at the addresses I would expect and other bits in other locations are shifting too.
I just re-read the spec sheet and noticed they mention 10 bit bytes. Is that the root of my problem? I'm not reading all the bits in a byte and all my data is shifted and skewed?
If so, how can I read 10bit bytes properly?
Thanks.
So you are reading the outputs which may not be stable. Second, you only have to worry about the "10 bit" values when parsing the data from the ANALOG inputs. And that's a little funky because the most significant bits are in the first byte of each pair, and the lowest two bits are in the second byte. In any case, lets say you are going to setup all your GPIO pins as inputs (10 digital, 5 analog). Note use of constants so that if addresses/device type change you don't lose your mind down the road:
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
When the going gets weird, the weird turn pro. -- HST
1uffakind.com/robots/povBitMapBuilder.php
1uffakind.com/robots/resistorLadder.php
Post Edited (Zoot) : 5/10/2009 8:51:41 PM GMT
Thanks a lot for the help. The code works, it's the board that is acting weird, or my stupidity, or both.
As far as syntax goes, this worked:
I2COUT SDA, GPIOw, $01, [noparse][[/noparse] index, $02 ] 'State: 0 = Output Low, 1 = Output High, 2 = Input
That being said, the docs mention that you can send a few commands, like 3 for reset.
Not sure how to send that though, tried I2COUT SDA, GPIOw, [noparse][[/noparse]$03], but that had no effect.
Anyway, the problem is deeper - this is what I get in the Debug window, with 4 digital devices hooked up to GPIO pins 3, 4, 5, 6 and nothing to the ADC pins:
analog pin 0: 01055
analog pin 1: 00546
analog pin 2: 00403
analog pin 3: 00409
analog pin 4: 01176
digital pin 0: 00000001
digital pin 1: 00000000
digital pin 2: 00000000
digital pin 3: 00000000
digital pin 4: 00000000
digital pin 5: 00000000
digital pin 6: 00000000
digital pin 7: 00000000
digital pin 8: 00000001
digital pin 9: 00000001
The analog readings are "dancing" like crazy and it's impossible to make any reading or pattern with the analog Sharp sensors hooked up and the digital ones are acting weird, as follows:
- I can change the state of all pins to Output Low/High - I hooked up LEDs and monitored the Debug, that works.
- The moment I switch all 10 digital pins to Input, they all look like above. Any digital device hooked up to pins 0, 1, and 2 will trigger "digital pin 0:" reading to change state. But not "digital pin 1:" or "2" or "3"! If I hook up anything to pins 4, 5, 6, nothing at all changes. If I hook up something to 7, it will change state to 1. Only 8 and 9 work as expected.
- If I fiddle with this for a few minutes, there is a point when everything turns to "1" and nothing changes until I hard-reset everything.
PS. Even if this worked as advertised, it is way to slow to be used for what I wanted, which is real time sensor based navigation. The program I'm running is nothing but a simple "read I2C, write to memory, then look at data" and even if Debug takes some time, it's just too slow to be practical.
I'm back to square 1, stuck at the "would like to do all these things but there are not enough I/O pins".
I2COUT SDA, GPIOw, [noparse][[/noparse]$03]
It would probably either be:
I2COUT SDA, GPIOw, $01, [noparse][[/noparse]$03]
or
I2COUT SDA, GPIOw, $00, [noparse][[/noparse]$03]
as I seem to recall $00 is the address for the "command" register. Remember in Pbasic I2C syntax, the order in the command is:
Bus Pin, SlaveAddr[noparse][[/noparse]r|w], internal register address, [noparse][[/noparse] data ]
I would not expect to see stable values in your AN ins unless you have inputs hooked up. Possibly ditto on the digital ins. Beyond that, it's hard to say. Can you post (attach) the actual program you ran?
I will agree that this chip is poorly programmed -- having to read 20 bytes every time just to sample analog or digital channels makes no sense. You should be able to query just the address for a single analog channel, and the digital ins could have been sent as two bytes with bit flags set for each pin.
In any case, you might want to look at the GPIO14 from Devantech, available at http://acroname.com -- it has 4 analog inputs (can also be digitial in/outs), 6 digital i/o, one PWM out, and it's much more sensible in it's programming.
However, if you what you really need is more digital ins, and you do not *have* to use I2C, then think about a 74HC165 (8 digital inputs) and possibly an ADC8034 or ADC8038 for 4 or 8 analog ins. You could share data/clock lines and would just need two /OE lines.
Maxim and Phillips also make a pretty broad range of sensible I2C I/O expanders, do a search at Digikey.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
When the going gets weird, the weird turn pro. -- HST
1uffakind.com/robots/povBitMapBuilder.php
1uffakind.com/robots/resistorLadder.php
I hear you about the correct format of the I2COUT, it's just that the doc for that board is soooo confusing. At this point I'm going to give up on it - I wrote in their forum, maybe I can get a firmware upgrade, or something (I realize it's just a PIC so it's more likely that there are issues in the software that's being programmed inside it, than circuitry issues...)
I don't *need* I2C necessarily, just sounded convenient and easy and I haven't used it before. I'm mostly in the phase when you get new toys and are excited to see them work, with no specific goal in mind. I have a modified Boe-bot with a BS2P, mattracks, compass, accelerometer, Ping, speech module, etc.... Now I'm experimenting with software to try to make things smooth. I'm also starting work on a Prop based self-balancing bot, but mostly like to work on my old Basic Stamp machine because it's so limited and it really makes me learn a lot. Every new idea comes with a set of new problems and puzzles to solve. For example, if it wasn't for this darn board's habit to spit out an entire row of 20 bytes, I would've not known how to use the scratch-pad memory (which now seems like "duh!! that's so easy"). So thanks for your help, this pushed me to learn a good amount of new stuff....
I'll definitely look at the chips you recommended - might even attempt to just get a chip and make my own board, I know at least I'll learn a lot in the process.
I also found these, based on PCA9535 from Phillips and ADS7828 from TI:
store.gravitech.us/i2c128anco.html
store.gravitech.us/i2c16gpex.html
modemman
Try using the following for a read: I2CIN SDA, $65, 0, [noparse][[/noparse]index, 2]
Just a thought.
Regards,
TCIII
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
If you are going to send·a Robot·to save the world, you·better make sure it likes it the way it is!
That's what is truly unclear from the documentation is that it appears some commands are "normal" in that the register address internal to the I2C slave has to be written to do a subsequent read, but that some commands -- like getting the byte stream -- only the slave address is written then the read is just started.
modemman -- rather than so much $$ on what is basically a breakout board, try these with very standard I2C communication. You can pick up both for about $5 incl. first class postage:
8 digital I/O pins search.digikey.com/scripts/DkSearch/dksus.dll?Detail&name=MCP23009-E/P-ND
8 analog inputs search.digikey.com/scripts/DkSearch/dksus.dll?Detail&name=568-1087-5-ND
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
When the going gets weird, the weird turn pro. -- HST
1uffakind.com/robots/povBitMapBuilder.php
1uffakind.com/robots/resistorLadder.php
You're very right, it's almost 10x the price of those chips for a breakout board and some blinking LEDs....
I'll definitely go with the chips, looks like the same thing. Digikey is the place to go, looks like they have any chip known to mankind.
Thanks.
I was trying to get across the point that using the base address, $64, in the slave address position, results in a write.
Using the base address +1, $65, in the slave address position, results in a read of the specified register (internal register address).
Example from Devantech for reading the "0" register of the TPA81 thermal sensor: I2CIN SDA, $d1, 0, [noparse][[/noparse]Ver, Ambient, Pix1, Pix2, Pix3, Pix4, Pix5, Pix6, Pix7, Pix8 ]
This register contains 10 bytes. The base address of the TPA81 is $d0. The "[noparse][[/noparse]index, 2]" was an artifact from your code above.
Based on the Robotics Connection IOWizard documentation, the correct register to read maybe register "0" or maybe "1", it is hard to tell. You will notice he says: "...then read back 20 bytes from its address +1." The base address +1 is $65.
I happen to have a RangeWizard from Robotics Connection, but have yet to try and communicate with it over the I2C interface. The problem modemman has been having with the IOWizard caught my attention because it uses the exact same programming for I2C communication.
I have had a lot of success using the Devantech products that communicate using I2C.
Hope this helps
Regards,
TCIII
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
If you are going to send·a Robot·to save the world, you·better make sure it likes it the way it is!
Thanks. I did try both $64 and $65, I think you write to $64 and you read from $64+1 - although there are places in the doc that say different things. Even their code examples are kind of strange.
Incidentally, both I2CIN SDA, $64... and I2CIN SDA, $65.... return the same exact results, if I go to $63 or $66 all hell breaks loose. I could've sworn that I read somewhere that the Basic Stamp implementation of the I2CIN figures out where to read from, knowing the "Slave ID". I'm too new at this so I could be imagining it - I looked up the Parallax docs and I don't see anything of sorts....
The problem is not reading it, I got that step - but its instability and the fact that more than half of the GPIO pins don't react at all as inputs (I can flip them fine as Outputs). Also, the analog inputs bleed like crazy. For example, if I throw 5V at the first analog pin, I do see wacky numbers going up, but also in the adjacent inputs, that is the second input shows high values, the third one goes up, the fourth one jitters, etc.... I hooked up some Sharp rangefinders and took a big piece of cardboard and tried to move it closer or farther, there was no apparent correlation between distance and the numbers dancing in the debug window. I think it's just broken.....
I got a line following sensor with 5 QTI modules on a I2C board also from Robotics Connection. Never used it before but got curious. Hooked that one up for testing and that one works like a champ (it has 5 GPIOs plus 2 headers for extra sensors) - I read 7 bits, 5 are changing based on input from the IR sensors, like they should. The board is on the same pins, with the same pullup resistors, same Vin, Vdd and Vss, basically same scenario.
Love Devantech - great robotic parts. With the risk of repeating myself though, I've never encountered more clearly written and complete documentation as with Parallax.
I came to the conclusion that while the I2C protocol is very clearly standardized, implementations differ. I also don't like the fact that I'm forced to read all 20 bytes every time I query the IOWizard board.
I love the SPSTR modifier (or whatever they call it) that just dumps everything into the scratch pad and organizes it neatly into bytes.
QUESTION: Is it OK to use the scratch-pad like that? That is, using it for near-real-time reading of sensors attached to I2C boards? What type of memory is that? Does it have a finite number of write/read cycles? How much, approximately? It would be quite terrible if one's embedded gizmo just died in the middle of some critical application because the thing wrote too many times to the SP....
I'm definitely going to get those chips that Zoot recommended. This experience made me realize that I want a separate chip for ADC and a separate one for GPIO. Also, it's a sin NOT to go this way, the whole thing costs less than a sandwich.
For right now I solved my "out-of-pins" issue by hooking an extra BS2 chip that I had from the upgrade to BS2P. It's actually quite excellent and fun, I get 14 pins and my expensive Stamp is put to work. Plus, I get extra variable space and can make one Stamp run things from the other Stamp. Multitasking with the Basic Stamp, it's just unusually cool.
modemman
It's RAM, write/read gazillions of times.
The LSB of the slave addr IS ALWAYS the r/w bit -- so addr 0xZZ is always EVEN and addr 0xZZ+1 is always the same device for read.
I2CIN and I2COUT automatically set the r/w bit (bit0) of the slave addr NO MATTER WHAT YOU PUT, but it's good form to set that bit anyway for clarity
so
I2COUT SDA, $A0, $00, [noparse][[/noparse] myVar ] ' writes myVar to register $00 in slave chip $A0
I2CCIN SDA, $A1, $00, [noparse][[/noparse] myVar ] ' reads myVar from register $00 in slave chip $A0 -- with LSB set to 1 for read
I2CCIN SDA, $A0, $00, [noparse][[/noparse] myVar ] ' reads myVar from register $00 in slave chip $A0 -- same thing -- Pbasic will set bit0 = 1 of the addr anyway
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
When the going gets weird, the weird turn pro. -- HST
1uffakind.com/robots/povBitMapBuilder.php
1uffakind.com/robots/resistorLadder.php
In terms of the IOWizard and analog bleed, theres a post on their forum https://www.roboticsconnection.com/userForums/Topic1010-10-1.aspx that says its a bug, needs a firmware fix and gives an address to send the sensor back for an upgrade.
I have used the devantech stuff a lot and never had a problem - including the GPIO chip.
Update: I had a IOWizard but hadn't got round to trying it. I managed to make it work but·it took some work. I got it working with the Propeller, I ended up writing a special purpose I2C driver for it, the normal I2C drivers dont work. At least one issue is it needs clock stretching - it inserts a delay of 1ms before each read byte. I dont know whether the stamp supports slave clock stretching or not. Without it, its not going to work.
Post Edited (Timmoore) : 5/16/2009 3:15:14 AM GMT
Just wanted to post an update, so maybe someone else can benefit from this.
In my original post, I was questioning the speed and flexibility of an I2C port expander because the first I2C board I ever tried was not the best option.
Since then, I tried a few options and came to the following conclusions:
1. There are specialized chips out there that are much better than some custom board based on a microcontroller (whether a PIC, and SX or anything else) - the microcontroller version can be more powerful in the sense that one can write code to take care of complex tasks and calculations, but then again, its performance depends largely on the effectiveness of the code that one programmed into it. If you're the one doing it, well, then you're not reading this post - if like me, you use someone else's, then you get what you get and you don't get upset. The dedicated chip however, was designed in the labs of a large chip maker and was optimized and then re-optimized for its one very specific task.
For the GPIO part, I now use this chip:
search.digikey.com/scripts/DkSearch/dksus.dll?Detail&name=MCP23017-E/SP-ND
I must admit I started with a MCP23009 version, on a breakout board. Then Zoot opened my eyes and I realized I'm wasting money - the breakout board didn't really have anything extraordinary (contrary to the marketing, which promised unique features), as the chip itself is self contained. My soldering skills do not go over stuff that can be done with a $10 Radio Shack soldering iron, so I'll never be able to use a chip in a SOIC or HVQFN package.... But a quick search on digikey.com revealed some equivalent DIP packaged chips. Those can go directly on a breadboard or on a proto board.
2. Using the approach from no. 1, you can build yourself a variety of robotic interfaces, on very small boards. Only 4 wires are needed between the carrier board and your main microcontroller board - actually, there are only 2 data wires, you might want to use a separate power supply (3.3V or 5V, depending on what you have). Since the robotic project that started this for me is an open project - meaning it is used mostly to experiment, learn and test things to be used in real projects with goals, I prefer to use breadboards. For example, I was able to squeeze on one little breadboard the above mentioned chip that gives me 2 banks of 8 GPIO inputs/outputs, a chip that does real time clock (RTC), a speech module (SP03 from Devantech), a little 32Kb eeprom to hold text for the speech module and a pair of BlinkM modules that are used as headlights, mood lights, status lights, etc.. (if you like LED gadgetry, status lights, etc.., get those, they're awesome - 12 bucks from Sparkfun, it sounds crazy expensive for a LED, but it's an I2C addressable RGB with memory, fades, scripts, etc...). The wiring is extremely simple - just connect all the 5V, grounds, data and clock pins together. To make things easy, I hardwired 2 pullup resistors to my controller, so I don't need to worry about it.
3. Speed was really the original question I had and I'm happy to report that the system is extremely fast, relatively to the speeds we are used to when building robots with Basic Stamp. The I2C chips I use are much faster than the BS2P can address, so no bottlenecks there. I also made sure I use chips with very simple addressing schemes, basically one initialization routine, then just basic I2CIN commands to read the registers, or basic I2COUT commands to start/stop things. I did hook up 8 digital IR sensors (Sharp GP2Y0D810Z0F) on my bot (2 for sides, 3 for front, 2 for holes in the ground and one for back) and I can read them as fast as I could by directly reading the Stamp's pins.
So thanks everyone for writing in this thread. Not only I solved my problem, but I also learned a lot from all of you.
modemman
Post Edited (modemman) : 5/18/2009 2:04:03 PM GMT
As I indicated in one of my earlier posts I have the Robotics Connection RangeWizard, but have not attempted to use the I2C port yet with my BS2p.
Am I going to have the same problem with the RangeWizard as modemman had with the IOWizard?
A workaround would be to use the RangeWizard's serial interface.
Regards,
TCIII
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
If you are going to send·a Robot·to save the world, you·better make sure it likes it the way it is!
With the IOwizard I haven't got the standard I2C routines going - I am guessing it is a speed issue since I am software driving the I2C. Once I got it going I found problems with the wrong readings for some ports - which is a known problem and they are upgrading the firmware to fix the problem (my iowizard is in the post to them for the upgrade).
I looked through the BS forums a bit and it looks like the BS2p supports clock stretching so that shouldn't be a problem.
Looking at the rangewizard forum there are people who have got it going successfully so you shouldn't have the wrong reading problem but whether the I2C is going to be straight forward or not I am afraid you will have to try it and see.
Thanks for the info. Much appreciated.
Regards,
TCIII
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
If you are going to send·a Robot·to save the world, you·better make sure it likes it the way it is!