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

[C] [C]Lampa RGB na Attiny13 z programowym PWM - ograniczenie liczby kolorów w tabeli

bb84 14 Lip 2017 00:30 2649 38
  • #1 16586673
    bb84
    Poziom 21  
    Mam drobny problem z programem z tej strony: http://fab.cba.mit.edu/classes/863.14/people/andrew_mao/week7/

    Zmodyfikowałem go nieco i wrzuciłem do Attiny13, który przy użyciu programowego PWN steruje paskiem LED RGB. Działa to pięknie za wyjątkiem jednej rzeczy.

    Wykorzystuję tabelę z predefiniowanymi kolorami do "programowania" różnych efektów, ale można do niej wrzucić tylko 5 kolorów. Przykładowo taka tabela działa:

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Taka tabela powoduje wyświetlanie koloru zielonego i białe błyski:

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Jak sobie z tym poradzić ?

    Zmodyfikowany kod wygląda następująco:

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • #2 16586720
    trol.six
    Poziom 31  
    bb84 napisał:
    Zmodyfikowałem go nieco i wrzuciłem do Attiny13

    Ten uC ma troche mało pamięci SRAM, a typowo tabela z danymi dla attiny13 w gcc tamże ląduje. Np:

    1. Zmień typ dla danych COLORS i brightness z int na unsigned char. Pętla wtedy będzie dla i < 255; i
    brightness[] = { 254, 254, 254 };

    Nie wiem czy takie zmiany wystarczą, ale to ci da ok 9-10 kolorów w tabeli.

    2. Można też np umieścić dane w pamięci FLASH albo nawet w EEPROM, choć nie pamiętam na ile szybki odczyt z eepromu jest. Z tym że jak wrzucisz do eepromu to ustaw bity BOD.
  • #3 16586744
    bb84
    Poziom 21  
    trol.six napisał:
    1. Zmień typ dla danych COLORS i brightness z int na unsigned char. Pętla wtedy będzie dla i < 255; i


    10 kolorów wystarczy. Mógłbym prosić o wprowadzenie zmiany w kodzie ?
  • #4 16586750
    JacekCz
    Poziom 42  
    strona dokumentacji
    http://www.atmel.com/webdoc/avrlibcreferencemanual/porting_1iar_porting_flash.html
    http://mikrokontrolery.blogspot.com/2011/03/K...tmel-PROGMEM-Problemy-z-kompatybilnoscia.html

    generalnie szkoda RAM dla stałych tablic. I tak taka tablica (jesli ma choć jedną niezerową inicjację) występuje dwa razy, w RAM używana podczas pracy, i flash (generalnie: pamięć ROM) z wartością inicjującą.

    EDIT: również stos jest w pamięci RAM, przejechanie nie jest to kontrolowane podczas wykonania na małych procesorach, czyli ukochane Undefined Behaviour
  • #5 16586960
    Konto nie istnieje
    Konto nie istnieje  
  • #6 16587010
    tmf
    VIP Zasłużony dla elektroda
    @R-MIK Dlatego należy użyć BOD przy zapisie do EEPROM, że generalnie tak zaleca producent - zapis do EEPROM przy zbyt niskim zasilaniu może doprowadzić do błędów zapisu i skasowania komórek znajdujących się na jednej stronie EEPROM.
    Co do umieszczania danych we FLASH - PROGMEM to przestarzała konstrukcja. Należy wykorzystać _flash, dzięki temu nie trzeba modyfikować reszy kodu i stosować makr pgm_read_xx.
  • #7 16587073
    Konto nie istnieje
    Konto nie istnieje  
  • #8 16587188
    tmf
    VIP Zasłużony dla elektroda
    @R-MIK Generalnie producent zaleca, aby używając EEPROM włączyć BOD. Przy zbyt inskim zasilaniu każdy dostęp do rejestrów EEPROM może zakończyć się skasowaniem strony wskazywanej przez EEADR ze względu na nieprawidłowe funcjonowanie tego modułu.
    Te czasy dostępu to nie wiem o co ci chodzi, bo nikt o tym nie wspominał.
  • #9 16587241
    trol.six
    Poziom 31  
    bb84 napisał:
    Mógłbym prosić o wprowadzenie zmiany w kodzie ?

    Może ktoś wrzuci, ja się nie podejmuje.

    tmf napisał:
    Należy wykorzystać _flash, dzięki temu nie trzeba modyfikować reszy kodu

    obawiam się że trzeba małe co nie co.
    Cytat:
    warning: assignment discards 'const' qualifier from pointer target type
    oldColor = COLORS[color];

    Albo mój kompilator avr-gcc czegoś nie umie :)
  • #10 16587602
    bb84
    Poziom 21  
    Nie bardzo wiem gdzie umieścić pgm_read_byte. Przykładowo poniższy kod przechodzi kompilację bez błędów, ale w praktyce przy 5-6 kolorach to nie działa.

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • #11 16587737
    Konto nie istnieje
    Konto nie istnieje  
  • #12 16587789
    bb84
    Poziom 21  
    R-MIK napisał:
    Co oznacza w praktyce nie działa? Jakie jest zachowanie programu?


    Powoduje wyświetlanie koloru zielonego i białe błyski.
  • #13 16587819
    Konto nie istnieje
    Konto nie istnieje  
  • #14 16587911
    grko
    Poziom 33  
    A może by tak użyć memcpy_P do odczytu wielu wartości? Czy może to już zbyt wiele zmarnowanych cykli procesora? Albo po prostu użyć __flash i odczytywać bezpośrednio.
  • #15 16588022
    JacekCz
    Poziom 42  
    grko napisał:
    A może by tak użyć memcpy_P do odczytu wielu wartości? Czy może to już zbyt wiele zmarnowanych cykli procesora? Albo po prostu użyć __flash i odczytywać bezpośrednio.


    Wątek się w lekki chaos rozwija. Ja nie zauwazyłem, aby optymalizacja pojedynczych cykli procesora była istotna
  • #16 16588079
    trol.six
    Poziom 31  
    Jak się chcecie męczyć się z tym kodem to oczywiście w ramach sportu chętnie wam pokibicuje :)

    A tak bez sportowo to najlepiej zrobć jak pisze tmf, z tym że będą potrzebne zmiany w kodzie.

    Oczywiście include zostaje, #include <avr/pgmspace.h>

    a zmiany w kodzie:

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • #17 16588163
    BlueDraco
    Specjalista - Mikrokontrolery
    Pierwszy z tuzina problemów z tym programem - to użycie typu int zamiast uint8_t do reprezentacji liczb z zakresu 0..250. Drugi, ważniejszy - to niedziałający PWM na opóźnieniach programowych zamiast przerwania timera. Trzeci - użycie mnożenia do liczenia kolorów - policzy coś innego niż się spodziewasz.

    Zaczynamy od obliczeń, z których już za chwilę wyniknie jasno, że sensownie programowo możemy uzyskać pewnie nie więcej niż ze 100 poziomów jasności. Potem czytamy starą notę aplikacyjną Atmela o programowym PWM w przerwaniu timera i robimy wszytko od nowa. Tak wygląda wersja hardcore

    Wersja dla rozsądnych - znajdujemy mikrokontroler o połowę tańszy od ATtiny13, wyposażony w min. 3 wyjścia PWM.
  • #18 16588288
    bb84
    Poziom 21  
    Powiem szczerze, że średnio to widzę. Docelowy projekt zakłada podświetlenie lamp 6S33S diodami 3W przez centralny otwór w ceramicznej podstawce septarowej. Efekt uzyskany tym programem jest nieco "odpustowy". Sporo ciekawiej wyglądałoby podświetlenie kolorem bursztynowym i od czasu do czasu zmiany koloru, intensywności i częstotliwości jak na załączonym filmie. Zacząłem pisać program na piechotę z predefiniowanymi wartościami koloru i częstotliwości (właściwie potrzebny bursztyn i purpura), ale nie mam pomysłu na płynne przejścia między nimi.

    Film z planowanym efektem:

    https://www.youtube.com/watch?v=rEaPixo1Ako

    Początki programu:

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • #19 16588720
    BlueDraco
    Specjalista - Mikrokontrolery
    Zacznij od nowa. żadnych delay().
  • #20 16588744
    Konto nie istnieje
    Konto nie istnieje  
  • #21 16588756
    BlueDraco
    Specjalista - Mikrokontrolery
    Przecież to nigdy nie będzie "ok".
  • #22 16588769
    Konto nie istnieje
    Konto nie istnieje  
  • #23 16588919
    bb84
    Poziom 21  
    trol.six napisał:
    A tak bez sportowo to najlepiej zrobć jak pisze tmf, z tym że będą potrzebne zmiany w kodzie.


    Serdecznie dziękuję kolegom za pomoc, w szczególności koledze trol.six. Po wprowadzeniu zmian program śmiga aż miło. W tabeli można umieścić do 90 kolorów. Efekt bursztynowej podstawy i chwilowych przejść w fiolet i jego odcienie jest przepiękny. Możliwości Attiny13 wykorzystane w 100% i o to właśnie chodziło.

    Co do pisania kodu na opóźnieniach i pętlach to masakra. Owszem, efekty są, ale jest to metoda prób i błędów, a przy kilku zdefiniowanych kolorach i ich przywołaniu pamięć jest momentalnie zapełniona.

    Docelowy kod po poprawkach wygląda tak:

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • #24 16589046
    Konto nie istnieje
    Konto nie istnieje  
  • #25 16589366
    bb84
    Poziom 21  
    Poprawiłem.

    Poziomy jasności są bardzo nieliniowe. Przykładowo przy pomocy poniższej tabeli uzyskuję tylko nieco ciemniejszy bursztynowy przechodzący w jasny pomarańczowy. Dopiero czerwony na poziomie 10-20 obniża mocno jasność.

    { 50, 4, 0 }, // amber 1
    { 150, 8, 0 }, // amber 2
    { 250, 10, 0 }, // amber 3
  • #26 16589386
    Konto nie istnieje
    Konto nie istnieje  
  • #27 16589472
    BlueDraco
    Specjalista - Mikrokontrolery
    Twój pseudo-PWM jest zupełnie nieliniowy. Czas świecenia diody nie jest proporcjonalny do wartości zmiennej określającej jasność, a na jasność każdej wpływają również pozostałe. Ten program nie ma wiele wspólnego z generowaniem przyzwoitych przebiegów PWM.

    Zacznij od przerwania timera - jakieś 10..20 kHz. Przeczytaj uważnie notę aplikacyjną Atmela o programowym PWM.

    Diody LED przy sterowaniu PWM są jak najbardziej liniowe - emitowana energia (średnie natężenie światła) jest liniowo proporcjonalne do wypełnienia. Gorzej z ludzkim okiem i postrzeganą jasnością - tu mamy nieliniowość, która jednak jest niewielka w porównaniu z nieliniowością tego potworka programowego w tym wątku.

    W tym programie może się zdarzyć, że przy jasności x dioda będzie świeciła jaśniej niż przy jasności x+1, bo czas świecenia przy x+1 będzie krótszy, niż przy x.
  • #28 16589480
    bb84
    Poziom 21  
    W praktyce program działa zadowalająco, jedynym problemem była tabela. Metodą prób i błędów można dobrać odpowiednie kolory/odcienie, poziomy natężenia światła i czas przejścia między kolorami, a wszystko na Attiny13, więc dalsze kombinacje mijają się z celem.
  • #29 16589495
    Konto nie istnieje
    Konto nie istnieje  
  • #30 16589518
    BlueDraco
    Specjalista - Mikrokontrolery
    Masz tu kawałek programu sprzed 8 lat z PWM dla diody RGB ze wspólną anodą, z samoczynną i płynną zmianą koloru wg zawartości wektora.
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
REKLAMA