www.elektronik.si Seznam forumov www.elektronik.si
Forum o elektrotehniki in računalništvu
 
 PomočPomoč  IščiIšči  Seznam članovSeznam članov  SkupineSkupine  StatisticsStatistika  AlbumAlbum  DatotekeFilemanager DokumentacijaDocDB LinksPovezave   Registriraj seRegistriraj se 
  PravilaPravila  LinksBolha  PriponkePriponke  KoledarKoledar  ZapiskiZapiski Tvoj profilTvoj profil Prijava za pregled zasebnih sporočilPrijava za pregled zasebnih sporočil PrijavaPrijava 

Arduino-generiranje sinusa

 
Objavi novo temo   Odgovori na to temo   Printer-friendly version    www.elektronik.si Seznam forumov -> Arduino sekcija
Poglej prejšnjo temo :: Poglej naslednjo temo  
Avtor Sporočilo
tadejcl
Neznanec
Neznanec



Pridružen-a: Sre 14 Okt 2020 15:58
Prispevkov: 3
Aktiv.: 0.07

PrispevekObjavljeno: Sre Okt 14, 2020 4:11 pm    Naslov sporočila:  Arduino-generiranje sinusa Odgovori s citatom

Pozdravljeni

Sem čisto nov na forumu in imam problem z enim projektom, ki sem se ga lotil. Upam, da si bo kdo vzel čas in mi lahko pomagal.

Z arduinom želim generirati tri signale s faznim zamikom 120°. Se pravi neka simulacija trifaznega generatorja. Signale na izhodu dobim na osciloskopu (za prikaz/simulacijo uporabljam Proteus 8). Iz arduina dobim PWM signale (pin9, pin10 in pin11). Problem se pojavi, ko želim uporabiti low pass filter. Ko priklopim na osciloskop je signal trikoten.

Kaj moram spremeniti, da bom dobil dokaj lep sinus ker vem da čistega nebom dobil vendar vsaj približek? Moram spremeniti kodo? Vrednosti RC filtra? Ali tabelo z izračuni funkcije?

Že v naprej hvala za pomoč.

Lep pozdrav
Nazaj na vrh
Odsoten Poglej uporabnikov profil Pošlji zasebno sporočilo
rplink3r
Član
Član



Pridružen-a: Tor 06 Feb 2007 20:02
Prispevkov: 480
Aktiv.: 2.30
Kraj: Levec

PrispevekObjavljeno: Sre Okt 14, 2020 4:47 pm    Naslov sporočila:   Odgovori s citatom

Tule je primer za eno fazo, ko ti to dela greš naprej,

https://www.instructables.com/Arduino-Sinewave-for-Inverters/

Sicer je primerov veliko, bolj kot ne za eno fazo, pa tudi za tri faze bi znalo bit kaj.
Če po filtriranju dobiš trikot, bo nekaj narobe z generacijo pwm-a, napačne vrednosti v lookup tabeli, ali pa napake v programu.

Priloži kodo, da se vidi kaj dejansko imaš.

_________________
"The statement below is false."
"The statement above is true."
Nazaj na vrh
Odsoten Poglej uporabnikov profil Pošlji zasebno sporočilo MSN Messenger - naslov
tadejcl
Neznanec
Neznanec



Pridružen-a: Sre 14 Okt 2020 15:58
Prispevkov: 3
Aktiv.: 0.07

PrispevekObjavljeno: Sre Okt 14, 2020 5:56 pm    Naslov sporočila:   Odgovori s citatom

Kodo imam tako:

/**
Arduino IDE project assembly
Name: Fequency generator (3-phase)
Purpose: Testing

@author Tadej Zupančič
@version 1.0 30/09/20
*/

// CONSTANTS
const int f = 50; // frekvenca signala
const float fs = 500.0; // respond(odziv) bo 2 ms
const int t_delay = 2; // zakasnitev spremembe izhoda

// PUBLIC VARS
byte sig_phase1[500]; // signal faze 1: +0°
byte sig_phase2[500]; // signal faze 2: +120°
byte sig_phase3[500]; // signal faze 3: +240°
int i = 0; // stevec pozicije tabele
float t;
long timestamp_phase_correct = 0; // casovnik signala faze 1: +0°

void setup() {
pinMode(10, OUTPUT);

// Generiranje graf sinusne funkcije za - FAZA 1
for (int i = 0; i < 500; i++) // i je array številka(0, 1, 2, 3,...) GRE OD 1 - 500 SIGNALOV
{
t = (float)i / fs;
sig_phase1[i] = (byte)(127.0 * (sin(2 * 3.14 * f * t))); // +1 da dobis signal nad 0!, formula za generiranje katerekoli frekvence

}

// Generiranje graf sinusne funkcije za - FAZA 2
for (int i = 0; i < 500; i++) // i je array številka(0, 1, 2, 3,...) GRE OD 1 - 500 SIGNALOV
{
t = (float)i / fs;
sig_phase2[i] = (byte)(127.0 * (sin((2 * 3.14 * f * t)-90))); // +1 da dobis signal nad 0!, formula za generiranje katerekoli frekvence

}

// Generiranje graf sinusne funkcije za - FAZA 3
for (int i = 0; i < 500; i++) // i je array številka(0, 1, 2, 3,...) GRE OD 1 - 500 SIGNALOV
{
t = (float)i / fs;
sig_phase3[i] = (byte)(127.0 * (sin((2 * 3.14 * f * t)-180))); // +1 da dobis signal nad 0!, formula za generiranje katerekoli frekvence

}

}

void loop() {

if(micros() - timestamp_phase_correct > t_delay)
{
analogWrite(9, sig_phase1[i]); //Change output value phase 1 ob Do:9 (PWM)
analogWrite(10, sig_phase2[i]); //Change output value phase 2 ob Do:10 (PWM)
analogWrite(11, sig_phase3[i]); //Change output value phase 3 ob Do:11 (PWM)

i++;
i = (i < 500)? i : 0; // counter reset after 500 times (0-499)

timestamp_phase_correct = micros(); // sampling interval time stamp
}
}
Nazaj na vrh
Odsoten Poglej uporabnikov profil Pošlji zasebno sporočilo
igo
Član
Član



Pridružen-a: Sre 11 Okt 2006 19:11
Prispevkov: 3638
Aktiv.: 17.11

PrispevekObjavljeno: Sre Okt 14, 2020 8:38 pm    Naslov sporočila:   Odgovori s citatom

Najlažje je vzeti 3 števce
byte kot000; // 0...255
byte kot120;
byte kot240;

Potem na roke izračunaš vrednost celotne periode sinusa v 256 točkah (vsakih 360/256 stopinje) in jih shraniš v programski prostor, ne pa v RAM.
Sinusoida[]={ 127, ... 255, ..., 127, ... 0, ... 125}; // dvignjena za 127
To so vrednosti v točkah i = 0, 63, 127, 195, 255, ostale so pač vmes.

Nato v setup nastaviš 3 števce:
kot000 = 0;
kot120 = 85;
kot240 = 170;

V loop() pa samo s ++ povečuješ vse 3 števce in se bodo sami obrnili iz 255 v 0, ko bo treba.

Še ena malenkost glede hitrosti:

void loop()
{
GlavnaZ: // GlavnaZanka: DVOPIČJE
...
... program
...
kot000++;
kot120++;
kot240++;
goto GlavnaZ; // goto skok je 11 ciklov hitrejši od loop
} // void loop()

Upoštevaj, da pri 50 Hz ena perioda traja 20 ms, en korak kota pa
20/256 = 78 us .
To hitro mine zato ne izgubljaj nepotrebnih ciklov.

Ni dvakrat za reči, da ne bi bilo hitreje direktno brati 3 timerje in v kar brez prekinitve direktno računati vrednosti ob katerih mora posamezen pin spremeniti trenutno stanje.

_________________
Teoretično je praksa posledica teorije, praktično je pa ravno obratno. (igo 2001)
LP, Igor
Nazaj na vrh
Odsoten Poglej uporabnikov profil Pošlji zasebno sporočilo Pošlji E-sporočilo
tadejcl
Neznanec
Neznanec



Pridružen-a: Sre 14 Okt 2020 15:58
Prispevkov: 3
Aktiv.: 0.07

PrispevekObjavljeno: Čet Okt 15, 2020 1:18 pm    Naslov sporočila:   Odgovori s citatom

[quote="igo"]Najlažje je vzeti 3 števce
byte kot000; // 0...255
byte kot120;
byte kot240;

Potem na roke izračunaš vrednost celotne periode sinusa v 256 točkah (vsakih 360/256 stopinje) in jih shraniš v programski prostor, ne pa v RAM.
Sinusoida[]={ 127, ... 255, ..., 127, ... 0, ... 125}; // dvignjena za 127
To so vrednosti v točkah i = 0, 63, 127, 195, 255, ostale so pač vmes.

Nato v setup nastaviš 3 števce:
kot000 = 0;
kot120 = 85;
kot240 = 170;

V loop() pa samo s ++ povečuješ vse 3 števce in se bodo sami obrnili iz 255 v 0, ko bo treba.

Še ena malenkost glede hitrosti:

void loop()
{
GlavnaZ: // GlavnaZanka: DVOPIČJE
...
... program
...
kot000++;
kot120++;
kot240++;
goto GlavnaZ; // goto skok je 11 ciklov hitrejši od loop
} // void loop()

Upoštevaj, da pri 50 Hz ena perioda traja 20 ms, en korak kota pa
20/256 = 78 us .
To hitro mine zato ne izgubljaj nepotrebnih ciklov.

Ni dvakrat za reči, da ne bi bilo hitreje direktno brati 3 timerje in v kar brez prekinitve direktno računati vrednosti ob katerih mora posamezen pin spremeniti trenutno stanje.[/quote]


Pozem obdrzim tako kodo kot je in jo le popravim kot si omenil?
Nazaj na vrh
Odsoten Poglej uporabnikov profil Pošlji zasebno sporočilo
int47
Član
Član



Pridružen-a: Pon 15 Dec 2003 0:10
Prispevkov: 2066
Aktiv.: 9.30
Kraj: Ljubljana

PrispevekObjavljeno: Pet Okt 16, 2020 10:12 am    Naslov sporočila:   Odgovori s citatom

Tako na hitro :
tadejcl je napisal/a:
sig_phase2[i] = (byte)(127.0 * (sin((2 * 3.14 * f * t)-90))); // +1 da dobis signal nad 0!, formula za generiranje katerekoli frekvence


Mislim, da sin() računa v radianih.

_________________
Kdor ni skregan, ni Slovenc !
Nazaj na vrh
Odsoten Poglej uporabnikov profil Pošlji zasebno sporočilo
igo
Član
Član



Pridružen-a: Sre 11 Okt 2006 19:11
Prispevkov: 3638
Aktiv.: 17.11

PrispevekObjavljeno: Ned Okt 25, 2020 9:58 am    Naslov sporočila:   Odgovori s citatom

Tisti timestamp_phase_correct je dokaj ponesrečeno uporabljen, saj 2 mikrosekundi mineta zelo hitro.

Že tako računanje (+, -) z long spremenljivkami dolgo traja, zato se znotraj if pogoja uporablja le primerjanje (<, >).

byte Sinusoida[]= ... izračunaj sinusoido v 256 točkah

Setup()
{
kot000=0;
kot120=85;
kot240=170;

}

void loop()
{

GlavnaZ:

microzdaj = micros();
if(microzdaj > micronext)
{
micronext = microzdaj + microsinhron; // if pogoj bo naslednjič (next) izpolnjen čez microsinhron mikrosekund

analogWrite(9, Sinusoida[kot000]);
analogWrite(10, Sinusoida[kot120]);
analogWrite(11, Sinusoida[kot240]);

kot000++;
kot120++;
kot240++;
}

goto GlavnaZ;

}

Nisem preverjal, ampak vsak analogWrite mora uporabljati svoj Timer.
Vsak timer je povezan z dvema izhodnima pinoma, zato ni nujno, da smeš uporabiti pine 9, 10 in 11.
Za povrhu analogWrite vrže ven zelo počasno frekvenco 480 ali 960Hz in ni nujno, da bo kaj pametnega prilezlo ven na izhode, če jo boš v loop stalno spreminjal.



Naštudiraj registre, ki so povezani s Timerji, in vanje direktno vpisuj vrednosti ob katerih naj izhodni pini spremenijo stanje. To je v datasheetu od mikrokontrolerja.

_________________
Teoretično je praksa posledica teorije, praktično je pa ravno obratno. (igo 2001)
LP, Igor
Nazaj na vrh
Odsoten Poglej uporabnikov profil Pošlji zasebno sporočilo Pošlji E-sporočilo
Pokaži sporočila:   
Objavi novo temo   Odgovori na to temo   Printer-friendly version    www.elektronik.si Seznam forumov -> Arduino sekcija Časovni pas GMT + 2 uri, srednjeevropski - poletni čas
Stran 1 od 1

 
Pojdi na:  
Ne, ne moreš dodajati novih tem v tem forumu
Ne, ne moreš odgovarjati na teme v tem forumu
Ne, ne moreš urejati svojih prispevkov v tem forumu
Ne, ne moreš brisati svojih prispevkov v tem forumu
Ne ne moreš glasovati v anketi v tem forumu
Ne, ne moreš pripeti datotek v tem forumu
Ne, ne moreš povleči datotek v tem forumu

Uptime: 48 dni


Powered by phpBB © 2001, 2005 phpBB Group