Serial Communication Between Picaxe Chips

kevinbrinkley

New Member
Hello,

My setup is:

28x2 - Collects and processes data from a number of 20x2 devices. These read their C pins and send the binary code o their state to the 28x2.

There are planned to be 12 20x2 in total all connected to the b.0 (serin on 28x2) and b.1 (serout on 28x2) pins of the 28x2. I am testing in VSM with just 2 actively at present.

The 28x2 sends a code along the line to the 20x2s with a qualifier to identify the correct 20x2. On receiving the correct qualifier, the 20x2 sends back the data.

When running the simulation, the first chip, regardless of which it is, always works.

However, the second always fails as the 28x2 fails to recognise the input it receives from the 20x2. the 20x3 does receive the qualifier and does send the signal.

I have so far tried:

Different baud rates
Calibfreq
Different setfreq values

Any other suggestions are very welcome :)

Thank you in advance.



The Code

On the 28x2:


COLLECT_DATA:

GOSUB POINTS1
GOSUB POINTS2
'GOSUB POINTS3
'GOSUB POINTS4
'GOSUB TOTI1
'GOSUB TOTI2
'GOSUB TOTI3
'GOSUB TOTI4
'GOSUB SWITCH1
'GOSUB SWITCH2
'GOSUB SWITCH3
'GOSUB SWITCH4

RETURN

POINTS1:

SEROUT SERIAL_OUT_INPUTS, N2400, ("WAKE")
PAUSE 10
SEROUT SERIAL_OUT_INPUTS, N2400, ("POINTS1")
PAUSE 10
SERIN [50, POINTS1], SERIAL_IN_INPUTS, N2400, ("POINTS1"), b0
PAUSE 10

RETURN

POINTS2:

SEROUT SERIAL_OUT_INPUTS, N2400, ("WAKE")
PAUSE 10
SEROUT SERIAL_OUT_INPUTS, N2400, ("PT2")
PAUSE 10
SERIN [50, POINTS2], SERIAL_IN_INPUTS, N2400, ("POINTS2"), b1 'FALLS OVER HERE, REGARDLESS OF TIMEOUT.
PAUSE 10

RETURN


On the 20x2 ("Points2" can be subbed for "Points1" etc)


MAIN:

GOSUB READ_PINS

GOSUB RECIEVE

GOSUB TRANSMIT

GOTO MAIN

END

READ_PINS:

b0 = pinsC

RETURN

RECIEVE:

SERIN SERIAL_IN, N2400, ("POINTS2")
PAUSE 10

RETURN

TRANSMIT:

SEROUT SERIAL_OUT, N2400, ("WAKE")
PAUSE 10
SEROUT SERIAL_OUT, N2400, ("POINTS2", b0)
PAUSE 10

RETURN
 

Technical

Technical Support
Staff member
You cannot connect multiple inputs to the same 28X2 pin. All these 12 20X2 outputs are all trying to actively drive the line - so will all corrupt the signal from each other.
 

Aries

New Member
I have used what is effectively one-wire serin/serout communication between two Picaxes, where they take turns to use the wire as input and output. If you leave all the 20x2 serout pins as inputs when not actually being used, they should not (Technical can correct me as necessary) interfere with a single one that is actually doing serout. As they do not use serout until they have received an appropriate serin signal, that should not be a problem to implement.

My other concern would be whether the 28x2 can drive a dozen 20x2 serin pins. If not, then you may need to use an amplifier (transistor or chip) to increase the fan-out sufficiently.
 

steliosm

Senior Member
You could try to use the rs-485 protocol which is designed for a bus topology using a master/slave model. There are modules in the Chinese market for rs485-to-ttl translation. You still use serial in/out on the picaxes but you need to implement the master/slave model in order to make sure that no two picaxes are trying to use the bus at the same time. This can be done by having the Master (28X2) poll each of the slaves (20X2) for data and each slave replying to Master with the data.
 

inglewoodpete

Senior Member
Implement Slave serial outputs in an "Open Drain" configuration.

My suggestion would be to have each slave's serial output pin connect to a pullup resistor via a diode connected between the slave's serial output pin and the pullup resistor. Each slave's chosen serial output pin would idle high, a state which is blocked by the diode. Each slave chip would be programmed with a unique ID number. The commoned output can only be allowed to be pulled low by one chip's serial output at a time - slave software must ensure that it's output remains high until in is addressed (queried) by the the master chip.
 

Aries

New Member
Going back to my one-wire comms ... I implemented this with 8 20x2s communicating with one 28x2, which used a multiplexer (HC4051B) to select each 20x2 in turn.
 

Flenser

Senior Member
Have you considered using I2C?

The 28x2 sends a code along the line to the 20x2s with a qualifier to identify the correct 20x2. On receiving the correct qualifier, the 20x2 sends back the data.
This sounds a lot like the way I2C communications work and the X2 chips support running the chip as either an I2C master or an I2C slave.

NOTE: I2C connections are only intended for relatively short connections.
There is some example I2C master & slave code by Hippy posted on the forum but I couldn't find it with a quick search.
 
Last edited:

kevinbrinkley

New Member
Thank you all. I will explore the ideas above and am considering I2C as a potential way forward.

I really appreciate your time and ideas.
 

Aries

New Member
The limited distance of I2C can be the main stumbling block. Serial works over much longer distances (my 28x2 to 20x2 operates through mains 3-core-and-earth cable over about 20 metres with no problems). From the look of it, you actually only need to read data from the 20x2s (slaves), so the slaves themselves only need to set themselves up with i2cslave and a suitable I2C address, and that is all. HOWEVER, make sure they do not use serial or sertxd as well, because it can (and does) interfere with I2C communications. The I2C connection can then hang (for all communications). I always include something on the following lines in the master (28x2) to clear the line before starting a new communication:
Code:
CloseI2C:
    hi2csetup off
    for b1 = 0 to 1
        input I2C_SCL
        input I2C_SDA
        b3 = 0                                                    ' count any residual slave bits
        for b0 = 0 to 15                                ' check if anything in I2C buffer
            low I2C_SCL                                        ' pull low
            pause 5
            b3 = b3 + I2C_SDApin
            input I2C_SCL                                    ' allow to go high
        next b0
        if b3 = 16 then CloseI2CEnd
        sertxd(13,10,"I2C stuck ",#b3)
        input I2C_SCL
    next b1
CloseI2CEnd:
    input I2C_SCL
    input I2C_SDA
    return
where I2C_SCL and I2C_SDA are the pin numbers (eg C.3) and I2C_SDApin is the "pin" version (eg pinC.3) for the I2C communications.
 

hippy

Ex-Staff (retired)
While I2C should work I would suggest using serial as it's much easier to use. I would expect a diode mixed 'open drain' multi-drop signal line as suggested by inglewoodpete to work.

The software itself can be greatly simplified because there is no real need for qualifiers if a slave only responds to being asked for data. It's reasonable to presume everything will work as expected, so one can get it working, then add qualifiers if needed in the final deployment.

This is how I would approach the 28X2 master ...
Code:
#Picaxe 28X2

; .-------------.
; | 28X2 MASTER |
; `-------------'
;
;  -.- 5V               -.- 5V
;  .|.                  .|.
;  |_|       28X2       |_|
;   |   .-----__-----.   |
;   `---| RST    B.7 |-  |
;       :            :   |
;      -|        B.1 |---|---> TX
;      -|        B.0 |---^---< RX

Symbol TX        = B.1
Symbol RX        = B.0
Symbol BAUD      = T4800

Symbol reserveW0 = w0
Symbol from1     = b11
Symbol from2     = b12
Symbol from3     = b13

PowerOnReset:
  High TX
  Pause 100

MasterLoop:
  Do
    b0 = 1 : Gosub ReadSlave : from1 = b1 ; Read from Slave 1
    b0 = 2 : Gosub ReadSlave : from2 = b1 ; Read from Slave 2
    b0 = 3 : Gosub ReadSlave : from3 = b1 ; Read from Slave 3
    Gosub ShowResults
    Pause 1000
  Loop

ReadSlave:
  b1 = 0
  SerOut TX, BAUD, (b0)
  SerIn [1000, TimedOut], RX, BAUD, b1
TimedOut:
  Return

ShowResults:
  SerTxd("From 1 = ", #from1, TAB)
  SerTxd("From 2 = ", #from2, TAB)
  SerTxd("From 3 = ", #from3, CR, LF)
  Return
And each 20X2 slave ...
Code:
#Picaxe 20X2

; .------------.
; | 20X2 SLAVE |
; `------------'
;
;            20X2
;       .-----__-----.         | /|
;      -| V+      0V |-    .---|< |---> TX
;      -|        A.0 |-    |   | \|
;      -|        B.0 |-----'
;      -|        B.1 |----------------< RX

Symbol ME        = 1  ; We are Slave 1

Symbol TX        = B.0
Symbol RX        = B.1
Symbol BAUD      = T4800

Symbol reserveW0 = w0 ; b1:b0
Symbol myData    = b2

PowerOnReset:
  High TX

SlaveLoop:
  Do
    Gosub WaitForDataRequest
    Gosub DetermineMyData
    Gosub SendMyData
  Loop

WaitForDataRequest:
  Do
     SerIn RX, BAUD, b0
  Loop Until b0 = ME
  Return

DetermineMyData:
  myData = pinsC
  Return

SendMyData:
  SerOut TX, BAUD, (myData)
  Return
 
Top