2

Author Topic: atmega source code  (Read 38173 times)

0 Members and 1 Guest are viewing this topic.

Offline AdminTopic starter

  • Administrator
  • Supreme Robot
  • *****
  • Posts: 11,660
  • Helpful? 169
    • Society of Robots
atmega source code
« on: February 08, 2007, 01:57:00 PM »
anyone have source code for either the atmega8 or atmega644 that they can post? a simple LED flash would suffice.

i figure it would speed me up in development for two separate projects im working on . . .

i dont remember the last time i had less than 4 robots to work on simultaneously . . . i must focus more . . .

Offline JesseWelling

  • Expert Roboticist
  • Supreme Robot
  • *****
  • Posts: 707
  • Helpful? 0
  • Only You Can Build A Robot!
Re: atmega source code
« Reply #1 on: February 08, 2007, 05:56:31 PM »
I found this written for an Atmega128 so it should be similar
Code: [Select]
/****************************************************************************
*
*   Copyright (c) 2006 Dave Hylands     <[email protected]>
*
*   This program is free software; you can redistribute it and/or modify
*   it under the terms of the GNU General Public License version 2 as
*   published by the Free Software Foundation.
*
*   Alternatively, this software may be distributed under the terms of BSD
*   license.
*
*   See README and COPYING for more details.
*
****************************************************************************/

#include <avr/io.h>

#include "Delay.h"
#include "Timer.h"

#define RED_LED_PIN     4
#define RED_LED_MASK    ( 1 << RED_LED_PIN )
#define RED_LED_DDR     DDRG
#define RED_LED_PORT    PORTG

#define BLUE_LED_PIN    3
#define BLUE_LED_MASK   ( 1 << BLUE_LED_PIN )
#define BLUE_LED_DDR    DDRG
#define BLUE_LED_PORT   PORTG

#define YELLOW_LED_PIN  4
#define YELLOW_LED_MASK ( 1 << YELLOW_LED_PIN )
#define YELLOW_LED_DDR  DDRB
#define YELLOW_LED_PORT PORTB

// Setting the pin to 0 turns the LED on

#define LED_ON( color )     color ## _LED_PORT &= ~color ## _LED_MASK
#define LED_OFF( color )    color ## _LED_PORT |= color ## _LED_MASK


int main(void)
{
    int led;

    InitTimer();

    ASSR &= ~( 1 << AS0 );  // Make sure Port G LED pins are setup for I/O

    RED_LED_DDR     |= RED_LED_MASK;
    YELLOW_LED_DDR  |= YELLOW_LED_MASK;
    BLUE_LED_DDR    |= BLUE_LED_MASK;

    led = 0;

    while( 1 )
    {
        // Turn all of the LEDs off

        LED_OFF( RED );
        LED_OFF( BLUE );
        LED_OFF( YELLOW );

        switch ( led )
        {
            case    0:  LED_ON( RED );      break;
            case    1:  LED_ON( BLUE );     break;
            case    2:  LED_ON( YELLOW );   break;
        }

        if ( ++led > 2 )
        {
            led = 0;
        }

        {
            int i;

            // Tick rate is 100/sec so waiting for 100 waits for 1 sec

            for ( i = 0; i < 100; i++ )
            {
                    WaitForTimer0Rollover();
            }
        }
    }

    return 0;
}

Offline dunk

  • Expert Roboticist
  • Supreme Robot
  • *****
  • Posts: 1,086
  • Helpful? 21
Re: atmega source code
« Reply #2 on: February 08, 2007, 05:59:46 PM »
by strange coincidence i just uploaded an article on my AVR based USB servo controller to your members area.
circuit diagrams and source code included.

the code is probably a bit more complicated than you want for a simple "hello world" though...

for my first attempt with AVRs i followed this article:
http://www.linuxfocus.org/English/March2002/article231.shtml
but it's very much from a Linux user's point of view.

which complier are you using?

there's a good article on AVR Freaks http://www.avrfreaks.net/index.php?module=FreaksArticles&func=viewArticles called "Which C-compiler should I choose" (i think you have to sign up for an account to get it).
it has flashing LEDs example code for some of the more common compilers.

if you are using GCC i can find and test one for you and paste it here if you want.
(although not tonight, it's getting late.)

good luck!

dunk.

Offline JesseWelling

  • Expert Roboticist
  • Supreme Robot
  • *****
  • Posts: 707
  • Helpful? 0
  • Only You Can Build A Robot!
Re: atmega source code
« Reply #3 on: February 08, 2007, 06:10:09 PM »
Here is my project all zipped up for you code browsing:
www.cs.montana.edu/~wellingj/JesseFreeRTOS.tar.gz

It's compiled with gcc. so go to /FreeRTOS/App/AVR_ATMega128_RbStx/
and run 'make' if you are using linux and have everything installed for
avr-gcc and gnu make and some other stuff (if you need help PM me)

I've used FreeRTOS and AVRlib and made changes to AVRlib when I had to.
The reason I had to modify and do some odd things with AVRlib is because it
makes the assumption that you are running under a single line of execution
with no context switches.

If there is alot of interest in this let me know and I will write a tutorial on it when I can.
« Last Edit: February 08, 2007, 06:11:35 PM by JesseWelling »

Offline AdminTopic starter

  • Administrator
  • Supreme Robot
  • *****
  • Posts: 11,660
  • Helpful? 169
    • Society of Robots
Re: atmega source code
« Reply #4 on: February 09, 2007, 01:39:27 PM »
back in 2005 i programmed the atmega168 to control servos . . . but at that time gcc was buggy and there was like no source code for it on the web . . . so my code was all ugly and hacked together from a total lack of understanding of why my code even worked (yea, it worked!) . . . this is what happens when you let a mechanical engineer program . . . :P

anyway, here is the atmega168 source code for others to use:

Code: [Select]
#include <avr/io.h>
//#include <avr/interrupt.h>
//#include <string.h>

//***************DELAY CODE**************
//delay exactly 1 clock cycle
void delay_cycles(unsigned int timed) {
while(timed>0)
timed--;
return;
}
//****************************************

//*************************BEEPER CODE**********************
//beep for cycle time at certain frequency
void beep (unsigned int cycles, unsigned int freq) {
DDRB |= 1<<PB0; //make PB0 an output
long i;
while (cycles > 0) {
PORTB |= 1<<PB0; // buzzer pin high
for(i=0;i<freq;i++);
PORTB &= !(1<<PB0); // buzzer pin low
for(i=0;i<freq;i++);
cycles--;
}
return;
}
//**********************************************************


//*****required for ADC conversion (screws up everything!)
/*

//this came from the main:
//usart_putchar(ADCL);
//******end of ADC code
*/


//main function, begins with initialization
//NOTE servo actuation code does not work outside of main for some odd reason
int main(void) {

#include <servoPositions.h>//this include ONLY works in main cause the compiler sucks like that
unsigned int step=0;
unsigned int i=0;

//DDRn Data Direction Registers (0 for input vs 1 for output)
//DDRC = 0xFF; //configure all ports for output
//DDRC = 0x00; //configure all ports for input
//pull up resistors generally good for inputs
//PORTC = 0xFF; //turns pullup resistors on for all C ports
//PORTC = 0x00; //turns pullup resistors off for all C ports
//DDRD |= 1<<PD1; // OR set PD1 to output
//DDRC |= 1<<PC3; // OR set PC3 to output

//DDRC |= 0<<PC6;//set ADC6 to input
//PORTC |= 1<<PC6;//turn on ADC6 pullup resistor

/*
//ADC init
ADMUX = 0; // channel 0 //ADC init
    ADCSRA |= _BV(ADEN) | _BV(ADPS1) | _BV(ADPS2);//ADC init

ADCSRA |= _BV(ADSC);//ADC Start Conversion

//!(ADCSRA & _BV(ADIF));//ADC wait for conversion

//ADCSRA |= _BV(ADIF);//ADC clear ADIF

//if(ADCL>200)
//beep(1500,28);
*/

beep(1500, 25);

DDRC |= 0x7C; //setup portC for output 0b1111100 (PC0-PC5)
//DDRC |= 0x3 //setup portC for input 0b0000011 (PC6-PC7)
//motor1table[4]=100;

PORTC &= !(1<<PC5);//initialize PWM off

while(1) {
i=0;

//delay_cycles(3000);
while(i<7) {
//step=7;
//***************SERVO ACTUATION CODE***************
//accepts a time in clock cycles to pulse each servo
PORTC |= 1<<PC3; //servo 1
delay_cycles(servo1table[step]);
PORTC &= !(1<<PC3);

PORTC |= 1<<PC2; //servo 2
delay_cycles(servo2table[step]);
PORTC &= !(1<<PC2);

PORTC |= 1<<PC1; //servo 3
delay_cycles(servo3table[step]);
PORTC &= !(1<<PC1);

PORTC |= 1<<PC0; //servo 4
delay_cycles(servo4table[step]);
PORTC &= !(1<<PC0);

PORTC |= 1<<PC4; //servo 5
delay_cycles(servo5table[step]);
PORTC &= !(1<<PC4);
/*
PORTC |= 1<<PC5; //motor 1
delay_cycles(motor1table[step]);
PORTC &= !(1<<PC5);*/
//**************************************************

//delay_cycles(100);
i++;
}

//in future, have it ++ only if the encoder detects a change in position
// -also have it reset to 0 if it detects restart mark
step++;//step=0;

if (step>=8) {
//beep(1500, 25);//step=0;
step=0;
}

/*
PORTD |= 1<<PD1; // LED on
for(i=0;i<10000;i++);
PORTD &= !(1<<PD1); // LED off
for(i=0;i<10000;i++);*/
}
return 0;
}

now for my questions . . .

looking at Dave Hyland's code, i have a few questions that will help me port this over to the atmega644:
(atmega128 datasheet for reference)

im kinda confused what this code does
    #define RED_LED_PIN     4
    #define RED_LED_MASK    ( 1 << RED_LED_PIN )
    #define RED_LED_DDR     DDRG
    #define RED_LED_PORT    PORTG

    RED_LED_DDR     |= RED_LED_MASK;

what i think the last line is saying is this:
DDRG |= 1 << 4;
which i think means configure port PG4 to output, right?

also this code . . .

    #define LED_ON( color )     color ## _LED_PORT &= ~color ## _LED_MASK
    #define LED_OFF( color )    color ## _LED_PORT |= color ## _LED_MASK

what i think this is saying is when I write LED_ON( RED ) in my main, it changes to this:
    PORTG  &= 1 << 4;
which i think means set PG4 to 0 (if i did PORTG  |= 1 << 4 , this would set the pin to 1), right?

what is the difference between these? i think this might clear up my confusion . . .
    PORTG  &= !(1 << 4);
    PORTG  |= !(1 << 4);
    PORTG  &= 1 << 4;//sets PG4 to 1
    PORTG  |= 1 << 4;


also, im looking at the AVRlib for AVR . . . quite possibly a dumb question . . . i just copy/paste the functions from the c files and put into my code, right? then i just include the .h files and it will work, right? believe it or not it took me like 20 min of confusion to figure that out . . . :-[

and a link to dunks new USB Servo Controller Tutorial (thanks, dunk!!! im already putting some of it to use)

(edit: changed dunk's link)
« Last Edit: February 16, 2007, 07:29:54 PM by Admin »

Offline JonHylands

  • Expert Roboticist
  • Supreme Robot
  • *****
  • Posts: 562
  • Helpful? 3
  • Robot Builder/ Software Developer
Re: atmega source code
« Reply #5 on: February 09, 2007, 02:12:06 PM »
Admin,

I fired off an email to my brother - I'll let you know what he says...

- Jon

Offline JesseWelling

  • Expert Roboticist
  • Supreme Robot
  • *****
  • Posts: 707
  • Helpful? 0
  • Only You Can Build A Robot!
Re: atmega source code
« Reply #6 on: February 09, 2007, 02:51:14 PM »
RED_LED_DDR     |= RED_LED_MASK;

there is a nuance to this...it doesn't mess with any thing else so say we have binary 01010101 (Ox55)
Then we OR it with 10101010 (0xEE)
then it becomes 11111111(0xFF)

But if we have 01011010 and we OR it with 00000001 I the becomes 01011011
So that's what is meant by a Mask it's a way to turn on stuff without messing with other bits.

#define LED_ON( color )     color ## _LED_PORT &= ~color ## _LED_MASK

This is a tricky bit of code that I had a hard time understanding as well.
the ## is the double hash token and it means concatonate the left and right tokens.

What dave is doing it really just stringing together stuff in the preeprocessor to abstract it away form his code.
I posted this a while ago but I think I'll post it again now.
http://thedotcommune.com/home/bitmasking.html
this will help you understand it more.

As for the AVRlib the idea here is to not have a big blob of code.

when you compile something with gcc you typicaly do this
gcc mymaincode.c myservocode.c -o myfilethatIwilluploadtothemicroprocessor

so what this does is make it possible to not have to put in the code from avrlib into your main file (why do you need the clutter)

So that brings us to make files, because no one wants to type all that stuff every time (especialy since it's all hard to remember) I would look at the /examples folder in the avrlib folder and see how they include stuff. then look at thier make files to see how it's all compiled.

yea it's kinda complicated...

Offline JonHylands

  • Expert Roboticist
  • Supreme Robot
  • *****
  • Posts: 562
  • Helpful? 3
  • Robot Builder/ Software Developer
Re: atmega source code
« Reply #7 on: February 09, 2007, 06:43:27 PM »
Got this response from Dave:

Hi Jon,

>    #define RED_LED_PIN     4
>    #define RED_LED_MASK    ( 1 << RED_LED_PIN )
>    #define RED_LED_DDR     DDRG
>    #define RED_LED_PORT    PORTG
>
>    RED_LED_DDR     |= RED_LED_MASK;
>
> what i think the last line is saying is this:
> DDRG |= 1 << 4;
> which i think means configure port PG4 to output, right?

Yes.

> also this code . . .
>
>    #define LED_ON( color )     color ## _LED_PORT &= ~color ## _LED_MASK
>    #define LED_OFF( color )    color ## _LED_PORT |= color ## _LED_MASK
>
> what i think this is saying is when I write LED_ON( RED ) in my main, it
> changes to this:
>    PORTG  &= 1 << 4;

Not quite.

LED_ON( RED ) is the same thing as PORTG &= ~( 1 << 4 )

which clears bit 4 in Port G.

> which i think means set PG4 to 0 (if i did PORTG  |= 1 << 4 , this would
> set the pin to 1), right?

Yes.

> what is the difference between these? i think this might clear up my
> confusion . . .
>    PORTG  &= !(1 << 4);

1 << 4 is the same as 0x10

! is a boolean not
~ is a bitwise not
!0x10 is boolean not and a non-zero value, so you get zero
~0x10 is a bitwise not and yields 0xEF

PORTG &= !( 1 << 4 )

is non-sensical. What you really want is

PORTG &= ~( 1 << 4 );

which clears bit 4 and leaves the other bits alone.

>    PORTG  |= !(1 << 4);

bitwise oring in zero does nothing. This is also non sensicle. You want to do

PORTG |= ( 1 << 4 ) to set bit 4.

>    PORTG  &= 1 << 4;

This is also non-sensical (at least in this example) and sets all of
the bits in PORTG to zero except for bit 4.

>    PORTG  |= 1 << 4;

This sets bit 4 to 1. So for controlling an individual bit, there are
only 3 patterns which make sense:

PORTG &= ~( 1 << 4 ); // Clears the bit
PORTG |= ( 1 << 4 ); // Sets the bit
PORTG ^= ( 1 << 4); // Toggles the bit (^ is the exclusive or operator)


 


Get Your Ad Here

data_list