Operácie

Integrátor s mikroprocesorom: Rozdiel medzi revíziami

Zo stránky SensorWiki

StudentMIPS (diskusia | príspevky)
StudentMIPS (diskusia | príspevky)
Riadok 174: Riadok 174:
=== Overenie ===
=== Overenie ===


Ako ste overili funkciu, napríklad... Na používanie našej aplikácie stačia dve tlačítka a postup používania je opísaný v sekcii popis riešenia.
Overovali sme naš program tym že menili sme polohu potenciometra a pozerali ako sa zmeni graf na serial plot.
Na konci uvádzame fotku hotového zariadenia.  


[[Súbor:GeminiAI-image1.jpg|400px|thumb|center|Aplikácia.]]
[[Súbor:Potenciometr0.jpg|400px|thumb|center|Poloha potenciometra 0.]]
[[Súbor:GeminiAI-image1.jpg|400px|thumb|center|Aplikácia.]]
[[Súbor:Graf0.jpg|400px|thumb|center|Graf pri polohe potenciometra 0.]]


== Čo by som urobil inak ==
== Čo by som urobil inak ==

Verzia z 21:04, 23. jún 2026

Záverečný projekt predmetu MIPS / LS2026 - Dmytro Domchuk


Zadanie

Integrátor. Potenciometer zadá veľkosť vstupu integrátora. Vytvorí sa zdroj reálneho času, prírastku času, napr. 5ms. A s nastavenou integračnou časovou konštantou sa bude meniť v reálnom čase, výstup, ktorý sa bude zobrazovať na serialplot. Takže, sčitame hodnotu ADC vstupu z potenciometra a budeme ju integrovať každych 5ms. Ďalej, vysledky budeme posielať cez seriovu linku do programu SerialPlot.

Vývojová doska ACROB.

Literatúra:


Analýza a opis riešenia

Našou ulohou bolo vytvoriť integrator na zaklade vyvijivej dosky Acrob a petenciometroveho modula. Potenciometrový model sa saklada z potenciometra, prepinača režimu fungovania(linearný alebo parabolický), reset tlačidko a kontrolera. Zapojili sme modul potenciometra ku doske Acrob na port X4. A pripojili Acrob ku počitaču pomocou USB kabla. Na moldule potenciometra nastavujeme velkosť potenciometra, sčitavame hodnotu z ADC, vypočitame integral a posielame dve hodnoty na SerialPlot. Prva hodnota je velkosťou vstupu a druha je integrolom.

Celkový pohľad na zariadenie.

Nezabudnite doplniť schému zapojenia! V texte by ste mali opísať základné veci zo zapojenia, samotná schéma nie je dostačujúci opis.

Schéma zapojenia.


Algoritmus a program

Algoritmus programu  v hlavnej slučke sa začina tym že robí inicializaciu UART, ADC a Timer1 apovoluje prerušenia pomocou sei(). Ďalej zapisuje parametre integratora. Potom program zčita hodnotu z ADC a spravi posun nuly. Ďalej sa vytvori pasmo necitlivosti na +-3 jednotky z hodnoty ADC. Potom program vypočita integral Eulerovou metodou a spravi anti-windup aby hodnota integrala ne prekročila hranice 10000 a -10000. Ďalej v programe vytvorime 2 premennych typu int16_t plot_input a plot_ integral ktore sa rovnaju hodnotam input a integral. Ďalej posielame hodnoty premennych cez seriovu linku v binarnom tvare.

Funkcia void UART_init() robo inicializaciu UART pre baud 14400 a posialanie 8 datovych bitov a 1 stop bit. Funkcia void UART_transmit_byte(uint8_t data) čaka pokial bufer sa vyprazdni a posiela 8 datovych bitov. Funkcia void UART_send_int16(int16_t value) 2 krat použiva predchadzajucu funkciu na posielani jedneho čisla typu int16. Inicializaciu ADC robi void ADC_init(). Funkcia uint16_t ADC_read() načitava hodnotu z ADC.Inicializujeme Timer1 v void Timer1_init(). Funkcia ISR(TIMER1_COMPA_vect) je rutiniu prerušenia. Ne použil som funkcie uart.c a adc.c zo semestra lebo musel by som ich moc silno zmeniť, takže na jeden krat stači aj realizacia priamo v programe. Ale pri vetšiem počte podobnych programov alebo pre zabezpečenie fungovania na viacerych zariadeniach radšej spraviť zvlašť hlavnu slučku a funkcie.


#include <avr/io.h>

#define F_CPU 16000000UL
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <stdlib.h> 
	 // Globálne premenné
	   volatile uint8_t timer_flag = 0;// Príznak z prerušenia 
	  
	   // --- Inicializácia UART pre 14400 baud (pri 16 MHz) --- 
	   
    void UART_init() {
    uint16_t ubrr = 68; 
    UBRR0H = (uint8_t)(ubrr >> 8);
    UBRR0L = (uint8_t)ubrr;
    UCSR0A &= ~(1 << U2X0); // Dvojnásobná rýchlost off 
    UCSR0B = (1 << TXEN0); // Povolenie vysielaca
    UCSR0C = (1 << UCSZ01) | (1 << UCSZ00);
		   } // 8 dátových bitov, 1 stop bit . Odošle jeden znak 
		   
		   
		   
    void UART_transmit_byte(uint8_t data) {
    while (!(UCSR0A & (1 << UDRE0))); // caká na vyprázdnenie buffra 
    UDR0 = data;
		    } 
			
			
			
    void UART_send_int16(int16_t value){
    UART_transmit_byte((uint8_t)(value & 0xFF));
    UART_transmit_byte((uint8_t)((value>>8) & 0xFF));
			  }
			  
			  
			   // --- Inicializácia ADC --- 
			  void ADC_init() { // Referencia AVCC (REFS0=1), výber kanála ADC0 (MUX = 0000) 
			  ADMUX = (1 << REFS0)|(1<<MUX2); // Povolenie ADC (ADEN=1), preddelic 128 (ADPS2..0 = 111) pre frekvenciu 125 kHz
			   ADCSRA = (1 << ADEN) | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); } 
			   
			   // Nacítanie hodnoty z ADC0 
			   uint16_t ADC_read() {
                ADCSRA |= (1 << ADSC); // Spustenie prevodu 
			   while (ADCSRA & (1 << ADSC)); // cakanie na dokoncenie 
			   return ADC; 
			   } 
			   // --- Inicializácia Timer1 pre 5ms prerušenie --- 
			   void Timer1_init() { 
// Režim CTC (Clear Timer on Compare Match), 
			   TCCR1B |= (1 << WGM12); 
// Nastavenie preddelica na 64 
// Frekvencia casovaca = 16 MHz / 64 = 250 kHz 
// Požadovaný cas = 5 ms (0.005 s) 
// Hodnota do OCR1A = (0.005 * 250000) - 1 = 1249 
			   
               OCR1A = 1249; 
// Povolenie prerušenia pri zhode (Compare Match A) 
			   TIMSK1 |= (1 << OCIE1A); 
// Spustenie casovaca s preddelicom 64 (CS11=1, CS10=1) 
			   TCCR1B |= (1 << CS11) | (1 << CS10); } 
			   
			   // Rutina obsluhy prerušenia od Timer1 (vykoná sa každých 5 ms) 
			   ISR(TIMER1_COMPA_vect) {
                 timer_flag = 1; // Len nastavíme vlajku, výpocet urobíme v main slu?ke 
			   } 
			   int main(void) {
			   UART_init();
			   ADC_init();
			   Timer1_init();
			   sei(); // Globálne povolenie prerušení 
				   
				   // Parametre integrátora 
				   const float Ts = 0.005; // 5 ms 
				   const float Ti = 1.0; 
				   float integral = 0.0; 
				   float input =0;
				  
				    while (1) {
					 if (timer_flag) {
					  timer_flag = 0; // Zhodenie vlajky 
					 					  
					  // 1. Nacítanie vstupu a posunutie nuly 
					  uint16_t raw_adc = ADC_read();
					   input = (float)(raw_adc - 512); 
// Softvérové pásmo necitlivosti (Deadband) 
// Ignoruje jemný šum (napr. +- 3 hodnoty z ADC okolo stredu), aby integrátor nedriftoval 
					   if (input > -3.0 && input < 3.0) {
					    input = 0.0; 
						} 
						// 2. Výpocet (Eulerova dopredná metóda) 
						integral = integral + (Ts / Ti) * input; 
						// Anti-windup 
						if (integral > 10000.0) integral = 10000.0;
						 if (integral < -10000.0) integral = -10000.0; 
						 
						 
						 int16_t plot_input=(int16_t)input;
						 int16_t plot_integral=(int16_t)integral;
						  
// 4. Odoslanie vo formáte pre Serial Plotter: "Hodnota1,Hodnota2\n" 
						  
						  
							UART_send_int16(plot_input);
							UART_send_int16(plot_integral);
							UART_transmit_byte('\r');
							UART_transmit_byte('\n');
							 } 
							 } 
					   }
#include <avr/io.h>

#define F_CPU 16000000UL
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <stdlib.h> 
void UART_init();
void UART_transmit_byte(uint8_t data);
void UART_send_int16(int16_t value);
void ADC_init();
uint16_t ADC_read();
void Timer1_init();
ISR(TIMER1_COMPA_vect);
int main(void);

Pridajte sem aj zbalený kompletný projekt, napríklad takto (použite jednoznačné pomenovanie, nemôžeme mať na serveri 10x zdrojaky.zip:

Zdrojový kód: zdrojaky.zip

Overenie

Overovali sme naš program tym že menili sme polohu potenciometra a pozerali ako sa zmeni graf na serial plot.

Poloha potenciometra 0.
Graf pri polohe potenciometra 0.

Čo by som urobil inak

Zamyslite sa spätne nad problémom, ktorý ste riešili a napíšte, čo sa vám nepodarilo a nabudúce by ste spravili inak.


Kľúčové slová 'Category', ktoré sú na konci stránky nemeňte.