Notwendiges Wissen: [HW] Sensors Module, [HW] User Interface Module, [ELC] Voltage Divider, [AVR] Analog-to-digital Converter, [LIB] Analog to Digital Converter, [LIB] 7-segment LED Display
Ein Potentiometer ist ein elektronisches Widerstandsbauelement mit drei Anschlüssen. Zwischen den beiden Seitenkontakten ist der Widerstand fix, zwischen Seiten- und Mittelkontakt ist er variabel. Im Grunde ist ein Potentiometer ein Spannungsteiler, dessen Widerstand zwischen den Seiten- und Mittelkontakten hergestellt wird.
Ein typisches Potentiometer besteht aus einem Widerstand mit einer leitenden Oberfläche und einem Schiebekontakt (slider). Je näher der Schiebekontakt am Rand des Widerstandes angebracht ist, desto geringer ist der Widerstand zwischen Slider und Ecke des Widerstands und umgekehrt. Ein Material mit hohem Widerstand oder einer Spule aus Widerstandsdraht kann als Widerstand fungieren. Bei einigen Potentiometern sind die Beziehungen zwischen Widerstand und Sliderposition linear oder logarithmisch. Potentiometer sind normalerweise einfache Drehpotentiometer (siehe Bild), es gibt aber auch Schiebepotentiometer. Ein spezieller Typ von Potentiometer sind digitale Potentiometer, bei denen die Regulation des Widerstands intern über Signale geschieht.
Am HomeLab Modul befindet sich ein 4,7 kΩ Drehpotentiometer. Das Potentiometer ist mit der Masse und dem +5 V Potential angeschlossen, und der Schiebekontakt ist am Kanal 3 des analog-digital Konverters angeschlossen. So kann der Spannungsoutput des Potentiometers zwischen 0 und 5 V reguliert werden. Der digitale Wert der Potentiometeroutputspannung kann gemessen werden indem die Vergleichsspannung vom AVR digital-analog Konverter vom AVCC Pin genommen wird. die Folgende Funktionen für den ACR ADC sind in der HomeLab Bibliothek enthalten.
// // Data types for adjustment // typedef enum { ADC_REF_AREF = 0x00, ADC_REF_AVCC = 0x01, ADC_REF_2V56 = 0x03 } adc_reference; typedef enum { ADC_PRESCALE_2 = 0x01, ADC_PRESCALE_4 = 0x02, ADC_PRESCALE_8 = 0x03, ADC_PRESCALE_16 = 0x04, ADC_PRESCALE_32 = 0x05, ADC_PRESCALE_64 = 0x06, ADC_PRESCALE_128 = 0x07 } adc_prescale; // // Starting the ADC // void adc_init(adc_reference reference, adc_prescale prescale) { // Allowing ADC to operate, selecting the frequency divider ADCSRA = bit_mask(ADEN) | (prescale & 0x07); // Selecting comparison voltage ADMUX = (reference & 0x03) << REFS0; } // // Converting the values of selected channel // unsigned short adc_get_value(unsigned char channel) { // Setting the channel ADMUX = (ADMUX & 0xF0) | (channel & 0x0F); // Starting the conversion bit_set(ADCSRA, ADSC); // Waiting the end of the conversion while (bit_is_set(ADCSRA, ADSC)) { asm volatile ("nop"); } // Returning the results return ADCW; }
Die Funktion adc_init muss zu Beginn des Programms ausgeführt werden. Sie sorgt dafür, dass der ADC funktioniert. Die Vergleichsspannung muss entweder vom AREF oder AVCC Pin kommen, oder es muss die eingestellte interne Spannung von 2,56 V ausgewählt werden. Dazu muss der Taktzyklus des Konverters mit einem Vorzähler gesetzt werden (Faktor des Frequenzteilers), welcher den Taktzyklus des Controllers teilt. Die Umsetzung ist schneller, wenn höhere Taktzyklen verwendet werden, jedoch kann die Genauigkeit drunter leiden. Die Funktion adc_get_value dient zur Messung. Es kann der Kanal gewählt werden und sie gibt 10-Bit Ergebnisse als ganze 16-Bit Zahlen aus. Die Funktion zur Messung wartet bis die Konversion beendet ist und gibt das Ergebnis erst dann aus.
In den zuvor erklärten Beispielprogrammen werden die Bibliotheken des ADC und des 7-Segment-Zifferanzeige genutzt. Der 10-Bit Wert des ADC wird mit 10 multipliziert und durch 1024 dividiert um einen Wert zwischen 0 und 9 zu erhalten. Der Wert 10 kann nicht erreicht werden, weil in C nur ganzzahligewerte berechnet werden und keine gerundeten Ergebnisse. Um die Genauigkeit des Ergebnisses zu erhöhen, wird eine Funktion zur Berechnung des Durchschnitts der Ergebnisse des ACSs genutzt. Daraus abgeleitet gibt das Programm auf der Anzeige einen Wert von 0 bis 9 aus, welcher der Position des Potentiometers entspricht.
// // Beispielprogramm für das Potentiometer des Sensormoduls // Die Position des Potentiometers wird auf der 7-Segmentanzeige dargestellt // #include <homelab/adc.h> #include <homelab/module/segment_display.h> // // Auswahl des Kanals // // 1 = Photoresistor // 2 = Thermistor // 3 = Potentiometer // #define ADC_CHANNEL 3 // // Hauptprogramm // int main(void) { int value; // Anpassung der 7-Segmentanzeige segment_display_init(); // Anpassung des ADC adc_init(ADC_REF_AVCC, ADC_PRESCALE_8); // Endlosschleife while (true) { // Liest viermal gerundete Werte aus dem Kanal value = adc_get_average_value(ADC_CHANNEL, 4); // Zeigt Hunderter des angezeigten Wertes an segment_display_write(value * 10 / 1024); } }