Skocz do zawartości

Generowanie 6 faz na Arduino - SPWM


Januszxd

Pomocna odpowiedź

Chciałbym zrobić 6 faz (używając 2 piny do każdej fazy) i do tej pory skutecznie zrobiłem takim sposobem 2 fazy na Arduino UNO i teraz napotykam ograniczenie, które nie wiem jak obejść. Najpierw wyjaśnię jak działa kod na 2 fazy oto on:

int i=0;
int j=0;
int x=0;
int y=0;
int OK=0;
int OK1=0;
int OK2=0;
int sinPWM[]={1,2,5,7,10,12,15,17,19,22,24,27,30,32,34,37,39,42,
44,47,49,52,54,57,59,61,64,66,69,71,73,76,78,80,83,85,88,90,92,94,97,99,
101,103,106,108,110,113,115,117,119,121,124,126,128,130,132,134,136,138,140,142,144,146,
148,150,152,154,156,158,160,162,164,166,168,169,171,173,175,177,178,180,182,184,185,187,188,190,192,193,
195,196,198,199,201,202,204,205,207,208,209,211,212,213,215,216,217,219,220,221,222,223,224,225,226,227,
228,229,230,231,232,233,234,235,236,237,237,238,239,240,240,241,242,242,243,243,244,244,245,245,246,246,
247,247,247,248,248,248,248,249,249,249,249,249,255,255,255,255,249,249,249,249,249,248,
248,248,248,247,247,247,246,246,245,245,244,244,243,243,242,242,241,240,240,239,238,237,237,236,235,234,
233,232,231,230,229,228,227,226,225,224,223,222,221,220,219,217,216,215,213,212,211,209,208,207,205,204,
202,201,199,198,196,195,193,192,190,188,187,185,184,182,180,178,177,175,173,171,169,168,166,164,162,160,
158,156,154,152,150,148,146,144,142,140,138,136,134,132,130,128,126,124,121,119,117,115,113,110,108,106,
103,101,99,97,94,92,90,88,85,83,80,78,76,73,71,69,66,64,61,59,57,54,52,49,47,44,42,39,37,34,32,30,
27,24,22,19,17,15,12,10,7,5,2,1};

void setup() {
Serial.begin(9600);

pinMode(5, OUTPUT);
pinMode(6,OUTPUT);
pinMode(3,OUTPUT);
pinMode(11,OUTPUT);

cli();// stop interrupts
TCCR0A=0;//reset the value
TCCR0B=0;//reset the value
TCNT0=0;//reset the value
//0b allow me to write bits in binary
TCCR0A=0b10100001;//phase correct pwm mode
TCCR0B=0b00000001; //no prescaler

TCCR2A=0;//reset the value
TCCR2B=0;//reset the value
TCNT2=0;//reset the value
//0b allow me to write bits in binary
TCCR2A=0b10100001;//phase correct pwm mode
TCCR2B=0b00000001; //no prescaler

TCCR1A=0;//reset the value
TCCR1B=0;//reset the value
TCNT1=0;//reset the value
OCR1A=509;// compare match value
TCCR1B=0b00001001; //WGM12 bit is 1 and no prescaler

TIMSK1 |=(1 << OCIE1A);// enable interrupts

sei();//stop interrupts
}
ISR(TIMER1_COMPA_vect){// interrupt when timer 1 match with OCR1A value
if(i>313 && OK==0){// final value from vector for pin 6
i=0;// go to first value of vector
OK=1;//enable pin 5
}
if(i>313 && OK==1){// final value from vector for pin 5
i=0;//go to first value of vector
OK=0;//enable pin 6
}
x=sinPWM[i];// x take the value from vector corresponding to position i(i is zero indexed)
i=i+1;// go to the next position
if(OK==0){
OCR0B=0;//make pin 5 0
OCR0A=x;//enable pin 6 to corresponding duty cycle
}
if(OK==1){
OCR0A=0;//make pin 6 0
OCR0B=x;//enable pin 5 to corresponding duty cycle
}

if ((i==209) || OK1==1){// the first signal has reached to position 209
//in the lookup table
OK1=1;// to maintain if function valid
if(j>313 && OK2==0){// final value from vector for pin 11
j=0;// go to first value of vector
OK2=1;//enable pin 3
}
if(j>313 && OK2==1){// final value from vector for pin 3
j=0;//go to first value of vector
OK2=0;//enable pin 11
}
y=sinPWM[j];// x take the value from vector corresponding to position j(j is zero indexed)
j=j+1;// go to the next position
if(OK2==0){
OCR2B=0;//make pin 3 0
OCR2A=y;//enable pin 11 to corresponding duty cycle
}
if(OK2==1){
OCR2A=0;//make pin 11 0
OCR2B=y;//enable pin 3 to corresponding duty cycle
}
}

}
void loop() {

}

Program wykorzystuje wszystkie 3 dostępne timery w UNO timer0, timer1 i timer2. W tablicy sinPWM[] zapisane są kolejne wartości dodatniej połówki sinusoidy, odpowiadają one kolejnym wartościom wypełnienia PWM.  Timer0 i Timer2 są ustawione w trybie PWM o konkretnej częstotliwości. Timer1 generuje przerwania o częstotliwości równej częstotliwości pozostałych dwóch timerów. W przerwaniu wartość wypełnienia sygnału np. na pinie 5 jest równa kolejnym wartościom z tablicy sinPWM[]. Po tym jak po kolei zostaną program przeleci te wszystkie wartości dla tego pinu, następuje zmiana na pin 6 i w taki sposób powstaje 1 faza. Analogicznie jest dla drugiej tyle, że ona zaczyna od wartości 209, a nie od 0 jak w przypadku 1 fazy (przesunięcie fazowe).

 

Ja chcę domyślnie zrobić 6 faz (mam swoje powody he he). Od razu widać, że tym sposobem nie osiągnę 6 faz na UNO, ponieważ ono ma tylko 3 timery, a ja potrzebuje po jednym timerze na każdą fazę do generowania PWM  i jeden timer, który będzie ustawiał wypełnienie w przerwaniu. 

Myślałem, że Arduino MEGA rozwiąże mój problem, ale tam jednak jest tylko 6 timer'ów czyli o 1 za mało bo ja potrzebuję ich 6. 

Czy jest może jakiś sposób / trik w jaki mógłbym uzyskać ten 1 dodatkowy timer? Ewentualnie jakieś inne rozwiązania mojego problemu? 

Są oczywiście inne uC, które mają więcej timerów, ale ich nie ogarniam.  Myślałem o Arduino DUE, ale tam też jest inne CPU i nie wiem nawet jak się za  to zabrać.

Z góry dzięki 😃 

Link do komentarza
Share on other sites

(edytowany)

Jeśli ma to być robione sprzętowo to musisz użyć czegoś wydajniejszego np: atmega128 ma w sam raz 6 wyjść PWM https://ww1.microchip.com/downloads/aemDocuments/documents/OTH/ProductDocuments/DataSheets/2467S.pdf lub szukać czegoś co ma "AT90PWM..." w nazwie, jest sporo tych mikrokontrolerów. Ja pewnie użyłbym do tego któregoś STMa  ale to taka moja opinia poza konkursem 🙂

 

Edytowano przez _LM_
Link do komentarza
Share on other sites

35 minut temu, Januszxd napisał:

ale tam jednak jest tylko 6 timer'ów

właściwie nie interesuje Cię ilość timerów a kanałów PWM jeden timer może obsłużyć wiele kanałów więc to nie jest kryterium

Link do komentarza
Share on other sites

26 minut temu, Januszxd napisał:

Ewentualnie jakieś inne rozwiązania mojego problemu? 

ESP32 posiada coś , co się nazywa MCPWM - sprzętowe rozwiązanie generowania przebiegów do sterowania silnikami. Są dwa moduły po 3 fazy, a więc tyle, ile potrzeba.

Jednak wdrożenie wymagać będzie wiele dociekliwości i pracy, bo opisy tej funkcjonalności są bardzo skąpe. Na początek do poczytania tu.

  • Lubię! 2
Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

12 minut temu, _LM_ napisał:

właściwie nie interesuje Cię ilość timerów a kanałów PWM jeden timer może obsłużyć wiele kanałów więc to nie jest kryterium

Czy sugerujesz, że da radę to zrobić na Arduino MEGA skoro w nim jest 15 kanałów PWM ? Z tego co się rozeznałem to tam niektóre timery mają po 3 rejestry porównawcze i łącznie na wszystkich timer'ach jest ich tyle, że powinno wystarczyć do generowania 6 faz...  jakbym np. w moim kodzie zmienił warunek tej instrukcji przerwania, żeby porównywała wartość z innym rejestrem porównawczym? Albo jakbym na tych dodatkowych kanałach generował kolejne przebiegi?
 

Link do komentarza
Share on other sites

2 godziny temu, Januszxd napisał:

Czy sugerujesz, że da radę to zrobić na Arduino MEGA

Przy takiej ilości tajmerów jak najbardziej jest to możliwe, tyle że rozwiązanie drogie płyta mega to koszt > 200zł to samo osiągniesz na dużo tańszych układach jak wspomniany ESP32, STM32 i RPI2040 Ale to twój wybór.

2 godziny temu, Januszxd napisał:

jakbym np. w moim kodzie zmienił warunek tej instrukcji przerwania, żeby porównywała wartość z innym rejestrem porównawczym? Albo jakbym na tych dodatkowych kanałach generował kolejne przebiegi?

Myślę że przeróbki programu to nie jest prosta podmiana paru linijek kodu. Już samo uruchomienie tylu timerów i powiązanych z nimi kanałami PWM to będzie nieco gimnastyki. Ja tego na tym mikrokontrolerze nie robiłem, z resztą mało co już robię w AVR  

  • Lubię! 1
Link do komentarza
Share on other sites

(edytowany)

To ma być sześć niezależnych kanałów PWM?

Niektóre AVRy np. ATTINY861 miały coś takiego jak tryb "6 kanałów PWM", ale było to pod kątem sterowania silnikami i ich mostkami. W praktyce były to sprzętowe kanały symetryczne, tzn. jeden kanał generował 2 przebiegi PWM, jeden w fazie, drugi w przeciw fazie.

Mając odpowiednio szybki mikrokontroler da się to zrobić pół programowo na 1 timerze.

Sprzętowo można było coś takiego zrobić na jakieś serii mikrokontrolerów PIC od MICROCHIPa, chyba max 4 kanały na jeden Timer, ale nie pamiętam czy PIC16 czy PIC18. Niestety to nie Arduino i nie AVRy. Obecnie rodzina AVR należy do MICROCHIPa, więc może mają jakieś nowe odmiany co potrafią taką sztuczkę zrobić jak PICi, ale trzeba by szukać i wnikać w temat.

Do zrobienia na ATMEGA 64 i Timer 1 oraz 3, bo maja po trzy kanały PWM. Na ATMEGA328 z ARDUINO UNO też niby do zrobienia, ale zużyjesz wszystkie Timery i rozdzielczość 8-bitów na 4 kanałach i 16 na dwóch.

Edytowano przez BlackJack
  • Lubię! 1
Link do komentarza
Share on other sites

16 godzin temu, BlackJack napisał:

To ma być sześć niezależnych kanałów PWM?

 

To ma być 6 faz sinusoidalnych przesuniętych względem siebie o 60 stopni do których potrzebuje po 2 piny na każdą z nich przy obecnym programie, jeżeli o to pytasz. 

Dziękuję wam za wszystkie przedstawione alternatywy. 

Ja osobiście skorzystam z Arduino skoro jest taka możliwość, ponieważ z nim tylko miałem doświadczenie do tej pory i jakoś się w nim odnajdę. Mimo wszystko porównując ceny innych uC to faktycznie prędzej czy później będę musiał przesiąść się na coś innego. W przyszłości spróbuję STM i kurs do niego.

Jeszcze raz dzięki 😁 

Link do komentarza
Share on other sites

Znalazłem artykuł w którym opisano temat generowania PWM na AVR. Z 16MHz ATMegi udało się wyciągnąć 16 kanałów PWM 300Hz. Wszystko zależy jakie parametry ma mieć twój PWM?

  • Lubię! 1
Link do komentarza
Share on other sites

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.