Let's Make Robots!

AVR C is hard!

Well, last week I got several packages of parts with lots of sets of ten. I got ten 8pin sockets, ten CR2032 batteries and ten battery holders, and most importantly ten attiny85 MCUs. I figure I can use this set of parts for a bunch of small projects, but my first project is to make a tiny bot! I've already got some tiny pager motors, and some ir emitters I can use as light sensors.

Of course my first problem was figuring out how to program these little things. I've been using Arduino relatives up until now, so I don't have a proper chip programmer. I'd read in a few places though that an Arduino could be used to program other 8bit AVR chips. It turns out most of the posts I found about this are out of date though. Luckly there is an example 'sketch' included with the Arduino environment that lets the Arduino act as an ISP, and the comments at the top of the file had all the information I needed to wire it up!

With that sorted my second problem was: figuring out how to program it! Programming a raw AVR chip isn't simple like the Arduino, there is no hand holding. I'm not that comfortable with C, so I at least wanted an IDE. I'm on a new Macbook pro though, so I couldn't even use the standard (Windows only) IDE. It wasn't hard to install the AVR crosspack for OSX and get Eclipse setup with the AVR plugin. From there I found a blinking LED tutorial somewhere, and read some tutorials in the AVR-Freaks forum. It is kind of a wierd way to work, but I'm starting to understand how to talk to these things. (BTW I had to specify a bitrate for AVRdude before it would work, but setting the bitrate with the avr plugin seemed buggy)

So after getting a light to blink I started working on the most basic thing I would need to get a bot working: using PWM to run a motor. This is where things got really tricky. All the tutorials I could find were doing the pulsing manually by playing with timers and interrupts, and the datasheet was just a bunch of nonsense acronyms and no clear example of the steps to get working PWM... Well, after hours of searching and reading on the internet, and reading the datasheet backward and forward I finally figured out the magic incantations used to run hardware PWM!

Here are some pictures of my setup:


Red and Black for power, Orange/Blue for ISP programming, White for ISP signal LEDs.

I got the motor driver "design" from the project here, which is incidentally about the same as what I want to make. It is just a transistor acting as a switch driven by a data pin, and a snubber diode. This only allows motor control in one direction, but my design still has one free data pin, so if I were clever I could probably find a way to switch the motor connections?

Here is my code:

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

// I haven't decided about these yet...
#define bit_get(p,m) ((p) & (m))
#define bit_set(p,m) ((p) |= (m))
#define bit_clear(p,m) ((p) &= ~(m))
#define bit_flip(p,m) ((p) ^= (m))
#define BIT(x) (0x01 << (x))

#define MOTOR PB4

void delay_ms(uint16_t ms){
    // _delay_ms is limited, and requires a const arg for optimal code generation
    // The maximal possible delay is 262.14 ms / F_CPU in MHz. (approx. 32 at 8MHz)
    int i;
    if (ms <= 32){
    ms = ms/32; // note rounding error!
    for (i=0;i<32;i++){

void setup_pwm(void){
    // Do all the bit twiddling magic to activate hardware PWM (only using pwmb for this test)
    int i;
    // First setup the pll (Fast Peripheral Clock)
    _delay_ms(0.1); // Datasheet
    for (i=0;i<255;i++) { // timeout at 256 trys
        if (~bit_get(PLLCSR, 0x01)) { // Wait for the PLOCK bit to be set
    // Set clock rate prescaler for 250kHz (From datasheet)
    TCCR1 = 0x01;
    // Setup timer1b for PWM on pb4
    // Set the Output Compare Register for 50% duty cycle
    OCR1B = BIT(7);

int main(void){
    int i;
    // Set clock full speed
    // Set port b to output
    for (;;){
        for (i=0;i<255;i++){
            // Change the PWM duty cycle
            OCR1B = i;
            // delay for a while
        for (i=255;i>0;i--){
            // Change the PWM duty cycle
            OCR1B = i;
            // delay for a while
        // pause for a moment
        DDRB = 0x00;
        DDRB = BIT(MOTOR);

    return (1);    // should never happen

It may not be the best code around, but like I said - I couldn't find any decent examples!

Next I'll try to get some ADC readings with my irLEDs!

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

Yeah, I should try the built-in. Because of my lack of pins I was thinking more along the lines of this here. I2C gives multiple slaves on one bus.

BTW: I found this while playing with LED 'simultaneous' light sensing and emission: Link to main page

I've just ordered a ATtiny84A, I'm looking forward to building a little tracked robot with it. Seems like AVR-C is quite a bit harder than Arduino coding, but it will be interesting to be able to access the chip on a very low level. As far as I know, if you use an Arduino as an ISP you can write Arduino functions (eg. digitalWrite()) that will then run on the ATtiny, or you can use AVR-C. Both work.

Except perhaps the pinout for the ATtiny will differ from the Arduino pinout, and you will not (especially if you are using the 8-pin ATtiny85!) be able to use all the pins available on the Arduino software (0-13) it would be more like 0-6 for ATtiny85.