I have a system that starts running at a low input, to be controlled by an Arduino Nano Every board.
After power-up the output of the Arduino is set as input, thus high impedance, the internal pull up of the system keeps it's input high.
In setup() of the Arduino I want to set my output to OUTPUT, but I don't want the system to start yet.
Method 2 does not affect the Output Register, and rightfully so.
Method 1 doesn't work because Arduino thinks I want to set the pull up resistor. Setting the mode to output hereafter will pull the output down, with undesired results.
So here is my question: how can I keep the output high, no pulse?
I might miss something, but even if I have never used a nano Every, I can't really get your point: if the other system starts running at low input I see it has an internal pullup, so why do you need to also set a pullup on the Arduino side?
Or don't just use an external (47k?) "physical" pullup from the pin and +5V to prevent it from floating?
Designer: "Boss, I found a neat feature that our customers surely will appreciate: internal pull up resistors. But to do this I want to reorganize the registers."
Boss (angry): "Have you any idea what messing with the registers is gonna cost us?"
Note: changing registers might break some of the existing software, the customers affected will not appreciate that.
So they found a way: use the Output Register for something it wasn't intended for. They used it to switch the pull up resistor when the pin is input.
Note: they also found a way to use the Input Register for something else: writing a 1 to it toggles the Output Register, but Arduino doesn't support that feature.
A quarter of a century later, another boss at last saw the necessity for innovation and a new line (with the 4809) was produced.
And now we're waiting for Arduino to see the light, because they still think 328 style. So when I issue the statement that should set the Output Register they still think that I want to set the pull up resistor, while that can be done with it's own statement.
Always a problem when you create an API based on a specific hardware, and then find it is not generic. Change the API and break existing code, or propagate the hardware specific feature?
It seems the author had some doubt, but went ahead with the side effect anyway :
/* Old implementation has side effect when pin set as input -
pull up is enabled if this function is called.
Should we purposely implement this side effect?
*/
Personally, I would have added OUTPUT_LOW and OUTPUT_HIGH to the API.
It's quite simple: if I switch to output mode I don't want the output to be pulled low. Using the Arduino language I can achieve that with a 328. But with a 4809 I can't.
Yes, I can use direct register access, but I feel it should be possible like it is in a 328.
Wasn't that "side effect" the main effect before there was a pinMode command?
Here it is:
The pullup resistors are controlled by the same registers (internal chip memory locations) that control whether a pin is HIGH or LOW. Consequently, a pin that is configured to have pullup resistors turned on when the pin is an INPUT, will have the pin configured as HIGH if the pin is then switched to an OUTPUT with pinMode(). This works in the other direction as well, and an output pin that is left in a HIGH state will have the pullup resistors set if switched to an input with pinMode().
Prior to Arduino 1.0.1, it was possible to configure the internal pull-ups in the following manner:
pinMode(pin, INPUT); // set pin to input
digitalWrite(pin, HIGH); // turn on pullup resistors
That doc says it should work exactly like you want:
"Consequently, a pin that is configured to have pullup resistors turned on when the pin is an INPUT, will have the pin configured as HIGH if the pin is then switched to an OUTPUT with pinMode()."
No, the doc describes what happens in the 328, and ignores the differences in other processors like the 4809.
What I want is not possible using the Arduino language for the 4809.
It may well be exactly what happens on the 328, but it also describes pullup behavior on other than 328 AVRs and the due.
I would read it as that the doc describes the API. And that the implementation on the 4809 is in error.
The primary/natural use of digitalWrite(pin,level) is to set (or stage) the output level, and the side effect of setting the output level on the 328-like processors is that it happens to set the pullup resistor.
They tried and failed. In my view, the clean implementation is to make the digitalWrite do what it must do, without side effect. The function of that side effect has it's own, designated statement. I can imagine a place for implementing the side effect in emulation mode.
The second illustration is correct in that the cathode of the diode (marked with a band) is connected to your "other system". This will stop any unwanted "LOWs" getting to that other system. But its not a pretty solution for what is effectively a software problem.
Clearly, as you have discovered, there is an inconsistency between the Arduino board packages for the Arduino Uno and the Arduino Nano Every because of the way the underlying hardware behaves and, as suggested, you could raise an issue in github: GitHub - arduino/ArduinoCore-megaavr: Arduino Core for the ATMEGA4809 CPU. If you do then Mention this thread because the type of solution proposed by @bobcousins in post #7, where an initial or default state is added to pinMode/output, looks good.