8: embedded programming

Individual Assignment

The individual assignment for this week was to read a microcontroller data sheet and program my board to do something with as many different programming languages and programming environments as possible.

Microcontroller Data Sheet

I began by reading an article by All About Circuits to learn about what a microcontroller was. I then read two articles that discussed how to read datasheets and what information to look for, one by Sparkfun and the other by Embedded Inventor.

Because I would be programming my board from electronics design week (week 6) which used an ATtiny412 chip, I read this data sheet. The first thing I did was download it and open it in Preview on my Mac so I could flip through the pages and not have to scroll through all 479 pages. I was instructed by the articles I read to thoroughly go through the summary, so I dissected it as carefully as I could and took note of several diagrams.

The first diagram compared the chips in the tinyAVR 1-Series in terms of pins and flash. As I mentioned previously, I used the ATtiny412, which is shown to have 8 pins and 4KB of storage.

The next figure described the naming convention of the microcontroller:

This block diagram depicted all the components of the ATtiny412 that would be discussed extensively in the following sections of the data sheet. Though it was multi-faceted and rather complicated, seeing the visual of all the parts of the microcontroller helped me understand it a bit more.

The pinout of the microcontroller revealed what each of the 8 pins were, their functions, and how they were oriented. I noted that the pins were numbered counter-clockwise, with VCC as pin 1 at the top left corner and GND as pin 8 at the top right.

I took note of the Memory Map that showed how the microcontroller’s memory was divided. The datasheet defined the CPU’s ability “to access memories, perform calculations, control peripherals, and execute instructions in the program memory.” The AVR CPU uses the Harvard architecture, as opposed to the von Neumann architecture, and consisted of nonvolatile data storage (which is used to store the microcontroller’s program) called Flash. It also contained Internal SRAM, volatile memory that temporarily stores data and loses it as the microcontroller loses power, and EEPROM.

One of the components I learned about was the Sleep Controller. The microcontroller uses three sleep modes, Idle, Standby, and Power Down, to shut down peripherals and clock domains so it can save power. The Sleep Controller “controls and handles the transitions between active mode and sleep mode” by interacting with the CPU and peripherals so program execution can be stopped.

The absolute maximum ratings describe the conditions that the microcontroller can handle without being permenantly damaged. These are very important so not to exceed and be forced to replace the part.

Hence, these are the general operating ratings–the recommended conditions for working with the microcontroller.

Overall, though the datasheet was pretty long and confusing, I think it helped my understanding of the microcontroller and how it operates. How a chip so tiny can have so many functions is pretty amazing!

Programming my Board

TinkerCircuits

To begin the assignment, I started with the simplest environment: TinkerCircuits. I created a basic circuit with an LED and resistor. I used the blocks to generate a simple Arduino IDE text-based code to blink the LED.

Arduino

From TinkerCircuits, I transitioned into using Arduino IDE to program my microcontroller. I followed this tutorial to turn my Arduino into a UPDI programmer.

The first step was downloading the megaTinyCore onto Arduino IDE. I did so by clicking Arduino -> Preferences and pasting http://drazzy.com/package_drazzy.com_index.json into the Additional Board Manager URLs area. I then opened the Boards Manager by selecting Tools -> Board -> Boards Manager and installing megaTinyCore and Arduino megaAVR boards.

Next, I downloaded and extracted this folder and opened the jtag2updi.ino sketch in Arduino. From there I uploaded it to my Arduino.

From there, I followed this diagram to connect my microcontroller to my Arduino. I had to add a 10uF capacitor and 4.7k resistor.

Here is what my setup looked like:

Once everything was hooked up, I changed the Board to Attiny412/212/202 and the Programmer to jtag2updi (megaTinycore). I made sure the chip was the ATtiny412.

Here is my code. I used the pinout diagram to establish that my LED was connected to pin 6, allowing me to blink the LED.

UPDATE 6/23/20: upon going back to my weeks and editing my documentation in accordance to my local evaluator’s comments, I was informed that I did not have a video of my board blinking with the code. I realized I could not find my hello world board. Luckily, I had my unused master board from week 14 that had an LED I could blink. Using the same code but replacing the pin (this LED was attached to pin 3), I uploaded the code via my jtag2updi programmer and blinked the LED as shown here:

void setup()
{
  pinMode(3, OUTPUT);
}

void loop()
{
  digitalWrite(3, HIGH);
  delay(1000); // Wait for 1000 millisecond(s)
  digitalWrite(3, LOW);
  delay(1000); // Wait for 1000 millisecond(s)
}

I also found another FabAcademy student that used Arduino IDE, but used C operators as opposed to Arduino’s C/C++. I was unfamiliar with C operators, but my peer Elaine Liu provided a very informative link that discussed them. I read through the website, specifically looking at which ones were incorporated in the code.

//Adrián Torres - Fab Academy 2020 - Fab Lab León
//tiny412 hello_blynk
//
//Original code:Neil Gershenfeld 12/8/19
// This work may be reproduced, modified, distributed,
// performed, and displayed for any purpose, but must
// acknowledge this project. Copyright is retained and
// must be preserved. The work is provided as is; no
// warranty is provided, and users accept all liability.
//
int ledpwm = 3;//pinout of the attiny412

int i = 0;//variable that will make the work cycle increase

void setup(){
 pinMode(ledpwm,OUTPUT); 
}
void loop(){
  for(i = 0; i <= 255 ; i++){
   analogWrite(ledpwm,i); 
   analogWrite(5,255-i);
   delay(25);
  }
   for(i = 255; i>= 0 ; i--){
   analogWrite(ledpwm,i); 
   analogWrite(5,255-i);
   delay(25);
  } 
}

To begin, the variable “i” is introduced that will make the brightness of the LED increase. In the void setup, we see that the LED will be an output. In the void loop is where we see the C operators. He begins with a for loop, which is defined as “a control flow statement for specifying iteration, which allows code to be executed repeatedly.” When using <=, this “checks if the value of left operand is less than or equal to the value of right operand. If yes, then the condition becomes true.” Therefore, i <= 255 checks if i is less than or equal to 255. When using ++, this “increases the integer value by one”, so i++ is being increased by one. The ledpwm is then increased by i. It decreases in the second for loop. I uploaded the code to my board and it worked:

I then attempted to use the .hex file and python to get the board to blink. After compiling and uploading the code, I knew that Arduino provided the .hex file and showed the location of it. Mine was in: /var/folders/kp/mvlv5nlj1v1_g_r0jyq9732m0000gn/T/arduino_build_70194/412blink2.ino.hex. This was a temporary file and when I searched for it in my Mac, nothing showed up. I Googled it and found that I needed to use my terminal to find the folder. I entered open $TMPDIR into my terminal and the temporary T folder popped up. I searched for arduino_build_70194 and found the .hex file inside. I copied and pasted the file into my pyupdi-master folder which was in my Downloads. Using my terminal again, I cd’d to my Downloads folder, then to the pyupdi-master folder. I then ran sudo python3 pyupdi.py -d tiny412 -c /dev/cu.usbserial-DA01LW41 -b 115200 412blink2.ino.hex -v in my terminal. I was prompted with the error: ModuleNotFoundError: No module named 'serial'. I Googled this and found that I did not have pyserial installed. I attempted to install it here but received the same error.

I decided instead to simply upload another iteration of blink code. This is Neil’s code and is written using ports and bitshifting. I also had to do some research to learn how the code worked, which I read about in the same link as before.

//
// hello.t412.blink.ino
//
// tiny412 blink hello-world
//
// Neil Gershenfeld 12/8/19
//
// This work may be reproduced, modified, distributed,
// performed, and displayed for any purpose, but must
// acknowledge this project. Copyright is retained and
// must be preserved. The work is provided as is; no
// warranty is provided, and users accept all liability.
//

#include <avr/io.h>

#define LED_AVR PIN2_bm
#define LED_ARDUINO 3

void setup() {
   PORTA.DIRSET = LED_AVR;
   //pinMode(LED_ARDUINO,OUTPUT); // does the same thing
   }

void loop() {
   //
   // timing tests
   //
   // Arduino digitalWrite: 3.9 us/bit
   //
   digitalWrite(LED_ARDUINO,HIGH);
   digitalWrite(LED_ARDUINO,LOW);
   //
   // port read-modify-write: 304 ns/bit
   //    6 cycles at 20 MHz
   //
   PORTA.OUT |= LED_AVR;
   PORTA.OUT &= ~LED_AVR;
   //
   // port bit write: 96 ns
   //    2 cycles at 20 MHz
   //
   PORTA.OUTSET = LED_AVR;
   PORTA.OUTCLR = LED_AVR;
   //
   // virtual port write: 50 ns
   //    1 cycle at 20 MHz
   //
   VPORTA.OUT |= LED_AVR;
   VPORTA.OUT &= ~LED_AVR;
   //
   // blink
   //
   digitalWrite(LED_ARDUINO,HIGH);
   delay(100);
   digitalWrite(LED_ARDUINO,LOW);
   delay(100);
   }

Here he defined the LED as opposed to introducing it. In the void setup, He uses PORTA.DIRSET = LED_AVR but the comment indicates that this is just another way of doing what pinMode(LED_ARDUINO,OUTPUT); does. In the void loop, he uses |= and &=. |= is a “Bitwise inclusive OR and assignment operator,” an example being that C |= 2 is same as C = C | 2. &= is a “Bitwise AND assignment operator,” an example being that C &= 2 is same as C = C & 2. I uploaded the code and it worked:

Python & Terminal

Next, I tried to get my board to blink using python and the Terminal on my Mac. I followed this tutorial that I found and realized was written by one of my instructors at the FabLab, Dr. Harris.

The first step was installing Python 3. I tried running the command

$ sudo apt-get update 
$ sudo apt-get install python3.6

to download this version of Python, but my Mac kept spitting out zsh: command not found: $. I realized that my Mac did not have all the commands I would need, so I downloaded Homebrew using the command /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)". Once it installed, I downloaded Python version 3.7.3 and continued to the next command, which was to install the dependencies for PyUPDI using pip3 install intelhex pylint pyserial. For some reason, my Mac also did not recognize the ‘pip’ command, so I installed it using sudo easy_install pip. While attempting to downloaded the packages, I kept getting the error

Could not install packages due to an EnvironmentError: [Errno 13] Permission denied: '/Library/Python/3.7'
Consider using the `--user` option or check the permissions.

I solved this by using a different command:

python3 -m venv env
source ./env/bin/activate
python -m pip install intelhex pylint pyserial

which was ultimately successful in downloading the packages I needed. I then downloaded the pyupdi files here and then set up my hardware. I connected a 5V FTDI chip to my microcontroller with a resistor following this diagram:

I opened up an Arduino blink file and changed it so it was the correct pin. Under Tools -> Board I selected Arduino UNO and Sketch -> Export a compiled Binary. The tutorial I followed detailed that this would save the .hex file in the Arduino project folder.

Next, I navigated to the pyupdi-master folder in terminal by typing the commands cd Downloads and cd pyupdi-master. In order to download the board, I used the command sudo python3 pyupdi.py -d tiny412 -c /dev/cu.usbserial-AH02MCP3 -b 115200 -f 412blink.ino.hex -v where /dev/cu.usbserial-AH02MCP3 was my port and 412blink.ino.hex was the name of my file. Unfortunately, my Mac gave me the error: Exception: UPDI initialisation failed, which I am pretty sure was an issue in my hardware and not my software. I was advised to use a 4.7k ohm resistor, but I only had a 10k. Because I had done everything else to set up this section, I opted to come back to it to resolve my issue in the future.

To download my files for this week, click here.

Group Assignment

The group assignment for this week was to compare the performance and development workflows for different microcontroller families. You can view the whole process on our group page here.