Modular Stackable Microcontroller System (lots of pics)

Thanks :slight_smile:

Rob - Software wise, I have most of it working already. By no means final, but I have the boards talking.

High Speed Board, Opto Input Board, and Sensor Board have code written, and they successfully talk to the Processor Board already. Analog Input Board and Relay Board obviously dont have processors so dont need software on the board itself, however I have test code written in the master which talks to these successfully too. Its just the Analog Output Board, General IO Board and the Encoder Board which I have not done anything with yet, mainly because I dont have these boards finished yet :wink:

Oh and I agree, RS485 would be nice. I might add that to the Processor Board for the next revision.... if I can fit it on. I might change the RS232 to be RS485....

Photos - yeah they are poor! Have a nice Canon DSLR however I didnt think too much about it before I took them. I should redo them.... but im sure you get the idea :wink:

Thanks for the comments everyone.

Oh and Rob, yes the 1284P bootloader is working and running at 18.432Mhz - thanks to Mark S.

Very nice indeed! I'm very impressed.

You could probably eliminate the DIP switches on the boards that have processors by having some sort of protocol to "set your I2C address" (which would then be remembered in EEPROM). (eg. do a broadcast to address 0 telling chip x to set its I2C address to Y).

Or even not have a protocol. Just have the processor boards grab their I2C address from a known address on the EEPROM (eg. address 0). Then before loading the "main" program (and before inserting into the stack) just power it up with a tiny program that writes the desired address to the EEPROM. Then upload the real program and you are done. It means pulling the board out of the stack to change it, but that wouldn't happen that often would it? That takes less hardware and lets you use any address at all.

Plus, if you read the address from EEPROM that frees up the pins you have connected to read the DIP switch, giving you more general IO pins.

Thanks Nick - ill give that some thought.

In terms of freeing up IO pins, in most case IO pins arent an issue. Since each board has a specific function, anything over and above those functions is effectively wasted. Ie, for the high speed counter board, I really only need 4 pins (if you ignore the address pins). The board cant really have any more inputs than that as I need the processor to be able to count really fast. ie a Test I did was it to read 10,000 pulses a second. If I had more than 4 inputs, then I am not sure if the uC would handle to count 4 channels at that rate. Ideally the 2 External Interrupts is all I wanted, but I put 2 Pin Change channels on there too, just incase there is a need.
Next week I am taking this out to a mates place, who has a function generator. I will crank that up and see what the limitation is of the uC and the software I have written for it. I can then determine if more inputs are appropriate etc

So yeah, it would be nice to get rid of the dip switches, but to do it to free up IO probably isnt the driver.
In the case of the General IO board, then yeah - fair point.

If I keep the same sort of size terminals, then I can fit 12 wires. They are 5mm pitch terminals so on the large side, maybe. I might look and see what the next step down is, probably 3.x I would think. That said, most boards are not restricted by the terminals, but of real estate due to the large through hole components, track size that I am restricted to with my current printer, not being able to have plated through holes so lots of manual vias, etc etc.

But yes, lots to improve on.
Ideally I want it to be all SMT, but its not really achievable if I am assembling myself, and I dont have the money or customers to make 100 of each board and get them assembled professionally.

Quite a lot of parts used were free samples I managed to get from manufacturers. ie the MAX127's I got 5 samples after pushing really hard. These are not cheap chips, about $58NZ from Digikey each!
Sample wise I dont have a huge amount left. I may be able to make another partial set, I am not really sure.

I would quite like to make this a backplane system too, rather than a stacking system, so modules can be inserted individually rather than stacking together and having to unbolt them all to get at one in the middle etc. More thought is needed though. It shouldnt be hard to do though, take off the stacking spine, and put 90 degree ones in, and then make a set backplane which takes like 15 modules or something, and then plug them on and attach them somehow. I wouldnt need headers top and bottom of each boards then, only 1 side as the backplane will join everything. I probably wouldnt need to change much at all to achieve this. The 2 6 pins headers that feed the ethernet board etc I would have to do something about, but that should be ok.

Lots I could do.

Any more ideas anyone - I need ideas! I want to keep improving, and the more improvements I can make each revision, the cheaper the overall project will be. Each revision is destructive too, as I need to pillage parts to make the next one. A little tricky with the SMT stuff though.

small steps James, small steps.

Just thinking... PLC's get their module address based on the position they are on the backplane.
I could have fixed length backplanes, like what you get with PLC's, say 5, 10 or 15 long or something.
Each backplane could even have a set of dip switches on it, and each module reads in this address and sets itself along with the position on the backplane. If you need more modules, expand over to another backplane and set the address to be the next one, etc etc.
Something like that may work...

It would save having a dip switch on each board, which would be nice, and addressing would be done based on position which would eliminate the change of having 2 modules with the same address. How this would work for the 'non processor' modules, I am not 100% sure. I could change the MCP23017 module to be a 328P, which would simplify that, however I still have the MAX127 which will have a fixed range it can be. I suppose I could reserve the whole MAX127 range and not allow other modules to use that range.

hmm. The possibilities.

James

I've done the backplane address thing in the past and it works well enough.

One thing I don't like about that system is that all the addressing changes if you decide card X should be one slot to the left, so all the other cards move up one.

How about a combination of the two approaches.

Every micro-based card has an address in EEPROM that is null to start with. If that value is null the card gets the address from the backplane, if not it uses the EEPROM version.

So cards can spend their life using the backplane address, but if you want some stability you have a utility that tells it to write an address into EEPROM.

Backplane addresses are < 16, EEPROM address 16 to 255 (or whatever).


Rob

That sounds like a good idea.

And like what you guys said, store it in EEPROM if required.
Start off each as Null, and read 4 bits off the backplane to get an address if told to by software. Once they have their address in RAM, that address can be locked into EEPROM by software.

How would I go about setting the address of modules 16 to 255 though? If they can only get 4 bits from the backplane and I need 2 backplanes joined together, then there will be modules with the same addresses.
I dont particularly want to have to rewrite software into each module seperately each time I plug them in, if I have more than 16 modules.

How would the broadcast work, like what Nick said.

You could probably eliminate the DIP switches on the boards that have processors by having some sort of protocol to "set your I2C address" (which would then be remembered in EEPROM). (eg. do a broadcast to address 0 telling chip x to set its I2C address to Y).

If there are addresses for 1-16 from the backplane, and the next backplane is also 1-16, then without unplugging the first one and telling "address 1, you are now address 17", "address 2, you are now address 18" etc... and then plugging them back together, what would the method be here?

Maybe a slightly different approach. You can put the processor into an 'Address Mode', which basically broadcasts every second or something. Start off with only the processor loaded on the backplane. Each module maybe has Address 100 or something loaded into it by default (or 128 or whatever). Load on the first module which is address 100, and the broadcast will say, if you are address 100, now be address 1. Saves it to EEPROM. Load in module 2, which is address 100, it says 'I already have an address 1 on the bus, you are therefore address 2', and saves it to EEPROM. etc etc...

Would something like that work you think?

Cheers
James

WanaGo:
Just thinking... PLC's get their module address based on the position they are on the backplane.

I'm not an engineer but I've seen this type of addressing by slot position. Possibly encoded by some wiring in the box?

Your system is very much like industrial equipment, surpassing the type of things most of us see or make here. It looks very awesome.
On another thought, since the pins are no longer compatible with arduinos, your market falls between the happy land of arduino newbies and hardcore PLC people. Will you be selling them very soon?

Hi Liudr

I am an Automation Engineer by trade, so you can probably guess where this project stemed from :slight_smile:

The aim of this project was for me to design a PLC like device which could be used for a number of projects, where hardware would not have to be redeveloped for each project and the project could be easily expanded. And a PLC fits those needs in most ways, however PLC's are expensive.

The intension was never for it to be pin compatible with the arduino platform, however it utilises the Arduino software, libraries etc.

The market was really only going to be myself, and one day it may go commercial. I am only 6 years into my working career as an Automation Engineer and one day I want to start my own automation businesss. Having something like this may be suitable for small automation projects where cost is an issue.

Once I get the hardware to a level where it is reliable, easy to use etc, then I very well may look at selling it. But it wouldnt be a cheap process to start as I would have to get multiple boards made at once in order to get them professionally made. I would also need to trim the fat and make each board cost effective. They may be ok now if I buy the components in bulk rather than 1 off's, I am not sure.

I would probably need assistance from another company in order to get it to that level though... RuggedCircuits etc etc :stuck_out_tongue:

I am just trying out the assigning address method as mentioned at the bottom of my last post, so far it looks promising.

Thanks
James

If I have a module which starts up at say Address 100, and executes its Wire.begin(100) in the setup routine, how do I go about ending that, and getting it to start up as a fresh address?
ie end Wire.begin(100) and start Wire.begin(1).

Is it possible to do this without doing a power cycle and loading from EEPROM?

I do want to do the EEPROM method, but I still need to start up as an address, talk over i2c, get reassigned and talk over i2c as the new address - etc.

Can I simply call Wire.being(x) again and overwrite the last one, or do I need to write to a register to end the previous one?

Any ideas?

Calling wire.begin(x) from inside the interrupt of the transmission from the Master seemed to work fine.

Module started as address 100.
Master started up.
I type 'A' into the Serial Terminal which goes into addressing mode. (Just as a test).
Master does a scan of all the devices on the bus, once a second.
In this case it reported back address 80 (my EEPROM) and address 100 (the module).
If an address == 100, assign it to the next available one, in this case I made it the last device before address 100, + 1.
So next address is 81, master then sends bytes 'A' and '81' to the module at address 100.
Module reads in the data, sees that an Address command has come in, reads in the new address and calls Wire.begin(81).
Master is still scanning the bus once a second, I see it change from 80 & 100, to be 80 & 81 on the bus :slight_smile:

So proof of concept seems to work :slight_smile:

Hope this becomes the first industry-regulation-approved arduino design soon!

My suggestion: you need HMI if you want to do automation, right?

Yep, an HMI is needed in alot of cases.

I have Ethernet, Bluetooth and RS232 Serial, so lots of possibilities of adding an HMI. RS232 most likely will be swapped for RS485 in the next revision.

I currently have a 24x8 character LCD with a serial backpack talking to my tower, all it needs now is buttons from the General IO board and its a very crude interface.

I have implemented the Modbus library in one of my previous designs, getting Modbus TCP and Modbus Serial working and they seem to go pretty well.

I even have an old school HMI here at home that I have borrowed from work, which speaks modbus RS232 and I have successfully populated that with data, made it draw sine waves etc.

A mate of mine started a Python interface with graphs and dials for a Dyno project which is still on the cards, however I am not sure how much further he wants to go with this.

Got some ideas?

I'm working on TUI and GUI on text LCDs and GLCDs. I have a phi_prompt library that one can use to construct HMI functions such as inputting numbers, selecting item from lists, menus of infinite levels, text inputs, text area displays with scroll (up/down keys), Y/N dialogs, OK dialogs. I didn't go as far as creating bar graphs or data charts on text LCDs but will consider it on GLCDs.

I use a four-directional pad plus two more keys for all inputs. The interesting thing for my buttons library is you can assign auto buttons that gets automatically pressed to save a physical button if you need, like inputting your name after beating the high score on a game console.

Take a look here see if you like any of the functions:

New features to be released next Monday:

http://arduino.cc/forum/index.php/topic,60830.0.html

Released features can be found here on my blog:

Very nice work.

Implementing this on the 24x8 LCD's I have would be very cool.

This is where I got a couple from. They accept TTL level Serial or RS232 Level Serial, @ 19200 baud.
http://cgi.ebay.com/Intel-8032-Single-Board-Controller-Serial-24-x-8-LCD-/120726684894?pt=LH_DefaultDomain_0&hash=item1c1bdf04de

I have about 6 of them. They were $15 at the time when got them.

WanaGo:
Calling wire.begin(x) from inside the interrupt of the transmission from the Master seemed to work fine.

I don't know that I would do that inside an ISR, but from what I can see doing another Wire.begin is the way to change the slave address.

WanaGo:
Very nice work.

Implementing this on the 24x8 LCD's I have would be very cool.

This is where I got a couple from. They accept TTL level Serial or RS232 Level Serial, @ 19200 baud.
http://cgi.ebay.com/Intel-8032-Single-Board-Controller-Serial-24-x-8-LCD-/120726684894?pt=LH_DefaultDomain_0&hash=item1c1bdf04de

I have about 6 of them. They were $15 at the time when got them.

My library is built entirely over the LiquidCrystal library so if LiquidCrystal runs on this display, there is no reason the library won't run. Its layer is higher than hardware display driver library so I hope to port it to more displays with minimal work. What library do you use on your display?

@liudr
I've been watching your menu library with interest. I'm currently designing a LCD board (with RS485 for remote displays) and it might be good for that.

Unfortunately I only have room for 4 buttons, is it still a goer without the extra two?

@wanago
Re HMI, I've just got two 4D Systems 3.2" LCD with touch. Serial interface so they would be easy to use.
Re RS485, if you add RS485 all my modules I'm designing should work with your system and give you access to remote sensors, displays, GPS, accelerometers etc. I would still keep RS232 if possible though because there's a lot of legacy equipment you'll need to talk to.


Rob

Graynomad:
@liudr
...
Unfortunately I only have room for 4 buttons, is it still a goer without the extra two?

...


Rob

I wonder if you could make up the last two buttons "logically" with a "chording" of some combination of other buttons...