• 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
Wykładnicze rozświetlanie LED
#1
Witam!

Problem tyczy się rozświetlania LED przy pomocy sygnału PWM 

Mianowicie od kilku dni próbuję napisać kilka linijek [podejrzewam] prostego kodu i nic nie wychodzi. 
Udało mi się napisać program , który będzie rozświetlał od 0 do 100% LED w określonym czasie, ale zrobienie tego wykładniczo jest bardziej skomplikowane.  W tym momencie wypełnienie [0-255] w ustawionym przyciskami czasie rośnie liniowo. Ale efekt wcale taki nie jest. Myślę , że to wynika z charakterystyki samej diody oraz z logarytmicznego działania zmysłu wzroku [Prawo Webera-Fechnera]. Stąd pomysł by robić to wykładniczo. No i dochodzi jeszcze jeden, wspomniany już problem. Musi być możliwość ustawienia czasu, w którym wypełnienie dojdzie do 255. 

Znalazłem taki  link, ale jak sprawdziłem go na swojej płytce to nie bardzo jest możliwość operowania docelowym czasem... 

Ma ktoś może jakiś pomysł? 
Z góry dziękuję za wszystkie odpowiedzi!
 
Odpowiedź
#2
Do zarządzania czasem w Arduino służą funkcje millis() i micros(), przykład użycia jest w podstawowych przykładach Arduino - blinkWithoutDelay oraz mnóstwo na tym forum. Albo co stały okres czasu zmiennie regulujesz wypełnienie, albo zmieniasz co jaki czas dodajesz mocy do leda (kolejny krok np. po 1000,500,250ms).
Miło być decenianym https://buycoffee.to/kaczakat
 
Odpowiedź
#3
Przyjrzyj się uważnie temu kodowi z linka. Jest  "możliwość operowania docelowym czasem".

Myślę, że najlepszym sposobem na wykładniczą regulację jasności diody, jest zrozumienie problemu.
Facet  z podanego linka pisze, że doszedł do tego metodą prób i błędów, a przecież jeśli wiadomo jak działa ludzkie oko, to poco kombinować?
Ludzki aparat wzroku działa logarytmicznie, więc chcąc wyrazić jego wrażenia wzrokowe, to dla Atmegi, mając 256 kroków, możemy napisać:

Kod:
float WW[256]; // wrażenia wzrokowe
for (int x = 1; x <= 256; x++){
WW[x-1] = LOG o podst 256 z x;

Żeby tą krzywą wyprostować, trzeba ją obniżyć o jej odwrotność.
Kod:
int wykres[256];
for (int x = 255; x >= 0; x--){
wykres[x] = (1 -  WW[255 - x]) * 256;
}
Zauważ, że wykres jest typu integer.
I teraz mamy mapę dla wypełnienia PWM.
Kod:
for (int i = 0; i<=255; i++){
analogWrite(ledPin, wykres[i];
}
Oczywiście policzenie logarytmu o podstawie 256 na atmedze, to kopanie się z koniem, będzie bolało i to bardzo.
Należy więc policzyć to sobie w excelu i wpisać do tablicy, najlepiej zaokrąglając do liczb rzeczywistych.
Jeśli masz problem z kodem lub sprzętem, zadaj pytanie na forum. Nie odpowiadam na PW, jeśli nie dotyczą one spraw forum lub innych tematów prywatnych.

[Obrazek: SsIndaG.jpg]
 
Odpowiedź
#4
(07-05-2018, 09:30)Robson Kerman napisał(a): Oczywiście policzenie logarytmu o podstawie 256 na atmedze, to kopanie się z koniem, będzie bolało i to bardzo.
Należy więc policzyć to sobie w excelu i wpisać do tablicy, najlepiej zaokrąglając do liczb rzeczywistych.

Witam,
Lepiej będzie od razu przeliczyć na int-y i dopiero taką tablicę zamieścić w programie.
Pozdrawiam.
 
Odpowiedź
#5
No właśnie się pomyliłem, miało być "do liczb naturalnych", a napisałem rzeczywistych.
Jeśli masz problem z kodem lub sprzętem, zadaj pytanie na forum. Nie odpowiadam na PW, jeśli nie dotyczą one spraw forum lub innych tematów prywatnych.

[Obrazek: SsIndaG.jpg]
 
Odpowiedź
#6
Witam ponownie !

Na start chciałbym podziękować wszystkim za podpowiedzi!

Poradziłem sobie troszeczkę inaczej. Przede wszystkim skorzystałem z potęgowego prawa Stevensa (jest to właściwie rozwinięciem prawa Webera-Fechnera), które dla różnych zmysłów podsuwa konkretne wykładniki. Okazuje się , że (na moje szczęście) dla światła; odczuwalna zmiana jest kwadratem wpakowanej mocy Big Grin

No i w afekcie popełniłem taki program - 


Kod:
#define sygnalPWM 11
#define wlacznik A2

int wypelnienie = 0;
boolean stanWlacznika = false;
unsigned long aktualnyCzas = 0;
int rozdzielczosc = 255;
unsigned long czasWypelnienia = 0;
unsigned long zapamietanyCzas = 0;
unsigned long roznicaCzasu = 0;
unsigned long czasDoPelnegoRozswietlenia = 10000;  

void setup() {

 Serial.begin(9600);
 pinMode(wlacznik, INPUT_PULLUP);
 pinMode(sygnalPWM, OUTPUT);
 
}

void loop() {
 aktualnyCzas = millis();
 roznicaCzasu = aktualnyCzas - zapamietanyCzas;
 czasWypelnienia = ((sqrt(wypelnienie)*czasDoPelnegoRozswietlenia)/sqrt(rozdzielczosc+1));
 Serial.println(wypelnienie);
 
 
  if (digitalRead(wlacznik) == LOW) {
    delay(500);
    stanWlacznika = !stanWlacznika;
    zapamietanyCzas = aktualnyCzas;
  }
 
  if (stanWlacznika == true ) {

      if (roznicaCzasu >= czasWypelnienia) {
   
      if (wypelnienie < rozdzielczosc) {
          wypelnienie = wypelnienie + 1;
      } else {
          digitalWrite(sygnalPWM, HIGH);
      }
     
          analogWrite(sygnalPWM, wypelnienie);
     
      }
     
}
     

  if (stanWlacznika == false) {
      wypelnienie = 0;
      digitalWrite(sygnalPWM, LOW);
  }
}
  
Program jest domyślnie ustawiony na 10s. 
Pełne wypełnienie jest w zmiennej ponieważ docelowo chciałbym zwiększyć rozdzielczość korzystając z tej strony.
Mam pełną świadomość , że program jest mocno nieschludny , ale działa zgodnie z założeniem więc jak na pierwsze spotkanie z programowaniem to jestem zadowolony!
Oczywiście jak ktoś ma pomysł co w nim pozmieniać to z chęcią go doszlifuję (wszelkie optymalizacje wskazane ponieważ docelowo będzie częścią większego programu).
Na marginesie chciałbym dodać , że od ładnych kilku lat zajmuję się elektroniką analogową i bardzo długo wzbraniałem się przed nauką programowania oraz cyfryzacją swoich projektów. Przyszedł moment kiedy bez pomocy jakiegoś mikrokontrolera nie mogło się obejść więc uznałem, że na początek - Arduino...
Zakochałem się w tej płytce  Heart
 
Odpowiedź
#7
No toć napisałem:

(07-05-2018, 09:30)Robson Kerman napisał(a): Żeby tą krzywą wyprostować, trzeba ją obniżyć o jej odwrotność.

Odwrotnością logarytmu jest potęgowanie.
W programowaniu piękne jest to, że każdy problem można rozwiązać na tyle sposobów, ilu programistów zajmuje się tym problemem.

Jeśli chcesz upakować to w większy projekt, radzę zainteresować się tablicami.
Jeśli masz problem z kodem lub sprzętem, zadaj pytanie na forum. Nie odpowiadam na PW, jeśli nie dotyczą one spraw forum lub innych tematów prywatnych.

[Obrazek: SsIndaG.jpg]
 
Odpowiedź
#8
Tak, tak - to zrozumiałem. Nie wiedziałem tylko czy to będzie funkcja kwadratowa. Ale jak już pisałem "na moje szczęście jest" Smile
Tablice to chyba dobry pomysł. Z przyjemnością ogarnę!
Jeszcze raz dziękuję wszystkim i życzę spokojnego wieczoru!
 
Odpowiedź
#9
(07-05-2018, 10:26)Smaczek napisał(a): Lepiej będzie od razu przeliczyć na int-y i dopiero taką tablicę zamieścić w programie.

To jedyne sensowne rozwiązanie. Gdy tablica jest liczona zajmuje pamięć RAM, której w AVR jest jak na lekarstwo.
 
Odpowiedź
#10
(08-05-2018, 20:37)Robson Kerman napisał(a): No toć napisałem:
Odwrotnością logarytmu jest potęgowanie.
Nie to żebym się czepiał, ale raczej odwrotnością potęgowania jest pierwiastkowanie (czyli w sumie też potęgowanie)
 
Odpowiedź
  


Skocz do:


Przeglądający: 1 gości