Skip to content

8. Embedded programming

This week’s assignment was to read a microcontroller datasheet and to program our board to do something in as many languages as possible. I read the datasheet for the ATtiny412 chip that I used on my blink board, and I programmed using Arduino, C, block-based code, and simulation with TinkerCircuits.

ATtiny412 Datasheet

I started off the week by reading the ATtiny412 datasheet. The datasheet is a massive 500-page document that explains the inner workings of the microcontroller. Most of what I wanted to get out of the datasheet involved port registers since I would be coding in C, so I read the first few pages, then skimmed the rest up to the I/O pins.

Pinout of the ATtiny412

How the avr series chips are named

The inner circuitry of the ATtiny412

Most of what I learned was under section 16 - I/O. I found the directory for the pin’s direction, value, and internal pullup resistors.

Software

The goal for my software is to get an led to change state per button press with each language I use. I already wrote this code in Arduino to test my button board in the Electronics Design week, so I started with C at the port register level.

After reading the datasheet, I had a deeper understanding of the ATtiny412 chip, but I still didn’t exactly know how to code in C - I had always used the Arduino IDE, which included a variety of libraries. To get an idea of how to code with registers, I watched a video about registers from Sparkfun. The video was about the 328 chip, but the principles were the same. After watching the video, I wrote this code to blink an LED when a button is pressed:

int ledPin = 2;    //PA2, pin 3
int buttonPin = 3; //PA3, pin 4
void setup() {
PORTA.DIR = B00000100;
PORTA.OUT = B00001100;
}

void loop()
{
 if(digRead(buttonPin))
 {
  digWrite(ledPin,HIGH);
  delay(500);
  digWrite(ledPin,LOW);
  delay(500);
 }
 if(!digRead(buttonPin))
 {
  digWrite(ledPin,HIGH);
 }
}


bool digRead(int pin){
 bool bval = ((1 << pin) & ~PORTA.IN) >> pin;
 return bval;
}

void digWrite(int pin,bool state){
  if(state)
  { 
    PORTA.OUT = ~(1 << pin) & PORTA.OUT;
  }
  else if (!state)
  {
    PORTA.OUT = (1 << pin) | PORTA.OUT; 
  }
}

I separated my code into different my own functions for reading and writing to make it easier to debug. This code worked, but it had some weird issues. Whenever I pressed my finger to the copper plate, the led would flash as if the button was pressed. The same thing happened when I barely touched the board through a jumper cable, so it wasn’t just me causing a short. The strangest thing about this issue was that I could touch any trace or component without causing the issue, but only the copper plate would cause the led to flash.

To try to understand what was happening, I replaced everything with the Arduino-supported libraries one at a time to isolate the problem. I found that my second line in setup, PORTA.OUT = B00001100;, was causing the problem. I looked through the datasheet until I found the parts for setting input/output pins. I read the page and realized that unlike with the 328 chip used in the Sparkfun video, the output register does not control port pullup resistors. After reading a little closer, I found that to control the pull-up resistor (on the 3rd pin), I would have to use the PORTA.PIN3CTRL register. I updated my code, and I finally no longer had this problem. I then wrote in a few more lines for variables, and after many hours of debugging, my button was changing state.

int ledPin = 2;    //PA2, pin 3
int buttonPin = 3; //PA3, pin 4
bool n;
void setup() {

PORTA.DIR = B00000100;
PORTA.PIN3CTRL = PORTA.PIN3CTRL | PORT_PULLUPEN_bm;
}

void loop()
{
 if(digRead(buttonPin))
 {
 n = !n;
  digWrite(ledPin,n);
  delay(150);
 }
}

bool digRead(int pin){    // custom function
 bool bval = ((1 << pin) & ~PORTA.IN) >> pin;
 return bval;
}

void digWrite(int pin,bool state){
 if(state)
 {
  PORTA.OUT = ~(1 << pin) & PORTA.OUT;
 }
else if (!state)
 {
  PORTA.OUT = (1 << pin) | PORTA.OUT; 
 }
}

After working with Arduino IDE, I decided to use the editor PlatformIO through Visual Studio Code. I started by downloaded PlatformIO from the Visual Studio Code marketplace and starting a project with the ATtiny412 chip and Arduino framework.

I then wrote code at the Arduino library level to switch my LED:

#include <Arduino.h>
bool n;
void setup() {
  pinMode(3, OUTPUT);
  pinMode(4,INPUT_PULLUP);
}
void loop() {
  if(digitalRead(4)==0){
    n =! n;
  digitalWrite(3, n);
 delay(150);
  }
}

Finally, I clicked the check icon to compile my code and the arrow icon to upload my code. PlatformIO automatically configures the upload procedure, so after clicking the arrow, the program was uploaded through my FTDI chip and programmer and to my button board. My LED was changing state as desired:

After using a very difficult level of code to program my board, I wanted to try using the simplest code possible: block code. I found the web based editor BlocklyDuino. It is designed around arduino, and includes block for digital read/write, logic, loops, variables, etc. After about 10 minutes, I created this program:

I then copied and pasted the generated code into Arduino IDE and uploaded it to my board.

Our group assignment for this week was to compare the performance and development workflows for other architectures. Our documentation for this week’s group assignment can be found on our group site page.

For this week we compared the Raspberry PI and Raspberry PI PICO.

My files from this week can be found inside this zip file.


Last update: May 18, 2021