Toggling a pin state

I'm trying to toggle the pin state of a digital pin set to OUTPUT.

This doesn't seem to work:

digitalWrite(pinToToggle, !digitalRead(pinToToggle));

Since digitalRead() seems to always return LOW.

What am I doing wrong?

Dumb question, but is the pin set to OUTPUT?pinMode(pinToToggle, OUTPUT);

Probably the answer, because this works fine:

void setup() {
  pinMode(2, OUTPUT);
}

void loop() {
  digitalWrite(2, !digitalRead(2));
  delay(500);
}

Some possible toggle code:

int prevState = LOW;

void loop()
{
   int currState = digitalRead(somePin);
   if(currState != prevState)
   {
      // A transition occurred (from pressed to released or from released to pressed)
   }
   prevState = currState;
}

Thank you

boolean toggle = false;

void setup() { pinMode(13, OUTPUT); }

void loop() { toggle = !toggle; digitalWrite(13,toggle); delay(500); }

Storing the state is unnecessary. Just do like Arrch. Reading the state should just work fine.

I searched this forum topic looking for an implementation of pin toggling by writing a "1" to the corresponding bit in the PINx register as described in the ATMega328 datasheet. I did not find it here; so, I wrote my own and tested it.

This inline assembler instruction will toggle PORTC PIN1. Of course, you must enable the port/pin as output.

asm ("sbi %0, %1 \n": : "I" (_SFR_IO_ADDR(PINC)), "I" (PINC1));

It's really fast too; it executes in 2 cpu clocks.

1 Like

So you were not able to find this in 14.1? "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."

Used thusly for example: PIND = PIND | 0b00000100; // toggle D2

PIND = PIND | 0b00000100; // toggle D2

Is indeed a nice trick to know and executes in 2 clocks cycles but of course that only works if you are using one of the arduino with PIND.

For those reading French I have posted some considerations and experiment on toggling pins on a uno type or a zero type arduino is discussion http://forum.arduino.cc/index.php?topic=423573.0

Yes, you have to select ports that are in the microcontroller you are using. I only write code for 3 generally (328P, 1284P, 2560), it's easy to see which ports are available right at the start of the datasheet.

CrossRoads: Used thusly for example: PIND = PIND | 0b00000100; // toggle D2

The OR is not necessary,

PIND = 0b00000100;

does the trick.

EDIT

Actually PIND = PIND | 0b00000100; does not just toggle D2, it toggles every pin that is high, i.e. every pin except D2 will be low and D2 is toggled.

I don't know why, but I seem to have had poor experience with just PIND = 0b00000100; hence my use of PIND = PIND | 0b00000100;

And "does not just toggle D2, it toggles every pin that is high, i.e. every pin except D2 will be low and D2 is toggled." That has not been my experience. Or, if other bits toggled, it didn't impact anything I was doing so it wasn't noticed.

Of course, if you want to Arduino-ize it:

void digitalToggle(uint8_t pin)
{
    uint8_t timer = digitalPinToTimer(pin);
    uint8_t bit = digitalPinToBitMask(pin);
    uint8_t port = digitalPinToPort(pin);
    volatile uint8_t *out;

    if (port == NOT_A_PIN) return;

    if (timer != NOT_ON_TIMER) turnOffPWM(timer);

    out = portInputRegister(port);

    uint8_t oldSREG = SREG;
    cli();

    *out |= bit;

    SREG = oldSREG;
}

Basically a modified version of digitalWrite that writes to the InputRegister instead of OutputRegister.

I would never do that to myself! Using pinMode to make the pin an OUTPUT in setup() and then PIND command in loop is all I've ever done. With while(1){ PIND = PIND | 0b00000100; } in loop() (to avoid the delays from cycling thru loop, which adds some # of microseconds) I think I showed 8 MHz toggling on a 'scope. I have a topic about various methods and the resulting speeds seen. Calling it as a function would only slow it down more.

I would never break the abstraction layer unless I really need to. So I would prefer the way of Jiggy-Ninja. Heck, most of the time I just make the toggle on top op digital Read/Write because speed is not that critical.

void inline digitalToggle(int pin){
  digitalWrite(pin, !digitalRead(pin));
}

while(1){ PIND = PIND | 0b00000100; } in loop() (to avoid the delays from cycling thru loop, which adds some # of microseconds) I think I showed 8 MHz toggling on a 'scope.

I believe that code actually benchmarks at 2.6 Mhz. 8 MHz requires the hardware timers.

http://forum.arduino.cc/index.php?topic=330098.0

CrossRoads: I would never do that to myself! Using pinMode to make the pin an OUTPUT in setup() and then PIND command in loop is all I've ever done. With while(1){ PIND = PIND | 0b00000100; } in loop() (to avoid the delays from cycling thru loop, which adds some # of microseconds) I think I showed 8 MHz toggling on a 'scope. I have a topic about various methods and the resulting speeds seen. Calling it as a function would only slow it down more.

Not possible. 8MHz on a 16 MHz clock would require the pin to toggle every clock cycle. The shortest branch instruction in the instruction set takes 2 clock cycles. 3 clock cycles per toggle (1 for SBR, 2 for RJMP) is 6 clock cycles per output period. 1/6th of the 16 MHz clock is 2.67 MHz, which matches what cattledog says.

itt: How many ways can you toggle the position of a large stick in the motion of beating a dead horse?

I looked for my topic where I tested different non-PWM ways, I can't find it. 2+ MHz certainly makes sense tho based on having to read & execute some instruction over & over.