Bei meiner 10 bit Variante hört man die Motoren manchmal leise piepsen
7Khz hört man halt - aber als Nachteil finde ich das nicht. Ich fänd's cool, wenn er proportional zur Geschwindigkeit brummen tät. Irgendwas mit Prescaler 64 und Fast PWM oder so..


Code:
/*********************************************************************



			N I B O B E E  Feste Zykluszeit für Mainloop und 

			zyklische (Sensor) Ein- und (LED) Ausgabe 



			Version 1.07 für alternative Nibobee C Bib von s.frings

			20100411 Birger Töpelmann 



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

#ifndef _ZYKLUS_H_
#define _ZYKLUS_H_




// Folgende Zeile auskommentieren für "normalen" NiboBee

#define _LED6_MUX_          // 6 LEDs an PB0..PB2; PB3 ist frei

/*--------------------------------------------------------------------


- PB2 -|100R|-->(x)			es leuchtet pro Takt immer nur eine LED;

- PB1 -|100R|-->(y)			ein PIN ist Plus, ein PIN Minus, ein Pin offen

- PB0 -|100R|-->(z)			LED (Vor-)Widerstand 2 x 100R



LED_Pattern

Bit 			  Anode - Kathode  	DDRB	PORTB

 0	DUO links grün	(y) - (z)		..110	..010

 1	DUO links rot	(x) - (z)		..101	..001

 2	DUO rechts grün	(z) - (y)		..110	..100

 3	DUO rechts rot	(x) - (y)		..011	..001

 4	ROTAUGE links	(z) - (x)		..011	..010

 5	ROTAUGE rechts	(y) - (x)		..101	..100





Zuordnung LED_Pattern Bit# und LED anpassbar in led_ausgabe():



	case 0:{ ddr = 0x06; pin = 0x02;} break; // DUO links grün

	case 1:{ ddr = 0x05; pin = 0x01;} break; // DUO links rot

	case 2:{ ddr = 0x06; pin = 0x04;} break; // DUO rechts grün

	case 3:{ ddr = 0x03; pin = 0x01;} break; // DUO rechts rot

	case 4:{ ddr = 0x03; pin = 0x02;} break; // ROTAUGE links

	case 5:{ ddr = 0x05; pin = 0x04;} break; // ROTAUGE rechts



--------------------------------------------------------------------*/




//#include "nibobee.h" 		// s.frings Bibliothek

#include "zyklus.h" 		// also includes "nibobee.h"

#include <stdio.h>
#include <avr/interrupt.h>
#include <util/atomic.h>
#include <util/delay.h>


/******************************************* ZYKLUS & CLOCK ***********/



// 				zählt bis 1000 (1s) in 1ms Schritten
volatile uint16_t takt_ms;
//				zählt die Sekunden seit dem Systemstart
volatile uint32_t takt_sec;
// 				Zyklustimer wird in ISR inkrementiert und in Zyklus()

volatile uint8_t zyklus_ms;		// überwacht und genullt


// 	bremst die Hauptschleife auf feste Zykluszeit (Zzeit in ms)

// 	organisert LED Ausgabe und Sensoren Eingabe mit Flankenerkennung

uint8_t Zyklus(uint8_t Zzeit);





/****************************************** Sensoren ******************/



volatile uint8_t Sensors;	// Aktueller Eingabestatus

volatile uint8_t SensSFL;   // Steigende Flanke erkannt

volatile uint8_t SensFFL;   // Fallende Flanke erkannt



/*---------------------------------------------------------------------

Flankenerkennung (Trigger):



		0101 Bitmuster vorher

		0011 Bitmuster aktuell

		0010 Bitmuster steigende Flanke

		0100 Bitmuster fallende Flanke



----------------------------------------------------------------------*/



void sens_eingabe();		// SensorPins lesen/Flankenerkennung



#define SENS_SW1_1 readBit(Sensors,4)
#define SENS_SW2_1 readBit(Sensors,5)
#define SENS_SW3_1 readBit(Sensors,7)
#define SENS_SW4_1 readBit(Sensors,6)

#define SENS_SW1_S readBit(SensSFL,4)
#define SENS_SW2_S readBit(SensSFL,5)
#define SENS_SW3_S readBit(SensSFL,7)
#define SENS_SW4_S readBit(SensSFL,6)

#define SENS_SW1_F readBit(SensFFL,4)
#define SENS_SW2_F readBit(SensFFL,5)
#define SENS_SW3_F readBit(SensFFL,7)
#define SENS_SW4_F readBit(SensFFL,6)



/***************************************** LED MULTIPLEX **************/



volatile uint8_t LED_Pattern; // LED Ausgabemuster

volatile uint8_t LED_PattSFL;

volatile uint8_t LED_PattFFL;

volatile uint8_t LED_Blinker; // gesetztes Bit lässt LED blinken



#ifdef _LED6_MUX_ // umgebauter NiboBee

// Kompatibilität zu s.frings: entsprechendes Bit in Pattern setzen

#define set_LED0(value) writeBit(LED_Pattern,1,value)
#define set_LED1(value) writeBit(LED_Pattern,4,value)
#define set_LED2(value) writeBit(LED_Pattern,5,value)
#define set_LED3(value) writeBit(LED_Pattern,3,value)

// Returns 1, if the LED is on
#define LED0 readBit(LED_Pattern,1)
#define LED1 readBit(LED_Pattern,4)
#define LED2 readBit(LED_Pattern,5)
#define LED3 readBit(LED_Pattern,3)


#else // normaler NiboBee



// Kompatibilität zu s.frings: entsprechendes Bit in Pattern setzen

#define set_LED0(value) writeBit(LED_Pattern,0,value)
#define set_LED1(value) writeBit(LED_Pattern,1,value)
#define set_LED2(value) writeBit(LED_Pattern,2,value)
#define set_LED3(value) writeBit(LED_Pattern,3,value)

// Returns 1, if the LED is on
#define LED0 readBit(LED_Pattern,0)
#define LED1 readBit(LED_Pattern,1)
#define LED2 readBit(LED_Pattern,2)
#define LED3 readBit(LED_Pattern,3)




#endif //_LED6_MUX_





// meine LED Makros basieren auf LED Nummer



#define LED_EIN(NR) 	LED_Pattern |=  (1 << NR);

#define LED_AUS(NR) 	LED_Pattern &= ~(1 << NR); LED_Blinker &= ~(1 << NR);

#define LED_BLINK(NR) 	LED_Pattern |=  (1 << NR); LED_Blinker |=  (1 << NR);

#define LED_TOGGLE(NR) 	LED_Pattern ^=  (1 << NR);





void led_ausgabe();         // LED Multiplex Ausgabe



// Debughilfen: vordere LED links/rechts bei ea==0 aus-, 

// sonst einschalten, !! schaltet jew. die andere LED aus

void augeL(uint8_t ea);		

void augeR(uint8_t ea);     





/***************************************** LED MULTIPLEX **************/



#endif // _ZYKLUS_H_


Code:
/*********************************************************************



			N I B O B E E  Feste Zykluszeit für Mainloop und 

			zyklische (Sensor) Ein- und (LED) Ausgabe 



			Version 1.07 für alternative Nibobee C Bib von s.frings

			20100411 Birger Töpelmann 



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



#include "zyklus.h" 			
#include <stdio.h>
#include <avr/interrupt.h>
#include <util/atomic.h>
#include <util/delay.h>


/***************************************** CLOCK & MOTPID ***********/



volatile uint16_t takt_ms;
volatile uint32_t takt_sec;



//#define Zykluszeit 1  	// Zykluszeit der Hauptschleife in ms

volatile uint8_t zyklus_ms;	// Zyklustimer wird in ISR inkrementiert

							// und in Zyklus() überwacht und genullt




/************************************************* SENS *************/



volatile uint8_t Sensors = 0;	// Aktueller Eingabestatus

volatile uint8_t SensSFL = 0;   // Steigende Flanke erkannt

volatile uint8_t SensFFL = 0;   // Fallende Flanke erkannt





void sens_eingabe()

{

	SensSFL = ~Sensors;  // vorherigen Zustand merken für Flankenerkennung

	SensFFL =  Sensors;



	Sensors ^= Sensors;  // bits nullen für neuen Zustand

	Sensors |= ~(PINC & 0xf0);  // 1 == Sensor aktiv

//  Hier Eingänge von Ext-Ports Pins verOdern



	SensSFL &=  Sensors; // Steigende Flanke erkennen

	SensFFL &= ~Sensors; // Fallende Flanke erkennen

}




/************************************************* LED **************/



/*

#define LED_EIN(NR) 	LED_Pattern |=  (1 << NR);

#define LED_AUS(NR) 	LED_Pattern &= ~(1 << NR); LED_Blinker &= ~(1 << NR);

#define LED_BLINK(NR) 	LED_Pattern |=  (1 << NR); LED_Blinker |=  (1 << NR);

#define LED_TOGGLE(NR) 	LED_Pattern ^=  (1 << NR);

*/



volatile uint8_t LED_Pattern = 0;

volatile uint8_t LED_Blinker = 0;



void led_ausgabe()

{

	static 	uint16_t  tmux  = 0;



	if (0 == tmux--) tmux = 640;  // !Wert = vielfaches von 8



	uint8_t  leds = LED_Pattern;  // Pattern für Ausgabe

	if (tmux < 400) leds &= ~LED_Blinker; // Blinkbits



#ifdef _LED6_MUX_ // umgebauter NiboBee 



	uint8_t  ddr = 0;

	uint8_t  pin = 0;	



	if ((1 << (tmux & 0x07)) & leds) // welche LED soll leuchten?

	{

		switch((tmux & 0x07))

		{

			case 0:{ ddr = 0x06; pin = 0x02;} break; // DUO links grün

			case 1:{ ddr = 0x05; pin = 0x01;} break; // DUO links rot

			case 2:{ ddr = 0x06; pin = 0x04;} break; // DUO rechts grün

			case 3:{ ddr = 0x03; pin = 0x01;} break; // DUO rechts rot

			case 4:{ ddr = 0x03; pin = 0x02;} break; // ROTAUGE links

			case 5:{ ddr = 0x05; pin = 0x04;} break; // ROTAUGE rechts

//			case 6:{ ddr = 0x00; pin = 0x00;} break;

//			case 7:{ ddr = 0x00; pin = 0x00;} break;

		}

	}

	DDRB  = (DDRB  & ~0x07) | ddr; // zwei PINS als Ausgang

	PORTB = (PORTB & ~0x07) | pin; // ein Pin = 1, Rest = 0



#else  // nicht umgebauter NiboBee 



	// Auch hier wird immer nur eine LED eingeschaltet 

	// 1 * Zykluszeit Ein; 3 * Zykluszeit Aus

	PORTB = (PORTB & ~0x0f) | (leds & (1 << (tmux & 3)));





#endif //_LED6_MUX_



}



/*

// Debughilfen

void augeL(uint8_t ea)

{

	uint8_t ddr = 0;

	uint8_t pin = 0;

	if(ea){ ddr = 0x03; pin = 0x02;}  // ROTAUGE links

	DDRB  = (DDRB  & ~0x07) | ddr; // zwei PINS als Ausgang

	PORTB = (PORTB & ~0x07) | pin; // ein Pin = 1, Rest = 0

}

void augeR(uint8_t ea)

{

	uint8_t ddr = 0;

	uint8_t pin = 0;

	if(ea){ ddr = 0x05; pin = 0x04;}  // ROTAUGE rechts

	DDRB  = (DDRB  & ~0x07) | ddr; // zwei PINS als Ausgang

	PORTB = (PORTB & ~0x07) | pin; // ein Pin = 1, Rest = 0

}

*/





/******************************* TIMER 1 CONFIG  PWM & TAKT **********/



// s.frings setup:

    // Initialize the motor PWM
    // Mode 2 = phase correct 10 bit PWM,
    // channel A+B outputs are set on compare match when upcounting
    // and cleared on compare match when downcounting.


	//	TCCR1A =		   PWM invertiert  + 						   + 10bit PWM Betrieb

	//  TCCR1A = (1<<COM1A1) | (1<<COM1A0) | (1<<COM1B1) | (1<<COM1B0) | (1<<WGM11); | (1<<WGM10);




// Original nibobee (springob) setup

	//	TCCR1A =		   PWM invertiert  + 						   +  9bit PWM Betrieb

	//	TCCR1A = (1<<COM1A1) | (1<<COM1A0) | (1<<COM1B1) | (1<<COM1B0) | (1<<WGM11);


    // Use I/O clock without prescaling
	//  TCCR1B = (1<<CS10);




	// Overflow Interrupt enable
//	TIMSK  |= (1<<TOIE1);

// F_CPU    = 15 Mhz
// Prescale = 1

// Frequenz bei 10 bit 15000000/(2*1023)= 7.331 kHz ; OVF alle 136 uS
// Frequenz bei  9 bit 15000000/(2* 511)=14.677 kHz ; OVF alle  68 uS




#define T1PERIODE 136  // Periodendauer zwischen Overflows in uS



/************************************* TIMER 1 OVERFLOW ISR **********/



ISR(TIMER1_OVF_vect) 

{
	static uint16_t takt_us=0;



		takt_us += T1PERIODE;


		if (takt_us >= 1000) 

		{
			takt_us -= 1000;
			takt_ms++;
			zyklus_ms++;



		}

		if (takt_ms >= 1000) 

		{
			takt_ms -= 1000;
			takt_sec++;

		}
}



/**************************************** ZYKLUS & WATCHDOG **********/



uint8_t Zyklus(uint8_t Zzeit)

{

	



	if(Zzeit == 0)              // Zyklustimer Reset / Init

	{

	// Timer 1 Overflow Interrupt freigeben, damit die Uhr tickt

	#ifdef TIMSK1
        // ATmega644
  		TIMSK1 |= (1<<TOIE1);
	#else
        // ATmega16
  		TIMSK  |= (1<<TOIE1);
	#endif

		zyklus_ms = 0;

		return(0);

	}



	sei();						// Interrupts freigeben



	led_ausgabe();				// Ausgänge aktualisieren



	uint8_t zms = zyklus_ms;    // aktuelle Zykluszeit merken

	while(zyklus_ms < Zzeit){};	// Zykluszeit abwarten



	sens_eingabe();				// Eingänge lesen



	// -------------------- WATCHDOG ---------------------------

	// es wird kein Reset/Neustart ausgelöst -> Endlosschleife	

	// LED blinken im Binär Muster der erfassten Zykluszeit

	if(zyklus_ms > Zzeit)  		// Zykluszeit überschritten ?

	{

		uint8_t zyt = 0;        // alternativ Zyklustimer (Blinken) 

		if (zms > 15) zms = 15; // Zykluszeit >= 15 -> alle LED ein

		while(1==1)				// Fehlerfalle Zykluszeit überschritten

		{

			_delay_ms(10);			// Klassische Verzögerung 

			if(zyt-- == 0) zyt = 70;// Blinktakt 700ms

			if(zyt > 50) {

 				LED_Pattern = zms;	// Ist-Zykluszeit Binär ausgeben

			} else {

				LED_Pattern = 0;	// LED aus für Blinklicht

			}

		led_ausgabe();          // LED Muster am Port ausgeben

		}

	}//--------------------------------------------------------

	else zyklus_ms = 0;			// Zykluszeit Timer Reset

	return(zms);				// Interessant bei Zykluszeit > 1:

								// Wie lang war der Zyklus tatsächlich

}
Und soweit bin ich bisher mit der Main() von s.frings gekommen: hier sind noch etliche Anpassungen nötig; _delay_ms(), while{} oder blockierende Funktionen sind eigentlich No Gos. Aber ich verspreche mir davon, dass mehrere "prozesse" quasi gleichzeitig bearbeitet werden können.
Code:
/*********************************************************************



			N I B O B E E  Projekt Alternative s.frings und Birger.T

			

			zum Selberbasteln und Ändern Ver.20100411



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



#define 	Zykluszeit 1 	// Hauptschleife Zykluszeit in ms

#define 	USE_SERIAL 0





#include "nibobee.h"
#include "zyklus.h"


uint16_t previousSpeed;

// Display battery status on the 4 led's
// LED0 = >4.1V
// LED1 = >4.3V
// LED2 = >4.5V
// LED3 = >4.7V
void battery_check() {
    set_AREF(REF_256);
    for (uint8_t i=0; i<10; i++) {
//        _delay_ms(50);
	    for (uint8_t t=0; t<50; t++) {
        	_delay_ms(1);

			led_ausgabe();

		}
        set_LED0(analog(VBAT)>(410*2));
        set_LED1(analog(VBAT)>(430*2));
        set_LED2(analog(VBAT)>(450*2));
        set_LED3(analog(VBAT)>(470*2));
//        _delay_ms(50);
	    for (uint8_t t=0; t<50; t++) {
        	_delay_ms(1);

			led_ausgabe();

		}
        set_LED0(0);
        set_LED1(0);
        set_LED2(0);
        set_LED3(0);
    }
    set_AREF(REF_VCC);
    _delay_ms(50);
}


// Wait for start signal (touch any sensor)
// While waiting, display debug information from sensors:
//   LED0: Left odometer sensor
//   LED3: Right odometer sensor
//   LED1: System timer
//   LED2: Center line sensor
void wait_for_start() {
    while (!(SENS_SW1 || SENS_SW2 || SENS_SW3 || SENS_SW4)) {
        // Display status of odometry sensors while waiting
        set_LED0(ODO_L);
        set_LED3(ODO_R);
        // Display system timer (flashes every second)
        set_LED1((system_time() % 1000) < 20);
        // Display line sensor
        set_LED2(analog(LINE_C)>600);

    	_delay_ms(1);

		led_ausgabe();
    }
    set_LED0(0);
    set_LED3(0);
    _delay_ms(10);
    while ((SENS_SW1 || SENS_SW2 || SENS_SW3 || SENS_SW4)) {}
    _delay_ms(400);
}


#define FORWARD 1
#define BACKWARD 0

volatile	uint8_t  running = 0;


// Drive forward or backward.
// Accellerate or decellerate softly to the maxSpeed.
// The distance is measured in 1/20 wheel rotations.
// LED0 or LED3 light if a which motor runs too fast.
uint8_t drive(uint8_t direction, uint16_t distance, uint16_t maxSpeed) {


static  uint16_t speed= 0;

static  uint32_t lastTime=0;



  if(!running){



    if (direction) {
        set_DIR_L(1);
        set_DIR_R(0);
    }
    else {
        set_DIR_L(0);
        set_DIR_R(1);
    }
    // Start with the previous speed
//    uint16_t speed=previousSpeed;
//    uint32_t lastTime=system_time();

    speed=previousSpeed;
    lastTime=system_time();

    reset_odometer();
	running = 1;

  }

   

//    while (odometer_left()<distance || odometer_right()<distance) {


	if(!(odometer_left()<distance || odometer_right()<distance)) running = 0; // Ziel erreicht

	else{

        int16_t diff=odometer_left()-odometer_right();
        // If left motor is too fast
        if (diff>0) {
            set_LED0(1);
            PWM_L=speed/2;
            PWM_R=speed;
        }
        // If right motor is too fast
        else if (diff<0) {
            set_LED3(1);
            PWM_R=speed/2;
            PWM_L=speed;
        }
        // Speed of both motors is equal
        else {
            set_LED0(0);
            set_LED3(0);
            PWM_L=speed;
            PWM_R=speed;
        }
        // If a millisecond has elapsed, increase or decrease the speed
        // a little until the maxSpeed has been reached.
        uint32_t currentTime=system_time();

		if (currentTime>lastTime) {
            if (speed<maxSpeed)
                speed++;
            else if (speed>maxSpeed)
                speed--;
            lastTime=currentTime;
        }
    } // vom while
    previousSpeed=speed;



	return(running);
}


// Stop driving.
void stop() {
    PWM_L=0;
    PWM_R=0;
    previousSpeed=0;

	running = 0;
}






// Main program
int main() 

{

	uint8_t tour = 0; // Merker für den Fahrtabschnitt

	uint16_t warten = 0;



//	nibobee_init();



    // Display battery status
    battery_check();
    // Wait for a start signal before start driving
    wait_for_start();

    // Drive forward and backward repeatedly, to demonstrate
    // that the drive() function keeps straight on properly.



	Zyklus(0);	//Zyklustimer Reset / Init

	while(1) 

	{
//		deactivate_output_bit(IO_LINE_EN); 	// Front IR Leds aus

		writeBit(PORTB,PB5,0);

		Zyklus(Zykluszeit);  				// Zykluszeit abwarten

// 		activate_output_bit(IO_LINE_EN); 	// Front IR LEDs blitzen im Zyklustakt für

										 	// Zeitmessung per IR Transistor und Oszi

		writeBit(PORTB,PB5,1);

		

		// Kollision (oder an die Fühler getippt) = Stop



		if(SENS_SW2_S || SENS_SW3_S) {

				tour = 100;

				stop();

		}

		

		// Neustart bei Sensor nach vorne tippen und loslassen

		if((tour == 100) && (SENS_SW1_F || SENS_SW4_F)) tour = 0;



        // Drive forward 2 meters, accellerating up to nearly maximum speed
      if((tour ==  0) && !drive(FORWARD,2000/6,900)) tour = 10;
        // Drive forward 30cm, decellerating down to the minimum speed
      if((tour == 10) && !drive(FORWARD,300/6,200)){
        stop();

		tour = 20;

		warten = 500;

		}
//	    _delay_ms(500);
      if((tour == 20) && !warten--) tour = 30;

        // Drive backward 2 meters, accellerating up to nearly maximum speed
      if((tour == 30) && !drive(BACKWARD,2000/6,900)) tour = 40;
        // Drive backward 30cm, decellerating down to the minimum speed
      if((tour == 40) && !drive(BACKWARD,300/6,200)) {
        stop();

		tour = 50;

		warten = 500;

		}
//        _delay_ms(500);
      if((tour == 50) && !warten--) tour = 0;



    }
    return 0;
}
Oder ich weiß nicht - liege ich mit meiner Vorstellung einer Controllerprogrammierung total daneben? Dann geb' ich's auf und bastel mir 'ne Logo oder zwei auf Räder...

Eigentlich wollte ich noch ein Foto machen: Meine Erfahrung LiPos halten so lange, bis man sie dann mal braucht.. bis zum WE.