Embedded Programming, March 20
This week  
Presentation Embedded Programming http://academy.cba.mit.edu/classes/embedded_programming/index.html
video of the review (Computer-Controlled Machining http://fab.academany.org/2018/lectures/fab-20180307.html
[video of the lecture http://fab.academany.org/2018/lectures/fab-20180307.html
video of the recitation on safety and security http://fab.academany.org/2018/lectures/fab-20180319.html
Assignment Used software Files/Downloads/links
Group Assignment compare the performance and development workflows for other architectures http://fab.academany.org/2018/labs/fablabamsterdam/week9/index.html
button_on_off.ino Arduino button_on_off.ino

Programming the hello world board

Clocks and Fuses!

Clocks

I was playing with the Oscilloscope, mainly because i think i’ve to use it for my final project (measuring ice thickness with Ultra Sone Sound).

During the local lecture Emma showed us the oscilloscope. Connecting one pin to GND and the other to the LED, we could see the timing of the LED (see the group assignment). We noticed a slightly longer signal on the oscilloscope, around 110ms, instead of the 100ms that we programmed. Emma told us that it had to do the arduino-ide that we used. C has a smaller footprint and uses less resources, and should be more accurate, she told us.

Anyway: i wanted to see it myself!. So i programmed the board with the arduino-ide and C, measured both with the oscilloscope. Here are the results:

with C code

with arduino code

Emma mentioned that it would also be nice to measure the clock, so we went to the attiny84 datasheet. Page 24-32 handles the clock system. The clock subsystems contains:

  • CPU clock
  • I/O clock
  • Flash clock
  • ADC clock

Anyway: here it gets interesting:

So that means that we could get a visual of the clock by the oscilloscope. In the attiny pinout diagram we figured out that it has to be PB2:

Fuses

So according to the datasheet i have to set the fuse.

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

Howto not to do it:

first read the status of the fuse:

avrdude -p t84 -P usb -c usbtiny -U  lfuse:r:-:h

Then i decided to trun the of and after that enable the fuse i need for routing the clock to PB2

avrdude -p t84 -P usb -c usbtiny  -v -U lfuse:w:0x00:m

It was a major victory. It worked as i expected, BUT… By disabling the fuse i also disabled the clock! And without a clock, the avr stop functioning. It took a while for me to understand, but now it seems logical that i bricked my attiny84 on purpose…

I started reading about fuses here (adafruit: what is a fuse) and here (Fabacademy: Understanding Fuses)

Be careful when experimenting with fuses as I bricked one of my boards. There seem to be ways to reset the fuses to factory settings, e.g. through the High Voltage Serial Programming (HVSP) interface, but usually replacing the chip is a cheaper and quicker method.

Fuses are an extremely important part programming a chip, but are rarely explained thoroughly. You only need to set them once, but if you don’t do it right, it’s a disaster!

What is a fuse?

You know about flash, eeprom and RAM as parts of the chip. What I did not mention is that there are also 3 bytes of permanent (by permanent I mean that they stick around after power goes out, but that you can change them as many times as you’d like) storage called the fuses. The fuses determine how the chip will act, whether it has a bootloader, what speed and voltage it likes to run at, etc. Note that despite being called ‘fuses’ they are re-settable and dont have anything to do with protection from overpowering (like the fuses in a home).

The fuses are documented in the datasheets, but the best way to examine the fuses is to look at a fuse calculator such as the avr fuse calculator from the palmavr project </I>

Topic: Help supply clock signal from Arduino (to debrick AVR)

Recovering from a “locked out” AVR

Possible solution is use an external clock from another source.

  • an STK500. This has an on-board clock circuit. In AVR Studio, when you connect to the STK500, you can program this clock to some division of 3.6864MHz
  • an STK600 has a very similar clock circuit though its upper frequency limit is higher than the STK500
  • an NE555 can easily be wired up with a handful of components to generate about 1MHz
  • another AVR can be used if you load a program such as:

Since i had 2nd hello world board i went for option 4. And i used a buspirate flashed with stk500-v2 avr programmer firmware, mainly because it was also mentioned as an option.

using a buspirate to program the board

Using external clock to program a bricked AVR

programmed the working hello world board with this:

it pulses as fast as it can, so is like a clock. I tried to see differences when using the different clock speeds. I used the arduino-ide to do this using the bootloader.

#include <avr/io.h>

int main(void) {
    DDRB = 0xFF;
    while(1) {
        PORTB ^= 0xFF;
    }
}

This is the pulse i get from PB2 now:

connecting oscilloscope to the clock i wanted to use

it was a dirty job. Somewhere it looked like something worked.


avrdude -p t84 -c usbtiny -U lfuse:w:0x6A:m -U hfuse:w:0xFF:m -B250

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.06s

avrdude: Device signature = 0x1e930c (probably t84)
avrdude: reading input file "0x6A"
avrdude: writing lfuse (1 bytes):

Writing | ################################################## | 100% 0.06s

avrdude: 1 bytes of lfuse written
avrdude: verifying lfuse memory against 0x6A:
avrdude: load data lfuse data from input file 0x6A:
avrdude: input file 0x6A contains 1 bytes
avrdude: reading on-chip lfuse data:

Reading | ################################################## | 100% 0.02s

avrdude: verifying ...
avrdude: 1 bytes of lfuse verified
avrdude: reading input file "0xFF"
avrdude: writing hfuse (1 bytes):

Writing |                                                    | 0% 0.00s ***failed;
Writing | ################################################## | 100% 0.16s

avrdude: 1 bytes of hfuse written
avrdude: verifying hfuse memory against 0xFF:
avrdude: load data hfuse data from input file 0xFF:
avrdude: input file 0xFF contains 1 bytes
avrdude: reading on-chip hfuse data:

Reading | ################################################## | 100% 0.02s

avrdude: verifying ...
avrdude: verification error, first mismatch at byte 0x0000
         0xdf != 0xff
avrdude: verification error; content mismatch

avrdude: safemode: hfuse changed! Was ff, and is now df
Would you like this fuse to be changed back? [y/n] y
avrdude: safemode: and is now rescued
avrdude: safemode: Fuses OK (E:FF, H:FF, L:6A)

avrdude done.  Thank you.

Since then there is a clock functioning somewhere on the chip. If i power the board trough the fabisp, the led blinks when i am trying to program it, simultaneous to the led on the fabisp.

Oscilloscope adventures

What is did was the following:

  • Burning the bootloader with different clock settings:
  • Uploading the hello_digital sketch
  • measuring the LED with the oscilloscope

1Mhz internal clock

8Mhz internal clock

8Mhz external clock

16Mhz external clock

20Mhz external clock

One conclusion of the measurements is that the internal clock of the attiny is less accurate then the external 20Mhz resonator on our hello world board.

Programming in arduino-ide (or NOT!)

I programmed the board with the arduino-ide, version 1.8.5.

I use vim as external editor. Its a setting you can select under “file” –> “preferences” in the arduino-ide. Once selected you can’t use the arduini-ide editor anymore, its greyed out. You now can edit the file with your favorite editor and every time the file is written to the FS, the arduino file-buffer is updated. So you can still use the other functions from arduino ide like “verify”, “upload” and select boards and ports.

So the workflow is:

  • open arduino-ide
  • open file in ide
  • open terminal
  • open file in vim
  • edit file in vim
  • write file or close
  • if needed change port and board setting
  • verify code in the arduino-ide
  • upload code

My screen looks like this:

While busy with the fabacademy and researching how to make better use of vim and arduino, i found this page on vim + arduino. It handles about using makefiles to avoid the workflow on editing and uploading in separate environments. Played a bit with and its nice if vim is your primary editor. Compiling Arduino sketches using Makefile. No need to leave vim, no need to switch to the arduino-ide window. And less noise on the computer screen :-)

It’s also possible to program the attiny this way. Place the Makefile in the same directory as the ino file. From within vim, use :make :make ispload to compile/verify or upload the sketch to the board. :make monitor opens the serial, but that only works when compiling for the Arduino with ftdi or other usb2serial connection.

The Makefile looks like this:

# Arduino Make file. Refer to https://github.com/sudar/Arduino-Makefile

# Set this if the IDE is not in your $PATH or you want to use a specific version:
ARDUINO_DIR = $(HOME)/arduino-1.8.5

# Programmer type:
ISP_PROG = usbasp

ALTERNATE_CORE = attiny-master
BOARD_TAG = attiny
BOARD_SUB = attiny85
F_CPU = 16000000L

# Path to the Arduino Makefile
include /usr/share/arduino/Arduino.mk

# !!! Important. You have to use 'make ispload' when using an ISP.

It also includes a python script to generate Makefiles:

usage: ardmk-init [-h] [-v] [-d DIRECTORY] [-b BOARD] [-u MICRO] [-f FREQ]
                  [-p PORT] [-n NAME] [--cli] [-P] [-t] [-V]

Arduino Makefile and boilerplate project generator. For use with Ard-Makefile:
https://github.com/sudar/Arduino-Makefile. Script created by John Whittington
https://github.com/tuna-f1sh 2017 Version: 1.1

optional arguments:
  -h, --help            show this help message and exit
  -v, --verbose         print file contents during creation
  -d DIRECTORY, --directory DIRECTORY
                        directory to run generator, default cwd
  -b BOARD, --board BOARD
                        board tag
  -u MICRO, --micro MICRO
                        microcontroller on board
  -f FREQ, --freq FREQ  clock frequency
  -p PORT, --port PORT  monitor port
  -n NAME, --name NAME  project name
  --cli                 run with user prompts (requires "Clint" module),
                        rather than args
  -P, --project         create boilerplate project with src, lib and bin
                        folder structure
  -t, --template        create bare minimum Arduino source file
  -V, --version         show program's version number and exit

Programming

Arduino Language Reference

Fascinating to see on how many ways you can program the same. I wanted to use the button to switch the led on or off. So it needed tot remember or question the current or last state of the led.

I started with this code and modified it to be used on my board.

First changed the main int settings according to my hello world board (ledpin = 7, button pin = 3). The lastButtonState is set to HIGH, the default state on my board.

Then in the setup function (void setup) i wrote the pin modes. The ledpin as OUTPUT, the buttonpin as INPUT_PULLUP. It monitors the state of the switchbutton. On my hello world board the state is HIGH. When the switchbutton is pushed (make a connection to GND, the state changes to LOW.

Then the programs function loop starts. It grabs the currentButtonState by reading the state of the buttonPin. If the state has changed (currentButtonState == HIGH && lastButtonState == LOW) it changes the state of the ledPin (if read 1, then write 0 == OFF), otherwise change to 1 (ON).

Then store the buttons current state so we can tell if it’s changed next time round.


// found here: https://arduino.stackexchange.com/questions/3479/how-to-toggle-led-on-button-press

int ledPin = 7;
int buttonPin = 3;
int lastButtonState = HIGH;


void setup() {

pinMode(ledPin, OUTPUT);
pinMode(buttonPin, INPUT_PULLUP);
}

void loop()
{
  // Get the current state of the button
  int currentButtonState = digitalRead(buttonPin);

  // Has the button gone high since we last read it?
 if (currentButtonState == HIGH && lastButtonState == LOW) {
     // Switch the state of the output
    if(digitalRead(ledPin))
       digitalWrite(ledPin, 0);
    else
       digitalWrite(ledPin, 1);

  }

  // Store the button's state so we can tell if it's changed next time round
  lastButtonState = currentButtonState;
}

You can make the code a bit smaller by substitute if() else() for this:


void loop()
{
  // Get the current state of the button
  int currentButtonState = digitalRead(buttonPin);

  // Has the button gone high since we last read it?
 if (currentButtonState == HIGH && lastButtonState == LOW) {
     // Switch the state of the output
     digitalWrite(ledPin, !digitalRead(ledPin));
  }

Or make it longer commenting the code and write out everything, counting the amount of pushes and als outputing for serial communication:

/*  The circuit:
  - pushbutton attached to pin 3 from +5V
  - LED attached from pin 7 to ground
*/

// this constant won't change:
const int  buttonPin = 3;    // the pin that the pushbutton is attached to
const int ledPin = 7;       // the pin that the LED is attached to

// Variables will change:
int buttonPushCounter = 0;   // counter for the number of button presses
int buttonState = 0;         // current state of the button
int lastButtonState = 0;     // previous state of the button

void setup() {
  // initialize the button pin as a input:
  pinMode(buttonPin, INPUT);
  // initialize the LED as an output:
  pinMode(ledPin, OUTPUT);
  // initialize serial communication:
  Serial.begin(9600);
}

void loop() {
  // read the pushbutton input pin:
  buttonState = digitalRead(buttonPin);

  // compare the buttonState to its previous state
  if (buttonState != lastButtonState) {
    // if the state has changed, increment the counter
    if (buttonState == HIGH) {
      // if the current state is HIGH then the button went from off to on:
      buttonPushCounter++;
      Serial.println("on");
      Serial.print("number of button pushes: ");
      Serial.println(buttonPushCounter);
    } else {
      // if the current state is LOW then the button went from on to off:
      Serial.println("off");
    }
    // Delay a little bit to avoid bouncing
    delay(10);
  }
  // save the current state as the last state, for next time through the loop
  lastButtonState = buttonState;


  // turns on the LED every four button pushes by checking the modulo of the
  // button push counter. the modulo function gives you the remainder of the
  // division of two numbers:
  if (buttonPushCounter % 2 == 0) {
    digitalWrite(ledPin, LOW);
  } else {
    digitalWrite(ledPin, HIGH);
  }