Generátor harmonického signálu: Rozdiel medzi revíziami
Zo stránky SensorWiki
slight fixes of formatting |
d formatting update |
||
| Riadok 1: | Riadok 1: | ||
Záverečný projekt predmetu MIPS / LS2026 - '''Oleksandr Mykyta''' | Záverečný projekt predmetu MIPS / LS2026 - '''Oleksandr Mykyta''' | ||
== Zadanie == | == Zadanie == | ||
| Riadok 19: | Riadok 18: | ||
kde: | kde: | ||
A₀ = 128 | A₀ = 128 | ||
A₁ = 100 | A₁ = 100 | ||
**TOC** | |||
== Analýza a opis riešenia == | == Analýza a opis riešenia == | ||
| Riadok 32: | Riadok 29: | ||
Základom je rovnica: | Základom je rovnica: | ||
y | y'' + ω²y = 0 | ||
Táto rovnica popisuje harmonické kmity (napr. pružina) a jej riešením sú funkcie sin() a cos(). To znamená, že ak vieme túto rovnicu numericky riešiť, vieme generovať sínus. | |||
=== Teoretický základ a odvodenia === | === Teoretický základ a odvodenia === | ||
| Riadok 47: | Riadok 43: | ||
Po úprave: | Po úprave: | ||
Y(s) · (T · s + 1) = X(s) | Y(s) · (T · s + 1) = X(s) | ||
T · s · Y(s) + Y(s) = X(s) | T · s · Y(s) + Y(s) = X(s) | ||
| Riadok 55: | Riadok 51: | ||
Týmto získame diferenciálnu rovnicu systému v časovej oblasti. | Týmto získame diferenciálnu rovnicu systému v časovej oblasti. | ||
==== Diskretizácia ==== | ==== Diskretizácia ==== | ||
| Riadok 63: | Riadok 58: | ||
Pre druhú deriváciu použijeme aproximáciu: | Pre druhú deriváciu použijeme aproximáciu: | ||
y | y'' ≈ (y[n] − 2y[n−1] + y[n−2]) / T_s² | ||
Po dosadení do (y | Po dosadení do (y'' + ω²y = 0): | ||
y[n] = (2 / (1 + ω²T_s²)) · y[n−1] − (1 / (1 + ω²T_s²)) · y[n−2] | y[n] = (2 / (1 + ω²T_s²)) · y[n−1] − (1 / (1 + ω²T_s²)) · y[n−2] | ||
Táto rovnica predstavuje numerickú aproximáciu oscilátora, ale nie je ideálna z hľadiska stability amplitúdy. | Táto rovnica predstavuje numerickú aproximáciu oscilátora, ale nie je ideálna z hľadiska stability amplitúdy. | ||
==== Diskrétny oscilátor (presný model) ==== | ==== Diskrétny oscilátor (presný model) ==== | ||
| Riadok 76: | Riadok 70: | ||
Presnejší prístup vychádza z trigonometrických identít: | Presnejší prístup vychádza z trigonometrických identít: | ||
sin(A + B) = sin(A)cos(B) + cos(A)sin(B) | sin(A + B) = sin(A)cos(B) + cos(A)sin(B) | ||
sin(A − B) = sin(A)cos(B) − cos(A)sin(B) | sin(A − B) = sin(A)cos(B) − cos(A)sin(B) | ||
| Riadok 85: | Riadok 79: | ||
Dosadením: | Dosadením: | ||
A = (n−1)θ | A = (n−1)θ | ||
B = θ | B = θ | ||
| Riadok 101: | Riadok 95: | ||
Tento vzťah generuje stabilný sínusový signál bez zmeny amplitúdy. | Tento vzťah generuje stabilný sínusový signál bez zmeny amplitúdy. | ||
==== Výpočet parametrov ==== | ==== Výpočet parametrov ==== | ||
| Riadok 110: | Riadok 103: | ||
kde: | kde: | ||
T = 0,5 s | T = 0,5 s | ||
ω = 1 / T = 2 rad/s | ω = 1 / T = 2 rad/s | ||
SAMPLE_RATE = 1000 Hz → T_s = 0,001 s | SAMPLE_RATE = 1000 Hz → T_s = 0,001 s | ||
θ = 0,002 | |||
==== Aproximacia cos() ==== | ==== Aproximacia cos() ==== | ||
| Riadok 128: | Riadok 120: | ||
2cos(θ) ≈ 2 · (1 − θ²/2) | 2cos(θ) ≈ 2 · (1 − θ²/2) | ||
==== Inicializácia oscilátora ==== | ==== Inicializácia oscilátora ==== | ||
| Riadok 134: | Riadok 125: | ||
Pre správnu činnosť oscilátora sú potrebné počiatočné hodnoty: | Pre správnu činnosť oscilátora sú potrebné počiatočné hodnoty: | ||
y1 = 1 | y1 = 1 | ||
y2 = 1 − θ²/2 | y2 = 1 − θ²/2 | ||
Tieto hodnoty zabezpečia vznik sínusového priebehu. | Tieto hodnoty zabezpečia vznik sínusového priebehu. | ||
==== Generovanie signálu ==== | ==== Generovanie signálu ==== | ||
| Riadok 149: | Riadok 139: | ||
kde: | kde: | ||
A0 = 128 | A0 = 128 | ||
A1 = 100 | A1 = 100 | ||
Tým sa signál posunie do kladného rozsahu vhodného pre PWM. | Tým sa signál posunie do kladného rozsahu vhodného pre PWM. | ||
==== Diskretizacia systému 1 / (sT + 1) ==== | ==== Diskretizacia systému 1 / (sT + 1) ==== | ||
| Riadok 167: | Riadok 156: | ||
Po úprave: | Po úprave: | ||
y[n] = x | y[n] = x − (T / T_s) · y[n] − (T / T_s) · y[n−1] | ||
y[n] · (1 + (T / T_s)) = x − (T / T_s) · y[n−1] | y[n] · (1 + (T / T_s)) = x − (T / T_s) · y[n−1] | ||
y[n] = (T_s / (T + T_s)) · x + (T / (T + T_s)) · y[n−1] | y[n] = (T_s / (T + T_s)) · x + (T / (T + T_s)) · y[n−1] | ||
| Riadok 177: | Riadok 166: | ||
dostaneme praktický tvar: | dostaneme praktický tvar: | ||
y[n] = α · x + (1 | y[n] = α · x + (1 − α) · y[n−1] | ||
y[n] = y[n−1] + α · (x − y[n−1]) | y[n] = y[n−1] + α · (x − y[n−1]) | ||
=== Algoritmus a program === | === Algoritmus a program === | ||
Algoritmus programu využíva diskrétny oscilátor a numerickú aproximáciu systému 1 / (sT + 1). Základné výpočty prebiehajú v prerušení Timer1 s frekvenciou 1 kHz: | |||
* výpočet oscilátora | |||
* generovanie vstupu x | |||
* výpočet výstupu systému | |||
* výstup cez PWM | |||
* odosielanie dát cez UART | |||
<tabs> | <tabs> | ||
| Riadok 221: | Riadok 208: | ||
ISR(TIMER1_COMPA_vect) | ISR(TIMER1_COMPA_vect) | ||
{ | { | ||
y = OSC_COEFF * y1 - y2; | |||
``` | |||
y2 = y1; | |||
y1 = y; | |||
float x = A0 + A1 * y; | |||
y_sys = y_sys + alpha * (x - y_sys); | |||
OCR0A = (uint8_t)(y_sys); | |||
printf("%d,%d\n", (int)x, (int)y_sys); | |||
``` | |||
} | } | ||
void timer1_init() | void timer1_init() | ||
{ | { | ||
TCCR1B |= (1 << WGM12); | |||
``` | |||
OCR1A = 15999; | |||
TCCR1B |= (1 << CS10); | |||
TIMSK1 |= (1 << OCIE1A); | |||
``` | |||
} | } | ||
void pwm_init() | void pwm_init() | ||
{ | { | ||
DDRD |= (1 << PD6); | |||
``` | |||
TCCR0A |= (1 << COM0A1) | (1 << WGM01) | (1 << WGM00); | |||
TCCR0B |= (1 << CS01); | |||
``` | |||
} | } | ||
int main(void) | int main(void) | ||
{ | { | ||
uart_init(); | |||
stdout = &mystdout; | |||
``` | |||
pwm_init(); | |||
timer1_init(); | |||
float Ts = 1.0 / SAMPLE_RATE; | |||
alpha = Ts / (T + Ts); | |||
float theta = (1.0 / T) * (1.0 / SAMPLE_RATE); | |||
y1 = 1.0; | |||
y2 = 1.0 - (theta * theta) / 2.0; | |||
OSC_COEFF = 2.0 * (1.0 - (theta * theta) / 2.0); | |||
sei(); | |||
while (1) | |||
{ | |||
} | } | ||
</syntaxhighlight></tab> | ``` | ||
</tabs> | |||
} </syntaxhighlight></tab> </tabs> | |||
=== Overenie === | === Overenie === | ||
| Riadok 291: | Riadok 288: | ||
Zo signálov je možné pozorovať zmenu amplitúdy a fázový posun, čo predstavuje bod frekvenčnej charakteristiky systému. | Zo signálov je možné pozorovať zmenu amplitúdy a fázový posun, čo predstavuje bod frekvenčnej charakteristiky systému. | ||
== Čo by som urobil inak == | == Čo by som urobil inak == | ||
Pri riešení by bolo možné použiť presnejšiu metódu diskretizacie systému 1/(sT + 1), napríklad bilineárnu transformaciu, ktorá by zlepšila presnosť modelu. | Pri riešení by bolo možné použiť presnejšiu metódu diskretizacie systému 1 / (sT + 1), napríklad bilineárnu transformaciu, ktorá by zlepšila presnosť modelu. | ||
Taktiež by bolo možné implementovať presnejší výpočet cos(θ) bez aproximacie, napríklad pomocou lookup tabuľky. | Taktiež by bolo možné implementovať presnejší výpočet cos(θ) bez aproximacie, napríklad pomocou lookup tabuľky. | ||
Ďalším zlepšením by mohlo byť automatické vyhodnotenie amplitúdy a fázového posunu priamo v mikrokontroleri namiesto spracovania na PC. | Ďalším zlepšením by mohlo byť automatické vyhodnotenie amplitúdy a fázového posunu priamo v mikrokontroleri namiesto spracovania na PC. | ||
[[Category:AVR]] [[Category:MIPS]] | [[Category:AVR]] [[Category:MIPS]] | ||
Verzia z 12:54, 18. apríl 2026
Záverečný projekt predmetu MIPS / LS2026 - Oleksandr Mykyta
Zadanie
Úlohou bolo generovať harmonický signál bez použitia funkcií sin() alebo cos(). Na tento účel bol použitý oscilátor realizovaný ako prenosová funkcia:
H(s) = 1 / ((s · T)^2 + 1)
Zároveň bolo potrebné zmerať jeden bod frekvenčnej charakteristiky systému:
H(s) = 1 / (s · T + 1)
pre frekvenciu ω = 1 / T, kde T = 0,5 s.
Výstupný signál má mať tvar:
A₀ + A₁ · sin(ωt + φ)
kde: A₀ = 128 A₁ = 100
- TOC**
Analýza a opis riešenia
Cieľom riešenia je vytvoriť sínusový signál bez použitia matematických funkcií sin() alebo cos(). Tento problém sa rieši pomocou diskrétneho oscilátora, ktorý vychádza z diferenciálnej rovnice harmonického kmitania.
Základom je rovnica:
y + ω²y = 0
Táto rovnica popisuje harmonické kmity (napr. pružina) a jej riešením sú funkcie sin() a cos(). To znamená, že ak vieme túto rovnicu numericky riešiť, vieme generovať sínus.
Teoretický základ a odvodenia
Laplaceova transformacia
Vychadzajme z prenosovej funkcie systému:
H(s) = Y(s) / X(s) = 1 / (T · s + 1)
Po úprave:
Y(s) · (T · s + 1) = X(s) T · s · Y(s) + Y(s) = X(s)
Použitím inverznej Laplaceovej transformacie (kde s predstavuje deriváciu) dostaneme:
T · dy(t)/dt + y(t) = x(t)
Týmto získame diferenciálnu rovnicu systému v časovej oblasti.
Diskretizácia
Mikrokontrolér pracuje v diskrétnom čase, preto je potrebné nahradiť derivácie rozdielmi medzi vzorkami.
Pre druhú deriváciu použijeme aproximáciu:
y ≈ (y[n] − 2y[n−1] + y[n−2]) / T_s²
Po dosadení do (y + ω²y = 0):
y[n] = (2 / (1 + ω²T_s²)) · y[n−1] − (1 / (1 + ω²T_s²)) · y[n−2]
Táto rovnica predstavuje numerickú aproximáciu oscilátora, ale nie je ideálna z hľadiska stability amplitúdy.
Diskrétny oscilátor (presný model)
Presnejší prístup vychádza z trigonometrických identít:
sin(A + B) = sin(A)cos(B) + cos(A)sin(B) sin(A − B) = sin(A)cos(B) − cos(A)sin(B)
Po sčítaní:
sin(A + B) + sin(A − B) = 2 · sin(A) · cos(B)
Dosadením:
A = (n−1)θ B = θ
dostaneme:
sin(nθ) + sin((n−2)θ) = 2 · cos(θ) · sin((n−1)θ)
Označením:
y[n] = sin(nθ)
vznikne rekurentný vzťah:
y[n] = 2 · cos(θ) · y[n−1] − y[n−2]
Tento vzťah generuje stabilný sínusový signál bez zmeny amplitúdy.
Výpočet parametrov
Platí:
θ = ω · T_s
kde: T = 0,5 s ω = 1 / T = 2 rad/s SAMPLE_RATE = 1000 Hz → T_s = 0,001 s
θ = 0,002
Aproximacia cos()
Keďže nie je dovolené použiť funkciu cos(), použije sa Taylorov rozvoj:
cos(θ) ≈ 1 − θ²/2
Pre malé θ je táto aproximacia dostatočne presná.
Z toho:
2cos(θ) ≈ 2 · (1 − θ²/2)
Inicializácia oscilátora
Pre správnu činnosť oscilátora sú potrebné počiatočné hodnoty:
y1 = 1 y2 = 1 − θ²/2
Tieto hodnoty zabezpečia vznik sínusového priebehu.
Generovanie signálu
Oscilátor generuje hodnoty v rozsahu ⟨−1, 1⟩.
Požadovaný výstup:
x = A0 + A1 · y
kde: A0 = 128 A1 = 100
Tým sa signál posunie do kladného rozsahu vhodného pre PWM.
Diskretizacia systému 1 / (sT + 1)
Zo spojitej rovnice:
T · dy/dt + y = x
Použitím Eulerovej metódy:
dy/dt ≈ (y[n] − y[n−1]) / T_s
Po úprave:
y[n] = x − (T / T_s) · y[n] − (T / T_s) · y[n−1] y[n] · (1 + (T / T_s)) = x − (T / T_s) · y[n−1] y[n] = (T_s / (T + T_s)) · x + (T / (T + T_s)) · y[n−1]
Po zavedení:
α = T_s / (T + T_s)
dostaneme praktický tvar:
y[n] = α · x + (1 − α) · y[n−1] y[n] = y[n−1] + α · (x − y[n−1])
Algoritmus a program
Algoritmus programu využíva diskrétny oscilátor a numerickú aproximáciu systému 1 / (sT + 1). Základné výpočty prebiehajú v prerušení Timer1 s frekvenciou 1 kHz:
- výpočet oscilátora
- generovanie vstupu x
- výpočet výstupu systému
- výstup cez PWM
- odosielanie dát cez UART
#define F_CPU 16000000UL
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdio.h>
#include "uart.h"
#define SAMPLE_RATE 1000.0
#define T 0.5
#define A0 128
#define A1 100
float OSC_COEFF;
volatile float y = 0;
volatile float y1 = 0;
volatile float y2 = 0;
volatile float y_sys = 0;
float alpha;
FILE mystdout = FDEV_SETUP_STREAM(uart_putc, NULL, _FDEV_SETUP_WRITE);
ISR(TIMER1_COMPA_vect)
{
y = OSC_COEFF * y1 - y2;
```
y2 = y1;
y1 = y;
float x = A0 + A1 * y;
y_sys = y_sys + alpha * (x - y_sys);
OCR0A = (uint8_t)(y_sys);
printf("%d,%d\n", (int)x, (int)y_sys);
```
}
void timer1_init()
{
TCCR1B |= (1 << WGM12);
```
OCR1A = 15999;
TCCR1B |= (1 << CS10);
TIMSK1 |= (1 << OCIE1A);
```
}
void pwm_init()
{
DDRD |= (1 << PD6);
```
TCCR0A |= (1 << COM0A1) | (1 << WGM01) | (1 << WGM00);
TCCR0B |= (1 << CS01);
```
}
int main(void)
{
uart_init();
stdout = &mystdout;
```
pwm_init();
timer1_init();
float Ts = 1.0 / SAMPLE_RATE;
alpha = Ts / (T + Ts);
float theta = (1.0 / T) * (1.0 / SAMPLE_RATE);
y1 = 1.0;
y2 = 1.0 - (theta * theta) / 2.0;
OSC_COEFF = 2.0 * (1.0 - (theta * theta) / 2.0);
sei();
while (1)
{
}
```
}
Overenie
Funkcia systému bola overená pomocou výpisu dát cez UART. Do sériového portu sa posielajú dvojice hodnôt:
x, y_sys
Tieto hodnoty je možné zobraziť napríklad pomocou Serial Plotteru, kde je viditeľný vstupný sínusový signál a výstup systému.
Zo signálov je možné pozorovať zmenu amplitúdy a fázový posun, čo predstavuje bod frekvenčnej charakteristiky systému.
Čo by som urobil inak
Pri riešení by bolo možné použiť presnejšiu metódu diskretizacie systému 1 / (sT + 1), napríklad bilineárnu transformaciu, ktorá by zlepšila presnosť modelu.
Taktiež by bolo možné implementovať presnejší výpočet cos(θ) bez aproximacie, napríklad pomocou lookup tabuľky.
Ďalším zlepšením by mohlo byť automatické vyhodnotenie amplitúdy a fázového posunu priamo v mikrokontroleri namiesto spracovania na PC.