This is an old revision of the document!
Necessary knowledge : [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, dessen Widerstandswerte mechanisch veränderbar sind. Es hat mindestens drei Anschlüsse und wird vorwiegend als stetig einstellbarer Spannungsteiler eingesetzt.
Ein typisches Potentiometer besteht aus einem Widerstand mit einer leitenden Oberfläche und einem Schiebekontakt (slider). Je näher der Slider zum Rand des Widerstands ist, des do geringer ist der Widerstand zwischen Slider und Ecke des Widerstands. Ein Material mit hohem Widerstand oder einer Spule aus Widerstandsdraht kann als Widerstand fungieren. Einige Potentiometer haben lineare oder logarithmische Verhältnisse zwischen Widerstand und Sliderposition. Potentiometer sind normalerweise einfache Drehpotentiometer (siehe Bild), aber es gibt auch Schiebepotentiometer. Ein spezieller Typ von Potentiometer sind digitale Potentiometer, wo die Regulation des Widerstands intern über Signale geschieht.
Am HomeLab ist ein 4,7kΩ Drehpotentiometer. Das Potentiometer ist zwischen der Erde und dem +5V Potential angeschlossen, und der Slider ist am Kanal 3 des analog-digital Konverters angeschlossen. Mit dieser Verbindung kann der Spannungsoutput des Potentiometers zwischen 0-5V reguliert werden. Der digitale Wert der Potentiometeroutputspannung kann gemessen werden wenn die Vergleichsspannung vom AVR digital-analog Konverters vom AVCC Pin genommen wird. die Folgende Funktion für den ACR ADC sind der HomeLab Library.
// // 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 am Anfang des Programms stehen, sie sorgt dafür, dass der ADC funktioniert. Die Vergleichsspannung muss entweder vom AREF oder AVCC Pin kommen, oder die eingestellte interne Spannung von 2,56V muss ausgewählt werden. Dazu muss der Taktzyklus des Konverters mit einem Prescaler gesetzt werden (Faktor des Frequenzteilers), welcher den Controller Taktzyklus teilt. Die Konversion ist mit höheren Taktzyklen schneller, jedoch kann die Genauigkeit drunter leiden. Die Funktion adc_get_value ist zum Messen, man kann den Kanal aussuchen und sie gibt 10 Bit Ergebnisse als 16 Bit Integers aus. Die Funktion zum Messen wartet bis die Konversion beendet ist und gibt das Ergebnis erst aus, wenn jede Messung beendet ist.
In den zuvor erklärten Beispielprogrammen werden die ADC und die 7-Segment Nummern Indikator Library genutzt. Der 10 Bit Wert des ADC wird mit 10 multipliziert und durch 1024 dividiert um einen Wert zwischen 0-9 zu bekommen. Der Wert 10 kann nicht erreicht werden, weil in der C-Sprache nur Integer-werte berechnet werden und keine gerundeten Ergebnisse. Eine Funktion um die Ergebnisse des ACSs zu mitteln wird benutzt um das Ergebnis genauer zu machen,. Dadurch abgeleitet gibt das Programm einen Wert von 0-9 aus, welcher mit der Position des Potentiometers entspricht.
// // Example program of potentiometer on the Sensor module // The position of the potentiometer is displayed on the 7-segment indicator // #include <homelab/adc.h> #include <homelab/module/segment_display.h> // // Selecting the channel // // 1 = photoresistor // 2 = thermistor // 3 = potentiometer // #define ADC_CHANNEL 3 // // Main program // int main(void) { int value; // Adjusting 7-segment indicator segment_display_init(); // Adjusting ADC adc_init(ADC_REF_AVCC, ADC_PRESCALE_8); // Endless loop while (true) { // Reading 4 times rounded values of the channel value = adc_get_average_value(ADC_CHANNEL, 4); // Displaying the hundreds of the indicated value segment_display_write(value * 10 / 1024); } }