• Witaj na Forum Arduino Polska! Zapraszamy do rejestracji!
  • Znajdziesz tutaj wiele informacji na temat hardware / software.
Witaj! Logowanie Rejestracja


Ocena wątku:
  • 0 głosów - średnia: 0
  • 1
  • 2
  • 3
  • 4
  • 5
ATTINY24, a PWM z wyjściem przeciwsobnym
#11
Właśnie problem mam taki, że nie mam pojęcia jak ustawić ten timer :E
Uskrobałbyś mi, proszę, ten kawałek kodu?
 
Odpowiedź
#12
Tak na szybko 

Kod:
#include <Arduino.h>

#define Pin_PWM1 5
#define Pin_PWM2 6

volatile uint8_t PWM = 0; // Wypelnienie o


ISR(TIMER1_COMPA_vect) {

  digitalWrite(Pin_PWM1,HIGH);
  digitalWrite(Pin_PWM2,LOW);
 
  OCR1B = PWM;   // 1000 Hz (16000000/((249+1)*64))

}

ISR(TIMER1_COMPB_vect) {

  digitalWrite(Pin_PWM1,LOW);
  digitalWrite(Pin_PWM2,HIGH);

}

void setup() {

  pinMode(Pin_PWM1, OUTPUT);
  pinMode(Pin_PWM2, OUTPUT);

  ///////////// ustawienie timera1 na 1Khz
  cli();
  TCCR1A = 0;
  TCCR1B = 0;
  TCNT1 = 0;
  OCR1A = 249;   // 1000 Hz (16000000/((249+1)*64))
  TCCR1B |= (1 << WGM12);
  TCCR1B |= (1 << CS11) | (1 << CS10);
  TIMSK1 |= (1 << OCIE1A) | (1 << OCIE1B);
  sei();
}

void loop() {
  PWM = 125;      // wypelnienie około 50% (0-249)
}

Musisz pamiętać ze PWM musi być z przedziału 0-249 co odpowiada 0-100% PWM  , pewnie jakieś wady są i trzeba poprawek. Na pewno jest wada przy wypełnieniu 0%  ale pierw przetestuj to dalej sie pomyśli..

A tutaj z opcja mapowania czyli PWM 0-100%
Kod:
#include <Arduino.h>

#define Pin_PWM1 5
#define Pin_PWM2 6

volatile uint8_t PWM = 0; // Wypelnienie o


ISR(TIMER1_COMPA_vect) {

  digitalWrite(Pin_PWM1,HIGH);
  digitalWrite(Pin_PWM2,LOW);

  uint8_t i_ = map(PWM, 0, 100 ,0, 249);
  OCR1B = i_;   // 1000 Hz (16000000/((249+1)*64))

}

ISR(TIMER1_COMPB_vect) {

  digitalWrite(Pin_PWM1,LOW);
  digitalWrite(Pin_PWM2,HIGH);

}

void setup() {

  pinMode(Pin_PWM1, OUTPUT);
  pinMode(Pin_PWM2, OUTPUT);

  ///////////// ustawienie timera1 na 1Khz
  cli();
  TCCR1A = 0;
  TCCR1B = 0;
  TCNT1 = 0;
  OCR1A = 249;   // 1000 Hz (16000000/((249+1)*64))
  TCCR1B |= (1 << WGM12);
  TCCR1B |= (1 << CS11) | (1 << CS10);
  TIMSK1 |= (1 << OCIE1A) | (1 << OCIE1B);
  sei();
}

void loop() {
  PWM = 50;      // wypelnienie w procentach
}
Arduino zostało wymyślone po to, by robić dobrze jedną prostą rzecz – migać diodą. 
 
Odpowiedź
#13
No więc tak:
Pierwsza sprawa - taktowanie zegara w moim przypadku to 8MHz (wewnętrzny zegar).
Twój kod działa połowicznie - owszem, zmiany stanów są zsynchronizowane (przeciwsobny PWM), ale kiedy ustawię PWM = 0, dalej generowana jest "szpilka" na jednym z wyjść, a na drugim jej odbicie.
Odziwo, zmiana na PWM = 249 nie daje żadnego rezultatu (brak zmiany na wyjściach).

W każdym razie, rzuć proszę okiem na ten kod:

Kod:
void setPwm (int val) {
  OCR1A = val;
  OCR1B = val;
  TCCR1A = 0b10110000 | (TCCR1A & 0b00001111);
}

Sprawa wygląda tak, że powyższy kod spełnia moje założenia, ale jedynie na Arudino (atmega328). Po załadowaniu do attiny24, na jednym wyjściu (OC1B) cały czas mam stan wysoki, natomiast na drugim (OC1A) jest pwm.
 
Odpowiedź
#14
Zapomniałem myślałem ze na 18mhz...  spróbuj to

Kod:
#include <Arduino.h>

#define Pin_PWM1 5
#define Pin_PWM2 6

volatile uint8_t PWM = 0; // Wypelnienie o


ISR(TIMER1_COMPA_vect) {

  digitalWrite(Pin_PWM1,HIGH);
  digitalWrite(Pin_PWM2,LOW);

  OCR1B = PWM;   // 1000 Hz (8000000/((124+1)*64))

}

ISR(TIMER1_COMPB_vect) {

  digitalWrite(Pin_PWM1,LOW);
  digitalWrite(Pin_PWM2,HIGH);

}

void setup() {

  pinMode(Pin_PWM1, OUTPUT);
  pinMode(Pin_PWM2, OUTPUT);

  ///////////// ustawienie timera1 na 1Khz
  cli();
  TCCR1A = 0;
  TCCR1B = 0;
  TCNT1 = 0;
  OCR1A = 124;   // 1000 Hz (8000000/((124+1)*64))
  TCCR1B |= (1 << WGM12);
  TCCR1B |= (1 << CS11) | (1 << CS10);
  TIMSK1 |= (1 << OCIE1A) | (1 << OCIE1B);
  sei();
}

void loop() {
  PWM = 62;      // wypelnienie około 50% (0-124)
}
 a w tym zobacz czy zlikwidowano szpilki problem jak PWM =0

Kod:
#include <Arduino.h>

#define Pin_PWM1 5
#define Pin_PWM2 6

volatile uint8_t PWM = 0; // Wypelnienie o


ISR(TIMER1_COMPA_vect) {

  digitalWrite(Pin_PWM1,HIGH);
  digitalWrite(Pin_PWM2,LOW);

  if(PWM >0){
    OCR1B = PWM;   // 1000 Hz (8000000/((124+1)*64))
    TIMSK1 = 0;
    TIMSK1 |= (1 << OCIE1A) | (1 << OCIE1B);
  }else{
    TIMSK1 = 0;
    TIMSK1 |= (1 << OCIE1A) ;
  }
 

}

ISR(TIMER1_COMPB_vect) {

  digitalWrite(Pin_PWM1,LOW);
  digitalWrite(Pin_PWM2,HIGH);

}

void setup() {

  pinMode(Pin_PWM1, OUTPUT);
  pinMode(Pin_PWM2, OUTPUT);

  ///////////// ustawienie timera1 na 1Khz
  cli();
  TCCR1A = 0;
  TCCR1B = 0;
  TCNT1 = 0;
  OCR1A = 124;   // 1000 Hz (8000000/((124+1)*64))
  TCCR1B |= (1 << WGM12);
  TCCR1B |= (1 << CS11) | (1 << CS10);
  TIMSK1 |= (1 << OCIE1A) ;
  sei();
}

void loop() {
  PWM = 62;      // wypelnienie około 50% (0-124)
}
Arduino zostało wymyślone po to, by robić dobrze jedną prostą rzecz – migać diodą. 
 
Odpowiedź
#15
Po załadowaniu do attiny24, na jednym wyjściu (OC1B) cały czas mam stan wysoki, natomiast na drugim (OC1A) jest pwm.


Nie ma Takiej możliwości... Coś musiałeś przerobić w kodzie... Na wyjściu pin6 i pin 5 jest machanie stanem wiec to nie możliwe co piszesz..

Sprawdzałem ten ostatni i jest ok brak szpilek przy "0" i przy "100" pwm...

A ta wersja nie ma żadnych wad 

Kod:
#include <Arduino.h>

#define Pin_PWM1 5
#define Pin_PWM2 6

volatile uint8_t PWM = 0; // Wypelnienie o


ISR(TIMER1_COMPA_vect) {

  digitalWrite(Pin_PWM1,HIGH);
  digitalWrite(Pin_PWM2,LOW);

  if(PWM >0){
    uint8_t i_ = map(PWM, 0, 100 ,0, 125);
    OCR1B = i_;   // 1000 Hz (8000000/((124+1)*64))
    TIMSK1 = 0;
    TIMSK1 |= (1 << OCIE1A) | (1 << OCIE1B);
  }else{
    TIMSK1 = 0;
    TIMSK1 |= (1 << OCIE1A) ;
  }
 

}

ISR(TIMER1_COMPB_vect) {

  digitalWrite(Pin_PWM1,LOW);
  digitalWrite(Pin_PWM2,HIGH);

}

void setup() {

  pinMode(Pin_PWM1, OUTPUT);
  pinMode(Pin_PWM2, OUTPUT);

  ///////////// ustawienie timera1 na 1Khz
  cli();
  TCCR1A = 0;
  TCCR1B = 0;
  TCNT1 = 0;
  OCR1A = 124;   // 1000 Hz (8000000/((124+1)*64))
  TCCR1B |= (1 << WGM12);
  TCCR1B |= (1 << CS11) | (1 << CS10);
  TIMSK1 |= (1 << OCIE1A) ;
  sei();
}

void loop() {
  PWM = 100;      // wypelnienie w %
}
Arduino zostało wymyślone po to, by robić dobrze jedną prostą rzecz – migać diodą. 
 
Odpowiedź
#16
Niestety, wada jaką zauważyłem jest taka, że nieważne czy ustawię 0% czy 100%, cały czas na tym samym wyjściu mam stan wysoki, a na drugim stan niski :/ Druga rzecz, teoretyczny 1% na wyjściu A trwa dobre kilka razy dłużej niż 1% na wyjściu B (sprawdzone oscyloskopem). Mówię o sytuacji kiedy ustawię PWM = 1, a następnie PWM = 99.

Co do mojego kodu, jakoś przypadkiem udało mi się go poprawnie uruchomić i działa Big Grin
Mam idealnie zsynchronizowany, lekki pod względem kodu, 10-bitowy PWM.

Załączam dla zainteresowanych:
Kod:
#define Pin_PWM1 5
#define Pin_PWM2 6

int x = 0;

void setup() {
  pinMode(Pin_PWM1, OUTPUT);
  pinMode(Pin_PWM2, OUTPUT);
}

void setPwm(int val){
  OCR1A = val;
  OCR1B = val;
  TCCR1A = 0b10110000 | (TCCR1A & 0b00001111);
}

void loop() {
  x = 511; //0-1023 PWM
  setPwm(x);
  while(1);
}


Sprawa wydaje się być rozwiązana, niemniej, dziękuję Ci kolego za zaangażowanie w temacie Smile
 
Odpowiedź
#17
No nie wiem mi tam na atmega328 prze taktowany na 8mHz działa bardzo dobrze bez szpilek, nie mam podwójnego oscyloskopu wiec sprawdzam tylko pojedynczo i jest u mnie ok..

Po drugie nie rozumiem dlaczego piszesz wyjście A i wyjście B skoro PWM jest programowe nie sprzętowe wiec jst tylko wyjście D5 i D6... .. i jedyne opóźnienie to czas przełączania pinów

digitalWrite(Pin_PWM1,HIGH);
digitalWrite(Pin_PWM2,LOW);


Ale ile to może trwać ??
Arduino zostało wymyślone po to, by robić dobrze jedną prostą rzecz – migać diodą. 
 
Odpowiedź
#18
(15-08-2020, 20:32)aj123 napisał(a): Niestety, wada jaką zauważyłem jest taka, że nieważne czy ustawię 0% czy 100%, cały czas na tym samym wyjściu mam stan wysoki, a na drugim stan niski :/

Przeciesz tak chciałeś..."ATTINY24, a PWM z wyjściem przeciwsobnym"
Arduino zostało wymyślone po to, by robić dobrze jedną prostą rzecz – migać diodą. 
 
Odpowiedź
#19
Nie zrozumieliśmy się; oczekiwałem, że kiedy ustawię wartość PWM na 0%, na wyjściu A dostanę stan niski, a na wyjściu B stan wysoki. Natomiast kiedy ustawię PWM na 100%, będzie odwrotnie - wysoki na A oraz niski na B.
W moim przypadku, nieważne czy ustawiłem 0% czy 100%, cały czas na A był stan niski, a na B wysoki.

A piszę wyjście A i B bo wykorzystuję wyjścia OC1A oraz OC1B, prawda?
 
Odpowiedź
#20
(15-08-2020, 21:05)aj123 napisał(a): Nie zrozumieliśmy się; oczekiwałem, że kiedy ustawię wartość PWM na 0%, na wyjściu A dostanę stan niski, a na wyjściu B stan wysoki. Natomiast kiedy ustawię PWM na 100%, będzie odwrotnie - wysoki na A oraz niski na B.
W moim przypadku, nieważne czy ustawiłem 0% czy 100%, cały czas na A był stan niski, a na B wysoki.


Wystarczyła mała modyfikacja to co oczekujesz
Kod:
#include <Arduino.h>

#define Pin_PWM1 5
#define Pin_PWM2 6

volatile uint8_t PWM = 0; // Wypelnienie o


ISR(TIMER1_COMPA_vect) {



  if(PWM >0){
    digitalWrite(Pin_PWM1,LOW);
    digitalWrite(Pin_PWM2,HIGH);
    uint8_t i_ = map(PWM, 0, 100 ,0, 125);
    OCR1B = i_;   // 1000 Hz (8000000/((124+1)*64))
    TIMSK1 = 0;
    TIMSK1 |= (1 << OCIE1A) | (1 << OCIE1B);
  }else{
    digitalWrite(Pin_PWM1,HIGH);
    digitalWrite(Pin_PWM2,LOW);
    TIMSK1 = 0;
    TIMSK1 |= (1 << OCIE1A) ;
  }
 

}

ISR(TIMER1_COMPB_vect) {

  digitalWrite(Pin_PWM1,HIGH);
  digitalWrite(Pin_PWM2,LOW);

}

void setup() {

  pinMode(Pin_PWM1, OUTPUT);
  pinMode(Pin_PWM2, OUTPUT);

  ///////////// ustawienie timera1 na 1Khz
  cli();
  TCCR1A = 0;
  TCCR1B = 0;
  TCNT1 = 0;
  OCR1A = 124;   // 1000 Hz (8000000/((124+1)*64))
  TCCR1B |= (1 << WGM12);
  TCCR1B |= (1 << CS11) | (1 << CS10);
  TIMSK1 |= (1 << OCIE1A) ;
  sei();
}

void loop() {
  PWM = 90;      // wypelnienie w %
}



Ja nie używam sprzętowego PWM..  Wiec nie ma  u mnie wyjścia OC1A oraz OC1B


 OC1A oraz OC1B, to tylko rejestry liczników kiedy następują zmiany...  na pinach 5,6 równiez moga to byc inne piny wszystkie cyfrowe.
Oczywiście jak zrobiłeś że działa ci sprzętowy to tak pozostaw bo sprzętowy jest lepszy niż programowy... 
Arduino zostało wymyślone po to, by robić dobrze jedną prostą rzecz – migać diodą. 
 
Odpowiedź
  


Skocz do:


Przeglądający: 1 gości