doxygen ist schon ein Begriff, oder?
Ja, sicher.
Was ist ein "Sendung mit der Maus"-Kommentar?
Zum Beispiel so etwas (RP6):
Code:
	// ---------------------------------------
	// LEDs:

	setLEDs(0b111111); // Turn all LEDs on!

	// 0b111111 is a binary value and is the same as
	// 63 in the decimal system.
	// For this routine, the binary value is better to read, because each bit
	// represents one of the LEDs.
	// e.g. this:
	// setLEDs(0b000001); would set only LED1
	// setLEDs(0b000010); LED2
	// setLEDs(0b000100); LED3
	// setLEDs(0b101001); LED6, LED4, LED1 - and so on!

	mSleep(1000); // delay 1000ms = 1s
	setLEDs(0b000000); // All LEDs off!
	mSleep(500); // delay 500ms = 0.5s


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

	uint8_t runningLight = 1; // This defines the local unsigned 8 bit variable "runningLight".
						      // It can be accessed everywhere _below_ in this function.
						      // And ONLY within this function!

	// ---------------------------------------
	// Main loop - the program will loop here forever!
	// In this program, it only runs a small LED chaselight.
	while(true)
	{
		// Here we do a small LED test:
		// ---------------------------------------
		setLEDs(runningLight); 	// Set status LEDs to the value of the variable
							// testLEDs.
							// In the first loop iteration it has the value 1,
							// and thus the StatusLED1 will be switched on.

		runningLight <<= 1; // shift the bits of "runningLight" one step to the left.
						// As there is only one bit set in this variable,
						// only one LED is on at the same time.
						// This results is a moving light dot like this:
						// 1: 0b000001
						// 2: 0b000010
						// 3: 0b000100
						// 4: 0b001000
						// 5: 0b010000
						// 6: 0b100000 
						//
						// In decimal format that would be the numbers:
						// 1, 2, 4, 8, 16, 32

		// When we have reached a value > 32 (32 means Status LED6 is on), 
		// we need to reset the value of runningLight to 1 to start again
		// from the beginning...
		// Instead of "32" we could also write "0b100000".
		if(runningLight > 32)
			runningLight = 1; 	// reset runningLight to 1 (StatusLED1) 

		// If we want to see the running Light, we need to
		// add a delay here - otherwise our human eyes would not see
		// the moving light dot: 
		mSleep(100); // delay 100ms = 0.1s 
		
		// ---------------------------------------

	}
	// End of main loop
	// ---------------------------------------

	// ---------------------------------------
	// The Program will NEVER get here!
	// (at least if you don't perform a "break" in the main loop, which
	// you should not do usually!)

	return 0; 
}
Ich finde dies für Programmier-Anfänger ideal erklärt. Da hat sich beim RP6 jemand richtig viel Mühe mit Liebe zu Einsteigern gemacht. Für diejenigen, die dies eher stört, gibt es die gleichen Programme unkommentiert. Das ist Service.

MOTCO_I2C_ID: ID ist ok als Akü für Identifier, I2C sollte einem auch was sagen, aber MOTCO ist doch wieder eine strange Akü. Also was spricht denn da?
Nibo hat neben dem ATmega128 noch zwei ATtiny 44. MOTCO bedeutet Motor-Controller, IRCO bedeutet IR-Controller. Ich denke, das ist als Nibo-Slang für mich akzeptabel.

Wichtig ist bei einer guten Dokumentation meiner Meinung nach auch, die Absicht (das "Warum") rüberzubringen.
Da stimme ich Dir zu 100% zu! Das nenne ich "Sendung mit der Maus"-Kommentar. Das fehlt in vielen Fällen, weil Entwickler irgendwann "betriebsblind" werden. Diesbezüglich finde ich Kommentare wie oben beim RP6 super.

Wieso fehlt die 'Kapselung' bei meinem Beispiel aus der RP6-LIB?
Kapselung ist für mich ein Begriff aus der Objekt-Orientierten Programmierung (OOP). Siehe z.B.: http://www.henkessoft.de/C++/C++/kapselung.htm
Kapselung:
Allgemein eine Technik zur Schnittstellendefinition.
Durch Kapselung werden Realisierungsdetails hinter einer definierten Schnittstelle verborgen. Die Schnittstelle kann dadurch oft auch erhalten bleiben, wenn sich Interna ändern müssen.
Bei dem Beispiel werden Begriffe verwendet, die "Prozessor-nah" sind, wie PORTB o.ä. Wenn ich programmiere, will ich z.B. die rote, grüne oder weiße LED oder die Display-Beleuchtung einschalten oder den linken Motor auf eine bestimmte Geschwindigkeit einstellen etc. Hierzu verwendet man möglichst sprechende Funktions-/Makronamen. Hier ein typisches Beispiel vom Nibo, bei dem dies IMHO gut gelungen ist:
Code:
    leds_set_displaylight(800);

    gfx_move(10,10);
    gfx_print_text("Nibo sagt:", 0);

    gfx_move(10,30);
    gfx_print_text("Hallo Welt!", 0);
 
    int i,j;
    for(i=0;i<10;++i)
    {   
        for(j=0;j<6;++j)
        {
            leds_set_status(LEDS_RED,j);
            delay(500);
        }

        leds_set_headlights(256);

        for(j=0;j<6;++j)
        {
            leds_set_status(LEDS_ORANGE,j);
            delay(500);
        }

        leds_set_headlights(512);

        for(j=0;j<6;++j)
        {
            leds_set_status(LEDS_GREEN,j);
            delay(500);
        }

        leds_set_headlights(1024);
    }
Da findest Du keine einzige Prozessorpinbezeichnung! Das meine ich mit Kapselung, und bei High-Level-Funktionen wie gfx_move oder gfx_print möchte ich nicht sehen, wie das läuft, sondern es nur anwenden. Die nächsthöhere Ebene ist dann z.B.:
Code:
void textout(int x, int y, char* str, int ft)
{
    gfx_move(x,y);
    gfx_print_text(str,ft);
}

   leds_set_displaylight(1000);

    float Ubatt = SupplyVoltage();
    char text[6];
    float2string(Ubatt,2,text);     

    textout(4,10,"Versorgungsspannung:",0);
    textout(4,24,text,0);
    textout(60,24,"Volt",0);
Da kann man doch schon fast mitlesen, oder?

Beim ASURO gibt es solche Funktionen inzwischen auch wie Go(...), Turn(...), Chirp(...). Man darf nur nicht in den Rumpf schauen, denn da fällt man bis auf die unterste Ebene durch, weil die Schichtung fehlt.

Für mich ist die Funktionalität schon dann gekapselt, wenn ein sinnvoller, notwendiger Softwareblock einen Funktionsnamen (plus Doku) bekommen hat.
Aus meiner Sicht fast richtig. Wenn ich nämlich bei einer High-Level in den Funktionsrumpf schaue möchte ich nichts von PORTB oder DDRB lesen, sondern erwarte ein bis zwei Schichtungen mehr.

Also ich fasse mal meine - zugegebenermaßen total persönliche - Sicht zusammen:
Was erwarte ich?
1) Gute "Schichtung" (iodefs.h / low level / mid level / high level)
2) Kapselung (z.B. finde ich es suboptimal, dass beim ASURO bei einem Anwender-Programm in asuro.c programmiert wird, in einer Datei, in der ich Details bis zum Prozessor finde)
3) "Sendung mit der Maus"-Kommentare (Hintergründe und Absicht erklären). Mit modernen Systemen kann man solche Kommentare ein-/ausblenden.

Keiner der von mir angesprochenen Roboter-Bibliotheken erfüllt diese Forderungen komplett.
Punkt 1 und 2 ist IMHO am besten beim Nibo erfüllt. Dafür ist Punkt 3 bei ihm noch völlig unterentwickelt.
RP6 ist bezüglich Punkt 3 an manchen Stellen wirklich vorbildhaft.
ASURO schneidet selbst bei Punkt 3 nicht gut ab, was er als Einsteigermodell sollte! (er hat eine so gute Bauanleitung)
Schaut euch doch mal die Funktion Init() in asuro.c an. Das sind doch alles Pseudo-Erklärungen, die ich ohne Datenblatt des ATmega8 nicht verstehen kann.
Code:
   /* Timer2, zum Betrieb mit der seriellen Schnittstelle, fuer die IR-Kommunikation auf 36 kHz eingestellt. */
   TCCR2  = (1 << WGM20) | (1 << WGM21) | (1 << COM20) | (1 << COM21) | (1 << CS20);
   OCR2   = 0x91;           // duty cycle fuer 36kHz
   TIMSK |= (1 << TOIE2);   // 36kHz counter
@Sternthaler: gerade hier hatten wir doch eine sehr fruchtbare Diskussion, warum hier 36 kHz resultieren. Du warst der Erste, der mir dies schlüssig erklären konnte (dafür wirklich vielen Dank!). Das müsste aber alles hier im Programm als Kommentar drinnen stehen, aber vielleicht nicht alles direkt in der ersten Ebene, das gehört weiter unten hin, in die dritte oder vierte Ebene.

Ich hoffe, dass meine Erklärungen dazu beigetragen haben, meine zugegebenermaßen hohen Erwartungen zu beleuchten. Ich bitte ernsthaft darum, dies als konstruktive Kritik aufzufassen. Kommentare kann man nachrüsten, bei Schichtungen/Kapselungen ist dies deutlich schwieriger.

Wer sich selbst ein Bild machen möchte:
Quellen für Sourcecode:
1) Nibo: http://downloads.sourceforge.net/nib...5&big_mirror=0
2) RP6: http://www.arexx.com/rp6/downloads/R...s_20070731.zip
3) ASURO: http://downloads.sourceforge.net/asu...9&big_mirror=0

PS: c't-Bot habe ich bei der Betrachtung bewusst ausgelassen, da diese Bibliothek nur wenigen bekannt ist und dieser Roboter hier kaum noch besprochen wird.