Help with atmega168 needed

Hi! We are programming a robot in a school project, namely a Johnny 5. For the servo steering, a SSC-32 microcontroller (containing an atmega168) is used, for steering 12 servos in total (pins 16 and 19 - 29, two of the servos has been removed), connected to pins belonging to two shift/storage registers (# 2 and 3). I have written test code and programmed it with, and I think that I should get some reactions from the arms, but nope, nothing happens. Anyway, here is the code that I’ve written to test it:

main.c:

/*** Includes ***************************************************************/
/* External library headers */
#include <avr/interrupt.h>
#include <avr/io.h>
 
/* Project headers */
#include "servos/servos.h"
 
/*** Main function **********************************************************/
int main(void)
{ 
    /* Init pin values */
    init_system();
    /* enable interrupts */
    sei();

    while (1) /* prevent process from from terminating */
    {
        DDRD = 0xff; /* disable the compiler to optimize the loop away */
    }
 
    return 1;
}

servos/servos.h:

#ifndef SERVOS_H
#define SERVOS_H

#include "common.h"

void
init_system(void);

#endif

servos/servos.c:


/****************************************************************************
 * INCLUDE FILES                                                            *
 ****************************************************************************/

#include <stdint.h>

#include <avr/interrupt.h>
#include <avr/io.h>

#include "servos.h"
void
init_system(void)
{
    DDRD = 255;
    /* Use wavegeneration mode 12 and clock select 4 (prescaler = 256) */
    TCCR1A = 0;
    TCCR1B = _BV(WGM13)|_BV(WGM12)|_BV(CS12);
    /* Prescaler = 256, processor speed = 14745600 Hz, Timer frequency = 57600 Hz */
    ICR1 = 89; /* Counter max value ~ 1.55 ms */
    TIMSK1 = _BV(ICIE1); /* Enable input capture interrupt */
}

inline static void
test_func_servos(void)
{
    static uint8_t i = 0;
    /* i will count from 0 to 12 and then back to 0 again*/
    i++;
    if (i == 13)
    {
        i = 0;

        /* Set signals to servos high until next interrupt (should be in approx. 1.55 ms) */
        SPDR = 255; /* Sending to shift registers will start automatically when writing to this register... */
        /* Wait for transmission complete */
        while (!(SPSR & _BV(SPIF)) ) ;

        /* Clock out the content of the shift register, use BANK2-RCK as clock signal */
        PORTD |=  _BV(PD6);
        PORTD &= ~_BV(PD6);

        SPDR = 255;
        /* Wait for transmission complete */
        while (!(SPSR & _BV(SPIF)) ) ;

        /* Clock out the content of the shift register, use BANK3-RCK as clock signal */
        PORTD |=  _BV(PD7);
        /* __no_operation(); */
        PORTD &= ~_BV(PD7);
    }
    else
    {
        /* Set signals to servos low in the next 12 interrupts (should take 12 * 1.55 ~ 18,6 ms ) */
        SPDR = 0;
        /* Wait for transmission complete */
        while (!(SPSR & _BV(SPIF)) ) ;

        /* Clock out the content of the shift register, use BANK2-RCK as clock signal */
        PORTD |=  _BV(PD6);
        PORTD &= ~_BV(PD6);

        SPDR = 0;
        /* Wait for transmission complete */
        while (!(SPSR & _BV(SPIF)) ) ;

        /* Clock out the content of the shift register, use BANK3-RCK as clock signal */
        PORTD |=  _BV(PD7);
        /* __no_operation(); */
        PORTD &= ~_BV(PD7);
    }
}

/* Callback function to be called every time timer 1 reaches its top value and starts over again. */
ISR(TIMER1_CAPT_vect)
{
    test_func_servos();
}

Using this test program, I should have set up a timer which counts with 57600 Hz, and with a top value at 89, it should take only about 1.55 ms for the timer to loop, and about 20.1 ms for the timer to perform 13 loops. In my function test_func_servos that should be called every time the timer reaches it’s top value and an interrupt occurs, the static variable i counts from 0 to twelve and then starts over again, getting a loop time at (1 + 12) * 1.55 ms ~ 20.1 ms, and a pulse at 1.55 ms should be sent to every servo once every 20.1 ms, which means that they all should set to their middle positions. However, nothing happens, and I have no idea of what is wrong. Coed anyone know why it is not working? Have I forgot to set some flag in some register or set some register incorrectly? Thanks in advance! :slight_smile:

Sorry, I am probably not much help here as I have never tried to update the software that runs on the SSC-32.

If you have a logic analyzer available, it would be good to see if you are getting any signals on those pins.

I would start debugging at a simple level. For example is your interrupt hander being called? I would try something like: toggle the LED pin as a way to see if it is being called correctly…

Things to look at include: are you hooking the right interrupt? Are you really wanting a timer input capture event, or are you wanting a compare match interrupt?

Good Luck
Kurt