8. Embedded programming

Amsterdam, March 18, 2020

To do

Description status
Group assignment: Done
Document my part of the group assignment Done
Read a data sheet done
Program one or more boards Hello World board ATtiny44
Write a program blink & fade & photosensor
Use one or more development environments Arduino & MAKE
Document my individual assignment done
fix source files from previous weeks done

Source files

Description link
Makefile & C code for blink program Downloadable zip.
Arduino file for fade program Downloadable zip.
Makefile & C code for testing switch program Downloadable zip.
Arduino file for operating the photosensor Downloadable zip.

urls

Description link
Index of this week’s topic http://academy.cba.mit.edu/classes/embedded_programming/index.html
Global lecture video https://vimeo.com/398805212
Global review video https://vimeo.com/400771541
Group assignment documentation https://fabacademy.org/2020/labs/waag/groupAssignments/week8.html
ATtiny44 datatsheet http://ww1.microchip.com/downloads/en/DeviceDoc/doc8183.pdf

Pandemic effects

The Netherlands, like so many other countries, is in the grip of the Covid-19 outbreak. A regime of social distancing was implemented this Monday March 16, 2020. Everybody is advised to stay at home as much as possible.
Both the larger Fab network and our local Waag FabLab are doing everything possible to keep operations going. On top of that the Fab network considers how it can contribute to the world in these trying times. There are working groups that are looking into manufacturing much needed supplies like face masks. Shenzen FabLab has offered all the Labs in the rest of the world to provide electronics kits so students can continue fabbing from home.
During the global lecture Neil pointed out that FabLabs is a globally connected, high resource network. If anyone has a need, or a plan to help out, communicate this to the rest of the network. We’re using the GitLab Issue tracker to communicate about the different plans and initiatives.

The Fab network has always already been deploying online resources for sharing information, communication and files. We’re actually pretty good equiped for this radical change.
In our local Waag node, adaption was also quick and smooth. Waag provided multiple Zoom rooms for the different get-togethers to continue. Instead of meeting in the Lab, we now meet each other in a Zoom room. Chitchat is done on Slack. Video conferencing went very smooth for the local and a regional reviews yesterday. The global review and lectures also did not buckle under the extra load. Thoughts also go out to the people worldwide running the internet infrastructure. Internet use must have increased tremendously but they are keeping it all working.
Henk provided us with kits full of components and boards. We can use them to continue our work for the coming weeks. He provided us with a lot of extra stuff, in case social distancing transitions to a complete lockdown. Harm also made kits from stuff he had access to and shared it with all of us.


Social distancing FabAcademy survival kit.

Group assignment

A full description of the group assignment can be found on our communual page.

For the group assignment we have to compare the performance and development workflows of different architectures. I will do the ATtiny 44a. I made this board for the assignment in week 04 and I like to know its specifications. Perhaps I’ll also do another architecture.

ATtiny 44a

Specification value
Board ATTINY44A-SSU-ND
link to datasheet http://ww1.microchip.com/downloads/en/DeviceDoc/doc8183.pdf
Operating voltage 1.8 - 5.5 V
input/output voltage Vil: when VCC = 1.8V - 2.4V then Vil is 0.2Vcc max. When VCC is 2.4 - 5.5V Vil is 0.3V max. Vih: VCC is 1.8V - 2.4V then Vih is 0.7 Vcc - Vcc+ 0.5 When VCC = 2.4V -5.5V then Vih is 0.7Vcc - Vcc+0.5. Vol: 0.6V maximum. Voh: 4.3V minimum.
Power consumption Active mode: 210 μA at 1.8V and 1 MHz; Idle Mode: 33 μA at 1.8V and 1 MHz; Power-down Mode: 0.1 μA at 1.8V and 25°C.
Chip architecture RISC Architecture
(clock)speed 4MHZ - 20 MHz range. 8MHZ is the factory setting. Settings related to voltage: 0 – 4 MHz @ 1.8 – 5.5V. 0 – 10 MHz @ 2.7 – 5.5V. 0 – 20 MHz @ 4.5 – 5.5V. See hackster.io on how to set the clock.
Memory 4KB Flash Program Memory; 256 Bytes of interntal EEPROM; 256 Bytes of internal SRAM
Pins (type and amount) 14 Pins Type: VCC, GND, Reset & 12 I/O pins.
Special feautures

How do you program the device:

Specification value
programming environment The tiny is an AVR microcontroller. This is a family of In-System Programming microcontrollers that can be programmed while already soldered on the board. To program it you need an ISP programmer. We use the TinyISP we made in week 04. But you can also use an Arduino for instance. Connect the TinyISP to the Hello World Board and to your computer. Run AVRdude which is a utility to download/upload/manipulate the ROM and EEPROM contents of AVR microcontrollers using the in-system programming technique.
programming language C
how do you get code on the device Run the Arduino software and select the Attiny44 and tinyISP programmer in the tools dropdown menu. Upload code to the board with the upload button. Another development environment you can use is MAKE: write a program in C. Create a Makefile. And upload the code with AVRdude.

Workflow to get code on the device

ATtiny44A workflow

Microcontroller: ATtiny44
Development environment: MAKE
Program download: MAKE and AVRdude
Communication: usbTiny programmer
Program I used in this example: Blink LED

  1. Open a text editor of your choice. I used Sublime.
  2. Write a program in C.

Example code in C. LED is off. When button is pressed, LED is on.

/*
Demo of the simplest on/off button code for Tiny44. 
This is adjusted code based on the example code of Robert Hart: http://fab.cba.mit.edu/classes/863.15/doc/tutorials/programming/Simple_examples/c_prog_examples.html. & with adjustments of YLi: http://fab.cba.mit.edu/classes/863.15/section.Harvard/people/YLi/Week%207%20-%20Embedded%20Programming/Ye_001.c

This code works by directly manipulating the register bits

In my case: 
Switch connected to PA3 (physical pin 10 of tiny44)
Yellow LED connected to PA7 (physical pin 6 of tiny44)

For details on the use of the registers PORtx, DDRx, and PINx  (where x = A or B) see tutorials on AVR programming.

This program was written by Robert Hart as a simple demonstration of programming AVR microcontrollers. 
*/

// ------- Preamble -------- //
/*This is a library that needs to be called upon for MAKE to know what to make of the code*/

#include <avr/io.h>                       

/* int main is a special function. It is added to all C code. All other functions are wrapped inside this function*/
int main(void) {                            
  // -------- Inits --------- //

/* initialize pullup resistor on our input pin (switch) by setting the bit of PA3 of register PORTA high. Check page 66 of the ATtiny datasheet for the register description.*/ 
  PORTA = 0b00001000;       
 /* Here we declare the LED pin PA7 as output pin by setting the DDA7 bit in the DDRA register to high.  (datatsheet p.66) */           
  DDRA = 0b10000000;                       

  // ------ Event loop ------ //
  /*while (1) declares a loop because 1 is always true.*/
  while (1) {
/* look for button press */                                             
     if ((PINA & 0b00001000) == 0 ) {       /* test to see if bit 3 of PINA is low  */
      PORTA = 0b10001000;                   /* turn on LED on pin 7 of port A if bit is low (button is pressed) */
    }
    else {                                  /* otherwise */
      PORTA = 0b00001000;                   /* leave output low.    */
    }
   }                                        

                                             /* End event loop */
  return (0);   
 }
  1. Save the file as .c. In this example: switch.c.

Creating a MAKEfile.
1. Open a text editor of you choice.
2. Save the file in the same directory as your .c file.
3. The MAKE file must be named Makefile. It does not have an extension.
4. Add the following to the Makefile :

PROJECT=switch
SOURCES=$(PROJECT).c
MMCU=attiny44
F_CPU = 20000000


CFLAGS=-mmcu=$(MMCU) -Wall -Os -DF_CPU=$(F_CPU)

$(PROJECT).hex: $(PROJECT).out
    avr-objcopy -O ihex $(PROJECT).out $(PROJECT).c.hex;\
    avr-size --mcu=$(MMCU) --format=avr $(PROJECT).out

$(PROJECT).out: $(SOURCES)
    avr-gcc $(CFLAGS) -I./ -o $(PROJECT).out $(SOURCES)



program-usbtiny: $(PROJECT).hex
    avrdude -p t44 -P usb -c usbtiny -U flash:w:$(PROJECT).c.hex

program-usbtiny-fuses: $(PROJECT).hex
    avrdude -p t44 -P usb -c usbtiny -U lfuse:w:0x5E:m

Per line exaplanation:
1. PROJECT=switch. The project name must be the same name as the filname of your .c file. In this case switch
2. Leave line 2 as is.
3. MMCU here you name your microcontroller.
4. F_CPU is the frequency of the board you program.
5. CFlags are compiler flags. You can leave as is.
6. The $(Project) functions tell MAKE what to do. Leave as is.
7. The next to functions are AVRdude commands to flash the code and program the fuses respectively. In theory running the MAKE file in your terminal will execute this AVRdude commands automatically. That did not work for me but you can manually enter and execude these commands in the terminal.

Make a .hex file with MAKE:
1. Install AVRdude and MAKE on Linux with the command: sudo apt install avrdude gcc-avr avr-libc make.
2. cd into the directory where your switch.c and Makefile are stored.
3. Run make. A .hex file and .out file should be produced.
4. Run avrdude -c usbtiny -p t44 to see if your programmer is recognized.
5. Run avrdude -p t44 -P usb -c usbtiny -U flash:w:$(PROJECT).c.hex where you replace $(PROJECT) with the name of your project.

The program should now be installed on your microcontroller.

Insights from the group assignment

Doing the group assignment I started reading the datasheet. There are a lot of terms I did not know such as input/output voltage. To answer the question about the pins I had to dive into what all the different pin functions mean. I had some idea about memory and chip architectures but I looked many of them up to get a better understanding of what the differences are.
I have documented research below under the header ‘Reading the datasheet’. Understanding and programming an IC is a fast field of knowledge. I’m hovering over this field like a pick-and-place machine, going over the board in helicopter mode and sometimes diving in to handle a particular topic. So what I learned from the group assignment is how little I know.

Reading the datasheet

I look for the datasheet and find it on Microchip.com. There isn’t just one sheet, there are many appendices. For instance and AVR Instruction Set Manual. Curious what that is. But here is the primary datasheet.
Oh beautiful electronics :). A 50 cent chip can retain data for a century! ‘Data Retention: 20 years at 85°C / 100 years at 25°C.’

Microcontrollers

On Mit.edu I found an interesting description of what microcontrollers actually are.

Microcontrollers are single chip computers that are slow, have very little memory, but are cheap and very easy to interface to real world devices. They are typically programmed in either C or assembly language.

Interfacing is done through the microcontroller’s I/O pins (input/output pins). A microcontroller can take actions in the world by changing the voltages of its output pins. Output pins typically take on two discrete voltages (usually 0 and 5 volts). Each output pin reflects the value of some bit in the microcontroller’s memory. When the bit is set to 1, the pin goes to 5 volts, and when the bit is set to 0, the pin goes to 0 volts.

A microcontroller can sense the world through its input pins. Input pins are either digital or analog. Digital inputs are the opposite of digital outputs - they expect to be set to either 0 or 5 volts by some external device. For each digital input there is a bit in the microcontroller’s memory that reflects its value.

Analog inputs are more flexible than digital inputs. They can be set to any voltage between 0 and 5 volts by some external device. Typically, an analog input has a byte in the microcontroller’s memory that reflects its voltage - 0 volts maps to 0, 2.5 volts maps to 128, and 5 volts maps to 255 (since 255 is the maximum value a byte can take on.)

On w9xt.com I read that an output pin when set to digital and a voltage near VCC will read 0 to half the VCC voltage as 0. And VCC/2 until VCC total as 1.
Pdx.edu describes the microcontroller and gives some basic information about programming an Arduino.

Input/output voltage

I did some research on what input/output voltage is and found information on Sparkfun.com.
In digital circuits there are only two states: on/off or 1/0 or HIGH/LOW.
TTL: Transistor-Transistor Logic. Transistors are electronically controlled switches that are either in ‘on’ or ‘off’ state, together they define the logic state of the circuit. As described above, there is a range of voltage in which a switch is on and a range in which it is off. There are several threshold voltage levels: for both inpiut and output pins and for bith high and low levels.
There are two kinds of pins: ‘If it’s an active-low pin, you must “pull” that pin LOW by connecting it to ground. For an active high pin, you connect it to your HIGH voltage (usually 3.3V/5V).’

Specification value
Voh Minimum output Voltage a TTL device will provide for a HIGH signal
Vih Minimum input Voltage level to be considered a HIGH.
Vol Maximum OUTPUT Voltage level a device will provide for a LOW signal
Vil Maximum INPUT Voltage level to still be considered a LOW.

If the Vih is 2V for instance, than the pin needs at least 2V to go into HIGH state.

Source: Sparkfun.com. Overview of voltage threshold levels.

The input/output voltage for the ATtiny44A can be found in the datasheet on p. 173, chapter 20 Electrical Characteristics.

Pin out

Trying to figure out the pin out I used the ATtiny 24/44/84 datasheet and the documentation page from Aby Michael (FabAcademy 2018) as sources.

I know that pins have different numbers. They have their position numbers and their port numbers. I thought the term ‘pin number’ refered to the port number. But now I think pin number refers to the position on the chip. So VCC in the schematic above is pin 1. That is at least the way I am going to use it for now.


Pinout ATtiny series.

pin position pin port pin function
1 VCC
2 PB0 PCINT8/XTAL1/CLKI
3 PB1 PCINT9/XTAL2
4 PB3 PCINT11/RESET/dW
5 PB2 PCINT10/INT0/OC0A/CKOUT
6 PA7 PCINT7/ICP/OC0B/ADC7
7 PA6 PCINT6OC1A/SDA/MOSI/DI/ADC6
8 PA5 ADC5/DO/MISO/OC1B/PCINT5
9 PA4 ADC4/USCK/SCL/T1/PCINT4
10 PA3 ADC3/T0/PCINT3
11 PA2 ADC2/AIN1/PCINT2
12 PA1 ADC1/AIN0/PCINT1
13 PA0 ADC0/AREF/PCINT0
14 GND

The ATtiny 44A has two ports: A and B. The B port has 4 pins PB0 - PB3. The A port has 8 pins: PA0 - PA7.

Pin functions

PCINT: Pin Change Interupt. (See explanation below)
XTAL: Pins to connect external chrystal/oscillator.
CLKI: External Clock Source Input.
Reset: reset pin.
dW: debug wire.
Int: dedicated hardware interrupt pins (See Arduino Forum explanantion below).
OC0A / OC0B: output pins from the timer/counter on which a frequency can be output – e.g. a PWM frequency. Source.
CKOUT: Outputs the system clock on this pin when the CKOUT fuse bit is programmed.
AIN0/AIN1: AIN0 and AIN1 are the input pins for the analog comparator. AIN0 is the positive input pin. AIN1 is the negative input pin.
ADC: Analog to Digital Converter: Converts an analog voltage on a pin to a digital number. For instance, is programmed to decide if 2.7V should be read as 1 or 0. Source: sparkfun.

PCINT / INT Almost all the pins are ‘PCINT’ so I looked up what that is. It is a Pin Change Interupt. If I understand correctly, a PCINT enabled pin can be interupted by an external signal if it functions as an input pin. For instance, this external signal can be pressing the switch button. Press switch, pin gets interrupted and calls on a Interupt Service Routine (ISR). ISR is a software program that will send the request to the CPU, interupting the active process. For instance: pressing down the key ‘P’ on you keyboard triggers a PCINT which triggers an ISR. The ISR sends to the CPU. CPU sends word to you text editor: print ‘P’ and P is printed. Source on ISR: techterms.com.

‘There are two main categories of interrupts: Hardware and Software. A Hardware interrupt is triggered by something outside of the chip like a button while a Software interrupt is triggered from inside the chip like a timer.
Within the Hardware interrupt there are two categories: External interrupts and Pin Change Interrupts. The nomenclature here is confusing since all hardware interrupts are external to the chip. But the things we are now calling External Interrupts are limited to only a couple pins, while the Pin Change interrupts can occur on all input pins. For instance, on the ATMEGA328, there are two External Interrupts but 24 Pin Change Interrupts.
Each time an interrupt occurs, it triggers the associated ISR (Interrupt Service Routine) assuming you have turned that interrupt on. Each External Interrupt has its own ISR and they can be triggered independently by either a rising signal, falling signal, or by both. But the Pin Change Interrupts share an ISR between all the pins on a port (port B, C, and D). And anytime a pin changes on that port, it calls the port’s ISR which must then decide which pin caused the interrupt. So Pin Change Interrupts are harder to use but you get the benefit of being about to use any pin.’ Source: The wandering engineer.

The wandering engineer then goes on to explain how to do PCINTs. This might be interesting to come back to later.

‘PCINT refers to the interrupts that can be generated by almost any of the I/O pins. INT refers to the dedicated hardware interrupt pins. PCINT has more overhead in determining what pin caused the interrupt as a group of pins share the same PCINT vector (there are 3 PCINT vectors) so you need to determine what pin caused the interrupt withing the ISR before acting on it. The INT pin is linked to a dedicated interrupt vector so you always know what pin caused the interrupt when in the ISR.
One big difference between INT and PCINT: PCINT: Any change on the pin trigger an interrupt. INT: It is possible to choose what kind of change trigger an interrupt.
Also, pcint can wake from sleep mode power down on change, int can only wake on low level. Pcint is very good if you want to look at several pins at once - ex, it’s very good for rotary encoders.’ Source: Arduino Forum

Chip architectures

There are different types of chip architectures:
Von Neuman: The term “von Neumann architecture” has evolved to mean any stored-program computer in which an instruction fetch and a data operation cannot occur at the same time because they share a common bus. Source: Wikipedia
Harvard: The Harvard architecture is a computer architecture with separate storage and signal pathways for instructions and data. It contrasts with the von Neumann architecture, where program instructions and data share the same memory and pathways. Source: Wikipedia
RISC: reduced instruction set computer. is a computer instruction set that allows a computer’s microprocessor to have fewer cycles per instruction (CPI) than a complex instruction set computer (CISC). A RISC computer has a small set of simple and general instructions, rather than a large set of complex and specialized ones. The main distinguishing feature of RISC is that the instruction set is optimized for a highly regular instruction pipeline flow. Source: Wikipedia.
CISC: complex instruction set computer. A computer in which single instructions can execute several low-level operations. Source: Wikipedia.
Microcontroller: A microcontroller is a small computer on a single chip incorporating CPU, memory and input/output peripherals. It can be referred to as IC or chip.
Microprocessor: A microprocessor has only a CPU. The Intel I5 is a microprocessor. Other functions like memory etc must be added to the rest of the circuit. It can be referred to as IC or chip. Source: engineersgarage.com.
GPU: Graphics Processing Unit: Powerfull but can handle only limited range of operations like processing graphics or mining bitcoins.
FPGA: field-programmable gate array is also an integrated circuit designed to be configured by a customer or a designer after manufacturing. source: Wikipedia.

Memory

Registers: The status register is a hardware register that contains the current state of the processor. Typically, flags in the status register are modified as effects of arithmetic and bit manipulation operations. For example, a Z bit may be set if the result of the operation is zero and cleared if it is nonzero. Source: Wikipedia.
SRAM DRAM: Static / Dynamic Random-access memory (RAM /ræm/) is a form of computer memory that can be read and changed in any order, typically used to store working data and machine code Source: Wikipedia.
EEPROM: electrically erasable programmable read-only memory. A type of non-volatile memory to store relatively small amounts of data but allowing individual bytes to be erased and reprogrammed. EEPROMs can be programmed and erased in-circuit, by applying special programming signals. Source: Wikipedia.
Flash memory: is a type of EEPROM designed for high speed and high density, at the expense of large erase blocks (typically 512 bytes or larger) and limited number of write cycles (often 10,000). There is no clear boundary dividing the two, but the term “EEPROM” is generally used to describe non-volatile memory with small erase blocks (as small as one byte) and a long lifetime (typically 1,000,000 cycles). Many microcontrollers include both: flash memory for the firmware, and a small EEPROM for parameters and history.
Fuse memory: A typical PROM comes with all bits reading as “1”. Burning a fuse bit during programming causes the bit to read as “0”. The memory can be programmed just once after manufacturing by “blowing” the fuses, which is an irreversible process. A programmable read-only memory (PROM) is a form of digital memory where the setting of each bit is locked by a fuse Source: Wikipedia.

Programming the Hello World board

I already did a little bit of programming of the ATtiny in week 06. I managed to get the LED of my board blinking. Now I am going to load another program that also makes use of the light sensor. I documented the first steps already in week 06, so I’ll be brief.

  1. I use the tinyISP I milled in week 04 and the Hello World board from week 06.
  2. I connect them to each other and the ISP to my computer with the USB cable.
  3. I run avrdude -c usbtiny -p t44
  4. AVRdude recognizes my board and the Blink program I installed still works.
  5. Startup the Arduino IDE.
  6. Under tools I check if the Board is set to ATtiny24/44/84.
  7. Under tools I check if the Processor is set to Attiny44.
  8. Under tools I check if the Programmer is set to tinyISP.
  9. The clock under tools is set to 1MHz internal. I have seen in the datasheet that it can be set to 8MHz if the voltage is at least 2.7V. I leave the default 1MHz for now, not yet knowing what the difference is. I found an how to on how to change clock speed to 16MHz internal: See hackster.io.

Writing a program.

I looked at the programming.pdf referred to in the global lexture. Some notes:

There are 5 basic datatypes you can use in C:
1. int - integer: a whole number.
2. float - floating point value: ie a number with a fractional part.
3. double: a double precision floating point value.
4. char: a single character.
5. void - valueless special purpose type.

You assign VARIABLES to hold data:
int this_year 2020;
char first_initial = ‘T’;

You can make conditional statements to decide what to do with data:
int age = 22;
int above_drinking_age;
If (age >= 21){
above_drinking_age = 1;
} else {
above_drinking_age = 0;
}

I don’t think I can do the Hello Echoboard programming described in the programming.pdf because I think you need a second USB cable. So I’ll start with the Fade example code from the Arduino IDE. Sources: Fade tutorial, PMW tutorial.
PWM: Pulse Width Modulation. This is a way to simulate analog signals with digital means. Digital signals can only be on or off, HIGH or LOW. With PWM you can set the duration of ‘on’ mode, this is called the pulse width. By changing or modulating the pulse width you simulate that the LED is receiving a Voltage between 0V and 5V. What is happening in actuality is that the LED goes on and off so quickly that you eyes think the light intensity is lower than if it were put to a steady 5V.

Example code of Arduino Fade:

/*
  Fade

  This example shows how to fade an LED on pin 9 using the analogWrite()
  function.

  The analogWrite() function uses PWM, so if you want to change the pin you're
  using, be sure to use another PWM capable pin. On most Arduino, the PWM pins
  are identified with a "~" sign, like ~3, ~5, ~6, ~9, ~10 and ~11.

  This example code is in the public domain.

  http://www.arduino.cc/en/Tutorial/Fade
*/

int led = 9;           // the PWM pin the LED is attached to
int brightness = 0;    // how bright the LED is
int fadeAmount = 5;    // how many points to fade the LED by

// the setup routine runs once when you press reset:
void setup() {
  // declare pin 9 to be an output:
  pinMode(led, OUTPUT);
}

// the loop routine runs over and over again forever:
void loop() {
  // set the brightness of pin 9:
  analogWrite(led, brightness);

  // change the brightness for next time through the loop:
  brightness = brightness + fadeAmount;

  // reverse the direction of the fading at the ends of the fade:
  if (brightness <= 0 || brightness >= 255) {
    fadeAmount = -fadeAmount;
  }
  // wait for 30 milliseconds to see the dimming effect
  delay(30);
}

Looking closer at the code:

int led = 9; // the PWM pin the LED is attached to
My LED pin is PA7 as I found out in week 06. However, I do not know if my PA7 is PWM capable. In the datasheet I read: ‘This is also the output pin for the PWM mode timer function.’ (p. 62).

My adjusted code:

// This is a program that fades the LED. It is derived from Arduino example code


//I declare PA7 pin as my LED pin
int led = 7;
int brightness = 0;
int fadeAmount = 5;

//The setup function sets the initial values. Everything between its breackets runs only once until you reset the code. 
void setup () {
// I declare that the led pin (PA7) is an output pin.
    pinMode(led, OUTPUT);
}


// void loop: everything between its breackets keeps on looping. 
void loop() {
    //I set the pin to analog rather than digital.
    analogWrite(led, brightness);
    // change the brightness for next time through the loop:
    brightness = brightness + fadeAmount;
    // reverse the direction of the fading at the ends of the fade:
    if (brightness <=0 || brightness >= 255) {
      fadeAmount = -fadeAmount;
    }
    // wait for 30 milliseconds to see the dimming effect
    delay(30);
}

And it works :).
I did not start up AVRdude in the terminal before running the code in the Arduino IDE. So appearantly that is not necessary. There are AVRdude outputs in the Arduino window. So appearantly AVRdude is integrated in Arduino.

Programming in C

I am now going to try to program the Fade code in C and upload it to the microcontroller with the MAKE development environment.

/* This program  fades the LED in and out. It is derived from Arduino example code. I'll rewrite it in a way that it can be uploaded to the board without using the Arduino IDE. 

Desciption of the program:
repeat forever
Set LED to zero
For each loop increase brightness of loop with fadeAmount. 
When brightness is 255 reset back to zero.
wait an amount of milliseconds with repeating the loop so the fade is witnessable.
*/

/*C programs always start by running a special function called 'main'. A function is an encapsulated block of code. So we wrap our while loop in a main function. The main function can only handle integers. But in our case it does not take any input so we declare void. 
*/
int main (void) {

//While defines a loop. 'while will run until the condition in the "()" is FALSE. in this case it runs forever because 1 is always TRUE.
while (1) {

//defining 

}


}

This is not going very well. I look up at the Arduino forum. Here is discussed exactly what I am trying to do and some C-code is shared:

int a= 0;    // i use this for brightness 

void loop() 
{
  for(a = 255; a >= 0; a = a - 10)
  {
     // set the brightness of pin 7:
     analogWrite(9, a);   
    // wait for 30 milliseconds to see the dimming effect   
    delay(30);                           
  }
//put a second for loop, analogWrite() and delay() here to fade from 0 to 255
}

When I run this through the online C compiler onlinegdb.com I get an error about ‘main’. So I add the ‘main’ function. I also change my pin to 7.

int main (void) {
int a= 0;    // i use this for brightness 

void loop() 
{
  for(a = 255; a >= 0; a = a - 10)
  {
     // set the brightness of pin 7:
     analogWrite(7, a);   
    // wait for 30 milliseconds to see the dimming effect   
    delay(30);                           
  }
//put a second for loop, analogWrite() and delay() here to fade from 0 to 255
}
}

I get to warnings: ‘implicit declaration of function ‘analogWrite’‘ and ‘implicit declaration of function ‘delay’. So I do:

int main (void) {
int a= 0;    // i use this for brightness 
int led = 7;
pinMode(led, OUTPUT);

void loop() 
{
  for(a = 255; a >= 0; a = a - 10)
  {
     // set the brightness of pin 7:
     analogWrite(7, a);   
    // wait for 30 milliseconds to see the dimming effect   
    delay(30);                           
  }
//put a second for loop, analogWrite() and delay() here to fade from 0 to 255
}
}

Even more warnings about implicitness; pinmode and output. I think I need to define the pins and other stuff too. But I am grasping in the dark here. I try to write C by just jumping in somewhere. It will take hours to look up every specific thing. It seems more usefull at this point to do some introductory beginners thing. So I abandon this quest.

Via a 2017 FabAcademy page I find a turorial on how to blink a light in C. Here I learn how to define the LED pin. I go over the example code line by line. In the comments in the code I wrote down what every line means.

//Blink the LED of the Echoboard written in C. Based on a tutorial by tinusaur: https://tinusaur.org/tutorials/tutorial-001-blinking-led-x1/


//defining that the LED is connected to port PA7. 
#define LED1_PORT PA7

//Standard function that must be included in all C programs. 
int main (void) {

//In this line we define DDRB: the data direction of port A. In the example it is DDRB but they work with a B port pin.
DDRA |= (1 << LED1_PORT);

while (1) {
//This sets LED bit to 1 - LED will be on
    PORTA |= (1 << LED1_PORT);
// Delay function
    _delay_ms(200);
// Set LED bit to 0 - LED will be off
    PORTA |= ~(1 << LED1_PORT);
// delay function
    _delay_ms (400);
    }
    return (0);
}

I upload the code with the Arduino to see if it works. Arduino spots a mistake, a rogue semicolon that sneaked into the code. When I remove that Arduino gives the okay. I upload the code. It works, sort of. The code uploads. But the LED does not blink but rather stays on.
The mistake was in the PORTA &= ~(1 << LED1_PORT); I used |= but it should be &=. Reason I did |= is that the example code was garbled at some places. It had translated << into &lt;&lt;. So I thought &= was a garblization too. I had expected that setting LED to 0 would closely resemble set LED to 1. But there are quite some differences.
This is the correct code and the LED blinks.

//Blink the LED of the Echoboard written in C. Based on a tutorial by tinusaur: https://tinusaur.org/tutorials/tutorial-001-blinking-led-x1/


//defining that the LED is connected to port PA7. 
#define LED1_PORT PA7

//Standard function that must be included in all C programs. 
int main (void) {

//In this line we define DDRB: the data direction of port A. In the example it is DDRB but they work with a B port pin.
DDRA |= (1 << LED1_PORT);

while (1) {
//This sets LED bit to 1 - LED will be on
    PORTA |= (1 << LED1_PORT);
// Delay function
    _delay_ms(200);
// Set LED bit to 0 - LED will be off
    PORTA &= ~(1 << LED1_PORT);
// delay function
    _delay_ms (400);
    }
    return (0);
}

Using the MAKE development environment

Now that I know the code works, I am going to try to use a different development environment to upload the code.
I copy the above code to a new file in Sublime editor and save as blink.c.
I installed Make in week 04. For sources on how to use it I querry Oliver Bucklin’s FabAcademy page and the programming.pdf and a MAkE tutorial from FabAcademy.
You need to make a MAKE file. You do this by creating a file in a text editor and than save it without an extension. Save this file in the same directory as your .c file.
The project name in the MAKE file must be the same as the .c file. In my case ‘blink.c’.
MMCU is to define the microcontroller you use. F_CPU Frequency of the board to program. I copied my value from the code used in the programming.pdf because that is for an ATtiny44 too.
Then there are CFLAGS: compiler flags. I don’t really know what I should put down there. I reuse the ones from Neil’s file.
The rest of the lines initialize the process, accoring to the MAKE tutorial. They tell the compiler to make an .o and a .hex file using avr.

PROJECT=blink
SOURCES=$(PROJECT).c
MMCU=attiny44
F_CPU = 20000000

CFLAGS=-mmcu=$(MMCU) -Wall -Os -DF_CPU=$(F_CPU)

$(PROJECT).hex: $(PROJECT).out
    avr-objcopy -O ihex $(PROJECT).out $(PROJECT).c.hex;\
    avr-size --mcu=$(MMCU) --format=avr $(PROJECT).out

$(PROJECT).out: $(SOURCES)
    avr-gcc $(CFLAGS) -I./ -o $(PROJECT).out $(SOURCES)

These lines are followed by terminal commmands that are defined in the MAKE file and will be executed upon running it. Lines like:

program-usbtiny: $(PROJECT).hex
    avrdude -p t44 -P usb -c usbtiny -U flash:w:$(PROJECT).c.hex

I look again at Neil’s file in the programming.pdf. There are four more lines.
The first two lines tell what programmer to use. And I use the usbtiny too. The second two lines say something on how to program the fuses. I have no idea if these are the correct fuses for my blink code.

program-usbtiny: $(PROJECT).hex
    avrdude -p t44 -P usb -c usbtiny -U flash:w:$(PROJECT).c.hex

program-usbtiny-fuses: $(PROJECT).hex
    avrdude -p t44 -P usb -c usbtiny -U lfuse:w:0x5E:m

According to the programming.pdf you don’t need to touch the MAKE file. You only have to change the board name and file name. That seems kind of counter intuitive. What if you use a different programmer?

I now go back to the MAKE commands we used in week 04.

avrdude -c usbtiny -p t44 checks if the usbtiny is recognized.
make builds the .hex file.
make flash uses the programmer to load it onto the target chip.
make fuses programs the fuses bits on the target chip.

Make sure you cd into the directory with your MAKE and .c file before executing these commands.

I run make in the proper directory.
output:
make: *** No targets specified and no makefile found. Stop.

I try make blink as input.
This outputs: make: 'blink' is up to date.

I look at the MAKE file from week 04. It is named Makefile. I rename my file as such and run the command again. That works.
Output:

avr-gcc -mmcu=attiny44 -Wall -Os -DF_CPU=20000000 -I./ -o blink.out blink.c
blink.c: In function ‘main’:
blink.c:11:1: error: ‘DDRA’ undeclared (first use in this function)
 DDRA |= (1 << LED1_PORT);
 ^
blink.c:11:1: note: each undeclared identifier is reported only once for each function it appears in
blink.c:5:19: error: ‘PA7’ undeclared (first use in this function)
 #define LED1_PORT PA7
                   ^
blink.c:11:15: note: in expansion of macro ‘LED1_PORT’
 DDRA |= (1 << LED1_PORT);
               ^
blink.c:15:2: error: ‘PORTA’ undeclared (first use in this function)
  PORTA |= (1 << LED1_PORT);
  ^
blink.c:17:2: warning: implicit declaration of function ‘_delay_ms’ [-Wimplicit-function-declaration]
  _delay_ms(200);
  ^
Makefile:14: recipe for target 'blink.out' failed
make: *** [blink.out] Error 1

There are undeclared identifiers: DDRA, PA7. PORTA. And an implicit declaration _delay_ms.
I go back to Oliver Bucklin’s page and look at his code. The first two lines are:

#include <avr/io.h>
#include <avr/interrupt.h>

Libraries. These are probably libraries being called upon to do some of the declaring. I go back to the example code of the blink program in C. And indeed. There are two lines I had not noticed before:

#include <avr/io.h>
#include <util/delay.h>

The util/delay one is a good sign, it’ll probably solve the ‘implicit declaration _delay_ms‘ one.
The avr/io.h one is called upon in all the programs I look at: Oliver’s, Neil’s and the example code. Probably a much used library.

I add the two lines to the blink.c and run make again.
output:

avr-gcc -mmcu=attiny44 -Wall -Os -DF_CPU=20000000 -I./ -o blink.out blink.c
avr-objcopy -O ihex blink.out blink.c.hex;\
avr-size --mcu=attiny44 --format=avr blink.out
AVR Memory Usage
----------------
Device: attiny44

Program:     100 bytes (2.4% Full)
(.text + .data + .bootloader)

Data:          0 bytes (0.0% Full)
(.data + .bss + .noinit)

And in my directory there are now a blink.hex file and blink.out file.

I run make flash.
output:
make: *** No rule to make target 'flash'. Stop.

The commands we used in week 04 were described in the MAKEfile. Maybe make flash is not a command that always works, but was specifically defined in that code. I look for a MAKE tutorial online and find ladyada.net. There the code is put on the chip using AVRdude. The example there is: avrdude -c usbtiny -p attiny2313 -U flash:w:test_leds.hex. I use avrdude -p t44 -P usb -c usbtiny -U flash:w:$(PROJECT).c.hex which is the AVR command I defined earlier in the MAKE file, replacing (PROJECT) with the name of my project: blink.

input: avrdude -p t44 -P usb -c usbtiny -U flash:w:$blink.c.hex

output:

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.00s

avrdude: Device signature = 0x1e9207 (probably t44)
avrdude: NOTE: "flash" memory has been specified, an erase cycle will be performed
         To disable this feature, specify the -D option.
avrdude: erasing chip
avrdude: reading input file ".c.hex"
avrdude: error opening .c.hex: No such file or directory
avrdude: can't determine file format for .c.hex, specify explicitly
avrdude: read from file '.c.hex' failed

avrdude: safemode: Fuses OK (E:FF, H:DF, L:62)

avrdude done.  Thank you.

Something happened. The LED that was in a fading loop from a previous program, is now off. Hope it’s not permanently damaged :/.
Using Arduino I reload the Fade program and LED is in fade mode again. Pfew.

I now see I removed the (PROJECT) from the re-used line but not the ‘$’ before it. I try again:

input: avrdude -p t44 -P usb -c usbtiny -U flash:w:blink.c.hex

output:

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.00s

avrdude: Device signature = 0x1e9207 (probably t44)
avrdude: NOTE: "flash" memory has been specified, an erase cycle will be performed
         To disable this feature, specify the -D option.
avrdude: erasing chip
avrdude: reading input file "blink.c.hex"
avrdude: input file blink.c.hex auto detected as Intel Hex
avrdude: writing flash (100 bytes):

Writing | ################################################## | 100% 0.20s

avrdude: 100 bytes of flash written
avrdude: verifying flash memory against blink.c.hex:
avrdude: load data flash data from input file blink.c.hex:
avrdude: input file blink.c.hex auto detected as Intel Hex
avrdude: input file blink.c.hex contains 100 bytes
avrdude: reading on-chip flash data:

Reading | ################################################## | 100% 0.26s

avrdude: verifying ...
avrdude: 100 bytes of flash verified

avrdude: safemode: Fuses OK (E:FF, H:DF, L:62)

avrdude done.  Thank you.

And it works! The LED blinks. There is a lot of delay between off-mode and on-mode but it blinks.
I make another blink program: blink2. I change the values to 20 ms delay instead of 200 and then the LED blinks like I want it to.

Overview steps MAKE development environment

  1. Write a program in C in a text editor.
  2. Save as ‘projectname.C’.
  3. Make a MAKEfile. Save without an extension.
  4. You must always name it ‘Makefile’.
  5. The Project name in the first line of the Makefile must be the same as the name of your C code file (see example below).
  6. Makefile and .C file must be in the same directory.
  7. cd into that directory.
  8. Run make. A .hex file and out. file should be produced.
  9. Run avrdude -c usbtiny -p t44 to see if your programmer is recognized.
  10. The idea is that the AVR commands at the bottom of the Makefile are run automatically. That did not work for me. But you can just run the commands in the terminal. (Still in the right directory).
  11. avrdude -p t44 -P usb -c usbtiny -U flash:w:$(PROJECT).c.hex where you replace $(PROJECT) with the name of your project.

Example of Makefile for ATtiny44. In this example the filename for the c code is blink2.c

PROJECT=blink2
SOURCES=$(PROJECT).c
MMCU=attiny44
F_CPU = 20000000


CFLAGS=-mmcu=$(MMCU) -Wall -Os -DF_CPU=$(F_CPU)

$(PROJECT).hex: $(PROJECT).out
    avr-objcopy -O ihex $(PROJECT).out $(PROJECT).c.hex;\
    avr-size --mcu=$(MMCU) --format=avr $(PROJECT).out

$(PROJECT).out: $(SOURCES)
    avr-gcc $(CFLAGS) -I./ -o $(PROJECT).out $(SOURCES)



program-usbtiny: $(PROJECT).hex
    avrdude -p t44 -P usb -c usbtiny -U flash:w:$(PROJECT).c.hex

program-usbtiny-fuses: $(PROJECT).hex
    avrdude -p t44 -P usb -c usbtiny -U lfuse:w:0x5E:m

Programming button

In week 06 I tried to upload [code written by my class mate Harm to test the photosensor. I did not succeed then. Now I’m going to try it again.

This is Harm’s code:

int ledPin = 7;
int buttonPin = 3;
int knoppie = 0;
int sensorPin = 2;

void setup() {
  pinMode(ledPin, OUTPUT);
  pinMode(buttonPin, INPUT_PULLUP);
}

void loop() {
  knoppie = digitalRead(buttonPin);
  int sensorWaarde = analogRead (sensorPin);

  if (knoppie) {
    digitalWrite(ledPin, HIGH);
  }  else {
    digitalWrite(ledPin, HIGH);
    delay (sensorWaarde / 50); //I divided the sensor-value by 50, it was trail and error. 
    digitalWrite(ledPin, LOW);
    delay (sensorWaarde / 50);
  }
}

Here is my adjusted code:

/* Code written by Harm https://fabacademy.org/2020/labs/waag/students/harm-vanvugt/posts/2020/03/04/week06.html. Goal is to test the Hello Echo board's LED light sensor and switch. The LED is on by default. When you press the button, the LED blinks with the frequency of the light on the phototransistor.  
*/
int ledPin = 7;
int buttonPin = 3;
int knoppie = 0;
int sensorPin = 2;

void setup() {
  pinMode(ledPin, OUTPUT);
  pinMode(buttonPin, INPUT_PULLUP);
}

void loop() {
  knoppie = digitalRead(buttonPin);
  int sensorWaarde = analogRead (sensorPin);

  if (knoppie) {
    digitalWrite(ledPin, HIGH);
  }  else {
    digitalWrite(ledPin, HIGH);
    delay (sensorWaarde / 50); //I divided the sensor-value by 50, it was trial and error. 
    digitalWrite(ledPin, LOW);
    delay (sensorWaarde / 50);
  }
}

The code loads but it does not seem to work as it did with Harm. He showed me how different light intensity would make the LED blink at different speeds. This does not happen with my board.

/* Code written by Harm https://fabacademy.org/2020/labs/waag/students/harm-vanvugt/posts/2020/03/04/week06.html. Goal is to test the Hello Echo board's LED light sensor and switch. The LED is on by default. When you press the button, the LED blinks with the frequency of the light on the phototransistor.  
*/
int ledPin = 7;
int buttonPin = 3;
int knoppie = 0;
int sensorPin = 2;
int sensorWaarde = analogRead (sensorPin);

void setup() {
  pinMode(ledPin, OUTPUT);
  pinMode(buttonPin, INPUT_PULLUP);
}

void loop() {
  knoppie = digitalRead(buttonPin);


  if (knoppie) {
    digitalWrite(ledPin, HIGH);
  }  else {
    digitalWrite(ledPin, HIGH);
    delay (sensorWaarde / 50); //I divided the sensor-value by 50, it was trial and error. 
    digitalWrite(ledPin, LOW);
    delay (sensorWaarde / 50);
  }
}

I abandon Harm’s code for now and try to write a program in C to use the switch on the board. On via Andrew Kriebels’ FabAcademy page I find a FabAcademy tutorial to write C code for the switch in three different ways.

The first version is interesting. Here actual bits are used to set the pins. Instead of HIGH you have to set an actual 1 to set the function of a pin.

/*
   Demo of the simplest on/off button code for Tiny44
   Button connected to PA5 (physical pin 8 on tiny44)
   Red LED connected to PB2 (physical pin 5 of tiny44)

   For details on the use of the registers PORtx, DDRx, and PINx  (where x = A or B) see tutorials on AVR programming.

  This program was written by Robert Hart as a simple demonstration of programming AVR microcontrollers. 


*/

// ------- Preamble -------- //
#include <avr/io.h>

int main(void) {
  // -------- Inits --------- //
  PORTA = 0b00100000;                       /* initialize pullup resistor on our input pin by setting bit 5 of register PORTA high. */
  DDRB = 0b00000100;                        /* set up pin 2 of port B for output by setting bit 2 of register DDRB high.*/

  // ------ Event loop ------ //
  while (1) {
                                            /* look for button press */
     if ((PINA & 0b00100000) == 0 ) {       /* test to see if bit 5 of PINA is low  */
      PORTB = 0b00000100;                   /* turn on LED on pin 3 of port B if bit is low (button is pressed) */
    }
    else {                                  /* otherwise */
      PORTB = 0b00000000;                   /* leave output low.    */
    }
   }                                        

                                             /* End event loop */
  return (0);   
 }

For instance: PORTA = 0b00100000. This refers back to the datasheet of the ATtiny. Under Chapter 10.1 - ‘Ports as General Digital I/O’ it says that each port has three registers. There is PORTxn (for instance PORTA7). There is DDxn: with the DDR register you can set the direction of the pin (input/output). Form the datasheet: ‘The DDxn bit in the DDRx Register selects the direction of this pin. If DDxn is written logic one, Pxn is configured as an output pin. If DDxn is written logic zero, Pxn is configured as an input pin.’
On page 67 of the datasheet the register description is given. Here you can see the registers of PORTB Data registerand the PORTB Data Direction Register (DDR). In the example code you see DDRB = 0b00000100. So looking at the datasheet you can see that DDR of PORTB2 is is now switched on to be an output pin.

Based on this I adjust the code for my own pins. See below. As I go along there are some insights/questions that I describe here.

Pull-up resistor
A pull-up resistor determines whether your pin is HIGH (pulled to VCC) or LOW (pulled to GND). From Sparkfun: ‘Let’s say you have an MCU with one pin configured as an input. If there is nothing connected to the pin and your program reads the state of the pin, will it be high (pulled to VCC) or low (pulled to ground)? It is difficult to tell. This phenomena is referred to as floating. To prevent this unknown state, a pull-up or pull-down resistor will ensure that the pin is in either a high or low state, while also using a low amount of current. Pull-ups are often used with switches. With a pull-up resistor it will read as HIGH when the button is not pressed. In other words, a small amount of current is flowing between VCC and the input pin (not to ground), thus the input pin reads close to VCC. When the button is pressed, it connects the input pin directly to ground. The current flows through the resistor to ground, thus the input pin reads a low state. Keep in mind, if the resistor wasn’t there, your button would connect VCC to ground, which is very bad and is also known as a short.’

0B
“0b” means that everything that follows is binary. YLI fabacademy page

About: if ((PINA & 0b00100000) == 0 ) in the original code. I understand we have set the the pin of the switch to high. If we press the switch voltage will be zero, so state will be LOW. What I don’t understand is is where PINA comes from. My switch is connected to PORTA3. Should I not specify as PINA3 instead of PINA? In the example code the switch is on PORT B and the LED is on PORT A. But in my case they are both on PORTA. How does the machine know that when I say PINA I mean PINA3?
The same goes for the next line: here the example code only refers to PORTB. But again. My LED and switch are both on PORTA. So how do I specify that?
I am going to try by specifying the port numbers of the pins. So PINA3 for the switch and PORTA 7 for the LED.
Wait, I don’t need to specify PORTA7. Because the code says that if x, then put register bit of PORTA7 to HIGH. So the PORTA specifies the PORT. The bit sequence specifies which pin (PA7).
And the same goes for the PINA thing. It checks PORTA and the bits declare that it must check pin 3.
I think I now rewrote the code to fit my pinout. I going to make this into a MAKE file and see if it works.

This is the adjusted code:

/*
Demo of the simplest on/off button code for Tiny44. 
This is adjusted code based on the example code of Robert Hart: http://fab.cba.mit.edu/classes/863.15/doc/tutorials/programming/Simple_examples/c_prog_examples.html. 

This code works by directly manipulating the register bits

In my case: 
Button connected to PA3 (physical pin 10 of tiny44)
Yellow LED connected to PA7 (physical pin 6 of tiny44)

For details on the use of the registers PORtx, DDRx, and PINx  (where x = A or B) see tutorials on AVR programming.

This program was written by Robert Hart as a simple demonstration of programming AVR microcontrollers. 


*/

// ------- Preamble -------- //
/*This is a library that needs to be called upon for MAKE to know what to make of the code*/

#include <avr/io.h>                       

/* int main is a special function. It is added to all C code. All other functions are wrapped inside this function*/
int main(void) {                            
  // -------- Inits --------- //

/* initialize pullup resistor on our input pin (switch) by setting the bit of PA3 of register PORTA high. Check page 66 of the ATtiny datasheet for the register description.*/ 
  PORTA = 0b00001000;       
 /* Here we declare the LED pin PA7 as output pin by setting the DDA7 bit in the DDRA register to high.  (datatsheet p.66) */           
  DDRA = 0b10000000;                       

  // ------ Event loop ------ //
  /*while (1) declares a loop because 1 is always true.*/
  while (1) {
/* look for button press */                                             
     if ((PINA3 & 0b00001000) == 0 ) {      /* test to see if bit 3 of PINA is low  */
      PORTA = 0b10000000;                   /* turn on LED on pin 7 of port A if bit is low (button is pressed) */
    }
    else {                                  /* otherwise */
      PORTA = 0b00000000;                   /* leave output low.    */
    }
   }                                        

                                             /* End event loop */
  return (0);   
 }

I make a Makefile using the MAKE overview steps described above. Make creates a .hex and .out file. Then I run: avrdude -c usbtiny -p t44
and avrdude -p t44 -P usb -c usbtiny -U flash:w:$(PROJECT).c.hex. Replacing $(PROJECT) with my project name switch1.

Output AVR;

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.00s

avrdude: Device signature = 0x1e9207 (probably t44)
avrdude: NOTE: "flash" memory has been specified, an erase cycle will be performed
         To disable this feature, specify the -D option.
avrdude: erasing chip
avrdude: reading input file "switch1.c.hex"
avrdude: input file switch1.c.hex auto detected as Intel Hex
avrdude: writing flash (68 bytes):

Writing | ################################################## | 100% 0.21s

avrdude: 68 bytes of flash written
avrdude: verifying flash memory against switch1.c.hex:
avrdude: load data flash data from input file switch1.c.hex:
avrdude: input file switch1.c.hex auto detected as Intel Hex
avrdude: input file switch1.c.hex contains 68 bytes
avrdude: reading on-chip flash data:

Reading | ################################################## | 100% 0.24s

avrdude: verifying ...
avrdude: 68 bytes of flash verified

avrdude: safemode: Fuses OK (E:FF, H:DF, L:62)

avrdude done.  Thank you.

But the program does not work. LED is on and does not switch off when pressing the button.

Perhaps code is wrong but I must also consider if perhaps my switch is not working.

Debugging table:

Description status
Is switch working

I check the code and see I made a mistake if ((PINA3 & 0b00001000) == 0 ). It is still named PINA3. Even though I decided to name it PINA. I change code and try again.
The LED still does not go on/off. But it seems as if the LED burns brighter when switch is pushed in.

Output AVRdude

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.00s

avrdude: Device signature = 0x1e9207 (probably t44)
avrdude: NOTE: "flash" memory has been specified, an erase cycle will be performed
         To disable this feature, specify the -D option.
avrdude: erasing chip
avrdude: reading input file "switch3.c.hex"
avrdude: input file switch3.c.hex auto detected as Intel Hex
avrdude: writing flash (76 bytes):

Writing | ################################################## | 100% 0.21s

avrdude: 76 bytes of flash written
avrdude: verifying flash memory against switch3.c.hex:
avrdude: load data flash data from input file switch3.c.hex:
avrdude: input file switch3.c.hex auto detected as Intel Hex
avrdude: input file switch3.c.hex contains 76 bytes
avrdude: reading on-chip flash data:

Reading | ################################################## | 100% 0.24s

avrdude: verifying ...
avrdude: 76 bytes of flash verified

avrdude: safemode: Fuses OK (E:FF, H:DF, L:62)

avrdude done.  Thank you.

I read in the datasheet that you must give specific PORT numbers: ‘However, when using the register or bit defines in a program, the precise form must be used. For example, PORTB3 for bit no. 3 in Port B’.
So maybe I do need to number all the ports.

This results in this code:

#include <avr/io.h>                       

/* int main is a special function. It is added to all C code. All other functions are wrapped inside this function*/
int main(void) {                            
  // -------- Inits --------- //

/* initialize pullup resistor on our input pin (switch) by setting the bit of PA3 of register PORTA high. Check page 66 of the ATtiny datasheet for the register description.*/ 
  PORTA3 = 0b00001000;          
 /* Here we declare the LED pin PA7 as output pin by setting the DDA7 bit in the DDRA register to high.  (datatsheet p.66) */           
  DDRA = 0b10000000;                       

  // ------ Event loop ------ //
  /*while (1) declares a loop because 1 is always true.*/
  while (1) {
/* look for button press */                                             
     if ((PINA3 & 0b00001000) == 0 ) {      /* test to see if bit 3 of PINA is low  */
      PORTA7 = 0b10000000;                   /* turn on LED on pin 7 of port A if bit is low (button is pressed) */
    }
    else {                                  /* otherwise */
      PORTA7 = 0b00000000;                  /* leave output low.    */
    }
   }                                        

                                             /* End event loop */
  return (0);   
 }

AVRdude output:

 avr-gcc -mmcu=attiny44 -Wall -Os -DF_CPU=20000000 -I./ -o switch3.out switch3.c
switch3.c: In function ‘main’:
switch3.c:26:10: error: lvalue required as left operand of assignment
   PORTA3 = 0b00001000;    
          ^
switch3.c:35:11: error: lvalue required as left operand of assignment
    PORTA7 = 0b10000000;                   /* turn on LED on pin 7 of port A if bit is low (button is pressed) */
           ^
switch3.c:38:14: error: lvalue required as left operand of assignment
       PORTA7 = 0b00000000;     /* leave output low. */
              ^
Makefile:14: recipe for target 'switch3.out' failed
make: *** [switch3.out] Error 1

Reading Stackoverflow and geeksforgeeks on lvalue:

lvalue means an assignable value (variable), and in assignment the left value to the = has to be lvalue (pretty clear).

Both function results and constants are not assignable (rvalues), so they are rvalues. so the order doesn’t matter and if you forget to use == you will get this error. (edit:)I consider it a good practice in comparison to put the constant in the left side, so if you write = instead of ==, you will get a compilation error.’

I think it means that the designator on the left site of the ‘=’ must be open/assignable. As is is assigned by the writing on the right side of the ‘=’. So you can’t have a static value (pin 7) on the left, if the right side is an assigner (Set pin 7 HIGH).

So this is not the answer.

I look at Andrew Kriebels code. He has the same pin-out on the same place as I do. I compare our code mark for mark. I don’t see a difference. Perhaps it isn’t the code but the switch itself. Andrew has pictures of his code, so I can’t copy it. (To check if the error is with my switch or my code.). So I copy a part of the code and run it through the FabAcademy search engine.
I find a page with code from YLi. I just copy the code, and use Arduino IDE to check my board.
It works! LED is off by default and goes on when switch is pressed. So the switch works!
I also upload code via MAKE environment, to see if that is where the error occurs.
Works with MAKE too.

So what is the difference between that code and mine?

YLi’s code:

#include <avr/io.h>

int main(void) {
DDRA = 0b10000000; //Data direction register, "0b" means that everything that follows is binary; 0 is input into, 1 is output out of microcontroller. Start counting from the right.
PORTA = 0b00001000; //Setting PA3 high to set/initialize the pull-up resistor in Attiny44.
while(1){

/*
The conditions in the "if" statement: 
When button is not pressed (the switch is not closed), 
the 5V of supply voltage of the ATTINY44 will flow through the pull-up resistor inside the ATTINY44,
and PA3 will be at 5V and a "high" state (1). 
When button is pressed (the switch is closed),
PA3 will be connected to ground and it will be at 0V or a "low" state (0).

When button is pressed, PINA = 0bxxxx0xxx; when button is not pressed, PINA = 0bxxxx1xxx. 
x stands for the state of other pins, which could either be 0 or 1.

If let's say PINA = 0b00000000 when button is pressed and PINA = 0b00001000 when button is not pressed,
then when button is pressed, (0b00000000 & 0b00001000) will give us a 0 because they have nothing in common.
When button is not pressed, (0b00001000 & 0b00001000) will give us a non-zero number. In this case, the "and" 
operation will return an 8 because they have "1000" in common and 2^3 = 8.

So when button is not pressed, the return value of the "and" operation is 8, and 8 is true,
so statement in "if" - "PORTA = 0b00001000" - will be carried out and the LED is off, because PA7 is low.
When button is pressed, the return value of the "and" operation is 0, and 0 is false. 
So the "else" statement "PORTA = 0b10001000" will be carried out and the LED is on, because PA7 is high.
*/

if (PINA & 0b00001000){ //PINA is the register that is read to detect input high or low.

    PORTA = 0b00001000; //We write to PORTA for output or to set pull-up resistor. Keeping the pull-up resistor high, now turn off LED by setting PA7 low
}

else{
    PORTA = 0b10001000; //Keeping the pull-up resistor high, now turn on LED by setting PA7 high
}

}
return (0);

}

PINA
PORT A Input Pins (datasheet p.67).
Each pin has has three register bits. DDxn PORTxn and PINxn. Each register has its own address. The PINxn bits are adressed at the PINx address. (from the datasheet p.54) So, taken that with stuff I discovered previously the PINA statement in the code just states that whatever follows is about the

Summerizing:
The IC has 2 PORTs (A and B). Each port has 3 memory address locations. One Data Direction register. Here we determine if a pin is input or output. When we state: DDRA = 0b0000001, we determine that for PORTA the PA0 is an output pin, the rest are input pins.
PORTx addresses the data register. This determines wheter the pin is set to HIGH or lOW. Arduino.cc. The PIN register reads the state of INPUT pins. (IN Arduino language referred to as pinMode).

So if I look at my code I see if ((PINA & 0b00001000) == 0 ). So that means, listen in on PORTA. Check if the pull-up resistor (that is on by default) is off (= 0).

The difference between YLi’s code and the example code is that YLi always has the bit for the pullup register high. Whereas the example code only addresses the LED bit. Compare example code for LED on PORTA = 0b10000000 to YLi’s PORTA = 0b10001000. YLi turns on fourth bit, the pull-up resistor, while the example code does not. When I copy this behavior in my example-derived code, it works.

The final example-derived code:

/*
Demo of the simplest on/off button code for Tiny44. 
This is adjusted code based on the example code of Robert Hart: http://fab.cba.mit.edu/classes/863.15/doc/tutorials/programming/Simple_examples/c_prog_examples.html. & with adjustments of YLi: http://fab.cba.mit.edu/classes/863.15/section.Harvard/people/YLi/Week%207%20-%20Embedded%20Programming/Ye_001.c

This code works by directly manipulating the register bits

In my case: 
Switch connected to PA3 (physical pin 10 of tiny44)
Yellow LED connected to PA7 (physical pin 6 of tiny44)

For details on the use of the registers PORtx, DDRx, and PINx  (where x = A or B) see tutorials on AVR programming.

This program was written by Robert Hart as a simple demonstration of programming AVR microcontrollers. 
*/

// ------- Preamble -------- //
/*This is a library that needs to be called upon for MAKE to know what to make of the code*/

#include <avr/io.h>                       

/* int main is a special function. It is added to all C code. All other functions are wrapped inside this function*/
int main(void) {                            
  // -------- Inits --------- //

/* initialize pullup resistor on our input pin (switch) by setting the bit of PA3 of register PORTA high. Check page 66 of the ATtiny datasheet for the register description.*/ 
  PORTA = 0b00001000;       
 /* Here we declare the LED pin PA7 as output pin by setting the DDA7 bit in the DDRA register to high.  (datatsheet p.66) */           
  DDRA = 0b10000000;                       

  // ------ Event loop ------ //
  /*while (1) declares a loop because 1 is always true.*/
  while (1) {
/* look for button press */                                             
     if ((PINA & 0b00001000) == 0 ) {       /* test to see if bit 3 of PINA is low  */
      PORTA = 0b10001000;                   /* turn on LED on pin 7 of port A if bit is low (button is pressed) */
    }
    else {                                  /* otherwise */
      PORTA = 0b00001000;                   /* leave output low.    */
    }
   }                                        

                                             /* End event loop */
  return (0);   
 }

Button works:

Programming phototransistor

First looked at this code of instructables but did not get it to work. Then found this code on an Arduino Forum.

// On-Board LED and Phototransistor: Code from Arduino forum https://forum.arduino.cc/index.php?topic=3636.0

int analogPin=3; //phototransistor connected to analog pin 3
int ledPin=13; //led is connected to pin 13 (on-board led)
int voltm=0;

void setup()
{pinMode(ledPin,OUTPUT);

Serial.begin(9600);
}

void loop()
{voltm=analogRead(analogPin); //read the phototransistor
Serial.println(voltm);
if (voltm>200)
{digitalWrite(ledPin,HIGH);}
else
{digitalWrite(ledPin,LOW);}
}

Changed the pin numbers, ran it, but the verification process reported in red letters about ‘serial’. I removed all ‘Serial’related lines and then the code worked.

Adapted code from Arduino forum:

// On-Board LED and Phototransistor. Adapted from code from Arduino forum https://forum.arduino.cc/index.php?topic=3636.0

int analogPin=2; //phototransistor connected to analog pin 2
int ledPin=7; //led is connected to pin 7 (on-board led)
int voltm=0;

void setup()
{pinMode(ledPin,OUTPUT);


}

void loop()
{voltm=analogRead(analogPin); //read the phototransistor
if (voltm>200)
{digitalWrite(ledPin,HIGH);}
else
{digitalWrite(ledPin,LOW);}
}

So now I know my phototransistor works.

Zip

I upload my source files as zip files. But I notice that the directories are empty. Looking back at previous weeks they are all empty.
Stackoverflow answers: use the recursive flag -R when zipping folders: zip -r folder.zip folder. And/or sudo apt-get install zip first. The -r flag works. I go back to the documentation of the previous weeks and re-upload all my zip files.

What went wrong

I had a bit trouble getting started this week. The field of programming ICs is so overwhelmingly vast, that I did not now where to start. I spend the first hours just looking up the meaning of different words and abbreviations on the internet. In retrospect I could have spend that time better by just starting to try to code. Then you run into obstacles and have to look for specific knowledge to answer them. So here we have again the returning theme of my ‘what went wrongs’: instead of plowing on, I halted before the vast unknown and insisted I get my bearings first. It is a boring endeavour and rather dishartening. For the only thing you realize is that the unknown is very very very vast indeed. Best to just get on a little raft and have it move forward by the current. You’ll soon enough realize that you need a sail. And figuring out how the build the sail is when the fun starts. And when your tiny handkerchief-based sail works… Satisfaction! And for some reason, that is when you realize that even though you may not now how to build a foresail let alone a mainsail, you know you’ll be able to one day if you just keep going it at.

What I learned

The thing I liked best were the registers. To set the pins with 0b00001000 type code. Because there is a lot less abstraction than with Arduino code. You really understand that you are manipulating the pins. Telling the IC it should (or should not) run current through pin Pxn. When you compare Arduino code pinMode(led, HIGH); to C-code DDRA = 0b10000000; the C-code is so much more concrete. So much more actually describing what is happpening.
Which is not to say that C is easier. But it does make you understand better what you are doing.

Global lecture

This week is Writing code for processes. The following weeks rest heavily on this week.

Ben Eater has a really good YouTube series showing how processors work (and how to build a semi-descrete one) up from transitor level: https://www.youtube.com/playlist?list=PLowKtXNTBypGqImE405J2565dvjafglHU

great notes from ferdi on this weeks lesson: https://git.hsrw.eu/ferdinand.meier/fablab/-/wikis/FabAc20_woche08

Local / global review

Tip: you can select a serial monitor output in Arduino.
TinkerCad: Nathan used TinkerCad to test his board first & learn how to write the code. This might be a good thing to use when we have to design a board of our own next week.

global review

How to make (almost) anything during a pandemic. How can our network help the world and how can we help the FabAcademy students

gitlab.cba.mit.edu/pub/coronavirus gitlab/fabclou What is most needed: personal protective gear for frontline health workers.
Swabs
Ventilators

Monday’s recition is about the Fab ecosystem. Recitation will be about responses to Carona response. Industry or DIY will save the day. But the answer is in the middle.

Input devices: what has changed is that you may use a pre-made dev board.
At-home classes are moved to the back. Lab access classes are moved forward in the hope that the pandemic will have been subdued by then.
Final projects are moved to a later date TBA.
MCU room: a 24 hour online space where we can meet each other.