Skip to content

9. Embedded programming

This week I worked on defining my final project idea and started to getting used to the documentation process.

PCB Design and Manufacturing

Design

The design of the board that I will be making and programming for this weeks assignment.

Board

Microchip Studio with FabPDI Programmer

I will be using the FabPDI programmer that I build for the electronics production week to program the PCB using Microchip Studio environment.

Once inside microchip studio, use the device programming window to check if the FabPDI programmer PCB is working.

MicroChipStudio1

inside the device programming window, AVRISP MKII should be available, and if the programmer is connected to a controller to program, it should be able to read its signuture.

MicroChipStudio1

Microcontroller GPIO registers

Referring to the ATtiny44 Datasheet, the GPIO pins have 3 registers that control their status, in the section of the assignment I will be blinking a LED.

to configure, a pin as a digital output first set the corresponding bit in the data direction register DDRX.

DDRX

the to pull the GPIO to high voltage, set the corresponding bit in the port status register PORTX, and to pull it to GND reset the bit.

PORTX

Bit Operation and Masks

In an 8 bit microcontroller, each register has 8 bits, in peripherals registers, each bit has its own unique job, such as the previous section, the GPIO registers have bits that modify the work of one of the GPIO pins.

to edit these registers I can simply edit its value directly such as DDRX = 0b0001010, such a method is fairly simple to use by has a huge drawback, every time I edit the value of one register I have to keep in mind not to change other bits in that I am not targeting in that command, which can get very tricky and time-consuming.

there is a better method which directly set a bit to either 1 or 0 by creating a mask and using bitwise operations, this Bit Operation tutorial makes a great job explaining these masking methods and they have macro functions that can be simply used for bitwise operations.

Blinking Code

How to programm

First Create a new executable GCC project, and pick the controller on the PCB.

MicroChipStudio1

MicroChipStudio1

the code is in main.c, this code blinks the led in one pure color (red, green, and blue), delays for a second then cycle to another.

to upload the code to the controller, click on start without debugging.

MicroChipStudio1

and here is a video of the board being flashed and fully working.

The Code

/*
 * blink.cpp
 *
 * Created: 3/19/2021 10:51:57 PM
 * Author : Yazan
 */ 
#define F_CPU 20000000 //set MCU clock speed

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

int main(void)
{
    DDRB |= (1 << 2); //this is the Data Direction Reg to set PB2 as outputs
    DDRA |= (1 << 6); //this is the Data Direction Reg to set PA6 as outputs
    DDRA |= (1 << 7); //this is the Data Direction Reg to set PA7 as outputs

    PORTB |= (1 << 2); //RGB LED OFF by giving high voltage to all 3 colors
    PORTA |= (1 << 6);
    PORTA |= (1 << 7);

    while (1) {

        PORTB &= ~(1 << 2); //Red LED ON alone by giving low voltage to red 
        PORTA |= (1 << 6);  //turn blue off
        _delay_ms(1000); //delay 1 second

        PORTB |= (1 << 2); //green LED ON alone by giving low voltage to green 
        PORTA &= ~(1 << 7);//turn red off
        _delay_ms(1000); //delay 1 second

        PORTA |= (1 << 7); //Blue LED ON alone by giving low voltage to blue 
        PORTA &= ~(1 << 6);// turn green off
        _delay_ms(1000); //delay 1 second

    }
    return 0;
}

Arduino IDE with TinyUSB programmer

in this section, I will be using the TinyUSB programming alongside the Arduino IDE.

I used damellis / attiny core, installing it is fairly simple, just add the json link to the arduino prefrences, and find the core in the hardware manager.

Click here for a detailed toturial on how to install the attiny core.

ArduinoBoardManager

after setting up the ATtiny core, I choose the controller that I am using, click on burn bootloader to upload the bootloader to the microcontroller, the bootloader enables the microcontroller to use the arduino enviroment.

arduinoProgramming

arduinoProgramming

Microcontroller Timer registers

timers/counter peripherals in a microcontroller count triggers, in a counter mode it counts external triggers, in timer mode, it counts the oscillator pulses or a pre-scaled number of them.

then once the count matches a user-set number, an interrupt routine a set in to run a function.

check this toturial for a good explaining of timers with their registers.

PWM RGB with PushButton input Code

This code generates random duty cycle PWM signals to the RGB pins to give a random color each time a push button is pressed, and the second push button shuts off the PWM functionality and lets the pins run on GPIO mode to shut off the RGB light completely.

and here is a video of the board being flashed and fully working.

void setup() {
  DDRB |= (1 << 2); // set PB2 as output
  DDRA |= (1 << 6); // set PA6 as output
  DDRA |= (1 << 7); // set PA7 as output


  DDRA  &= ~(1 << 2); // set PA2 as INPUT
  DDRA  &= ~(1 << 3); // set PA3 as INPUT
  PORTA &= ~(1 << 2); // set internal pull-up off
  PORTA &= ~(1 << 3); // set internal pull-up off

  PORTB |= (1 << 2); //RGB LED OFF by giving high voltage to all 3 colors
  PORTA |= (1 << 6);
  PORTA |= (1 << 7);
}

void loop() {

  if(~PINA & (1 << 2)) //if push button on PA2 is pressed
  {
    TCCR0A &= ~(1 << COM0A1) & ~(1 << COM0A0) & ~(1 << COM0B1) & ~(1 << COM0B0);  // shutsOff PWM of PA7 and PB2
    TCCR1A &= ~(1 << COM1A1) & ~(1 << COM1A0);  //shutsOff PWM of PA6
    PORTB |= (1 << 2); //RGB LED OFF by giving high voltage to all 3 colors
    PORTA |= (1 << 6);
    PORTA |= (1 << 7);
  }

  if(~PINA & (1 << 3)) //if push button on PA3 is pressed
  {
    TCCR0A |= (1 << COM0A1) | (1 << COM0B1) | (1 << WGM01) | (1 << WGM00);  //turn on PWM of PA7 and PB2
    OCR0A = random(50, 255); //set a rendom duty cycle for PB2
    OCR0B = random(50, 255);//set a rendom duty cycle for PA7
    TCCR0B |= (1 << CS00); //turns of the clock

    TCCR1A |= (1 << COM1A1) | (1 << WGM10);  //shutsOff PWM of PA6
    TCCR1B |= (1 << WGM12);
    OCR1AL = random(50, 255); //set a rendom duty cycle for PA6
    TCCR1B |= (1 << CS10); // turns on the clock

  }


}

Last update: June 29, 2021