Modular Stackable Microcontroller System (lots of pics)

Hello,

I just wanted to share the project I am currently working on as I know a number of people have been curious to see it.
Sorry for the long post!

The project started off around September of last year and has progressively developed into what it is now.

Ill start of saying this project is NOT complete. All of my boards are printed locally at a printer who cannot do plated through holes, or a raft of other standard things most board houses do these days. That said, each 80x80mm board only cost a few dollars (NZ), so perfect for prototyping.

The initial design was to make a controller suitable for use on a number of my friends projects. He is a mechanical engineer and has an amazing home workshop. He always has projects on the go, and I have done a number with him and made custom PCB's to do a particular task.
As I thought more about this 'controller' I decided to attempt to make something modular, more like an industrial PLC.

The very first design was 100x80mm in size, and featured a Atmega644P main processor board, which talked over I2C via cables to a Relay Board with a MCP23017 IO expander on it, and an Opto Isolated input board with a MCP23017 on it also.

It then progressed into stackable boards with headers top and bottom, and standoffs - which is where we are now. This is the 3rd revision of the design, but still far from where I ideally want it to end up.

99% of the components are Through Hole - as SMT are not really that ideal for hobby projects however are possible to use obviously. Some components are SMT however as they are the only package some chips come in, however I went for the largest size ones I could in those cases.

Anyway, onto the detail.
I have 10 PCB's current, each measuring 80mm x 80mm in size, and stack together. Each PCB has a certain function, just like an industrial PLC module.
Most of the boards are smart boards, and talk to the main processor board over I2C, via Adum1250ARZ I2C isolation/hot swap chips. Each board has isolated DC/DC power supplies, which isolates them from each other and the power supply board, so if one board goes pop - it hopefully will not effect the rest. I also have a chip on most of the boards which isolates the reset line, so a reset from the processor board will reset all the other modules. Boards can be added and removed while power is applied too - a nice to have.

Onto the pictures and the detail of each board.

The headers you will see in the pics... The large 18 pin header which runs up the spine of the 'tower' delivers power to the boards. It carries the Raw source voltage for boards which may require that, and 2 independant 5V lines, and ground. The small 6 pin header next to this is the I2C backbone (not on PSU or Comms board). There is also additional 6 pin headers on the PSU, Comms Board and Processor Boards, which do seperate things, detailed soon.

Power Supply Board. This board features 2x 5V Switch Mode power supplies, each capable of delivering a max of 3A. Whether my design is good enough to handle this, I am not sure, however I doubt I will require that much power. This board supplies power to the main bus, and each board taps off this supply via a DC/DC converter (or 2). This board has current sensors which feed an analog signal back to the Processor Board, so I can attempt to see how much current is being drawn from each supply.

Comms Board. This board has headers to plug in a Wiznet 812MJ Ethernet module, and a Sena ESD110 V2 Bluetooth Module. The Wiznet communicates to the Processor Board via SPI, and the Bluetooth Module communicates to the Processor board via Serial. This board features dual 3.3V DC/DC's, which are powered off the 5V supplies from the PSU board. This board is effectively an extension of the Processor Board, and is isolated from the main power bus, however is not isolated from the processor board.

Processor Board. This board features a Atmega1284P AVR, DS1307 RTC (I2C), 256k EEPROM (I2C), FTDI programming, ISCP programming, and a MAX232 for RS232 comms. This is obviously the powerhouse of the design, and talks to each of the modules over the I2C bus, and talks to Serial LCD's, Bluetooth, Ethernet etc. I have not yet had success making the Ethernet work with the 1284P, however I have had it working fine with a standard 328P or Arduino - so not sure what the problem is at this stage. Either a core or a library issue, but not sure which. This will be solved in time im sure.

Opto Isolated Input Board. This board features 8 opto isolated inputs, which feed into a Atmega328P. It is capable of taking 5V inputs, or each input can be toggled to take 24V too if required, so it can handle more 'industrial stuff'.

Relay Output Board. This board features 4 relays, capable of switching 250VAC @ 10A, or 30VDC @ 10A. It features a MCP23017 IO Expander.

Analog Input Board. This board uses a MAX127 which is an awesome chip. It is a 12bit ADC that has software configurable input ranges, 0-5V, 0-10V, +/-5V and +/-10V, and talks over I2C. It has buffered Op Amp inputs, which I have added resistor spaces to so the op amps can be used as amplifiers if required, for situations where you have a 0-1V input source or something like that.

Analog Output Board. This board has a 328P on it, and simply outputs 4 PWM's into an op amp, which has a 12V power source, so 0-10V analog outputs can be achieved. This board hasnt been tested yet as I forgot to order the 12V DC/DC.

High Speed Counter Board. This board features a 328P, and takes up to 4 inputs. 2 of these are hardware interrupts and 2 are Pin Change interrupts. I have a software design which accurately allows me to count very fast input pulse trains accurately. I have tested this design on an existing PCB which is being used, and it works well. I ran out of wire-to-board headers, hence the unpopulated bits. The inputs are opto isolated too, and are switchable from lower voltage inputs to higher voltage. It seems to work from about 3v to 24v or so, so quite handy.

Sensor Board. This board features a 328P, and has a port for a SCP1000 Barometric Pressure Sensor, and a port for a SHT15 or similar Temp/Humidity Sensor. It also has another port which could be used for another SHT15, or can be used for a Serial device of some kind, as its on the hardware UART.

General IO Board. This board was made (or not yet made, as is the case) to allow the 'tower' to have 16 general purpose IO. It has a Atmega644P on it, and can be used to interface to LCD's, or for testing, or push buttons etc etc. The board could even be used by itself (well, with the PSU board) as just a general 'arduino' like microcontroller.

Encoder Board. This board is in progress, and will be similar to the high speed counter, but will have a couple of encoder inputs for directly interfacing to quadrature encoders etc.

Here are some other photos, and of the tower being assembled with the standoff's. The first one is the bottom of one of the boards, showing the Samtec headers that are on the bottom. Samtec rule for free samples!






All the boards run on standard 16Mhz crystals except the Processor Board, which I have running on 18.432Mhz.

So yeah, thats it so far.
Each board has its own program obviously, and then the main processor has the main code which interfaces to the modules to do stuff/receive info etc.
Since its on I2C you can just keep stacking the boards until you run out of addresses or run out of power. Most boards have processors so the addresses can be changed easily, however some boards are MAX127's or MCP23017's, so have limited addresses, so their type is more limited in terms of quantity of those boards in 1 design.

At this stage, I only have 4 bit DIP's for addresses on the boards with processors, which obviously means the addresses will run out sooner rather than later. This will be changed in the next revision, as will a number of things. This is all just proof of concept at this stage.

But that is where I am at, hopefully someone has enjoyed the read and the pictures at least :slight_smile:
I have 5 projects lined up which will use this concept, so very exciting times to come.

Let me know any comments, critique etc - Im here to learn too.

Thanks
James

thats it so far.

Is that all?

Wow, like I said when saw the 3d mockup, I get vertigo just looking at it.

The other day you said you got the 1284 bootloader working , was that at 18.432Mhz?

4 bit DIP's for addresses on the boards with processors,

If the pins used for this go to ADCs you can use trinary encoding (albeit not with normal DIP switches) to get 64 addresses from 4 inputs or 27 from 3 inputs.

The photographer in me says you should have more depth of field in the shots :slight_smile:

Good job, it will take you another year to write all the software now.

PS: For industrial use I think you should ad RS-485 capability


Rob

Wow! Very cool looking/sounding system!

I don't care if this hardware ever actually accomplishes ANYTHING. It is simply a work of art. What an awe-inspiring design. I am such a fan of hardware that just looks clean, well-organized and well-designed. I can't wait to see what types of jobs you assign to these modules. Congratulations on creating a beautiful, and highly useful collection of hardware.

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.