Integrátor s mikroprocesorom: Rozdiel medzi revíziami
Zo stránky SensorWiki
| Riadok 179: | Riadok 179: | ||
[[Súbor:GeminiAI-image1.jpg|400px|thumb|left|Aplikácia.]] | [[Súbor:GeminiAI-image1.jpg|400px|thumb|left|Aplikácia.]] | ||
[[Súbor:GeminiAI-image1.jpg|400px|thumb|right|Aplikácia.]] | [[Súbor:GeminiAI-image1.jpg|400px|thumb|right|Aplikácia.]] | ||
== Čo by som urobil inak == | == Čo by som urobil inak == | ||
Verzia z 19:08, 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.

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.

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.

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
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. Na konci uvádzame fotku hotového zariadenia.


Č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.