Why do we use state variables to remember the value of an output pin?

207 views
Skip to first unread message

Michael Shiloh

unread,
Mar 26, 2016, 9:41:18 PM3/26/16
to devel...@arduino.cc
If I'm reading the ATmega328 datasheet correctly, starting on page 76, setting the port as an output only enables the output of the pin register onto the pin itself, but the pin itself is always readable as nothing stands between it and the data bus save the synchronizer and the RPx buffer.

Why then do many Arduino examples, such as Blink Without Delay, use state variables to remember the state of the LED?

As one of my students pointed out,

digitalWrite (13,!digitalRead(13));

works very nicely to change the state of an LED.

One reason I can think of: Perhaps this feature of the ATmega328 is not universal, and may not be found on all microcontrollers. Is this the reason?

Or something else?

I'm always happy to learn new things.
Michael


Tom Igoe

unread,
Mar 26, 2016, 9:47:46 PM3/26/16
to Arduino Developers

For the beginner, seeing a function call inside a parameter is harder to parse. I found when I broke the result out into a state variable, beginners found the code easier to understand.

Tom Igoe
--
sent on the go. please forgive any terseness or typos

--
You received this message because you are subscribed to the Google Groups "Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to developers+...@arduino.cc.

Michael Shiloh

unread,
Mar 26, 2016, 10:05:26 PM3/26/16
to devel...@arduino.cc
Agreed about the function call inside a parameter, but it could be eased with

currentLEDstate = digitalRead(...)
digitalWrite(!currentLEDstate(...)

I just want to understand why things are done a certain way.

Michael

Tom Igoe

unread,
Mar 26, 2016, 10:13:15 PM3/26/16
to Arduino Developers

I've always written my sample code for readability over efficiency. It's been my experience that it's helped a lot in the classroom, and when I've varied from it, it's tended to cause confusion among my students. No reason other than that, really.

I prefer to teach efficiency after I teach the basic concepts. People tend to respond better to learning one idea at a time.

T.

Tom Igoe
--
sent on the go. please forgive any terseness or typos

Michael Shiloh

unread,
Mar 26, 2016, 11:02:13 PM3/26/16
to devel...@arduino.cc
I agree with you 100%: readability over efficiency

I had been telling students that the reason for the state variable was due to inability to know the value at the pin, but now I see I was wrong.

All the best,
Michael

Tom Igoe

unread,
Mar 26, 2016, 11:13:56 PM3/26/16
to Arduino Developers

I think it's fine to do it the way you showed, as long as the person it's written for understands it. If you're teaching the efficiency lesson there, I'd suggest explaining it in comments, to be inclusive.

Personally, I tend to trip over my own experience. Every time I think I can explain a more complex example in an introductory class, I fail. Turns out it doesn't matter that I'm gaining experience when whole new group of beginners comes in, knowing exactly as little as the last year.

Tom Igoe
--
sent on the go. please forgive any terseness or typos

Michael Shiloh

unread,
Mar 26, 2016, 11:20:28 PM3/26/16
to devel...@arduino.cc
Not teaching efficiency. It's never been an issue in student projects. They will sometimes ask about this and I point out that readibility is more important, just like you say.

I only explain complex issues if they ask, and then I like to get it right.

I find that if they are curious about something, they stay engaged if I can take the detour for a little while.

M

Tom Igoe

unread,
Mar 26, 2016, 11:33:24 PM3/26/16
to devel...@arduino.cc
On Mar 26, 2016, at 11:20 PM, Michael Shiloh <m.sh...@arduino.cc> wrote:

Not teaching efficiency. It's never been an issue in student projects. They will sometimes ask about this and I point out that readibility is more important, just like you say.

I’d like to see someone do a good book or tutorial on it, though, for non-beginners. It’d be useful. It’s on the ever-growing to-do. 


I only explain complex issues if they ask, and then I like to get it right.

I find that if they are curious about something, they stay engaged if I can take the detour for a little while.

I think that’s a good approach.


t.

William Westfield

unread,
Mar 27, 2016, 2:47:51 AM3/27/16
to devel...@arduino.cc
> As one of my students pointed out,
> digitalWrite (13,!digitalRead(13));
> works very nicely to change the state of an LED.

1) In fact, this may not work on other architectures, or depending on port settings. PICs are infamous reading the actual value of the pin, rather than the value that was last written. 8051s usually have “open drain” outputs that may read “randomly” when set to “HIGH”...
2) calling digitalRead() is much slower than accessing a state variable. (usually not relevant, but… irrelevant cpu cycle efficiency vs irrelevant memory efficiency?)
3) in some sort of vague, hand-wavy way, I think it’s important that students grasp that the LED state cn shadow a data variable state, rather than just being manipulable as an “LED thing.”

BillW/WestfW

j. eric townsend

unread,
Mar 27, 2016, 3:51:55 PM3/27/16
to devel...@arduino.cc
On 3/26/16 23:33, Tom Igoe wrote:
>
>> On Mar 26, 2016, at 11:20 PM, Michael Shiloh <m.sh...@arduino.cc
>> <mailto:m.sh...@arduino.cc>> wrote:
>>
>> Not teaching efficiency. It's never been an issue in student projects.
>> They will sometimes ask about this and I point out that readibility is
>> more important, just like you say.
>
> I’d like to see someone do a good book or tutorial on it, though, for
> non-beginners. It’d be useful. It’s on the ever-growing to-do.

Here's one part of my swipe file on writing clean code:

http://www.ibm.com/developerworks/rational/library/nov06/pollice/index.html

What I've been doing lately is having students write the comments first
explaining what they do then add the code that matches the comments.

// read the analog pin
// if it is in the upper half turn on the green led
// if it is zero turn on the red led
// if it is zero turn on data pin 1

That also helps *me* figure out what they're trying to do and if they
understand what they're trying to do.

--
J. Eric Townsend
<http://www.flatline.net>
HF: KG6ZVQ
PGP: 0x335E5548 / 75DB 5C22 FD5D F33E B1FA D5BA B429 EA93 335E 5548

Urja Rannikko

unread,
Mar 27, 2016, 4:08:27 PM3/27/16
to devel...@arduino.cc
Just popping by to say these (some partly said before):
1. the digital input might not match the output (input disable stuff,
other arch specific stuff)
2. reading it can be of varying efficiency, but usually needs an
actual I/O access vs. optimization of a variable by the compiler to a
register in the CPU, especially when used in a single function.
3. On recent AVRs, the most efficient way to toggle an output is to
actually write a 1 to the pin register (PINport = _BV(bit); ) (check
the datasheet) - this is obviously totally non-portable.
> --
> You received this message because you are subscribed to the Google Groups
> "Developers" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to developers+...@arduino.cc.



--
Urja Rannikko

Michael Shiloh

unread,
Mar 27, 2016, 4:30:18 PM3/27/16
to devel...@arduino.cc
>> What I've been doing lately is having students write the comments first explaining what they do then add the code that matches the comments.

That is brilliant. I'm going to adopt that. Thanks!

Mikael Patel

unread,
Mar 27, 2016, 6:37:26 PM3/27/16
to Developers
I find teaching from an object-oriented point of view very natural for students. The concept of objects with state and functions is a more higher level of abstraction and allows students to grasp much more of computer science (please see teaching of Smalltalk and Logo as examples). Cosa is built from this software engineering point of view.

Last, I must comment on the methodology below. There is a great historical document on this; http://oberoncore.ru/_media/library/wirth_program_development_by_stepwise_refinement2.pdf

"nihil sub sole novum", Mikael.
To unsubscribe from this group and stop receiving emails from it, send an email to developers+unsubscribe@arduino.cc.

David Zanetti

unread,
Mar 28, 2016, 3:23:25 AM3/28/16
to devel...@arduino.cc
It's bad because it violates the API as documented. digitalWrite() expects one of two constants, HIGH (0x1) or LOW (0x0). The return of digitalRead() bitwise inverted would be (assuming 16-bit int) 0xffff or 0xfffe, and only works as a toggle because the internal implementation discards all but the last bit.

This is undocumented behavior from the API and the devs would be free to change the implementation to be more strict about 0x1 or 0x0, or the student may use another API that has similar constants that may not be so forgiving.

Besides, state variables are a key building block of finite state machines which don't have to depend on IO port behavior.

IMO :)
--
David Zanetti <da...@wetstring.net>
Sent from my Android device with K-9 Mail. Please excuse my brevity.

David Zanetti

unread,
Mar 28, 2016, 3:29:13 AM3/28/16
to devel...@arduino.cc
Ah actually, ignore me, I just realised I mixed up logical and bitwise not. Oops :)

--
David Zanetti <da...@wetstring.net>
Sent from my Android device with K-9 Mail. Please excuse my brevity.

On 27 March 2016 2:40:50 AM GMT+01:00, Michael Shiloh <m.sh...@arduino.cc> wrote:

Tim Leek

unread,
Mar 29, 2016, 8:35:41 AM3/29/16
to Developers
I have (incorrectly) used digitalWrite (13,!digitalRead(13)) in examples because it is a one liner that doesn't require a global state and therefore requires less documentation.

For experienced users it makes the point clearly but for novices it is bad practise.

It doesn't work on some platforms such as the Arduino Zero.

Tim

indigoredster

unread,
Mar 29, 2016, 2:48:30 PM3/29/16
to devel...@arduino.cc
I think it is always good practice to use shadow variables to hold the state of outputs on a port before modification. Modify the shadow then write it out.
This eliminates what is called the "read-modify-write" issue in some MPU architectures were a read of a mixed I/O  port will return the 
physical pins levels. If this is done too quickly, a pin may not settle due to capacitance on the value expected, so the bit read in 
on a byte/word size port which is then modified on another bit then re-written out might change the expected state of the other bit.
This issue is more prevalent in coding operations that constantly change a port pin's direction, as in emulating a rail-limited open collector pin
ie IIC bus
-Lee Studley




--
You received this message because you are subscribed to the Google Groups "Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to developers+...@arduino.cc.

Gabriel Staples

unread,
Mar 29, 2016, 9:42:46 PM3/29/16
to devel...@arduino.cc
This is definitely brilliant, in my opinion. It's how I often-times write code myself as well, as it helps me get my thoughts out and keep the flow of what I'm trying to do, in my memory. It keeps me on track so I don't get lost in the weeds of some of the low-level implementation details. Very good habit in my opinion .


Thank you!

Sincerely, 

Gabriel Staples

Victor Aprea

unread,
Mar 29, 2016, 10:00:38 PM3/29/16
to Arduino Developers
When I read this, the first thing that came into my head was "Comment-Driven-Development" ... then I Googled it, and sure enough, it's a thing :-).

Cheers,
Vic

Victor Aprea // Wicked Device

j. eric townsend

unread,
Mar 31, 2016, 3:44:06 PM3/31/16
to devel...@arduino.cc
Also, encourage students to leave the comments in the code so they can
return to it later and not have to decipher what they were thinking at
3am last week. It also helps when they come to a TA or prof when
they're stuck.

On 3/29/16 21:59, Victor Aprea wrote:
> When I read this, the first thing that came into my head was
> "Comment-Driven-Development" ... then I Googled it, and sure enough,
> it's a thing :-).
>
> Cheers,
> Vic
>
> Victor Aprea // Wicked Device
> victor...@wickeddevice.com <mailto:victor...@wickeddevice.com>
> T: @vicatcu <http://twitter.com/vicatcu/>
>
> On Tue, Mar 29, 2016 at 9:42 PM, Gabriel Staples <panth...@gmail.com
> <mailto:panth...@gmail.com>> wrote:
>
> This is definitely brilliant, in my opinion. It's how I often-times
> write code myself as well, as it helps me get my thoughts out and
> keep the flow of what I'm trying to do, in my memory. It keeps me on
> track so I don't get lost in the weeds of some of the low-level
> implementation details. Very good habit in my opinion .
>
>
> Thank you!
>
> Sincerely,
>
> Gabriel Staples
> www.ElectricRCAircraftGuy.com <http://www.ElectricRCAircraftGuy.com>
> <mailto:developers+...@arduino.cc>.
>
>
> --
> You received this message because you are subscribed to the Google
> Groups "Developers" group.
> To unsubscribe from this group and stop receiving emails from it,
> send an email to developers+...@arduino.cc
> <mailto:developers+...@arduino.cc>.
>
>
> --
> You received this message because you are subscribed to the Google
> Groups "Developers" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to developers+...@arduino.cc
> <mailto:developers+...@arduino.cc>.

indigoredster

unread,
Mar 31, 2016, 5:36:46 PM3/31/16
to devel...@arduino.cc
I think this is a very good way to learn and use in general. I often flesh out what 
I want to do as comments, then fill in the code needed. Then do a cleanup phase 
after it's tested. -Lee

Tom Igoe

unread,
Mar 31, 2016, 5:52:00 PM3/31/16
to devel...@arduino.cc
I agree. I always encourage students to pseudo-code out their ideas in comments and drawings first. It’d be great if we had a tool that could turn those comments into code faster.  Anyone seen examples of this that they really like?

(this would be a good discussion on the teachers list as well)

t.

indigoredster

unread,
Mar 31, 2016, 6:04:23 PM3/31/16
to devel...@arduino.cc
Another oddity I and find very helpful, that some might not agree with, is to put homegrown bookmarks for debug issues
at the end of comments so I can search on them for collection of points to test or that were affected by the debugging. 

I do it like this:

  i += 10    // inc by 10 to move pointer to next group  ntsl113"             which tells me:   "notes to self Lee: This is for Issue113 ..."


Using regex search/replace, I later clear them out( or leave them as needed ) when the issue is resolved. 

Using a good editor with "files" search you can grab these tagged "ntsl..." lines to a history file to document what you did to fix the issue with dates.

Your Initials can work also.

I try to keep the "ID code" short and simple so that other programmers following up on you code don't get irritated if
I don't remove them. Sometimes a pattern of periods is tidier and more covert:  .. ... and will only make sense to you if 
you forget remove them.

I had people come a year later and ask me what "ntsl" was so I went to using the periods. People you are mentoring might emulate
your ID code if you don't explain this to them that it needs to be unique to the coder.

Curious if anyone hates this? I've been using it a long time now.

-Lee

Tom Igoe

unread,
Mar 31, 2016, 6:30:41 PM3/31/16
to devel...@arduino.cc
Interesting.  I see the sense of it. I tend to do something similar with TODO: which some editors will insert and highlight for me. I don’t tend to tie it to issues though, just notes to actually  do something. 

it does bring up a related issue, though, which is how you write when you’re writing just for yourself vs when you’re writing for others.

With students, I encourage them in documentation and in code to write like they’re writing to the next people to take this class. When I write sample code, I write like I am writing to my students, which is probably experienced coders tend to find my examples “needlessly verbose”, as I’ve been told. There’s not a lot of code I get to write just for me anymore, but when I do, I still tend to comment the hell out of it, just so I can remember what I was doing in later years. I also tend to think through the problem by writing pseudocode, then following up with lines of code.

How about others? Who do you write to when you’re writing code?

j. eric townsend

unread,
Mar 31, 2016, 7:07:07 PM3/31/16
to devel...@arduino.cc
IMHO: this discussion really needs to be happening in parallel with
arduino_teachers@.

Tom Igoe

unread,
Mar 31, 2016, 7:08:06 PM3/31/16
to devel...@arduino.cc
Feel free to cc: that list or move it there. As I said, I think it would be good.

Andrew Kroll

unread,
Mar 31, 2016, 7:42:48 PM3/31/16
to devel...@arduino.cc
Since we are talking about code styles and best practices....

Now all you need to do is teach them that standard console tabs are 8 spaces, not 2, not 3, not 4, or something else, and the planet will become normal and code will be readable once again.

Please stop teaching people incorrectly on just this one point and many people will be happier. Not just because it is easier to read, but nesting too deep can be a massive source of errors and performance problems. If your indents are so deep that you run out of width, your function or method is either too complex or too nested and could end up very slow. Break down the problem and/or use macros, use 132 columns instead of 80 if you have to.

<rant>If I ever locate the retard that started teaching this bad habit, oh the torture I would do to them as payment for the pain caused to me.</rant>


--
Visit my github for awesome Arduino code @ https://github.com/xxxajk

j. eric townsend

unread,
Mar 31, 2016, 11:33:35 PM3/31/16
to devel...@arduino.cc
On 3/31/16 19:07, Tom Igoe wrote:
> Feel free to cc: that list or move it there. As I said, I think it would be good.

Jinx. I just now got your email with the same suggestion.

Gabriel Staples

unread,
Apr 1, 2016, 5:24:59 PM4/1/16
to devel...@arduino.cc

Tom, to respond to your question below ("How about others? Who do you write to when you’re writing code?"):

One other thing I do that I find *very* helpful for me is I make a special LibreOffice Writer document for every major code I write, called "[name of code] - what to work on next - Gabriel.odt" Ex, for one of my more popular libraries called "eRCaGuy_NewAnalogRead", which allows both speeding up the ADC clock to get faster reads on Arduino AVR-based chips, as well as oversampling to get higher resolution, my document name is "eRCaGuy_NewAnalogRead - What to work on next! - Gabriel.odt". I don't intend to share these files--they are just for personal use in development. They are my notes to myself. At any given moment I may have 10 or 20 projects, files, or libraries I'm working on, periodically jumping back and forth, and each file is critical to helping me know:
  • what I've done
  • why I did it
  • what bugs I ran into
  • what fixes I have done
  • what fixes I have remaining, and for me, most importantly, 
  • what features I want to add next
This makes jumping around and refreshing my memory much more possible, and it allows me to sit on something for a long time (even years if needed), until I have time to do it, but by reviewing the file and my comments in the code I can relatively quickly jump back into it and even pick up where I left of, adding the very features or whatever I wanted to implement years ago. 

My personal preference is to make the whole thing a big bulleted list. Each major bullet begins with the date, as a year month day thing, ex: 1 April 2016 is 20160401. I then jot down notes and thoughts from today. Occasionally I'll go to the top of the document and jot down a general architecture/design strategy, but my bulleted list is generally chronological, with that date format, most recent entries at the bottom of the list. 

Attached is an example of my personal notes for NewAnalogRead. Don't be too cricital. This was never intended for sharing. :) I have dozens of docs like these.

Thank you!

Sincerely, 

Gabriel Staples


eRCaGuy_NewAnalogRead - What to work on next! - Gabriel.odt

William Westfield

unread,
Apr 4, 2016, 5:47:06 PM4/4/16
to devel...@arduino.cc
On Apr 1, 2016, at 2:24 PM, Gabriel Staples <panth...@gmail.com> wrote:

> One other thing I do that I find *very* helpful for me is I make a special LibreOffice Writer document for every major code I write ...
> • what I've done
> • why I did it
> • what bugs I ran into
> • what fixes I have done
> • what fixes I have remaining, and for me, most importantly,
> • what features I want to add next

A great idea. Does the arduino IDE let you add .txt/etc files to your project?

We used to have a thing called a “date edit” that was added to comments at the top of a file, in a standard format. Standard format, most recent comment at the top… Very useful, when people remember to do it:

> ;[SIMTEL20]PS:<SOURCES.MICRO>MODEM.MAC.246, 8-Sep-84 21:50:42, Edit by WANCHO
> ; expanded nout to four places (and backspaces)
> ;[SRI-KL]PS:<BILLW>MODEM.MAC.244, 21-Apr-84 14:20:42, Edit by BILLW
> ; add return instruction in DISINT!
> ;<BILLW>NMODEM.MAC.237, 9-Jan-84 19:54:24, Edit by BILLW
> ; add multiple send. Have errors occuring when receiving or
> ; transmitting a filename clean up after themselves.

The more modern equivalent is a “revision control system.” Something like git or even rcs can be very useful, even for single developers working on personal projects.

And a bug-tracker, too. github and similar are great. And not really that difficult to use, for simple cases…

Revision control and bug tracking tend to be “advanced features” added to IDEs as an afterthought or add-on. But I wonder if simplified capabilities in those areas could be added to something line the arduino IDE, in a way easy enough for Arduino users to grasp. Instead of the more traditional IDE features. Documentation is more important that auto-completion?

BillW/WestfW

indigoredster

unread,
Apr 4, 2016, 7:51:36 PM4/4/16
to devel...@arduino.cc
Doxygen can work with your style too if costume aliases are used as found in this answer

The generalization of \bug and \todo is \xrefitem.

The solution I suggest is:

  • in Doxyfile:

    ALIASES += "req=\xrefitem req \"Requirement\" \"Requirements\" "
    
  • in documented code:

    /// \req #42 - The system shall work in any situation

On Thu, Mar 31, 2016 at 2:36 PM, indigoredster <indigo...@gmail.com> wrote:
Reply all
Reply to author
Forward
0 new messages