More inputs and outputs needed

koyli

Member
Hello everyone. This is my first post to this forum and I am asking for help/advice as to how to increase the number of I/O pins and if this is possible, how to access and control them.

The project is to control the signal interlocking on a model railway. My original plan was to use standard logic gates, but to make the circuit board simpler I decided to use microcontrollers.

I have managed to do the simplest end of the layout with a 28X2 which had just enough pins to control enerything, but the other end is far more complex and requires 69 inputs and 25 outputs.

Is this possible and if so what do I need and how do I go about it?
 

westaust55

Moderator
Welcome to the PICAXE forum.

One option is some cascades 74HC595 chip for extra outputs and 74HC164 or 165 chips for extra inputs.
These can be controlled with X2 parts using the SHIFTOUT and SHIFTIN commands.

Next option is to use MCP23017 chips. These are i2c based IO expanders. Each pin can be an input or output.
Each chip has 16 IO arranged as 2 8-bit ports.


Example code for using both is available on the PICAXE forum.
 
Last edited:

koyli

Member
Welcome to the PICAXE forum.

One option is some cascades 74HC595 chip for extra outputs and 74HC164 or 165 chips for extra inputs.
These. An be controlled with X2 parts using the SHIFTOUT and SHIFTIN commands.

Next option is to use chips. These are i2c based IO expanders. Each pin can be an input or output.
Each chip has 16 IO arranged as 2 8-bit ports.


Example code for using both is available on the PICAXE forum.
Thank you for your reply.
Can you explain in plain english how to connect the MCP23017 and how to read/write to the inputs/outputs?
 

koyli

Member
-Thanks to everyone who replied.

This task will probably seem simple to those "in the know" but to a novice it is quite daunting.
I have spent all day reading the manuals several times and some of it is starting to sink in. The trouble with all these kind of manuals is that they are written by evperts who do not write them as though they were talking face to face.
You have to know how the thing works to understand the manual!

Anyway, I will get some IC`s and have a play on the breadboard.
 

premelec

Senior Member
@koyli - assuming you know something about electronic circuits the manufacturer's datasheet for the part you might use usually has good information so that should be read as well as PICAXE manuals - no, it isn't easy and takes a bunch of work :) Have fun...
 

techElder

Well-known member
koyli, now you're doing the right thing, as all of us here have done, too.

Heck, if it was easy, just anybody could do it! :)
 

srnet

Senior Member
The trouble with all these kind of manuals is that they are written by evperts who do not write them as though they were talking face to face.
You have to know how the thing works to understand the manual!
That is almost inevitable in any manual, a basic level of understanding is assumed in order to document the product in a concise way.
 

Dartmoor

Member
You can simply connect two picaxe chips together with a serial data link between them.
This needs no other hardware, just a spare pin on each chip (2 pins if you want to send data back to the interlocking, eg point/train detection etc).
It is explained somewhere in one of the manuals!!
No need to learn I2C etc?
 

lbenson

Senior Member
>You can simply connect two picaxe chips together with a serial data link between them.

This is true, but then you need to develop the protocol for communicating between the two to provide additional I/O for the one you want to consider the master. If you use I2C, you connect two wires (plus power and 0V), and use the established and documented protocol for the I2C chip (for which there are probably examples on the forum). And once you are comfortable with I2C, you have a broad selection of chips with which to expand picaxe capabilities.
 

koyli

Member
Dartmoor

This was my first thought. I have two 40X2 chips but there is not enough inputs. I have 69 inputs and require 25 outputs so my plan is to use the MCP23017 expanders for the inputs and the 40X2 for the outputs.
Does that sound alright?
 

westaust55

Moderator
Such a scheme with a combination of PICAXE and IO Expander pins will work.


You may find it worthwhile to consider having some outputs on the IO Expander chips for more distributed IO.
Although the nominal length of the i2c bus is short, having outputs also distributed may save on wiring from say point motors back to a central location.
 

koyli

Member
Such a scheme with a combination of PICAXE and IO Expander pins will work.


You may find it worthwhile to consider having some outputs on the IO Expander chips for more distributed IO.
Although the nominal length of the i2c bus is short, having outputs also distributed may save on wiring from say point motors back to a central location.
Are you saying I can mount the expanders remotely, away from the PIC,and under the baseboard?
I had never thought of that. How long can the I2C bus be>
.
 

koyli

Member
The PICAXE will not be sending any outputs to the actual layout, it is for operating the interlocking on the signalling lever frame.

The circuit board will be fitted in this cabinet and the track circuits PCB (which I built nearly 30 years ago for a previous layout) also, so the distances are quite small.
The point detection inputs are the only one`s that are distant from the lever frame, but no more than 2m.
I have yet to construct the signal drivers PCB, but that will also be fitted in the same cabinet.

If I fit the expanders on the same board as the PICAXE will it need shielding from the noise from the loco`s?
 

BeanieBots

Moderator
If I fit the expanders on the same board as the PICAXE will it need shielding from the noise from the loco`s?
It is unlikely that you will need "shielding" but you will need to decouple the power supplies.
Will you be powering the PICAXE and the loco's from the same supply?
If yes, make sure motor noise cannot come down the power rail (either the 0v line or the supply line) and into the PICAXE.
 

koyli

Member
Will you be powering the PICAXE and the loco's from the same supply?
.
No, I have 3 power supplies.
I use the 5v from an old AT power supply for the logic circuitry and 2 12 volts from another transformer for the controllers.
Another separate transformer supplies 9v for the track circuits.

The controllers 12v dc and the track circuits 9v dc have a common return.

I just remembered, there is a 16v ac supply for the Tortoise point motors.
 

edmunds

Senior Member
Some time ago, I had the same problem. My need was about 70 outputs as well. I ended up going with PCA9554s and 9555s. While it took a little fiddling to start with, I worked with some invaluable help from members of this forum and still works like a charm to date in a model railroading like application. I never look elsewhere these days, when I need more picaxe pins that the chips have. I'm not in a position to find my own posts (sorry, hate to that sort of thing on the phone), but a search for the above names should easily find them.

I can post some code as well later on if it turns out to be needed.


Good luck,

Edmunds
 

Circuit

Senior Member
Firstly, I am guessing that you will be happier working with DIL/DIP packages rather than surface mount? If so, you will be best off with the MCP23017 which you can obtain from here http://uk.rs-online.com/web/p/i-o-expanders/0403806/ or here http://uk.farnell.com/microchip/mcp23017-e-sp/ic-io-expander-16bit-i2c-28dip/dp/1332088?searchRef=SearchLookAhead. Grab the datasheet from either site and you will get the wiring sorted. Then look here http://www.picaxeforum.co.uk/showthread.php?26267-Need-to-know-code-to-interface-mcp23017-i-o-exp-via-i2c&highlight=MCP23017 for your code to get started. This shows how you can program the MCP23017 for input or output and how to read or set it.

You can address up to eight of these chips on one I2C bus - giving you a potential 128 inputs/outputs. Just remember, as previously mentioned, to connect a 100nF bypass capacitor across and as close as possible to the power pins of each and every chip.

Hope that sets you on the right path.
 

koyli

Member
Thankyou Circuit this is getting me closer to understanding how these things work.

I already have the IC`s and building the hardware is no problem, I can do that all day. It is the software part that is baffling me. Now I have read that code snippet you pointed to I can understand some of the MCP23017 datasheet.

Just a few more questions.

To get all the inputs I require I shall need five expanders so;-

Do I issue all those commands for each expander?

Where/how do I store the inputs on the PICAXE?

Do I need to change anything to use a 40X2?

I`m sorry if all these questions are getting tedious for you, but this is my first venture into microcontrollers and it is a steep learnig curve. I am still on the vertical bit!
I have never really got into coding and the reason I chose the PICAXE micro`s was for the flowchart type programming.
That is what I used to program the 28X2 at the other end of the layout.

Thankyou for your patience so far.
 

westaust55

Moderator
If you look at my original demo code for the MCP23017
http://www.picaxeforum.co.uk/showthread.php?12531-MCP23017-i2c-IO-exapander-data&highlight=Mcp23017
That includes more comments and an example of using interrupts to detect when there is an input change.

You will need to separately address each MCP23017 chip to read the inputs for each chip.
That can be done by including the slave address in the Hi2cin commands so that a single Hi2cSetUp command is possible.
To keep the status of all the input pins you will need to store the byte values read from each MCP23017 8-bit port in either a predefined byte variable (eg b0, b1, etc) or in higher RAM locations using PEEK/POKE commands or the note command.
An X2 part using the ptr pointer can also store the input pin port values in the scratchpad memory.

You do need to send commands to each MCP23017 to set each chip up for use as inputs.

You can configure the MCP23017 so the the two IO posts use consecutive locations so that the PICAXE can read all 16 inputs with one Hi2cIN command into two byte variables or consecutive byte/scratchpad locations.

I suggest that you do some experiments on a breadboard starting with the code I posted first with 1 chip then with 2 or more chips. That way you can determine how YOU want to read and store the data from the input pins.
 

Circuit

Senior Member
Thankyou Circuit this is getting me closer to understanding how these things work.

I already have the IC`s and building the hardware is no problem, I can do that all day. It is the software part that is baffling me. Now I have read that code snippet you pointed to I can understand some of the MCP23017 datasheet.
Given that you are up against a steep learning curve, there is a much simpler way of getting additional inputs and outputs and it is described in FAQ section of the PICAXE website here; http://www.picaxe.com/FAQs/Interfacing/
under the sections titled "I need more inputs - what can I do?" and "I need more outputs - what can I do?". Although I use the MCP23017 for some purposes (and shift registers for others), the addition of a few extra PICAXE chips to the board is often my solution. It is really easy compared with the I2C and shift register options and the serial link only needs one line per linked chip. If, therefore, you link in a couple of 40X2 chips as interface expanders, you can immediately gain more than sixty extra inputs and you are dealing with programming and hardware with which you are already familiar. This would use up only two pins on your main chip, but of course you can add more 40X2s as you need. As you can see from the program examples in the above link, this is almost certainly your least complicated (and possibly the most reliable) option.

Furthermore, because the serial link between PICAXE 40X2 chips is rather robust, you don't have to be concerned over length of cable runs etc. I find that this works really well on model railways - on one layout I control all my points this way. I have also programmed the outputs to be single-pulse so that they can fire solenoid point motors correctly via MOSFETs.

I think that your best bet would be to put the I2C port expanders to one side (but keeping on with the learning experience on a breadboard) and buy a few 40X2s and remain in familiar and robust territory. You may even find that you are adding to the programming of the slave 40X2s to "contract out" some of your subroutines etc., as I have done with my pulsed points interface.
 

lbenson

Senior Member
If I were going to use additional 40X2s, I would still use i2c and would make the additional ones i2c slaves, with the i2c master accessing the first 128 bytes of the slave's scratchpad as if it were 128-byte i2c eeprom memory.

Then, on the slave side, for all inputs (32 bits), the code would be this:

Code:
#picaxe 40x2
  hi2csetup i2cslave, %10100000 ' set up i2c slave mode & address
do
  b0 = pinsB
  b1 = pinsC
  b2 = pinsA
  b3 = pinsD
  put 0,b0,b1,b2,b3 ' write 4 bytes (32 bits of input) to scratchpad memory
loop
For the master, the code would be like this:
Code:
#picaxe 40x2
  hi2csetup i2cmaster,%10100000, I2Cslow, i2cbyte
  pause 40
do
  hi2cin 0,b0,b1,b2,b3
  ' now do what you need to do with the 32 bit values in b0, b1, b2, b3
loop
Add additional 40X2s as needed, adjusting the hi2csetup command, or as westaust55 suggests, use the "location" parameter in the hi2cin & hi2cout commands to select the appropriate slave 40x2 (or 28X2 or 20X2).

You do need to make sure that the I2Cslow parameter is appropriate for the speed of the slave, for instance, I2Cslow_4, I2Cslow_8, etc.

Note that A.4 is output only, so you get a maximum of 31 bits of input on the 40X2.

[EDIT: you must also subtract the i2c pins, so you get a maximum of 29 bits of input on the slave 40X2.]
 
Last edited:

koyli

Member
Thanks westaust and Circuit, some very good advice allround.

I will keep working on it. At the moment I am still laying track, but trying to learn this as well.

It`s amazing to see that nearly every reply has come from a diferent country.

Thanks also Ibenson, your post came in as I was writing this one.
 

Circuit

Senior Member
If I were going to use additional 40X2s, I would still use i2c and would make the additional ones i2c slaves, with the i2c master accessing the first 128 bytes of the slave's scratchpad as if it were 128-byte i2c eeprom memory.
An elegant way of working, but please remember that this gentleman indicated that he is at the very beginning of writing code; he has been using flowchart programming so far. He will take some time to get up to speed with the operation of I2C, use of scratchpad memory etc. Furthermore, I2C is not without its reported issues; some of our most experienced posters have run into trouble with I2C lockups etc. as well as interference issues on the line. (http://www.picaxeforum.co.uk/showthread.php?19694-Does-12c-lock-up ; http://www.picaxeforum.co.uk/archive/index.php/t-18654.html ; http://www.picaxeforum.co.uk/showthread.php?24087-i2c-port-lockups-in-20X2-Slave&highlight=i2c+lockup etc. ) - Incidentally, Inglewoodpete, did you ever sort your particular issue?

It is because of his position on the learning curve that I am suggesting he would be best off with a simple but reliable serial link as suggested by and documented in the PICAXE reference pages, but I do acknowledge that your solution is a very practicable way of working but is perhaps more suited to the more advanced user.
 

Circuit

Senior Member
Thankyou Circuit this is getting me closer to understanding how these things work.

Where/how do I store the inputs on the PICAXE?
Well, this appears to be my 200th posting! Koyli, we have all been where you are at some time. I hope that I am not reading your experience level inappropriately with this one, but perhaps I can suggest that you have a look a the way that PICAXE Basic handles variables in this context.

Each variable, represented by b0, b1 etc. is an eight bit binary number. Assuming that you are using any of the interface expansion systems that we have been talking about, you will have an eight-bit variable representing the port status. When you map an input port to a variable then each of the contained binary digits represents one pin of a port. e.g. PORT C, four pins high and four pins low may be represented by b0 which will show the number 15 or, in binary, "00001111" If you use the first four variables, b0, b1, b2, b3, then you can address any single binary digit within these (i.e. any pin on the ports that are represented by the variable) using "bit0" through to "bit31". Have a look at PICAXE Manual 2, page 11 for a fuller explanation.

You can make things a lot easier by assigning a name to the individual bits using SYMBOL (manual 2 page 7); for example " SYMBOL Station_home_signal = bit7" or "SYMBOL track_occupancy_detector_5 =bit17". This allows you to use algorithms such as "If Station_home_signal = 0 and track_occupancy_detector_5 = 0 then...." etc.

This will only work for byte variables b0 to b3, of course, but you can work around this by using higher variable names for storage and then mapping them over to the lower variable names for computation, though you would have to also rethink the use of the SYMBOL convention that you adopt for this.

The use of symbols to represent what is connected to the port by name can make subsequent programming very much easier.
 

edmunds

Senior Member
Code:
'I2C I/O expander addresses
Symbol PCA9554A_1 = %01111000    'Lane 1 DIP switch inputs
Symbol PCA9554A_2 = %01111100    'Lane 2 DIP switch inputs
Symbol PCA9554A_3 = %01110110    'Lane 3 DIP switch inputs
Symbol PCA9554A_4 = %01110010    'Lane 4 DIP switch inputs
Symbol PCA9554A_5 = %01111110    '10x2 rotary DIP switch inputs (2x8421)
Symbol PCA9554A_6 = %01110000    'Traffic lights

'ALCU Picaxe-20X2 I2C addresses
Symbol ALCULane_1 = %01100010     'Lane 1 ALCU
Symbol ALCULane_2 = %01100100     'Lane 2 ALCU
Symbol ALCULane_3 = %01100110     'Lane 3 ALCU
Symbol ALCULane_4 = %01101000     'Lane 4 ALCU

'I2C I/O expander masks
Symbol TLState1 = %00011000         'R1_3 ON G2_4 ON Y OFF
Symbol TLState2 = %00001000         'R1_3 ON G2_4 OFF Y OFF
Symbol TLState3 = %00000101         'R2_4 ON G1_3 ON Y OFF
Symbol TLState4 = %00000001         'R2_4 ON G1_3 OFF Y OFF
Symbol TLState5 = %00000010         'R2_4 OFF G1_3 OFF Y ON
Symbol TLStateOFF = %00000000     'R2_4 OFF G1_3 OFF Y OFF

Symbol AllInputs = %11111111         'All port I/O pins set as inputs or All inputs inverted
Symbol AllOutputs = %00000000      'All port I/O set as outputs

'Command bytes for PCA9554A
Symbol InputReg = 0
Symbol OutputReg = 1
Symbol PolarInvReg = 2
Symbol ConfigReg = 3

'Interrupt pins
Symbol I2CInt = pinB.2    'I2C Interrupt, Active Low
Symbol IRInt1 = pinB.1    'Infrared transmission interrupt, Lane 1
Symbol INT1 = B.1           'Same pin as output for initialization
Symbol IRInt2 = pinD.4    'Infrared transmission interrupt, Lane 2
Symbol INT2 = D.4           'Same pin as output for initialization
Symbol IRInt3 = pinD.2    'Infrared transmission interrupt, Lane 3
Symbol INT3 = D.2           'Same pin as output for initialization
Symbol IRInt4 = pinD.3    'Infrared transmission interrupt, Lane 4
Symbol INT4 = D.3           'Same pin as output for initialization

'Remote access pins
Symbol SerRXPin = pinC.7
Symbol SerRX = C.7
Symbol SerTXPin = pinC.6
Symbol SerTX = C.6

'Automatically set up correct ALCU I2C addresses depending on the Lane unit is connected to
  pause 500                                                                                                  'wait some extra time for ALCUs to initialise
  serout INT1, SerNRate, ("ICCU", ChipAddrMSB, ChipAddrLSB, ALCULane_1)   'send address string to Lane 1
  serout INT2, SerNRate, ("ICCU", ChipAddrMSB, ChipAddrLSB, ALCULane_2)   'send address string to Lane 2
  serout INT3, SerNRate, ("ICCU", ChipAddrMSB, ChipAddrLSB, ALCULane_3)   'send address string to Lane 3
  serout INT4, SerNRate, ("ICCU", ChipAddrMSB, ChipAddrLSB, ALCULane_4)   'send address string to Lane 4

'Intialise I/O expanders
  hi2csetup i2cmaster, PCA9554A_1, I2CSpeed, i2cbyte      'Announce there will be I2C
  hi2cout ConfigReg,(AllInputs)                                             'Configure all Lane1 DIP swithc inputs as inputs
  hi2cout [PCA9554A_2],ConfigReg,(AllInputs)                      'Configure all Lane2 DIP swithc inputs as inputs                     
  hi2cout [PCA9554A_3],ConfigReg,(AllInputs)                      'Configure all Lane3 DIP swithc inputs as inputs
  hi2cout [PCA9554A_4],ConfigReg,(AllInputs)                       'Configure all Lane4 DIP swithc inputs as inputs
  hi2cout [PCA9554A_5],ConfigReg,(AllInputs)                       'Configure Custom Address selector switches as inputs
  hi2cout PolarInvReg, (AllInputs)                                           'Invert all inputs to read correct 1248 BCD switch values
  hi2cout [PCA9554A_6],ConfigReg,(AllOutputs)                    'Configure Traffic Lights as outputs
  
Main:
  gosub ReadSetup
#rem when I2C does not seem to work
  sertxd ("Lane1State is: ",#Lane1State,"; ")
  sertxd ("Lane2State is: ",#Lane2State,"; ")
  sertxd ("Lane3State is: ",#Lane3State,"; ")
  sertxd ("Lane4State is: ",#Lane4State,"; ")
  sertxd ("Custom Address 1 is: ",#CustomAddress1,"; ")
  sertxd ("Custom Address 2 is: ",#CustomAddress2,"; ")
  sertxd ("CAValue is: ", #CAValue,". ")
#endrem  
  gosub ErrorCheck
  do
    gosub TrafficLight
  loop
goto Main

ReadSetup:
'read dip switch status through I2C I/O expanders
  hi2csetup i2cmaster, PCA9554A_5, I2CSpeed, i2cbyte 'read custom addresses first to free bit variables
  hi2cin InputReg, (CAValue)
  gosub DecodeBCD 'decode bit variables from CAValue into CustomAddress1 and CustomAddress2
  hi2cin [PCA9554A_1],InputReg,(Lane1State)
  hi2cin [PCA9554A_2],InputReg,(Lane2State)
  hi2cin [PCA9554A_3],InputReg,(Lane3State)
  hi2cin [PCA9554A_4],InputReg,(Lane4State)
'read if Traffic Lights Module is present and with what setting (jumper)
  readadc 6, helper3
  select case helper3
  case 0 to 64 : ModeFlag = 2                         'TLM not present or jumper not set
  case 65 to 128 : ModeFlag = 1                     'TLM present, set to yellow only mode (yellow jumper, high value resistor)
  case 129 to 196                                           'TLM present, for future use
  case 197 to 256 : ModeFlag = 0                   'TLM present, trafic lights in normal mode (green jumper, no resistor)
  end select
  return

ErrorCheck:
'check which lanes are connected at all
  hi2csetup i2cmaster, ALCULane_1, I2CSpeed, i2cbyte             'set up I2C
  hi2cout 0, (1)                                                                            'assign the connected chip as Lane_1 for I2C test
  hi2cout [ALCULane_2], 0, (2)                                                     'assign the connected chip as Lane_2 for I2C test
  hi2cout [ALCULane_3], 0, (3)                                                     'assign the connected chip as Lane_3 for I2C test
  hi2cout [ALCULane_4], 0, (4)                                                     'assign the connected chip as Lane_4 for I2C test
  
  hi2cin [ALCULane_1], 0, (helper3)                                             'read back if that was stored ...
    if helper3 = 1 then                                                                 '... if yes, set Lane1 as available/connected and increase couter
    	Lane1AvailableFlag = 1
    	inc ErrCounter
    endif
  hi2cin [ALCULane_2], 0, (helper3)
    if helper3 = 2 then
    	Lane2AvailableFlag = 1
    	inc ErrCounter
    endif
  hi2cin [ALCULane_3], 0, (helper3)
    if helper3 = 3 then
    	Lane3AvailableFlag = 1
    	inc ErrCounter
    endif
  hi2cin [ALCULane_4], 0, (helper3)
    if helper3 = 4 then
    	Lane4AvailableFlag = 1
    	inc ErrCounter
    endif
  if ErrCounter < 2 then                                                            'signal error if less than 2 lanes are connected
  	high ErrLED
  	for Counter = 183 to 232
      read Counter, helper3
    next Counter
   endif
'check if no routes are available for some type of vehicle or in layout OFF mode
  for BitNumber = 0 to 7
    ErrCounter = 0                                                         'reset the counter
  	if Lane1State bit BitNumber set then : inc ErrCounter : endif
  	if Lane2State bit BitNumber set then : inc ErrCounter : endif
  	if Lane3State bit BitNumber set then : inc ErrCounter : endif
  	if Lane3State bit BitNumber set then : inc ErrCounter : endif
  	if ErrCounter < 1 then exit
  next BitNumber
  if ErrCounter < 1 then                                              'signal error if less than 1 lane is open for any vehicle type or in layout OFF mode...
  	high ErrLED                                                             '...this could be increased to 2, if it is certain, that no vehicle of a restricted...
  	for Counter = 233 to 252                                       '...type would enter FROM a lane, restricted for exit from the crossing
      read Counter, helper3
   next Counter
  endif                                                                         
'check if main road configuration is correct - only two of the available lanes selected at any time
  ErrCounter = 0                                                         'reset the counter
  if MAIN1 = 0 and Lane1AvailableFlag = 1 then : inc ErrCounter : endif
  if MAIN2 = 0 and Lane2AvailableFlag = 1 then : inc ErrCounter : endif
  if MAIN3 = 0 and Lane3AvailableFlag = 1 then : inc ErrCounter : endif
  if MAIN4 = 0 and Lane4AvailableFlag = 1 then : inc ErrCounter : endif
  
  select case ErrCounter                                            'demands main road to be selected - could omit to >2 only to allow not using the feature
  case 0
  	MainRoadConfig = 0                                               'set to no configuration/error code
  case 2
    if MAIN1 = 0 and MAIN3 = 0 then : MainRoadConfig = 1 : endif    'check if lane1 and lane3 selected
    if MAIN2 = 0 and MAIN4 = 0 then : MainRoadConfig = 2 : endif    'check if lane2 and lane4 selected
    if MAIN1 = 0 and MAIN2 = 0 then : MainRoadConfig = 3 : endif    'check if lane1 and lane2 selected
    if MAIN2 = 0 and MAIN3 = 0 then : MainRoadConfig = 4 : endif    'check if lane2 and lane3 selected
    if MAIN3 = 0 and MAIN4 = 0 then : MainRoadConfig = 5 : endif    'check if lane3 and lane4 selected
    if MAIN4 = 0 and MAIN1 = 0 then : MainRoadConfig = 6 : endif    'check if lane4 and lane1 selected
  else
  	MainRoadConfig = 0                                               'set to no configuration/error code
  	high ErrLED                                                             'indicate error
  	for Counter = 233 to 252                                       'read and display error text over serial
      read Counter, helper3
    next Counter
  endselect
return
 

edmunds

Senior Member
The forum would not allow to post any longer bla bla bla :), but the above is code that shows both, PCA9554A implementation and master 40X2 talking to 4 20X2s and negotiating their I2C addresses beforehand (I don't remember if that part is actually tested or not). This is not entire code, so some variables will be missing, but it was hardly squeezed into allowed 10.000 char maximum as it is.

It is really not all that difficult. Even if you are just starting out with coding MCUs (like me). :)

Hope this helps,

Edmunds
 

westaust55

Moderator
It is really not all that difficult. Even if you are just starting out with coding MCUs (like me). :)
This is quite true.

It is difficult to provide code for someone when the exact scope/specification is not known.
Examples are available on the forum.
It just needs some experimentation and tests with specific assistance from this forum
 

koyli

Member
Thankyou for that, edmunds it all helps towards my understanding of the code.

It just shows how far off the online manuals are. In there it only takes one line to set up an i2c slave.

As things stand at the moment, my only problem is getting all the inputs into the PICAXE. Solving the logic to get the correct outputs is not. If a PICAXE chip was available with 100 I/O`s then I would not have a problem.

My earlier layout was modern image with signalling controlled by an entrance/exit panel, the PCB for that had 150+ connections. All the logic done by standard logic gates.

Now I have gone back in time to the 1970s and a station with an earlier track plan and signalled by a miniature lever frame.
I was going to use logic gates again for this one, but to avoid having 1 square metre of circuit board, I thought I would try something more elegant.

This is the situation.

26 track circuits
12 turnouts of which half are crossovers
31 signals. Both home signals have route indicators.
43 levers

All inputs are logic 1 when normal/unoccupied.
All outputs to lever frame logic 1 when activated.

I will plod along with it and report back how I am doing.
 

westaust55

Moderator
Keep in mind that it only takes 1 line of PICAXE code to set up the PICAXE as a slave device (for X1 and X2 parts) or to set up a master to communicate with external chips. This is what the PICAXE manuals cover.

The part that requires several lines is then configuring the external i2c chip to do as you require.
There is a limit to how much Revolution Education (PICAXE.com) can insert for these external chips.
Every external chip has different requirements so which do Rev Ed include ?
It becomes a requirement of folks to read the datasheets search the forum for past examples/tutorials others have posted here and ask questions.
 

edmunds

Senior Member
Sorry, I forgot to post some I2C slave code. Here it is:

Code:
#rem
TODO:
1) Next version should have reed sensor on an interrupt pin, which would allow IRCode or Reed modes
    to be selected and paralell detection of Reed sensor in case no IRCode was read;
2)


Aproaching Lane Control Unit (ALCU) software, version 1.0
Designed as a slave unit for Intersection Central Control Unit (ICCU)

EEPROM use:
  * locations 0 and 1 - device address for serial communication from the system master
  * location 2 - device (slave) address for I2C communication from ICCU (master) depending on the Lane device is connected to

Scratchpad use:
  * for hserin commands from the main computer/control unit

#endrem

#picaxe20X2

setfreq M32

'Constants
Symbol I2CSpeed = i2cfast_32
Symbol SerBaudRate = B9600_32
Symbol SerNRate = N9600_32

'I/O pins, B.5&B.7 reserved for I2C
Symbol IRSens = C.7

'Interrupt pins
Symbol INT1 = B.0

'Status LED pins
Symbol StatLED = C.4
Symbol ErrLED = C.5

'Remote access pins
Symbol SerRXPin = pinB.6
Symbol SerRX = B.6
Symbol SerTXPin = pinC.0
Symbol SerTX = C.0

'Byte variables
Symbol IRCode=b15                       'received IR code
Symbol Counter = b26                    'just a counter
Symbol ChipAddrLSB = b36             'chip address, LSB
Symbol ChipAddrMSB = b37            'chip address, MSB
Symbol ChipAddrI2C = b38             'chip address for I2C

'Word variables
Symbol ChipAddr = w19                 'a combination of ChipAddrMSB (b37) and ChipAddrLSB (b36)

init:
  high ErrLED
  high StatLED  

'Set up the serial address for this chip
  serin INT1, SerNRate, ("ICCU"), ChipAddrMSB, ChipAddrLSB, ChipAddrI2C    'wait for ALCU address from ICCU
  low ErrLED                                                                                                   'to indicate address was received
  write 0, WORD ChipAddr, ChipAddrI2C                                                       'store in EEPROM

'Initialise background serial receive to scratchpad
  hsersetup SerBaudRate, %0

'Initialise to invalid codes
  IRCode = 0

'Intialise I2C
'ALCULane_1 = %01100010     'Lane 1 ALCU
'ALCULane_2 = %01100100     'Lane 2 ALCU
'ALCULane_3 = %01100110     'Lane 3 ALCU
'ALCULane_4 = %01101000     'Lane 4 ALCU
  hi2csetup i2cslave, ChipAddrI2C      'Make this a slave for the Lane it is connected to

'Initialise outputs


Main:
  irin IRSens, IRCode
  if IRCode <> 0 then
  	put 0, IRCode
  	high INT1
  	high ErrLED
    pause 400             'hold the line high long enough for ICCU to notice
  	low INT1
  	low ErrLED
  	pause 3600           'hold the line low long enough to debounce - not to register a vehicle twice
  	                              'in theory, should be the time it takes for a car between crossing the IRreceiver and leaving the turn servo
  endif
  input INT1               'set INT1 back to input to wait for serial command from the master
goto Main
Edmunds
 

edmunds

Senior Member
Thankyou for that, edmunds it all helps towards my understanding of the code.

It just shows how far off the online manuals are. In there it only takes one line to set up an i2c slave.
I don't see anything "off" there, as it really does take one line to do it. What the manual does not address is what's next? But that really depends on the application of the user.

26 track circuits
12 turnouts of which half are crossovers
31 signals. Both home signals have route indicators.
43 levers

All inputs are logic 1 when normal/unoccupied.
All outputs to lever frame logic 1 when activated.
This is good to know, but does not say much about what you are trying to achieve. There are many railroad modellers on the forum that would sure be interested to help subject to their availability and might even provide some code snippets, but what it takes is clear definition of what you need, broken down into chunks that can be addressed in max 10 to 15 minutes, since this is what people can allocate for this kind of thing. Talking form experience here ;).

Possibly, you really don't need I2C and serial "conversation" between a few picaxe chips that you could take out from the code I posted would do it for you. I am using serial before I2C, because I am connecting 4 visually identical slave units to a master unit and I don't want to remember which needs to be connected where and bother programming 4 different downloads with a change of one bit in I2C address. It depends a lot on how busy the master is, trying to do what it has to do and if there is a reason to include any other I2C devices like sensors or EEPROMs.

Edmunds
 

koyli

Member
This is good to know, but does not say much about what you are trying to achieve. There are many railroad modellers on the forum that would sure be interested to help subject to their availability and might even provide some code snippets, but what it takes is clear definition of what you need, broken down into chunks that can be addressed in max 10 to 15 minutes, since this is what people can allocate for this kind of thing. Talking form experience here ;).

Possibly, you really don't need I2C and serial "conversation" between a few picaxe chips that you could take out from the code I posted would do it for you. I am using serial before I2C, because I am connecting 4 visually identical slave units to a master unit and I don't want to remember which needs to be connected where and bother programming 4 different downloads with a change of one bit in I2C address. It depends a lot on how busy the master is, trying to do what it has to do and if there is a reason to include any other I2C devices like sensors or EEPROMs.

Edmunds
All the turnouts and signals will be operated directly from the switches in the lever frame. The PICAXE will be used to control the interlocking to prevent a conflicting route being set up. A red LED will show when a switch is locked and a green LED when it is free.

My original question was not about i2c, all I wanted to know was how to increase the number of inputs/outputs.
 

lbenson

Senior Member
>My original question was not about i2c, all I wanted to know was how to increase the number of inputs/outputs.

After moderate use of both serial and i2c, and MCP23017 and slave picaxes, I would still say that the i2c slave picaxe method would be the easiest (depending perhaps on your wiring setup and the length of runs).

Why not test the setup I suggested in post 28? That would be 2 40X2s on a breadboard, set up with the standard programming connection, reset pin connected to 5V with 4.7K resistor, and legs 23 and 18 connected each to each, with a 4.7K resistor from one leg 23 to 5V, and another 4.7K resistor from one leg 18 to 5V.

Then program as in the post (9 lines of code in the slave 40X2, 6 in the master (plus what you want to do with the I/Os).

For outputs on the master, you could, for instance, say "outpinsB = %01010101" to turn on ports B.0,B.2,B.4,B.6 (and so on with outpinsA, outpinsC, outpinsD--I don't know if you would need to use a different method with outpinsC (individual port settings as in "high C.0") because of possible interference with the i2c on pins C.3 and C.4--perhaps use master portC only for inputs).

I can understand that going from flowchart to basic could seem daunting, but I would think that a flowchart controlling over 100 I/Os would be extraordinarily complex, if even possible.
 
Top