PC to PICAXE communication

roho

Member
Hi all,

I'm moving into an area in which I have no technical experience. A search of this forum's database hasn't thrown up anything useful, and so I'm hoping for assistance from anyone who may have already been down this particular route. I am looking to control a number of PICAXE28X2s from my PC for my model railway project. Communication must be bi-directional between PC and any given PICAXE, but the PICAXEs do not communicate with each other. At the moment, I am thinking of the following, though since my plans are embryonic, many things could be changed.

I need to write a user interface, and I am planning to do this in tcl/tk since I have some experience of this language. Now comes the big leap. I'm assuming that this UI can (be made to) output data to a port. Communication would be via an AXE027 cable to the microcontrollers. This would require me to build a dedicated interface PCB, but that shouldn't be a problem. Protocol would be I2C with the PC as master and the PICAXEs as slaves. In the first instance there will be two slaves but ultimately there could be up to, let's say, 15. Another consideration is that each PICAXE is itself an interface to further PICAXEs, the communication protocol for which uses the interrupt. I presume that I would therefore need to poll the PC to PICAXE interface for activity.

Hopefully there's enough detail there for you to understand my requirements. Is it even feasible? Could it be improved (without going to a lot of expense)? Thanks for any and all advice.

Roger.
 

westaust55

Moderator
You could use serial from the PC.
Then hsersetup with a higher baud rate and use a higher clock frequency.
http://www.picaxe.com/BASIC-Commands/Serial-RS232-Interfacing/hsersetup/

Finally the Hserin command:
http://www.picaxe.com/BASIC-Commands/Serial-RS232-Interfacing/hserin/
And set a different qualifier for each PICAXE so that each can be addressed over a common comms link.

I have used I2C between two X2 parts with the master a 20X2 clocked at 64 MHz and the slave a 28X2 with external resonator for 72 or 80 MHz.
Then the i2c set for a nominal 1000 MHz (see datasheet for value to use).
In round figures I transfer/read roughly 200 bytes of new data in a burst every 200 ms.
 
Last edited:

Aries

New Member
There can be problems with mixing I2C and serial i/o. I suspect that I2C can hang if it coincides with a serial i/o operation. With hserin, you do not have control of when the i/o happens, so you cannot choose your I2C times to avoid the conflict. There is sample code on the forum for unblocking I2C if it does hang, by "manually" clocking SCL , but I can't lay my hands on it.
 

roho

Member
Thanks for the ideas, I now plan to use the serial in/out. I ran a simple experiment of outputting an ASCII character from the USB port via the AXE027 cable to the 40X2 serial input of the development / programming board, where I could observe the character correctly on an oscilloscope. I couldn't try to capture the character due to the hardware constraints (I've no way of isolating the AXE027 from the 40X2 serial data input at pin 6), but it has given me enough confidence to design an interface board (PCBs are currently being made in China) so that I should be able to overcome the existing constraints. I should be able to resume testing some time in the new year.
 

roho

Member
The PCBs have arrived, testing has started but is not going to plan. The board has been designed so that I can select, by means of switches, communication via either HSERIN/OUT or SERIN/OUT. I'm concentrating on getting HSERIN to work. I'm sending a single ASCII character from the PC via the AXE027 to the PCB, and can capture on an oscilloscope the correct waveform at pin 26 of the 40X2. I can also see that the 40X2 is receiving something because I load the captured data into port B and drive some LEDs. However, the output neither matches the character sent nor does it alter as different ASCII characters are sent. On the other hand, I can get the output to change if I alter the HSERSETUP command. The result of all of this is that I suspect that I am misusing the HSERSETUP and/or HSERIN commands.

The data line is normally low, and a total of 9 bits are sent: 8 for the ASCII character and a stop bit. Baud rate is 4800. The timing, as seen on the oscilloscope, all appears to be correct. Here is the relevant part of the 40X2 code:
Code:
; Turn off the LEDs and then set up the hardware serial data interface.
LET PortBOutputReg = 0x00
LET pinsB = INV PortBOutputReg
HSERSETUP B4800_4, %00100
LET PTR = 0

DO
  LET PTR = 0
  HSERIN PTR, 1
  GET PTR, PortBOutputReg
  LET pinsB = INV PortBOutputReg
LOOP
The idea is to run in the loop until the PC sends the ASCII character, dump that to the LEDs at port B, and then repeat the process. Having not used HSERIN before, I suspect my code may need attention. Can anybody help?
 
Last edited:

Buzby

Senior Member
HSERIN has two possible rx methods; recieve to variable, or background recieve to scratchpad.

The HSERSETUP you have is for the first method. You need to set a different bit to enable receiving to the scratchpad.

Cheers,

Buzby
 

inglewoodpete

Senior Member
The default clock speed for a 40X2 is 8MHz, so the baud rate in the hSerSetup command should be B4800_8, if you want to receive data at 4800 baud.

I have not used hSerIn (Ie foreground with hardware UART), so can't offer much help beyond this.
 

hippy

Technical Support
Staff member
This is a good starting point, will show every byte received in the Terminal window -
Code:
#Picaxe 40X2
#Terminal 9600

HSerSetup B4800_8, %111 ; or %001

Do
  Gosub GetByte
  SerTxd( "Got ", #b0, TAB )
  SerTxd( #bit7, #bit6, #bit5, #bit4, " " )
  SerTxd( #bit3, #bit2, #bit1, #bit0, TAB )
  SerTxd( b0, CR, LF )
Loop

GetByte:
  Do : Loop while ptr = hSerPtr
  b0 = @ptrInc
  Return
 

Buzby

Senior Member
Sorry, I got my writing wrong !.

HSERIN does only write to scratchpad in the X2, I was getting distracted by my barking dog !.
 

Flenser

Senior Member
roho,

The short segment of code you posted in post #5 does not contain all the info we need to investigate. What clock speed do you set in your code?

Inglewoodpete has spotted one possible reason you could see this behavour that is consistent with what you have described so far. If you do not set clock speed in your code then it will run at the default speed, which is 8MHz.
Your command "HSERSETUP B4800_4, %00100", which sets the seriral hardware for 4800 baud at a clock speed of 4MHz, will then be reading the values of bits at a speed that is _not_ 4800 baud and so the character that it recevies will be wrong.
The oscilloscope will show the correct set of start bit, bits 0-7 and stop bit buy the bit width will be wrong.
 

roho

Member
Thanks all for your feedback -- it's been most useful in getting things working, and I am now able to transfer single ASCII characters from PC to PCB using TCL and an AXE027.

The code I posted earlier was the entire code bar the definitions so, yes, I definitely bungled when setting the baud rate. Hippy's code worked immediately, proving the basic connectivity. The problem with the TCL generated transfer was found to be an extra pair of CR and LF characters being sent, presumably automatically, approximately 60ms after the designated ASCII character. This may be related to the closing of the port, but I'm going to have to dig deeper into the TCL to get to the bottom of what's happening here. For the moment, I'm just filtering out the CR and LF characters in the SW.

Here's the 40X2 code as it stands at the moment, minus the definitions:
Code:
; Turn off the LEDs and then set up the hardware serial data interface.
LET PortBOutputReg = 0x00
LET pinsB = INV PortBOutputReg
HSERSETUP B9600_8, %00111

DO
  GOSUB GetByte
  ; Processing is needed to strip away the CR and LF characters until I can
  ; find out how to stop them from being sent automatically from the TCL.
  IF b0 <> 0x0A AND b0 <> 0x0D THEN
    SERTXD( "Got ", #b0, TAB )
    SERTXD( #bit7, #bit6, #bit5, #bit4, " " )
    SERTXD( #bit3, #bit2, #bit1, #bit0, TAB )
    SERTXD( b0, "   PTR = ", #PTR, CR, LF )
    LET PortBOutputReg = b0
    LET pinsB = INV PortBOutputReg
  ENDIF
LOOP

GetByte:
  DO
  LOOP WHILE PTR = HSERPTR
  LET b0 = @PTRINC
  RETURN
For those that may be interested, I'll attach the circuit schematic. Note that the 28X2s are for future development and are not yet fitted. Next step is basic data transfer from PCB to PC.
 

Attachments

Top