I ask because there are so many ways to handle input contacts (going back to your original question). Sure, looking at using struct or some other mechanism might be good, however, sometimes, when you look at the entirety of the problem a different perspective might surface.
In this case you have to read the pins individually by using pin objects. If we step back to that layer, before even considering struct packing and unpacking, what can you do?
Here's one example. I am using simulated pin values to make it easier to experiment. If you uncomment the pin-object code and edit it to represent your setup it might work with the actual I/O as wired:
Code: Select all
_NUMBER_OF_CONTACTS = 12
# Hypothetical pin assignments; it's a tuple of input pin objects
# contact_pins = (machine.Pin(1, machine.Pin.IN),
# machine.Pin(2, machine.Pin.IN),
# machine.Pin(3, machine.Pin.IN),
# machine.Pin(4, machine.Pin.IN))
simulated_contact_pin_values = (0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0)
# This assigns each of the above pins to a bit in an integer
# This should be a one-hot table; meaning, only a single bit should be 1 per value
# You can assign any contact to any bit position
#
contact_pin_masks = (0b1000_0000_0000,
0b0100_0000_0000,
0b0010_0000_0000,
0b0001_0000_0000,
0b0000_1000_0000,
0b0000_0100_0000,
0b0000_0010_0000,
0b0000_0001_0000,
0b0000_0000_1000,
0b0000_0000_0100,
0b0000_0000_0010,
0b0000_0000_0001)
# Read the pin states and pack into an integer
# This really simple loop reads every single one of your input contacts and stores the
# state of each of them at the bit location you selected using the binary mask for that contact
contact_states = 0
for i in range(_NUMBER_OF_CONTACTS):
# contact_states |= contact_pins[i].value() and contact_pin_masks[i]
contact_states |= simulated_contact_pin_values[i] and contact_pin_masks[i]
print(f"contacts encoded into integer: {contact_states:012b} the integer:{contact_states}")
# Test an integer for pin states
print("integer decoded into contact states: ", end="")
for i in range(_NUMBER_OF_CONTACTS):
print(f"{1 * (0 != contact_states & contact_pin_masks[i])}", end="")
The output statement is just an example to show that you can easily determine contact state from this packed integer with simple logical operations. I would say that one of the advantages of such an approach is that you are not dynamically creating and modifying lists. Your inputs are (and should be) tuples with pin objects and, the other, integers that map each pin object to a position in the integer you'll use to store the state of each contact.
From there you can unpack one or all of the contact states any way you want using the same mask. In fact, in your application you might not need to have all the contact states unpacked at once. Maybe you check contact[0] here and, if set, you might check contact[5]. Well, this allows you to do this without having to unpack all 12 contacts.
Just a thought. Not the only way to do it.