math formulas

code

Saturday, February 16, 2013

Taking apart our first program

As announced in the last post, I wanted to take apart the code that made our LED flash to explain what's happening here.

The code:

#define F_CPU 1200000UL

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

int main (void)
{
  // port B pins 0, 1, 2 as output
  DDRB = (1 << PB2) | (1 << PB1) | (1 << PB0);

  unsigned int i = 0;
  while( true )
  {
    PORTB = i & ( (1 << PB2) | (1 << PB1) | (1 << PB0) );

    i = (i+1) % 8;
    
    _delay_ms( 500 );
  }
}

A basic understanding of C/C++ is required to understand the code - if you don't know C or C++, have a look at some tutorials =)

So what's happening here? Line 1 contains a definition - F_CPU (F for frequency). Many modules/headers that can be used for programming an AVR need some information about how the processor is clocked. For example, the delay routine further below needs this information to know how long to wait, other functions that perform some I/O tasks also need this value for timing purposes. An ATtiny13 is, if its fuses are not modified, clocked at approximately 1.2MHz, or 1200000Hz. If the internal RC oscillator is used (as it is by default), the real frequency can vary by several percent and is dependent on ambient temperature and supply voltage, among other things. If a more exact frequency is needed, the AVRs can be clocked by an external source, for example by a quartz oscillator.

The include in line 3 provides the port definitions, like 'DDRB' and 'PB2', the next include allows us to use the '_delay_ms()' function.

In line 9, the data direction register for port B 'DDRB' is configured. Writing a one to the bit corresponding to a port pin tells the controller that we want to use this port as an output port. By default, all 'DDRB' bits are set to zero, so all ports are configured as inputs. We write ones to the bits corresponding pins 0, 1 and 2 of port B, since we have attached our LEDs to these pins.

The main program loop outputs the value of i as binary value to the three port B pins, loops i though 0..7 and waits 500 milliseconds.

The output in line 14 is done via the port B data register, PORTB. Each pin of port B corresponds to a bit in the PORTB register - e.g. writing a one to the bit at position PB0 sets the the output of the corresponding pin to high level, so an LED connected to this pin lights up.

Masking i by the bit pattern for PB0..PB2 doesn't really make sense here since i will have no other bits set, but I left it in to make clear what's happening here.

The call to '_delay_ms()' in line 18 causes the program to wait for half a second. This doesn't mean the processor is halted. The value '500 ms' is used internally together with the frequency defined via 'F_CPU' to calculate the right amount of processor cycles that need to be wasted to cause the right delay.

That's all there is to it. The most important thing to be taken from this example is that the I/O ports of the controller can be used like normal variables, their physical state is reflected in the variable's memory, they are memory mapped.

Next up: Using a button to interact with our micro controller.




Tuesday, January 22, 2013

First steps with an ATtiny

The way I got to programming microcontrollers was that I wanted to build a 15 minute timer. The goal was to have a simple circuit that counts down for 15 minutes after I pressed a button, giving me some visual cue when the time is up. I chose to try and realize this via one of those small Atmel ATtiny controllers.

So I bought an ATtiny13, as it was one of the cheapest controllers around. After some searching around for a way to program it, some tutorials mentioned a small, cheap and easy to use ISP (in-system programming) programmer, the Pocket AVR Programmer sold by SparkFun. From playing around with electronics before, I had some LEDs and resistors and a breadboard lying around, so I just could start once the parts were delivered.

The first project was to just flash some LEDs as a test of functionality. This project turned out to be the first project I port to other controllers I want to test, as it is very easy to put together.

For programming an AVR microcontroller you need:
  • A programmer. There are lots of them, I chose the Pocket AVR Programmer.
  • A microcontroller. There are also lots of them, you would need to find the one that fits your application - for my first steps I chose the ATtiny13.
  • Some wires, preferably in different colors. I got a length of CAT 6 network cable from a friend, taking 15cm of it apart and stripping the insulation off the ends yielded very useful cables.
  • A breadboard
For this project, you also need:
  • 3 LEDs - I had some red 2V 20mA LEDs lying around.
  • Resistors for your LEDs
The right resistors for this would be (5V-2V)/0.02A = 150Ω - I had some 1kΩ resistors and they worked nicely.

Hardware

First, we'll have to put the hardware together. To make the programmer talk to your microcontroller, the serial bus, consisting of the MOSI (master out slave in), MISO (master in slave out), SCK (serial clock) and RST (reset) wires, needs to be connected according to the spec sheets of the programmer and the microcontroller. Of course you'll have to connect the VCC and GND pins, too.  Using the (preferably colored) wires, you can either use the 6-pin connector that comes with the controller or solder your own connector:


Using the 6-pin connector of the pocket programmer

To have a bit less clutter I soldered my own connector
Wire the pins to the microcontroller and also put the LEDs with their resistors on the breadboard, according to the following schematic. Note: Pin1 on the ATtiny is where the small dot is on its body, and LEDs have a + and a - side, the side with the longer wire is +.

Schematic for our first project


When you're done, the breadboard should look somewhat like this.

The finished setup


Software

To control the programmer from our PC, we need to install some drivers, some programmer software and to actually have something to write to the microcontroller, we need a compiler:
  • The SparkFun page links the drivers for Windows, including a workaround for Win64 systems (you need to replace some files in the driver directory). Unzip the files, plug in the programmer and point the driver dialog to the location of the driver files.
  • AVRDUDE is a program to upload our program (and do a lot of other stuff).
  • Atmel offers a version of Visual Studio as a development platform: Atmel Studio. This is quite a huge download, but worth it since you'll get the comfort of a good IDE.
While you wait for Atmel Studio to load, you can check your wiring and that you installed both AVRDUDE and the driver correctly. Open a console and type
avrdude -c usbtiny -p t13 -n -v
And hit <enter>. This command tries to connect to the ATtiny13 and reads back some info. It should result in something like the output below (click the image). If something fails, check the wiring and make sure the driver is installed correctly.

Software (again)

Now that everything is set up, we can start coding. Fire up AtmelStudio, choose File->New->Project. Select "GCC C++ Executable Project" and choose a name and a directory below. After clicking OK a 'Device Selection' dialog will appear, choose 'ATtiny13' (duh) and click OK. To make programming the microcontroller even easier, click Project-><name> Properties, choose 'Build Events' on the left, and add
avrdude -c usbtiny -p $(avrdevice) -U flash:w:$(SolutionName).hex
as a post-build event. This will execute AVRDUDE and copy the binary file of our program to the microcontroller after the program was built successfully.


Copy the following code into the code window of your main .cpp file:

#define F_CPU 1200000UL

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

int main (void)
{
  // port B pins 0, 1, 2 as output
  DDRB = (1 << PB2) | (1 << PB1) | (1 << PB0);

  unsigned int i = 0;
  while( true )
  {
    PORTB = i & ( (1 << PB2) | (1 << PB1) | (1 << PB0) );

    i = (i+1) % 8;
    
    _delay_ms( 500 );
  }
}
... and hit F7 ("Build Solution"). If the project is set up correctly, AVRDUDE is installed correctly, the drivers work and the wiring is correct the build should complete and call AVRDUDE, which in turn copies the compiled code onto your microcontroller (the LEDs will flash a bit while happens). Then the ATtiny resets and the LEDs should start blinking. Congratulations! You finished your first project. We'll take the code apart in the next post.


Monday, January 21, 2013

Hello World.

We'll see what turns up here. My first idea was to collect some information about micro controller programming.