pinMode - INPUT_PULLUP correct set up

I'm having a little difficulty interpreting how to use pinMode and the internal pull up resistors from the documentation. I'm not sure the following set up is correct.

The pins have quite different functions.

Is the use of the internal pull up resistors required for pin1 and pin2. They are not required to provide current as in powering an LED. They are connected to voltage driven switches (e.g., the mosfet gate)?

After reading the documentation I think pin1 and pin2 should possibly be INPUT_PULLUP to avoid a floating pin and interference from nearby sources.

Thinking ahead - analog pins connected to sensors should also be INPUT_PULLUP - not sure?

A bit confused?

void setup()
{
pinMode(BUTTON, INPUT); // connected to a simple pushbutton with external pull down resistor

pinMode(pin1, OUTPUT); // driving logic level mosfet gate - protected by series resistor

pinMode(pin2, OUTPUT); // switches on 5pin Murata mini smps voltage regulator

}

Use pinMode (pinX, INPUT_PULLUP);

  • anytime you are using a switch/button that connects the pin the Gnd when pressed
  • on analog inputs where the source can overcome the 30K to 50K pullup resistance and you don't want the input to float around; or use a 100K pullup and 100k pulldown to hold the pin at 2.5V, say for measuring an AC signal coming in (audio, generally). The audio would be connected thru say a 1uF capacitor to block out any DC level and let the pin see 2.5V +/- 2.5V (or 0 to 5V total).
  • on unused analog and digital inputs so they don't float around and switch from high to low and back needlessly.

Analogs don't use pull-ups.

pinMode(BUTTON, INPUT_PULLUP); // connected to a simple pushbutton with external pull down resistor

Most older example of code used:

pinMode ( X, INPUT );
digitalWrite ( X, HIGH );

This is the same as

pinMode ( X, INPUT_PULLUP );

INPUT_PULLUP is probably a little less code and probably faster.

Do note that if the pin is to be bidirectional,
and you set it to output and low, you have to set it
back to INPUT_PULLUP when receiving data, such as many of the 1 wire
type devices use ( Specific libraries do this for you ).
Dwight

That clears up my understanding of pinMode with digital pins, but I'm not clear about analog pins.

LarryD indicates that analog pins don't have pull up resistors. However. I have read elsewhere, similar comments to CrossRoads about the use of pull up resistors with analog pins.

Is this just a difference in hardware on different boards?

They do have pull-up resistors.
You do not need to use them when you use your analog inputs for reading voltages.

"INPUT_PULLUP is probably a little less code and probably faster."

Incorrect reasoning.

As pointed out , but apparently needs to be reinforced, it is a HARDWARE configuration / function and its code implementation and speed is immaterial.

These are processor internals and code is just enabling them.

On lighter note - it is digital , ones and zeros , not "probably" ones and zeros.

Using correct terminology is what makes you real computer geek.

Have fun.
Jim

LarryD:
They do have pull-up resistors.
You do not need to use them when you use your analog inputs for reading voltages.

Thanks.

You have to set 2 registers to change both pin state and direction.

One is PORTx where x is the port A,B,C,D,... depends on which AVR how many you get.

One is DDRx, the port data direction register.

The 2 lines of the old way set each register --but-- since the Arduino functions are used there is safe-ing going on to protect beginners, costs 5x the cycles of directly setting the registers, something you can do safely if you've taken precautions.

http://playground.arduino.cc/Learning/PortManipulation

Why use port manipulation?

From The Bitmath Tutorial

Generally speaking, doing this sort of thing is not a good idea. Why not? Here are a few reasons:

The code is much more difficult for you to debug and maintain, and is a lot harder for other people to understand. It only takes a few microseconds for the processor to execute code, but it might take hours for you to figure out why it isn't working right and fix it! Your time is valuable, right? But the computer's time is very cheap, measured in the cost of the electricity you feed it. Usually it is much better to write code the most obvious way.
The code is less portable. If you use digitalRead() and digitalWrite(), it is much easier to write code that will run on all of the Atmel microcontrollers, whereas the control and port registers can be different on each kind of microcontroller.
It is a lot easier to cause unintentional malfunctions with direct port access. Notice how the line DDRD = B11111101; above mentions that it must leave pin 1 as an input pin. Pin 1 is the receive line on the serial port. It would be very easy to accidentally cause your serial port to stop working by changing pin 1 into an output pin! Now that would be very confusing when you suddenly are unable to receive serial data, wouldn't it?

So you might be saying to yourself, great, why would I ever want to use this stuff then? Here are some of the positive aspects of direct port access:

If you are running low on program memory, you can use these tricks to make your code smaller. It requires a lot fewer bytes of compiled code to simultaneously write a bunch of hardware pins simultaneously via the port registers than it would using a for loop to set each pin separately. In some cases, this might make the difference between your program fitting in flash memory or not!
Sometimes you might need to set multiple output pins at exactly the same time. Calling digitalWrite(10,HIGH); followed by digitalWrite(11,HIGH); will cause pin 10 to go HIGH several microseconds before pin 11, which may confuse certain time-sensitive external digital circuits you have hooked up. Alternatively, you could set both pins high at exactly the same moment in time using PORTB |= B1100;
You may need to be able to turn pins on and off very quickly, meaning within fractions of a microsecond. If you look at the source code in lib/targets/arduino/wiring.c, you will see that digitalRead() and digitalWrite() are each about a dozen or so lines of code, which get compiled into quite a few machine instructions. Each machine instruction requires one clock cycle at 16MHz, which can add up in time-sensitive applications. Direct port access can do the same job in a lot fewer clock cycles.

Share

GoForSmoke:
You have to set 2 registers to change both pin state and direction.

One is PORTx where x is the port A,B,C,D,... depends on which AVR how many you get.

One is DDRx, the port data direction register.

The 2 lines of the old way set each register --but-- since the Arduino functions are used there is safe-ing going on to protect beginners, costs 5x the cycles of directly setting the registers, something you can do safely if you've taken precautions.

Arduino Playground - HomePage

An interesting post and article.
Thanks.

Jim

I've also written code where I had to drop all use of pinMode and replace with writes to the registers, so that it doesn't have to include pinMode(), saving the 170 bytes that took.

It's more than 5x slower, too. It's not just the interrupt safety, it's the lookup to convert pin numbers to port and bit. Whereas writing a register is really fast

If you only do pinMode once in setup, how is that 5x slower? Or did you mean digitalWrite() vs direct port manipulation in general? I often use that for speed also, such as:

PORTD = PORTD & 0b11111011; // clear D2 as chip select, or shift register output clock
SPI.transfer(dataArray[0]); // send byte
PORTD = PORTD | 0b00000100; // set D2

julyjim:
"INPUT_PULLUP is probably a little less code and probably faster."

Incorrect reasoning.

As pointed out , but apparently needs to be reinforced, it is a HARDWARE configuration / function and its code implementation and speed is immaterial.

These are processor internals and code is just enabling them.

On lighter note - it is digital , ones and zeros , not "probably" ones and zeros.

Using correct terminology is what makes you real computer geek.

Have fun.
Jim

If one is running a 1 wire serial where one is both changing
the direction and the value, the speed may not be immaterial.
I assume that INPUT_PULLUP is written at a low level and
only has to look up the pin mapping once, while:

pinMode( x, input );
digitalWrite( x, LOW );

has two separate calls.
You are also assuming that these operations are only used
once during setup(). This is not true. They have purpose
other place within code.
Dwight

DrAzzy:
I've also written code where I had to drop all use of pinMode and replace with writes to the registers, so that it doesn't have to include pinMode(), saving the 170 bytes that took.

It's more than 5x slower, too. It's not just the interrupt safety, it's the lookup to convert pin numbers to port and bit. Whereas writing a register is really fast

It's the digitalRead that I've measured as 5x slower in a while loop with enough to keep the compiler from optimizing the test away.

I was going to write that using setMode() once and then doing direct reads or writes is not bad, but 170 BYTES just for that routine? Eee-yiii!

Learning the port hardware enough to safely operate the registers seems well worth the RAM savings as well as the speed. I can recommend the AVR chip docs as a reference to go with practice and tutorials.

A nice enhancement might be to optimize these
I/O operation when the port number is a constant.
Many cases it is a fixed value.
Dwight

dwightthinker:
A nice enhancement might be to optimize these
I/O operation when the port number is a constant.
Many cases it is a fixed value.
Dwight

I use pointers to the port registers. The compiler will optimize my code right down to using registers.

Have you seen how many general-use registers the AVR core has? Or that they all do "everything"?

Not sure if I should start another thread :o

Board is a Teensy 2.0 (Teensyduino)

All pins in use, except for the LED, were set to INPUT_PULLUP. Similarly, pins not in use were listed as global variables and set to INPUT_PULLUP. (an array might be better here)

At start the sketch runs as designed - output to OLED is as expected. After a minute or so the sketch seems to freeze and outputs rubbish. For example, the temperature readout on the OLED goes to 50.00, which tends to indicate that the analog pin is not reading the sensor. Other readings are also screwy.

Not sure what follows is the right way of setting pull up resistors while also avoiding variable conflicts later in the sketch.

//pins in use - there are many more

#define LED 11

#define pin1 1
#define pin2 2

//pins not in use - there are many more

#define pin3 3
#define pin4 4

void setup() {

// pins in use
pinMode(LED, OUTPUT);
pinMode(pin1, INPUT_PULLUP);
pinMode(pin2, INPUT_PULLUP);

// and all the other pins except for analog pins and the SCL and SDA for the OLED?

//pins not in use
pinMode(pin3, INPUT_PULLUP);
pinMode(pin4, INPUT_PULLUP);

// many more pins as well
}

void loop() {}

Things that come to mind are; the original sketch only referenced the pins in use as global variables and pinMode. By adding a list of unused pins (#define) there could be a conflict of variables later in the body of the code? Reading the documentation, perhaps I should be using 'const int' instead of #define. If this is the case finding the issue will not be easy - for me anyway.

I don't want to risk running the sketch again until I get a better grasp of this.

Alternatively...

//pins in use - there are many more

#define LED 11

#define pin1 1
#define pin2 2

//pins not in use - there are many more

const int pin3 3
const int pin4 4

void setup() {

// pins in use

pinMode(LED, OUTPUT);
pinMode(pin1, INPUT_PULLUP);
pinMode(pin2, INPUT_PULLUP);

// and all the other pins except for analog pins and the SCL and SDA for the OLED?

//pins not in use

pinMode(pin3, INPUT_PULLUP);
pinMode(pin4, INPUT_PULLUP);

// many more pins as well

void loop() {}
}

If the pin is not used then leave it at the default INPUT LOW condition.
As long as you don't read it, it is effectively neutral.

DrAzzy:
It's more than 5x slower, too. It's not just the interrupt safety, it's the lookup to convert pin numbers to port and bit. Whereas writing a register is really fast

You are off by an order of magnitude.
A bit clear/set in an AVR register is a single instruction that runs in 2 cycles.
2 clocks at 16mHz where each clock tick 62.5ns for a total of 125ns to set/clear a bit.

digitalWrite()/digitalRead() take anywhere from 4.5us to 7us depending on the version of the IDE.
(the newer IDEs are slower, but IDE 1.6.11 got a little bit faster)

The typical time is about 6us. or close to a 50x difference is time.

The crappy thing about the Arduino digitalXX() routines that causes them to be so slow has more to do with the actual coding than what the API needs to do.
i.e. there are ways to make the same API functions MUCH faster by simply writing better code.
In fact if you run the Teensy boards, they come with a re-written core that will perform just as fast as direct port i/o (since that is what it is doing), if all the arguments are constants vs using variables.
But even when using variables it will be MUCH faster than the stock IDE AVR core code.

Another option is to do indirect port i/o. This is typically about 75-80% as fast as doing direct register i/o reads/writes but is completely portable. To do this, you fetch the register pointers and bit masks up front. Then use the pointers and bit masks rather than calling the digitalXX() routines which look up the information every single time.
You do have to make sure to mask interrupts when updating registers to ensure atomicity but it is still very much a big win over the AVR digitalXX() functions.

Ideally the digitalXX() functions in the AVR core should have been re-written to be better so that everyone could get much faster i/o, but the arduino.cc developers would never accept any code updates.

To get the ultimate speed, particularly on other non AVR processors, the API semantics need to be changed.
From digitalWrite(pin, value) to something like digitalsetPinHIGH(pin), digitalsetPinLOW(pin)
This allows taking advantage of more information at compile time and the ability to take advantage of smarter hardware registers that are uses in many of the other processors. On more modern processors this could turn into a single inline instruction.
The current API semantics punish the other better processors since they can't take advantage of their better h/w.

--- bill