inter-Picaxe serial communication

08M_serial_chip0.bas (871Bytes)
08M_serial_chip1.bas (890Bytes)
08M_serial_chip2.bas (735Bytes)

Picaxe serial bus

This walkthrough shows you how to make multiple picaxe chips talk to each other using 1 line. This works for all picaxe models but I only used the 08M in my test.

basic setup : 08M with flashing LED

This is the basic setup for each of the 3 chips. I wont bother with the serial connection to the PC because I removed the serial socket from the breadboard after the programming.

The picaxe 08M needs V and GND and a pull down resistor for the serial in (of the PC connection). To show that the chip is working, it flashes an LED every half second or so.

SerialBus_basic_setup.jpg

symbol LED = 2

symbol blinkspeed=w0

blinkspeed = 500

main:

high LED

pause blinkspeed

low LED

pause blinkspeed

goto main

Receiving a message on the serial bus

We want chip 0 to be able to receive a command that changes the speed of the flashing LED. This is done with the serin command on pin 4.

If you issue a serin command everything the picaxe is doing in the background stops. What’s worse is that the 08M will wait for ever to receive the data. There is no way for the command to timeout and resume the LED flashing. So we need to know when to expect some data.

SerialBus.jpg

The data-line is pulled high with a 22K resistor. We set an interrupt on pin4 the triggers when pin4 detects that the line is being pulled low, indicating that another picaxe wants to talk.

setint 0,%00010000 'interrupt on pin4 when low

(obviously: i left the V, GND and LED stuff from the basic setup out of the picture. Top one is chip0, bottom one chip2)

When the interrupt occurs, the serin command is fired. It waits for an escape code (27) to prevent it from misreading a message by starting at the wrong byte.

The message itself is 3 bytes: the number of the chip the message is for (in this case 0,1 or 2) followed by two bytes that make up a word variable indicating the new blinkspeed.

interrupt:

' someone wants to talk

serin serpin,N2400,(27),seraddr, b4,b5 ‘w2 = b5,b4

if seraddr=chipid or seraddr=255 then 'they are talking to us!

blinkspeed = w2

end if

setint 0,%00010000 'interrupt on pin4 when low

return

All messages are read, but only if it is intended for this chip, will the blinkspeed be set.

If you look at the condition in this code sample, you see that it will also act on the message if it is addressed to 255. This way, a sending chip can address all picaxes on the line in one message (broadcast). After reading the message, we set the interrupt again and return to where we left of.

Sending a message

A chip that wants to send a message has to pull down the line by setting pin 4 low. Before it does that, it turns the interrupt off to prevent the picaxe to wait for its own message. then it starts a loop waiting for the line to be high. This is just to make sure that if another chip pulled the line low, this chip will not start sending until the line is cleared.

Pin4 is renamed to talkbutton in this code: like the button on a walkie-talkie.

talk:

setint off

do: pause 1: loop until talkbutton=1

if talkbutton=1 then

low serpin

pause 50

serout serpin, N2400,(27,seraddr,b4,b5)

endif

input serpin

setint 0,%00010000 'interrupt on pin4 when low

return

using 2 pins (for non 08M picaxes)

Chip2 in this setup is configured differently. It uses two pins instead of one. Pin4 is now just an output pin. It is tied to the dataline with a 4K7 resistor and is set to high all the time, unless it wants to talk.

Pin1 is used as an input and works just like on the other 2 chips. (please note that in the drawing, I swapped the function of pin1 and pin4)

If this setup is used, the 22K pullup resistor isn’t needed but I left it there in case I wanted to remove chip2 from the circuit.

Also, and this is important, this setup requires a fixed delay on setting the interrupts on all the chips. Because output pins are low by default, any non-08M picaxe will pull the line low for a short while when starting up. The delay prevents the other chips to fire the interrupt on startup and wait for a message that will not come. Another way to circumvent that is to send a dummy message from the non-08M picaxe after startup.

code samples

In the attached code samples, chip 0 blinks and receives new blinkspeeds. If the blinkspeed is greater then 500 (half a second) if sets the blinkspeed of chip1 and chip2 to 75 (very fast)

chip1 blinks 8 times and then increases the blinkspeed (slowing down the blinking) and sends the new speed to chip0

chip2 waits for 30 seconds with the LED on. Then tells chip1 to set the speed to 300 and sets its own blinkspeed to half a second.

If you run this code you’ll see chip2 waiting with the LED on.

LED0 and LED1 going through a cycle where LED1 blinks slower and slower with LED0 following behind. Until the blinkspeed is to slow and chip0 sets the speed of chip1 to 75.

After 30 seconds, chip2 joins the blinking but without changing speed until chip0 tells it to

some remarks / ideas / todos

 

  • The serial bus might be configured with the data line pulled low by default instead of high in order to suit the picaxe 28 board. On that board the inputs are connected to the ground with a 10K resistor. That will also solve the problem of the line being pulled into "talkmode" by the default low of an outpunt pin.
  • In the talk routine there is a 50ms pause to wait for all the chips on the line to start listening. 50ms is a very long time in processing terms so this delay could be made a lot shorter. I'd say 1 or 2 ms will still be on the safe side.
  • The protocol should be expanded with a sender address.
  • (crazy!) make a picaxe 28X1 relay messages from a 08M to I2C devices.

 

I was thinking of some domotic…

It’s definitely the solution for the domotic switches and alarm I’ll build for my house !

great walkthrough

I am wiring as we speak
This is going to be fun. Both of us hitting this one at the same time! --Right now I have an 28x taking pulsin commands coming from my remote control receiver and landing in 6 variables. I have an "isolated" 18x that will do nothing but send PWM commands to my motor driver board for Walter. The 18x is going to be set-up as a "slave" on the serial line chain-gang while the same variables will also be sent to the 40x "main brain". A little "addressing" will let everyone know who is who and what to do when. Great walk through, by the way! I am stealing code snippets right now! --You da man! (I hope to be soon)

diode protection?

I am a little confused with “sharing” a serial line. I am using the same “trigger” line and serial line so the chip gets a “heads-up” before a data transfer. However, in my set up, I have 2 master chips talking to one slave. I.e. 2 serouts into one serin. In this configuration, one of the master chips is back feeding serial data into the other master chip’s serout. Would you think a couple diodes are in order here? Also, because the 40x main brain is sharing serin and serout lines is there also a backfeed problem here? --I assume I can just code the 40x properly so it ignores its serin pin when transmitting and therefore doesn’t talk to itself.

serial_schem.jpg

EVERYBODYLook up CAN
EVERYBODY

Look up CAN communication, it is very similar to this.

I thought it was more
I thought it was more similar to i2c than can…

2 master nodes? I’d be
2 master nodes? I’d be worried about a race condition potential on that one. Anyway, signal diodes like 1N4148’s or 1N914’s would work and make sense for this setup.

@ voodoo
In the diagram I wrote slave and master. In reality, there is no code what so ever putting the chips into actual slave and master set-ups. Really, the notes are just so my brain can think about the configuration better. The 18x really is a slave though, in that it probably won’t have a serial out and won’t need to talk back to the other 2 chips. I am using the 18x simply as a poor-man’s servo driver and will do nothing but that, drive servos. Because I want to run those servos from both the 28x and the 40x (in different situations) I need them to share the serial lines -Thus the diode question.

With CAN it can have
With CAN it can have multiple addresses along the bus.

Diodes and code

I’ve tried the setup with a diode. I’ve put an extra LED between the 4K7 and the dataline in the demo setup above so you can see when the line is pulled low. It works.

You wont have to worry about sending serial data in the other master chips outpin, because it will be high when it’s listening. Only the master that is sending will have the output low.

In order to prevent the 40X1 to listen to itself, you need to turn of the interrupt on the pin you use for the serin before you pull the line low. Like in the code for CHIP2

I changed the picture to show how I’d set it up.

SerialBus_CTC.jpg

Note that I did't draw any output for the 18X picaxe, because you said it just receives servo commands and send nothing back.

PICs CAN, PICAXEs CANnot

CAN is a serial broadcast bus just like this.

The main difference is that CAN has collision control built in. In order to do that, a device that sends a bit, reads the dataline at the same time. If one device sends a 1 while another sends a 0, all the listening devices (including the sending device) read the 0. The device that originally sent the 1 will stop sending after that.

I don’t think anything like that (sending and receiving simultaniously) can be done with a PICAXE, but I’ve read that some PIC models have support for CAN built in. So if you’re writing assembly, you’ll be able to make use of that.

BTW the setup used in this walkthrough also has multiple addresses on the bus.

Indeed…
Thank you, sir… thank you.

28x board
So how does one connect a serial line to a picaxe on a project board? The three pins on the top?

Serial in on a 28x1 is pin 6
Serial in on a 28x1 is pin 6 and out is pin 7. Map that to your project board and your good. Those 3 pins on the project board is for i2c.

Which serial line? I2C, RS232 or other

The three pin header on top of the 28X project board connect to the hardware serial pins. I believe those are the same pins used for I2C communication, but due to the resistors on the board, I don’t think you’d be able to use them for I2C. If you want to use them, use the hserin, hserout and hsersetup commands. For connection with a computer, you’ll also need a MAX232 inverter chip.

For serial connection with the computer it is probably easier to use the programming cable on the jack thats on the board.

If you want to communicate using the serial interface described in this walkthrough, have a look at Diodes and code. Also in this walkthrough. You can use any regular digital input and output. The picture shows a setup using pin11 (=input 0) for input and pin 28 (=output 7) for output. The diode is used to prevent current from flowing to the output pin when it is low.

serial pin

pin 6 and 7 as in digital input 6 and 7? or the pin on the chip?

My concern is that I no longer have the 3 pins on my board (they were in the way and Rev-Ed’s wonderful documentation said it was reduntant). So if there’s another spot on the board that i can connect to …

Oh wait, i just read the post below. I think that might answer the question.

Once again, thanks guys!

serial jack

Pin 6 and pin 7 are connected to the serial jack you use for uploading programs. They are not connected to anything else. The pins you’ll need depend on what device is going to be connected.

serial jack -> talk to your PC

3 pins on top -> talk to a PIC programmer

any digital input/output -> talk to another picaxe chip.

[edit] Oh wait. I just saw your edit. never mind … :wink:

08m won’t react on interrupt

I’m trying the serial communication between a 40X1 and a 08m.

With the 40X everything works fine. It’s sending, pulling the line down, receiving, perfect.

But the 08m just doesn’t react to the interrupt. I connected input 1 (pin6) via 330R to the data line. When I put a LED to the data line I can see how it is pulled low, but the 08m just does nothing. I used the setint 0,%00000010 command.

Does anyone has an idea?

hmmm

For now I found out, that it doesn’t matter if I use the interrupt for low or high signal. Both times the same behavior.

I also found out, that the whole program doesn’t work correctly as soon as the controller encounters the setint command.
As soon as I delete the setint, I can perform simple checks for the inputs again. With setint it doesn’t work.

I try to update my programming editor. Maybe it’s a bug???

Heureka

It was indeed a bug in the programming editor.

With version 5.2.11 it works.