Integrátor s mikroprocesorom: Rozdiel medzi revíziami
Zo stránky SensorWiki
| Riadok 27: | Riadok 27: | ||
=== Algoritmus a program === | === Algoritmus a program === | ||
Algoritmus programu | 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. | ||
| Riadok 72: | Riadok 71: | ||
// --- Inicializácia ADC --- | // --- Inicializácia ADC --- | ||
void ADC_init() { // Referencia AVCC (REFS0=1), výber kanála ADC0 (MUX = 0000) | void ADC_init() { // Referencia AVCC (REFS0=1), výber kanála ADC0 (MUX = 0000) | ||
ADMUX = (1 << REFS0)|(1<<MUX2); // Povolenie ADC (ADEN=1), | 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); } | ADCSRA = (1 << ADEN) | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); } | ||
| Riadok 82: | Riadok 81: | ||
} | } | ||
// --- Inicializácia Timer1 pre 5ms prerušenie --- | // --- Inicializácia Timer1 pre 5ms prerušenie --- | ||
void Timer1_init() { // Režim CTC (Clear Timer on Compare Match), | void Timer1_init() { | ||
TCCR1B |= (1 << WGM12); // Nastavenie preddelica na 64 | // Režim CTC (Clear Timer on Compare Match), | ||
// Frekvencia | TCCR1B |= (1 << WGM12); | ||
// Požadovaný | // 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 | // Hodnota do OCR1A = (0.005 * 250000) - 1 = 1249 | ||
| Riadok 96: | Riadok 97: | ||
// Rutina obsluhy prerušenia od Timer1 (vykoná sa každých 5 ms) | // Rutina obsluhy prerušenia od Timer1 (vykoná sa každých 5 ms) | ||
ISR(TIMER1_COMPA_vect) { | ISR(TIMER1_COMPA_vect) { | ||
timer_flag = 1; // Len nastavíme vlajku, | timer_flag = 1; // Len nastavíme vlajku, výpocet urobíme v main slu?ke | ||
} | } | ||
int main(void) { | int main(void) { | ||
UART_init(); | |||
ADC_init(); | |||
Timer1_init(); | |||
sei(); // Globálne povolenie prerušení | |||
// Parametre integrátora | // Parametre integrátora | ||
| Riadok 114: | Riadok 115: | ||
timer_flag = 0; // Zhodenie vlajky | timer_flag = 0; // Zhodenie vlajky | ||
// 1. | // 1. Nacítanie vstupu a posunutie nuly | ||
uint16_t raw_adc = ADC_read(); | uint16_t raw_adc = ADC_read(); | ||
input = (float)(raw_adc - 512); | input = (float)(raw_adc - 512); | ||
| Riadok 159: | Riadok 160: | ||
void Timer1_init(); | void Timer1_init(); | ||
ISR(TIMER1_COMPA_vect); | ISR(TIMER1_COMPA_vect); | ||
int main(void) | int main(void); | ||
Verzia z 18:49, 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.
#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.

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