• Register
    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search

    Charlyplexing or matrix

    General Discussion
    2
    19
    5347
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • W
      Wim Stockman last edited by

      Hello,
      I m building a home automation system and I was wondering if I could use the unipis digital input for charlyplexing or matrix setup. So I could use a lot of push buttons.

      Kind regards
      Wim

      1 Reply Last reply Reply Quote 0
      • T
        tomas_hora administrators last edited by

        Hello @Wim-Stockman,

        charlieplexing is not possible with digital inputs of UniPi. However matrix is OK, you just need the SW that will take care of decoding the states of inputs.

        1 Reply Last reply Reply Quote 0
        • W
          Wim Stockman last edited by

          Hello,

          Thx for the quick reply. I was thinking of using the keypad arduino library as a base for making the matrix scanner. Do you think this might work ?.
          It would be great if I get it do work. Would mean you have suddenly 49 inputs available.
          I think that will be enough for my house :-).

          Kind regards
          Wim Stockman

          T 1 Reply Last reply Reply Quote 0
          • T
            tomas_hora administrators @Wim Stockman last edited by

            @Wim-Stockman Basically yes. What interface to the DIs do you plan to use? Direct GPIOs on the RPi or websocket...?

            W 1 Reply Last reply Reply Quote 0
            • W
              Wim Stockman @tomas_hora last edited by

              @tomas_hora I 'll try direct gpio with the pigpio.I found something on the forum to get started. So I 'll try over the weekend if I get something working :-)

              T 1 Reply Last reply Reply Quote 0
              • T
                tomas_hora administrators @Wim Stockman last edited by

                @Wim-Stockman Good luck! Would be great it you share some results :)

                W 1 Reply Last reply Reply Quote 0
                • W
                  Wim Stockman @tomas_hora last edited by

                  Hi,
                  I run into a stupid problem.
                  trying the example of connecting with python through websocket.
                  I get this error : File "test.py", line 20, in <module>
                  ws = websocket.WebSocketApp(url, on_message = on_message, on_error = on_error, on_close = on_close)
                  AttributeError: 'module' object has no attribute 'WebSocketApp'

                  I don't know what I'm doing wrong , just copy paste the example check the ip adres (just localhost) but I seem stuck.
                  could you help me ?
                  thx

                  W 1 Reply Last reply Reply Quote 0
                  • W
                    Wim Stockman @Wim Stockman last edited by

                    @Wim-Stockman Ok found the solution
                    uninstall websocket: sudo apt-get uninstall python-websocket
                    and install : sudo pip install websocket-client

                    this does the trick for me :-)

                    W 1 Reply Last reply Reply Quote 0
                    • W
                      Wim Stockman @Wim Stockman last edited by

                      It seems the get attribute isn't implemented for the relays
                      and if I do a full request it gets dump on de command line in evok.py instead of sent to the websocketclient.
                      So I could initialise the position of the relays

                      import websocket
                      import json
                      import time
                      import threading
                      
                      url = "ws://127.0.0.1/ws"
                      i = 0
                      relaystatus = [0,0,0,0,0,0,0,0]
                      
                      #initiliaze relay 3 just for demo purpose
                      wsinit = websocket.create_connection("ws://127.0.0.1/ws")
                      time.sleep(2)
                      wsinit.send('{"cmd":"full","dev":"relay","circuit":"3"}')
                      result = json.loads(wsinit.recv())
                      relaystatus[2] = result["value"]
                      print relaystatus
                      wsinit.close()
                      
                      def on_message(ws, message):
                          obj = json.loads(message);
                          dev = obj['dev'];
                          print obj['dev'];
                          circuit = obj['circuit'];
                          value = obj['value'];
                          global i
                          global relaystatus
                          i += 1
                          print i
                          if dev == 'input' and i > 2:
                              print "erin";
                              ws1 = websocket.WebSocket();
                              ws1.connect(url);
                              #sending messages
                              print obj['value'];
                              if relaystatus[2] == 0:
                                      ws1.send('{"cmd":"set","dev":"relay","circuit":"3","value":"1"}')
                                      relaystatus[2] = 1
                              else:
                                      ws1.send('{"cmd":"set","dev":"relay","circuit":"3","value":"0"}')
                                      relaystatus[2] = 0
                      
                              i = 0
                      
                          print message
                      
                      
                      
                      def on_error(ws, error):
                          print error
                      
                      def on_close(ws):
                          print "Connection closed"
                      
                      
                      
                      #receiving messages
                      ws = websocket.WebSocketApp(url, on_message = on_message, on_error = on_error, on_close = on_close)
                      wst = threading.Thread(target=ws.run_forever())
                      wst.daemon = True
                      wst.start()
                      while not  ws.sock.connected:
                              time.sleep(5)
                      
                      

                      This demo work for a push button that's why I have the 2 counter to activate the relay , because rising edge triggers a message as well as the falling edge. But that will come in handy for detecting how long somebody presses de button.

                      Somebody know where I can begin to omplent the Get for the relays.

                      Kind regards,
                      Wim

                      1 Reply Last reply Reply Quote 0
                      • T
                        tomas_hora administrators last edited by tomas_hora

                        @Wim-Stockman Thanks for the report. See this modification of the on_message function:

                                    try:
                                        device = Devices.by_name(dev, circuit)
                                        # result = device.set(value)
                                        func = getattr(device, cmd)
                                        if value is not None:
                                            result = func(value)
                                        else:
                                            result = func()
                                        if is_future(result):
                                            result = yield result
                                        #devents.status(device)
                                        self.write_message(result)
                                        #print json.dumps(result)
                                    except Exception, E:
                                        print E
                         
                        

                        It will send the result of the command to only the client that send the command. But in our test, you are using two clients, so you will not receive the result in the other client. If you want to send the result to all clients connected to the WebSocket, use the devevents.satus(device) insted.

                        Working example of the test client:

                        import websocket
                        import json
                        import time
                        import threading
                        
                        url = "ws://127.0.0.1/ws"
                        i = 0
                        relaystatus = [0,0,0,0,0,0,0,0]
                        
                        #initiliaze relay 3 just for demo purpose
                        wsinit = websocket.create_connection("ws://127.0.0.1/ws")
                        time.sleep(2)
                        wsinit.send('{"cmd":"full","dev":"relay","circuit":"3"}')
                        while True:
                          result = json.loads(wsinit.recv())
                          if result['dev'] == 'relay':
                            print result
                        wsinit.close()
                        

                        I will commit it in the first week of January.

                        W 1 Reply Last reply Reply Quote 0
                        • W
                          Wim Stockman @tomas_hora last edited by

                          Hi thx,

                          This works !
                          But now I get a weird exception on the evok.py on line 140 it throws an exception:
                          I get "Expected bytes, unicode, or None; got <type 'int'>"

                          Each time I sent a message : wsinit.send('{"cmd":"set","dev":"relay","circuit":"3","value":"1"}')

                          It's like it iterates twice over the on_message loop

                          my demo code is

                          
                          import websocket
                          import json
                          import time
                          import threading
                          
                          url = "ws://127.0.0.1:8088/ws"
                          i = 0
                          global relaystatus
                          relaystatus = [0,0,0,0,0,0,0,0]
                          
                          #initiliaze relay 3 just for demo purpose
                          wsinit = websocket.create_connection("ws://127.0.0.1:8088/ws")
                          time.sleep(2)
                          wsinit.send('{"cmd":"full","dev":"relay","circuit":"3"}')
                          result = json.loads(wsinit.recv())
                          relaystatus[2]=result["value"]
                          while True:
                          
                            result = json.loads(wsinit.recv())
                            if result['dev'] == 'input':
                                  if relaystatus[2]==0 :
                                     wsinit.send('{"cmd":"set","dev":"relay","circuit":"3","value":"1"}')
                                     relaystatus[2] = 1
                                  else:
                                     wsinit.send('{"cmd":"set","dev":"relay","circuit":"3","value":"0"}')
                                     relaystatus[2] = 0
                          
                            print result
                          
                          wsinit.close()
                          

                          Thanks for the great help already :-)
                          Wim

                          T W 2 Replies Last reply Reply Quote 0
                          • T
                            tomas_hora administrators @Wim Stockman last edited by

                            @Wim-Stockman I saw your pull request.. Did you find out what it was with the Expected bytes, unicode, or None; got <type 'int'>"? On what code did it crash?

                            W 1 Reply Last reply Reply Quote 0
                            • W
                              Wim Stockman @Wim Stockman last edited by

                              So I found the problem, solved it and put a pull request in github.

                              made a little change in the evok.py.

                              #adding support to get state of relays using full msg in cmd 
                                         if cmd == "full":
                                               self.write_message(result)
                              
                              1 Reply Last reply Reply Quote 0
                              • W
                                Wim Stockman @tomas_hora last edited by

                                @tomas_hora yes the on_events routing fired a new message for the status change of the relay which was captured by the on_message and since it just sented a 0 or 1 the on_message gave this weird thing

                                W 1 Reply Last reply Reply Quote 0
                                • W
                                  Wim Stockman last edited by

                                  This post is deleted!
                                  1 Reply Last reply Reply Quote 0
                                  • W
                                    Wim Stockman @Wim Stockman last edited by Wim Stockman

                                    So I finished the hardware part for the input plexing.
                                    I used a variation on the charlyplexing.

                                    In the example breadboard I only used 4 digital inputs (symbolized by the Leds), the 12V Vcc is symbolized by the battery and 8 pushbutton : https://circuits.io/circuits/3580634-stockmaninputplexing.

                                    You could attach up to 15 pushbuttons on 4 digital inputs with this method. It is just some binary logic behind and a lot of diodes :-)
                                    The purple wires are connected to an input just directly. (you could place diodes for safety)
                                    and the next 6 pushbuttons are connected through 2 wires.
                                    If you want 4 more pushbuttons you should combine 3 wires
                                    and for the last one you need 4 wires.

                                    So in theory with this method you could make 16383 different input combinations with this method.
                                    I think it will not be practical but with 2 wires you can easily attach up to (14²-1) 195 pushbuttons with each different reactions.
                                    So know I will create a python class to handle these inputs using the websocket method :-)

                                    1 Reply Last reply Reply Quote 0
                                    • W
                                      Wim Stockman last edited by

                                      Hello,

                                      Is there a possibility to receive the inputs via websocket with timestamps.
                                      I know the pigpio librabry does this, but since the new neurons don't work anymore with pigpio. I was wondering if this is possible would be easy to detect , long pressed buttons etc...

                                      T 1 Reply Last reply Reply Quote 0
                                      • W
                                        Wim Stockman last edited by

                                        Hello,
                                        I have written some code to detect two inputs simultaniously activated through websocket.
                                        Here is the code

                                        #timingclass
                                        import websocket
                                        import threading
                                        import datetime
                                        import json
                                        import time
                                        
                                        
                                        
                                        url = "ws://192.168.1.104:8088/ws"
                                        
                                        
                                        class DI:
                                        		
                                        	
                                        	def __init__(self,circuit,value,timestamp):		
                                        		self.circuit = circuit
                                        		self.value = value
                                        		self.timestamp = timestamp						
                                        		self.longpress = 0
                                        		self.doubletap = 0
                                        		
                                        		
                                        		
                                        class homecontrol:
                                        	def __init__(self,websock_evok_url):
                                        		
                                        		self.status = 0
                                        		self.digitalinput_list = [[0,0],[0,0]] # create list with timestamp inputs
                                        		self.timeout = 1000				
                                        		self.websock_evok_url = websock_evok_url	
                                        		
                                        		#connect to websocket and spawn message thread		
                                        		self.ws = websocket.WebSocketApp(url, on_message = self.on_message, on_error = self.on_error, on_close = self.on_close)
                                        		self.wst = threading.Thread(target=self.ws.run_forever())		
                                        		self.wst.daemon = True
                                        		self.wst.start()
                                        		
                                        		
                                        	def time_stamp_inputs(self):
                                        			t = datetime.datetime.now()
                                        			t = (t.second * 1000)+(t.microsecond / 1000)								
                                        			return t
                                        					
                                        
                                        	def detect_if_pressed_together(self):				
                                        		d1 = self.digitalinput_list[0]
                                        		d2 = self.digitalinput_list[1]
                                        		# must be two different inputs and the same values you cannot press and unpress at the same time
                                        		if d1.circuit != d2.circuit and d1.value == d2.value:		
                                        				t = d1.timestamp -d2.timestamp		
                                        				if t < self.timeout:				
                                        					return 1			
                                        				else:
                                        					return 0
                                        
                                        		
                                        	def on_message(self,ws, message):		
                                        			self.obj = json.loads(message)
                                        			print self.obj
                                        			self.dev = self.obj["dev"]
                                        			self.circuit = self.obj["circuit"]
                                        			self.value = self.obj['value']		
                                        			if self.dev == "input" and self.value == 1 :											
                                        				digitalinput = DI(self.circuit,self.value,self.time_stamp_inputs())			
                                        				self.digitalinput_list.insert(0,digitalinput)
                                        
                                        				if(self.detect_if_pressed_together()):					
                                        					l = (self.digitalinput_list[0].circuit,self.digitalinput_list[1].circuit)
                                        					l = sorted(l)					
                                        					x = str(l[0])+str(l[1])						
                                        					self.digitalinput_list[0].circuit = int(x)
                                        					x = self.digitalinput_list[0]
                                        					proc = threading.Thread(target=self.proceed_input,args=(x,))
                                        					proc.start()
                                        					
                                        
                                        					
                                        					
                                        	def detect_long_press_of_button(self):
                                        		pass
                                        	
                                        	
                                        	
                                        	def proceed_input(self,I):# SETUP a method to declare what to do which each function , was thinking of using codeblocks for this part ?		  
                                        		  if I.circuit == 17:			  
                                        			  print I.circuit
                                        			  relay = 5
                                        			  t = threading.Thread(target=self.switch_rel,args=(relay,))
                                        			  #t = threading.Thread(target=switch_on_off_relay,args=(relay,))
                                        			  t.start()
                                        			  print "thread"
                                        			  
                                        			
                                        		  if I.circuit == 26:	
                                        			  print "26"
                                        			  relay = 1
                                        			  c = threading.Thread(target=self.switch_rel,args=(relay,))			  
                                        			  c.start()
                                        			  print "thread2"
                                        			  
                                        			  
                                        	def on_error(self,ws,error):
                                        			print "error"
                                        			print error
                                        
                                        	def on_close(self,ws):
                                        			print "connection closed"
                                        			
                                        	def switch_rel(self,c):		
                                        		relaynumber = c
                                        		self.ws.send('{"cmd":"set","dev":"relay","circuit":"'+str(relaynumber)+'","value":"0"}')
                                        		
                                        		#else:
                                        		#		self.ws.send('{"cmd":"set","dev":"relay","circuit":"'+str(relaynumber)+'","value":"0"}')
                                        		#		self.status = 1
                                        		
                                        
                                        
                                        # SETUP a method to declare what to do which each function , was thinking of using codeblocks for this part ?		  				
                                        
                                        
                                        
                                        def switch_on_off_relay(c):
                                        			print c
                                        			relaynumber = c
                                        			url = "ws://192.168.1.104:8088/ws"		
                                        			ws = websocket.create_connection(url)		
                                        			print "swdf"
                                        			ws.send('{"cmd":"set","dev":"relay","circuit":"'+str(relaynumber)+'","value":"1"}')
                                        			
                                        			ws.send('{"cmd":"set","dev":"relay","circuit":"'+str(relaynumber)+'","value":"0"}')
                                        			
                                        			ws.close
                                        			pass
                                        
                                               	
                                        
                                        x = homecontrol(url)	
                                        
                                        

                                        But I have a problem that some inputs when they are to fast one after each other get forgetten.
                                        and if I do none multithreading it does do al the steps but then one push may hold the others so not good.
                                        Can somebody help me ?

                                        1 Reply Last reply Reply Quote 0
                                        • T
                                          tomas_hora administrators @Wim Stockman last edited by

                                          @Wim-Stockman I will take a look at it during the next week. Thanks for the tip.

                                          I did not check the code much but there should be some time buffer while decoding the correct input. The messages does not always come at the same time, there might be a tens of ms gap between each and you shoudl tie those together...

                                          1 Reply Last reply Reply Quote 0
                                          • First post
                                            Last post