; Oster-Contest 2013
;
; servo1: 1 ms-2 ms / 50Hz (futaba 0,6-2,4ms)
;
; Das Poti/ADC(2) wird per Interrupt in r16 geholt.
; Das verbraucht etwa 20% der Gesammtzeit.
; Dadurch sind die Zeiten nur ungefähr berechenbar.
;
; Mit PB.1=1 wird r18 einmal durchgezählt (0-255), um den Pulsanfang von 0,8ms zu erzeugen,
; dann wird r18 noch einmal durchgezählt und mit r16(adc) verglichen,
; bei Übereinstimmung wird PB.1 auf 0 gesetzt,
; nun sind 2,3ms vergangen und die Rest-Pause (17,7ms) beginnt.
;
; das Ganze funktioniert nur bei 1,2MHz
;
; Lock FF, Fuse 6A = 0b0110_1010, Fusehigh FF
; devide=^ ^^^^=9,6MHz
;
; ATMEL ATtiny13
; _____ _____
; | |_| |
; o-|Res Vcc|-------o +5V
; | |
; | |
; | sck|
; o-|PB3 PB2|-o
; |ADC3 ADC1|
; | | |-o Servo schwarz
; ___ | miso| +5V o Servo rot
; +-|___|---|PB4 PB1|-------o Servo gelb/braun
; | 1k |ADC2 oc0b|
; | | |
; _v_ | mosi|
; +5V o-|___|-----+-|Gnd PB0|-o
; 10k | | oc0a|
; Poti |--+ |_____________|
;
;
.DEVICE ATtiny13 ;für gavrasm, für Symbolische Registerbezeichnungen (z.B.'DDRB')
.cseg ;codesegment
.org 0 ;adr 0
;Vector-Tabelle
rjmp init ;Reset vector
reti ;Int0 interrupt vector
reti ;PCINT0 vector
reti ;TC0 overflow vector
reti ;Eeprom ready vector
reti ;Analog comparator int vector
reti ;TC0 CompA vector
reti ;TC0 CompB vector
reti ;WDT vector
rjmp int_adc ;ADC conversion complete vector
;--------------------------------
Int_adc: ;Aufruf NUR, wenn neuer Wert verfügbar
in r16,ADCh ;Lese ADC-Wert, obere 8Bit
reti ;zurück ins Hauptprogramm
;--------------------------------
init: ;Vorbereitungen
ldi r16,ramend ;Stack vorbereiten
out spl,r16 ;auf RAMEND setzen
sbi ddrb,1 ;Ausgang definieren
init_adc: ;
ldi r16,0b00100010 ; - 0 1 - - - 1 0
Out Admux , R16 ;ref-^ ^adlar ^+^-adc2
ldi r16,0b00000000 ; - - - - - 0 0 0
Out Adcsrb , R16 ; ^+^+^-Free Run
ldi r16,0b11101111 ; 1 1 1 0 1 1 1 1
Out Adcsra , R16 ;ena-^ ^-start ^+^+^-prescale
sei ;Set Enable Interrupt (-Flag)
;--------------------------------
main: ;Hauptprogramm
sbi portb,1 ;Pulsanfang (1Cy) nur einmal
main0: ;Offset (us ~ 256 * 3Cy) ungefähr 768us
inc r18 ;0-255-0 (1Cy)
brbc 1,main0 ;springe wenn Z=0 (2Cy)
;------------------------
main1: ;+ adc * 6Cyclen (us ~ 256 * 6Cy) ungefähr 1536us
cpse r16,r18 ;skip if R18=adc ? (1Cy)
rjmp main2 ;nein, weiterzählen (2Cy)
cbi portb,1 ;ja, Pulsende (1Cy) nur einmal
main2: ;zählen
inc r18 ;0-255-0 (1Cy)
brbc 1,main1 ;springe wenn Z=0 (2Cy)
;------------------------
ldi r25,79 ;pausenlänge (256-79)*256/8 (1Cy) nur einmal
main3: ;17,7 ms (us ~ (256-79) * 100) ungefähr 17700us
adiw r24,8 ;step 8 (2Cy)
brbc 1,main3 ;springe wenn Z=0 (2Cy)
rjmp main ;nochmal (2Cy) nur einmal
;end
; 2013-Oster-Contest, Servo-Tester2 in Stufen von 121us
;
; PWM-Modul für 1,2MHz (für 4,8MHz prescaler auf 256 erhöhen)
;--------------------------------
; ocr0a ~ 193 ~ 1,2MHz / 64prescaler / 2phase / 50 Hz (= 188)
; ocr0b ~ 121us * n
;--------------------------------
; Fuse 0b0110_1010
; devide=^ ^^^^=9,6MHz
;--------------------------------
.DEVICE ATtiny13 ; für gavrasm
.cseg ; codesegment
.org 0 ; adr 0
;--------------------------------
init: ; Vorbereitungen
sbi ddrb,1 ; Ausgang definieren
;--------------------------------
init_pwm: ; Mode 5
ldi r16,0b00100001 ; 0 0 1 0 - - 0 1
Out Tccr0a , R16 ; A-^-^ ^-^-B ^+^=PWM clear OC0B on compare
ldi r16,0b00001011 ; 0 0 - - 1 0 1 1
Out Tccr0b , R16 ; PWM-^ ^+^+^-prescale
ldi r16,193 ; 193 => 50Hz
out ocr0a,r16 ;
; neue Werte müssen nur einmal im Hauptprogramm geladen werden
ldi r16,12 ; n = t / 121us
Out Ocr0b,R16 ; lade OCR0B = 12 => 1,5ms
;--------------------------------
main: ; Hauptprogramm
rjmp main ;
;--------------------------------
;end
;===============================================================================================
;
; Oster-Contest: Servo (-Tester) 3 oder Voltmeter für Schwersichtige
;
;===============================================================================================
;
; ATtiny13
; _____ _____
; | |_| | 1N4148 /
; |Res Vcc|-------+---|<|---+-o o-o +4,5V-6V
; | | | |
; | | --- C1 |
; | sck| --- 1u |
; +-----|PB3 PB2|-----+ | |
; | | | | | |
; | | | | | |
; | | miso| | | |
; | +---|ADC2 PB1|---+ | | |
; | | | | | | | |
; | | | | | | | |
; | | | mosi| | | | |
; | | +-|Gnd PB0|-+ | | | |
; | | | |_____________| | | | | |
; | | o--o--o--o--o--o--|-|-|-+ schwarz |
; | | o--o--o--o--o--o--|-|-|-----------+ rot
; | +-o o o o o-----+ | | gelb
; +------+ | +----------+ |
; +---------------+
; B4 B3 B2 B1 B0 Batt
;
;
; ALLE GND-Anschlüsse MÜSSEN (sternförmig) auf kürzestem Weg am Pin 4 zusammenlaufen,
; um keine Spannungsabfälle auf ADC(2) zu übertragen.
;
; Die Skala wird mit einem DVM geeicht
;===============================================================================================
; ADC(2)=PB.4 wird per Interrupt in r16 geholt. Uref auf 1,1V eingestellt
; ist ADC=255 wird die Clipping-LED=PB.2 eingeschaltet
;
; Zuerst wird r18 mit dem Startwert für Rechtsanschlag geladen und bis 0 herunter gezählt (main0) ~ 600us
;
; dann wird r18 herunter gezählt (255-0) und mit r16(adc) verglichen,
; bei Übereinstimmung wird PB.1 auf 0 gesetzt, Pausenanfang (main1+2) ~ 2000us
; # durch hinzufügen/entfernen eines NOP wird der Gesamtwinkel (165°) bestimmt.
;
; nun sind ~ 2,6ms vergangen und die Rest-Pause beginnt. (main3) ~ 17400us
; nur in main3 wird der ADC-Int erlaubt, um das zappeln zu verringern.
; ggf. kann ein 100nF am ADC gegen GND das zappeln weiter verringern.
;===============================================================================================
; das Ganze funktioniert nur bei 1,2MHz
; Fuse 0b0110_1010
; devide=^ ^^^^=9,6MHz
;===============================================================================================
.DEVICE ATtiny13 ; für gavrasm
.cseg ; codesegment
.org 0 ; adr 0
rjmp init ; Reset vector
reti ; Int0 interrupt vector
reti ; PCINT0 vector
reti ; TC0 overflow vector
reti ; Eeprom ready vector
reti ; Analog comparator int vector
reti ; TC0 CompA vector
reti ; TC0 CompB vector
reti ; WDT vector
rjmp int_adc ; ADC conversion complete vector
;--------------------------------
Int_adc: ; Aufruf NUR, wenn neuer Wert verfügbar
in r16,ADCh ; Lese ADC-Wert, obere 8Bit
sbi portb,3 ; Clip on
cpse r16,r17 ; skip if adc=r17 ? (1Cy)
cbi portb,3 ; Clip off
reti ; zurück ins Hauptprogramm
;--------------------------------
init: ldi r16,0b00001010 ; Ausgaang definieren
out ddrb,r16 ;
ldi r17,255 ; clipping-Wert
init_adc: ;
ldi r16,0b01100010 ; - 1 1 - - - 1 0
Out Admux , R16 ; ref-^ ^adlar ^+^-adc2
ldi r16,0b00000000 ; - - - - - 0 0 0
Out Adcsrb , R16 ; ^+^+^-Free Run
ldi r16,0b11101110 ; 1 1 1 0 1 1 1 1
Out Adcsra , R16 ; ena-^ ^-start ^+^+^-prescale
;--------------------------------
main: cli ; verbiete Interrupts (1Cy) nur einmal
sbi portb,1 ; Pulsanfang (1Cy) nur einmal
ldi r18,208 ; offset k (rechts) (1Cy) nur einmal
main0: dec r18 ; 0->255->0 (1Cy)
brbc 1,main0 ; springe wenn Z=0 (2Cy) us ~ k * 3 Cy
;--------------------------------
main1: dec r18 ; fang mit 255 an ->0 (1Cy)
cpse r16,r18 ; skip if R18=adc ? (1Cy)
rjmp main2 ; nein, weiterzählen (2Cy)
cbi portb,1 ; ja, Pulsende (2Cy) nur einmal
main2: nop ; # 165°-Anpassung # (1Cy)
nop ; # Winkel # (1Cy)
brbc 1,main1 ; Puls+Pause (2Cy) us ~ 256 * 8Cy
;--------------------------------
sei ; erlaube adc-Int (1Cy) nur einmal
ldi r25,17 ; pause k (1Cy) nur einmal
main3: sbiw r24,1 ; dec (2Cy)
brbc 1,main3 ; springe wenn Z=0 (2Cy) us ~ 256 * k * 4Cy
rjmp main ; nochmal (2Cy) nur einmal
;===============================================================================================
;end