MaxIV-KitsControls / dev-maxiv-raspberry_pi

Tango DS for the Raspberry Pi GPIO
GNU General Public License v3.0
3 stars 4 forks source link

More pins for I/O #1

Open reszelaz opened 6 years ago

reszelaz commented 6 years ago

First of all many thanks for sharing this project! It will be very usefull for our needs (timed control of the pneumatic valves).

I was going to implement 5 more I/O pins. I was thinking about pins: 11, 12, 13, 15 and 16. Would you accept such PR?

jensun84 commented 6 years ago

Hi Zibi! I'd absolutely accept this PR. Yet, I have a task to add support for all GPIO pins. Maybe I can have it done within two weeks, I'll let you know.

Best, /J

reszelaz commented 6 years ago

Do you think that the pin numbers are fine? If we agree on these we could already prepare the cabling in our setup.

jensun84 commented 6 years ago

Hi Zibi! Yes, those numbers will work and are in the correct order. I will push by the end of today. Best, Jens

jensun84 commented 6 years ago

Hi Zibi! In new commit: added support for 10 pins (3,5,7,8,10,11,12,13,15,16) removed socket timeout from tcp server removed hardcoded attribute polling for now, removed change event subscription and pushing

I have not had time to look at the tcp server causing the ~50ms overhead yet. I did the changes quickly so please review the code before using. :) All the best,/J

AntoineDupre commented 6 years ago

Hi,

Maybe you can consider setting the available pins through a tango property and then create pin attribute dynamically.

Dynamic attributes are created through initialize_dynamic_attributes function. This function is call after the init_device method.

Here a small example (not tested):

      pins = device_property(dtype=(int,)) 

      def initialize_dynamic_attributes(self):                                     
          for pin_number in self.pins:                                             
              # Create attribute name                                              
              voltage_attrname = "pin{}_voltage".format(pin_number)                
              output_attrname = "pin{}_output".format(pin_number)                  
              # Get tango type                                                     
              tango_type = tango.CmdArgType.DevBoolean                             
              # Create attributes                                                  
              voltage_attr = tango.Attr(voltage_attrname,                          
                                        tango_type, tango.READ_WRITE)              
              output_attr = tango.Attr(output_attrname,                            
                                       tango_type, tango.READ_WRITE)               
              # Add attribute and setup read/write/allowed method                  
              self.add_attribute(                                                  
                  voltage_attr,                                                    
                  r_meth=self.read_pin_voltage,                                    
                  w_meth=self.write_pin_voltage,                                   
                  is_allo_meth=self.is_voltage_allowed)                            
              self.add_attribute(                                                  
                  output_attr,                                                     
                  r_meth=self.read_pin_output,                                     
                  w_meth=self.write_pin_output,                                    
                  is_allo_meth=self.is_output_allowed)                             
              # If event needed, setup change event                                
              self.set_change_event(voltage_attrname, True, True)                  
              self.set_change_event(output_attrname, True, True)                   

      # Voltage                                                                    

      @catch_connection_error                                                      
      def read_pin_voltage(self, attr):                                            
          attr_name = attr.get_name()                                              
          pin_number = int(filter(str.isdigit, attr_name))                         
          value = self.raspberry.readvoltage(pin_number)                           
          setattr(self, "__pin{}_voltage".format(pin_number), value)               
          attr.set_value(value)                                                    

      @catch_connection_error                                                      
      def write_pin_voltage(self, attr):                                           
          w_value = attr.get_write_value()                                         
          attr_name = attr.get_name()                                              
          pin_number = int(filter(str.isdigit, attr_name))                         
          python_attr = "__pin_{}_voltage".format(pin_number)                      
          self.set_voltage(w_value, pin_number, getattr(self, python_attr))        
          setattr(self, "_{}".format(attr_name), w_value)                          

      # Ouptut                                                                     

      @catch_connection_error                                                      
      def read_pin_output(self, attr):                                             
          attr_name = attr.get_name()                                              
          pin_number = int(filter(str.isdigit, attr_name))                         
          value = self.raspberry.readoutput(pin_number)                            
          setattr(self, "__pin{}_output".format(pin_number), value)                
          attr.set_value(value)                                                    

      @catch_connection_error                                                      
      def write_pin_output(self, attr):                                            
          w_value = attr.get_write_value()                                         
          attr_name = attr.get_name()                                              
          pin_number = int(filter(str.isdigit, attr_name))                         
          self.raspberry.setoutput(pin_number, w_value)                            

You can notice that the write methods are slightly different. As attributes are created dynamically, you can not profit of the PyTango hight level API wrapping and you have to set yourself the attribute value (same to get the write value).

Cheers, /Antoine

reszelaz commented 6 years ago

Sounds good to me! For the moment we will try the recently added pins attributes which fulfills with our requirements. So do not rush with this refactoring just for us. Thanks a lot guys!

jensun84 commented 6 years ago

Thanks Antoine! The dynamic pin attributes is a great idea. I also realized that I can refactor the TCP IP server, adding an argument with argparse to flag wheter to start the HTTP server for the camera frame or not. In this case you’ll only add camera support to the server when needed.