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

Led Light by Gerhard Schmidt

_ACeK_ 06 Gru 2025 14:28 4302 4

TL;DR LABEL_AI_GENERATED

  • Zbudowano efekt LED na ATtiny13 na uniwersalnej płytce, z tranzystorem na pająka i gwiazdą z diodami.
  • Układ steruje jasnością przez Timer0 w fast PWM z TOP=15 i pobiera przebiegi z tabel w pamięci flash.
  • Przy zegarze 1,2 Mcs/s i preskalerze 256 PWM ma 293 c/s, a czasy cykli mieszczą się w 0,055–0,88 s.
  • S1 obniża jasność do połowy, S2 przyspiesza animację 16×, a S3 i S4 wybierają program.
  • Tryby 00–03 obejmują siedmiokrotne włączanie i wyłączanie, liniowe przejścia, sinusoidalne efekty oraz sekwencyjne odtwarzanie wszystkich programów.
Podsumowanie AI na podstawie dyskusji. Może zawierać błędy.
REKLAMA
Słuchaj:
  • :smile: Ponad 10 lat temu Gerhard Schmidt DG4FAC na stronie avr asm tutorial.net (strona już nie istnieje) :cry: zaprezentował taki oto układ :idea: efekt LED oparty na ATtiny13

    Schemat obwodu LED z mikrokontrolerem ATtiny13 i czterema przyciskami

    
    ;
    ; ***********************************
    ; *    Ledlight with an ATtiny13    *
    ; * (C)2012 by avr-asm-tutorial.net *
    ; ***********************************
    ;
    .nolist
    .include "tn13def.inc"
    .list
    ;
    ; *******************
    ;   H A R D W A R E
    ; *******************
    ;
    ;          ____________
    ;         /            |
    ; RES o--|             |--o VCC
    ;        |     AT      |
    ;  S3 o--|             |--o S2/SCK
    ;        |    tiny     |
    ;  S4 o--|             |--o OUT/MISO
    ;        |     13      |
    ; GND o--|             |--o S1/MOSI
    ;        |_____________|
    ;
    ; Input port bits
    .equ bS1In = 0
    .equ bS2In = 2
    .equ bS3In = 3
    .equ bS4In = 4
    ;
    ; Output port bit
    .equ bOut = 1
    ;
    ; *******************************
    ;  H O W   T H I N G S   W O R K
    ; *******************************
    ;
    ; Processor:
    ;   Operates with 1.2 Mcs/s clock
    ;   Default R/C oscillator dived by 8
    ;   Default fuse settings
    ; Timer 0:
    ;   Operates as fast PWM with TOP=15
    ;   System clock prescaled by 256
    ;   f(PWM) = 293 c/s
    ;   OC0B controls PWM ratio (0 .. 15)
    ;     OCR0B set by lower nibble of control byte
    ;     sets OC0B output on restart,
    ;     clears output on compare match
    ;   OC0A sets TOP and interrupts
    ; Timing of cycles:
    ;   Upper nibble of control byte sets number
    ;     of PWM cycles (16 to 256)
    ;   Results in times between 0.055 and 0.88 seconds
    ; Input switches:
    ;   S1: if set dims down LED by half current (PWM / 2)
    ;   S2: accelerates speed by 16 (cycle duration / 16)
    ;   S3, S4: selects program
    ;     00: LEDs on and off seven times
    ;     01: linear up and down of LEDs
    ;     02: sinewave-type LEDs
    ;     03: anything from 00 to 03 in sequence
    ;
    ; *********************
    ;   R E G I S T E R S
    ; *********************
    ;
    ; Free: R0..R14
    .def rSreg = R15       ; for saving and restoring SREG
    .def rmp   = R16       ; multipurpose outside ints
    .def rimp  = R17       ; multipurpose inside ints
    .def rCnt  = R18       ; count register for PWM cycles
    .def rC3   = R19       ; counter for cycles in all-mode
    ; Free: R20 .. R29
    ; Used: ZH:ZL as Pointer to table in flash
    ;
    ; *******************************************
    ;  R E S E T   A N D   I N T - V E C T O R S
    ; *******************************************
    ;
          rjmp    main                   ; Reset vector
          reti                        ; INT0
           reti                         ; PCINT0
           rjmp    Tc0Int                   ; TIM0_OVF
           reti                         ; EE_RDY
           reti                         ; ANA_COMP
           reti                         ; TIM0_COMPA
           reti                         ; TIM0_COMPB
           reti                         ; WDT
           reti                         ; ADC
    ;
    ; Interrupt vector TIM0_OVF
    ;
    Tc0Int:
           in       rSreg,   SREG             ; save SREG
           dec    rCnt                   ; next PWM cycle
           brne    Tc0IntRet                ; if not zero, continue
           lpm    rCnt,   Z+                ; read from table in flash
           mov    rimp,   rCnt             ; copy byte to rimp
           andi    rimp,   0x0F             ; mask upper nibble
           sbis    PINB,   bS1In             ; half intensity?
           lsr    rimp                   ; half PWM cycle
           out    OCR0B,   rimp             ; write to PWM compare
           andi    rCnt,   0xF0             ; mask lower nibble
           sbis    PINB,   bS2In             ; double speed?
           swap    rCnt                   ; 16 times faster
    Tc0Int1:
           lpm    rimp,   Z                ; read next table value
           tst    rimp                   ; zero?
           brne    Tc0IntRet                ; not zero
           out    SREG,   rSreg             ; restore SREG
           set                         ; set T-flag
           reti                         ; return from int 
    Tc0IntRet:
           out    SREG,   rSreg             ; restore SREG
           reti                         ; return from int
    ;
    ; *************************************
    ;  M A I N   P R O G R A M   S T A R T
    ; *************************************
    ;
    Main:
     ; Init stack
           ldi    rmp,   LOW(RAMEND)       ; RAMEND to SPL
           out    SPL,   rmp
     ; Init ports
           ldi    rmp,   1<<bOut          ; Output port as output
           out    DDRB,   rmp
           ldi    rmp,   0x1F-(1<<bOut)       ; Switches pull-up, LEDs on
           out    PORTB,   rmp
     ; init Z-Pointer
           ldi    ZH,      HIGH(2*Tab1)       ; Point Z to Tab1
           ldi    ZL,      LOW (2*Tab1)
           ldi    rCnt,   1                ; counter stage 1
     ; init Timer 0, Fast PWM, COMPB as positive PWM 
           ldi    rmp,   0x0F             ; Compare A sets TOP
           out    OCR0A,   rmp
           ldi    rmp,   0x00             ; Compare B to LED off
           out    OCR0B,   rmp
           ldi    rmp,   (1<<COM0B1)|(1<<WGM01)|(1<<WGM00) ; Fast PWM
           out    TCCR0A,   rmp
           ldi    rmp,   (1<<WGM02)|(1<<CS02); Presc=256
           out    TCCR0B,   rmp
           ldi    rmp,   1<<TOIE0          ; int on TOP
           out    TIMSK0,   rmp
     ; init sleep and interrupts
           ldi    rmp,   1<<SE             ; enable sleep mode idle
           out    MCUCR,   rmp
           sei                         ; enable interrupts
    ;
    ; *******************
    ;  M A I N   L O O P
    ; *******************
    ;
    Loop:
           sleep                         ; go to sleep
           nop
           brtc    Loop                   ; nothing to do, go to sleep again
           clt                         ; clear flag
           in       rmp,   PINB             ; read switches
           andi    rmp,   0x18             ; mask all switches other than S3+S4
           brne    Loop2                  ; program is 4
          inc    rC3
          inc    rC3
          cpi    rC3,   7                ; beyound limit
          brcs    Loop1
          clr    rC3
    Loop1:
          ldi    ZH,      HIGH(2*TabPtr)       ; point to pointer table
          ldi    ZL,      LOW (2*TabPtr)
          add    ZL,      rC3             ; add displacement
          ldi    rmp,   0                ; MSB correct? 
          adc    ZH,      rmp
          lpm    rmp,   Z+                ; Read table address
          lpm    ZH,      Z
          mov    ZL,      rmp
          rjmp    Loop
    Loop2:                               ; read switches
          lsr    rmp                   ; divide by 2
          lsr    rmp                   ; divide by 4
          ldi    ZH,      HIGH(2*TabPtr)       ; pointer to pointer table
          ldi    ZL,      LOW (2*TabPtr)
          add    ZL,      rmp             ; add displacement
          ldi    rmp,   0                ; MSB correct?
          adc    ZH,      rmp
          lpm    rmp,   Z+
          lpm    ZH,      Z
          mov    ZL,      rmp
          rjmp    Loop
    ;
    ; Table pointers
    ;
    TabPtr: 
     .dw 2*Tab1                         ; program 4, start with program 1
     .dw 2*Tab3                         ; dto., program 3
     .dw 2*Tab2                         ; dto., program 2
     .dw 2*Tab1                         ; point to table of program 1
    ;
    ; Tables for programs
    ;
    Tab1:
     .dw 0xFFF0                         ; off and on
     .dw 0xFFF0
     .dw 0xFFF0
     .dw 0xFFF0
     .dw 0xFFF0
     .dw 0xFFF0
     .dw 0xFFF0
     .dw 0xFFF0
     .dw 0xFFF0
     .dw 0x0000                         ; end
    Tab2:                               ; Modulated Up/Down
     .dw 0xA0C1
     .dw 0xA1C2
     .dw 0xA2C3
     .dw 0xA3C4
     .dw 0xA4C5
     .dw 0xA5C6
     .dw 0xA6C7
     .dw 0xA7C8
     .dw 0xA8C9
     .dw 0xA9CA
     .dw 0xAACB
     .dw 0xABCC
     .dw 0xACCD
     .dw 0xADCE
     .dw 0xAECF
     .dw 0xAFCE
     .dw 0xAECD
     .dw 0xADCC
     .dw 0xACCB
     .dw 0xABCA
     .dw 0xAAC9
     .dw 0xA9C8
     .dw 0xA8C7
     .dw 0xA7C6
     .dw 0xA6C5
     .dw 0xA5C4
     .dw 0xA4C3
     .dw 0xA3C2
     .dw 0xA2C1
     .dw 0xA1C0
     .dw 0xA0C1
     .dw 0xA1C2
     .dw 0xA2C3
     .dw 0xA3C4
     .dw 0xA4C5
     .dw 0xA5C6
     .dw 0xA6C7
     .dw 0xA7C8
     .dw 0xA8C9
     .dw 0xA9CA
     .dw 0xAACB
     .dw 0xABCC
     .dw 0xACCD
     .dw 0xADCE
     .dw 0xAECF
     .dw 0xAFCE
     .dw 0xAECD
     .dw 0xADCC
     .dw 0xACCB
     .dw 0xABCA
     .dw 0xAAC9
     .dw 0xA9C8
     .dw 0xA8C7
     .dw 0xA7C6
     .dw 0xA6C5
     .dw 0xA5C4
     .dw 0xA4C3
     .dw 0xA3C2
     .dw 0xA2C1
     .dw 0xA1C0
     .dw 0x0000
    Tab3:
     .dw 0xC1C0                         ; linear up/down
     .dw 0xC3C2
     .dw 0xC5C4
     .dw 0xC7C6
     .dw 0xC9C8
     .dw 0xCBCA
     .dw 0xCDCC
     .dw 0xCFCE
     .dw 0xCDCE
     .dw 0xCBCC
     .dw 0xC9CA
     .dw 0xC7C8
     .dw 0xC5C6
     .dw 0xC3C4
     .dw 0xC1C2
     .dw 0xC1C0                         ; restart
     .dw 0xC3C2
     .dw 0xC5C4
     .dw 0xC7C6
     .dw 0xC9C8
     .dw 0xCBCA
     .dw 0xCDCC
     .dw 0xCFCE
     .dw 0xCDCE
     .dw 0xCBCC
     .dw 0xC9CA
     .dw 0xC7C8
     .dw 0xC5C6
     .dw 0xC3C4
     .dw 0xC1C2
     .dw 0x00C0
    TabEnd:
    ;
    ; End of source code
    ;
    .db "(C)2012 by Gerhard Schmidt",0x00,0x00
    .db "C(2)10 2ybG reahdrS hcimtd",0x00,0x00
    
    

    😊 Wzorując się na nim zrobiłem swoją wersje z uniwersalnej płytki (moje DIY) z attiny13, trazystora na pająku oraz gwiazdy z diodami 🛠️

    Zbliżenie na układ DIY z przewodami i płytką z ATtiny13

    DIY płytka z mikrokontrolerem ATTiny13 i bateria litowo-polimerowa na tle stołu

    
    :020000020000FC
    :100000001DC01895189506C018951895189518953F
    :1000100018951895FFB62A9579F42591122F1F701F
    :10002000B09B169519BD207FB29B22951491112388
    :1000300019F4FFBE68941895FFBE18950FE90DBF1F
    :1000400002E007BB0DE108BBF0E0E0EB21E00FE0D0
    :1000500006BF00E009BD03E20FBD0CE003BF02E0F4
    :1000600009BF00E205BF789488950000EEF7E89498
    :1000700006B3087171F433953395373008F03327A0
    :10008000F0E0E8EAE30F00E0F01F0591F491E02FC3
    :10009000EBCF06950695F0E0E8EAE00F00E0F01FF0
    :1000A0000591F491E02FE0CFB0003E01C400B00014
    :1000B000F0FFF0FFF0FFF0FFF0FFF0FFF0FFF0FFC8
    :1000C000F0FF0000C1A0C2A1C3A2C4A3C5A4C6A5DD
    :1000D000C7A6C8A7C9A8CAA9CBAACCABCDACCEAD80
    :1000E000CFAECEAFCDAECCADCBACCAABC9AAC8A952
    :1000F000C7A8C6A7C5A6C4A5C3A4C2A3C1A2C0A1C0
    :10010000C1A0C2A1C3A2C4A3C5A4C6A5C7A6C8A7AF
    :10011000C9A8CAA9CBAACCABCDACCEADCFAECEAF21
    :10012000CDAECCADCBACCAABC9AAC8A9C7A8C6A72F
    :10013000C5A6C4A5C3A4C2A3C1A2C0A10000C0C1DA
    :10014000C2C3C4C5C6C7C8C9CACBCCCDCECFCECD1D
    :10015000CCCBCAC9C8C7C6C5C4C3C2C1C0C1C2C34B
    :10016000C4C5C6C7C8C9CACBCCCDCECFCECDCCCBEB
    :10017000CAC9C8C7C6C5C4C3C2C1C0002843293242
    :100180003031322062792047657268617264205391
    :1001900063686D696474000043283229313020326D
    :1001A0007962472072656168647253206863696D83
    :0401B0007464000073
    :00000001FF
    

    🎥



    🎅 Btw Szkoda że strony znikają z netu :cry: :cry: :cry: Ostatnio zniknął też khoam 👀 mam nadzieję że ma szanse jeszcze do nas wrócić 😇

    Fajne? Ranking DIY
    O autorze
    _ACeK_
    Poziom 15  
    Offline 
    _ACeK_ napisał 204 postów o ocenie 222, pomógł 7 razy. Jest z nami od 2024 roku.
  • REKLAMA
  • #2 21773292
    Urgon
    Poziom 38  
    Posty: 7295
    Pomógł: 197
    Ocena: 2636
    AVE...

    Ja takie rzeczy robiłem w C, w kilku linijkach kodu. Generalnie assembler jest okej, jak trzeba liczyć każdy cykl zegarowy. Ale generalnie pisać wypada w C, na przykład. Języki wysokiego poziomu łatwiej portować między platformami - w przypadku mikrokontrolerów zwykle ogranicza się to do zmiany nazw rejestrów i niekiedy wartości w tych rejestrach. Kompilatory są teraz tak dobre, że kod z C do maszynowego jest wydajnie konwertowany. Jak ktoś chce, to może ustawić kompilator by generował też pośredni kod źródłowy ASM by sobie podejrzeć, jak sprawnie kompilator kompiluje...

    Wiele starych, nieistniejących stron jest dostępnych przez Archive.org. Ja tam kilka lat temu znalazłem zaginioną stronę o złodziejach dżuli, która nie istnieje od ponad dekady, i zapisałem sobie do PDFa...
  • REKLAMA
  • #3 21773564
    gulson
    Administrator Systemowy
    Posty: 29526
    Pomógł: 150
    Ocena: 6123
    Piękne czasy, piękny kod napisany przez człowieka w assemblerze a nie wygenerowany. Dzięki za podzielenie się zapomnianym rozwiązaniem. Niech trwa wiecznie.
  • REKLAMA
  • #4 21773896
    robgold
    Poziom 23  
    Posty: 726
    Pomógł: 10
    Ocena: 290
    @Urgon pozwolę się nie zgodzić z Tobą. Dziś również krytyczne rzeczy czasowo generuje się w ASM na dany procek i nie jest to jakiś problem. Nie mowie tu o projektach mało wolumenowych ale tam gdzie liczy się każdy cent i nie wsadzisz zawsze mocniejszego procka. Na studiach pisało się prawie wszystko w ASM na '51 i działało. Takie były czasy, ja też wolałem potem pisać w C w AVR Studio lub MPLABa niż zakichane Platforimio czy Arduino ale takie czasy.

    @gulson dziś chyba coraz trudniej przy takiej ilości kodu nie korzystać z AI. Tym bardziej, że przy tych darmowych i tak trzeba wiedzieć co Ci generują, jak działa inaczej masę bzdur dostaniesz. Oczywiście można mówić stanowcze "nie" ale to jak próba zaklinania rzeczywistości, że nie będziesz używać smartphona.
  • #5 21773929
    Urgon
    Poziom 38  
    Posty: 7295
    Pomógł: 197
    Ocena: 2636
    AVE...

    No ale teraz na studiach raczej uczy się programowania ARM w C++, a nie '51 w ASM. Jak pisałem wcześniej, ASM jest dobry tam, gdzie trzeba liczyć każdy cykl zegarowy. Generalnie sam programuję w C, ale raz czy dwa musiałem mieć wstawkę ASM, bo do edytowania pamięci programu wymagana jest precyzyjna sekwencja instrukcji. Generalnie jednak poza tym szczególnym przypadkiem nie miałem sytuacji, by programowanie w assemblerze było potrzebne. A celowo sięgam zazwyczaj po mniejsze mikrokontrolery, jak PIC10F322...
Słuchaj:
REKLAMA