I want to make a control surface that has approx 150 buttons (Cherry MX keyboard switches), each having its own LED.
Besides reading the keys I want to individually dim each LED. The dimming does not have to be of very high resolution, I am fine with maybe 8 different brightness levels. Only importance is the individual control of each LED.
On the button side, I need to make sure that even the fastest and shortest button press is registered and does not get lost.
My approach would be to use a couple of matrices, separately for LEDs and buttons, made out of PCF8574s.
Are they fast enough to read the button states and provide a Soft-PWM for the LEDs?
A 24x8 matrix will provide you with enough buttons/leds. Although the matrix is 24x8 electrically, it does not have to be 24x8 physically.
I would consider using shift registers and the the Arduino's SPI hardware interface for speed. I2C might not be fast enough, even at 400KHz. You could use 3 x 74hc595 to drive the led columns (as long as you don't need high brightness), 3 x 74hc164 to read the switch matrix columns, and 1 x tpic6b595 to drive the rows (common to switch and led matrices). With SPI, you can update 3 chained 74hc595 at a very fast speed, and simultaneously read 3 x 74hc164.
You can use "bit-angle-modulation" to dim the leds. For 8 brightness levels including off, scanning the matrix will need to be done 3 times as often as a matrix where the leds are only on/off. For the 3 scans, the second scan would last half as much time as the first, and the third scan would
last half as long as the second.
An important question is do you need n-key rollover? If so, you will need to wire a diode in series with every switch.
Thanks for the detailed help! I will have a look at the datasheets and do a first draft of the layout.
The project is part of a lighting console, in which many keys shall be able to be pressed simultaneously (how many I cannot tell).
So, did I understand correctly that a diode in series with every switch enables me to (theoretically) press every key at the same time? (or better: press all keys except one and correctly read the single one as not pressed)
Or you could use a string of WS2803 which have 18 PWM outputs and send them brightness data based on button pushes. Or Ws2811 with 3 outputs. I don't see a source of WS2803 anywhere anymore.
I wouldn't do the multiplexing of the leds by hand with PCF8574s.
150 leds with individual brightnes control might get tricky. Maybe the adafruit charlieplex breakout board works for you (but only can drive 144 leds).
Drivers for more leds exist but you will quickly leave the land of cheap breakoutboards with prepared libraries.
Ok, I successfully built a 24x8 LED matrix with 3x 74HC595 and 1 TPIC6B595 with 3mm low current LEDs.
Works perfectly but the LEDs' brightness naturally is very low. I need 20mA LEDs in order to reach the brightness requirements.
The 74HC595 is too weak to support that current. What is the best alternative to use, especially taken into account that I need to work it on the high side of the LEDs?
You could connect the 74HC595 outputs to UDN2981 drivers. These may give a significant voltage drop, perhaps 0.7V, so factor that in when you calculate the led series resistors.
Also there is MIC5891 which could replace the 74HC595. This chip may also have a higher voltage drop.
Alternatively, you can put pnp transistor on every 74HC595 output, like BC327. These should have a much lower voltage drop, like 0.2V, but you will need 24 transistors and 24 resistors to limit the base current.