Hallo,
als ich mir gerade das Programm RP6Base_I2CSlave.c ansah, kam ich zu der Funktion task_update:
Code:
uint16_t uBat_measure = 720;
uint8_t  uBat_count = 0;        
        
/**
 * This function needs to be called frequently in the main loop. It updates
 * some values (currently only Battery Voltage and Motor status, but this may
 * be expanded in future). 
 */ 
void task_update(void)
{
    if(getStopwatch4() > 250)
    {
        uBat_measure += adcBat;
        uBat_measure /= 2;
        uBat_count++;
        setStopwatch2(0);
    }
    if(uBat_count > 5)
    {
        if(!interrupt_status.batLow && uBat_measure < 560)
        {
            interrupt_status.batLow = true;
            signalInterrupt();
        }
        else if(interrupt_status.batLow && uBat_measure > 580)
        {
            interrupt_status.batLow = false;
            signalInterrupt();
        }
        uBat_count = 0;
    }
        
    drive_status.motorsOn = (mleft_power || mright_power);
    drive_status.direction = getDirection();
 }
und fragte mich wieso in der Zeile 16 setStopwatch2(0); steht ich finde setStopwatch4(0); sinnvoller, weil sonst die Funktion immer ausgefürt wird nicht nur nach den die Zeit abgelaufen ist. Oder verstehe ich das Falsch?

Hier noch mal der Komplette Quellcode:
Code:
/* 
 * ****************************************************************************
 * RP6 ROBOT SYSTEM - ROBOT BASE EXAMPLES
 * ****************************************************************************
 * Example: I2C Slave
 * Author(s): Dominik S. Herwald
 * ****************************************************************************
 * Description:
 *
 * A very common thing that many users will want to do with their RP6 is 
 * to control it with a second controller which has more free resources. 
 * (more free memory, free I/O Ports and ADCs, faster, etc. pp.
 * for example the RP6-M32 expansion Module)
 * 
 * This programs allows you to control the Robot Base Unit completely via
 * I2C-Bus as a slave device!
 * 
 * Also have a look at the RP6 CONTROL M32 example programs which can also
 * be found on this CD-ROM - there you get examples of how to use
 * this program! 
 *  
 * ****************************************************************************
 */

/*****************************************************************************/
// Includes:

#include "RP6RobotBaseLib.h"     

#include "RP6I2CslaveTWI.h"     // Include the I²C-Bus Slave Library

/*****************************************************************************/

// The Slave Address on the I2C Bus can be specified here:
#define RP6BASE_I2C_SLAVE_ADR 10

/*****************************************************************************/

// This bitfield contains the main interrupt event status bits. This can be
// read out and any Master devices can react on the specific events.
union {
     uint8_t byte;
    struct {
        uint8_t batLow:1;
        uint8_t bumperLeft:1;
        uint8_t bumperRight:1;
        uint8_t RC5reception:1;
        uint8_t RC5transmitReady:1;
        uint8_t obstacleLeft:1;
        uint8_t obstacleRight:1;
        uint8_t driveSystemChange:1;
    };
} interrupt_status;

// Some status bits with current settings and other things.
union {
     uint8_t byte;
    struct {
        uint8_t powerOn:1;
        uint8_t ACSactive:1;
        uint8_t watchDogTimer:1;
        uint8_t wdtRequest:1;
        uint8_t wdtRequestEnable:1;
        uint8_t unused:3;
    };
} status;

// Drive Status register contains information about current movements. 
// You can check if movements are complete, if the motors are turned
// on, if there were overcurrent events and for direction.
union {
     uint8_t byte;
    struct {
        uint8_t movementComplete:1;
        uint8_t motorsOn:1;
        uint8_t motorOvercurrent:1;
        uint8_t direction:2;
        uint8_t unused:3;
    };
} drive_status;


RC5data_t lastRC5Reception;

/*****************************************************************************/

/**
 * Generates Interrupt Signal and starts Software Watchdog
 */ 
void signalInterrupt(void)
{
    I2CTWI_dataWasRead = 0;
    extIntON();
    if(status.watchDogTimer)
        startStopwatch2();
}

/**
 * Clears Interrupt
 */ 
void clearInterrupt(void)
{
    stopStopwatch2();
    setStopwatch2(0);
    status.wdtRequest = false;
    interrupt_status.RC5reception = false;
    interrupt_status.driveSystemChange = false;
    extIntOFF();
}

/**
 * ACS Event Handler 
 */ 
void acsStateChanged(void)
{
    interrupt_status.obstacleLeft = obstacle_left;
    interrupt_status.obstacleRight = obstacle_right;
    signalInterrupt();
}

/**
 * Bumpers Event Handler
 */ 
void bumpersStateChanged(void)
{
    interrupt_status.bumperLeft = bumper_left;
    if(bumper_right)
        interrupt_status.bumperRight = true;
    else
        interrupt_status.bumperRight = false;
    signalInterrupt();
}

/**
 * RC5 Event Handler
 */ 
void receiveRC5Data(RC5data_t rc5data)
{
    lastRC5Reception.toggle_bit = rc5data.toggle_bit;
    lastRC5Reception.device = rc5data.device;
    lastRC5Reception.key_code = rc5data.key_code;
    interrupt_status.RC5reception = true;
    signalInterrupt();
}    

/**
 * Motion Control Event Handler
 */ 
void motionControlStateChanged(void)
{
    drive_status.movementComplete = isMovementComplete();
    drive_status.motorOvercurrent = motion_status.overcurrent;
    interrupt_status.driveSystemChange = true;
    signalInterrupt();
}


uint16_t uBat_measure = 720;
uint8_t  uBat_count = 0;        
        
/**
 * This function needs to be called frequently in the main loop. It updates
 * some values (currently only Battery Voltage and Motor status, but this may
 * be expanded in future). 
 */ 
void task_update(void)
{
    if(getStopwatch4() > 250)
    {
        uBat_measure += adcBat;
        uBat_measure /= 2;
        uBat_count++;
        setStopwatch2(0);
    }
    if(uBat_count > 5)
    {
        if(!interrupt_status.batLow && uBat_measure < 560)
        {
            interrupt_status.batLow = true;
            signalInterrupt();
        }
        else if(interrupt_status.batLow && uBat_measure > 580)
        {
            interrupt_status.batLow = false;
            signalInterrupt();
        }
        uBat_count = 0;
    }
        
    drive_status.motorsOn = (mleft_power || mright_power);
    drive_status.direction = getDirection();
}

/*****************************************************************************/
// I2C Registers that can be read by the Master. Their names should 
// be self-explanatory and directly relate to the equivalent variables/functions 
// in the RP6Library

#define I2C_REG_STATUS1          0
#define I2C_REG_STATUS2          1
#define I2C_REG_MOTION_STATUS      2
#define I2C_REG_POWER_LEFT          3
#define I2C_REG_POWER_RIGHT      4
#define I2C_REG_SPEED_LEFT          5
#define I2C_REG_SPEED_RIGHT      6
#define I2C_REG_DES_SPEED_LEFT      7
#define I2C_REG_DES_SPEED_RIGHT  8
#define I2C_REG_DIST_LEFT_L      9
#define I2C_REG_DIST_LEFT_H      10
#define I2C_REG_DIST_RIGHT_L     11
#define I2C_REG_DIST_RIGHT_H      12
#define I2C_REG_ADC_LSL_L          13
#define I2C_REG_ADC_LSL_H          14
#define I2C_REG_ADC_LSR_L          15
#define I2C_REG_ADC_LSR_H          16
#define I2C_REG_ADC_MOTOR_CURL_L 17
#define I2C_REG_ADC_MOTOR_CURL_H 18
#define I2C_REG_ADC_MOTOR_CURR_L 19
#define I2C_REG_ADC_MOTOR_CURR_H 20
#define I2C_REG_ADC_UBAT_L          21
#define I2C_REG_ADC_UBAT_H          22
#define I2C_REG_ADC_ADC0_L          23
#define I2C_REG_ADC_ADC0_H          24
#define I2C_REG_ADC_ADC1_L          25
#define I2C_REG_ADC_ADC1_H          26
#define I2C_REG_RC5_ADR              27
#define I2C_REG_RC5_DATA          28
#define I2C_REG_LEDS              29


/**
 * This very important function updates ALL registers that the Master can read.
 * It is called frequently out of the Main loop. 
 */
void task_updateRegisters(void)
{
    if(!I2CTWI_readBusy) 
    {
        I2CTWI_readRegisters[I2C_REG_STATUS1] =          (uint8_t)(interrupt_status.byte);
        I2CTWI_readRegisters[I2C_REG_STATUS2] =          (uint8_t)(status.byte);
        I2CTWI_readRegisters[I2C_REG_MOTION_STATUS] =      (uint8_t)(drive_status.byte);
        I2CTWI_readRegisters[I2C_REG_POWER_LEFT] =          (uint8_t)(mleft_power);
        I2CTWI_readRegisters[I2C_REG_POWER_RIGHT] =      (uint8_t)(mright_power);
        I2CTWI_readRegisters[I2C_REG_SPEED_LEFT] =          (uint8_t)(getLeftSpeed());
        I2CTWI_readRegisters[I2C_REG_SPEED_RIGHT] =      (uint8_t)(getRightSpeed());
        I2CTWI_readRegisters[I2C_REG_DES_SPEED_LEFT] =      (uint8_t)(getDesSpeedLeft());
        I2CTWI_readRegisters[I2C_REG_DES_SPEED_RIGHT] =  (uint8_t)(getDesSpeedRight());
        I2CTWI_readRegisters[I2C_REG_DIST_LEFT_L] =      (uint8_t)(getLeftDistance());
        I2CTWI_readRegisters[I2C_REG_DIST_LEFT_H] =      (uint8_t)(getLeftDistance()>>8);
        I2CTWI_readRegisters[I2C_REG_DIST_RIGHT_L] =      (uint8_t)(getRightDistance());
        I2CTWI_readRegisters[I2C_REG_DIST_RIGHT_H] =      (uint8_t)(getRightDistance()>>8);
        I2CTWI_readRegisters[I2C_REG_ADC_LSL_L] =          (uint8_t)(adcLSL);
        I2CTWI_readRegisters[I2C_REG_ADC_LSL_H] =          (uint8_t)(adcLSL>>8);
        I2CTWI_readRegisters[I2C_REG_ADC_LSR_L] =          (uint8_t)(adcLSR);
        I2CTWI_readRegisters[I2C_REG_ADC_LSR_H] =          (uint8_t)(adcLSR>>8);
        I2CTWI_readRegisters[I2C_REG_ADC_MOTOR_CURL_L] = (uint8_t)(adcMotorCurrentLeft);
        I2CTWI_readRegisters[I2C_REG_ADC_MOTOR_CURL_H] = (uint8_t)(adcMotorCurrentLeft>>8);
        I2CTWI_readRegisters[I2C_REG_ADC_MOTOR_CURR_L] = (uint8_t)(adcMotorCurrentRight);
        I2CTWI_readRegisters[I2C_REG_ADC_MOTOR_CURR_H] = (uint8_t)(adcMotorCurrentRight>>8);
        I2CTWI_readRegisters[I2C_REG_ADC_UBAT_L] =          (uint8_t)(adcBat);
        I2CTWI_readRegisters[I2C_REG_ADC_UBAT_H] =          (uint8_t)(adcBat>>8);
        I2CTWI_readRegisters[I2C_REG_ADC_ADC0_L] =          (uint8_t)(adc0);
        I2CTWI_readRegisters[I2C_REG_ADC_ADC0_H] =          (uint8_t)(adc0>>8);
        I2CTWI_readRegisters[I2C_REG_ADC_ADC1_L] =          (uint8_t)(adc1);
        I2CTWI_readRegisters[I2C_REG_ADC_ADC1_H] =          (uint8_t)(adc1>>8);
        I2CTWI_readRegisters[I2C_REG_LEDS] =              (uint8_t)(statusLEDs.byte);
        I2CTWI_readRegisters[I2C_REG_RC5_ADR] =          (uint8_t)((lastRC5Reception.device)|(lastRC5Reception.toggle_bit<<5));
        I2CTWI_readRegisters[I2C_REG_RC5_DATA] =          (uint8_t)(lastRC5Reception.key_code);
        if(I2CTWI_dataWasRead && I2CTWI_dataReadFromReg == 0)
            clearInterrupt();
    }
}

/*****************************************************************************/
// Command Registers - these can be written by the Master.
// The other registers (read registers) can NOT be written to. The only way to
// communicate with the Robot is via specific commands. 
// Of course you can also add more registers if you like...

// ----------------------

#define I2C_REGW_CMD 0
#define I2C_REGW_CMD_PARAM1 1
#define I2C_REGW_CMD_PARAM2 2
#define I2C_REGW_CMD_PARAM3 3
#define I2C_REGW_CMD_PARAM4 4
#define I2C_REGW_CMD_PARAM5 5
#define I2C_REGW_CMD_PARAM6 6

// ----------------------

uint8_t cmd;
uint8_t param1;
uint8_t param2;
uint8_t param3;
uint8_t param4;
uint8_t param5;
uint8_t param6;

/**
 * Checks if a new Command has been received and also reads all 
 * paramters associated with this command.
 * It returns true if a new command has been received.
 */
uint8_t getCommand(void)
{
    if(I2CTWI_writeRegisters[I2C_REGW_CMD] && !I2CTWI_writeBusy) 
    {
        cmd = I2CTWI_writeRegisters[I2C_REGW_CMD]; // store command register
        I2CTWI_writeRegisters[I2C_REGW_CMD] = 0; // clear command register (!!!)
        param1 = I2CTWI_writeRegisters[I2C_REGW_CMD_PARAM1]; // parameters 1-6...
        param2 = I2CTWI_writeRegisters[I2C_REGW_CMD_PARAM2];
        param3 = I2CTWI_writeRegisters[I2C_REGW_CMD_PARAM3];
        param4 = I2CTWI_writeRegisters[I2C_REGW_CMD_PARAM4];
        param5 = I2CTWI_writeRegisters[I2C_REGW_CMD_PARAM5];
        param6 = I2CTWI_writeRegisters[I2C_REGW_CMD_PARAM6];
        return true;
    }
    return false;
}

/*****************************************************************************/
// Command processor:


uint8_t leds = 1;

// Commands:
#define CMD_POWER_OFF         0
#define CMD_POWER_ON         1
#define CMD_CONFIG             2
#define CMD_SETLEDS         3
#define CMD_STOP               4
#define CMD_MOVE_AT_SPEED   5
#define CMD_CHANGE_DIR        6
#define CMD_MOVE             7
#define CMD_ROTATE             8
#define CMD_SET_ACS_POWER    9 
#define CMD_SEND_RC5        10 
#define CMD_SET_WDT            11 
#define CMD_SET_WDT_RQ        12

// Parameters for CMD_SET_ACS_POWER:
#define ACS_PWR_OFF  0
#define ACS_PWR_LOW  1
#define ACS_PWR_MED  2
#define ACS_PWR_HIGH 3

/**
 * This function checks if commands have been received and processes them.
 */ 
void task_commandProcessor(void)
{
    if(getCommand()) 
    {
        switch(cmd) 
        {
            case CMD_POWER_OFF:    powerOFF(); status.powerOn = false; break;
            case CMD_POWER_ON:  powerON(); status.powerOn = true; break;
            case CMD_CONFIG: break;
            case CMD_SETLEDS: setLEDs(param1); break;
            case CMD_STOP: stop(); break;
            case CMD_MOVE_AT_SPEED: moveAtSpeed(param1, param2); break;
            case CMD_CHANGE_DIR: changeDirection(param1); break;
            case CMD_MOVE: move(param1, param2, ((param3<<8)+param4), false); break;
            case CMD_ROTATE: rotate(param1, param2, ((param3<<8)+param4), false); break;
            case CMD_SET_ACS_POWER: 
                switch(param1)
                {
                    case ACS_PWR_OFF: 
                        disableACS(); setACSPwrOff(); status.ACSactive = false; 
                    break;
                    case ACS_PWR_LOW: 
                        enableACS(); setACSPwrLow();  status.ACSactive = true; 
                    break;
                    case ACS_PWR_MED: 
                        enableACS(); setACSPwrMed();  status.ACSactive = true; 
                    break;
                    case ACS_PWR_HIGH: 
                        enableACS(); setACSPwrHigh(); status.ACSactive = true; 
                    break;
                }
            break;
            case CMD_SEND_RC5: IRCOMM_sendRC5(param1, param2); break;
            case CMD_SET_WDT: status.watchDogTimer = param1 ? true : false; break;
            case CMD_SET_WDT_RQ: status.wdtRequestEnable = param1 ? true : false; break;
        }
    }
}

/**
 * This is the Software watchdog function. After any interrupt event, a timer is
 * stated and if a certain amount of time has passed by with no reaction from
 * the Master, the Robot is stopped to prevent any damages. Usually the Master
 * program has errors or is locked up if it does not react, so this it is
 * very good idea to stop moving.
 */
void task_MasterTimeout(void)
{
    if(status.watchDogTimer)
    {
        if( getStopwatch2() > 3000)  // 3 seconds timeout for the master to react on
        {                            // our interrupt events - if he does not react, we 
                                    // stop all operations!
            cli();
            IRCOMM_OFF();
            setACSPwrOff();
            OCR1AL = 0;
            OCR1BL = 0;
            TCCR1A = 0;
            powerOFF();
            writeString_P("\n\n##### EMERGENCY SHUTDOWN #####\n");
            writeString_P("##### ALL OPERATIONS STOPPED TO PREVENT ANY DAMAGE! #####\n\n");
            writeString_P("The Master Controller did not respond to the interrupt requests\n");
            writeString_P("within the defined timeout! Maybe he's locked up!\n");
            writeString_P("\nThe Robot needs to be resetted now.\n\n");
            while(true) // Rest In Peace
            {
                setLEDs(0b100010);
                uint8_t dly;
                for(dly = 10; dly; dly--)
                    delayCycles(32768);
                setLEDs(0b010100);
                for(dly = 10; dly; dly--)
                    delayCycles(32768);
            }
        }
        else if(getStopwatch3() > 250)
        {
            status.wdtRequest = true;
            signalInterrupt();
            setStopwatch3(0);
        }
    }
}

/*****************************************************************************/
// Main - The program starts here:

int16_t main(void)
{
    initRobotBase();
    
    setLEDs(0b111111);
    mSleep(100);       
    setLEDs(0b000000);

    I2CTWI_initSlave(RP6BASE_I2C_SLAVE_ADR);
    
    ACS_setStateChangedHandler(acsStateChanged);
    BUMPERS_setStateChangedHandler(bumpersStateChanged);
    IRCOMM_setRC5DataReadyHandler(receiveRC5Data);
    MOTIONCONTROL_setStateChangedHandler(motionControlStateChanged);

    powerON();

    startStopwatch1();

    disableACS();
    setACSPwrOff();
    
    status.byte = 0;
    interrupt_status.byte = 0;
    drive_status.byte = 0;
    
    status.watchDogTimer = false;
    status.wdtRequestEnable = false;
    
    startStopwatch3();
    startStopwatch4();
    
    while(true) 
    {
        task_commandProcessor();
        task_update();
        task_updateRegisters();
        task_RP6System();
        task_MasterTimeout();
    }
    return 0;
}
Danke schon mal für eure Antworten.
Thorben W