Week | 9


Embedded Programming


How I’m programming the board I’ve made previously to “do something”.


20 March 2018 09:15:

This week’s assignment is to use the Hello Board I’ve made a couple of weeks ago and program it to do something. Since this is my first experience with programming, I decided to take it slow and take the time to get used with the language and structural aspects of programming, before moving on to something more elaborated.

As already mentioned before, it is highly recommended to search online for the datasheets of each component of your board.

By doing this with the Attiny44 microcontroller I’m using, I was able to know:

  • The Pin Layout (where each pin is located on the component), description (the functionality of each pin) and configuration.

  • The I/O (in and out) ports, meaning, which pins read and write values in the microcontroller memory. Port A pins are 8-bit bi-directional I/O port with internal pull-up resistors (pin names are from PA0 to PA7) and Port B pins are 4-bit bi-directional I/O port with internal pull-up resistors(pin names are from PB0 to PB3).

  • Memory, so we can understand limitations and the layout of different memory types.In this case, 4K Bytes of Flash Program Memory + 256 Bytes of Programmable EEPROM (read-only memory) and 256 bytes SRAM.

  • Operating voltage, which in this case is between 1.8 ~ 5.5V.

A very visual pin layout of the Attiny44 can be found here.

And here’s the complete documentation about the microcontroller we have used, the ATtiny 44. To be able to connect both, the AVR ISP 6-Pin Header and the FTDI SMD Header you have to know where each pin is located. For the example “ State Change detection” below, as an instance, RX and TX where required to program.

The examples below are quite simple and all from Arduino’s sketch library. I understand programming is, like any other language, quite complex and requires time to learn. Since my overall interest in Fab Academy is to get familiarised with multiple digital fabrication techniques, but not necessarily, “master” all of them, I believe I would like to explore the basics about coding only.

Programming the board


1 - Install the ATtiny support on Arduino.
On the Arduino software, I have followed this tutorial to install the ATtiny support via Arduino’s built-in boards manager. I have found the ATtiny support through a google search that led me to the developer’s repository here.

2 - Set the Parameters On Arduino’s menu, go to >Tools and set:
Board to “ATtiny 44”;
Processor to “ATtiny44”:
Clock to “External 20 MHz”;
Port to the port where your Hello Board is connected;
Programmer to “USBTinyISP” or “AVR ISP”.
And select “Burn Bootloader”.

PROGRAMMING TEST 1

Making the LED blink intermittently: On Arduino go to Files>Examples>01.Basics>Blink and add the PIN Position for the LED (PIN 7 in the ATTiny Microcontroller).

Here’s a screenshot of Arduino’s example and the changes written:

And a video with the result:


PROGRAMMING TEST 2

Making the LED light up when the button is pushed: On Arduino go to Files>Examples>Digital>Button and add the PIN Position for the LED (PIN 7 in the ATTiny Microcontroller).

Here’s a screenshot of Arduino’s example and the changes written, I have also changed so that the LED is ON when the Button is pushed:

And a video with the result:


The 2 programming tests above were already made on my electronics design week, but I decided to do a 3rd one for the current ““Embedded Programming” week.

PROGRAMMING TEST 3

Making the serial monitor read when the button is pushed, counting button pushes and lighting the Led every 4 pushes:

I have started by using the example “State change Detection” as a basis: Files>Examples>Digital>StateChangeDetection. The chip we are using (ATtiny44) does not have a hardware serial, meaning that it cannot establish a communication between the board and my computer via USB. In order to do that I had to install a “Software Serial Library”, which is a software used to replicate the functionality of serial communication.

After making sure I had the Software Serial Library installed:

The first step was to add the “include a statement” on the top of my sketch:

#include <SoftwareSerial.h>

Then I have specified the RX pin (pin to receive on) and the TX pin (pin to send on). If in my board the RX and TX Pins are respectively 1 and 0:

The ones on the object below should be inverted:

#define RX    0   //        
#define TX    1   //      
SoftwareSerial Serial(RX, TX);

Then, I have kept the previous constants, that specify my Button and Led pins:

const int  buttonPin = 3;    
const int ledPin = 7;     

And used the rest of the code from the State Change Detection example from Arduino’s library.

Here’s the final code:

  /*
    State change detection (edge detection)

    Often, you don't need to know the state of a digital input all the time, but
    you just need to know when the input changes from one state to another.
    For example, you want to know when a button goes from OFF to ON. This is called
    state change detection, or edge detection.

    This example shows how to detect when a button or button changes from off to on
    and on to off.

    The circuit:
    - pushbutton attached to pin 2 from +5V
    - 10 kilohm resistor attached to pin 2 from ground
    - LED attached from pin 13 to ground (or use the built-in LED on most
      Arduino boards)

    created  27 Sep 2005
    modified 30 Aug 2011
    by Tom Igoe

    This example code is in the public domain.

    http://www.arduino.cc/en/Tutorial/ButtonStateChange
  */
  // added software serial foll0wing this tutorial: https://www.hackster.io/porrey/easy-serial-on-the-attiny-2676e6

  #include <SoftwareSerial.h>

  // ***
  // *** Define the RX and TX pins. Choose any two
  // *** pins that are unused. Try to avoid D0 (pin 5)
  // *** and D2 (pin 7) if you plan to use I2C.
  // ***

  #define RX    0   //
  #define TX    1   //

  // ***
  // *** Define the software based serial port. Using the
  // *** name Serial so that code can be used on other
  // *** platforms that support hardware based serial. On
  // *** chips that support the hardware serial, just
  // *** comment this line.
  // ***

  SoftwareSerial Serial(RX, TX);


  // then kept previous constants

  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(50);
    }
    // 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 % 4 == 0) {
      digitalWrite(ledPin, HIGH);
    } else {
      digitalWrite(ledPin, LOW);
    }

  }

And a video with the result:


A .zip file with all of this week’s files that were mentioned but aren’t linked above, can be found here

Update

Following the suggestion of my global evaluator, I decided to use another programming language, in this case pure C, to program one of my boards.

The board I used was my “Fabduino” and the idea was to make the board led to blink, intermittently.

First of all, I have connected my board to my computer via the FTDI Cable as follows:



And here’s my board pinout:

I had to use avr-gcc which is a high quality C library for use with GCC(a library and compiler collection) on Atmel AVR microcontrollers. Together avr-gcc and avr-libc (which contains useful functions and headers to access the functionalities and I/Os of AVR chips) form the heart of the Free Software toolchain for the Atmel AVR microcontrollers, like the Atmega328p that’s on my Fabduino board.

In order to toggle the output pin connected to the on-board LED we need to read/write directly on the I/O registers of that particular chip. Looking at the schematics of my board, I could see that the LED is connected to the pin PB5 of my microcontroller, so, this is the PIN I want to control:




The Schematics says Yellow LED, but when stuffing the board I couldn’t finad any yellow led, so had to use a red one.

Since I am using libraries, I don’t have write complete C programs with lots of assembly language. Following the avr-libc reference manual we can find some examples on how to toggle the inputs and outputs and was able to use the following code in a file called “led.c“.

  • This header file includes the appropriate IO definitions for the device:

    #include <avr/io.h>
    
  • This header includes delay routines we will need for the intermittent blinking:

    #include <util/delay.h>
    
  • Then we define the duration of the delay, which is 1000 MS or 1 second:

    #define BLINK_DELAY_MS 1000
    

In the main function we have an infinite loop:

  • Since my led pin is PB5, we need to set pin 5 of PORTB for output:

    DDRB |= _BV(DDB5);
    
  • Set pin 5 high to turn led on and delay (1 second):

    PORTB |= _BV(PORTB5);
      _delay_ms(BLINK_DELAY_MS);
    
  • Set pin 5 low to turn led off:

    PORTB &= ~_BV(PORTB5);
    _delay_ms(BLINK_DELAY_MS);
    

And this is the complete code:

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

  #define BLINK_DELAY_MS 1000

  int main (void)
  {
   DDRB |= _BV(DDB5);

   while(1) {
    PORTB |= _BV(PORTB5);
    _delay_ms(BLINK_DELAY_MS);

    PORTB &= ~_BV(PORTB5);
    _delay_ms(BLINK_DELAY_MS);
   }
  }

Now, we need to create an IHEX file and use the avrdude tool to load it inside the Flash.

After listing my devices (via ls /dev/tty* command in terminal) and finding in which my board is connected /dev/tty.usbserial-FT9P06BY, I used the following commands to flash the program to my “Fabduino”:

    Andres-MacBook-2:Led_C andrepulcino$ avr-gcc -Os -DF_CPU=16000000UL -mmcu=atmega328p -c -o led.o led.c
    Andres-MacBook-2:Led_C andrepulcino$ avr-gcc -mmcu=atmega328p led.o -o led
    Andres-MacBook-2:Led_C andrepulcino$ avr-objcopy -O ihex -R .eeprom led led.hex
    Andres-MacBook-2:Led_C andrepulcino$ avrdude -F -V -c arduino -p ATMEGA328P -P /dev/tty.usbserial-FT9P06BY -b 115200 -U flash:w:led.hex

Here’s the flashing results screenshot:



And a video of my board blinking as expected:


That’s it for this week : )