Programowanie AVR: miniSUMO

Zacząłem pisać program sterujący do robota miniSUMO. Jak na razie nie robi nic szczególnego, jak tylko odczytuje stan czujników linii i zapala odpowiednią diodę. Zacznę może od dokładniejszego opisania architektury elektroniki robota i prostego przykładu „Hello, world!”.

Elektronikę sterującą tworzą dwa mikrokontrolery, ATMega32 i ATMega8. Mniejszy uC służy do obsługi sonaru, czyli ultradźwiękowego czujnika odległości. Nie będę na razie zmieniał jego programu, zajmę się natomiast programem sterującym ATMega32, gdzie będzie cała logika robota.

Na pokładzie mamy także 4 diody LED. Z przodu płyty są umieszczone sonary. Z tyłu złącze ISP, port podczerwieni. Na płycie także jest jeden przycisk monostabilny, złącze modułu radiowego oraz złącze rozszerzeń. Od dołu płyty są złącza, które łączą się z dolną częścią, gdzie jest zasilanie (baterie i ładowarka), czujniki linii i silniki.

Poniżej schemat blokowy elektroniki.

Przykładowy program „Hello, world!”
Oczywiście od suchej teorii i opisów, ciekawsze jest programowanie robota i sprawdzanie czy i jak to działa. Dlatego też napiszę prosty program do mrugania diodami LED.

Struktura programu:

  • Inicializacja odpowiednich portów I/O – konfiguracja uC
  • Zapalanie i gaszenie diod z odpowiednim opóźnieniem – główna pętla programu

Program nie będzie robił zbyt wiele, ale pomoże zweryfikować poprawność konfiguracji środowiska do programowania i wrzucania softu na uC. Jeżeli wszystko dobrze pójdzie, to po poprawnym skompilowaniu i zaflashowaniu pamięci procesora programem, diody powinny zacząć migać.

Plik main.h:

#ifndef MAIN_H_
#define MAIN_H_

// ---- information LEDs in board corners ----
// left front
#define LED_LF          7
#define LED_LF_DDR      DDRA
#define LED_LF_PORT     PORTA
// right front
#define LED_RF          3
#define LED_RF_DDR      DDRC
#define LED_RF_PORT     PORTC
// left rear
#define LED_LR          6
#define LED_LR_DDR      DDRA
#define LED_LR_PORT     PORTA
// right rear
#define LED_RR          1
#define LED_RR_DDR      DDRC
#define LED_RR_PORT     PORTC

// ---- information LED control macros ----
#define LED_LF_ON       LED_LF_PORT |= (1<<LED_LF)
#define LED_LF_OFF      LED_LF_PORT &= ~(1<<LED_LF)
#define LED_LF_TOGGLE   LED_LF_PORT ^= (1<<LED_LF)

#define LED_RF_ON       LED_RF_PORT |= (1<<LED_RF)
#define LED_RF_OFF      LED_RF_PORT &= ~(1<<LED_RF)
#define LED_RF_TOGGLE   LED_RF_PORT ^= (1<<LED_RF)

#define LED_LR_ON       LED_LR_PORT |= (1<<LED_LR)
#define LED_LR_OFF      LED_LR_PORT &= ~(1<<LED_LR)
#define LED_LR_TOGGLE   LED_LR_PORT ^= (1<<LED_LR)

#define LED_RR_ON       LED_RR_PORT |= (1<<LED_RR)
#define LED_RR_OFF      LED_RR_PORT &= ~(1<<LED_RR)
#define LED_RR_TOGGLE   LED_RR_PORT ^= (1<<LED_RR)

#define LED_ALL_ON      LED_LF_ON;LED_RF_ON;LED_LR_ON;LED_RR_ON
#define LED_ALL_OFF     LED_LF_OFF;LED_RF_OFF;LED_LR_OFF;LED_RR_OFF
#define LED_ALL_TOGGLE  LED_LF_TOGGLE;LED_RF_TOGGLE;\
                        LED_LR_TOGGLE;LED_RR_TOGGLE

// functions
void init_led_io(void);

#endif // MAIN_H_

Plik main.c:

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

// own includes
#include "main.h"

// function prototypes
void init_io(void);

// main function, start of the program
int main(void)
{
    init_io();

    // main program loop
    for(;;)
    {
        _delay_ms(150);
        LED_ALL_TOGGLE;
    }
}

void init_io(void)
{
    // set all ports as inputs
    DDRA = 0x00;
    DDRB = 0x00;
    DDRC = 0x00;
    DDRD = 0x00;

    init_led_io();
}

void init_led_io(void)
{
    LED_LF_DDR |= (1<<LED_LF);
    LED_RF_DDR |= (1<<LED_RF);
    LED_LR_DDR |= (1<<LED_LR);
    LED_RR_DDR |= (1<<LED_RR);
}

Do kompilacji użyłem pliku Makefile wygenerowanego za pomocą mFile z pakietu WinAVR. Kompilujemy za pomocą ‘make’, a programujemy poprzez ‘make program’.

Logi z kompilacji:

> “make.exe” all

——– begin ——–
avr-gcc (WinAVR 20100110) 4.3.3
Copyright (C) 2008 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Size before:
AVR Memory Usage
—————-
Device: atmega32

Program: 202 bytes (0.6% Full)
(.text + .data + .bootloader)

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

Compiling C: main.c
avr-gcc -c -mmcu=atmega32 -I. -gdwarf-2 -DF_CPU=16000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=./main.lst -std=gnu99 -MMD -MP -MF .dep/main.o.d main.c -o main.o

Linking: MAOR_main.elf
avr-gcc -mmcu=atmega32 -I. -gdwarf-2 -DF_CPU=16000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=main.o -std=gnu99 -MMD -MP -MF .dep/MAOR_main.elf.d main.o –output MAOR_main.elf -Wl,-Map=MAOR_main.map,–cref -lm

Creating load file for Flash: MAOR_main.hex
avr-objcopy -O ihex -R .eeprom -R .fuse -R .lock MAOR_main.elf MAOR_main.hex

Creating load file for EEPROM: MAOR_main.eep
avr-objcopy -j .eeprom –set-section-flags=.eeprom=”alloc,load” \
–change-section-lma .eeprom=0 –no-change-warnings -O ihex MAOR_main.elf MAOR_main.eep || exit 0

Creating Extended Listing: MAOR_main.lss
avr-objdump -h -S -z MAOR_main.elf > MAOR_main.lss

Creating Symbol Table: MAOR_main.sym
avr-nm -n MAOR_main.elf > MAOR_main.sym

Size after:
AVR Memory Usage
—————-
Device: atmega32

Program: 202 bytes (0.6% Full)
(.text + .data + .bootloader)

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

Wynikowy plik hex:

:100000000C942A000C9434000C9434000C943400AA
:100010000C9434000C9434000C9434000C94340090
:100020000C9434000C9434000C9434000C94340080
:100030000C9434000C9434000C9434000C94340070
:100040000C9434000C9434000C9434000C94340060
:100050000C94340011241FBECFE5D8E0DEBFCDBF25
:100060000E9442000C9463000C940000D79AA39A5B
:10007000D69AA19A08951ABA17BA14BA11BA0E9458
:10008000360008950E943B002CED35E0E8E070E476
:1000900062E040E951E005C0CA010197F1F7215043
:1000A000304021153105C1F78BB380588BBB85B328
:1000B0008E2785BB8BB387278BBB85B3862785BBF4
:0A00C0002CED35E0E9CFF894FFCFF6
:00000001FF

Logi z programowania:

> “make.exe” program
avrdude -p atmega32 -P usb -c usbasp -U flash:w:MAOR_main.hex

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.03s

avrdude: Device signature = 0x1e9502
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 “MAOR_main.hex”
avrdude: input file MAOR_main.hex auto detected as Intel Hex
avrdude: writing flash (202 bytes):

Writing | ################################################## | 100% 0.97s

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

Reading | ################################################## | 100% 0.88s

avrdude: verifying …
avrdude: 202 bytes of flash verified

avrdude done. Thank you.

> Process Exit Code: 0
> Time Taken: 00:09

Jak widać w logach kompilacji, program do mrugania diodami zajmie tylko 202 bajty pamięci uC i jest to 0.06 % dostępnej przestrzeni programowej. Plik Makefile można także wykorzystać w systemie Linux do kompilacji i programowania. Na razie mam problem z programatorem i jądrem linuksa, z jakiegoś powodu urządzenie USB nie może być poprawnie zainstalowane. Na starszej wersji działa, ale proces programowania się nie powodzi, ponieważ nie można znaleźć urządzenia o odpowiednim ID. Pewnie jest to gdzieś we wspomnianym pliku Makefile, który został wygenerowany pod Windowsem.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s