FABACADEMY 2017

Week 8 - Eembedded programming

Assignment


  • read a microcontroller data sheet

  • program your board to do something, with as many different programming languages
    and programming environments as possible
  • Read a detailed datasheet of ATtiny24/44/84 and explain learning and problems and also things I like to know more. Learn different approaches to programming attiny or avr's and programming hello-ftdi board.

    With programming iam not very familar with. I had electrical engineering while studying, but that is very long ago. For this topic of the electronics development, as well as the programming, I really have to start at zero.

    The main task of embedded programming is the microprocessor you will use or you want to deliver a package.
    My board design is based on the fabacadamy's 6th electronics design explanations two weeks ago from Fabacademy Tutorial website. I added a LED and an 20MHz resonator to my board.
    Now I have to program my board through my programmer, which we have made in the 4th week.

    What information I have put together from the ATtiny44 Datasheet:

    ATtiny44 Datasheet:


    Overview

    The Atmel ATtiny24/44/84 is a low-power CMOS 8-bit microcontroller based on the AVR enhanced RISC architecture. By executing powerful instructions in a single clock cycle, the Atmel ATtiny24/44/84 achieves throughputs approaching 1MIPS per MHz allowing the system designer to optimize power consumption versus processing speed.

    The ATtiny24/44/84 AVR is supported with full suite of program and system development tools
    including: C Compilers, Macro Assemblers, Program Debugger/Simulators and Evaluation kits.

    The device is manufactured using Atmel´s high desity non-volatile memory-technology. The on-chip
    ISP Flash allows the program memory to be re-programmed in-system through an SPI serial interface, by a conventional non-volatile memory programmer or by an on-chip boot code running on the AVR core.

    Pin configuration Explanations from the Datasheet (page 60-65 in the Datasheet):

  • The numbers behind the letters are channels E.g. ADC0 or ADC3.
  • ADC0-ADC7: Analog Digital Converter
  • AREF: External Analog Reference for ADC. In this case pull-up and output driver are disabled
  • PCINT0-11: Pin Change Interrupt source 0-11
  • AIN0: Analog Comparator Positive Input. Configure port pin as input.
  • AIN1: Analog Comparator Negative Input.
  • T0,T1: Timer/Counter source 0, 1
  • USCK: Three-wire mode Universal Serial Interface Clock
  • SCL: Two-wire mode Serial Clock for USI Two-wire mode.
  • DO: Data Output
  • SDA: Two-wire mode Serial Interface Data.
  • DI: Data Input as USI Three-wire node does not override normal port functions pin has to be configured as input for DI functions.
  • Miso: Master Data Input, Slave Data Output for SPI channel
  • Mosi: Mater Data Output, Slave Data Input for SPI channel
  • OC1B: Output Compare Match output. Can serve as external output for Timer Counter1 MatchB. OC1B pin is also a output pin for PWM moder timer function.
  • OC0B: Output Compare Match output. Can serve as external output for Timer Counter0 Match B. Output pin for PWM mode timer function.
  • OC1A: Output pin for PWM mode. Timer/Counter 1.
  • OC0A: Output pin for PWM mode. Timer/Counter 0. Can serve as external output but has to be configured as output (DDB2=1)
  • CKOUT: SystemClock Output, when CKOUT Fuse is programmed.
  • CLK1: Clock Input from external clock.
  • XTAL1, XTAL2: Chip Clock Oszillator pin1, pin2 used for chip clocks. When used as clock it can not be uses as I/O pin. When internal Oszillator is used, then pin serves as ordinary I/O pin.
  • Reset: Ecternal Reset INput is active low and enabled by unprogramming "1" the RSTDISBL Fuse. When pn is used as Reset pin output driver an digital input are deactivated.
  • dW: When debugWire Enable (DWEN) Fuse is programmed and Lock bits unprogrammed. It is configured as a wire and bi-directional I/O pin, that means it is a communication gateway between target and emulator.
  • Possible PWM (Pulse Width Modulation) is on PA5,PA6 and PA7 and PB2. PWM you need for Informationtransfer and often to regulate the conversion of energy into technical systems.

    External Clock

    To drive the device from an external clock source, CLKI should be driven as shown in Figure 7-3. To run the device on an external clock, the CKSEL fuses must be programmed to “0000”.

    Thinks I like to know more:

    How to Reset?

    What happen with unconnected pins?

    What does MISO, MOSI and SCK means?

    On the following photo you can see the Pin Configuration of the ATiny24/44/84


    My LED with a 330 Ω resistor is on Pin PA7 (blue underlined); the Button with the 10 kΩ Resistor is on Pin PA3 (red underlined).

    Furthermore, I describe on this sketch what the terms MISO, MOSI and SCK mean.

    What problems I had ?

    Sometimes my programmer from electronics production wasnt recognized by my computer. To solve this Problem, I pull the usb-cable out of my omputer and plug it in again. Furthermore my pc could not find the ftdi-cable at first. this problem I solved with the right driver for the ftdi-cable the prolific driver.

    Software I used:

    AVR DUDE is a command line tool with Functions include:

  • Transferring program code to the flash memory
  • Read out unprotected codes from the flash
  • Setting and reading fuse and lockbits
  • Writing and reading the EEPROM
  • I ordered a cable a COM-FOUR PL2303HX USB zu TTL RS232 COM cabel-Modul Konverter to read the serial signal USB to TTL cable for 7 € from Amazon.


    Programming the board:

    The main.c for LED-Blinking example:

    
        
        //main.c AtTiny44 Program
    
    #include  <avr/io.h>
    #include <util/delay.h>
    
    #define F_CPU 16000000
    #define BUTTON_PRESSED	(PINA & (1<<PA3))		// check for button press
    #define LED_ON	PORTA |= (1 << PA7)			// turn LED on code
    #define LED_OFF	PORTA &= ~(1<< PA7)			// turn LED off code
    
    typedef unsigned char  BYTE;
    typedef unsigned short WORD;
    
    void signal(){
    	LED_ON;
    	_delay_ms(500);
    	LED_OFF;
    	_delay_ms(500);
    	LED_ON;
    	_delay_ms(500);
    	LED_OFF;
    	_delay_ms(500);
    	LED_ON;
    	_delay_ms(500);
    	LED_OFF;
    	_delay_ms(500);
    	LED_ON;
    	_delay_ms(500);
    	LED_OFF;
    	_delay_ms(500);
    	LED_ON;
    	_delay_ms(500);
    	LED_OFF;
    	_delay_ms(500);
    	LED_ON;
    	_delay_ms(500);
    	LED_OFF;
    	_delay_ms(500);
    	LED_ON;
    	_delay_ms(500);
    	LED_OFF;
    	_delay_ms(500);
    	LED_ON;
    	_delay_ms(500);
    	LED_OFF;
    	_delay_ms(500);
    	LED_ON;
    	_delay_ms(500);
    	LED_OFF;
    	_delay_ms(500);
    	LED_ON;
    	_delay_ms(500);
    	LED_OFF;
    	_delay_ms(500);
    
    }
    
    int main (void) {
    	// declare PA0 as output pin. This is where the motor and LED is connected
    	DDRA = (1 << PA7);
    	DDRA |= (1 << DDA3);	// using A3 as button input
    	PORTA |= (1 << PA3);	// pull-up resistor
    
    
    	// main loop
    	while (1) {
    
    		if (!BUTTON_PRESSED){
    		   signal(0);
    		}
    
    	}
    	return 1;
    }
        
        
       

    Video 1:

    Video 2:

    Go over the terminal into the directory in which the program file (Makefile and main.c you find in the download section) and the make file lies and type "make flash":

    If at the end of the process "avrdude done. Thank you" (as marked as red appears), everything has been properly flashed on the chip

    On the following photo you can see the self-made
    fabISP for the first time in operation.

    Programming hello-ftdi board

    hello_echo44.c 115200 baud FTDI character echo

    At first I would like to prefer to highlowtech.org. There I found a tutorial to insert attiny ics into the arduino libary.

    To let me view the data via a serial interface (FTDI cable) in addition to the Arduino serial monitor I have downloaded the software coolterm.

    Modified sketch for hello_echo44.c 115200 baud FTDI character echo

    
    

    // #include <stdio.h> #include <avr/io.h> #include <util/delay.h> #include <avr/pgmspace.h> #define output(directions,pin) (directions |= pin) // set port direction for output #define set(port,pin) (port |= pin) // set port pin #define clear(port,pin) (port &= (~pin)) // clear port pin #define pin_test(pins,pin) (pins & pin) // test for port pin #define bit_test(byte,bit) (byte & (1 << bit)) // test for bit set #define bit_delay_time 8.5 // bit delay for 9600 with overhead #define bit_delay() _delay_us(bit_delay_time) // RS232 bit delay #define half_bit_delay() _delay_us(bit_delay_time/2) // RS232 half bit delay #define char_delay() _delay_ms(10) // char delay #define serial_port PORTA #define serial_direction DDRA #define serial_pins PINA #define serial_pin_in (1 << PA0) #define serial_pin_out (1 << PA1) #define max_buffer 25 void get_char(volatile unsigned char *pins, unsigned char pin, char *rxbyte) { // // read character into rxbyte on pins pin // assumes line driver (inverts bits) // *rxbyte = 0; while (pin_test(*pins,pin)) // // wait for start bit // ; // // delay to middle of first data bit // half_bit_delay(); bit_delay(); // // unrolled loop to read data bits // if pin_test(*pins,pin) *rxbyte |= (1 << 0); else *rxbyte |= (0 << 0); bit_delay(); if pin_test(*pins,pin) *rxbyte |= (1 << 1); else *rxbyte |= (0 << 1); bit_delay(); if pin_test(*pins,pin) *rxbyte |= (1 << 2); else *rxbyte |= (0 << 2); bit_delay(); if pin_test(*pins,pin) *rxbyte |= (1 << 3); else *rxbyte |= (0 << 3); bit_delay(); if pin_test(*pins,pin) *rxbyte |= (1 << 4); else *rxbyte |= (0 << 4); bit_delay(); if pin_test(*pins,pin) *rxbyte |= (1 << 5); else *rxbyte |= (0 << 5); bit_delay(); if pin_test(*pins,pin) *rxbyte |= (1 << 6); else *rxbyte |= (0 << 6); bit_delay(); if pin_test(*pins,pin) *rxbyte |= (1 << 7); else *rxbyte |= (0 << 7); // // wait for stop bit // bit_delay(); half_bit_delay(); } void put_char(volatile unsigned char *port, unsigned char pin, char txchar) { // // send character in txchar on port pin // assumes line driver (inverts bits) // // start bit // clear(*port,pin); bit_delay(); // // unrolled loop to write data bits // if bit_test(txchar,0) set(*port,pin); else clear(*port,pin); bit_delay(); if bit_test(txchar,1) set(*port,pin); else clear(*port,pin); bit_delay(); if bit_test(txchar,2) set(*port,pin); else clear(*port,pin); bit_delay(); if bit_test(txchar,3) set(*port,pin); else clear(*port,pin); bit_delay(); if bit_test(txchar,4) set(*port,pin); else clear(*port,pin); bit_delay(); if bit_test(txchar,5) set(*port,pin); else clear(*port,pin); bit_delay(); if bit_test(txchar,6) set(*port,pin); else clear(*port,pin); bit_delay(); if bit_test(txchar,7) set(*port,pin); else clear(*port,pin); bit_delay(); // // stop bit // set(*port,pin); bit_delay(); // // char delay // bit_delay(); } void put_string(volatile unsigned char *port, unsigned char pin, char *str) { // // print a null-terminated string // static int index; index = 0; do { put_char(port, pin, str[index]); ++index; } while (str[index] != 0); } int main(void) { // // main // static char chr; static char buffer[max_buffer] = {0}; static int index; // // set clock divider to /1 // CLKPR = (1 << CLKPCE); CLKPR = (0 << CLKPS3) | (0 << CLKPS2) | (0 << CLKPS1) | (0 << CLKPS0); // // initialize output pins // set(serial_port, serial_pin_out); output(serial_direction, serial_pin_out); // // main loop // index = 0; while (1) { get_char(&serial_pins, serial_pin_in, &chr); put_string(&serial_port, serial_pin_out, "hello_echo44.c: you typed \""); buffer[index++] = chr; if (index == (max_buffer-1)) index = 0; put_string(&serial_port, serial_pin_out, buffer); put_char(&serial_port, serial_pin_out, '\"'); put_char(&serial_port, serial_pin_out, 10); // new line } }

    To also check the FTDI cable or a serial interface with a print function I have created in week 14 another fabkit, whereby I read the serialprint of a simple text with a baud rate of 57600 via the software Coolterm. If you want to learn more about coolterm and also what driver you need check my Week 13 - input devices.

    Sketch for serialprint a text:

    
    

    // the setup function runs once when you press reset or power the board void setup() { // initialize digital pin LED_BUILTIN as an output. pinMode(LED_BUILTIN, OUTPUT); Serial.begin(57600); } // the loop function runs over and over again forever void loop() { Serial.print("Hallo Welt!\n"); digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level) delay(1000); // wait for a second Serial.print("I bims, der FabKit vong Marsi her! \n"); digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW delay(1000); // wait for a second }

    Download-Section:


    hello_echo44.c
    main.c (blink example)
    Makefile attiny 44
    Hello world case
    coolterm software