Prop to Prop communication
Podion
Posts: 90
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
To :
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.
Client_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.
[/COLOR]