Microkontrollerprogrammierung

Haptical Forklifter: Mikrocontrollerprogrammierung

Um die Microkontrollerprogrammierung zu erlernen, wurden wir von Marcus Borst (Albotronic) unterstützt.

Wir erhielten ein Evaluationsboard mit verschiedenen Potentiometern, LEDs, Tastern und zwei 7-Segmentanzeigen. Ausserdem kann man an das Evaluationsboard Motortreiber und ein UART Modul zur Kommnunikation mit dem Computer oder anderen Microkontrollern anschliessen. Programmiert wird der Chip über ein paralleles Kabel und z.B. Ponyprog.

 

Kompilieren der Codebeispiele

Um die entstandenen c Programme zu kompilieren und auf den Microkontroller zu bringen benutzen wir verschiedene Hilfsprogramme.

Kompilieren:

Eine gute Anleitung zur Installation des gcc Compilers für atmel devices
findet sich unter http://home.overta.ru/users/denisc/. Für debian Nutzer finden sich bereits fertige avr-gcc Packete im unstable Zweig. 

Zum Übertragen des Programmes auf den Atmel benutzen wir ein paralleles
Programmierkabel, welches mittels ponyprog betrieben wird. http://www.lancos.com/prog.html avrprog, ein anderers Programmiertool gibts es auch als fertiges .deb Packet nutzen. 

In unserem Makefile gibt es dazu einen speziellen Build-Befehl (make prog),
der dann nach erfolgtem build das Programm überträgt.

Joystickpotentiometergesteuerte Lichtpunktpositionsveränderung

Dieser Versuchsaufbau diente zum Erkunden der Analog-Digital-Wandler Einheit des ATMega32 Microkontrollers. Wir verwendeten das Evaluationsboard von Marcus Borst, an dem ein Potentiometerjoystick und eine LED Matrix angeschlossen wurde.

Durch Auslenken des Potentiometerjoystick kann dann die Position des Lichtpunktes auf der LED Matrix verändert werden.

Die AD Einheit des Atmel kann 8 Kanäle wandeln mit bis zu 10bit Genauigkeit wandeln. Allerdings erfolgt die Wandlung im Multiplexbetrieb, d.h. es wird pro Zeiteinheit stehts nur 1 Kanal gewandelt, nach der Wandlung wird dann der nächste Kanal gewandelt. Je weniger Kanäle verwendet werden, desto höher ist damit auch die Updaterate. Laut Datenblatt dauert eine Wandlung 65-260µs. Wir haben uns bei diesem Beispiel auf eine Auflösung von 8bit beschränkt. Zunächst aus Geschwindigkeitsgründen, und da die LED Matrix ohnhin nur 16x16 LEDs breit war.

Die Verwendung der AD Einheit erfolgt so:

//ADC enabled
ADCSRA = ADCSRA | 1<<ADEN;
//ADC auto-Triggering enabled
ADCSRA = ADCSRA | 1<<ADATE;
//ADC Interrupt enabled
ADCSRA = ADCSRA | 1<<ADIE;
//Prescalerauf ne höhere Samplingrate (Hz) setzen
//ADCSRA = ADCSRA | 1<<ADPS0;
//right justified setzen, damit es ausreicht, das ADCH bit auszulesen 8bit Genauigkeit
ADMUX = ADMUX | 1<<ADLAR;
//mux register auf ADC0 setzeen
ADMUX = ADMUX | 0<<MUX0;
//ADC starten
ADCSRA = ADCSRA | 1<<ADSC;
/* enable interrupts */
sei();

In der Interruptroutine wird dann jeweils der aktuelle Wert an einem Pin gespeichert, und auf den nächsten Pin weitergeschaltet. Die Variablen, welche die Werte zugewiesen bekommen müssen unbedingt vom Type volatile uint8_t sein, damit die Variable in der Interruptroutine beschrieben werden kann.

Hier nun die Interruptroutine, welche automatisch nach jeder AD-Konvertierung aufgerufen wird:

SIGNAL(SIG_ADC){

uint8_t i;
if (ADMUX == 32)

{

ADCValue=ADCH;
ADCValue=(ADCValue-17)*16/(241-17);
PORTC=ADCValue;
ADMUX = 33;
//auf PORTC ausgeben
PORTC = ADCValue1+ADCValue;
while(i++<0xff);
return;

}

if (ADMUX == 33)
{

ADCValue1=ADCH;
ADCValue1=(ADCValue1-17)*16/(207-35);
ADCValue1= 16-ADCValue1;
ADCValue1 = ADCValue1 << 4;
ADMUX = 32;
//auf PORTC ausgeben
PORTC = ADCValue1+ADCValue;
while(i++<0xff);

}

}

Die beiden Variablen

volatile uint8_t ADCValue;
volatile uint8_t ADCValue1;

werden normalisiert und auf Werte zwischen 0 und 15 gemappt. Die LED Matrix wird dann mit den 8bit von PortC gesteuert. Die unteren 4 bit (16 Werte) dienen der Spaltenzuordnung, und die oberen 4bit der Zeilenzuordnung. Die ICs auf der LED Matrix decodieren dann das Signal und steuern die entsprechenden LEDs an.

Quelle: lichtpunkt_joystick.c

Automatische Rückstellung eines motorisierten Drehpotentiometers

Bei diesem Aufbau verwendeten wir ebenfalls das Evaluationsboard von Marcus Borst. Allerdings in einer erweiterten Variante; mit einer Motortreiberplatine.

Damit können DC Motoren gesteuert werden. Die Anwendung ist denkbar einfach über 2 Pins des Atmels geregelt. Ein Pin wird zur Richtungssteuerung, ein weiterer zum Ein/Ausschalten des angechlossenen Motors verwendet.
Der Potentiometer des Motors wurde dann an einen AD Kanal der Atmels angeschlossen, der Motor an den Motortreiber. 

Die Anwendung ist sehr einfach: Es wird stehts der Wert der AD Wandlung mit einem Sollwert ( minus Toleranz durch Wandlungsfehler) verglichen. Der Sollwert in diesem Falle ist die Mittelstellung des Potis. Falls der Ist-Wert die Grenzen 111 und 119 der AD Wandlung unter- bzw. überschreitet wird der Motor entsprechend aktiviert und fährt in diese Grenzen zurück.
 

Das Hauptprogramm auf dem Atmel sieht folgendermassen aus:

if (ADCValue<110)

{

sbi(PORTC,4); //Motor an
sbi(PORTD,4); //nach rechts drehen

}

if (ADCValue>111 & ADCValue < 119)

cbi(PORTC,4); //Motor aus

if (ADCValue>120)

{

sbi(PORTC,4); //Motor an
cbi(PORTD,4); //nach links drehen

}
 

Quelle: motor_rueckstellen.c