Arduino Uno port manipulation, single command to invert two ports D4&D5

Hello everyone!

Is it possible to invert digital output port 4 and 5 with a single command to spare time?

An alternative would be to write/set the pin 4 and pin 5 on different logic levels with a single command if possible?

While not touching the other pins from the same port register.

i tried to build a pulse which is inverted on pin 5, the uncommeted command (EXOR?) doesn't work the port is not written at all :frowning:

void setup(){
pinMode(4,       OUTPUT); 
digitalWrite(4, HIGH); 
pinMode(5,       OUTPUT); 
digitalWrite(5, LOW);
}

void(loop){
delay(500);
PORTD = PORTD | B00010000;                  //(7)(6)(5)[4](3)(2)(1)(0)
 //PORTD = PORTD ^ B11001111;            //(7)(6)[5][4](3)(2)(1)(0)
delay(500);
PORTD = PORTD & B11101111;                    //digitalWrite(5, LOW);
//PORTD = PORTD ^ B11001111;                 //(7)(6)[5][4](3)(2)(1)(0)
}

Port Registers might interest you

PORTD = PORTD ^ B00110000;

i've never directly access registers on an Arduino.

Writing a 1 bit to PIND will invert the level of the corresponding output.

@david_2018
But can i write 2 pins with single command? i thought it would set/reset just the pin specified not more than one

PIND - The Port D Input Pins Register - read only

aye read only :-7

A couple of quotes from the datasheet http://ww1.microchip.com/downloads/en/DeviceDoc/ATmega48A-PA-88A-PA-168A-PA-328-P-DS-DS40002061A.pdf

Three I/O memory address locations are allocated for each port, one each for the Data Register – PORTx, Data
Direction Register – DDRx, and the Port Input Pins – PINx. The Port Input Pins I/O location is read only, while
the Data Register and the Data Direction Register are read/write. However, writing a logic one to a bit in the
PINx Register, will result in a toggle in the corresponding bit in the Data Register. In addition, the Pull-up Disable
– PUD bit in MCUCR disables the pull-up function for all pins in all ports when set.

14.2.2 Toggling the Pin
Writing a logic one to PINxn toggles the value of PORTxn, independent on the value of DDRxn. Note that the
SBI instruction can be used to toggle one single bit in a port.

PIND = B00110000; //toggle pins D5 and D4 simultaneously

Meins321:
Arduino Reference - Arduino Reference

PIND - The Port D Input Pins Register - read only

aye read only :-7

Not the first time an Arduino reference page is incorrect or incomplete.

@david_2018
wow thanks!
i did try it on my uno and on the fist try it look like it did not invert the output because my valve would not move :slight_smile:
Turns out there is some minimal pressure needed to make it move at all because it lubricates with air

@oqibidipo
That's something i did not expect :o well it is possible

I do use these port manipulations to be exact as possible in opening pneumatic valves to sort glas cann that slide infront of a lightbar that is connected to the interrupt pin 2 or 3 on arduino uno.

i did not expect this "kids"-toy to be this powerful and fast but it worksjust out of curiosity

Meins321:
I do use these port manipulations to be exact as possible in opening pneumatic valves to sort glas cann that slide infront of a lightbar that is connected to the interrupt pin 2 or 3 on arduino uno.

I doubt that a pneumatic valve moves very far in 20 microseconds. That's about what a digitalWrite() takes.

yes it does not move very far but if you open it with an interrupt and keep it open for 50ms, then close it does move.

The error adds up if you cycle it over a longer period of time or if you want a litte preciser timing from the user defined side.

200x20 micro = 4 miliseconds "longer" time you get maybe later if used delay(ms)?

i have found a library which makes timing easier for everyone:

I will try to use that instead of delay to get it precise and fast

I'm not really understanding why you think there would be some additive error when you are opening a valve based on an interrupt input then closing it a specific time later. As long as the value open time is less than the shortest interval between interrupts, then the timing for each valve opening would be totally independent and not additive.

Your initial post was a bit misleading, you asked how to "invert digital output port 4 and 5 with a single command", that implies you do not care about the actual level of the output pins, only that you want the levels to change. You actually want a specific output level, so using PIND is totally inappropriate in this case.

My approach to this would be to have the interrupt set the outputs to operate the valves, and also save the current value of millis(), then the main code in loop() will deactivate the valve the specified interval after the activation, using the value of millis() saved in the interrupt as a reference.