Shop OBEX P1 Docs P2 Docs Learn Events
RS485 ROUTER - A Propeller/Tachyon Application — Parallax Forums

RS485 ROUTER - A Propeller/Tachyon Application

Peter JakackiPeter Jakacki Posts: 10,193
edited 2018-02-11 11:34 in Customer Projects
The title might look familiar, I borrowed it off nglordi's post as I never think to post much in the way of projects. But here's one which required five RS485 MODBUS ports operating at 115,200 baud. Normally these only operate at much slower speeds and since MODBUS uses short gaps for delineating packets it's important that the packet stays together even at higher speeds. So here are 57 lines of code in Tachyon Forth that allow a MODBUS master to talk to 4 RS485 ports, each of which may have many units strung off them. Although it is possible to have the master talk directly to the slaves the problem is noise and ringing etc over long lines, so splitting this up in 4 lines allows for more units or longer lines etc. When the master talks to the slaves they all receive the same packet which has already been buffered by the router and then when a slave responds then that packet is buffered until there is enough data to start sending back to the master.

The "application" takes 336 bytes of code and while it is running I can still talk to it in Forth and debug it from the console port. Each RS485 port can work up to 2M baud so 115.2k is certainly not pushing any boundaries in Tachyon.

*** MODBUS RS485 ROUTER ***

64		== rxsz
rxsz 8 +	== comsz
rxsz 1-		== rxszm

--- port buffers: combuf(2) stat(2) rxrd(2) rxwr(2) rxbuf(rxsz)

comsz		bytes combuf1
comsz		bytes combuf2
comsz		bytes combuf3
comsz		bytes combuf4
comsz		bytes combuf5

--- some offset constants
combuf1 8 +	== rxbuf1
combuf1 4 +	== rxrd1
combuf1 6 +	== rxwr1

--- Calculate baud rate ticks
pub b ( baud -- ticks )		CLKFREQ SWAP U/ ;

---                     &mode.te.tx.rx  baud ticks      buffer size     buffer start
TABLE pars
---	 MO TE TX RX     BAUD		RX SIZE		BUFFERS
	&00.00.01.01 ,	115200 b ,	rxsz ||		combuf1 ||	--- COM1 RS485 PORT 1
	&00.02.03.03 ,	115200 b ,	rxsz ||		combuf2 ||	--- COM2 RS485 PORT 2
	&00.04.05.05 ,	115200 b ,	rxsz ||		combuf3 ||	--- COM3 RS485 PORT 3
	&00.06.07.07 ,	115200 b ,	rxsz ||		combuf4 ||	--- COM4 RS485 PORT 4
	&00.08.09.09 ,	115200 b ,	rxsz ||		combuf5 ||	--- COM5 RS485 MASTER

---		Load HSUART ROM from cog 3 with 12 byte pars entries for 5 cogs - then flush all buffers
pub !COMS	" HSUART    " 3 pars 12 5 LOADCOGS 50 ms combuf1 comsz 5 * ERASE ;

--- common transmit routine - store to channels combuf when ready
pub TX ( dat ch -- )		1- comsz * combuf1 + TX! ;

--- common receive buffer check
pri RX? ( chan -- offset diff )	 1- comsz * rxwr1 OVER + W@ rxrd1 3RD + W@ - rxszm AND ;

--- common read buffered receive data routine
pri RX ( chan -- dat )
	RX?
	IF rxrd1 OVER + W@ rxszm AND rxbuf1 3RD + + C@ $100 OR SWAP rxrd1 + W++
	ELSE DROP FALSE
	THEN
	;

pub ROUTER
---	start delivering data from master to slave ports when enough data is already buffered
	5 RX? NIP 3 > IF BEGIN 5 RX ?DUP WHILE 4 FOR DUP I 1+ TX NEXT DROP REPEAT THEN
---	scan all 4 slave ports and send to master if enough data is buffered
	4 FOR I 1+ RX? NIP 3 > IF BEGIN I 1+ RX ?DUP WHILE 5 TX REPEAT NEXT
	;

--- setup 5 high-speed RS485 UARTS and run router in background ( leave console active )
pub MAIN	CR !COMS ' ROUTER keypoll W! ;

Here's the packet timing using another Tachyon unit for the master and one of my units as a slave at address 7.
MODBUS%20ROUTER.png

Comments

  • You do such neat things with Tachyon that I really want to learn it. And then I think to myself, "Holy ****, where do I start?"
  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2018-02-11 23:33
    JonnyMac wrote: »
    You do such neat things with Tachyon that I really want to learn it. And then I think to myself, "Holy ****, where do I start?"

    Thanks Jon, but in return I would say you do such neat things with action Props and WS2812 style LEDs that I would say "why don't you start there" :)
    Starting with what you do know, you know what to expect. The difference now though is that you can interact at the console level, either directly or having it run in its own cog.

    There are just three words specifically for this type of serial LED, they are LEDPIN to set the target pin, LED for playing with a single LED or LEDS where you specify the array and bytes which of course varies with whether they are RGB or RGBW. In fact they could all be combined in just one word if needed These are just the primitives but you can extend the language to include the JM pizazz!

    Some basics:
    19 LEDPIN --- use pin 19
    red LED --- just light up a single LED with one of 7 ANSI colors ( red /green/yellow/blue/magenta/cyan/white )
    $404000 LED --- use a 24-bit color
    20 LEDPIN --- I decide to connect a 40 LED array on pin 20
    0 120 LEDS --- will simply write out memory from address 0 fro 120 bytes to those 40 WS2812 LEDs.

    To make 8 lines of 40 LEDs continually refresh from a buffer (P0..P7 for simplicity):
    120 8 * bytes myleds
    pub JMWHEEL    BEGIN 8 FOR I LEDPIN I 120 * myleds + 120 LEDS NEXT AGAIN ;
    
    Then kick it off using cog 3:
    ' JMWHEEL 3 RUN
    
    Then all you have to worry about is writing to the myleds buffer knowing that one line of code is looking after those strings of LEDs.

    Sorry to have LED you astray :)
  • The key for me is becoming as comfortable with Forth as I am with Spin. I recently purchased Starting Forth and Thinking Forth -- will dive in and see how it goes.
  • JonnyMac wrote: »
    The key for me is becoming as comfortable with Forth as I am with Spin. I recently purchased Starting Forth and Thinking Forth -- will dive in and see how it goes.

    Well that's a good start, I have those books although I had "lost" (lent) my copies of Starting Forth but ended up finding an original a few years ago. I have fond memories of my first copy of that about the same time I had a copy of my K&R white book which was boring (but the cover was cute).

    While it is possible to follow along with an old 79 standard Forth on a PC, it is infinitely better to connect up Tachyon and try some of those basics. There are a lot of things that are non-standard about Tachyon, a Forth for a non-standard micro, but those non-standard things are where the most fun and usefulness are. Remember though that Tachyon compiles everything you type in rather than interpreting the words, so that once you hit the enter key it is read to run, so you can include all those compile-time only words which you can't use with standard Forths, for looping, branching, printing " Hello World" etc

    The latest versions of Tachyon though do away with DO and LOOP and +LOOP favoring the simpler FOR NEXT but allowing indexing and then augmenting those words with FROM for a starting index and BY for the index step. The looping words have their own stack so all those restrictions that apply in Starting Forth because they use the return stack don't apply in Tachyon so loops can be referenced outside of the loop when you call other functions. I will probably have to rewrite my Introduction to Tachyon page though. Have fun!

  • I fully intend to be running any exercises from any Forth book I can find through Tachyon. Again, I just want to learn the language and then start to build fun things from it. I was just watching your RS-485 demo on YouTube and smiling because it was so cool. For most of my big Hollywood displays I use the EFX-TEK HC-8+ which has a full-duplex RS-485 circuit on it. Most of the time, I use one controller as a master and the others as DMX slaves. It would be fun to extend that in a way that I could interact with the system in real-time through a terminal.
Sign In or Register to comment.