Serial comm from PC to 14m2

qcjym2017

New Member
Hello picaxe guru! I'm trying to set up a one way comm from a pc to a 14m2. The string to be
sent looks like this : ,1,2,4,3,7,12,5,6,2 and those number have to be used as DATA. Those numbers
represent a sequenece to be executed by an HO scale gantry crane (
).
I think the 'hsersetup' and ' hserout' should be used but have not enough detail on their usage and
how to move the data from the scratchpad to the DATA command.
Any help appreciated!

jym
 
'hserout' will send info from the Picaxe, what you need is 'hserin', or probably easier to use 'serrxd'.

The 'h' serial commands use different pins to the programming cable, whereas 'sertxd' and 'serrxd' use the programming cable.
This means you only need one cable to your PC, not two. You can switch between programming the Picaxe or communicating with the Picaxe without changing cables.

The received characters will be stored in Picaxe variables of your choice. The 'data' keyword is used to write preset constants to the eeprom, so you can't use that for variables. You will need to use the 'write' command.

How are you generating the strings at the PC end ?.
 
  • Like
Reactions: hex
Hi,

Welcome to the forum. Indeed, the format that the PC uses to transmit the data to a PICaxe needs to be identified before we can give specific reception details. For example, are the digits transmitted as byte values (e.g. 5 , $05 or %00000101) or ASCII characters (e.g. "5" , 53 , $35 or %00110101) and is every digit separated by the "," character, etc. ? It might also be significant if the "data" represents actions of the form "Move (the crane) 243 mm along the track" or "Move along the track until a Stop instruction is received", etc.. Also the baud rate and polarity, etc. must be known and specified.

A common problem with the "RS232" transmission from a PC is that the bytes may be "concatonated" (i.e. "joined up"), but the PICaxe SERIN and SERRXD commands must have a gap after each character/byte to give it time to process (e.g. store) the data (and only a few specific baud rates can be used). Thus the HSERIN (or an equivalent) instruction is necessary to receive "faster" data rates (initially configured with the HSERSETUP instruction). Normally, the "Background Receive" mode is easier to use, but this is only available with the ..X2 chips (not any of the ..M2s).

Generally, the "Background (RAM) Receive Buffer" is larger than the "DATA" (EEPROM) memory (which also can "Wear Out" if used too much) , or the "Indirect RAM" (PEEK/POKE or @{B}PTR) and certainly larger than the "Variables" space (b0 up to b27 or b54). Therefore you may choose to leave the data in the Background RAM until it is actually needed; For example: recovering the individual bytes @PTRINC and "Parsing" the string of bytes "2", "4", "3", "," into a variable b1 = 243 , etc.. Usually, the PTR value will "automatically" wrap around (to zero) at the end of the buffer, so it may only be necessary to ensure that the data is read out before it is overwritten by the PC. However, AFAIK there are no "Buffer Empty" or "Buffer Full" flags, so the Housekeeping may be easier if the Pointer value can be reset after each "block" of data (i.e. before the PC sends any more).

Cheers, Alan.
 
Last edited:
Yes, 'serrxd' will not work properly if the input string is concatenated. That's why I asked about the source of the strings.

Background receiving into a scratchpad buffer is definitely the best way to cater for concatenated data, but the 14M2 does not have a scratchpad.
The M2 parts have a two byte FIFO for received data, so it is easier to handle concatenation, but still not as easy as having a scratchpad buffer as in X2.

We really need more details on the format of the strings from the PC before we can help anymore.
 
We really need more details on the format of the strings from the PC before we can help anymore.
Also, perhaps, some details on ...
Why does the information need to be stored in DATA?
How often is the data being sent? (this is relevant because, as Alan pointed out, ROM/DATA memory has a finite life)
How does the Picaxe know when data is being sent?
Is the data always the same length?
Is the Picaxe doing anything else, or just waiting for the data and then storing it (and presumably doing something with it almost immediately)?
 
One way to reduce repeated writing of data to EEPROM is to read the location before writing to it, then compare the existing value with the new value and only overwrite the location if the new value differs.
 
If you need to store data, read it back multiple times, change the data and repeat, the Openlog device designed by Sparkfun might be ideal. It stores data to a microSD card so there would be almost no limit to the amount of re-writing you can do. Even the smallest available microSD card is rated in the hundreds of megabytes.
Details here: https://www.sparkfun.com/sparkfun-openlog.html
I have not used the Openlog device (yet - have two on the bench waiting for me to have time to put the next project together) but there is more info about it in the PICAXE forums.

Spark fun wants about $20US plus shipping for their original device but AliExpress has their clone Openlog cards for under $3US plus shipping.
 
Well, lots of comments and interrogations. I will try to clarify the purpose of that comm.

The crane has a set of coordinate defined for each position of containers. In this particular
case, 1 to 10 for container in yard and 11 to 13 for those on the train. Actual mode is automatic,
that is, a set of position to reach is listed in a data set and the picaxe move the crane one position at a time.

What I want to do is alter the data by sending a new set of position to reach according to a waybill
generated by the computer. I tried serrdx with some results but far from what I'm looking for. I attach
the file of the picaxe program. The PC program is built with LabView.
 

Attachments

I think we are still going to be asking some of the same questions:

Does the DATA change frequently - for example, does it change every time you have a new load to be moved?
Must the data be retained in the Picaxe when the power is turned off, or does it have to wait for new instructions when it starts up?
How does the Picaxe know when data is being sent?
Is it possible for the data to be sent (as serial data, to be read by SERIN/HSERIN) so that the Picaxe can read it using SERIN?

If the data does change frequently, and if it does not need to be saved when the Picaxe is turned off, then it is better to use the volatile storage (accessed by PEEK/POKE) than ROM (accessded by READ/WRITE).

The M2 Picaxes do not have proper hserin - for that you need at least a Picaxe 20X2. If you can change to a 20X2, then loading data automatically becomes a lot simpler. Otherwise, you will need an input pin to indicate when data is coming, as well as a data pin to receive the serial input and read it with SERIN, then move it into DATA if you need to, using something like this:

Code:
for b6 = 0 to 19
  serin B.1,T1200_4,b0
  write b6,b0
next b6
(It is possible to use just one pin - I have done it for communication between Picaxes, but it does need something on the sending side beyond just sending the serial data.
 
Hi,
.... I tried serrdx [sic] with some results but far from what I'm looking for. ..... The PC program is built with LabView.
In what way(s) did SERRXD not do what you were looking for? But I'm not surprised if it didn't work because SERRXD uses a high baud rate (4800 baud), compared with (and proportional to) the PICaxe's default clock rate (4 MHz). It would be helpful if you could post a 'Scope photo or a Logic Analyser trace of a few serial bytes from the Labview interface (to show the inter-character time gap), but that's probably too much to hope for. Therefore I think that we must assume that the inter-character gap(s) might be quite short. It looks as if you might be quite committed to the 14M2, and also the HSERIN command introduces several "complications", so I think it's worth persevering with SERIN ..... for now.

The problem with the "normal" serial commands (SERIN and SERRXD) is that they "bit bang" the input pin, so the processor is "Busy" (sometimes referred to as "blocking") whilst waiting for a Start pulse, then during the Start Pulse and throughout the eight Data bits. Therefore the only time that it is available for the PICaxe to "process" the received data is during the Stop Pulse(s) and during any inter-character gap (if it exists). Thus the first thing to try is to use SERIN ... with the Lowest baud rate compatible with the appropriate SETFREQ , i.e. 600 baud at the default M4 (4 MHz) through to 4800 baud at SETFREQ M32 (personally I'd try 2400 baud at M16). A quick look at the Labview Serial Interface setup instructions suggests that you can set the baud rate as desired, also set a double-width Stop Pulse ("2 stop bits") and perhaps add a Parity bit, which the PICaxe should just ignore.

Initially, I thought it might be best to Keep It Simples by staying with the EEPROM/DATA memory for now, but there are several problems: The WRITE instruction is one of the slowest executing that I've encountered with a PICaxe, because the EEPROM programming algorithm requires a multiple Write - Verify - Repeat loop. Also, putting the WRITE for each separate byte, within a loop, will cause multiple writes into the same "page", so the memory may wear out much faster than expected. Therefore, I suggest modifying the program to work with data stored in the RAM, for example from byte (pointer) 60 upwards (instead of from zero) and using PEEK instead of the READ keyword. For example, only the following changes may be sufficient:
Code:
init: poke 60 , 11,2,12,1,13,8,6,11,9,12,3,13,2,6,1,9,8,3   ; Test data bytes
  for b6 = 60 to 77 step 2
    peek b6,b8
;    ...                   ; code as before
    peek b7,b8
;    ...
  next

You will need to plan how to "handshake" the transfer of data from the PC, but the SERIN instruction has many more useful features than HSERIN (even in the X2 chips), such as Qualifiers, Timeouts and the automatic parsing of character/bytes into numbers (using the # prefix). i.e. :

" When the #variable format is used received data will be taken and converted to a number.
All characters received are ignored until the first ASCII digit character is received. A number is then determined until a ASCII non-digit character is received. The value stored in the variable will be number represented by the digit characters received. Note that the #variable will not complete until the number has been terminated by a non-digit character being received."


The PICaxe might be fast enough to put the SERIN within an efficient (For .. Next ..) loop, but SERIN can receive a complete block of data in a single line, provided that the number of variables (not the individual characters) is known and fixed. However, this would probably run out of the "named" variables' space (b0-b27), but this can be solved by using the native byte pointer BPTR in place of the b6. Thus the core of the receiving code might be:
Code:
BPTR = 60
SERIN [timeout, address] , pin , baudmode, #@BPTRINC,#@BPTRINC,#@BPTRINC,#@BPTRINC, _
      #@BPTRINC,#@BPTRINC,#@BPTRINC,#@BPTRINC,#@BPTRINC,#@BPTRINC,#@BPTRINC, _
      #@BPTRINC,#@BPTRINC,#@BPTRINC,#@BPTRINC,#@BPTRINC,#@BPTRINC,#@BPTRINC      ; Receive 18 byte variables into RAM
;  Note that the line continuation character "_" must not be followed by comment text !

The equivalent code using HSERIN ... (even with an X2) would be much more complex, and used with the M2 chips has two further "issues": An "oversight" in the design of the base PIC silicon means that it cannot receive "Idle Low" signals (i.e. normal RS232) only Idle High, commonly known as "RS232-TTL" (polarity). There is no workaround except to use an external hardware inverter, for example a MAX232 receiver (or a simple NPN transistor and two resistors may be sufficient). There is also a "bug" in the M2 firmware which can prevent even one pair of concatonated characters being received successfully. It's described in This long Thread particularly posts #1 and #7, but there is any easy workaround ; to use a PEEKSFR $79 , @bptrinc instead of HSERIN W1 . It's also necessary to alter the two lines of code which determine whether a character has actually been received or not (since HSERIN does not wait for a character to arrive).

Cheers, Alan.
 
AllyCat, your solution might work better. Peek and Poke will sure help in making the data available. Waybills
are generated for a one time used and do not need to be retained any further as a new waybill is issued
each time a train arrive. Since the PC keep trace of where is each container, picaxe dosent have to.

Slowing down the comm should help in stablelising the tansfert of data. I made a test using serrxd and sertxd
to echoed the data to the computer and it did show better result when I slow down the execution of the program.

I intend to add a switch on the crane to go from auto mode to manual mode. In this mode, I will put a timeout on
the serin and disconnect so that I can reprogram if needed. And yes, I did put the scope on this but that was not
very concluant. Might be better when I will slow it down.

Thank you for all those infos, time to go back to experimenting a bit more!

N.B. Sorry for the sometimes flaky english, I'm a french canadian!
 
Code:
BPTR = 60
SERIN [timeout, address] , pin , baudmode, #@BPTRINC,#@BPTRINC,#@BPTRINC,#@BPTRINC, _
      #@BPTRINC,#@BPTRINC,#@BPTRINC,#@BPTRINC,#@BPTRINC,#@BPTRINC,#@BPTRINC, _
      #@BPTRINC,#@BPTRINC,#@BPTRINC,#@BPTRINC,#@BPTRINC,#@BPTRINC,#@BPTRINC      ; Receive 18 byte variables into RAM
;  Note that the line continuation character "_" must not be followed by comment text !

The equivalent code using HSERIN ... (even with an X2) would be much more complex,
What would be more complex with HSERIN?

Code:
hsersetup b115200_32, %00001   ' Set up the serial port

receivePage:
   
    failure = 0;
    hserptr = 0;
   
    hserout 0,("G")                            ' 71 is G for "GO"!

    hserin 0,128                                ' Bring in 128 bytes store starting at Scratchpad 0

    if hserptr <> 0 then                      ' 64 works for 64 bytes '0' means we rolled over from 127 ... so 128 bytes rcvd.
        hserout 0,("W")                        ' W for "Wait a sec, this is screwed up!"
        failure = 1
        return
    endif

I use the code above to receive 128 bytes from the PC at 230400 baud (20x2 PICAXE running at 64mhz) ... there is no inter-character delay. After receiving the 128 bytes, the computer waits while the PICAXE writes it to external EEPROM, and then sends a "G" for the next page.

I'm able to push a text file (a book) into a 512kb EEPROM in around 7 seconds with this code. :)
 
What would be more complex with HSERIN?

I use the code above to receive 128 bytes from the PC at 230400 baud (20x2 PICAXE running at 64mhz) ... :)
OP is using a 14M2, so HSERIN doesn't work anything like (as well as) an X2 (as I implied in my earlier post)
 
Hi,

... I made a test using serrxd and sertxd to echoed the data to the computer and it did show better result when I slow down the execution of the program.

I did put the scope on this but that was not very concluant.

N.B. Sorry for the sometimes flaky english, I'm a french canadian!
How much better? But IMHO SERRXD is unlikely to work well. However, if you want to use the same (interface) cable from the PC, then you could link the "RXD" input to also another pin and use SERIN on that. If you make that an "interrupt capable" pin then it could simplify or improve the wakeup / handshake possibilities: From the SETINT Command Syntax : "14M2 : only inputs C.0, C.1 and C.2 may be used" (as an interrupt input).

The present "COM" Interface Protocol is basically just a "Send and Hope" (that the data is correctly received), so a 'Scope trace even with the PICaxe not connected should give an indication of the inter-character time gap, which is what we need for now. The interface might support "Hardware Handshaking" (e.g. CTS on a separate pin), but in my experience the RS232 PC hardware will often send (at least) one more character after the hardware "Stop Sending" level is returned. It might be helpful if the LabView Program could send a "non-digit" character (e.g. the "," separator) at the Start and at the End of the data packet, to activate an Interrupt or Wake-Up Qualifier, and to terminate the # or other Parsing code.

Your English is better than my French. Actually, there is a French section of the forum, but you might get better advice here. :)

What would be more complex with HSERIN?
Code:
hsersetup b115200_32, %00001   ' Set up the serial port
; ......
    hserin 0,128                ' Bring in EXACTLY 128 bytes store starting at Scratchpad 0
The HSERIN command, even with the X2 chips does not support the # operator and receives only individual bytes. But the OP / LabView PC program is transmitting (comma-separated) number variables of 1 or 2 bytes/digits. A count of the variables sent appears to be fixed (at 18) but the number of bytes can be variable (probably around 40), so the program needs to work "intelligently", either at the single-received-byte level, or by Parsing the (background) received data bytes into variable values. To quote from the Description in the Command Syntax [with my clarifications] :

"Users familiar with the serin command will note the hserin command has a completely different format. This is because the hserin command supports much higher baud rates than serin, and so is unable to process received bytes 'on the fly' (e.g. by changing [strings of] ASCII [digits] into binary, as [is possible] with the serin # prefix), because there is insufficient time for this processing to occur before the next hserin byte is received ..."

OP is using a 14M2, so HSERIN doesn't work anything like (as well as) an X2 (as I implied in my earlier post)

Indeed, however I did get (the equivalent PEEKSFR version of) HSERIN working reliably with an 08M2 in a "Background Receive" mode (using interrupts) at 19200_32 baud with fully concatonated bytes. A rate of almost 2,000 bytes per second is faster than a PICaxe (and certainly a "human") can do much useful processing. So personally, I've never found it necessary to resort to an X2 (which is why I don't know much about them ;) ).

Cheers, Alan.
 
Well. I did some test using this program on a spare 14M2. Outputs are 4 leds so that I can check if the routine works.
I set a pattern at start and check if the pattern is altered by the incoming message. So far no luck. I know that the
picaxe receive something since the timeout is reseted but it doesnt seem to be able to decode what is comong in.
I set Labview to 600 baud, 2 stop bits, even parity(for the sake of it) and tried sending the whole string or the string
byte per byte to no avail. There is a subtility somewhere that I'm missing!

Why did I tought it would be simple? :devilish:

JYM
 

Attachments

Hi,

IMHO it's better to post sample programs within [code ] [/code] tags so that we can all see the example without needing to download and read a file. ;) Here's the significant part with a few added comments **.

Code:
    goto showptrn     ;** Before any data has been received?
    goto message       ;** This will never be executed (since it follows an unconditional jump)
message:
    bptr=60
    serin [5000,main] ,c.2, T600_4, ("xx") ,#@bptrinc, #@bptrinc, #@bptrinc, #@bptrinc    ;** Is a QUALIFIER "xx" definitely transmitted ?
    pause 200
    goto showptrn    ;** This is unnecessary (will fall through anyway)
showptrn:    peek 60,b0
    peek 61,b1
    peek 62,b2
    peek 63,b3
    if b0 =1 then high b.0
    endif
; ......
    goto message

First, is Labview definitely transmitting the Qualifier "xx" , i.e. two consecutive bytes = 120 (or $78 or ASCII character "x")? Personally I would NEVER use a Qualifier (i.e. inside the braces "( )" ) until the program is definitely receiving something recognisable. Similarly, very specific IF conditions such as IF b0 = 1 THEN .. give no useful information if/when they fail. One solution would be to transfer each received byte in turn to b0 (i.e. b0= @bptrinc) and then if bit0 = 1 .. ; set the first LED ON, if bit1 = 1 .. ; set the second LED ON through to the fourth LED, and then at least the four LEDs will indicate the values 0 to 15 in binary, and "clues" to other ASCII values (e.g. "1", "A", "a", "Q" and "q" all have their four low bits represented by the nibble 1). Then maybe change to bit4 to bit7 to see the "case" of the characters (e.g. raw/control bytes (0-1), ASCII numbers (3), Capitals (4-5), etc.).

But generally, the best method of debugging serial communications is to "Echo Back" the received characters with a SERTXD command. Maybe this is not as easy if the PC is running both Labview and the PICaxe Editor/Terminal, but it should be possible, at least manually by switching programs or cables. Personally, I would label two of the LEDs "TRANSMIT" (i.e. Ready to receive data via RS232) and "RECEIVED" (i.e. connect the PICaxe terminal to see what has been received) and then use a test program such as (untested) :
Code:
#picaxe 14m2
#no_data
#terminal 4800
symbol Transmit =  b.0       ; LED
symbol Received = b.1
do
    Low Received : High Transmit     ; Initialise LEDs
    bptr=60
main:
    serin [5000,main] c.2, T600_4, @bptrinc, @bptrinc, @bptrinc, @bptrinc   ;  (and perhaps some more) Fall through when received
    Low Transmit
    for b9 = 0 to 9      ; 10 opportunities to report the bytes (in 100 seconds)
      Pause  10000      ; Time to swap programs/cables
      High Received    ; Report that we're transmitting
      bptr = 60
      sertxd (cr,lf, #@bptrinc, #@bptrinc, #@bptrinc, #@bptrinc )
      Low Received
    next b9
loop         ; Try again   (or restart the program if quicker)

Once the above code starts receiving recognisable ASCII number sequences, e.g. 49 for "1" , 120 for "x" , 44 for comma , and 13 for "CR" (Newline) etc., then you can remove the # prefixes and start attempting to decode the received bytes or characters.

Cheers, Alan.
 
Back
Top