If you drive them all off the same port you can make them all react at exactly the same time by changing the port output. It’s a bit mind blowing to start with, but once the penny has dropped it’s easier than multiple digitalWrite statements. I used it for driving a stepper motor in half step mode
Good idea, but I’d put it on the back burner for the time being. Not only is it ‘a bit mind blowing to start with’, but the programmer has to get port code absolutely right, and, unlike digitalWrite(), there is no error checking. The computer will silently do as it’s told even if that completely screws up other internal functions! digitalWrite() checks for such nightmears, and, though the program won’t work as expected, digitalWrite() doesn’t cause any weird hard to debug side effects.
Here’s the ATmega328P’s block diagram:
Bottom left is a box labelled ‘Port D (8)’, meaning ‘I am an 8 bit register connected to 8 pins, that do digital Input-Output’. The pins it services are listed on the arrow below – PD0 to PD7. Next diagram shows how they relate to physical pins on an Arduino Nano, not always logically – PB5 is D13:
The advantage of writing directly to PortD is that eight pins will be switched together simultaneously on the next clock tick. Super-fast and synchronised, wonderful, and the code is simple.
DDRD = B11111111; // Set all pins controlled by PORT D to HIGH
DDRD = B0000000; // All pins set LOW
The problem with my DDRD example is that PortD is also connected to Timer/Counter 0, and USART0. (Universal Synchronous/Asynchronous Receiver/Transmitter) As Arduino Nano Pins PD0 and PD1 are dedicated by Arduino to Serial Transmit and Receive, my DDRD code example collides with a system function. Eek – don’t do it by accident! The chip’s other Ports are also shared with other system functions, so proceed with care, and watch out for weird bugs – probably indicate a collision under the bonnet!
Good explanation of how to read and write ports directly here.
Excellent technique, but I was James, I’d save it for later. In his application, I doubt it matters if the second, minute and hour pulses are staggered by a few tens of microseconds.
Also, when speed matters, the DirectIO library is a good compromise. digitalWrite() wastes a lot of time by checking for conflicts every time it’s called. DirectIO checks at compile time, and doesn’t worry thereafter. On the downside, DirectIO isn’t quite as bomb-proof, and it uses a C++ template, which is a step harder to understand in the first place than a function. But easier than writing directly to a port register.
Dave