This shows you the differences between two versions of the page.
pm:lab:lab4-2021 [2021/04/05 09:24] jan.vaduva |
pm:lab:lab4-2021 [2021/04/05 12:15] (current) alexandru.predescu [4. Exercitii] |
||
---|---|---|---|
Line 2: | Line 2: | ||
Acest laborator are ca scop familiarizarea voastră cu lucrul cu convertorul analog-digital prezent în microcontroller-ul Atmega328p. | Acest laborator are ca scop familiarizarea voastră cu lucrul cu convertorul analog-digital prezent în microcontroller-ul Atmega328p. | ||
- | ===== Măsurarea semnalelor analogice ===== | + | ===== 1. Măsurarea semnalelor analogice ===== |
Pentru a putea măsura semnalele analogice într-un sistem de calcul digital, acestea trebuie convertite în valori numerice discrete. Un convertor analog – digital (ADC) este un circuit electronic care convertește o tensiune analogică de la intrare într-o valoare digitală. | Pentru a putea măsura semnalele analogice într-un sistem de calcul digital, acestea trebuie convertite în valori numerice discrete. Un convertor analog – digital (ADC) este un circuit electronic care convertește o tensiune analogică de la intrare într-o valoare digitală. | ||
Line 25: | Line 25: | ||
* ADC Sigma-delta (delta-sigma, 1-bit ADC sau ADC cu oversampling). | * ADC Sigma-delta (delta-sigma, 1-bit ADC sau ADC cu oversampling). | ||
- | ===== Convertorul ADC al Atmega 328p ===== | + | ===== 2. Convertorul ADC al Atmega 328p ===== |
Convertorul analog-digital inclus în microcontroller-ul Atmega324 este un ADC cu aproximări succesive. Are o rezoluție de pana la 10 biți și poate măsura orice tensiune din gama 0-5V de pe opt intrări analogice multiplexate (6 disponibile pe arduino). | Convertorul analog-digital inclus în microcontroller-ul Atmega324 este un ADC cu aproximări succesive. Are o rezoluție de pana la 10 biți și poate măsura orice tensiune din gama 0-5V de pe opt intrări analogice multiplexate (6 disponibile pe arduino). | ||
Line 56: | Line 56: | ||
==== Registre ==== | ==== Registre ==== | ||
=== ADMUX - ADC Multiplexer Selection Register === | === ADMUX - ADC Multiplexer Selection Register === | ||
- | {{ pm:lab:ADCMUX.png?800 | ADCMUX }} | + | {{ pm:lab:ADMUX.png?800 | ADCMUX }} |
* Bit 7:6 - **REFS1:0: Reference Selection Bits** -> Selecteaza tensiunea de referinta | * Bit 7:6 - **REFS1:0: Reference Selection Bits** -> Selecteaza tensiunea de referinta | ||
* Bit 5 - **ADLAR ADC: Left Adjust Result** -> Modul de aliniere a celor 10 biti. (left-aligned sau right-aligned) | * Bit 5 - **ADLAR ADC: Left Adjust Result** -> Modul de aliniere a celor 10 biti. (left-aligned sau right-aligned) | ||
Line 102: | Line 102: | ||
</code> | </code> | ||
- | ===== ADC in Arduino ===== | + | ===== 3. ADC in Arduino ===== |
Biblioteca arduino ne pune la dispozitie o functie simpla pentru a folosi ADC-ul si anume **analogRead()**. | Biblioteca arduino ne pune la dispozitie o functie simpla pentru a folosi ADC-ul si anume **analogRead()**. | ||
Line 116: | Line 116: | ||
Tensiunea de referinta folosita se poate seta cu functia analogReference() | Tensiunea de referinta folosita se poate seta cu functia analogReference() | ||
- | ===== Exercitii ===== | + | ===== 4. Exercitii ===== |
- | 1. Folositi cod arduino pentru a citi valoarea unui potentiometru si a unui senzor de temperatura si apoi trimiteti valorile pe seriala. | + | **Task 0** Folositi cod Arduino pentru a citi valoarea unui potentiometru si a unui senzor de temperatura si apoi trimiteti valorile pe seriala. |
- | + | - Valoarea potentiometrului ar trebui transmisa catre consola ca un procent. Va trebui sa convertiti numarul citit de ADC la un procent intre 0% si 100%. | |
- | a) Valoarea potentiometrului ar trebui transmisa catre consola ca un procent. Va trebui sa convertiti numarul citit de ADC la un procent intre 0% si 100%. | + | - Valoarea citita pentru senzorul de temperatura trebuie sa fie exprimata in grade Celsius. Tensiunea de iesire a senzorului variaza liniar cu temperatura. Puteti sa faceti conversia experimental sau folosindu-va de datasheet ([[https://www.analog.com/media/en/technical-documentation/data-sheets/TMP35_36_37.pdf|Datasheet TMP36 ]]). |
- | + | ||
- | b) Valoarea citita pentru senzorul de temperatura trebuie sa fie exprimata in grade celsius. Tensiunea de iesire a senzorului variaza liniar cu temperatura. Puteti sa faceti conversia experimental sau folosindu-va de datasheet (TMP36 - link-ul este mai jos). | + | |
{{ pm:lab:PB1.png?500 | PB1 }} | {{ pm:lab:PB1.png?500 | PB1 }} | ||
- | 2. Folosind cod specific de microcontroller, cititi valoarea potentiometrului doar atunci cand se apasa un buton. (Codul trebuie testat pe Ardunino, Tinkercad nu are suport pentru Auto-trigger). | + | <hidden> |
+ | **Soluția** se găsește pe [[https://www.tinkercad.com/things/b2Yra0sAu2J-brilliant-lappi-habbi/editel?sharecode=LfeWdU6ojyT1VzyOCdjwU3ieYR6u4bV2-lEko5iVrTc|Tinkercad TMP36]] | ||
+ | </hidden> | ||
+ | |||
+ | **Task 1** Folosind cod specific de microcontroller, cititi valoarea potentiometrului doar atunci cand se apasa un buton. | ||
+ | <note>Codul trebuie testat pe Arduino, Tinkercad nu are suport pentru Auto-trigger.</note> | ||
{{ pm:lab:PB2.png?500 | PB2 }} | {{ pm:lab:PB2.png?500 | PB2 }} | ||
+ | <hidden> | ||
+ | **Soluția** se găsește pe [[https://www.tinkercad.com/things/b2Yra0sAu2J-brilliant-lappi-habbi/editel?sharecode=LfeWdU6ojyT1VzyOCdjwU3ieYR6u4bV2-lEko5iVrTc|Tinkercad Interrupt]] | ||
- | 3. Folosind cod specific microcontrollerului cititi valoarea potentiometrului o data la 10ms. Pentru aceste exercitiu trebuie sa folositi ADC-ul sa porneasca o conversie automat in functie de un timer. (Codul trebuie testat pe Ardunino, Tinkercad nu are suport pentru Auto-trigger). | + | <code> |
+ | void timer_setup(){ | ||
+ | // set timer A for 10ms | ||
+ | TCCR0A = 0; | ||
+ | TCCR0B = 0; | ||
+ | TCNT0 = 0; | ||
+ | |||
+ | OCR0A = 156; // compare match -> 10ms | ||
+ | TCCR0A |= (1 << WGM01); // CTC mode | ||
+ | TCCR0B |= ((1 << CS02) | (1 << CS00)); // 1024 prescaler | ||
+ | TIMSK0 |= (1 << OCIE0A); | ||
+ | |||
+ | // Enable timer as source | ||
+ | ADCSRB |= ((1 << ADTS0) | (1 << ADTS1)); | ||
+ | } | ||
+ | |||
+ | void button_setup(){ | ||
+ | // Select INT0 as trigger source | ||
+ | ADCSRB = 0; | ||
+ | ADCSRB |= (1 << ADTS1); | ||
+ | |||
+ | // Enable INT0 | ||
+ | EICRA |= (1 << ISC00); | ||
+ | EIMSK |= (1 << INT0); | ||
+ | } | ||
+ | |||
+ | |||
+ | void setup() | ||
+ | { | ||
+ | |||
+ | // disable interrupts | ||
+ | cli(); | ||
+ | |||
+ | ADMUX = 0; | ||
+ | /* AVCC with external capacitor at AREF pin */ | ||
+ | ADMUX |= (1 << REFS0); | ||
+ | |||
+ | ADCSRA = 0; | ||
+ | /* set prescaler at 128 */ | ||
+ | ADCSRA |= (7 << ADPS0); | ||
+ | |||
+ | // Enable auto-trigger | ||
+ | ADCSRA |= (1 << ADATE); | ||
+ | // Enable Intrerupt | ||
+ | ADCSRA |= (1 << ADIE); | ||
+ | |||
+ | // Set button as trigger source | ||
+ | button_setup(); | ||
+ | |||
+ | // Select Timer as trigger source | ||
+ | //timer_setup(); | ||
+ | |||
+ | /* enable ADC */ | ||
+ | ADCSRA |= (1 << ADEN); | ||
+ | |||
+ | // Enable interrupts | ||
+ | sei(); | ||
+ | Serial.begin(9600); | ||
+ | } | ||
+ | |||
+ | ISR(ADC_vect){ | ||
+ | Serial.println(ADC); | ||
+ | } | ||
+ | |||
+ | ISR(INT0_vect) | ||
+ | { | ||
+ | Serial.println("Button Pressed!"); | ||
+ | } | ||
+ | |||
+ | ISR(TIMER0_COMPA_vect){ | ||
+ | // Even if this does nothing. It has to be here | ||
+ | // Else the code just doesn't work. Still don't know why. | ||
+ | // [AP] Deoarece ai activat intreruperea de compare match: TIMSK0 |= (1 << OCIE0A); | ||
+ | // [AP] Astfel, daca nu e definit ISR-ul se va reseta uC | ||
+ | } | ||
+ | |||
+ | void loop() | ||
+ | { | ||
+ | delay(50); | ||
+ | } | ||
+ | </code> | ||
+ | </hidden> | ||
+ | |||
+ | **Task 2** Folosind cod specific microcontrollerului cititi valoarea potentiometrului o data la 10ms. Pentru aceste exercitiu trebuie sa folositi ADC-ul sa porneasca o conversie automat in functie de un timer. | ||
+ | <note>Codul trebuie testat pe Arduino, Tinkercad nu are suport pentru Auto-trigger.</note> | ||
+ | |||
+ | <hidden> | ||
+ | **Soluția** se găsește pe [[https://www.tinkercad.com/things/grYhoajb3sd-exquisite-hango-waasa/editel?sharecode=gNPGmOuI6oZBx3bp-q-S7NlxWoz_wRwWZm9LJK4DHbI|Tinkercad Potentiometer]] | ||
+ | |||
+ | <code> | ||
+ | void timer_setup(){ | ||
+ | // set timer A for 10ms | ||
+ | TCCR0A = 0; | ||
+ | TCCR0B = 0; | ||
+ | TCNT0 = 0; | ||
+ | |||
+ | OCR0A = 156; // compare match -> 10ms | ||
+ | TCCR0A |= (1 << WGM01); // CTC mode | ||
+ | TCCR0B |= ((1 << CS02) | (1 << CS00)); // 1024 prescaler | ||
+ | TIMSK0 |= (1 << OCIE0A); | ||
+ | |||
+ | // Enable timer as source | ||
+ | ADCSRB |= ((1 << ADTS0) | (1 << ADTS1)); | ||
+ | } | ||
+ | |||
+ | void setup() | ||
+ | { | ||
+ | pinMode(2, INPUT_PULLUP); | ||
+ | |||
+ | // disable interrupts | ||
+ | cli(); | ||
+ | |||
+ | ADMUX = 0; | ||
+ | /* AVCC with external capacitor at AREF pin */ | ||
+ | ADMUX |= (1 << REFS0); | ||
+ | |||
+ | ADCSRA = 0; | ||
+ | /* set prescaler at 128 */ | ||
+ | ADCSRA |= (7 << ADPS0); | ||
+ | |||
+ | // Enable auto-trigger | ||
+ | ADCSRA |= (1 << ADATE); | ||
+ | // Enable Intrerupt | ||
+ | ADCSRA |= (1 << ADIE); | ||
+ | |||
+ | // Select Timer as trigger source | ||
+ | timer_setup(); | ||
+ | |||
+ | /* enable ADC */ | ||
+ | ADCSRA |= (1 << ADEN); | ||
+ | |||
+ | // Enable interrupts | ||
+ | sei(); | ||
+ | Serial.begin(9600); | ||
+ | } | ||
+ | |||
+ | ISR(ADC_vect){ | ||
+ | Serial.println(ADC); | ||
+ | } | ||
+ | |||
+ | ISR(TIMER0_COMPA_vect){ | ||
+ | // Even if this does nothing. It has to be here | ||
+ | // Else the code just doesn't work. Still don't know why. | ||
+ | // [AP] Deoarece ai activat intreruperea de compare match: TIMSK0 |= (1 << OCIE0A); | ||
+ | // [AP] Astfel, daca nu e definit ISR-ul se va reseta uC | ||
+ | } | ||
+ | |||
+ | void loop() | ||
+ | { | ||
+ | delay(50); | ||
+ | } | ||
+ | </code> | ||
+ | </hidden> | ||
+ | ===== 5. Resurse ===== | ||
- | ===== Linkuri Utile ===== | + | * {{:pm:atmel-7810-automotive-microcontrollers-atmega328p_datasheet.pdf|Datasheet Atmega 328p}} |
- | [[https://www.arduino.cc/reference/en/language/functions/analog-io/analogread/|Arduino Analog Read]] | + | * Arduino UNO pinout |
- | [[https://www.analog.com/media/en/technical-documentation/data-sheets/TMP35_36_37.pd|Datasheet TMP36 ]] | + | {{:pm:lab:uno.jpg?200|pinout Arduino UNO}} |
- | [[https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-7810-Automotive-Microcontrollers-ATmega328P_Datasheet.pd|Datasheet ATmega328p]] | + | * Responsabili: [[catalin.ghenea@cti.pub.ro | Cătălin Ghenea ]] |
+ | ===== 6. Linkuri Utile ===== | ||
+ | * [[https://www.arduino.cc/reference/en/language/functions/analog-io/analogread/|Arduino Analog Read]] | ||
+ | * [[https://www.analog.com/media/en/technical-documentation/data-sheets/TMP35_36_37.pdf|Datasheet TMP36 ]] | ||
+ | * [[https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-7810-Automotive-Microcontrollers-ATmega328P_Datasheet.pdf|Datasheet ATmega328p]] |