Nawijarka godzin

Miejsce dobre do dyskusji nad własnymi projektami - pochwal się wszystkim co samodzielnie stworzyłeś.
ODPOWIEDZ
ZbeeGin

Nawijarka godzin

Post autor: ZbeeGin » 23 kwie 2008, 18:46

Skoro panuje ostatnio atmosfera projektowo-filmowa postanowiłem i Ja coś pokazać.

Ostatnio poświęciłem dwie soboty na zbudowanie i uruchomienie zegara z tym czymś co odróżnia go od innych konstrukcji. Proszę zobaczyć:

Plik video (4.9MB WMV)

Głosu próbkom udzielił DarBie. Oryginalny projekt powstał w 1994-1995 roku na zaliczenie. Opierał się on na małym systemie mikroprocesorowym Z80. Program został napisany w asemblerze i powstał jeszcze na ZX Spectrum, a poprawki i symulacje wykonano już na komputerze Amiga. Oba komputery brały czynny udział w tworzeniu wszystkiego co łączyło się z tym projektem.

Teraz po 13 latach, postanowiłem całość napisać od nowa z wykorzystaniem procesora ATMega64. A ponieważ nie można go było dostać, trzeba było skorzystać z ATMega32 i zewnętrznej pamięci próbek dźwiękowych. Oczywiście program jak daweniej został napisany w języku maszynowym. Kaprys? Być może. :wink:
Ostatnio zmieniony 27 kwie 2008, 17:59 przez ZbeeGin, łącznie zmieniany 1 raz.

Awatar użytkownika
Tranzystor
Użytkownik
Posty: 889
Rejestracja: 28 sie 2005, 19:19
Lokalizacja: Świętochłowice
Kontakt:

Post autor: Tranzystor » 23 kwie 2008, 18:57

Witam,
ZbeeGin projekt mi się bardzo podoba, ale najbardziej podoba mi się pomysł. Jak AVR generuje dźwięk? Przez PWM czy jakiś przetwornik? Wydaje mi się, że PWM raczej by nie był wstanie tego zrobić, ale różne rzeczy robią ludzie :razz: Od małych kalkulatorów poprzez takie zabawki do mikrokomputerów na AVR32, ostatnio widziałem filmik o czymś takim na YouTube :smile: W tym wszystkim przeraża mnie tylko jedno, kiepska jakość filmów. Mam nadzieje, że powoli to się będzie zmieniać. Projekcik na prawdę godny podziwu :!:
Bardzo zainteresował mnie ten wyświetlacz. Jaki to jest typ wyświetlacza, jak dla mnie zwykły zielony LED, ale pewny nie jestem, bo za ładnie wygląda :D

Pozdro ;)

ZbeeGin

Post autor: ZbeeGin » 23 kwie 2008, 19:09

Tranzystor pisze:Wydaje mi się, że PWM raczej by nie był wstanie tego zrobić, ale różne rzeczy robią ludzie
A jednak. Taktowany pełną częstotliwością procesora TIMER0 w trybie FastPWM 8bit (bo takie są próbki) gada jak najęty - jak zresztą widać i słychać.
Tranzystor pisze:Bardzo zainteresował mnie ten wyświetlacz. Jaki to jest typ wyświetlacza, jak dla mnie zwykły zielony LED, ale pewny nie jestem, bo za ładnie wygląda
Jest to stary wyświetlacz LED z kasy fiskalnej produkcji... CCCP. A ponieważ ma gotowe połączenia w tryb multiplex to skorzystałem na początek z jego możliwości (i znikomej drutologii).

Oczywiście w pełnej wersji projektu będą większe wyświetlacze z działającym dwukropkiem. A mały wyświetlacz sekund będze służył także do programowania: alarmów czy okresowych sygnalizacji (pip/auto-mowa co godzinę). A może i inne fajerwerki sobie dobuduję.
Pamięci jest jeszcze dosyć. Program dlatego, iż nie został napisany w BASCOMie zajmuje tylko 648 bajtów (bez optymalizacji). Tabela odnośników próbek dalsze 1,2KB.

Awatar użytkownika
Tranzystor
Użytkownik
Posty: 889
Rejestracja: 28 sie 2005, 19:19
Lokalizacja: Świętochłowice
Kontakt:

Post autor: Tranzystor » 23 kwie 2008, 19:18

No, na prawdę fajna sprawa. Ja tam tylko zauważyłem, że on nie do końca składa wszystkie literki poprawnie. Mam nadzieję, że to jeszcze uda Ci się dopracować. No to pomyśl o jakimś sterowniku domu. Może zamontujesz go w ścianie i będziesz w nocy z nim gadał :D Mało prawdopodobne, ale pomarzyć można :)
W takim razie jakie jest próbkowanie tego PWMa? Szczerze mówiąc dzięki Twojemu projektowi wpadłem na ciekawy pomysł :D Zobaczymy czy uda mi się go zrealizować.

Muszę pogratulować :!:

Pozdrawiam ;)

ZbeeGin

Post autor: ZbeeGin » 23 kwie 2008, 19:41

Tranzystor pisze:Ja tam tylko zauważyłem, że on nie do końca składa wszystkie literki poprawnie. Mam nadzieję, że to jeszcze uda Ci się dopracować.
Żaden problem. Muszę tylko popoprawiać dane, gdyż wszystko da się podocinać jak trzeba. Niestety jak mówisz to wypowiadane sentencje akcentujesz, a tego wystkiego się nie da zaimplementować by mowa była doskonała - po prostu braknie pamięci.
Tranzystor pisze:No to pomyśl o jakimś sterowniku domu. Może zamontujesz go w ścianie i będziesz w nocy z nim gadał
Wolałbym spać w nocy niż słuchać opowieści w stylu "01:59", "02:00", "02:01" itd. Zatem program w godzinach nocnych mówić nie będzie, chyba, że jakiś nocny Marek sobie to tak skonfiguruje.
Tranzystor pisze:W takim razie jakie jest próbkowanie tego PWMa? Szczerze mówiąc dzięki Twojemu projektowi wpadłem na ciekawy pomysł Zobaczymy czy uda mi się go zrealizować.
Częstość podsyłania kolejnych wartości dobrałem eksperymentalnie. :razz: Nie chciało mi się liczyć ile zajmie czasu transmisja przez TWI + przygotowywanie danych. Próbki były w 1995r. zresamplowane na 6kHz. Stąd nieco marna jakość dżwięku. Jakbym użył licznika do odliczania okresu t=1/6000Hz przy pzesyłaniu kolejnych bajtów to dzwięk byłby oryginalny.
Samo odtwarzanie jest krótkie i zwięzłe:

Kod: Zaznacz cały

;--------------------------------------------------------------
pwm_setup:                              ; teraz czas na generator PWM (jako przetwornik DAC)
        ldi     r16, (1<<CS00)|(1<<WGM00)|(1<<WGM01)|(1<<COM00)|(1<<COM01)
                                        ; preskaler 8, tryb PWM Fast, inverted mode
        out     TCCR0, r16
        
        clr     r16                     ; OCR jest na poziomie 0
        out     OCR0, r16               ; zeruj rejestr
		
        sbi     DDRB, PORTB3            ; OCR0 jako wyjście
                                        ; koniec pwm

Kod: Zaznacz cały

;--i2c+odtwarzanie---------------------------------------------
_i2c_start:

        ldi     r24, (1 << TWINT)|(1 << TWSTA)|(1 << TWEN)
        out     TWCR, r24               ; włącz TWI, magistrala:START
        rcall   __wait_4_twiready       ; czekaj aż wykona

        ldi     r24, 0b10100000         ; adres+zapis (SLA+W) + ACK
        out     TWDR, r24               ; z adresem 24C512 (A0.A1=0.0)
        ldi     r24, (1 << TWINT)|(1 << TWEN) 
        out     TWCR, r24               ; wyślij teraz
        rcall   __wait_4_twiready       ; czekaj aż wykona

        out     TWDR, YH                ; poślij adres w pamięci H
        ldi     r24, (1 << TWINT)|(1 << TWEN)
        out     TWCR, r24               ; wyślij teraz
        rcall   __wait_4_twiready       ; czekaj aż wyśle

        out     TWDR, YL
        ldi     r24, (1 << TWINT)|(1 << TWEN) 
        out     TWCR, r24                ; wyślij teraz
; a my tymczasem...
        lpm                             ; pobierz długość
        mov     YL, r0                  ; najpierw młodszy
        adiw    ZL:ZH, 1                ;
        lpm
        mov     YH, r0                  ; teraz starszy i wpisz do licznika Y
        rcall   __wait_4_twiready       ; czy TWI gotowe?

        ldi     r24, (1 << TWINT)|(1 << TWSTA)|(1 << TWEN)
        out     TWCR, r24               ; magistrala: RSTART
        rcall   __wait_4_twiready

        ldi     r24, 0b10100001         ; adres+odczyt (SLA+R) + ACK
        out     TWDR, r24               ; 
        ldi     r24, (1 << TWINT)|(1 << TWEN)
        out     TWCR, r24               ; wyślij teraz

__play_loop:

        ldi     r24, (1 << TWINT)|(1 << TWEN)|(1 << TWEA)
        out     TWCR, r24               ; czytaj bajt z potwierdzeniem ACK
        rcall   __wait_4_twiready
        in      r24, TWDR               ; przepisz odebraną wartość do R24

        ldi     r16, 127
        add     r24, r16                ; dodaj 127 bo dane są signed
        out     OCR0, r24               ; poślij do przetwornika
      
        ldi     r24, 65                 ; odczekaj chwilę
__play_pause:        
        dec     r24                     ; licznik - 1
        nop                             ; standard :)
        nop
        brne    __play_pause

        sbiw    YL:YH, 1                ; zmniejsz licznik Y
        brne    __play_loop             ; jak dalsze dane to skocz

        ldi     r24, (1 << TWINT)|(1 << TWEN)|(0 << TWEA)
        out     TWCR, r24               ; inaczej odczytaj bajt z NACK
        rcall   __wait_4_twiready
        in      r24, TWDR               ; dana niepotrzebna - NACK się liczył

        ldi     r24, (1 << TWINT)|(1 << TWSTO)|(1 << TWEN)
        out     TWCR, r24               ; magistrala: STOP

ODPOWIEDZ