About Us Knowledge Base Community Forum Electronics Toolbox FAQ Shipping & Delivery

Community Forum

Share your projects and post your questions

Search
Register or Sign In
Forum

Multiple buttons lighting multiple leds

1401 Views - Created 06/06/2017

06/06/2017

Posted by:
TonyE

Users Avatar

I would like to use the IO PLus to create a 'keyboard' to light LEDs.So I have 8 buttons (could be many more!) which when pressed light a corresponding LED and when released the LED goes out.

I have looked at tutorial2.py and can see how to light an LED on button press but the LED goes out depending on time.sleep(x).

I have succesfully done this with gpiozero (Ben Nuttall, Raspberry Pi Foundation) using led = LED(17) button = Button(3) button.when_pressed = led.on button.when_released = led.off

or their latest LEDBoard & ButtonBoard and linking them with xx.source & yy.values

However the RPi does not have enough IO pins for my needs, hence the IO Plus

Has anyone done this before on the IO Plus?

Thanks for your help, TonyE

06/06/2017

Posted by:
andrew

Users Avatar

Location:
United Kingdom

Users Twitter  Users Website  

Hi TonyE

The simplest way to do this with an IO Pi Plus would be to connect the buttons to the bus on one chip and the leds to the bus on the second chip with the led pins matching the button pins, so Button 1 connects to bus 1 pin 1 while LED 1 connects to bus 2 pin 1.  You can then use a loop to read the values from the two ports on bus 1 and write the them to the ports on bus 2.

For each button you will need to connect the input to the button to 5V and the output to bus 1 on the IO Pi.  You may also need a pull-down resistor connected between the button output and ground to make sure the voltage drops to 0V when button is released.  A 10K resistor should do the job.  Without a pull-down resistor the input on the IO Pi Plus would be floating which means if there is any stray capacitance in the wire it could cause the input to be read as high or low.

The code below should do what you need.

from ABE_helpers import ABEHelpers
from ABE_IoPi import IoPi

i2c_helper = ABEHelpers()
i2c_bus = i2c_helper.get_smbus()

# create the two buses
bus1 = IoPi(i2c_bus, 0x20)
bus2 = IoPi(i2c_bus, 0x21)

# set bus 1 to be inputs
bus1.set_port_direction(0, 0xFF)
bus1.set_port_direction(1, 0xFF)

# set bus 2 to be outputs and turn all of the pins off
bus2.set_port_direction(0, 0x00)
bus2.set_port_direction(1, 0x00)

bus2.write_port(0, 0x00)
bus2.write_port(1, 0x00)

port0val = 0x00
port1val = 0x00

while True:
    
    port0val = bus1.read_port(0)
    port1val = bus1.read_port(1)
    
    bus2.write_port(0, port0val)
    bus2.write_port(1, port1val)

AB Electronics UK Tech Support

07/06/2017

Posted by:
TonyE

Users Avatar

Hi Andrew,

many thanks for your comprehensive prompt reply. I'll give this a try.

Can I use the internal resistors as outlined in tutorial 2 rather than an external resistors?

I presume that if I needed more buttons and LEDs then the same approach would work with stacked IOPlus boards.

Regards

TonyE

07/06/2017

Posted by:
andrew

Users Avatar

Location:
United Kingdom

Users Twitter  Users Website  

The internal resistors on the IO Pi Plus are pull-up rather than pull down so to use them you would need to connect the button to ground instead of 5V so when you press a button it shorts the input to ground.  The side effect of this method would be that the inputs would be inverted so when the button is pressed the input goes to 0 instead of 1.  This means that you would need to invert the values from bus 1 before writing them to bus 2 otherwise the LEDs would be on all of the time and go out when you press a button.

You can stack up to 4 IO Pi Plus boards on a Raspberry Pi so you could have up to 64 buttons and leds connected.  You just need to change the solder bridges on the address select pads to give each board a different pair of addresses.

One thing to note is the maximum current the IO controller chip can source is 125mA so if you have 16 leds connected and being lit at the same time you would only be able to safely drive 7.8mA to each LED.  If you use lower current LEDs and 680R resistors this would keep the total current below the 125mA maximum.  Alternativly you could use external transistors or darlington arrays to drive higher current LEDs.

AB Electronics UK Tech Support

31/08/2017

Posted by:
TonyE

Users Avatar

Hi Andrew,

After some delayI have set up my initial system (16 buttons & 16 LEDs) but didn't get the response I expected.

The IO Plus is powered from a separate power supply (solder link removed) and the set up is

5V from board -> input of button; output of button -> 10k resistor -> pin on bus 1

Output of bus 2 -> LED -> resistor -> GND on board

When I run the program all the LEDs light and the buttons do nothing.

I'm sure I must have made a mistake with the wiring somewhere. Can you help?

Regards

Tony

31/08/2017

Posted by:
andrew

Users Avatar

Location:
United Kingdom

Users Twitter  Users Website  

Hi Tony

With the inputs do you have the internal pull-up resistors enabled?  If you have the input of the button connected to 5V you will need to disable the internal pull-ups and use a 10K resistor to connect each button output to ground to act as a pull-down.  Without a pull-down resistor the inputs will be floating which means after a button press they may stay high or alternate between high and low due to the internal capacitance on the input lines.

 

AB Electronics UK Tech Support

31/08/2017

Posted by:
TonyE

Users Avatar

Hi Andrew

can you remind me how I disable the internal pull up resistors please?

Regards

Tony

31/08/2017

Posted by:
andrew

Users Avatar

Location:
United Kingdom

Users Twitter  Users Website  

You can use the set_port_pullups method so to disable the pullups on both busses it would be:

bus1.set_port_pullups(0,0)
bus1.set_port_pullups(1,0)
bus2.set_port_pullups(0,0)
bus2.set_port_pullups(1,0)

AB Electronics UK Tech Support

31/08/2017

Posted by:
TonyE

Users Avatar

Hi Andrew

thanks for your response. I added the set.port_pullups statements just before the while True: in the program you suggested I use at the beginning of this string.

Then, by mistake, I lost power to the Raspberry Pi. All the LEDs remained on with no power on rhe R Pi! I'm sure I have done something wrong as the IO Pi Plus still responds to the tutorials I used when I first set it up.

Help!

Regards

Tony

31/08/2017

Posted by:
andrew

Users Avatar

Location:
United Kingdom

Users Twitter  Users Website  

If the IO Pi is powered separately from the Raspberry Pi then it will continue in the same state as it was running in when the Raspberrry Pi powered down, you have to remove the power to the IO Pi Plus as well for it to reset to its default state.  

The picture below shows the two ways you can connect inputs to the IO Pi Plus.  

The 5V input option should be how you have the inputs wired at the moment.  In this mode you will need to make sure the internal pull-up resistors are disabled.

If the button is connected to ground like in the second schematic then you need to enable the internal pull-up resistors and the inputs will show high when the button is open and go low when the button is pressed.  You can get around this by using the invert_pin() or invert_port() methods in the python library to invert the inputs so 1 becomes 0 and 0 becomes 1.  That way when you press the button and short the pin to ground it will register the input as going high.

The 1K and 500R resistor values are not critical as they are only there to limit the current being fed to and drawn from the IO Pi inputs in the event that the pins are accidentally set as outputs.  As long as the resistors limit the current to less than 20mA it should be fine. 

Post image

AB Electronics UK Tech Support

01/09/2017

Posted by:
TonyE

Users Avatar

Hi Andrew

spent the evening modifying my breadboard prototype with 16 buttons and LEDs to match the set up you suggested and 'bingo!' it worked.

Once again thank you for the excellent technical support you provide. An example to all technical companies, many much larger than AB Electronics.

Regards

Tony

03/09/2017

Posted by:
TonyE

Users Avatar

Hi Andrew

Now I have my led/button combination working, I want to modify the project to drive 16 solenoids from the IO Pi using this relay board 

XSOURCE 12v 16 channel module shield board with opto coupler

i think Sainsmart do something very similar.

I cannot find any instructions anywhere and wondered if you could help or at least be able to point me to somewhere where I might find instructions.

Many thanks in advance,

Regards

Tony

03/09/2017

Posted by:
andrew

Users Avatar

Location:
United Kingdom

Users Twitter  Users Website  

I found this photo of a relay board that looks very similar to the XSOURCE board and it uses a DPC-817C opto coupler.  Here is the datasheet for the opto coupler.  According to the datasheet the opto coupler needs a 50mA forward current on the LED so you will need to add a transistor in between the IO Pi output and the relay board input.  

Looking at the photo of the relay board it looks like the cathode side of the LED is connected to the input pins.  You would activate the relay by connecting an input to ground so you will need to use an NPN transistor to switch the inputs.

We have a tutorial in our knowledge base on driving relays from the IO Pi using a transistor, you should be able to use the same circuit but instead of connecting the collector on the transistor to the relay you would connect it to the input on the relay board.  This should then allow you to safely activate the opto coupler on the relay board without putting to much load on the IO Pi outputs.

AB Electronics UK Tech Support

03/09/2017

Posted by:
TonyE

Users Avatar

Hi Andrew

once again, many thanks for your prompt help. I'll give it a try.

Regards

Tony

19/10/2017

Posted by:
TonyE

Users Avatar

Hi Andrew

After a long pause I've set things up as you suggested in the tutorial and things are not working as I expected! 

Ive a 12v relay board so presumably I can substitute 12v for 5v in the diagram.   When I do this I cannot get the relay to trigger but each individual relay triggers if I connect the input pin to ground.

have I wired up something wrong do you think!

regards

tony

19/10/2017

Posted by:
andrew

Users Avatar

Location:
United Kingdom

Users Twitter  Users Website  

Hi Tony

Try connecting the cathode from the transistors to the inputs on the relay board and the anode to ground.  When you power the transistors base from the IO Pi via a resistor it should short the relay input to ground, triggering the relay.

 

AB Electronics UK Tech Support

19/10/2017

Posted by:
TonyE

Users Avatar

Hi Andrew

Ive tried your suggestion and all I get is the relay indicator led on the relay board flickering but the relay doesn't operate. I'm using the switch set up (switching to 5v) you mentioned 31/08/17 and assumed that cathode = emitter and anode = collector.

Regards

Tony

19/10/2017

Posted by:
andrew

Users Avatar

Location:
United Kingdom

Users Twitter  Users Website  

If the indicator on the relay board is flickering then it is possible that there isn't enough current being passed through the transistor to activate the relay.  Try changing the resistor on the transistor base to a lower value.  The maximum current on any one IO pin is 20mA so you could go as low as a 250R resistor but try someing around 700R to start with.

AB Electronics UK Tech Support

19/10/2017

Posted by:
TonyE

Users Avatar

Hi Andrew

Ive noticed that the LED light on the relay board is flickering irrespective of me pushing the button or not!

Regards

Tony

19/10/2017

Posted by:
andrew

Users Avatar

Location:
United Kingdom

Users Twitter  Users Website  

Can you measure measure the current and voltage between the relay inputs and ground?  Also try measuring the 12V power supply to make sure there is a stable voltage going into the relay board.

What happens if you connect the the transistors gate resistor directly to a 5V or GND input?

AB Electronics UK Tech Support

19/10/2017

Posted by:
TonyE

Users Avatar

Hi

Ive connected the base to +5v via 470 ohm resistor, the emitter to the input pin on the relay and the collector to ground. Using either a separate power supply or the 5v output from the relay board, the relays operate as expected.

The 12v PS is very steady at 12v.

Could the problems be associated different earths? Should all the grounds (12v power supply, 5v power supply, ground on the relay board and ground on the io pi be all connected together?

Regards

Tony

 

19/10/2017

Posted by:
andrew

Users Avatar

Location:
United Kingdom

Users Twitter  Users Website  

You will need to connect all of the grounds together for the circuit to work correctly.

AB Electronics UK Tech Support

06/02/2018

Posted by:
TonyE

Users Avatar

Hi Andrew 

for a number of reasons I have not been able to work on this project. I have abandoned the relay board and am now using Darlington arrays. I’ve now wired these all up but the software you suggested I used to link the buttons and leds stops working.

l get the following 

Traceback (most recent call last)

bus1 = IoPi(i2c_bus,0x20)

Self.portbval = self._bus.read_byte_data(self.address! self.GPIOB)

OSError:(Errno 121) Remote I/O error

Any suggestions?

Regards

Tony

06/02/2018

Posted by:
andrew

Users Avatar

Location:
United Kingdom

Users Twitter  Users Website  

Hi Tony

Does the error happen all the time or after the software has been running for a while?   The Remote I/O error normally happens when something is blocking access to the I2C bus or the IO Pi library can not find the IO Pi.  Do you have any other software running that would be making calls to the I2C bus?

When you run the command "sudo i2cdetect -y 1"  does the IO Pi appear on address 0x20?

AB Electronics UK Tech Support

08/02/2018

Posted by:
TonyE

Users Avatar

Hi Andrew 

when I run the command I get a matrix (0 to f, 00 to 70) with 20 at the intersection of 20 and 0 & 21 at the intersection of 20 and 1.i presume this confirms the presence of the IO Pi.

i have the IOPi library in the same folder as the program and I don’t have any other software running that would call to i2c bus that I know of.

The IO Pi is running off an external 5V supply (solder bridge removed) but I only detect less than 2V at the Gnd and 5V pins on both Bus 1 and Bus 2. Would this suggest the IO Pi is faulty?

Regards

Tony

08/02/2018

Posted by:
andrew

Users Avatar

Location:
United Kingdom

Users Twitter  Users Website  

Hi Tony

If there is only 2V at the power input pins then that suggests there could be a problem with either the power supply not supplying enough voltage or the IO Pi is drawing too much current causing the voltage to drop.

Can you try measuring the amount of current the IO Pi is drawing by connecting your multimeter in current mode between the 5V wire from the power supply and the 5V pin on the IO Pi power connector?  The IO Pi should only draw a few millamps when none of the IO pins are set as outputs so if it is drawing a lot of current that would suggest that one or both of the IO chips are faulty.  You could also try touching the chips to see if they are warm as that would also suggest a fault.

Also try checking the continuity between the ground output on your power supply and the ground pins on the Raspberry Pi GPIO connector, or the outside of the ethernet or USB sockets, to make sure there is a good connection between the grounds on the two power supplies.

The fact that the IO chips are shwoing up on 0x20 and 0x21 I2C addresses suggests that they are working at least to some degree as faulty chips normally wouldn't show up on the I2C bus so it could be a power supply fault that is causing the problems.  The MCP2317 IO chips will work from 1.8V to 5.5V so if your power supply is only providing 2V the chips would appear on the I2C bus but they would also only provide 2V on the output pins which may not be enough to drive your darlington arrays.

If you are only using the IO Pi to drive darlington arrays then it should be safe to use the Raspberry Pi to power the IO Pi instead of an external power supply.  Darlington arrays like the ULN2003A should draw less than 2mA from each IO Pi output so it will put minimal load on the Raspberry Pi's power supply.

AB Electronics UK Tech Support

08/02/2018

Posted by:
TonyE

Users Avatar

Hi Andrew 

the 5V is fed in from the 2 pin header and the measurements taken at the 16 pin header. The power supply is 5V, 3.8V stand alone unit.

I’ll check the power draw and the earth continuity tomorrow morning.

Regards

Tony

09/02/2018

Posted by:
TonyE

Users Avatar

Hi Andrew,

I traced the problem to a poor connection from my power supply to the IO Pi. One of the cables was faulty hence providing less than 2V. Once this was replaced, all is going to plan!

Until my next problem.......

Thank you so much for you help.

Regards

Tony

21/02/2018

Posted by:
TonyE

Users Avatar

Hi Andrew,

The project is growing! I'm now looking at 48 pins in and 48 pins out, so planning to buy further IO-Plus boards soon.

The project works in two ways. FIrstly taking inputs from buttons and using that input to light LEDs. This, I think I know waht I have to do to modify the code you sen me on 06/06/17.

The second part of the project is to take data from an external file with values thta will be fed into the following

 bus2.write_pin(note_no, note_change)

note_no takes the value 1-16 and note_change the value 0 or 1

Howwever I want to utilise note_no values 1-48 across 3 busses (bus2, bus4 and bus6). note_no values 1-16 going to the pins on bus2, note_no values 17-32 going to bus4 and note_ no values 33-48 going to bus 6.

I'm  not sure how to do this. Can you help?

Regards

Tony

22/02/2018

Posted by:
andrew

Users Avatar

Location:
United Kingdom

Users Twitter  Users Website  

Hi Tony

The easiest way to map the values to three busses would be to use a function which takes an input pin and state and uses a series of if statements to map it to the correct pin.

The code below should do what you need.

def update_output_pin(pin, state, bus2, bus4, bus6):
    '''
    Update the output pin for busses 2, 4 and 6 based on an input value of 1 to 48
    '''
    if state is 0 or state is 1:
        if pin >= 1 and pin <= 16:
            bus2.write_pin(pin, state)
        elif pin >= 17 and pin <= 32:
            pinval = pin - 16
            bus4.write_pin(pinval, state)
        elif pin >= 33 and pin <= 48:
            pinval = pin - 32
            bus6.write_pin(pinval, state)
        else:
            print("pin out of range")
    else:
        print("state out of range")


def main():
    '''
    Main program function
    '''

    # Create 6 instances of the IOPi class with an I2C address of 0x20 to 0x25
    iobus1 = IOPi(0x20)
    iobus2 = IOPi(0x21)
    iobus3 = IOPi(0x22)
    iobus4 = IOPi(0x23)
    iobus5 = IOPi(0x24)
    iobus6 = IOPi(0x25)

    # Busses 1, 3 and 5 will be inputs
    iobus1.set_port_direction(0, 0xFF)
    iobus1.set_port_direction(1, 0xFF)
    iobus3.set_port_direction(0, 0xFF)
    iobus3.set_port_direction(1, 0xFF)
    iobus5.set_port_direction(0, 0xFF)
    iobus5.set_port_direction(1, 0xFF)

    # Busses 2, 4 and 6 will be outputs with the pins initially set to 0
    iobus2.set_port_direction(0, 0x00)
    iobus2.set_port_direction(1, 0x00)
    iobus2.write_port(0, 0x00)
    iobus2.write_port(1, 0x00)

    iobus4.set_port_direction(0, 0x00)
    iobus4.set_port_direction(1, 0x00)
    iobus4.write_port(0, 0x00)
    iobus4.write_port(1, 0x00)

    iobus6.set_port_direction(0, 0x00)
    iobus6.set_port_direction(1, 0x00)
    iobus6.write_port(0, 0x00)
    iobus6.write_port(1, 0x00)

    while True:

        # count to 48 and and set the pin state high for each pin in turn
        for val in range(1, 48):
            time.sleep(0.05)
            update_output_pin(val, 1, iobus2, iobus4, iobus6)

        # count to 48 and and set the pin state low for each pin in turn
        for val in range(1, 48):
            time.sleep(0.05)
            update_output_pin(val, 0, iobus2, iobus4, iobus6)

if __name__ == "__main__":
    main()

The update_output_pin(pin, state, bus2, bus4, bus6) function takes the pin number between 1 and 48, the state and the three busses which will be used for outputs.

In the main function I created 6 instances of the IO Pi class with the i2c addresses 0x20 to 0x25 and set busses 1, 3 and 5 as inputs and 2, 4 and 6 as outputs.  The while loop at the bottom contains some test for loops that will switch each pin on in turn and then switch them off again in turn.  In your program you would replace the for loops with your code to read from the text file.

AB Electronics UK Tech Support

22/02/2018

Posted by:
TonyE

Users Avatar

Hi Andrew,

Brilliant! Thank you.

Regards

Tony

21/01/2019

Posted by:
TonyE

Users Avatar

Hi Andrew 

This has been an intermittent project!

I now have 3 IO Pi Plus cards stacked on top of one another and propose to remove the link from each one so that they are all externally powered. I presume I therefore need to connect the 5V & GND (separate in its own white box between Bus 1 & Bus 2) on each board to a power supply. If so i presume there is a 2 pin equivalent of the 40 pin header I can buy. I’ve tried searching but not sure what to call it!!

Can you help?

Regards

Tony

21/01/2019

Posted by:
andrew

Users Avatar

Location:
United Kingdom

Users Twitter  Users Website  

Hi Tony

If you are using external power then you will need to connect all of the IO Pi Plus boards together using the 5V and GND pins.

I don't think there is a 2 pin version of the 40 pin header available but the 40 pin header is the same height as the single row headers that are used on Arduino boards.  We sell a 6 pin and 8 pin version which could be cut down to be 2 pins wide.

On the IO Pi Plus the power connector has holes for 2.54mm and 5.08mm connectors so if you could find a 3 pin version of the arduino stackable headers you could remove the middle pin and solder it in the 5.08mm holes.

The other alternative is to use a 5mm pitch screw terminal and join the boards together using wires.

AB Electronics UK Tech Support

21/01/2019

Posted by:
TonyE

Users Avatar

Hi Andrew

Further to my earlier enquiry........

Can I use your 6 pin stackable header and clip off 4 of the legs?

Alternatively can I supply power via the 5V & GND on one or both of the 20 pin headers?

Regards

Tony

21/01/2019

Posted by:
andrew

Users Avatar

Location:
United Kingdom

Users Twitter  Users Website  

Hi Tony

You can clip off four of the legs on the 6 way connector and use that to power the board.  The 5V and GND on the 20 pin headers are connected to the 5V and GND power header so you can supply power through either or both of the 20 pin connectors.

AB Electronics UK Tech Support

Note: documents in Portable Document Format (PDF) require Adobe Acrobat Reader 5.0 or higher to view, download Adobe Acrobat Reader or other PDF reading software for your computer or mobile device.