logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

[ATtiny2313][C] 6IN, 3OUT

CSun 07 Gru 2008 21:51 939 6
REKLAMA
  • #1 5830918
    CSun
    Poziom 11  
    Witam.

    Próbuję zaprojektować urządzenie na układzie ATtiny2313 mające na wyjściu 3 kanały PWM, które były by sterowane za pomocą 6 przycisków (2 na kanał do sterowania szerokością impulsu +/-).

    Napisałem taki kod:

    
    #include <avr/io.h>
    
    #define OSC 8 // was: 4
    
    // makra do sterowania kanałami wyjściowymi
    #define RED_ON    PORTB |=  0x20    // PORTB.5
    #define RED_OFF   PORTB &= ~0x20
    #define GREEN_ON  PORTB |=  0x40    // PORTB.6
    #define GREEN_OFF PORTB &= ~0x40
    #define BLUE_ON   PORTB |=  0x80    // PORTB.7
    #define BLUE_OFF  PORTB &= ~0x80
    
    // zmienne globalne zawierające aktualne wartości wypełnień kanałów
    unsigned char RV; // red value (0-255)
    unsigned char GV; // green value (0-255)
    unsigned char BV; // blue value (0-255)
    
    // enumeracja kanałów
    const unsigned char R = 0; // red
    const unsigned char G = 1; // green
    const unsigned char B = 2; // blue
    
    //-----------------------------------------------------------
    //-----------------------------------------------------------
    //-----------------------------------------------------------
    void CHNG(unsigned char Color, unsigned char Value){
    
      // red -----------------------------------------
      if(Color == R){
    
        if(Value == 2){
    
          if(RV == 0){
    
            RV = 255;
    
          } else {
    
            RV = 0;
    
          }
    
        } else if(Value == 1){
    
          if(RV < 255) RV++;
    
        } else if(Value == 0){
    
          if(RV > 0) RV--;
    
        }
    
      // green ---------------------------------------
      } else if(Color == G){
    
        if(Value == 2){
    
          if(GV == 0){
    
            GV = 255;
    
          } else {
    
            GV = 0;
    
          }
    
        } else if(Value == 1){
    
          if(GV < 255) GV++;
    
        } else if(Value == 0){
    
          if(GV > 0) GV--;
    
        }
    
      // blue ----------------------------------------
      } else if(Color == B){
    
        if(Value == 2){
    
          if(BV == 0){
    
            BV = 255;
    
          } else {
    
            BV = 0;
    
          }
    
        } else if(Value == 1){
    
          if(BV < 255) BV++;
    
        } else if(Value == 0){
    
          if(BV > 0) BV--;
    
        }
    
      }
    
    }
    
    //-----------------------------------------------------------
    //-----------------------------------------------------------
    //-----------------------------------------------------------
    int main(void){
    
      // port B jako wyjście
      DDRB = 0xFF;
    
      // konfiguracja początkowych opcji
      RV = 0;
      GV = 0;
      BV = 0;
    
      // główna pętla programu
      while(1){
    
        // aby opóźnić obsługę butonów
        unsigned char l;
        for(l=0; l<100; l++){
    
          // jeśli wartości koloru są > 0 to włączamy diodę
          if(RV > 0) RED_ON;
          if(GV > 0) GREEN_ON;
          if(BV > 0) BLUE_ON;
    
          // PWM
          unsigned char i;
          for(i=0; i<256; i++){
    
            // wyłączamy diody kiedy i > %V (% = R,G,B)
            if(i > RV) RED_OFF;
            if(i > GV) GREEN_OFF;
            if(i > BV) BLUE_OFF;
    
          }
    
        }
    
    
        // Jeśli PIND.X jest w sanie niskim to znaczy, że wciśnięto X buton
        //-------------------------------------
        if(bit_is_clear(PIND, 0) && bit_is_clear(PIND, 1)){ // RED TO MAX/ZERO
    
          CHNG(R, 2);
    
        } else if(bit_is_clear(PIND, 0)){ // RED +
    
          CHNG(R, 1);
    
        } else if(bit_is_clear(PIND, 1)){ // RED -
    
          CHNG(R, 0);
    
        }
    
        //-------------------------------------
        if(bit_is_clear(PIND, 2) && bit_is_clear(PIND, 3)){ // GREEN TO MAX/ZERO
    
          CHNG(G, 2);
    
        } else if(bit_is_clear(PIND, 2)){ // GREEN +
    
          CHNG(G, 1);
    
        } else if(bit_is_clear(PIND, 3)){ // GREEN -
    
          CHNG(G, 0);
    
        }
    
        //-------------------------------------
        if(bit_is_clear(PIND, 4) && bit_is_clear(PIND, 5)){ // BLUE TO MAX/ZERO
    
          CHNG(B, 2);
    
        } else if(bit_is_clear(PIND, 4)){ // BLUE +
    
          CHNG(B, 1);
    
        } else if(bit_is_clear(PIND, 5)){ // BLUE -
    
          CHNG(B, 0);
    
        }
    
      }
    
      return 0;
    
    }
    
    //-----------------------------------------------------------
    //-----------------------------------------------------------
    //-----------------------------------------------------------
    


    i chciałem zapytać czy będzie to działać zgodnie z oczekiwaniami?

    A oto oczekiwania:

    przyciski na porcie D od 0 do 5 mają sterować wypełnieniem 3 sygnałów PWM na porcie B 5, 6, 7. Ponadto ma to się odbywać z częstotliwością minimum 100Hz. Opóźnienie wynikające z wciśnięcia przyciska nie jest tutaj wadą.

    Proszę o wasze odpowiedzi.

    Dodam, że w KamAVR kompiluje się bez błędów.

    Pozdrawiam.
  • REKLAMA
  • #2 5831169
    dawid512
    Poziom 32  
    A nie prościej wrzucić na uc i zobaczyć? Forum to nie maszynka do której wrzucasz program a ona wróży ci czy zadziała czy nie...
  • REKLAMA
  • #3 5831212
    CSun
    Poziom 11  
    Wrzucam pierw na forum ponieważ może ktoś zobaczy coś nieprawidłowego w tym co zrobiłem, ale jeszcze jedno mam pytanie odnośnie tego układu...

    skoro przyciski łączy się z wejściami układu i masą to w jaki sposób mogę przerobić to tak, aby alternatywnie używać do sterowania portu LPT?
    Czy koniecznie muszę PORT-MASA przepuszczać przez tranzystor sterowany przez LPT? A może są jakieś prostsze sposoby?
  • REKLAMA
  • #4 5831226
    dawid512
    Poziom 32  
    Nie koniecznie masa, może być stan wysoki czy zbocze rosnące czy opadające.
  • REKLAMA
  • #5 5831274
    CSun
    Poziom 11  
    Czy gdybym bezpośrednio podłączył powiedzmy wyjście (LPT)D0 do wejścia (UC)D0, (oczywiście wszystkie masy razem) to gdy dam stan wysoki na LPT to będzie działać jak "wciśnięty przycisk", a jak niski to jak "nie-wciśnięty przycisk"?

    //----------
    Dla tych, którzy by się sugerowali moim kodem:

    Teoretycznie można to tak zostawić, ale myślę, że nie jest to 'eleganckie' rozwiązanie ponieważ w najgorszym wypadku kożdy kanał byłby gaszony 254 razy...:

    
          // jeśli wartości koloru są > 0 to włączamy diodę
          if(RV > 0) RED_ON;
          if(GV > 0) GREEN_ON;
          if(BV > 0) BLUE_ON;
    
          // PWM
          unsigned char i;
          for(i=0; i<256; i++){
    
            // wyłączamy diody kiedy i > %V (% = R,G,B)
            if(i > RV) RED_OFF;
            if(i > GV) GREEN_OFF;
            if(i > BV) BLUE_OFF;
    
          }
    


    lepiej:

    
    dodać do main:
    
      // info co jest włączone
      char RO = 0; // RED
      char GO = 0; // GREEN
      char BO = 0; // BLUE
    
    
    zamienić:
    
          // jeśli wartości koloru są > 0 to włączamy diodę
          if(RV > 0){ RED_ON; RO = 1; }
          if(GV > 0){ GREEN_ON; GO = 1; }
          if(BV > 0){ BLUE_ON; BO = 1; }
    
          // PWM
          unsigned char i;
          for(i=0; i<256; i++){
    
            // wyłączamy diody kiedy i > %V (% = R,G,B)
            if(i > RV && RO){ RED_OFF; RO = 0; }
            if(i > GV && GO){ GREEN_OFF; GO = 0; }
            if(i > BV && BO){ BLUE_OFF; BO = 0; }
    
          }
    
  • #6 5831520
    Dr.Vee
    VIP Zasłużony dla elektroda
    Jeśli robisz tego typu software'owy PWM, to lepiej będzie zrobić tak:
    1) robisz tablicę par (poziom, maska_diody)
    2) sortujesz tablicę tak, żeby poziomy były w porządku niemalejącym
    3) przy T=0 włączasz wszystkie diody, i = 0
    4) czekasz na czas T >= i-ty czas z tablicy
    5) wyłączasz i-tą diodę z tablicy
    6) i = i+1
    7) if i < liczba diod goto 4) else goto 3)

    Przy zmianie wartości jasności zaczynasz od 2).

    Nie mówiąc już o tym, że w attiny2313 masz aż 4 wyjścia sprzętowego PWM - aż się prosi, żeby je tu wykorzystać.

    Pozdrawiam,
    Dr.Vee
  • #7 5831801
    CSun
    Poziom 11  
    Skoro można to oczywiście wolę sprzętowe PWM'y...

    PYTANIE 1:
    Zatem rozumiem, że OCR0A, OCR0B, OCR1B (w nocie OC0A, OC1A, OC1B) to będą wyjścia PWM'ów pod które mam podłączyć diody (pomijając resztę elektroniki)?

    PYTANIE 2:
    Czy jak połączę wejścia uC z wyjściami portu LPT to ustawienie sygnału na stan wysoki spowoduje że bit_is_set() zwróci TRUE dla danego pinu?


    W załączniku zamieszczam zmodyfikowaną wersję, z uwzględnieniem zapisywania i odczytu stanów kanałów - proszę o ewentualne komentarze jeśli ktoś by zauważył usterki w programie.
REKLAMA