Full Duplex Serial Tx/Rx with XBee
Botulism
Posts: 18
in Propeller 1
I can successfully Tx from a Propeller to a PC with XBees in between. I can also Tx from one Propeller to a second Propeller with XBees in between, but the Rx data is not right. I have been searching and reading everything I can find and I feel like the answer is obvious, but I'm missing something.
Setups are identical for both Propellers: 2 buttons to incr/decr a variable, a serial LCD display, and an XBee.
When both bootup the value of the variable is displayed correctly. The variable on the Rx Propeller incr/decr correctly when it's local buttons are pushed. However, the variable on the Rx side jumps from it's starting value to 48 or 57 and then incr/decr between 48 and 57 when the buttons are pushed on the Tx side. I know communication is occuring, but the data is garbled.
Tx Propeller Code:
CON
_clkmode = xtal1 + pll16x
_xinfreq = 5_000_000
TX = 2 'Tx pin for display
BAUD = 9_600 'Display BAUD
UpButton = 1 'Button changes the frequency up
DownButton = 0 'Button changes the frequency down
XB_Rx = 14 'XBee DOUT Data coming in from XBee
XB_Tx = 13 'XBee DIN Data going out of XBee
XB_Baud = 9600 'Baud for XBee
OBJ
LCD : "FullDuplexSerial.spin"
XB : "FullDuplexSerial.spin"
VAR
long Stack[40], Stack1[40]
byte number
PUB Main
LCD.start(TX, TX, %1000, BAUD) 'Initialize comms for display
waitcnt(10000 + cnt) 'Pause for FullDuplexSerial.spin to initialize
LCD.tx(12) 'Clear Display
waitcnt(10000 + cnt) 'Pause for Clear Display Command
LCD.tx(17) 'Turn On LCD Backlight
LCD.tx(22) 'Turn Display on with No Cursor and No Blink
XB.start(XB_Rx, XB_Tx, 0, XB_Baud) 'Initialize comms for XBee
waitcnt(10000 + cnt) 'Pause for XB to initialize
cognew (Check, @Stack) 'Cog to check button state
cognew (Display, @Stack1) 'Cog for display
number := 10 'Initial value
dira[UpButton] := 0 'Set Buttons as INPUT
dira[DownButton] := 0
outa[UpButton] := 1 'Set Buttons HIGH because buttons pulls LOW
outa[DownButton] := 1
PUB Display
repeat
LCD.tx(12) 'Clear Display
waitcnt(10000 + cnt) 'Pause for Clear Display Command
LCD.str(String("Number: "))
LCD.Dec(number)
waitcnt(clkfreq/10 + cnt)
PUB Check 'Check if a button is pressed
repeat
if ina[UpButton] == 0 'Increase number
waitcnt(clkfreq/20 + cnt)
if ina[UpButton] == 0
number++
XB.Dec(number)
waitcnt(clkfreq + cnt)
if ina[DownButton] == 0 'Decrease number
waitcnt(clkfreq/20 + cnt)
if ina[DownButton] == 0
number--
XB.Dec(number)
waitcnt(clkfreq + cnt)
Rx Propeller Code:
CON
_clkmode = xtal1 + pll16x
_xinfreq = 5_000_000
TX = 2 'Tx pin for display
BAUD = 9_600 'Display BAUD
UpButton = 1 'Button changes the frequency up
DownButton = 0 'Button changes the frequency down
XB_Rx = 14 'XBee DOUT Data coming in from XBee
XB_Tx = 13 'XBee DIN Data going out of XBee
XB_Baud = 9600 'Baud for XBee
OBJ
LCD : "FullDuplexSerial.spin"
XB : "FullDuplexSerial.spin"
VAR
long Stack[40], Stack1[40], Stack2[40]
byte number
PUB Main
LCD.start(TX, TX, %1000, BAUD) 'Initialize comms for display
waitcnt(10000 + cnt) 'Pause for FullDuplexSerial.spin to initialize
LCD.tx(12) 'Clear Display
waitcnt(10000 + cnt) 'Pause for Clear Display Command
LCD.tx(17) 'Turn On LCD Backlight
LCD.tx(22) 'Turn Display on with No Cursor and No Blink
XB.start(XB_Rx, XB_Tx, 0, XB_Baud) 'Initialize comms for XBee
waitcnt(10000 + cnt) 'Pause for XB to initialize
cognew (Check, @Stack) 'Cog to check button state
cognew (Display, @Stack1) 'Cog for display
cognew (XBee, @Stack2) 'Cog for XBee
number := 20 'Initial value
dira[UpButton] := 0 'Set Buttons as INPUT
dira[DownButton] := 0
outa[UpButton] := 1 'Set Buttons HIGH because buttons pulls LOW
outa[DownButton] := 1
PUB Display
repeat
LCD.tx(12) 'Clear Display
waitcnt(10000 + cnt) 'Pause for Clear Display Command
LCD.str(String("Number: "))
LCD.Dec(number)
waitcnt(clkfreq/10 + cnt)
PUB Check 'Check if a button is pressed
repeat
if ina[UpButton] == 0 'Increase number
waitcnt(clkfreq/20 + cnt)
if ina[UpButton] == 0
number++
waitcnt(clkfreq + cnt)
if ina[DownButton] == 0 'Decrease number
waitcnt(clkfreq/20 + cnt)
if ina[DownButton] == 0
number--
waitcnt(clkfreq + cnt)
PUB XBee
repeat
number := XB.Rx ' Rx data from XBee
Setups are identical for both Propellers: 2 buttons to incr/decr a variable, a serial LCD display, and an XBee.
When both bootup the value of the variable is displayed correctly. The variable on the Rx Propeller incr/decr correctly when it's local buttons are pushed. However, the variable on the Rx side jumps from it's starting value to 48 or 57 and then incr/decr between 48 and 57 when the buttons are pushed on the Tx side. I know communication is occuring, but the data is garbled.
Tx Propeller Code:
CON
_clkmode = xtal1 + pll16x
_xinfreq = 5_000_000
TX = 2 'Tx pin for display
BAUD = 9_600 'Display BAUD
UpButton = 1 'Button changes the frequency up
DownButton = 0 'Button changes the frequency down
XB_Rx = 14 'XBee DOUT Data coming in from XBee
XB_Tx = 13 'XBee DIN Data going out of XBee
XB_Baud = 9600 'Baud for XBee
OBJ
LCD : "FullDuplexSerial.spin"
XB : "FullDuplexSerial.spin"
VAR
long Stack[40], Stack1[40]
byte number
PUB Main
LCD.start(TX, TX, %1000, BAUD) 'Initialize comms for display
waitcnt(10000 + cnt) 'Pause for FullDuplexSerial.spin to initialize
LCD.tx(12) 'Clear Display
waitcnt(10000 + cnt) 'Pause for Clear Display Command
LCD.tx(17) 'Turn On LCD Backlight
LCD.tx(22) 'Turn Display on with No Cursor and No Blink
XB.start(XB_Rx, XB_Tx, 0, XB_Baud) 'Initialize comms for XBee
waitcnt(10000 + cnt) 'Pause for XB to initialize
cognew (Check, @Stack) 'Cog to check button state
cognew (Display, @Stack1) 'Cog for display
number := 10 'Initial value
dira[UpButton] := 0 'Set Buttons as INPUT
dira[DownButton] := 0
outa[UpButton] := 1 'Set Buttons HIGH because buttons pulls LOW
outa[DownButton] := 1
PUB Display
repeat
LCD.tx(12) 'Clear Display
waitcnt(10000 + cnt) 'Pause for Clear Display Command
LCD.str(String("Number: "))
LCD.Dec(number)
waitcnt(clkfreq/10 + cnt)
PUB Check 'Check if a button is pressed
repeat
if ina[UpButton] == 0 'Increase number
waitcnt(clkfreq/20 + cnt)
if ina[UpButton] == 0
number++
XB.Dec(number)
waitcnt(clkfreq + cnt)
if ina[DownButton] == 0 'Decrease number
waitcnt(clkfreq/20 + cnt)
if ina[DownButton] == 0
number--
XB.Dec(number)
waitcnt(clkfreq + cnt)
Rx Propeller Code:
CON
_clkmode = xtal1 + pll16x
_xinfreq = 5_000_000
TX = 2 'Tx pin for display
BAUD = 9_600 'Display BAUD
UpButton = 1 'Button changes the frequency up
DownButton = 0 'Button changes the frequency down
XB_Rx = 14 'XBee DOUT Data coming in from XBee
XB_Tx = 13 'XBee DIN Data going out of XBee
XB_Baud = 9600 'Baud for XBee
OBJ
LCD : "FullDuplexSerial.spin"
XB : "FullDuplexSerial.spin"
VAR
long Stack[40], Stack1[40], Stack2[40]
byte number
PUB Main
LCD.start(TX, TX, %1000, BAUD) 'Initialize comms for display
waitcnt(10000 + cnt) 'Pause for FullDuplexSerial.spin to initialize
LCD.tx(12) 'Clear Display
waitcnt(10000 + cnt) 'Pause for Clear Display Command
LCD.tx(17) 'Turn On LCD Backlight
LCD.tx(22) 'Turn Display on with No Cursor and No Blink
XB.start(XB_Rx, XB_Tx, 0, XB_Baud) 'Initialize comms for XBee
waitcnt(10000 + cnt) 'Pause for XB to initialize
cognew (Check, @Stack) 'Cog to check button state
cognew (Display, @Stack1) 'Cog for display
cognew (XBee, @Stack2) 'Cog for XBee
number := 20 'Initial value
dira[UpButton] := 0 'Set Buttons as INPUT
dira[DownButton] := 0
outa[UpButton] := 1 'Set Buttons HIGH because buttons pulls LOW
outa[DownButton] := 1
PUB Display
repeat
LCD.tx(12) 'Clear Display
waitcnt(10000 + cnt) 'Pause for Clear Display Command
LCD.str(String("Number: "))
LCD.Dec(number)
waitcnt(clkfreq/10 + cnt)
PUB Check 'Check if a button is pressed
repeat
if ina[UpButton] == 0 'Increase number
waitcnt(clkfreq/20 + cnt)
if ina[UpButton] == 0
number++
waitcnt(clkfreq + cnt)
if ina[DownButton] == 0 'Decrease number
waitcnt(clkfreq/20 + cnt)
if ina[DownButton] == 0
number--
waitcnt(clkfreq + cnt)
PUB XBee
repeat
number := XB.Rx ' Rx data from XBee
Comments
Your coding seems quite minimal on the Xbee side and you have not mentioned how the Xbees are configured, so it is difficult to troubleshoot.
I used the comprehensive coding, data flow and configuration from examples in Martin Hebel's "Getting started with Xbee" tutorial, then pared my coding back when I was confident on the Xbee interface.
There is even mesh networking covered here
This all works for byte sized chunks. How do I move numbers larger than a byte?
Not quite, the default from Digi is that both the destination address (DH:DL) and the receive address (MY) are set to zero, so they can communicate in transparent mode right out of the box. Good until you want more capabilities and a fancier network. Assuming this is a 802.15.4 XBee.
When you include code, it helps if you enclose it in code brackets (The letter "C" on the formatting bar). Then it will retain the Spin indentations. Is the following the way it is, so it increments and decrements at 1 second intervals as long as you hold down the button?
That should be good for big numbers as well as bytes.
Yes, it incr/decr every second.
Apparently, I have never displayed a number larger than 3 digits in length to the Parallax display - https://www.parallax.com/product/27977. The moment I get to 4 digits the display just shows 255. There a command I'm missing? Looking at FullDuplexSerial and it doesn't appear to be limited by this. Is it the display? The examples I can find never go above 3 digits.