3
\$\begingroup\$

In Arduino Uno, I noticed that when I set a PIN to output, the default initial state is low. Is there a way to set the initial output state to high?

The pinmode documentation supports only input, input_pullup, and output. I wish there is an option for output_pullup. If I put an external 10k Ohm pullup resistor around the output PIN, it does help a little pushing the initial state towards high.

Still, if there is a software based solution (i.e. flash the arduino uno to default output to high), that would be much appreciated.

Thanks for reading

\$\endgroup\$
4
\$\begingroup\$

There is nothing stopping you from writing the output registers (PORTx) before writing the direction registers (DDRx). Unfortunately, the Arduino library functions (pinMode and digitalWrite) have a number of side effects and may or may not work. (Perhaps someone more familiar than I am with the Arduino libs can advise if a digitalWrite followed by a pinMode will work.

So, direct register manipulation can achieve what you want, if @Tom's solution is insufficient (Tom's solution should work in just about every case). First, consult page 77 of the ATmega328 datasheet and note table 14-1.

Assuming a pin starts with the DDR and PORT bits clear: it's a Hi-z input pin. Set the PORT bit, the pin is now an input with a pullup. Now, when you set the DDR bit, the pin goes from an input with pullup directly to a output high.


Edit: trying to better understand what would happen with the following code by reading through wiring_digital.c:

// where p is an Arduino pin, x is the corresponding port,
// and n is the corresponding bit
// pin starts with DDRxn == 0, PORTxn == 0
digitalWrite(PINp, HIGH);
// PORTx |= 1<<n, from line 159
// PORTxn == 1, DDRxn == 0: input pullup
pinMode(PINp, OUTPUT)
// DDRx |= 1<<n, from line 56
// PORTxn == 1, DDRxn == 1: output high

So, it appears that calling digitalWrite before pinMode will do exactly what you want. Ignore the mess about direct register manipulation above.

\$\endgroup\$
  • \$\begingroup\$ Just to add a little, the AVR boots up with all pins defaulting to Tristate, so if you need the high level asserted during reset you should use a pullup, otherwise setting the pins in setup() is the easiest way. If the pin is configured by the bootloader then the solution won't work btw. \$\endgroup\$ – crasic May 2 '16 at 3:35
1
\$\begingroup\$

You can't change the hardware default. There is code that executes at startup that you don't control (there is at least some startup code in ROM inside the processor, and there may also be a bootloader that can be changed but is difficult to modify for you). Sometimes this code may toggle pins in unexpected ways while searching for alternate boot devices or what have you. This has caused me lots of problems at various times in my career, because it is not always well documented by the silicon vendors (low cost 2nd tier vendors).

From your question, it is not clear if the pin you want to use is actively being driven low by the processor, or if it just has a weak pulldown. If it is just a weak pulldown, you can overpower it with a 1k pullup. Also, you can try the ideas previously mentioned. Basically, you need to somehow make sure that the data is set to high BEFORE the direction is set to output in the code you have control over. I don't know much about arduino, but I have dealt with this sort of thing in various microprocessors and it is normally possible to set data before setting direction of an IO pin. Sometimes the same bit that enables the internal pullup also sets the data to 1 for the output.

If the pin is actively being driven low by code you do not have the ability to alter, a pullup is not going to fix the problem. But you might be able to look through documentation (or experiment) and find another pin that does not drive low after reset.

Good luck.

\$\endgroup\$
  • \$\begingroup\$ I'm pretty sure that there is no boot ROM on AVR. \$\endgroup\$ – duskwuff -inactive- May 2 '16 at 3:04
  • \$\begingroup\$ OK. There is still mask rom code which causes the processor to do whatever it does during startup. It is possible for the maskrom code to toggle IO's, in principle. \$\endgroup\$ – mkeith May 2 '16 at 3:17
  • \$\begingroup\$ I'm not certain there is any mask ROM. All indications are that AVR reset and startup is controlled entirely by hardware. \$\endgroup\$ – duskwuff -inactive- May 2 '16 at 3:20
  • \$\begingroup\$ What does it do when it boots up? If it does anything more complex than fetch code from a fixed address and begin executing it, then it probably has mask rom in the processor. Or something very similar. \$\endgroup\$ – mkeith May 2 '16 at 3:30
  • \$\begingroup\$ Resets peripherals, initializes the clock source, and jumps to the reset vector. Nothing that'd be likely to require mask ROM. \$\endgroup\$ – duskwuff -inactive- May 2 '16 at 3:35
0
\$\begingroup\$

While not exactly what you were looking for, adding some extra code into setup() should work:

void setup() {
    pinMode(PINx, OUTPUT); // replace PINx with the pin number
    digitalWrite(PINx, HIGH); //makes PINx high almost immediately (few uS)
    // rest of code
}

There is no problem with performing digital writes or digital reads in void setup(), you can do anything in setup(), but it only executes once. Unless you mean 'go high the instant power is applied' because other than a pullup resistor, I think you may be out of luck

\$\endgroup\$
  • \$\begingroup\$ Technically you can do anything in setup() whenever you want to, it's just a normal C function. The line setup(); is in the main function at the beginning (well after a hidden init() call). \$\endgroup\$ – Tom Carpenter May 2 '16 at 1:15
  • 1
    \$\begingroup\$ I am referring to the moment external power is applied or the moment when the reset button on the board is pushed. it is the time before setup() was called \$\endgroup\$ – Antony May 2 '16 at 2:02
  • \$\begingroup\$ You might be stuck with a pull up, although if you need a strong pull up, you could have a PMOS or PNP pulling the pin high at power on which would be turned off once setup() was run, catch is you'd need TWO IO pins, one for the output and another to disable the pull up (although all pull ups could share a common control). Actually, what about rigging in an inverter? That'd always be high as long as the input was low, would that work? \$\endgroup\$ – Sam May 2 '16 at 2:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.