- Labornetzteil AliExpress         
Seite 2 von 2 ErsteErste 12
Ergebnis 11 bis 17 von 17

Thema: Problem mit Mittelwertberechnung (Atmega8)

  1. #11
    Neuer Benutzer Öfters hier
    Registriert seit
    25.06.2007
    Beiträge
    9
    Anzeige

    LiFePo4 Akku selber bauen - Video
    CPI hat geholfen! blöder fehler
    Vielen Dank für die Hilfe!!!
    Ich hab nur grad das nächste Problem. Die Werte sind jetzt einigermaßen in Ordnung aber die Hysterese macht immer noch nicht was sie soll. Auch wenn die Werte genau dazwischen liegen kommt es vor dass die Ausgänge mal aus- und mal eingeschaltet werden. Kann es sein das irgenwelche anderen Eingänge stören?
    Terminalprogramm hab ich. Zeigt die Werte als Punkte in einem Diagramm von 0-255 an.

  2. #12
    Erfahrener Benutzer Robotik Einstein Avatar von wkrug
    Registriert seit
    17.08.2006
    Ort
    Dietfurt
    Beiträge
    2.232
    Auch wenn die Werte genau dazwischen liegen kommt es vor dass die Ausgänge mal aus- und mal eingeschaltet werden. Kann es sein das irgenwelche anderen Eingänge stören?
    Sind alle benötigten Kondensatoren an deinem Spannungsregler vorhanden ?
    Hast Du den VCC Pin mit einem Kondensator entkoppelt ?
    Hast Du die AVCC mit Drossel und Kondensator entkoppelt ?
    Benutzt Du die interne 2,56V Referenz - hast Du den AREF Pin mit 100nF entkoppelt ?
    Hast Du AGND und GND (DGND) auf der Platine eigens geroutet und die beiden Signale nur an einem Punkt (z.B. beim Spannungsregler) miteinander verbunden ?
    Hast Du eine sternförmige Masseverbindung bei deinem Layout ?
    Hast Du für deine Verbraucher die etwas mehr Strom ziehen eigene Leiterbahnen zum gemeinsamen Massepunkt vorgesehen ?
    Hast Du andere Taktquellen NE555 oder MAX232 mit Drosseln entkoppelt ?

    Das alles könnten Gründe für dein Problem sein.

  3. #13
    Neuer Benutzer Öfters hier
    Registriert seit
    25.06.2007
    Beiträge
    9
    Also bis auf die separate und sternförmige Masse kann ich eigentlich alles ausschließen. Ich benutze eine externe Referenzspannung 3,3V.
    Um weitere Layoutfehler auszuschließen hab ich alles nochmal auf dem myAVR experimentierboard gesteckt. Hab jetzt nochmal alles unnötige aus dem Code genommen und die Hysterese etwas vereinfacht. Ändert aber nix.

    Code:
    ;+----------------------------------------------------------------------
    ;| Title : myAVR Grundgerüst für ATmega8
    ;+----------------------------------------------------------------------
    ;| Funktion : ...
    ;| Schaltung:
    ;eingänge: gehäuse temp portC5
    ; verdampfer temp 1 portC1
    ; verdampfer temp 2 portC2
    ; verdampfer temp 3 portC3
    ; verdampfer temp 4 portC4
    ; pumpsignal portC0
    ; leistungswahl 1 portB4
    ; leistungswahl 2 portB5
    ; fluidmangel portB3
    ;Ausgänge: pumpen1-2 portB1
    ; pumpen3-4 portB2
    ; lüfter portB0
    ; pumpen bereit1-2 portD2
    ; pumpen bereit3-4 portD3
    ; heizung 1 portD4
    ; heizung 2 portD5
    ; heizung 3 portD6
    ; heizung 4 portD7
    ;
    ;blinkreg: bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0
    ; "blinkbit" - - - - - - -
    ;
    ;heizreg: bit7 bit6 bit5 bit4 bit3 bit2
    ; - - - heizen m.4 heizen m.3 heizen m.2
    ;
    ;pumpreg: bit7 bit6 bit5 bit4 bit3
    ; pumpen möglich 4 1.pumpen möglich 4 p.m.3 1.p.m.3 p.m.2
    ;+----------------------------------------------------------------------
    ;| Prozessor : ATmega8
    ;| Takt : 3,6864 MHz
    ;| Sprache : Assembler
    ;| Datum : 30.06.2007
    ;| Version : 1.5
    ;| Autor : Ulrich Betz
    ;+----------------------------------------------------------------------
    .include "AVR.H"
    .equ blinkreg, 0x14 ;r20 als variable (register für blink
    .equ heizreg, 0x15 ;r21 als variable (register für heizf
    .equ pumpreg, 0x16 ;r22 als variable (register für pumpf
    .equ lotemp, 0x17 ;r23 als variable (untere temperatur)
    .equ midtemp, 0x18 ;r24 als variable (mitlere temperatur
    .equ hitemp, 0x19 ;r25 als variable (obere temperatur)
    ;------------------------------------------------------------------------
    ;Reset and Interrupt vector ;VNr. Beschreibung
    rjmp main ;1 POWER ON RESET
    reti ;2 Int0-Interrupt
    reti ;3 Int1-Interrupt
    reti ;4 TC2 Compare Match
    reti ;5 TC2 Overflow
    reti ;6 TC1 Capture
    reti ;7 TC1 Compare Match A
    reti ;8 TC1 Compare Match B
    reti ;9 TC1 Overflow
    rjmp ontimer ;10 TC0 Overflow
    hystereseversuch.s, Seite 1 von 8
    reti ;11 SPI, STC Serial Transfer Complet
    reti ;12 UART Rx Complete
    reti ;13 UART Data Register Empty
    reti ;14 UART Tx Complete
    reti ;15 ADC Conversion Complete
    reti ;16 EEPROM Ready
    reti ;17 Analog Comparator
    reti ;18 TWI (I²C) Serial Interface
    reti ;19 Store Program Memory Ready
    ;------------------------------------------------------------------------
    ;Start, Power ON, Reset
    main: ;initialisiere stack
    ldi r16,lo8(RAMEND)
    out SPL,r16
    ldi r16,hi8(RAMEND)
    out SPH,r16
    ;initialsiere I/O Register
    ldi r16, 0b00000111 ;portB5,B4,B3 als eingang portB2,B1,
    out DDRB, r16
    ldi r16, 0b00111000 ;pull up für portB5,B4,B3, ausgänge
    out PORTB, r16
    ldi r16, 0b11111100 ;portD7,D6,D5,D4,D3,D2 als ausgang
    out DDRD, r16
    ;initialisierung timer0
    ldi r16, 0b00000101 ;maskiere timer0
    out TCCR0, r16
    ldi r16, 0b00000001 ;konfiguriere
    out TIMSK, r16 ;interrupt auslösen
    ;initialisierung ADC
    ldi r16, 0b00000001 ;ADC channel 1
    out ADMUX, r16 ;portC1 ADC channel 1
    ldi r16, 0b10000101 ;ADC ein und 115KHz taktrate
    out ADCSRA, r16 ;single step
    ;initialisierung UART
    sbi UCSRB, 3 ;TX aktivieren
    ldi r16, 23
    out UBRRL, r16 ;baudrate 9600 einstellen
    ;Temperatur Vergleichswerte (Schaltpunkte)
    ldi lotemp, 140 ;unterer schaltpunkt
    ldi midtemp, 180 ;mitlerer schaltpunkt
    ldi hitemp, 240 ;oberer schaltpunkt
    ldi pumpreg, 0
    ldi heizreg, 0
    ldi r18, 0
    ldi r19, 0
    sei
    ;------------------------------------------------------------------------
    mainloop:
    sbis PINB, 4 ;skip wenn LWahl-1 nicht gewählt B4=l
    rjmp tempabfr12
    cbi PORTD, 4 ;heizen 1 off
    cbi PORTD, 5 ;heizen 2 off
    cbi PORTB, 1 ;pumpen 1-2 off
    cbi PORTD, 2 ;pumpen 1-2 led off
    rjmp LWahl2
    tempabfr12: rcall tempabfrage12 ;unterprogrammaufruf
    sbis PINB, 3 ;skip wenn kein fluidmangel B3=logisc
    rjmp pump12off
    sbrs pumpreg, 0 ;skip wenn 1pumpen 1 möglich
    rjmp pump12off
    sbrs pumpreg, 1 ;skip wenn pumpen 1 möglich
    hystereseversuch.s, Seite 2 von 8
    rjmp pump12off
    sbrs pumpreg, 2 ;skip wenn 1pumpen 2 möglich
    rjmp pump12off
    sbrs pumpreg, 3 ;skip wenn pumpen 2 möglich
    rjmp pump12off
    ;rcall pump12
    rjmp LWahl2
    pump12off: cbi PORTD, 2 ;portD2 logisch 0 , "1-2 bereit led"
    cbi PORTB, 1 ;pumpen 1-2 off
    LWahl2: sbis PINB, 5 ;skip wenn LWahl-2 nicht gewählt B5=l
    rjmp tempabfr34
    cbi PORTD, 6 ;heizen 3 off
    cbi PORTD, 7 ;heizen 4 off
    cbi PORTB, 2 ;pumpen 3-4 off
    cbi PORTD, 3 ;pumpen 3-4 led off
    rjmp mainloop
    tempabfr34: rcall tempabfrage34 ;unterprogrammaufruf
    sbis PINB, 3 ;skip wenn kein fluidmangel B3=logisc
    rjmp pump34off
    sbrs pumpreg, 4 ;skip wenn 1pumpen 3 möglich
    rjmp pump34off
    sbrs pumpreg, 5 ;skip wenn pumpen 3 möglich
    rjmp pump34off
    sbrs pumpreg, 6 ;skip wenn 1pumpen 4 möglich
    rjmp pump34off
    sbrs pumpreg, 7 ;skip wenn pumpen 4 möglich
    rjmp pump34off
    ;rcall pump34
    rjmp mainloop
    pump34off: cbi PORTD, 3 ;portD3 logisch 0 , "3-4 lereit led"
    cbi PORTB, 2 ;pumpen 3-4 off
    rjmp mainloop
    ;------------------------------------------------------------------------
    tempabfrage12:
    push r16
    push r17
    lds r16, 0x61 ;Twert1 aus sram laden
    lds r17, 0x62 ;Twert2 aus sram laden
    cp r16, hitemp
    brlo heizenon
    cbi PORTD, 4
    rjmp ende1
    heizenon: cp r16, midtemp
    brsh ende1
    sbi PORTD, 4
    ende1: cp r17, hitemp
    brlo heizenon2
    cbi PORTD, 5
    rjmp ende2
    heizenon2: cp r17, midtemp
    brsh ende2
    sbi PORTD, 5
    ende2: pop r16
    pop r17
    ret
    ;-------------------------------------------------------------------------
    tempabfrage34:
    push r16
    push r17
    lds r16, 0x63 ;Twert3 aus sram laden
    lds r17, 0x64 ;Twert4 aus sram laden
    hystereseversuch.s, Seite 3 von 8
    cp r16, hitemp
    brlo heizenon3
    cbi PORTD, 6
    rjmp ende3
    heizenon3: cp r16, midtemp
    brsh ende3
    sbi PORTD, 6
    ende3: cp r16, hitemp
    brlo heizenon4
    cbi PORTD, 7
    rjmp ende4
    heizenon4: cp r16, midtemp
    brsh ende4
    sbi PORTD, 7
    ende4: pop r16
    pop r17
    ret
    ;----------------------------------------------------------------------------
    ;
    ;versuchstext
    ontimer:
    ;Twert1 einlesen
    wertelesen: push r16
    push r20
    ldi r20, 0
    loop0: inc r20 ;zähler +1
    ldi r16, 0b00000000 ;ADC channel 0
    out ADMUX, r16 ;portC1 ADC channel 0
    sbi ADCSRA, 6 ;starte nächste konvertierung
    warten0: sbis ADCSRA, 4 ;skip wenn AD conversion abgeschlosse
    rjmp warten0
    in r26, ADCL ;low-teil auslesen
    in r27, ADCH ;high-teil auslesen
    add r18, r26
    adc r19, r27
    cpi r20, 16 ;zähler =16?
    brne loop0 ;wenn nicht dann geh zu loop0
    ;wert durch 16 teilen
    clc ;carry flag löschen
    ror r19 ;high byte durch zwei teilen, übertra
    ror r18 ;carry links einschieben und durch zw
    clc ;carry für nächste teilung löschen
    ror r19
    ror r18
    clc
    ror r19
    ror r18
    clc
    ror r19
    ror r18
    clc
    ;.................... ;10 bit zu 8 bit auflösung, alle bits
    asr r19 ;schiebe bit 0 des high-teils ins C-F
    ror r18 ;schiebe alle bits nach rechts, C-Fla
    hystereseversuch.s, Seite 4 von 8
    asr r19 ;schiebe nächstes bit des high teils
    ror r18 ;schiebe alle bits nach rechts, C-Fla
    sts 0x60, r18 ;r18 in sram speichern
    ;werte senden
    putChar0: sbis UCSRA, 5 ;bit 5 = UDR empty
    rjmp putChar0 ;warten bis UDR bereit
    out UDR, r18 ;senden
    ;werte senden ende
    ldi r18, 0 ;werteregister lo-teil zurücksetzen
    ldi r19, 0 ;werteregister hi-teil zurücksetzen
    ldi r20, 0 ;zähler zurücksetzen
    loop1: inc r20 ;zähler +1
    ldi r16, 0b00000001 ;ADC channel 1
    out ADMUX, r16 ;portC1 ADC channel 1
    sbi ADCSRA, 6 ;starte nächste konvertierung
    warten1: sbis ADCSRA, 4 ;skip wenn AD conversion abgeschlosse
    rjmp warten1
    in r26, ADCL ;low-teil auslesen
    in r27, ADCH ;high-teil auslesen
    add r18, r26
    adc r19, r27
    cpi r20, 16 ;zähler =16?
    brne loop1 ;wenn nicht dann geh zu loop0
    ;wert durch 16 teilen
    clc ;carry flag löschen
    ror r19 ;high byte durch zwei teilen, übertra
    ror r18 ;carry links einschieben und durch zw
    clc ;carry für nächste teilung löschen
    ror r19
    ror r18
    clc
    ror r19
    ror r18
    clc
    ror r19
    ror r18
    clc
    ;.................... ;10 bit zu 8 bit auflösung, alle bits
    asr r19 ;schiebe bit 0 des high-teils ins C-F
    ror r18 ;schiebe alle bits nach rechts, C-Fla
    asr r19 ;schiebe nächstes bit des high teils
    ror r18 ;schiebe alle bits nach rechts, C-Fla
    sts 0x61, r18 ;r18 in sram speichern
    ;werte senden
    putChar1: sbis UCSRA, 5 ;bit 5 = UDR empty
    rjmp putChar1 ;warten bis UDR bereit
    out UDR, r18 ;senden
    ;werte senden ende
    ldi r18, 0 ;werteregister lo-teil zurücksetzen
    ldi r19, 0 ;werteregister hi-teil zurücksetzen
    ldi r20, 0 ;zähler zurücksetzen
    loop2: inc r20 ;zähler +1
    ldi r16, 0b00000010 ;ADC channel 2
    out ADMUX, r16 ;portC2 ADC channel 2
    hystereseversuch.s, Seite 5 von 8
    sbi ADCSRA, 6 ;starte nächste konvertierung
    warten2: sbis ADCSRA, 4 ;skip wenn AD conversion abgeschlosse
    rjmp warten2
    ;Twert2 einlesen
    in r26, ADCL ;low-teil auslesen
    in r27, ADCH ;high-teil auslesen
    add r18, r26
    adc r19, r27
    cpi r20, 16 ;zähler =16?
    brne loop2 ;wenn nicht dann geh zu loop2
    ;wert durch 16 teilen
    clc ;carry flag löschen
    ror r19 ;high byte durch zwei teilen, übertra
    ror r18 ;carry links einschieben und durch zw
    clc ;carry für nächste teilung löschen
    ror r19
    ror r18
    clc
    ror r19
    ror r18
    clc
    ror r19
    ror r18
    clc
    ;.................... ;10 bit zu 8 bit auflösung, alle bits
    asr r19 ;schiebe bit 0 des high-teils ins C-F
    ror r18 ;schiebe alle bits nach rechts, C-Fla
    asr r19 ;schiebe nächstes bit des high teils
    ror r18 ;schiebe alle bits nach rechts, C-Fla
    sts 0x62, r18 ;r26 in sram speichern
    ;werte senden
    putChar2: sbis UCSRA, 5 ;bit 5 = UDR empty
    rjmp putChar2 ;warten bis UDR bereit
    out UDR, r18 ;senden
    ;werte senden ende
    ldi r18, 0 ;werteregister lo-teil zurücksetzen
    ldi r19, 0 ;werteregister hi-teil zurücksetzen
    ldi r20, 0 ;zähler zurücksetzen
    loop3: inc r20 ;zähler +1
    ldi r16, 0b00000011 ;ADC channel 3
    out ADMUX, r16 ;portC3 ADC channel 3
    sbi ADCSRA, 6 ;starte nächste konvertierung
    warten3: sbis ADCSRA, 4 ;skip wenn AD conversion abgeschlosse
    rjmp warten3
    ;Twert3 einlesen
    in r26, ADCL ;low-teil auslesen
    in r27, ADCH ;high-teil auslesen
    add r18, r26
    adc r19, r27
    cpi r20, 16 ;zähler =16?
    brne loop3 ;wenn nicht dann geh zu loop2
    ;wert durch 16 teilen
    clc ;carry flag löschen
    ror r19 ;high byte durch zwei teilen, übertra
    ror r18 ;carry links einschieben und durch zw
    clc ;carry für nächste teilung löschen
    ror r19
    ror r18
    hystereseversuch.s, Seite 6 von 8
    clc
    ror r19
    ror r18
    clc
    ror r19
    ror r18
    clc
    ;.................... ;10 bit zu 8 bit auflösung, alle bits
    asr r19 ;schiebe bit 0 des high-teils ins C-F
    ror r18 ;schiebe alle bits nach rechts, C-Fla
    asr r19 ;schiebe nächstes bit des high teils
    ror r18 ;schiebe alle bits nach rechts, C-Fla
    sts 0x63, r18 ;r26 in sram speichern
    ;werte senden
    putChar3: sbis UCSRA, 5 ;bit 5 = UDR empty
    rjmp putChar3 ;warten bis UDR bereit
    out UDR, r18 ;senden
    ;werte senden ende
    ldi r18, 0 ;werteregister lo-teil zurücksetzen
    ldi r19, 0 ;werteregister hi-teil zurücksetzen
    ldi r20, 0 ;zähler zurücksetzen
    loop4: inc r20 ;zähler +1
    ldi r16, 0b00000100 ;ADC channel 4
    out ADMUX, r16 ;portC4 ADC channel 4
    sbi ADCSRA, 6 ;starte nächste konvertierung
    warten4: sbis ADCSRA, 4 ;skip wenn AD conversion abgeschlosse
    rjmp warten4
    ;Twert4 einlesen
    in r26, ADCL ;low-teil auslesen
    in r27, ADCH ;high-teil auslesen
    add r18, r26
    adc r19, r27
    cpi r20, 16 ;zähler =16?
    brne loop4 ;wenn nicht dann geh zu loop2
    ;wert durch 16 teilen
    clc ;carry flag löschen
    ror r19 ;high byte durch zwei teilen, übertra
    ror r18 ;carry links einschieben und durch zw
    clc ;carry für nächste teilung löschen
    ror r19
    ror r18
    clc
    ror r19
    ror r18
    clc
    ror r19
    ror r18
    clc
    ;.................... ;10 bit zu 8 bit auflösung, alle bits
    asr r19 ;schiebe bit 0 des high-teils ins C-F
    ror r18 ;schiebe alle bits nach rechts, C-Fla
    asr r19 ;schiebe nächstes bit des high teils
    ror r18 ;schiebe alle bits nach rechts, C-Fla
    sts 0x64, r18 ;r26 in sram speichern
    ;werte senden
    putChar4: sbis UCSRA, 5 ;bit 5 = UDR empty
    rjmp putChar4 ;warten bis UDR bereit
    out UDR, r18 ;senden
    hystereseversuch.s, Seite 7 von 8
    ;werte senden ende
    ldi r18, 0 ;werteregister lo-teil zurücksetzen
    ldi r19, 0 ;werteregister hi-teil zurücksetzen
    ldi r20, 0 ;zähler zurücksetzen
    ldi r16, 0b00000101 ;ADC channel 5
    out ADMUX, r16 ;portC5 ADC channel 5
    sbi ADCSRA, 6 ;starte nächste konvertierung
    warten5: sbis ADCSRA, 4 ;skip wenn AD conversion abgeschlosse
    rjmp warten5
    ;Twert5 einlesen
    in r26, ADCL ;low-teil auslesen
    in r27, ADCH ;high-teil auslesen
    ;.................... ;10 bit zu 8 bit auflösung, alle bits
    asr r27 ;schiebe bit 0 des high-teils ins C-F
    ror r26 ;schiebe alle bits nach rechts, C-Fla
    asr r27 ;schiebe nächstes bit des high teils
    ror r26 ;schiebe alle bits nach rechts, C-Fla
    sts 0x65, r26 ;r26 in sram speichern
    ;werte senden
    putChar5: sbis UCSRA, 5 ;bit 5 = UDR empty
    rjmp putChar5 ;warten bis UDR bereit
    out UDR, r26 ;senden
    ;werte senden ende
    pop r16
    pop r20
    reti
    hystereseversuch.s, Seite 8 von 8
    Angehängte Dateien Angehängte Dateien

  4. #14
    Erfahrener Benutzer Robotik Einstein Avatar von wkrug
    Registriert seit
    17.08.2006
    Ort
    Dietfurt
    Beiträge
    2.232
    Du benutzt in deiner ontimer Routine eine menge Register, ohne die Werte zu sichern.
    Ist das so OK ?
    In deiner ontimer Interuptroutine wird das SREG zwar verändert aber nicht gesichert.

    PUSH r16
    IN r16,SREG
    PUSH r16
    .....


    POP r16
    OUT SREG,r16
    POP r16

    Hatte schon mal ein Problem mit sowas.

  5. #15
    Neuer Benutzer Öfters hier
    Registriert seit
    25.06.2007
    Beiträge
    9
    Guter Tip!
    Bei der gekürzten Codeversion hilft das. Bei der richtigen Version hat sich das "Fehlverhalten" etwas geändert aber ist noch da. Dann hab ich den das Unterprogramm tempabfrage12 gegen das Kürzere aus der gekürzten Codeversion getauscht und dann ging es. Dann hab ich dieses mit ca 30 NOP versehen und dann war der Fehler wieder da. Es muss also an der Zeit liegen.
    Müsste das Programm nach einem Interrupt nicht eigentlich an der Stelle weitermachen wo der Interrupt kam? Oder wird das Unterprogramm einfach abgebrochen?

  6. #16
    Erfahrener Benutzer Robotik Einstein Avatar von wkrug
    Registriert seit
    17.08.2006
    Ort
    Dietfurt
    Beiträge
    2.232
    Müsste das Programm nach einem Interrupt nicht eigentlich an der Stelle weitermachen wo der Interrupt kam? Oder wird das Unterprogramm einfach abgebrochen?
    Solange Du nicht am Stack rummanipulierst, sollte das Programm da weitermachen, wo es unterbrochen wurde.

    Wenn Du verhindern willst, das bei einer Werteübergabe ein Interrupt auftritt, kannst Du vorher mit CLI die Interruptabarbeitung stoppen und danach gleich wieder mit SEI freigeben.

    Beispiel:
    In einem Interrupt wird ein 4Byte Zähler bearbeitet und im RAM zwischengespeichert.
    Du verarbeitetst jetzt aber diese Werte im Hauptprogramm in Registern.
    Also machst Du das so:
    CLI
    LDS r16,adr
    LDS r17,adr + 1
    LDS r18,adr + 2
    LDS r19,adr + 3
    SEI

    Wenn jetzt also während der Werteübernahme dieser Interrupt auftreten würde, wird er aufgehalten, bist alle 4 Werte in den entsprechenden Registern sind.
    Diese Wartezeiten sollten natürlich so kurz wie nur irgend möglich sein, sonst kommt dein Interrupttiming in Schwierigkeiten.

  7. #17
    Neuer Benutzer Öfters hier
    Registriert seit
    25.06.2007
    Beiträge
    9
    Jetzt funktioniert es einwandfrei!
    Nochmal Vielen Dank für die Hilfe!

    Gruß, agent

Seite 2 von 2 ErsteErste 12

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

Solar Speicher und Akkus Tests