- 12V Akku mit 280 Ah bauen         
Ergebnis 1 bis 10 von 11

Thema: Roboter Linienverfolgung

Baum-Darstellung

Vorheriger Beitrag Vorheriger Beitrag   Nächster Beitrag Nächster Beitrag
  1. #1
    Benutzer Stammmitglied
    Registriert seit
    30.04.2010
    Beiträge
    35

    Roboter Linienverfolgung

    die Logik habe ich zuerst in Basic geschrieben und dann in Assembler, ich habe im Folgenden auch den Basic Code gepostet, damit man die Logik selbst rauslesen kann und ich sie nicht in einen Text irgendwie verschlüsseln muss.
    Der Hauptalgorithmus [Hauptprogramm ... JMP Hauptprogramm] funktioniert, aber scheinbar hat es noch Probleme mit der Messung der Schwellwerte auf sich, nur weis ich nicht was, bitte um Hilfe.

    basic code
    Code:
    'Erstellungsdatum: 21.Feb 2010
    'Ein Roboter, der einer 1,5cm breiten Linie nachfährt
    '
    'Initialisierungen*************************************************************
    $regfile = "m8def.dat"
    $crystal = 16000000
    $hwstack = 64
    $swstack = 64
    $framesize = 64
    
    'ADC-init
    Config Adc = Single , Prescaler = Auto , Reference = Avcc   'Konfiguriere ADC
    
    '--> Deklarationen von HP*******************
    Dim Messergebnisleft As Word                                'Miss Spannung am linken LDR
    Dim Messergebnismiddle As Word                              'Miss Spannung am mittleren LDR
    Dim Messergebnisright As Word                               'Miss Spannung am rechten LDR
    
    Dim Summe As Word
    
    Dim Schwellwertgespeichertmiddle As Eram Word
    Dim Speichermitteaus As Eram Word
    Dim Schwellwertmiddle As Word
    Dim Mitteaus As Word
    
    Dim Schwellwertgespeichertleft As Eram Word
    Dim Speicherlinksaus As Eram Word
    Dim Schwellwertleft As Word
    Dim Linksaus As Word
    
    Dim Schwellwertgespeichertright As Eram Word
    Dim Speicherrechtsaus As Eram Word
    Dim Schwellwertright As Word
    Dim Rechtsaus As Word
    
    Dim Weisslinks As Word
    Dim Weissmitte As Word
    Dim Weissrechts As Word
    
    Dim Zustand As Byte                                         'Hier wird der Aktuelle Stand der Sensren reingeschrieben
    
    Dim Letzterzustand As String * 10
    
    Config Debounce = 30                                        'Debaonce verzögerungszeit 30ms
    
    
    Schwellwertleft = Schwellwertgespeichertleft
    Schwellwertmiddle = Schwellwertgespeichertmiddle
    Schwellwertright = Schwellwertgespeichertright
    
    Linksaus = Speicherlinksaus
    Mitteaus = Speichermitteaus
    Rechtsaus = Speicherrechtsaus
    
    'EIN-AUSgänge******************************************************************
    Config Portb.1 = Output                                     'oc1a
    Config Portb.2 = Output                                     'oc1b
    Config Portc.3 = Output
    
    Config Pind.2 = Input
    
    'Hauptprogramm*****************************************************************
    Do
        Start Adc
    
        Messergebnisleft = Getadc(0)
        If Messergebnisleft > Schwellwertleft Then Zustand.0 = 1       'Else Zustand = 0
        If Messergebnisleft < Linksaus Then Zustand.0 = 0       'schreibe Information von sensor rechts in Byte Zustand
    
        Messergebnismiddle = Getadc(1)
        If Messergebnismiddle > Schwellwertmiddle Then Zustand.1 = 1       'Else Zustand = 0
        If Messergebnismiddle < Mitteaus Then Zustand.1 = 0     'schreibe Information von sensor mitte in Byte Zustand
    
        Messergebnisright = Getadc(2)
        If Messergebnisright > Schwellwertright Then Zustand.2 = 1       'Else Zustand = 0
        If Messergebnisright < Rechtsaus Then Zustand.2 = 0     'schreibe Information von sensor links in Byte Zustand
    
        Select Case Zustand
    
            Case &B00000001 :
                Portb = &B00000100
                Letzterzustand = "Links"                        'Merke dir den letzten Zustand
    
            Case &B00000100 :
                Portb = &B00000010
                Letzterzustand = "Rechts"
    
            Case &B00000010 :
                Portb = &B00000110
                Letzterzustand = "Mitte"
    
            Case &B00000000                                     'Falls undefinierter Zustand dann behalte letzten Zustand
                If Letzterzustand = "Links" Then
                    Portb = &B00000100
                End If
    
                If Letzterzustand = "Rechts" Then
                    Portb = &B00000010
                End If
    
        End Select
    
        Debounce Pind.2 , 0 , Messeschwellwert                  'Gehe zu Messeschwellwert wenn PinD2= 1
    
    Loop
    
    '*****************************InterruptRoutinen*******************************
    Messeschwellwert:
    
        Start Adc
    
        Weisslinks = Getadc(0)                                  'Zuerst alle 3 auf weißen Untergrund ausmessen
        Weissmitte = Getadc(1)                                  'Zuerst alle 3 auf weißen Untergrund ausmessen
        Weissrechts = Getadc(2)                                 'Zuerst alle 3 auf weißen Untergrund ausmessen
    
        Wait 1
    
        Portb = &B00000010
        Wait 3
    
        Portb = 0
        'Linker Schwellwert--------------
        Messergebnisleft = Getadc(0)                            'Schwarzer Untergrund wird ausgemessen
    
        Summe = Messergebnisleft + Weisslinks
        Schwellwertleft = Summe / 2                             'Bilde Mittelwert(Einschaltschwelle)
        Linksaus = Schwellwertleft - 20                         'Ausschaltschwelle
        Speicherlinksaus = Linksaus                             'Speichere in Eprom
        Schwellwertgespeichertleft = Schwellwertleft            'Speichere diesen im Eprom
        Wait 1
        '--------------------------------
    
        Portb = &B00000110                                      'Vorbereitung auf mittleren Schwellwert
        Wait 3
    
        Portb = 0
    
        'Mittlerer Schwellwert-----------
        Messergebnismiddle = Getadc(1)
    
        Summe = Messergebnismiddle + Weissmitte                 'Bilde Summe
        Schwellwertmiddle = Summe / 2                           'Bilde Mittelwert
        Mitteaus = Schwellwertmiddle - 20                       'Ausschaltschwelle
        Speichermitteaus = Mitteaus                             'Speichere in Eprom
        Schwellwertgespeichertmiddle = Schwellwertmiddle        'Speichere diesen im Eprom
        Wait 1
        '--------------------------------
    
        Portb = &B00000100                                      'Vorbereitung auf rechten Schwellwert
        Wait 3
    
        Portb = 0
    
        'Rechter Schwellwert-------------
        Messergebnisright = Getadc(2)
    
        Summe = Messergebnisright + Weissrechts
        Schwellwertright = Summe / 2
        Rechtsaus = Schwellwertright - 20                       'Ausschaltschwelle
        Speicherrechtsaus = Rechtsaus                           'Speichere in Eprom
        Schwellwertgespeichertright = Schwellwertright          'Schreibe Wert in EPROM
        Wait 1
        '--------------------------------
    
        Portb = &B00000100
        Waitms 500
        Portb = &B00000010
        Waitms 500
        Portb = &B00000100
        Waitms 500
        Portb = &B00000010
        Waitms 500
    
    Return
    assembler code
    Code:
    ;**********************************Header**************************************
    ;* Projektname:    Roboter-Linienverfolgung                                      *
    ;* Name des Erstellers:                                           *
    ;* Zuletzt aktualisiert: 7.4.2010                                              *
    ;* Beschreibung: Ein ROboter, der einer ca1,5-2cm breiten Linie nachfaährt      *                                                                          
    ;******************************************************************************
    
    
    ;*****************************Initialisierungen********************************
    .include "m8def.inc" ;Definitionsdatei des Mega8
    
    ;Stackpointer-init***********
        ldi r16, High(Ramend)
        out SPH, r16
    
        ldi r16, Low(Ramend)
        out SPL, r16
    
    ;ADC-init***********
        sbi ADCSRA, ADEN    ;ADC erlauben
        cbi ADCSRA, ADPS0    
        sbi ADCSRA, ADPS1    
        sbi ADCSRA, ADPS2    ;PRESCALER 64 
    
    ;*************************Variablendeklarationen*******************************
    .def Messergebnisleft = r16
    .def Messergebnisright = r17
    .def Messergebnismiddle = r18
    
    .def Schwellwertleft = r19
    .def Schwellwertmiddle = r20
    .def Schwellwertright = r21
    
    .def Linksaus = r22
    .def Mitteaus = r23
    .def Rechtsaus = r24
    
    .def Linienerkennung = r29
    
    ;*****************************Ein-Ausgänge*************************************
        sbi DDRB, 1        ;PORTB.1 als Ausgabeport
        sbi DDRB, 2        ;PORTB.2 als Ausgabeport
    
        cbi DDRD, 2        ;PORTD.2 als Eingabeport
        sbi PORTD, 2    ;Pullups aktivieren
    
        
    ;*****************************Hauptprogramm************************************
    Hauptprogramm:
    clr Linienerkennung ;Virbereitung auf neue Messung
            
    ;TEIL1...................START.......................Messe aktuelle Werte der Linie aus
    rcall    StartADConChanel0_8bit            
                in Messergebnisleft, ADCH
    rcall    StartADConChanel1_8bit            
                in Messergebnismiddle, ADCH
    rcall    StartADConChanel2_8bit            
                in Messergebnisright, ADCH        
    
    ;TEIL2...................START.......................Erstelle aktuelle Werte für Linienerkennung
            cp Messergebnisleft, Schwellwertleft    ;Vergleiche LDR links aktuell mit vorher ausgerechnetem
                                                    ;Schwellwert
            brlo FahreFort0                                    
            ldi Linienerkennung, 0b00000100                ;Wenn nicht kleiner, sprich wenn größer dann setze Bit auf 1
                                                    
    FahreFort0:
    
    
    
            cp Messergebnismiddle, Schwellwertmiddle    ;Vergleiche LDR mitte aktuell mit vorher ausgerechnetem
                                                        ;Schwellwert
            brlo FahreFort1                                    
            ldi Linienerkennung, 0b00000010                ;Wenn nicht kleiner, sprich wenn größer dann setze Bit auf 1
                                                    
    FahreFort1:                                        ;wenn kleiner dann lass es auf Null
            
    
    
            cp Messergebnisright, Schwellwertright    ;Vergleiche LDR rechts aktuell mit vorher ausgerechnetem
                                                    ;Schwellwert
            brlo FahreFort2                                    
            ldi Linienerkennung, 0b00000001                ;Wenn nicht kleiner, sprich wenn größer dann setze Bit auf 1
                                                    
    FahreFort2:                                        ;wenn kleiner dann lass es auf Null    
    
    ;TEIL3...................START.......................Auswertung-->Motorsteuerung
            
            sbrc Linienerkennung, 2    
                ldi r28, 0b00000010        ;Motor = Rechts
                out PORTB, r28
            sbrc Linienerkennung, 1        
                ldi r28, 0b00000110        ;Motor = Beide
                out PORTB, r28
            sbrc Linienerkennung, 0        
                ldi r28, 0b00000100        ;Motor = Links
                out PORTB, r28
    ;TEIL4...................START.......................Falls neie Messung vorgesehen dann mache sie zuerst
            sbis PIND, 2                ;Überprüfe PIND.0
            rcall Messeschwellwert         ;Wenn PIND.0 = 0 (Taster betätigt)--> Messung
    rjmp Hauptprogramm                    ;ansosnten wieder von vorne
    ;*********************************************************************************
    
    
    
    ;***********************Unterprogramme/Funktionen******************************
    Messeschwellwert:
    rcall    StartADConChanel0_8bit            ;Messe linken LDR bei weißem Untergrund
                in r25, ADCH
    rcall    StartADConChanel1_8bit            ;Messe mittleren LDR bei weißem Untergrund
                in r26, ADCH
    rcall    StartADConChanel2_8bit            ;Messe rechten LDR bei weißem Untergrund
                in r27, ADCH
    cbi PORTB, 1
    cbi PORTB, 2
    rcall Wait1
    sbi PORTB, 1
    rcall Wait3
    cbi PORTB, 1
    
        ;Linker Schwellwert--------------
        push r28 ;In diesem Register wird das Carry einer Addition geprüft, deswegen ist sicherung nötig
        clr r28    ;lösche registerinhalt in r28 zur neuen Anwendung
        rcall    StartADConChanel0_8bit
                    in Messergebnisleft, ADCH     ;Messe LDRleft bei schwarzem Untergrund
                    add    r25, Messergebnisleft    ;Addiere Weißen Wert mit Schwarzen Wert
                    BRCC RechneWeiter0;Teste Carry Flag wegen Addition, wenn 1 dann war ein Überlauf und lade
                    ;128 in ein Register weil nachher der Mittelwert gebildet wird und dafür 
                    ;eine 9 Bit Zahl notwendig ist, dh: r27/2 + (Register mit Carry = 255/2)
                    ;ergibt den richtigen Schwellwert
                    
                    ldi r28, 128    ;wenn Carry 1 dann lade 128 in carry-register
    
        RechneWeiter0:                ;wenn Carry 0 dann lasse carry-Register auf 0 (wenn Schwellwerte niedrig)
                    mov r16, r25    ;Den Dividenten ins Register der Division kopieren
                                    ;Diese Register ist als Messergebnisleft definiert
                                    ;jedoch hats keine auswirkung, denn dies wird hier nicht verwendet
                    ldi r17, 2        ;Den Divisor ins Register der Division laden
                                    ;Dieses Register ist Messergebnismiddle, dass tört aber keinen
                                    ;da hier nicht verwendet
                    rcall Division
                                    ;Ergebnis steht jetzt in Register Ergebnis (r30)
    
                    add r28, Ergebnis    ;Korrektur falls Carry 1 war, dies dinet dazu, falls der Schwellwert
                                        ;bei verschiedenen Linienfarben unterschiedlich, kann es sein
                                        ;dass es kleinere Spannungen auch geben kann, daher muss
                                        ;ein möglicher Überlauf berücksichtigt werden
                    
                    ;Endergebnis steht jetzt in r28
    
                    mov Schwellwertleft, r28    ;Kopiere den Schwellwert in definiertes Register
                                                ;für diesen Wert
        rcall Wait1  
        pop r28      
        ;--------------------------------
    
    sbi PORTB, 1
    sbi PORTB, 2                                      
    rcall Wait3
    cbi PORTB, 1
    cbi PORTB, 2
    
        ;Mittlerer Schwellwert-----------
        push r28 ;In diesem Register wird das Carry einer Addition geprüft, deswegen ist sicherung nötig
        clr r28    ;lösche registerinhalt in r28 zur neuen Anwendung
        rcall    StartADConChanel1_8bit
                    in Messergebnismiddle, ADCH     ;Messe LDRleft bei schwarzem Untergrund
                    add    r26, Messergebnismiddle    ;Addiere Weißen Wert mit Schwarzen Wert
                    BRCC RechneWeiter1;Teste Carry Flag wegen Addition, wenn 1 dann war ein Überlauf und lade
                    ;128 in ein Register weil nachher der Mittelwert gebildet wird und dafür 
                    ;eine 9 Bit Zahl notwendig ist, dh: r27/2 + (Register mit Carry = 255/2)
                    ;ergibt den richtigen Schwellwert
                    
                    ldi r28, 128    ;wenn Carry 1 dann lade 128 in carry-register
    
        RechneWeiter1:                ;wenn Carry 0 dann lasse carry-Register auf 0 (wenn Schwellwerte niedrig)
                    mov r16, r26    ;Den Dividenten ins Register der Division kopieren
                                    ;Diese Register ist als Messergebnisleft definiert
                                    ;jedoch hats keine auswirkung, denn dies wird hier nicht verwendet
                    ldi r17, 2        ;Den Divisor ins Register der Division laden
                                    ;Dieses Register ist Messergebnismiddle, dass tört aber keinen
                                    ;da hier nicht verwendet
                    rcall Division
                                    ;Ergebnis steht jetzt in Register Ergebnis (r30)
    
                    add r28, Ergebnis    ;Korrektur falls Carry 1 war, dies dinet dazu, falls der Schwellwert
                                        ;bei verschiedenen Linienfarben unterschiedlich, kann es sein
                                        ;dass es kleinere Spannungen auch geben kann, daher muss
                                        ;ein möglicher Überlauf berücksichtigt werden
                    
                    ;Endergebnis steht jetzt in r28
    
                    mov Schwellwertmiddle, r28    ;Kopiere den Schwellwert in definiertes Register
                                                ;für diesen Wert
        rcall Wait1  
        pop r28      
        ;--------------------------------
    
    sbi PORTB, 2 
    rcall Wait3
    cbi PORTB, 2
    
        ;Rechter Schwellwert-------------
         push r28 ;In diesem Register wird das Carry einer Addition geprüft, deswegen ist sicherung nötig
        clr r28    ;lösche registerinhalt in r28 zur neuen Anwendung
        rcall    StartADConChanel2_8bit
                    in Messergebnisright, ADCH     ;Messe LDRleft bei schwarzem Untergrund
                    add    r27, Messergebnisright    ;Addiere Weißen Wert mit Schwarzen Wert
                    BRCC RechneWeiter2;Teste Carry Flag wegen Addition, wenn 1 dann war ein Überlauf und lade
                    ;128 in ein Register weil nachher der Mittelwert gebildet wird und dafür 
                    ;eine 9 Bit Zahl notwendig ist, dh: r27/2 + (Register mit Carry = 255/2)
                    ;ergibt den richtigen Schwellwert
    
                    ldi r28, 128    ;wenn Carry 1 dann lade 128 in carry-register
    
        RechneWeiter2:                ;wenn Carry 0 dann lasse carry-Register auf 0 (wenn Schwellwerte niedrig)
                    mov r16, r27    ;Den Dividenten ins Register der Division kopieren
                                    ;Diese Register ist als Messergebnisleft definiert
                                    ;jedoch hats keine auswirkung, denn dies wird hier nicht verwendet
                    ldi r17, 2        ;Den Divisor ins Register der Division laden
                                    ;Dieses Register ist Messergebnismiddle, dass tört aber keinen
                                    ;da hier nicht verwendet
                    rcall Division
                                    ;Ergebnis steht jetzt in Register Ergebnis (r30)
    
                    add r28, Ergebnis    ;Korrektur falls Carry 1 war, dies dinet dazu, falls der Schwellwert
                                        ;bei verschiedenen Linienfarben unterschiedlich, kann es sein
                                        ;dass es kleinere Spannungen auch geben kann, daher muss
                                        ;ein möglicher Überlauf berücksichtigt werden
                    
                    ;Endergebnis steht jetzt in r28
    
                    mov Schwellwertright, r28    ;Kopiere den Schwellwert in definiertes Register
                                                ;für diesen Wert
        rcall Wait1  
        pop r28      
        ;--------------------------------
    
    ret
    ;*************************************
    ;*************************************
    
    
    ;################################################################################
    .include "Division8Bit+Rest.asm"     ;8 Bit division        //call division
    .include "wait1.asm"
    .include "wait3.asm"
    .include "ReadEEPROM.asm"            ;                //call Read_EEPROM
    .include "WriteEEPROM.asm"            ;                //call Write_EEPROM
    .include "StartADConCHANEL0_8bit.asm"
    .include "StartADConCHANEL1_8bit.asm"
    .include "StartADConCHANEL2_8bit.asm"
    ;################################################################################
    In Aufrufe.txt sind die Unterprogramme die ich geschrieben habe
    ich habe auch ausführlichst rauskommentiert

    lg andy
    Angehängte Dateien Angehängte Dateien

Berechtigungen

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

fchao-Sinus-Wechselrichter AliExpress