Author Topic: Educational design: teaching ATmega328P GPIO with almost zero prerequisites  (Read 1226 times)

0 Members and 1 Guest are viewing this topic.

Offline costycncTopic starter

  • Newbie
  • Posts: 6
  • Country: it
    • www.costycnc.it
# Teaching the ATmega328P: reducing prerequisites before introducing abstractions

When teaching microcontrollers, the main question should not be:

**"Which abstraction is better?"**

The real question is:

**Which model requires the fewest previous concepts while still creating a correct understanding of the hardware?**

For a complete beginner, every unknown concept adds cognitive load.

The goal is not to remove complexity, but to introduce concepts in an order where each new idea has a clear meaning.

---

## Starting with Arduino

A common starting point is Arduino:

digitalWrite(13, HIGH);

Arduino is extremely useful. It allows beginners to create working projects quickly.

However, even this simple instruction already requires several hidden concepts:

* what a function is;
* what a pin is;
* what a library does;
* how software can affect hardware;
* that there is a microcontroller behind the framework.

The beginner can easily create this mental model:

> "I call a function and the LED turns on."

But the real chain is hidden:

function call
      ↓
Arduino library
      ↓
C code
      ↓
register manipulation
      ↓
hardware
      ↓
electrical signal
      ↓
LED turns on

Arduino is not wrong. It is an excellent abstraction layer.

The problem is that the student may learn the abstraction before knowing what is being abstracted.

---

## Moving to AVR assembly

The next step is often AVR assembly:

sbi PORTB,PB5

This is much closer to the hardware, but it still requires previous knowledge.

The beginner must already know:

* what a register is;
* what PORTB means;
* what PB5 means;
* why changing bit 5 changes a physical output.

These concepts seem obvious to experienced microcontroller users, but for a complete beginner they are not obvious at all.

Even assembly is still an abstraction.

The processor does not know the name `PORTB`.

The processor does not know the name `PB5`.

These are labels created for humans.

---

## A simpler first model: the cabinet with drawers

A possible first model with almost zero prerequisites is a simple physical analogy.

Imagine the microcontroller as a cabinet with drawers.

One drawer has number 5.

Inside that drawer there is a switch.

The beginner only needs to understand:

> "If I close switch number 5, the connected circuit changes."

The model becomes:

drawer 5
    ↓
switch 5
    ↓
electrical change
    ↓
LED turns on

No knowledge of PORTB is required.
No knowledge of registers is required.
No knowledge of AVR architecture is required.

This is a very small mental model:

location
   ↓
value/state
   ↓
hardware response

After this concept is understood, the real names can be introduced:

drawer 5 = PORTB
switch 5 = bit PB5

Now `PORTB` is no longer a difficult new concept.

It is simply the technical name of something already understood.

---

## Introducing the real AVR hardware

At this point the assembly instruction:

sbi PORTB,PB5
has a clear meaning:

> "Set switch number 5 inside drawer PORTB."

The student can now understand the real relationship:

PORTB register
        ↓
bit 5 becomes 1
        ↓
PB5 output changes state
        ↓
Arduino pin 13 LED turns on

The instruction is no longer magic.

One bit changes.

One hardware function reacts.

The physical world changes.

---

## The role of the tool

The tool is an essential part of this learning approach.

A normal AVR development environment introduces many additional concepts:

* compiler installation;
* assembler setup;
* programmer configuration;
* command line tools;
* build systems;
* upload procedures.

These are useful skills, but they are not the concept being taught.

A beginner can become confused by two different problems:

1. How does the microcontroller work?
2. How do I configure the tools to program it?

A browser-based AVR compiler and uploader removes the second problem.

Using a tool such as https://costycnc.github.io/avr-compiler-js,
(source code:https://github.com/costycnc/avr-compiler-js/)
 a beginner can directly write a simple instruction:

sbi 5,5

compile it, upload it from the browser, and observe the real hardware result:

assembly instruction
        ↓
assembler translation
        ↓
machine code
        ↓
ATmega328P executes instruction
        ↓
I/O bit changes
        ↓
Arduino onboard LED (pin 13) turns on

The student does not need to imagine the connection between software and hardware.

They can see it.

The feedback loop becomes extremely short:

write instruction
        ↓
upload
        ↓
physical result

This creates a direct causal model:

one instruction
        ↓
one bit changed
        ↓
one electrical signal
        ↓
one physical effect

---

## Returning to higher abstractions

Only after this understanding exists do higher-level abstractions become truly useful.

Arduino and functions such as:

digitalWrite(13,HIGH);

can then be appreciated for what they really are:

not magic commands, but convenient layers that save the programmer from manually controlling every register and bit.

The learning sequence becomes:

simple physical model
        ↓
numbered switches and drawers
        ↓
real registers (PORTB, DDRB)
        ↓
AVR assembly
        ↓
machine instructions
        ↓
Arduino framework

The objective is not to eliminate abstraction.

The objective is to introduce abstraction after the student has a concrete mental model of what is being abstracted.

A good educational tool is not the one that hides the most complexity.

It is the one that removes unnecessary complexity while keeping the fundamental cause-and-effect relationship visible.
 

Offline brucehoult

  • Super Contributor
  • ***
  • Posts: 6464
  • Country: nz
A 6502 + 6522 worked pretty well.

Or on an Apple ][:

X=PEEK(49200) — click the speaker

10 X=PEEK(49200): GOTO 10 — make a tone

10 PRINT PEEK(49152)-128: GOTO 10 — continuously print the ASCII code of the most recently pressed key (for some unknown reason they set the hi bit)

You could then readily show these in machine code too.
 

Offline Doctorandus_P

  • Super Contributor
  • ***
  • Posts: 5370
  • Country: nl
I'm not sure "what the main question should be". There is no single "right" path. If you want to teach / learn CPU architecture, then ASM is a decent starting point.

If you want to teach / learn practical uC usage then C or C++ is a much better starting point.

I don't understand your viewpoint of "minimal prerequisites" or "Fewest previous concepts". First learning C (or Rust, whatever) on a PC before introducing microntrollers is useful. Learning programming on a PC is a much better platform then on a uC, but on the other side, I do see that working with blinking LED's on a breadboard is much more fun.

I have always disliked "arduino" very much. It's easy to get a blinking led going, but "arduino" mostly teaches bad habits that you have to unlearn later if you want to do any "decent" sort of programming. "arduino" obfuscates everything. They can't even acknowledge they're using a basterdized form of C++. The java contraption they call an "IDE" is not worthy of the name (It may have become a little bit less obnoxious in the last bunch of years, but the first 10 or so years it was truly awful.
« Last Edit: July 08, 2026, 10:31:24 am by Doctorandus_P »
 

Offline brucehoult

  • Super Contributor
  • ***
  • Posts: 6464
  • Country: nz
They can't even acknowledge they're using a basterdized form of C++.

Bastardised how? It's completely standard avr-gcc, and you can supply your own copy if you want (e.g. a newer version).

Last I checked, Arduino have stuck with version 7.3.0 because Microchip have.

The only thing Arduino does is run a preprocessor over the code to do some includes and generate prototypes for all functions at the start of the file so that you can put your functions in any order. Duplicate prototypes doesn't harm anything in standard code.
 

Online MariuszD

  • Frequent Contributor
  • **
  • Posts: 703
  • Country: pl
Electronics and programming require a lot of knowledge to function efficiently in these fields. It's best to simply get used to the fact that you constantly have to learn new things.
Arduino teaches that this process can be skipped. Arduino is a promise that everything will be easy, in a field that is not easy. This is how hobbyists are created who cannot solve problems by themselves.

Quote
**Which model requires the fewest previous concepts while still creating a correct understanding of the hardware?**
The fewer new concepts there are at the initial stage of learning, the greater the gap will be to bridge on the way to self-sufficiently constructing circuits and writing programs.
 

Offline costycncTopic starter

  • Newbie
  • Posts: 6
  • Country: it
    • www.costycnc.it
I did without any abstract code

A possible first model with almost zero prerequisites is a simple physical analogy.

Zero Prerequisites with tool compiler uploader online

And magine the microcontroller as a cabinet with drawers.

With zero-setup online tool, students don't fight with syntax: they just send a command to a coordinate, like sbi 5,5, get a 'Hit D13' response, and see the LED light up.
 

Offline Obin

  • Regular Contributor
  • *
  • Posts: 136
  • Country: be
  • Hi
    • nacho.works
I think its a nice abstraction, but, knowing class-time limitations, why go through the effort of reducing the toggle of an LED to someone opening a closet? IMO if someone found their way into a situation where they learn about low-level hardware, they should be aware of some basic concepts.
Going through the effort of this deviation will cost you a decent chunk of class-time.

Offline costycncTopic starter

  • Newbie
  • Posts: 6
  • Country: it
    • www.costycnc.it
I think its a nice abstraction, but, knowing class-time limitations, why go through the effort of reducing the toggle of an LED to someone opening a closet? IMO if someone found their way into a situation where they learn about low-level hardware, they should be aware of some basic concepts.
Going through the effort of this deviation will cost you a decent chunk of class-time.

The discourse was :

A few moments later, explain the PORTB register.

A few moments later, explain digitalWrite.

It takes no more than 5 minutes, but this concept stays with them for a lifetime.
 

Online ledtester

  • Super Contributor
  • ***
  • Posts: 4207
  • Country: us
(for some unknown reason they set the hi bit)

The Apple ][ uses the high bit to indicate that a key has been pressed. You acknowledge receipt of the keypress by reading $C010 and the read clears the high bit of $C000. This is needed so you can detect the same key being pressed multiple times in a row.

Using the high bit also allows for efficient checking using the bit-test instruction, see lines 19 and 23 here:

https://github.com/cmosher01/Apple-II-Source/blob/8ab5049415370a4282b8c23b0c216817f3ad1e4f/src/system/monitor/common/keyin.m4#L19


« Last Edit: July 08, 2026, 03:04:24 pm by ledtester »
 

Offline costycncTopic starter

  • Newbie
  • Posts: 6
  • Country: it
    • www.costycnc.it
Electronics and programming require a lot of knowledge to function efficiently in these fields. It's best to simply get used to the fact that you constantly have to learn new things.
Arduino teaches that this process can be skipped. Arduino is a promise that everything will be easy, in a field that is not easy. This is how hobbyists are created who cannot solve problems by themselves.

Quote
**Which model requires the fewest previous concepts while still creating a correct understanding of the hardware?**
The fewer new concepts there are at the initial stage of learning, the greater the gap will be to bridge on the way to self-sufficiently constructing circuits and writing programs.

I actually agree that Arduino creates many 'programmers' who rely entirely on copy-paste and pre-made libraries—the classic 'pappa pronta' (spoon-fed code). But this shortcut is exactly what leads to massive failure later on. When their big, ambitious projects crash and break, they lack the tools to fix them because they never truly understood the hardware.This is exactly where my approach changes the game. Even if they fail at their big dreams initially, they will eventually come back to this simple web tool. Why? Because they will never, ever forget that they turned on a real physical LED using nothing but sbi 5,5. That core memory sticks with them forever.Armed with that raw, unbloated understanding, they can finally read a sensor manual or control a motor using pure Assembly, without being slaves to massive libraries. We aren't hiding the complexity like Arduino does; we are making the real hardware unforgettable.
 

Offline costycncTopic starter

  • Newbie
  • Posts: 6
  • Country: it
    • www.costycnc.it
I'm not sure "what the main question should be". There is no single "right" path. If you want to teach / learn CPU architecture, then ASM is a decent starting point.

If you want to teach / learn practical uC usage then C or C++ is a much better starting point.

I don't understand your viewpoint of "minimal prerequisites" or "Fewest previous concepts". First learning C (or Rust, whatever) on a PC before introducing microntrollers is useful. Learning programming on a PC is a much better platform then on a uC, but on the other side, I do see that working with blinking LED's on a breadboard is much more fun.

I have always disliked "arduino" very much. It's easy to get a blinking led going, but "arduino" mostly teaches bad habits that you have to unlearn later if you want to do any "decent" sort of programming. "arduino" obfuscates everything. They can't even acknowledge they're using a basterdized form of C++. The java contraption they call an "IDE" is not worthy of the name (It may have become a little bit less obnoxious in the last bunch of years, but the first 10 or so years it was truly awful.

To be honest, I didn't realize there were such strong negative opinions about Arduino here—I thought I was the only one who felt this way!

 I am not a computer scientist, I am just someone with a deep passion for electronics.

 And out of this passion, I managed to build a zero-setup web tool by combining an avrass.js compiler with a web uploader (uploader.js).

My goal is exactly what you are discussing: to eliminate the massive cognitive load for beginners.
 Instead of making them memorize acronyms or learn C on a PC (which can be abstract and boring), I introduce the ATmega328 as a simple cabinet with drawers and switches.

It becomes a game of Battleship. You type sbi 5,5, click upload, and the onboard LED hits target D13 and turns on.

 You type sbi 5,4, click upload, and D13 turns off while D12 turns on. No prerequisites, no IDE installation, no bloated libraries.

Only after they play this game do I explain a little bit about registers, and only after that do we look at digitalWrite.
 I agree that Arduino creates a lot of 'copy-paste failures.' But with this 5-minute approach, even if a student gives up on massive projects later on, they will never forget that they controlled hardware with sbi 5,5.
That core memory remains for a lifetime, and it might just spark a real, lasting love for AVR Assembly to read sensors and control motors directly.

And the ATmega328 was not chosen by chance. It was selected because it has a simple architecture, it is cheap, and it is by far the most well-documented chip out there. It has a small memory and a very small set of Assembly instructions.




 

Offline brucehoult

  • Super Contributor
  • ***
  • Posts: 6464
  • Country: nz
(for some unknown reason they set the hi bit)

The Apple ][ uses the high bit to indicate that a key has been pressed. You acknowledge receipt of the keypress by reading $C010 and the read clears the high bit of $C000. This is needed so you can detect the same key being pressed multiple times in a row.

Using the high bit also allows for efficient checking using the bit-test instruction, see lines 19 and 23 here:

https://github.com/cmosher01/Apple-II-Source/blob/8ab5049415370a4282b8c23b0c216817f3ad1e4f/src/system/monitor/common/keyin.m4#L19

That's fine for the actual keyboard input buffer, but they kept the hi bit set in strings and variable names in BASIC source code, in text files, in the text display buffer.
 

Online ledtester

  • Super Contributor
  • ***
  • Posts: 4207
  • Country: us
That's fine for the actual keyboard input buffer, but they kept the hi bit set in strings and variable names in BASIC source code, in text files, in the text display buffer.

I guess being completely 100% ASCII compatible wasn't a big priority for the Woz.
 

Online tooki

  • Super Contributor
  • ***
  • Posts: 15985
  • Country: ch
# Teaching the ATmega328P: reducing prerequisites before introducing abstractions

When teaching microcontrollers, the main question should not be:

**"Which abstraction is better?"**

The real question is:

**Which model requires the fewest previous concepts while still creating a correct understanding of the hardware?**
Says who?


Arduino is not wrong. It is an excellent abstraction layer.

The problem is that the student may learn the abstraction before knowing what is being abstracted.
That is not a problem, it is an advantage!!!

Microcontroller programming requires numerous skills, including how to structure program logic, writing good code, how to interact with peripherals, and much more. Many of those skills (most?) are not dependent on the MCU in use. Abstraction lets you focus on a given aspect or skill before tackling the others. IMHO it is a huge advantage to not burden a beginner with everything at once. Embracing abstractions gives you a huge amount of flexibility.

And in terms of reaching goals, understanding what’s inside the abstraction is often not actually useful. I mean… ok, great, I know that doing digitalWrite() ultimately sets some bits on a register. But does knowing this actually help me accomplish anything? And if it doesn’t help right now, it still doesn’t mean I can’t learn it in the future.

I’m not a gifted programmer. But I have a decent understanding of program logic, and I have learned how registers work, etc, such that I can use them when needed. I don’t see any advantage in “looking under the hood” too early.

In summary, your proposal is yet another example of an arrogant, prescriptivist, dogmatic approach that insists that deep understanding of the hardware at the lowest levels is inherently necessary and desirable. But it isn’t! It may be necessary for some situations, but people can learn more when they run into such a situation!
« Last Edit: July 08, 2026, 07:41:56 pm by tooki »
 
The following users thanked this post: Obin


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf

 

-->