µC Microcontroller Einstiegsseite

Ich gehe nicht sehr ins Detail, die erste Inbetriebnahme steht im Vordergrund, wenn es erst mal läuft, ist der weitere Ausbau recht einfach.
(Es ist auch die Seite, die ich mir gewünscht hatte, als ich anfing ;-)
Ich beschreibe wie es bei mir funktioniert, daher kein Gewähr und keine Haftung.

Inhalt:
Welcher nehmen ?
Test Board
ISP (In System Programming)
Quellcode Beispiel
LCD Ausgabe
Servo ansteuern


Zuerst die Grundlagenfrage, ob es ein programmierbarer Prozessor sein muss und nicht programmierbare Logikbausteine oder sogar nur festverdrahtete Logik auch geht ?

Wenn es nun ein Microcontroller sein muss, dann stellt sich die grosse Frage: Welcher ?

So vielfältig die Anwendungsmöglichkeiten, so viele Typen gibt es und diese in fast allen Variationen !

Aber der Einsatzzweck filtert vieles heraus:

Ein Zitat zu den eingebauten Funktionen:
"Nimm nie einen Menschen, wenn du auch eine Maschine nehmen kannst."
Agent Smith aus dem Film "Matrix"

= Man sollte Funktionen die "in Silizium gegossen" sind, bevorzugen, anstelle es selber zu programmieren (versuchen).
Ein Hardware-UART (Universal Asynchronous Receiver and Transmitter) ist einfach zu benutzen, schnell, stabil und getestet. Dies nun mit Timern und Interrupts selber mit Programmcode nachzubilden ist schwierig und aufwendig.
Und es zieht sehr viel Zeit vom eigentlichen Projekt ab!


Ich suchte für einfache Steuer+Regelaufgaben ein µC mit serieller Schnittstelle.

Er sollte sein:
Meine Wahl fiel auf den Atmel ATmega64L !
Weil:
Ich habe die benötigte Software, die bei mir unter Linux SuSE 9.0 läuft, hier auf meinem Mirror abgelegt, es gibt viele Varianten davon!
lokal:Homepage:
avr-binutils-2.14-1.i386.rpm
avr-gcc-3.3.1-1.i386.rpm
avr-libc-1.0-1.i386.rpm
http://www.nongnu.org/avr-libc/
uisp-20030618-1.i386.rpm
http://savannah.nongnu.org/projects/uisp/
(Einzig was mich erstaunt ist "nongnu" mit GNU-Software, was solls)


Test Board
Auf dem Bord werden viele Komponenten zu Test- und Übungszwecken verbaut (Schalter, LED's, usw).
Nun wird gebaut, aber da dies die ersten Versuche sind, lässt es sich kaum vermeiden, dass etwas umgebaut werden muss.
So musste ich Kabel umverlegen und Bauteile hinzufügen.
Es sieht schrecklich aus mit den Heisskleber, aber der isoliert die Kontakte und hält die Kabel fest. Markant ist der grosse, blaue Elko, der den kurzzeitig hohen Strombedarf des Servos ausgleichen muss (er könnte kleiner sein, aber manchmal muss man nehmen was gerade da ist, ausserdem gefällt mir der "Wasserturm" irgendwie).

Mit den neuen Erkenntnissen wird dann die nächste Version besser aussehen !

Nun zu den einzelnen Komponenten:

ISP (In System Programming)
Das µC-Board kann über ein 6poliges Kabel an der Drucker Schnittstelle (parallel / LPT / lp) gelöscht und neu programmiert werden:

Schema:

  • 1x Sub-D Stecker 25pol
  • 1x OCTAL 3 STATE DRIVER, HCT, 74HCT244, SO-20
  • 1x Winderstand 100k
  • 2x Kondensator 100nF (nahe IC und nahe Kabel)
  • 1x Buchsenleiste 6pol
  • und Kabel (möglichst kurz, dieses ist 1,2m)

Das zu ladende C Programm entsprechend der Anleitung "avr-libc-user-manual.pdf" oder der zahlreichen Beispiele erstellen.

Zum compilieren von z.B. blinkled.c:
avr-gcc -g -mmcu=atmega64 -c blinkled.c && avr-gcc -g -mmcu=atmega64 -o blinkled.elf blinkled.o && avr-objcopy -j .text -j .data -O ihex blinkled.elf blinkled.hex

Damit die PC-Schnittstelle initialisiert wird, das Programm einmal leer laufen lassen (mit Board angesteckt, aber ohne Stromversorgung) !
Das gibt zwar eine Fehlermeldung, aber nun ist alles initialisiert.

Zum Löschen:
uisp -dlpt=/dev/parport0 --erase -dprog=stk200

Zum Beschreiben:
uisp -dlpt=/dev/parport0 --upload if=blinkled.hex -dprog=stk200 -v=3 --hash=32


Achtung da sind noch zwei böse Fallen:
1) Ab Werk ist der 64er reduziert auf einen Atmega103, dieses Einstellungsbit muss pro Chip nur ein einziges mal beim ISP gelöst werden:
uisp -dlpt=/dev/parport0 --wr_fuse_e=0xff --wr_fuse_l=0xef --wr_fuse_h=0xd9 --upload if=blinkled.hex -dprog=stk200 -v=3 --hash=32

Die Fuses müssen nur 1x pro Chip während dem Programmieren gesetzt werden, sie werden nicht gelöscht !


2) Die Pin-Bezeichnungen MOSI + MISO gelten NUR im JTAG-Modus, aber nicht zum Programmieren !
Die Verdrahtung für das obige Kabel zum Programmieren muss heissen:
KabelµC
Pin 1 - VccVcc
Pin 2 - SCKPin 11 - PB1 (SCK)
Pin 3 - ResetPin 20 - Reset
Pin 4 - MOSIPin 2 - PE0 (RXD/PDI)
Pin 5 - MISOPin 3 - PE1 (TXD/PD0)
Pin 6 - GNDGND
Erschwerend kommt hinzu, dass diese Ports schon mit der seriellen Schnittstelle 0 belegt ist, also während dem Programmieren nichts anschliessen !

Man kann den Programmiermodus auch erzwingen, indem man Pin 1 (/PEN) vor und während dem Power-on auf Masse zieht.


Quellcode Beispiel
blinkled.c:
/* Testprogramm, welches die LED an Port A Pin 0 im Halbsekundentakt blinken laesst. */
#include <avr/io.h>
#ifndef F_CPU
 #define F_CPU 8000000UL     /* Quarz mit 8 Mhz */
#endif
#include <util/delay.h>
 
int main( void )
{
    DDRA = ( 1 << PA0 );        // PortA Pin 0 als Ausgang setzen
 
    while( 1 ){                 // Endlosschleife
	PORTA &= ~(1 << PA0);	// PortA Pin 0 ausschalten
        _delay_ms(500);         // Eine halbe Sekunde warten

	PORTA |= (1<< PA0);	// PortA Pin 0 einschalten
        _delay_ms(500);         // Eine halbe Sekunde warten
    }                           // Ende while-Schleife
    return 0;
}


Noch ein kleiner Stolperstein: Sobald Interrupts verwendet werden, sollten alle 35 Interrupts definiert sein, wenn auch ohne Inhalt, z.B:
ISR(TIMER0_OVF_vect) { }   //Timer/Counter0 Overflow

LCD Ausgabe
Bei den Zeichen Displays, also nur Buchstaben und Zahlen, aber keine Grafik, ist der HD44780 Controller zum Quasi-Standart geworden.
Viele Controller, z.B. KS0066 sind kompatibel dazu.

Nun der Anschluss und Ansteuerung des 2x16 Zeichen LCD's:
Ich habe den 4-bit Modus gewählt, um I/O-Ports zu sparen.

Anschlussplan:      Wahrheitstabelle:
Im Betrieb ist mir aufgefallen, dass ich nie etwas vom LCD lesen musste (auch kein Busy-Bit da die Pausen lang genug sind), so habe ich den R/W-Port auf GND gelegt und machte so einen weiteren IO-Port frei.

Servo ansteuern
Ein Servo wird mittels PWM (Puls-Weiten-Modulation) angesteuert.
Das heisst, die Pulsdauer ist entscheidend.
Der Nachteil dabei ist, dass zur Kontrolle des Programms ein Oszilloskop erforderlich ist (es sei denn es läuft auf Anhieb).

Beispiel Futaba/Graupner:
Jeder Puls hat üblicherweise* eine Mindestlänge von 1ms (quasi das Startbit) und bedeutet Vollausschlag rechts (Uhrzeigersinn).
Maximale Pulslänge ist 2ms und bedeutet Vollausschlag links (Gegenuhrzeigersinn).
Die zweite ms wird in 1000 Schritten ausgewertet, wobei der Servo schon bei einer Abweichung von 3µs nachregelt !

Dieser Puls muss alle 15 bis 23 ms aufgefrischt werden, ansonsten regelt der Servo nicht mehr nach und lässt sich mit wenig Kraft wegdrücken !
Der graue Bereich stellt den Steuerbereich dar.

*) Servos steuern üblicherweise nur 90°, was für Ruder bei Flugmodellen Sinn macht. Es gehen aber bis zu 180° und mehr, je nach Typ, also ausprobieren lohnt sich.

So steuere ich meinen Servo mit folgender Pulsdauer an:
 500ms = "Startzeit" = Vollausschlag links -90°
1000ms = -45°
1500ms = Mittelstellung 0°
2000ms = +45°
2500ms = Vollausschlag rechts +90°

Bei wenigen Servos kann dies mit den PWM-Generatoren gemacht werden, man berechnet die Timer nach der Taktfrequenz, schreibt die erhaltenen Werte in die Steuerregister und aktiviert den Timer und die Interrupts.

Sind alle PWM-Generatoren aufgebraucht, kann man mit Timern und einem Port die Servos selbst ansteuern.


Üblicherweise arbeiten Servos mit 4,8 - 6 V.
Aber Vorsicht: Ein Servo fährt nicht langsam, sondern immer "volle Pulle" auch wenn er sich nur sehr wenig bewegen muss.
Das wäre nicht weiter schlimm, würde dazu nicht sehr kurz relativ viel Strom fliessen, wodurch die Spannung einbrechen kann und der µC abstürzt und neu startet !
(Deswegen habe ich den grossen Elko hinzufügen müssen)

Die Hersteller haben teils sehr unterschiedliche Anschüsse:

(Die Stecker von Conrad, Graupner und Futaba passen auf handelsübliche Stiftleisten mit 2,54 mm Raster)
Wobei + = Vcc   ;   - = GND   und natürlich den Pin für die Modulation.