ShiftRegister PWM Library
The ShiftRegister PWM Library enables usage of shift register pins as pulse-width modulated (PWM) pins. Instead of setting them to either high or low, the library lets the user set them to up to 256 PWM-levels. This post serves as a documentation page for the library and is to be extended over time.
The following video (slides) gives an overview about the library. The source code can be found on GitHub: /Simsso/ShiftRegister-PWM-Library (ZIP-download)
Getting Started
In order to get started, you need an Arduino UNO, a 74HC595 shift register (NXP data sheet), and some LEDs. The figure below shows the wiring (click to enlarge). The LEDs may be connected to the eight shift register output pins (Q0 to Q7). Note that the shift register’s control wires (data, shift clock, and latch clock) are connected to the Arduino pins 2, 3, and 4. These pins can not be changed easily, because the library internally uses port manipulation to maximize performance. The Custom Wiring section of this post explains how these pins can be altered.
After setting up the hardware, download and install the library on your machine. Now you can run the example sketch Sine by uploading the following code. The sketch makes the LEDs of the shift register pulse like a sine wave (as shown in the introduction video).
#include "ShiftRegisterPWM.h" ShiftRegisterPWM sr(1, 16); void setup() { pinMode(2, OUTPUT); // sr data pin pinMode(3, OUTPUT); // sr clock pin pinMode(4, OUTPUT); // sr latch pin // use timer1 for frequent update sr.interrupt(ShiftRegisterPWM::UpdateFrequency::SuperFast); } void loop() { for (uint8_t i = 0; i < 8; i++) { uint8_t val = (uint8_t)(((float) sin(millis() / 150.0 + i / 8.0 * 2.0 * PI) + 1) * 128); sr.set(i, val); } }
The key things to note from the sketch above are:
- Create a shift register object. An explanation for the
resolution
parameter can be found in the next section. It is important to keep the resolution as low as possible because the memory consumption grows linearly with it.
ShiftRegisterPWM sr(numShiftRegisters, resolution);
- Enable timer interrupts, i.e. automatically update the shift register output pins using timer 1 of the ATmega328P. The parameter defines the clock frequency (see next section for a table of possible values).
sr.interrupt(ShiftRegisterPWM::UpdateFrequency::SuperFast);
- Set the i-th pin of the shift register to a PWM value between 0 (always off) and 255 (always on). If the output resolution is set to a lower value, e.g. 8, the PWM value will be scaled down accordingly.
sr.set(i, val);
Terminology
Pulse-width modulation (PWM) is a technique for encoding information in a digital signal through pulsing. See Wikipedia for details. The Arduino Uno has six pins that support PWM output (namely 3, 5, 6, 9, 10, and 11) which can be accessed using the function analogWrite. In some cases, however, more PWM pins might be required. This library makes the pins of a shift register PWM capable.
A shift register in our use-case is a storage that can be serially fed with digital values. In case of the 74HC595 shift register, it outputs the last eight bits of data in parallel.
The PWM carrier frequency, denoted as $f_\text{carrier}$, is the frequency that at which PWM pulses are emitted. Its inverse value is the period. The Arduino’s carrier frequency is $490$ or $980$ Hz by default (reference).
The PWM clock frequency, denoted as $f_\text{clock}$, is the maximum frequency at which outputs can be changed. Some possible values are predefined and listed in the table below. They can be passed to the interrupt
function. For example like that:
sr.interrupt(ShiftRegisterPWM::UpdateFrequency::SuperFast);
Name | Clock frequency $f_\text{clock}$ |
---|---|
VerySlow |
$\approx6,400\text{ Hz}$ |
Slow |
$\approx12,800\text{ Hz}$ |
Medium |
$\approx25,600\text{ Hz}$ |
Fast |
$\approx35,714\text{ Hz}$ |
SuperFast |
$\approx51,281\text{ Hz}$ |
The PWM resolution $r$ is defined to be the fraction $r=\frac{f_\text{clock}}{f_\text{carrier}}$. Intuitively, it can be understood as the number of different brightness levels that LEDs can take when connected to the shift register. The resolution can be manually set on initialization of a shift register object (it is the second parameter of the constructor). Possible values are $r\in(0,255]$. For the Arduino’s PWM pins it is fixed to $r_\text{Arduino}=256$.
Stacking Shift Registers
The library support serial operation of multiple shift registers. The 74HC595 can be chained as shown in the following circuit diagram (click to enlarge).
Now, the ShiftRegisterPWM constructor needs to be called with the corresponding number of shift registers. For the circuit diagram above that would be srCount=2
.
ShiftRegisterPWM shiftRegisterPWM(srCount, resolution);
The time it takes to update the shift register output pins increases with the number of stacked shift registers. Therefore it is strongly recommended to decrease resolution $r$ and $f_\text{clock}$ with an increasing number of shift registers.
Custom Wiring
By default, the shift register must be connected to the Arduino UNO’s digital pins 2, 3, and 4.
Arduino | Shift register | Role |
---|---|---|
D2 | DS | Serial data |
D3 | SH_CP | Serial data transmission clock |
D4 | ST_CP | Shift register output flip-flop clock |
While other libraries for different purposes offer to manually set the pins by passing them as parameters, the ShiftRegister PWM Library does not offer that for performance reasons. Nevertheless, there is an option to change the pins. For each of the three wires, two macros can be defined which contain (1) the port and (2) a bit selection mask. The following table lists the macros with descriptions and the default value.
Name | Default | Role |
---|---|---|
ShiftRegisterPWM_DATA_PORT |
PORTD |
Register name of the bit that corresponds to the data pin |
ShiftRegisterPWM_DATA_MASK |
0B00000100 |
Byte that masks the bit that corresponds to the data pin (2) |
ShiftRegisterPWM_CLOCK_PORT |
PORTD |
Register name of the bit that corresponds to the serial clock pin |
ShiftRegisterPWM_CLOCK_MASK |
0B00001000 |
Byte that masks the bit that corresponds to the serial clock pin (3) |
ShiftRegisterPWM_LATCH_PORT |
PORTD |
Register name of the bit that corresponds to the latch clock pin |
ShiftRegisterPWM_LATCH_MASK |
0B00010000 |
Byte that masks the bit that corresponds to the latch clock pin (4) |
The macros can be overwritten by making a definition prior to including the library. In the following snippet, the latch clock pin is set to be the digital pin 8 (instead of 4).
#define ShiftRegisterPWM_LATCH_PORT PORTB #define ShiftRegisterPWM_LATCH_MASK 1 #include "ShiftRegisterPWM.h"
The associated example sketch is called CustomPins. Details regarding the register names and bit masks can be found in the Arduino port manipulation guide.
Custom Timer
In order to update the digital pins of the shift register with the desired PWM frequency, the library uses timer interrupts. The library registers an interrupt if the function sr.interrupt()
is called. Note that this works only for a single shift register object (or multiple in serial). If (1) multiple PWM shift registers shall be used in parallel, (2) an exact frequency is required, or if (3) the timer is not available for usage, e.g. because another library is already using it, it is possible to manually configure the library to use another timer. For calculating the compare-match-register values, I recommend using a timer interrupt calculator tool. The example sketch CustomTimerInterrupt demonstrates manual timer operation mode.
The library registers the timer 1 interrupt service routine (ISR) depending on a macro. In the source code, this is implemented as follows:
#ifndef ShiftRegisterPWM_CUSTOM_INTERRUPT // Timer 1 interrupt service routine (ISR) ISR(TIMER1_COMPA_vect) { // function which will be called when an interrupt occurs at timer 1 cli(); // disable interrupts (in case update method takes too long) ShiftRegisterPWM::singleton->update(); sei(); // re-enable }; #endif
Therefore, with writing #define ShiftRegisterPWM_CUSTOM_INTERRUPT
prior to the library import, the redefinition of 'void __vector_11()'
error can be prevented and timer 1 is spare.
Hello! i wanted to try this program on my esp 8266 but i always get a fatal error: avr/interrupt.h: No such file or directory.
where is the avr interrupt used and where in the code can I bypass that.. so that it will work on my controller?
Thank you!
Hi there, It is possible to run it on an ESP8266, however, you have to make some modifications. The timers are different. Have a look at the “Custom Timer” section above and at this example sketch.
If you have a working version for the ESP8266 feel free to share it here!
that are good news! I think I understand the problem with the timer a little bit. It’s about synchronizing the ESP frequency with the interrupts. Unfortunately, I’m relatively new in programming and therefore it would be a pleasure if you could help me a little bit more (maybe with a code)? where do I have to start exactly to solve the problem.
Thx
I’ve read a lot about timers and interrups of ESP modules and arduino boards. ESPs have hardware and software timers. I think for this program will probably be used a software timer. However, as a newbe of the arduino scene, I do not know how to rewrite this in this program code. Unfortunately, I find no suitable example programs on timers and interrupts for the ESP. I’m looking for a way to write an ISR code for ESP8266. So please can somebody help me!
I found a solution for my problem. At this time you can get up to 32 outputs from ESP8266 boards using shift registers and I2S with cryptoio. The library is still in progress but works realy well! You can also make Delta-Sigma PWM, exponentialy scalled for realistic LED light output.
https://github.com/Crypter/CryptoIO
is it possible to make a serial connection (eg with a HM-10 or an Wlanmodul) i know there are some problems with the interrupt and timer. but is there any way to do this (eg to switch on/off or edit some variables) while the program is running?
i also tryed SoftwareSerials on other pins..which also didnt work realy well..
or is it only possible with an second controller or an different Arduino with multiple hardware serial ports?
Thanks!
Hello, i tried use the arduino Mega but not worked like your exemple, i followed all yours steps and add all your libraries, do you know saying if it work on the mega ?
I haven’t tried it yet but my first assumption is that the library is not working on the Mega because the I/O ports have different names. You have to make manual adjustments in order to make it work. The reason this stuff is so complicated is the performance advantage of direct port manipulation over digitalWrite.
This is the relevant part of the code: https://github.com/Simsso/ShiftRegister-PWM-Library/blob/master/src/ShiftRegisterPWM.h#L17-L41
Hello Timo,
Do you know what the I/O port names for the MKR series (MKR1000 and MKR1010) are, or where I could find them?
I have been searching for a couple of days unsuccessfully.
Thanks,
Ignacio
Hi Ignacio,
I wasn’t able to find it either. Maybe this datasheet is relevant http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-42618-SmartConnect-ATSAMW25-MR210PB_Datasheet.pdf
I found it by searching for the name of the microcontroller that is placed on top of the MKR1000 (https://store.arduino.cc/arduino-mkr1000).
Alternatively, you might want to look into the boards\ directory and see which constants they define.
I hope that helps!
Best,
Timo
Hi Timo,
Yeah that was my initial thought also. I have been going through the libraries but I can’t find any of the digital ports being defined, which is off because the analog are. I tried guessing a few of the names but they don’t seem to be defined anywhere. Thanks for the link, I will keep digging and see if I can find the answer.
Thanks again for the quick response.
Alles Gute,
Ignacio
Hi Timo,
I am having an issue with the wiring of the 74HC595. As I understand from your document, Pin 0 should map to Q0 on the 74HC595, Pin 1 to Q1 and so on.
It seems that the order of the pins are reversed. I am getting Pin 0 value on Q7 instead, Pin 1 on Q6 and so on.
Any idea why this might be?
Thanks
Hey there!
I think you are right, that’s just the way it is implemented right now (here: https://github.com/Simsso/ShiftRegister-PWM-Library/blob/master/src/ShiftRegisterPWM.h#L105). Since the numbering of the SR pins is kind of arbitrary you can just change the wiring and assume pin 8 was pin 1, 7 was 2, and so on.
Have a good one!
I made a connection to D1, D2, D9.is it OK? can I use it for PWM output ? I’il use it for DC motor ENA.
Hi!
I was thinking about using this library dimming a relatively big number of LEDs. I’m also trying to make the whole package as small as possible for the sake of mobility. Would it be possible to convert this for an ATTiny or will memory constraints and/or clock frequencies be a problem? Is there other similar alternatives that might fit better for the task? I’m very new to all this so I’m sorry if the questions are dumb. 😛
Hi Marcus,
if you want to control a large number of LEDs (say ~100) independently, this library won’t do the job. It’s not memory efficient enough and I am not even sure whether shift registers can be used in such a scenario. The clock frequency would need to be extremely high.
My recommendation is to buy digital to analog converters in such a case.
Hello, I would suggest adding a sample code to use this library with servo motors, as it might be a good alternative for PCA9685. (Despite this PCA if I2C: https://www.adafruit.com/product/815 )
Hi,
So what if I initiate several instances of the object ShiftRegisterPWM; will I be able to send PMW signals to registers connected at different pins. I am trying to control an RGB matrix. I need the dimming effect since its sooooo much fun.
Hi Rolland, instantiating the ShiftRegisterPWM class several times does not make sense unless you call the update function (https://github.com/Simsso/ShiftRegister-PWM-Library/blob/master/src/ShiftRegisterPWM.h#L110) manually. Otherwise, the interrupt code won’t work.
Hello, I am starting to play around with arduino but I cannot manage to get your library to work. I copied you example explicitly and i get an error in this line:
sr.interrupt(ShiftRegisterPWM::UpdateFrequency::SuperFast);
saying ” ‘sr’ does not name a type”.
Is this to do with the library or my IDE?
Thank you in advance
Hi Felipe, sounds as if you forgot to place this line of code at the top of your program:
ShiftRegisterPWM sr(1, 16);
. That’s where you declare the variablesr
. Best regards!I need real knight rider scanner code
Hello Timo!
I am using your library to control 6 pwm servo motors on a NODEMCU with esp8266. It works fine, but when I connect to wifi it causes an error and restarts NODEMCU. I believe the problem is in the timing control that causes conflict between interrupts used in the library and the hardware time required to switch the connection. Is there an example that connects to the internet and uses your library? regards
I am not aware of any example that “connects to the internet and uses your library”. In your case a solution to the problem might be to use two microcontrollers: one that’s connected to the internet and one that controls the servos. The two would communicate through a simple wired connection.
Hello Timo,
do you have a solution for my trouble with the library?
1) In function ‘void setup()’: HC595_PWM:30: error: ‘ShiftRegisterPWM::UpdateFrequency’ is not a class or namespace
2) ShiftRegisterPWM.h:199: error: ISO C++ forbids in-class initialization of non-const static member ‘time’
Library is used with the included example code in Arduino IDE with MEGA2560.
I moved the initialization of “time” to the constructor so that problem is solved.
But the problem with the namespace I couldn’t solve yet – do you have an idea?
Best
Manuel
Hello Manuel,
I am unfortunately unable to reproduce your error. I can successfully compile the example sketches “CustomPins” and “Potentiometer” with Arduino IDE version 1.8.10 on Mac OS for Arduino/Genuino Mega or Mega 2560 (board) with ATmega 2560 (processor). Can you tell me the exact configuration you are using when the error occurs?
Thanks and best regards,
Timo
Hello sir, I tried your library
It worked flawlessly first time but now
All the led’s are fading at the same time together. When I removed the latch connection the led’s started glowing in a sine manner.
So I tried the potentiometer example (latch removed). When I turn the knob halfway all the led’s are lit up to a minimal brightness, then Brightness is increasing
Along with the turn of the knob.
So I connected the latch, this time all the led’s are fading at the same time when I turn the knob
Is there any way to fix this ??
Have you thought of using the hardware SPI to do all the shifting business? You know, connecting the data line to MOSI, clock to SCK, and letting the wonderful internals of AVR micro to take care of it.
I haven’t, but it sounds very intriguing. Can you provide a link to someone doing that?
Hi Timo,
Really great library! Works perfectly with 1 shiftreg, even with other pins.
Nevertheless can’t use a 2nd shiftreg. This second one is correctly wired (it duplicates the first shiftreg outputs with
ShiftRegisterPWM sr(1, 16)
setting.But leds freeze when replacing this by
ShiftRegisterPWM sr(2, 16)
andfor (uint8_t i = 0; i < 8; i++)
byfor (uint8_t i = 0; i < 16; i++)
in your sine exemple. Can't succeed with various code modifications. What am I doing wrong?Hey Ben, thanks for your comment and please pardon the late reply. Your sanity check with the duplication is very good, that makes perfect sense. My suspicion would be that the update frequency is too high for two registers, that is the Arduino is still busy shifting out when the next update cycle starts. I’d try to debug that by lowering the update frequency. Hope that helps!
Hi Timo, Great library and it works perfectly so far.
I’m using it to control 8 LEDS fading up and down and I would like to add 5 more using the Arduino Nano’s PWM pins (5,6,9,10,11). However, Pin 9 and 10 don’t work as expected with the library running. I think it has something to do with your library using Timer 1 to control the interrups.
Is there a way to use your library AND all 5 PWM pins (5,6,9,10,11) at the same time ?
At the end of your article you discuss custom timers, but I’m afraid this is above my current skill level. A little help would be much appreciated. How can I use #define ShiftRegisterPWM_CUSTOM_INTERRUPT to make this work?
Thanks and all the best,
Hey Simon, thanks for your nice comment! I am honestly a little bit surprised to hear that pins 9 and 10 do not work in PWM mode. The library should not be using these pins and interrupts are (as far as I know) generally not “disabling” or affecting the PWM functionality of these pins either. I’m afraid I cannot help here, also the analogWrite docs do not contain any information on interference with timer interrupts. If you happen to figure it out, please share your learnings here. 🙂
Hi Simon,
I have the same issue as you. if Pin 9 is attached the sketch will not run anymore, and pin 10 don’t work at all.
Have you found a solution?
Best,
Carl
Thanks Timo for your comments.
Unfortunately I never found a solution and was able to not have to use those two pins.
Thanks again and all the best!
Hi Timo,
I like the library because it allows me to control my LEDs. However I am running into a problem when I want to control the pins without PWM, the pwm control overwrites anything I try to write to the pins. Is there any way to turn off the pwm control?
Hello. Does it work for esp32?
Hi Timo, Could you help to advise, we should edit and load the program on to Attiny24 or Attiny45?
It complies fine when I select UNO, but gives several errors when I have Digispark (Default – 16.5mhz) selected. Here is the complete message:
Arduino: 1.8.12 (Windows 10), Board: “Digispark (Default – 16.5mhz)”
In file included from C:\Users\PowerUser\Documents\Arduino\libraries\ShiftRegister-PWM-Library\examples\sine\sine.ino:8:0:
C:\Users\PowerUser\Documents\Arduino\libraries\ShiftRegister-PWM-Library\src/ShiftRegisterPWM.h: In member function ‘void ShiftRegisterPWM::update()’:
C:\Users\PowerUser\Documents\Arduino\libraries\ShiftRegister-PWM-Library\src/ShiftRegisterPWM.h:37:39: error: ‘PORTD’ was not declared in this scope
#define ShiftRegisterPWM_LATCH_PORT PORTD
^
C:\Users\PowerUser\Documents\Arduino\libraries\ShiftRegister-PWM-Library\src/ShiftRegisterPWM.h:46:48: note: in expansion of macro ‘ShiftRegisterPWM_LATCH_PORT’
#define ShiftRegisterPWM_toggleLatchPinTwice() ShiftRegisterPWM_LATCH_PORT ^= ShiftRegisterPWM_LATCH_MASK; ShiftRegisterPWM_LATCH_PORT ^= ShiftRegisterPWM_LATCH_MASK
^
C:\Users\PowerUser\Documents\Arduino\libraries\ShiftRegister-PWM-Library\src/ShiftRegisterPWM.h:126:5: note: in expansion of macro ‘ShiftRegisterPWM_toggleLatchPinTwice’
ShiftRegisterPWM_toggleLatchPinTwice();
^
In file included from C:\Users\PowerUser\Documents\Arduino\libraries\ShiftRegister-PWM-Library\examples\sine\sine.ino:8:0:
C:\Users\PowerUser\Documents\Arduino\libraries\ShiftRegister-PWM-Library\src/ShiftRegisterPWM.h: In member function ‘void ShiftRegisterPWM::interrupt() const’:
C:\Users\PowerUser\Documents\Arduino\libraries\ShiftRegister-PWM-Library\src/ShiftRegisterPWM.h:139:39: error: ‘ShiftRegisterPWM::UpdateFrequency’ is not a class or namespace
this->interrupt(ShiftRegisterPWM::UpdateFrequency::Medium);
^
C:\Users\PowerUser\Documents\Arduino\libraries\ShiftRegister-PWM-Library\src/ShiftRegisterPWM.h: In member function ‘void ShiftRegisterPWM::interrupt(ShiftRegisterPWM::UpdateFrequency) const’:
C:\Users\PowerUser\Documents\Arduino\libraries\ShiftRegister-PWM-Library\src/ShiftRegisterPWM.h:155:5: error: ‘TCCR1A’ was not declared in this scope
TCCR1A = 0; // set TCCR1A register to 0
^
C:\Users\PowerUser\Documents\Arduino\libraries\ShiftRegister-PWM-Library\src/ShiftRegisterPWM.h:156:5: error: ‘TCCR1B’ was not declared in this scope
TCCR1B = 0; // set TCCR1B register to 0
^
C:\Users\PowerUser\Documents\Arduino\libraries\ShiftRegister-PWM-Library\src/ShiftRegisterPWM.h:187:21: error: ‘WGM12’ was not declared in this scope
TCCR1B |= (1 << WGM12); // turn on CTC mode
^
C:\Users\PowerUser\Documents\Arduino\libraries\ShiftRegister-PWM-Library\src/ShiftRegisterPWM.h:188:5: error: 'TIMSK1' was not declared in this scope
TIMSK1 |= (1 < Preferences.
It is not possible to include this library and compile with a platform that is not compatible with AVR, such as esp boards to my knowledge.
Hey I’m trying to use this library with AltSoftSerial library but I can’t compile. I’ve tried the custom timer example but still doesn’t work with AltSoftSerial. Any suggestions?
https://github.com/PaulStoffregen/AltSoftSerial
Hello. I’m trying to use this library on a Mega 2560 with six shift registers using PWM pin 8 as data pin, PWM pin 9 as latch pin and PWM pin 10 as clock pin and I can’t get it to work. I have set the following, but can’t get it to work:
I think the mask settings may be incorrect but I can’t find anything on the precise settings. Any help would be much appreciated.
Hi Roger, I don’t know the Mega’s register names by heart, but I assume you double checked them. What I would try is getting it to work with a single shift register first. Six seem like a lot to me and there is a good chance that the ISR takes too long to terminate, so the microcontroller will end up doing nothing effectively. Please let me know whether you can get it to run for a single shift register. 🙂
Hello Timo and thanks for th ereply
I tried with one register only, exactly as per your instructions, and that didn’t work either. I think the problem is with the MASK entries. I am not sure they are mapped correctly. I’ve gone through 1,2,3 then 3,4,5 then 4,5,6 and so on using trial-and-error and it still doesn’t work, even with just one register.
Hi Roger. I think you want the masks to be powers of two. Sorry, I overlooked that at first. Try going with
1
,2
, and4
, for example. You can also write them in binary, that makes it more apparent (but means exactly the same):0B00000001
,0B00000010
, and0B00000100
.Thanks for that, Timo, but unfortunately it didn’t work.
I’ve tried shifting the bits too, so 0B00000001, 0B00000010, and 0B00000100 then 0B00000010, 0B00000100, and 0B00001000 then 0B00000100, 0B00001000, and 0B00010000 and so on, but it will still do nothing.
I used your loop:-
for (uint8_t i = 0; i < 8; i++) {
uint8_t val = (uint8_t)(((float)
sin(millis() / 150.0 + i / 8.0 * 2.0 * PI) + 1) * 128);
sr.set(i, val);
}
to test it and nothing happens.
when I do a normal:-
digitalWrite(9,LOW); shiftOut(8,10,MSBFIRST,B11111111); digitalWrite(9,HIGH);
it lights the eight LEDs on the first shift register, so I know the connections are all working.
This is a real head-scratcher!
Hi Timo,
I framed a picture and put 20 LEDs on it. To control them I used three shift registers and transistor arrays. For testing I used your sine code and it works as intended. I’m new to programming so my question is, how can I easily change the speed and the brightness? (so that the values never go to negative and the LEDs always glow a bit) Hope you can help.
Hi Daniel! In the sine example the relevant line is number 24:
The value
150.0
controls the speed. In order to change the minimum brightness you can change the code to the following and control the minimum withminBrightness
:I haven’t tested that though… I hope it works. 🙂
Thank you for the quick help! It works perfectly, just one more question. How can I add maximum brightness with a float value as well? 🙂
Hi Timo,
What is maximum output frequency on 11 daisy-chained 74hc595’s?
I need at least 20 kHz on 88 output pins.
Thank you Timo for the great library! This tutorial is really great, the code works really awesome!
One way to make this even faster would be to use the Arduino’s SPI interface which is also supported by the SN54HC595. Via SPI, the arduino can transfer 1 byte in roughly 1µs, which really boosts the performance of the library. With 6 SN54HC595, SPI enables 100 Hz update frequency with full resolution or 1.6kHz at a resolution of 16. The changes required are really minimal.
### 1: Connect
Arduino SCK (pin 13) to SRCLK (pin 11) of the 74HC595
Arduino MOSI (pin 11) to SER (pin 14) of the 74HC595
Latch can stay where it is.
### 2: In ShiftRegisterPWM.h, include the SPI header and change the update routine
Hey, thanks a lot for pointing this out. It’s a great idea (because performance surely is a limitation of the lib right now). If you have time feel encouraged to open a pull request in the repo https://github.com/Simsso/ShiftRegister-PWM-Library/pulls. Cheers!
Unfortunately, I do not have GIT set up. The code got a bit messed up, don’t know how it happened. SPI.h should be included.
SPI also opens up the possibility to decrease OCR1A a bit if only one register is used since the interrupt routine is shorter. Values down to 150-170 work for me which is yet another factor 2.
Hello,
I am trying to figure out how to change the shift register pins to non-PWM-capable Arduino pins, as I would like to have some PWM pins still available on the Arduino. The only pin change that works is the “CustomPins” Example included in the library. Here’s the pins I would like to change to:
Data – D2
Clock – D4
Latch – D5