Prop to Prop communication
Hello
I have 2 prop, they work in series using the this http://forums.parallax.com/showthread.php?134641-DEMO-High-Speed-Multi-Prop-to-Prop-Communication
My problem is that i have 4 button to control 1 light. I have 2 ON and 2 OFF. Wen i click ON the light turn on but wen I click OFF on the client prop the light stay ON.
I what to know if it's possible to use 4 button to turn on and off a single light?
Client code
Server code
I have 2 prop, they work in series using the this http://forums.parallax.com/showthread.php?134641-DEMO-High-Speed-Multi-Prop-to-Prop-Communication
My problem is that i have 4 button to control 1 light. I have 2 ON and 2 OFF. Wen i click ON the light turn on but wen I click OFF on the client prop the light stay ON.
I what to know if it's possible to use 4 button to turn on and off a single light?
Client code
{{***************************************
* HighSpeed Client DEMO v1.0a *
* Author: Beau Schwabe *
* Copyright (c) 2011 Parallax, Inc. *
* See end of file for terms of use. *
***************************************
Revision History:
Version 1.0 - (09/20/2011) initial release
Version 1.0a - (09/26/2011) minor change to detect When the USB plug is connected
to the PC. This prevents unwanted resets.
}}
CON
' Set up the processor clock in the standard way for 80MHz on DemoBoard
_CLKMODE = xtal1 + pll16x
_XINFREQ = 5_000_000 + 0000
RX_Pin = 26
TX_Pin = 27
Command = 00 '' Feature not used in this demo
Offset = 0 '' Feature not used in this demo
USB_Rx = 31
USB_Tx = 30
RANGE = 23 'Range is 0 to RANGE.
SAMPLES = 2 'Number of samples to pick: 1 to RANGE + 1
temps = 1
_irrpin = 0 'ir receiver module on this pin
_device = 0 'accept any device code
_dlyrpt = 6 'delay before acception code as repeat
{{
Round Robin configuration using 2 Propellers:
┌────────────────────────────//────────────────────────────┐
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ Propeller 1 │ │ Propeller 2 │ │
┣─┤RX TX├──┳───//───┳─┤RX TX├──┫
 │ Client │   │ Server │ 
 └─────────────────┘   └─────────────────┘ 
Vss Vss Vss Vss
Round Robin configuration using 3 or more Propellers:
┌────────────────────────────/.../────────────────────────────────/.../────────────────────────────┐
│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │
│ │ Propeller 2 │ │ Propeller N │ │ Propeller 1 │ │
┣─┤RX TX├──┳───/.../───┳─┤RX TX├──┳───/.../───┳─┤RX TX├──┫
 │ Client │   │ Client │   │ Server │ 
 └─────────────────┘   └─────────────────┘   └─────────────────┘ 
Vss Vss Vss Vss Vss Vss
Note: All resistors tied to Vss are 330 Ohm and are there to establish a transmission line
Note: All resistors between TX and RX are 100 Ohm and are there to current limit the I/O's in the chance
of a collision.
With round robin, the idea is that you have one buffer that propagated around and around inside the
round robin loop. To avoid any data collisions, all Propellers are capable of reading any location
within the buffer, however each Propeller has a specific (assigned by the programmer) location that
it can write to.
So in the Demo, there is a 1K long buffer (4K bytes). As an example Propeller 1 may only write to
locations 0 to 255. While Propeller 2 can write to locations 256 to 511. Propellers 3 & 4 depicted
as N because of the expandable nature of round robin would write to the remaining 512 to 1023 locations.
}}
VAR
long Buffer[10]
long Buffer1[10]
byte Pin[10]
long Stack[400],Stack1[400]
byte numbers[RANGE + 1]
long seed
long keycode
OBJ
hsRX : "HSp2pRX" 'High Speed Receive driver
hsTX : "HSp2pTX" 'High Speed Transmit driver
PST : "Parallax Serial Terminal" 'RS232 Serial Driver
rcvir : "ir_reader_sony"
SN : "Simple_Numbers"
PUB Main
Start
PUB Main_IR
rcvir.init(_irrpin,_device,_dlyrpt,true) 'startup
Start_IR1
PUB Start|debugLED
'-------------------------------------------------------------------------------------------
if ina[USB_Rx] == 0 '' Check to see if USB port is powered
outa[USB_Tx] := 0 '' Force Propeller Tx line LOW if USB not connected
else
cognew(SerialDisplay,@Stack) '' Initialize serial communication to the PC
'-------------------------------------------------------------------------------------------
dira[16..23]~~ '<- I/O direction for debug LEDs
'-------------------------------------------------------------------------------------------
repeat
hsRX.RX(RX_Pin,@Buffer) '<- Receive Data from External Propeller
hsTX.TX(TX_Pin,10,@Buffer,Command,Offset) '<- Transmit Data to External Propeller
hsTX.TX(TX_Pin,10,@Buffer1,Command,Offset) '<- Transmit Data to External Propeller
hsRX.RX(RX_Pin,@Buffer1)
Menu_Principal
'-------------------------------------------------------------------------------------------
'-------------------------------------------------------------------------------------------
PUB Start_IR1
repeat
keycode := rcvir.fifo_get 'try a get from fifo
if keycode == -1 'empty try again
keycode := keycode + 1
next
else
keycode := keycode + 1
Menu_Principal_IR
PUB Menu_Principal_IR
' ~~=on ~=off
dira[16..21]~~
[COLOR=#ff0000]case keycode
1 : bytemove(@Buffer1,@IR_ON,strsize(@IR_ON))
outa[16]~~
129 : bytemove(@Buffer1,@IR_OFF,strsize(@IR_OFF))
outa[16]~[/COLOR]
2 : !outa[17]
3 : !outa[18]
4 : !outa[19]
5 : !outa[20]
6 : !outa[21]
7 : outa[16..21]~~
8 : LED
9 : RANDOM
22 : outa[16..21]~
PUB SerialDisplay 'DEBUG ONLY
PST.Start(19200)
repeat
PST.HOME
PST.dec(Buffer1[9] ) '<- Display Data
PUB Menu_Principal
[COLOR=#ff0000]case Buffer[0]
1: outa[16]~~
0: outa[16]~ [/COLOR]
outa[17] := Buffer[1]
outa[18] := Buffer[2]
outa[19] := Buffer[3]
outa[20] := Buffer[4]
outa[21] := Buffer[5]
PUB RANDOM | i, j, sample1, sample2
repeat 10
repeat i from 10 to RANGE 'Fill numbers array in order.
numbers[i] := i
repeat i from 10 to (SAMPLES - 1)
j := ||?seed // (RANGE - i + 1) + i 'Pick a number at random from the remaining choices.
sample1 := numbers[j]
bytemove(@numbers[i + 1], @numbers[i], j - i) 'Shift the values to make room.
numbers[i] := sample1
if sample1 < sample2
sample2 := sample1
waitcnt( _xinfreq / temps +cnt)
outa[16..23]~
waitcnt( _xinfreq / temps +cnt)
!outa[sample2]
next
if sample1 > sample2
sample2 := sample1
waitcnt( _xinfreq / temps +cnt)
outa[16..23]~
waitcnt( _xinfreq / temps +cnt)
!outa[sample2]
next
if sample1 == sample2
j := ||?seed // (RANGE - i + 1) + i 'Pick a number at random from the remaining choices.
sample1 := numbers[j]
bytemove(@numbers[i + 1], @numbers[i], j - i) 'Shift the values to make room.
numbers[i] := sample1
next
'Put the selected number in the newly vacated spot.
bytemove(@Buffer1,@NB1,strsize(@NB1))
PUB LED
dira[16..23]~~
outa[16..23]~
repeat 10
outa[16]~
!outa[23]
waitcnt ( _xinfreq + cnt)
!outa[23]
!outa[22]
waitcnt ( _xinfreq + cnt)
!outa[22]
!outa[21]
waitcnt ( _xinfreq + cnt)
!outa[21]
!outa[20]
waitcnt ( _xinfreq + cnt)
!outa[20]
!outa[19]
waitcnt ( _xinfreq + cnt)
!outa[19]
!outa[18]
waitcnt ( _xinfreq + cnt)
!outa[18]
!outa[17]
waitcnt ( _xinfreq + cnt)
!outa[17]
!outa[16]
waitcnt ( _xinfreq + cnt)
outa[16]~
bytemove(@Buffer1,@NB2,strsize(@NB2))
DAT
NB1 BYTE 1,0
NB2 BYTE 2,0
PIN0 BYTE 0,0
PIN1 BYTE 1,0
IR_ON BYTE 1,0
IR_OFF BYTE 129,0
Server code
{{
─────────────────────────────────────────────────
Copyright (c) 2011 AgaveRobotics LLC.
See end of file for terms of use.
File....... HTTPServer.spin
Author..... Mike Gebhard
Company.... Agave Robotics LLC
Email...... mailto:mike.gebhard@agaverobotics.com
Started.... 11/01/2010
Updated.... 07/16/2011
─────────────────────────────────────────────────
}}
{
About:
HTTPServer is the designed for use with the Spinneret Web server manufactured by Parallax Inc.
Usage:
HTTPServer is the top level object.
Required objects:
Parallax Serial Terminal.spin
W5100_Indirect_Driver.spin
S35390A_SD-MMC_FATEngineWrapper.spin
Request.spin
Response.spin
StringMethods.spin
S35390A_RTCEngine.spin
Change Log:
}
CON
_clkmode = xtal1 + pll16x
_xinfreq = 5_000_000
MAX_PACKET_SIZE = $5C0 '1472 '$800 = 2048
RxTx_BUFFER = $800 '$600 = 1536
TEMP_BUFFER = $600 '$5B4 = 1460
TCP_PROTOCOL = 01 '$300 = 768
UDP_PROTOCOL = 10 '$200 = 512
TCP_CONNECT = $04 '$100 = 256
DELAY = $10
MAX_TRIES = $25
#0, DONE, PUT, CD
RX_Pin = 27
TX_Pin = 26
Command = 00 '' Feature not used in this demo
Offsett = 0 '' Feature not used in this demo
DAT
mac byte $00, $08, $DC, $16, $F2, $73
subnet byte 255, 255 ,255, 0
gateway byte 108,171,79,7 'WAN Default Gateway : 24.230.203.1
ip byte 192,168,0,105 'LAN
port word 5555
remoteIp byte 24,230,203,105 'http://www.whatismyip.com
remotePort word 80
uport word 5050
emailIp byte 0, 0, 0, 0
emailPort word 25
status byte $00, $00, $00, $00
rxdata byte $0[RxTx_BUFFER]
txdata byte $0[RxTx_BUFFER]
udpdata byte $0[TEMP_BUFFER]
fileErrorHandle long $0
debug byte $0
lastFile byte $0[12], 0
closedState byte 00
openState byte 00
listenState byte 00
establishedState byte 00
closingState byte 00
closeWaitState byte 00
lastEstblState byte 00
lastEstblStateDebug byte 00
udpListen byte 00
tcpMask byte 11
udpMask byte 00
fifoSocketDepth byte $0
fifoSocket long $00_00_00_00
debugSemId byte $00
debugCounter long $00
stringMethods long $00
closingTimeout long $00, $00, $00, $00
udpLen long $00
time byte "00/00/0000 00:00:00", 0
httpDate byte "Wed, 01 Feb 2000 01:00:00 GMT", 0
globalCache byte $1
NB0 BYTE 999,0
NB1 BYTE 1,0
NB2 BYTE 2,0
NB3 BYTE 3,0
NB4 BYTE 4,0
NB5 BYTE 5,0
NB6 BYTE 6,0
NB7 BYTE 7,0
NB8 BYTE 8,0
NB9 BYTE 9,0
NB22 BYTE 22,0
VAR
long StackSpace[20]
long stack[50]
long Buffer[10]
long Buffer1[10]
byte Pin[10]
OBJ
pst : "Parallax Serial Terminal"
Socket : "W5100_Indirect_Driver"
SDCard : "S35390A_SD-MMC_FATEngineWrapper"
Request : "Request"
Response : "Response"
str : "StringMethods"
rtc : "S35390A_RTCEngine"
hsRX : "HSp2pRX" 'High Speed Receive driver
hsTX : "HSp2pTX" 'High Speed Transmit driver
PUB Initialize | id, size, st , x
debug := 1
SDCard.Start
stringMethods := str.Start
Request.Constructor(stringMethods)
Response.Constructor(stringMethods, @txdata)
pst.Start(115_200)
pause(200)
'Mount the SD card
pst.str(string("Mount SD Card - "))
SDCard.mount(fileErrorHandle)
pst.str(string("OK",13))
pst.str(string("Start RTC: "))
rtc.RTCEngineStart(29, 28, -1)
pause(200)
pst.str(FillTime)
'Start the W5100 driver
if(Socket.Start)
pst.str(string(13, "W5100 Driver Started", 13))
pst.str(string(13, "Status Memory Lock ID : "))
pst.dec(Socket.GetLockId)
pst.char(13)
if(debugSemId := locknew) == -1
pst.str(string("Error, no HTTP server locks available", 13))
else
pst.str(string("HTTP Server Lock ID : "))
pst.dec(debugSemId)
pst.char(13)
'Set the Socket addresses
SetMac(@mac)
SetGateway(@gateway)
SetSubnet(@subnet)
SetIP(@ip)
' Initailize TCP sockets (defalut setting; TCP, Port, remote ip and remote port)
repeat id from 0 to 3
InitializeSocket(id)
Request.Release(id)
pause(50)
' Set all TCP sockets to listen
pst.char(13)
repeat id from 0 to 3
Socket.Listen(id)
pst.str(string("TCP Socket Listener ID : "))
pst.dec(id)
pst.char(13)
pause(50)
pst.Str(string(13,"Started Socket Monitoring Service", 13))
x := 6
cognew(StatusMonitor, @StackSpace)
pause(250)
pst.Str(string(13, "Initial Socket States",13))
StackDump
pst.Str(string(13, "Initial Socket Queue",13))
QueueDump
pst.str(string(13,"//////////////////////////////////////////////////////////////",13))
Main
PUB Main | packetSize, id, i, reset, j, temp
''HTTP Service
repeat
comm
repeat until fifoSocket == 0
bytefill(@rxdata, 0, RxTx_BUFFER)
if(debug)
pst.str(string(13, "----- Start of Request----------------------------",13))
pause(DELAY)
else
pause(DELAY)
' Pop the next socket handle
id := DequeueSocket
if(id < 0)
next
if(debug)
pst.str(string(13,"ID: "))
pst.dec(id)
pst.str(string(13, "Request Count : "))
pst.dec(debugCounter)
pst.char(13)
packetSize := Socket.rxTCP(id, @rxdata)
reset := false
if ((packetSize < 12) AND (strsize(@rxdata) < 12))
repeat i from 0 to MAX_TRIES
pst.str(string(13,"* Retry *"))
'Wait for a few moments and try again
waitcnt((clkfreq/300 ) + cnt)
packetSize := Socket.rxTCP(id, @rxdata)
if(packetSize > 12)
quit
if(i == MAX_TRIES)
'Clean up resource request
Request.Release(id)
Socket.Disconnect(id)
reset := true
if(debug)
StackDump
pst.char(13)
QueueDump
pst.str(string(13,"* Timeout *",13))
if(reset)
next
Request.InitializeRequest(id, @rxdata)
if(debug)
pst.char(13)
HeaderLine1(id)
else
pause(DELAY)
' Process router
Dispatcher(id)
'Clean up request resource
Request.Release(id)
' This starts the close process -> 0x00
' use close to force a close
Socket.Disconnect(id)
bytefill(@txdata, 0, RxTx_BUFFER)
debugCounter++
GotoMain
PUB comm
dira[23]~~
repeat 1
hsTX.TX(TX_Pin,10,@Buffer,Command,Offsett) '<- Transmit Data to External Propeller
hsRX.RX(RX_Pin,@Buffer) '<- Receive Data from External Propeller
hsRX.RX(RX_Pin,@Buffer1) '<- Receive Data from External Propeller
hsTX.TX(TX_Pin,10,@Buffer1,Command,Offsett) '<- Transmit Data to External Propeller
case Buffer1[0]
1: outa[23]~~
129: outa[23]~
return
PRI SendLedResposne(id) | headerLen, qstr,qstr1
'' Get the query string value
comm
qstr := Request.Get(id, string("led"))
qstr1 := Buffer1[0]
'' Exit if there is no querystring
if(qstr == 0)
return false
'' Turn the LED on if the led= value is "on"
if (strcomp(string("on"), qstr )) or qstr1 == 1
LedStatus(1)
Buffer[0] := 1
qstr1 := 1
comm
if (strcomp(string("off"), qstr )) or qstr1 == 129
LedStatus(0)
Buffer[0] := 0
qstr1 := 129
comm
if (strcomp(string("what"), qstr ))
if(pin[0]) == 1 and qstr1 == 1
qstr := string("on")
qstr1 := 1
else
qstr := string("off")
qstr1 := 0
comm
'' Build and send the header
'' Send the value of led= on or off
headerLen := Response.BuildHeader(Request.GetExtension(id), 200, globalCache)
Socket.txTCP(id, @txdata, headerLen)
Socket.txTCP(id, qstr, strsize(qstr))
comm
return true
PRI SendLedResposneA(id) | headerLen, qstr
'' Get the query string value
qstr := Request.Get(id, string("led"))
'' Exit if there is no querystring
if(qstr == 0)
return false
'' Turn the LED on if the led= value is "on"
if (strcomp(string("on"), qstr ))
LedStatus1(1)
Buffer[1] := 1
if (strcomp(string("off"), qstr ))
LedStatus1(0)
Buffer[1] := 0
if (strcomp(string("what"), qstr ))
if(pin[1])== 1
qstr := string("on")
else
qstr := string("off")
'' Build and send the header
'' Send the value of led= on or off
headerLen := Response.BuildHeader(Request.GetExtension(id), 200, globalCache)
Socket.txTCP(id, @txdata, headerLen)
Socket.txTCP(id, qstr, strsize(qstr))
comm
return true
PRI SendLedResposneB(id) | headerLen, qstr
'' Get the query string value
qstr := Request.Get(id, string("led"))
'' Exit if there is no querystring
if(qstr == 0)
return false
'' Turn the LED on if the led= value is "on"
if (strcomp(string("on"), qstr ))
LedStatus2(1)
Buffer[2] := 1
if (strcomp(string("off"), qstr ))
LedStatus2(0)
Buffer[2] := 0
if (strcomp(string("what"), qstr ))
if(pin[2])==1
qstr := string("on")
else
qstr := string("off")
'' Build and send the header
'' Send the value of led= on or off
headerLen := Response.BuildHeader(Request.GetExtension(id), 200, globalCache)
Socket.txTCP(id, @txdata, headerLen)
Socket.txTCP(id, qstr, strsize(qstr))
comm
return true
PRI SendLedResposneC(id) | headerLen, qstr
'' Get the query string value
qstr := Request.Get(id, string("led"))
'' Exit if there is no querystring
if(qstr == 0)
return false
'' Turn the LED on if the led= value is "on"
if (strcomp(string("on"), qstr ))
LedStatus3(1)
Buffer[3] := 1
if (strcomp(string("off"), qstr ))
LedStatus3(0)
Buffer[3] := 0
if (strcomp(string("what"), qstr ))
if(pin[3])==1
qstr := string("on")
else
qstr := string("off")
'' Build and send the header
'' Send the value of led= on or off
headerLen := Response.BuildHeader(Request.GetExtension(id), 200, globalCache)
Socket.txTCP(id, @txdata, headerLen)
Socket.txTCP(id, qstr, strsize(qstr))
comm
return true
PRI SendLedResposneD(id) | headerLen, qstr
'' Get the query string value
qstr := Request.Get(id, string("led"))
'' Exit if there is no querystring
if(qstr == 0)
return false
'' Turn the LED on if the led= value is "on"
if (strcomp(string("on"), qstr ))
LedStatus4(1)
Buffer[4] := 1
if (strcomp(string("off"), qstr ))
LedStatus4(0)
Buffer[4] := 0
if (strcomp(string("what"), qstr ))
if(pin[4])==1
qstr := string("on")
else
qstr := string("off")
'' Build and send the header
'' Send the value of led= on or off
headerLen := Response.BuildHeader(Request.GetExtension(id), 200, globalCache)
Socket.txTCP(id, @txdata, headerLen)
Socket.txTCP(id, qstr, strsize(qstr))
comm
return true
PRI SendLedResposneE(id) | headerLen, qstr
'' Get the query string value
qstr := Request.Get(id, string("led"))
'' Exit if there is no querystring
if(qstr == 0)
return false
'' Turn the LED on if the led= value is "on"
if (strcomp(string("on"), qstr ))
LedStatus5(1)
Buffer[5] := 1
if (strcomp(string("off"), qstr ))
LedStatus5(0)
Buffer[5] := 0
if (strcomp(string("what"), qstr ))
if(pin[5])==1
qstr := string("on")
else
qstr := string("off")
'' Build and send the header
'' Send the value of led= on or off
headerLen := Response.BuildHeader(Request.GetExtension(id), 200, globalCache)
Socket.txTCP(id, @txdata, headerLen)
Socket.txTCP(id, qstr, strsize(qstr))
comm
return true
PRI SendLedResposneF(id) | headerLen, qstr
'' Get the query string value
qstr := Request.Get(id, string("led"))
'' Exit if there is no querystring
if(qstr == 0)
return false
'' Turn the LED on if the led= value is "on"
if (strcomp(string("on"), qstr ))
LedStatus6(1)
Buffer[6] := 1
if (strcomp(string("off"), qstr ))
LedStatus6(0)
Buffer[6] := 0
if (strcomp(string("what"), qstr ))
if(pin[6])==1
qstr := string("on")
else
qstr := string("off")
'' Build and send the header
'' Send the value of led= on or off
headerLen := Response.BuildHeader(Request.GetExtension(id), 200, globalCache)
Socket.txTCP(id, @txdata, headerLen)
Socket.txTCP(id, qstr, strsize(qstr))
comm
return true
PRI SendLedResposneG(id) | headerLen, qstr
'' Get the query string value
qstr := Request.Get(id, string("led"))
'' Exit if there is no querystring
if(qstr == 0)
return false
'' Turn the LED on if the led= value is "on"
if (strcomp(string("on"), qstr ))
LedStatus7(1)
Buffer[7] := 1
if (strcomp(string("off"), qstr ))
LedStatus7(0)
Buffer[7] := 0
if (strcomp(string("what"), qstr ))
if(pin[7])==1
qstr := string("on")
else
qstr := string("off")
'' Build and send the header
'' Send the value of led= on or off
headerLen := Response.BuildHeader(Request.GetExtension(id), 200, globalCache)
Socket.txTCP(id, @txdata, headerLen)
Socket.txTCP(id, qstr, strsize(qstr))
comm
return true
PRI SendLedResposneH(id) | headerLen, qstr
'' Get the query string value
qstr := Request.Get(id, string("led"))
'' Exit if there is no querystring
if(qstr == 0)
return false
'' Turn the LED on if the led= value is "on"
if (strcomp(string("on"), qstr ))
LedStatus8(1)
Buffer[8] := 1
if (strcomp(string("off"), qstr ))
LedStatus8(0)
Buffer[8] := 0
if (strcomp(string("what"), qstr ))
if(pin[8])==1
qstr := string("on")
else
qstr := string("off")
'' Build and send the header
'' Send the value of led= on or off
headerLen := Response.BuildHeader(Request.GetExtension(id), 200, globalCache)
Socket.txTCP(id, @txdata, headerLen)
Socket.txTCP(id, qstr, strsize(qstr))
comm
return true
PRI SendLedResposneI(id) | headerLen, qstr
'' Get the query string value
qstr := Request.Get(id, string("led"))
'' Exit if there is no querystring
if(qstr == 0)
return false
'' Turn the LED on if the led= value is "on"
if (strcomp(string("on"), qstr ))
LedStatus9(1)
Buffer[9] := 1
if (strcomp(string("off"), qstr ))
LedStatus9(0)
Buffer[9] := 0
if (strcomp(string("what"), qstr ))
if(pin[9])==1
qstr := string("on")
else
qstr := string("off")
'' Build and send the header
'' Send the value of led= on or off
headerLen := Response.BuildHeader(Request.GetExtension(id), 200, globalCache)
Socket.txTCP(id, @txdata, headerLen)
Socket.txTCP(id, qstr, strsize(qstr))
comm
return true
PRI Dispatcher(id)
''Do some processing before sending the response
comm
Request.Get(id, string("led"))
comm
if(strcomp(Request.GetFileName(id), string("aled.htm")) AND Request.GetDepth(id) == 1)
if(SendLedResposne(id))
comm
return
comm
Request.Get(id, string("led"))
if(strcomp(Request.GetFileName(id), string("aleda.htm")) AND Request.GetDepth(id) == 1)
if(SendLedResposneA(id))
return
Request.Get(id, string("led"))
if(strcomp(Request.GetFileName(id), string("aledb.htm")) AND Request.GetDepth(id) == 1)
if(SendLedResposneB(id))
return
Request.Get(id, string("led"))
if(strcomp(Request.GetFileName(id), string("aledc.htm")) AND Request.GetDepth(id) == 1)
if(SendLedResposneC(id))
return
Request.Get(id, string("led"))
if(strcomp(Request.GetFileName(id), string("aledd.htm")) AND Request.GetDepth(id) == 1)
if(SendLedResposneD(id))
return
Request.Get(id, string("led"))
if(strcomp(Request.GetFileName(id), string("alede.htm")) AND Request.GetDepth(id) == 1)
if(SendLedResposneE(id))
return
Request.Get(id, string("led"))
if(strcomp(Request.GetFileName(id), string("aledf.htm")) AND Request.GetDepth(id) == 1)
if(SendLedResposneF(id))
return
Request.Get(id, string("led"))
if(strcomp(Request.GetFileName(id), string("aledg.htm")) AND Request.GetDepth(id) == 1)
if(SendLedResposneG(id))
return
Request.Get(id, string("led"))
if(strcomp(Request.GetFileName(id), string("aledh.htm")) AND Request.GetDepth(id) == 1)
if(SendLedResposneH(id))
return
Request.Get(id, string("led"))
if(strcomp(Request.GetFileName(id), string("aledi.htm")) AND Request.GetDepth(id) == 1)
if(SendLedResposneI(id))
return
StaticFileHandler(id)
comm
return
PRI LedStatus(state)
pin[0] := state
return
PRI LedStatus1(stateA)
pin[1] := stateA
return
PRI LedStatus2(stateB)
pin[2] := stateB
return
PRI LedStatus3(stateC)
pin[3] := stateC
return
PRI LedStatus4(stateD)
pin[4] := stateD
return
PRI LedStatus5(stateE)
pin[5] := stateE
return
PRI LedStatus6(stateF)
pin[6] := stateF
return
PRI LedStatus7(stateG)
pin[7] := stateG
return
PRI LedStatus8(stateH)
pin[8] := stateH
return
PRI LedStatus9(stateI)
pin[9] := stateI
return
PRI GotoMain
Main
PRI StaticFileHandler(id) | fileSize, i, headerLen, temp, j
''Serve up static files from the SDCard
'pst.str(string(13,"Static File Handler",13))
SDCard.changeDirectory(@approot)
pst.char(13)
'Make sure the directory exists
ifnot(ChangeDirectory(id))
'send 404 error
WriteError(id)
SDCard.changeDirectory(@approot)
return
' Make sure the file exists
ifnot(FileExists(Request.GetFileName(id)))
'send 404 error
WriteError(id)
SDCard.changeDirectory(@approot)
return
' Open the file for reading
SDCard.openFile(Request.GetFileName(id), "r")
fileSize := SDCard.getFileSize
'WriteResponseHeader(id)
'BuildHeader(extension, statusCode, expirer)
headerLen := Response.BuildHeader(Request.GetExtension(id), 200, globalCache)
Socket.txTCP(id, @txdata, headerLen)
if fileSize < MAX_PACKET_SIZE
' send the file in one packet
SDCard.readFromFile(@txdata, fileSize)
Socket.txTCP(id, @txdata, fileSize)
else
' send the file in a bunch of packets
repeat
SDCard.readFromFile(@txdata, MAX_PACKET_SIZE)
Socket.txTCP(id, @txdata, MAX_PACKET_SIZE)
fileSize -= MAX_PACKET_SIZE
' once the remaining fileSize is less then the max packet size, just send that remaining bit and quit the loop
if fileSize < MAX_PACKET_SIZE and fileSize > 0
SDCard.readFromFile(@txdata, fileSize)
Socket.txTCP(id, @txdata, fileSize)
quit
' Bailout
if(i++ > 1_000_000)
WriteError(id)
quit
SDCard.closeFile
SDCard.changeDirectory(@approot)
return
PRI WriteError(id) | headerOffset
'' Simple 404 error
pst.str(string(13, "Write 404 Error",13 ))
headerOffset := Response.BuildHeader(Request.GetExtension(id), 404, false)
Socket.txTCP(id, @txdata, headerOffset)
return
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'' directory and file handlers
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
PRI ChangeDirectory(id) | i, found
'Handle directory structure for this Request
if(Request.GetDepth(id) > 1)
repeat i from 0 to Request.GetDepth(id)-2
'Return if the directory is not found
ifnot(FileExists(Request.GetPathNode(id, i)))
return false
found := SDCard.changeDirectory(Request.GetPathNode(id, i))
return true
PRI FileExists(fileToCompare) | filenamePtr
'Start file find at the top of the list
SDCard.startFindFile
'Verify that the file exists
repeat while filenamePtr <> 0
filenamePtr := SDCard.nextFile
if(str.MatchPattern(filenamePtr, fileToCompare, 0, false ) == 0 )
return true
return false
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'' Time Methods and Formats
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
PRI GetTime(id) | ptr, headerOffset
ptr := @udpdata
FillHttpDate
bytemove(ptr, string("<p>"),3)
ptr += 3
bytemove(ptr, @httpDate, strsize(@httpDate))
ptr += strsize(@httpDate)
bytemove(ptr, string("</p>"),4)
ptr += 3
headerOffset := Response.BuildHeader(Request.GetExtension(id), 200, false)
Socket.txTCP(id, @txdata, headerOffset)
StringSend(id, @udpdata)
bytefill(@udpdata, 0, TEMP_BUFFER)
return
PRI FillTime | ptr, num
'ToString(integerToConvert, destinationPointer)
'00/00/0000 00:00:00
ptr := @time
rtc.readTime
FillTimeHelper(rtc.clockMonth, ptr)
ptr += 3
FillTimeHelper(rtc.clockDate, ptr)
ptr += 3
FillTimeHelper(rtc.clockYear, ptr)
ptr += 5
FillTimeHelper(rtc.clockHour , ptr)
ptr += 3
FillTimeHelper(rtc.clockMinute , ptr)
ptr += 3
FillTimeHelper(rtc.clockSecond, ptr)
return @time
PRI FillHttpDate | ptr, num, temp
'ToString(integerToConvert, destinationPointer)
'Wed, 01 Feb 2000 01:00:00 GMT
ptr := @httpDate
rtc.readTime
temp := rtc.getDayString
bytemove(ptr, temp, strsize(temp))
ptr += strsize(temp) + 2
FillTimeHelper(rtc.clockDate, ptr)
ptr += 3
temp := rtc.getMonthString
bytemove(ptr, temp, strsize(temp))
ptr += strsize(temp) + 1
FillTimeHelper(rtc.clockYear, ptr)
ptr += 5
FillTimeHelper(rtc.clockHour , ptr)
ptr += 3
FillTimeHelper(rtc.clockMinute , ptr)
ptr += 3
FillTimeHelper(rtc.clockSecond, ptr)
return @httpDate
PRI FillTimeHelper(number, ptr) | offset
offset := 0
if(number < 10)
offset := 1
str.ToString(@number, @tempNum)
bytemove(ptr+offset, @tempNum, strsize(@tempNum))
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'' SDCard Logger
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
PRI AppendLog(logToAppend)
'' logToAppend: Pointer to a string of test we'd like to log
SDCard.changeDirectory(@approot)
if(FileExists(@logfile))
SDCard.openFile(@logfile, "A")
else
SDCard.newFile(@logfile)
SDCard.writeData(string(13,10,"----- Start "),14)
SDCard.writeData(FillTime, 19)
SDCard.writeData(string(" -----"),6)
SDCard.writeData(@crlf_crlf, 2)
SDCard.writeData(logToAppend, strsize(logToAppend))
SDCard.writeData(@crlf_crlf, 2)
SDCard.writeData(string("----- End "),10)
SDCard.writeData(FillTime, 19)
SDCard.writeData(string(" -----"),6)
SDCard.writeData(@crlf_crlf, 2)
SDCard.closeFile
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'' Memory Management
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
PRI Set(DestAddress, SrcAddress, Count)
bytemove(DestAddress, SrcAddress, Count)
bytefill(DestAddress+Count, $0, 1)
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'' Socekt helpers
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
PRI GetTcpSocketMask(id)
return id & tcpMask
PRI DecodeId(value) | tmp
if(01 & value)
return 0
if(10 & value)
return 1
if(00 & value)
return 2
if(00 & value)
return 3
return -1
PRI QueueSocket(id) | tmp
if(fifoSocketDepth > 4)
return false
tmp := |< id
'Unique check
ifnot(IsUnique(tmp))
return false
tmp <<= (fifoSocketDepth++) * 8
fifoSocket |= tmp
return true
PRI IsUnique(encodedId) | tmp
tmp := encodedId & $0F
repeat 4
if(encodedId & fifoSocket)
return false
encodedId <<= 8
return true
PRI DequeueSocket | tmp
if(fifoSocketDepth == 0)
return -2
repeat until not lockset(debugSemId)
tmp := fifoSocket & $0F
fifoSocket >>= 8
fifoSocketDepth--
lockclr(debugSemId)
return DecodeId(tmp)
PRI ResetSocket(id)
Socket.Disconnect(id)
Socket.Close(id)
PRI IsolateTcpSocketById(id) | tmp
tmp := |< id
tcpMask &= tmp
PRI SetTcpSocketMaskById(id, state) | tmp
'' The tcpMask contains the socket the the StatusMonitor monitors
tmp := |< id
if(state == 1)
tcpMask |= tmp
else
tmp := !tmp
tcpMask &= tmp
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'' W5100 Helper methods
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
PRI GetCommandRegisterAddress(id)
return Socket#_S0_CR + (id * $0100)
PRI GetStatusRegisterAddress(id)
return Socket#_S0_SR + (id * $0100)
PRI SetMac(_firstOctet)
Socket.WriteMACaddress(true, _firstOctet)
return
PRI SetGateway(_firstOctet)
Socket.WriteGatewayAddress(true, _firstOctet)
return
PRI SetSubnet(_firstOctet)
Socket.WriteSubnetMask(true, _firstOctet)
return
PRI SetIP(_firstOctet)
Socket.WriteIPAddress(true, _firstOctet)
return
PRI StringSend(id, _dataPtr)
Socket.txTCP(id, _dataPtr, strsize(_dataPtr))
return
PRI SendChar(id, _dataPtr)
Socket.txTCP(id, _dataPtr, 1)
return
PRI SendChars(id, _dataPtr, _length)
Socket.txTCP(id, _dataPtr, _length)
return
PRI InitializeSocket(id)
Socket.Initialize(id, TCP_PROTOCOL, port, remotePort, @remoteIp)
return
PRI InitializeSocketForEmail(id)
Socket.Initialize(id, TCP_PROTOCOL, port, emailPort, @emailIp)
return
PRI InitializeUPDSocket(id)
Socket.Initialize(id, UDP_PROTOCOL, uport, remotePort, @remoteIp)
return
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'' Debug/Display Methods
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
PRI QueueDump
'' Display socket IDs in the queue
'' ie 00000401 -> socket Zero is next to pop off
pst.str(string("FIFO["))
pst.dec(fifoSocketDepth)
pst.str(string("] "))
pst.hex(fifoSocket, 8)
PRI StackDump | clsd, open, lstn, estb, clwt, clng, id, ulst
'' This method is purely for debugging
'' It displays the status of all socket registers
repeat until not lockset(debugSemId)
clsd := closedState
open := openState
lstn := listenState
estb := establishedState
clwt := closeWaitState
clng := closingState
ulst := udpListen
lockclr(debugSemId)
pst.char(13)
repeat id from 3 to 0
pst.dec(id)
pst.str(string("-"))
pst.hex(status[id], 2)
pst.str(string(" "))
pause(1)
pst.str(string(13,"clsd open lstn estb clwt clng udps", 13))
pst.bin(clsd, 4)
pst.str(string("-"))
pst.bin(open, 4)
pst.str(string("-"))
pst.bin(lstn, 4)
pst.str(string("-"))
pst.bin(estb, 4)
pst.str(string("-"))
pst.bin(clwt, 4)
pst.str(string("-"))
pst.bin(clng, 4)
pst.str(string("-"))
pst.bin(ulst, 4)
pst.char(13)
PRI HeaderLine1(id) | i
pst.str(Request.GetMethod(id))
pst.char($20)
i := 0
repeat Request.GetDepth(id)
pst.char($2F)
pst.str(Request.GetPathNode(id, i++))
PRI Pause(Duration)
waitcnt(((clkfreq / 1_000 * Duration - 3932) #> 381) + cnt)
return
PRI StatusMonitor | id, tmp, value
'' StatusMonitor is the heartbeat of the project
'' Here we monitor the state of the Wiznet 5100's 4 sockets
repeat
Socket.GetStatus32(@status[0])
' Encode status register states
repeat until not lockset(debugSemId)
closedState := openState := listenState := establishedState := {
} closeWaitState := closingState := 0
repeat id from 0 to 3
case(status[id])
$00: closedState |= |< id
closedState &= tcpMask
$13: openState |= |< id
openState &= tcpMask
$14: listenState |= |< id
listenState &= tcpMask
$17: establishedState |= |< id
establishedState &= tcpMask
$18,$1A,$1B: closingState |= |< id
closingState &= tcpMask
$1C: closeWaitState |= |< id
closeWaitState &= tcpMask
$1D: closingState |= |< id
closingState &= tcpMask
$22: udpListen |= |< id
udpListen &= udpMask
if(lastEstblState <> establishedState)
value := establishedState
repeat while value > 0
tmp := DecodeId(value)
if(tmp > -1)
QueueSocket(tmp)
tmp := |< tmp
tmp := !tmp
value &= tmp
lastEstblState := establishedState
lockclr(debugSemId)
' Initialize a closed socket
if(closedState > 0)
id := DecodeId(closedState)
if(id > -1)
InitializeSocket(id & tcpMask)
'Start a listener on an initialized/open socket
if(openState > 0)
id := DecodeId(openState)
if(id > -1)
Socket.Listen(id & tcpMask)
' Close the socket if the status is close/wait
' response processor should close the socket with disconnect
' there could be a timeout so we have a forced close.
' TODO: CCheck for a port that gets stuck in a closing state
'if(closeWaitState > 0)
'id := DecodeId(closeWaitState)
'if(id > -1)
'Socket.Close(id & tcpMask)
'pause(100)
return
DAT
approot byte "\", 0
defaultpage byte "index.htm", 0
logfile byte "log.txt", 0
'binFile byte "filename.bin", 0
FS byte "/", 0
fn byte "filename=", 0
doublequote byte $22, 0
crlf byte 13, 10, 0
crlf_crlf byte 13, 10, 13, 10, 0
uploadfile byte $0[12], 0
uploadfolder byte "uploads", 0
tempNum byte "0000",0
multipart byte "Content-Type: multipart/form-data; boundary=",0
boundary byte $2D, $2D
boundary1 byte $0[64]
'loadme file "TogglePin0.binary"

Comments
1 : bytemove(@Buffer1,@IR_ON,strsize(@IR_ON)) outa[16]~~ 129 : bytemove(@Buffer1,@IR_OFF,strsize(@IR_OFF)) outa[16]~To :
1 : bytemove(@Buffer1,@IR_ON,strsize(@IR_ON)) outa[16]~~ 129 : bytemove(@Buffer1,@IR_OFF,strsize(@IR_OFF)) DIRA[16]~~will fix your problem
Ok I will give it a try ! Thank you. :-)
Short answer: Yes, it is possible.
I don't know it it's possible with the code you're using.
It looks like one of your Props uses Beau's Prop to Prop code while the other uses Mike G's Spinnerete code.
I wouldn't think the two would communicate with each other.
I don't see Beau's objects used in the second Prop's code anywhere (there's a lot going on in the server code so I may have missed it).
Edit: I did miss seeing Beau's code. Sorry. That's a lot a code to wade through. It might help to write some simple Prop to Prop test code without all the internet stuff.
Yes, it is not only possible, but they do it in residential electrical construction all the time. I don't have the switching combinations down as in poles and throws, but here is how it is done with very common three-way and four way switches, with 120V single phase wiring. The same principle can be adapted by using switches with the appropriate poles and throws.
Bruce
EDIT: What is your current wiring schematic for the light and pushbuttons?
EDIT: In fact, with this type of configuration, the number of switching locations is pratically endless. Just keep adding four-way switches in between the two three-way switches.
Bruce,
I suppose we can let Podion correct us, but my interpretation of the problem was to have push buttons connected to two different Props. Each Prop would have an "on" and a "off" button. My guess is, these "on" and "off" buttons should control a LED on only one of the Props.
By using microcontrollers, the wiring can be kept very simple since the uC can take care of the logic.
Whatever the case, I believe the logic would be equal to the switch states of the circuitry shown. And I believe that if it was controlled logically, as in 1s and 0s, I believe it could be done with four single pole pushbuttons.
Something such as the functions: AddThreeWayPB(PIN), AddFourWay(PIN)
If the logic was correct, a person could control a light circuit from numerous locations.
EDIT: More like this
EDIT: However, if spare pins are available, the same circuitry could be replicated with the spare pins
EDIT: Or simply tie the light to a pin, monitor the state as on or off, and if one of the pushbuttons is pressed, simply change the state of the light pin.
There is a code that I simplify. The principle is the same, 2 prop work in serial to control 1 light via 2 ON button and 2 OFF. Each prop have is own ON/OFF button. In reality those button are a IR remote. remote code 1 = On 2=Off / 3=On 4=Off.
The 3 way don't work for this. the logic of the tree way : Off+Off=Off, On+Off=On, On+On=Off, Off+On=On and this is not what i want.
{{*************************************** * HighSpeed Server DEMO v1.0 * * Author: Beau Schwabe * * Copyright (c) 2011 Parallax, Inc. * * See end of file for terms of use. * *************************************** Revision History: Version 1.0 - (09/20/2011) initial release }} CON ' Set up the processor clock in the standard way for 80MHz on DemoBoard _CLKMODE = xtal1 + pll16x _XINFREQ = 5_000_000 + 0000 RX_Pin = 27 TX_Pin = 26 Command = 00 '' Feature not used in this demo Offset = 0 '' Feature not used in this demo '-------------------------------------------------------- _irrpin = 24 'ir receiver module on this pin _device = 0 'accept any device code _dlyrpt = 6 'delay before acception code as repeat {{ Round Robin configuration using 2 Propellers: ┌────────────────────────────//────────────────────────────┐ │ ┌─────────────────┐ ┌─────────────────┐ │ │ │ Propeller 1 │ │ Propeller 2 │ │ ┣─┤RX TX├──┳───//───┳─┤RX TX├──┫  │ Client │   │ Server │   └─────────────────┘   └─────────────────┘  Vss Vss Vss Vss Round Robin configuration using 3 or more Propellers: ┌────────────────────────────/.../────────────────────────────────/.../────────────────────────────┐ │ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ │ │ Propeller 2 │ │ Propeller N │ │ Propeller 1 │ │ ┣─┤RX TX├──┳───/.../───┳─┤RX TX├──┳───/.../───┳─┤RX TX├──┫  │ Client │   │ Client │   │ Server │   └─────────────────┘   └─────────────────┘   └─────────────────┘  Vss Vss Vss Vss Vss Vss Note: All resistors tied to Vss are 330 Ohm and are there to establish a transmission line Note: All resistors between TX and RX are 100 Ohm and are there to current limit the I/O's in the chance of a collision. With round robin, the idea is that you have one buffer that propagated around and around inside the round robin loop. To avoid any data collisions, all Propellers are capable of reading any location within the buffer, however each Propeller has a specific (assigned by the programmer) location that it can write to. So in the Demo, there is a 1K long buffer (4K bytes). As an example Propeller 1 may only write to locations 0 to 255. While Propeller 2 can write to locations 256 to 511. Propellers 3 & 4 depicted as N because of the expandable nature of round robin would write to the remaining 512 to 1023 locations. }} VAR long Buffer[10] long Buffer1[10] long keycode long cogStack[500] long stack[20] OBJ hsRX : "HSp2pRX" 'High Speed Receive driver hsTX : "HSp2pTX" 'High Speed Transmit driver rcvir : "ir_reader_sony" SN : "Simple_Numbers" PUB Main Start_IR PUB Start_IR rcvir.init(_irrpin,_device,_dlyrpt,true) 'startup Start_IR1 PUB Start_IR1 'start the tv terminal dira[23]~~ repeat start start1 keycode := rcvir.fifo_get 'try a get from fifo if keycode == -1 'empty try again next else keycode := keycode + 1 PUB start case keycode 1 : bytemove(@Buffer,@NB1,strsize(@NB1))' <- Moves TestMessage into Buffer 2 : bytemove(@Buffer,@NB2,strsize(@NB2)) 3 : bytemove(@Buffer,@NB3,strsize(@NB3)) 4 : bytemove(@Buffer,@NB4,strsize(@NB4)) 5 : bytemove(@Buffer,@NB5,strsize(@NB5)) 6 : bytemove(@Buffer,@NB6,strsize(@NB6)) 7 : bytemove(@Buffer,@NB7,strsize(@NB7)) 8 : bytemove(@Buffer,@NB8,strsize(@NB8)) 9 : bytemove(@Buffer,@NB9,strsize(@NB9)) 22 : bytemove(@Buffer,@NB22,strsize(@NB22)) other : bytemove(@Buffer,@NB0,strsize(@NB0)) pub start1 comm PUB comm repeat 1 hsTX.TX(TX_Pin,10,@Buffer,Command,Offset) '<- Transmit Data to External Propeller hsRX.RX(RX_Pin,@Buffer) '<- Receive Data from External Propeller hsRX.RX(RX_Pin,@Buffer1) hsTX.TX(TX_Pin,10,@Buffer1,Command,Offset) '<- Transmit Data to External Propeller return Dat NB0 BYTE 999,0 NB1 BYTE 1,0 NB2 BYTE 2,0 NB3 BYTE 3,0 NB4 BYTE 4,0 NB5 BYTE 5,0 NB6 BYTE 6,0 NB7 BYTE 7,0 NB8 BYTE 8,0 NB9 BYTE 9,0 NB22 BYTE 22,0 CON{{ *************************************** * HighSpeed Client DEMO v1.0a * * Author: Beau Schwabe * * Copyright (c) 2011 Parallax, Inc. * * See end of file for terms of use. * *************************************** Revision History: Version 1.0 - (09/20/2011) initial release Version 1.0a - (09/26/2011) minor change to detect When the USB plug is connected to the PC. This prevents unwanted resets. }} CON ' Set up the processor clock in the standard way for 80MHz on DemoBoard _CLKMODE = xtal1 + pll16x _XINFREQ = 5_000_000 + 0000 RX_Pin = 27 TX_Pin = 26 Command = 00 '' Feature not used in this demo Offset = 0 '' Feature not used in this demo USB_Rx = 31 USB_Tx = 30 RANGE = 23 'Range is 0 to RANGE. SAMPLES = 2 'Number of samples to pick: 1 to RANGE + 1 temps = 1 _irrpin = 0 'ir receiver module on this pin _device = 0 'accept any device code _dlyrpt = 6 'delay before acception code as repea {{ Round Robin configuration using 2 Propellers: ┌────────────────────────────//────────────────────────────┐ │ ┌─────────────────┐ ┌─────────────────┐ │ │ │ Propeller 1 │ │ Propeller 2 │ │ ┣─┤RX TX├──┳───//───┳─┤RX TX├──┫  │ Client │   │ Server │   └─────────────────┘   └─────────────────┘  Vss Vss Vss Vss Round Robin configuration using 3 or more Propellers: ┌────────────────────────────/.../────────────────────────────────/.../────────────────────────────┐ │ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ │ │ Propeller 2 │ │ Propeller N │ │ Propeller 1 │ │ ┣─┤RX TX├──┳───/.../───┳─┤RX TX├──┳───/.../───┳─┤RX TX├──┫  │ Client │   │ Client │   │ Server │   └─────────────────┘   └─────────────────┘   └─────────────────┘  Vss Vss Vss Vss Vss Vss Note: All resistors tied to Vss are 330 Ohm and are there to establish a transmission line Note: All resistors between TX and RX are 100 Ohm and are there to current limit the I/O's in the chance of a collision. With round robin, the idea is that you have one buffer that propagated around and around inside the round robin loop. To avoid any data collisions, all Propellers are capable of reading any location within the buffer, however each Propeller has a specific (assigned by the programmer) location that it can write to. So in the Demo, there is a 1K long buffer (4K bytes). As an example Propeller 1 may only write to locations 0 to 255. While Propeller 2 can write to locations 256 to 511. Propellers 3 & 4 depicted as N because of the expandable nature of round robin would write to the remaining 512 to 1023 locations. }} VAR long Buffer[10] long Buffer1[10] long Stack[400] long Stack1[400] byte numbers[RANGE + 1] long seed long keycode OBJ hsRX : "HSp2pRX" 'High Speed Receive driver hsTX : "HSp2pTX" 'High Speed Transmit driver PST : "Parallax Serial Terminal" 'RS232 Serial Driver rcvir : "ir_reader_sony" SN : "Simple_Numbers" PUB Main rcvir.init(_irrpin,_device,_dlyrpt,true) 'startup Start_IR1 PUB start|debugLED '------------------------------------------------------------------------------------------- '<- I/O direction for debug LEDs '------------------------------------------------------------------------------------------- repeat hsRX.RX(RX_Pin,@Buffer) '<- Receive Data from External Propeller hsTX.TX(TX_Pin,10,@Buffer,Command,Offset) '<- Transmit Data to External Propeller hsTX.TX(TX_Pin,10,@Buffer1,Command,Offset) '<- Transmit Data to External Propeller hsRX.RX(RX_Pin,@Buffer1) Menu_Principal '------------------------------------------------------------------------------------------- '------------------------------------------------------------------------------------------- PUB Start_IR1 dira [16]~~ repeat keycode := rcvir.fifo_get 'try a get from fifo if keycode == -1 'empty try again next else keycode := keycode + 1 case keycode 3: outa[16] := 1 4: outa[16] := 0 return PUB Menu_Principal dira [16]~~ case Buffer 1: outa[16] := 1 2: outa[16] := 0 Dat NB2 BYTE 1,0Client_DEMO.spinHSp2pRX.spinHSp2pTX.spinir_reader_sony.spinMain.spinServer_DEMO.spinSimple_Numbers.spin
One thing I see in the Client portion of your code is that you are never calling the PUB start|debugLED routine.... where you have the High speed RX and TX routines. Also, you should be able to do this using only one buffer instead of two. That would eliminate some redundancy with transmitting and receiving.
When attaching files, can you use the File-->Archive-->Project and then attach the resulting file? This makes sure that we have all of the pieces when trying to look at code.
Thanks.
I'll try to setup a demo using some of my original code to show how a 3-way or even a 4-Way switch might work as I explained in an earlier post.
Main.spin
I just went from your latest example... in that, the PUB start|debugLED routine was not referenced. None the less, here is a bit of revised DEMO code from my original code that shows how to implement a switch function across multiple Propellers to control lights, etc.
On each Propeller the 'switch' acts like a one-shot, where it's only acted upon if there is a change in its state. If there is a change in state, that state gets passed along to the other Propellers in the loop. Both Clients and Server have control of a memory address (pre defined in your code) that determines if the lights are on or off. Note: the DEMO uses the 8 leds built into the Propeller Demo board and/or the Propeller QuickStart as well as the Def-Con badges.
Because the switches are setup in one-shot mode, there is a possibility that you may want to turn the lights OFF but the switch at your location is already OFF. In this case you will need to turn the switch ON, and then OFF to take control of the lighting. The opposite is true if you want to turn the lights ON and the switch position at your location is already ON. You must first turn your switch OFF and then back ON. If however your switch matches the current state of the lighting situation, then all you need to do is move your switch to the desired position.
{{*************************************** * HighSpeed Client DEMO v1.0a * * Author: Beau Schwabe * * Copyright (c) 2011 Parallax, Inc. * * See end of file for terms of use. * *************************************** Revision History: Version 1.0 - (09/20/2011) initial release Version 1.0a - (09/26/2011) minor change to detect When the USB plug is connected to the PC. This prevents unwanted resets. }} CON ' Set up the processor clock in the standard way for 80MHz on DemoBoard _CLKMODE = xtal1 + pll16x _XINFREQ = 5_000_000 + 0000 RX_Pin = 27 TX_Pin = 26 Command = %0000 '' Feature not used in this demo Offset = 0 '' Feature not used in this demo USB_Rx = 31 USB_Tx = 30 RANGE = 23 'Range is 0 to RANGE. SAMPLES = 2 'Number of samples to pick: 1 to RANGE + 1 temps = 1 _irrpin = 0 'ir receiver module on this pin _device = 0 'accept any device code _dlyrpt = 6 'delay before acception code as repea {{ Round Robin configuration using 2 Propellers: ┌────────────────────────────//────────────────────────────┐ │ ┌─────────────────┐ ┌─────────────────┐ │ │ │ Propeller 1 │ │ Propeller 2 │ │ ┣─┤RX TX├──┳───//───┳─┤RX TX├──┫  │ Client │   │ Server │   └─────────────────┘   └─────────────────┘  Vss Vss Vss Vss Round Robin configuration using 3 or more Propellers: ┌────────────────────────────/.../────────────────────────────────/.../────────────────────────────┐ │ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ │ │ Propeller 2 │ │ Propeller N │ │ Propeller 1 │ │ ┣─┤RX TX├──┳───/.../───┳─┤RX TX├──┳───/.../───┳─┤RX TX├──┫  │ Client │   │ Client │   │ Server │   └─────────────────┘   └─────────────────┘   └─────────────────┘  Vss Vss Vss Vss Vss Vss Note: All resistors tied to Vss are 330 Ohm and are there to establish a transmission line Note: All resistors between TX and RX are 100 Ohm and are there to current limit the I/O's in the chance of a collision. With round robin, the idea is that you have one buffer that propagated around and around inside the round robin loop. To avoid any data collisions, all Propellers are capable of reading any location within the buffer, however each Propeller has a specific (assigned by the programmer) location that it can write to. So in the Demo, there is a 1K long buffer (4K bytes). As an example Propeller 1 may only write to locations 0 to 255. While Propeller 2 can write to locations 256 to 511. Propellers 3 & 4 depicted as N because of the expandable nature of round robin would write to the remaining 512 to 1023 locations. }} VAR long Buffer[10] long Buffer1[10] long Stack[400] long Stack1[400] byte numbers[RANGE + 1] long seed long keycode OBJ hsRX : "HSp2pRX" 'High Speed Receive driver hsTX : "HSp2pTX" 'High Speed Transmit driver PST : "Parallax Serial Terminal" 'RS232 Serial Driver rcvir : "ir_reader_sony" SN : "Simple_Numbers" PUB Main rcvir.init(_irrpin,_device,_dlyrpt,true) 'startup Start_IR1 PUB start|debugLED repeat hsRX.RX(RX_Pin,@Buffer) '<- Receive Data from External Propeller hsTX.TX(TX_Pin,10,@Buffer,Command,Offset) '<- Transmit Data to External Propeller hsTX.TX(TX_Pin,10,@Buffer1,Command,Offset) '<- Transmit Data to External Propeller hsRX.RX(RX_Pin,@Buffer1) Menu_Principal PUB Start_IR1 dira [16]~~ repeat keycode := rcvir.fifo_get 'try a get from fifo if keycode == -1 'empty try again next else keycode := keycode + 1 [COLOR=#ff0000] case keycode[/COLOR] [COLOR=#ff0000] 3: outa[16] := 1 'LED ON Control by client [/COLOR] [COLOR=#ff0000] 4: outa[16] := 0 'LED OFF Control by client [/COLOR] return PUB Menu_Principal dira [16]~~ case Buffer [COLOR=#ff0000] 1: outa[16] := 1 'LED ON Control by server[/COLOR] [COLOR=#ff0000] 2: outa[16] := 0 'LED OFF Control by server[/COLOR]