Replicating latching switches using XOR


Well-known member
I have been musing for a few weeks on the question of how to create, with a series of momentary tactile switches, the effect of latching switches, so that one press turns the LED (or whatever) on, and the next turns it off. I couldn't find anything on the forum, but a bit of poring over truth tables, and a lot of trial and error with the simulator and SerTXD to see what's happening, has produced a result. I have a couple of DIL switches that would do the job, but they are a bit too small and stiff to operate easily. It may be that I've missed a more obvious solution, and I'm sure there are better solutions, but in case this is useful for anyone else, here is the code. It uses the XOR function (truth table and description in the code below). I've tested it on the simulator. It's actually intended to allow remote switching of headlights and other accessories on my vehicle project, so the resulting instruction is intended to send as a single byte via IR, which is why it's added to the value 104 (0 to 103 being used for motor control), but it can be adapted for other contexts. I've added the code to the vehicle project and have successfully transmitted and received the headlight instruction and another LED instruction via IR. Because I'm starting with value 104 and can only go up to 127 with the IR code, I can only transmit 4 instructions (15 in decimal). Next step is to convert the motor code transmitter from IROUT to Serial via IR as I have done for the TOF10120 scanner: at which point it will be able to handle up to value 255, allowing more switch instructions. If you're not constrained by the IROUT limit, you can immediately transmit a larger number of switch instructions.

Rich (BB code):
;Short test cycle to demonstrate latching switches with XOR function

#Picaxe 28x2
#terminal 9600


      ;PINs from 1 Anticlockwise
      ;down one side
      ;RST no SYMBOL pin 1
      ;SYMBOL = A.0 ; pin 2 not used
      ;SYMBOL = A.1 ; pin 3 not used;
      SYMBOL RedLED = A.2 ;pin 4 used
      SYMBOL GreenLED = A.3 ;pin 5 used
      ;RXD no SYMBOL pin 6 used
      ;Serial Out no SYMBOL pin 7 used
      ;0V no SYMBOL pin 8 used
      ;RES no SYMBOL pin 9 not used
      ;RES no SYMBOL pin 10 not used
      ;SYMBOL = C.0 pin 11 used for input switch
      ;SYMBOL = C.1 ;pin 12 used for input switch
      ;SYMBOL = C.2 ;pin 13 not used
      ;READADC 4 C.3 pin 14 not used
      ;and back up the other side
      ;SYMBOL = C.4 pin 15 not used
      ;SYMBOL = C.5 ;pin 16
      ;SYMBOL = C.6 ;pin 17
      ;SYMBOL = C.7 pin 18
      ;0V no SYMBOL pin 19
      ;V+ no SYMBOL pin 20
      ;SYMBOL = B.0 ; pin 21 - pins B.0 to B.7 used for on/off
      ;SYMBOL = B.1 ; pin 22
      ;SYMBOL = B.2 pin 23
      ;SYMBOL = B.3 pin 24
      ;SYMBOL = B.4 ; pin 25
      ;SYMBOL = B.5 ; pin 26
      ;SYMBOL = B.6 pin 27
      ;SYMBOL = B.7 pin 28
      ;byte/word variables
      ;Note: 28X2 has up to 56 bytes/27 words plus 200 storage variables plus 1024 bytes scratchpad
For b4 = 1 to 3
      High GreenLED
      pause 50
      Low GreenLED
      High RedLED
      pause 50
      Low RedLED
Next b4
      SYMBOL NewSwitches = b5
      SYMBOL SwitchChanges = b6
      SYMBOL SendIt = b7
      SYMBOL Outputs = b0
      let dirsB = %11111111; sets B pins as outputs
      Let SwitchChanges = 0 & %00000000 ; sets value to 0 before we start; the "&%00000000" sets it as a binary value, I hope;
      SerTXD ("SwitchChanges = ", #SwitchChanges, CR, LF)

      let NewSwitches = pinsC & %00000011 ; tactile switches on C.0 and C.1.  "NewSwitches" gets switch settings. 
      ;&00000011 masks inputs 0 and 1:

      ;     C.0   C.1
      ;0 =  off   off
      ;1 =  on    off
      ;2 =  off   on
      ;3 =  on    on

      SerTXD ("NewSwitches = ", #NewSwitches, CR, LF)

      let SwitchChanges = SwitchChanges XOR NewSwitches ; this establishes whether there has been a change in the switch state between the previous switch state, shown as SwitchChanges, and the new state, shown by NewSwitches

      ;XOR gate truth table:
      ;A    B     Out
      ;0    0     0 ; no change - switch remains off
      ;0    1     1 ; so if the switch was off and is now on, the result is on
      ;1    0     1 ; this is an important one: if the switch was previously on, but is now off, the result is on, so the LED etc stays lit.  This will perpetuate because "Out" (SwitchChanges) becomes A and "NewSwitches" is B, so the result stays on
      ;1    1     0; if switch was on and is now on again, the result is off

      SerTXD ("SwitchChanges = ", #SwitchChanges, CR, LF);

      let SwitchChanges = SwitchChanges & %11111111; this sets the binary value

      SerTXD ("SwitchChanges = ", #SwitchChanges, CR, LF)

      let SendIt = SwitchChanges + 104 ; the SendIt part is only to create a value for transmission by IR in the real life version of this - it can be omitted if all of this is to happen on the same chip

      SerTXD ("SendIt = ", #SendIt, CR, LF)

      Let Outputs = SendIt - 104; this decodes the transmission. In the real version, this is on another Picaxe

      SerTXD ("Outputs = ", #OutPuts, CR, LF)

      Let OutPinB.0 = bit0
      Let OutPinB.1 = bit1

      pause 100