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

Thema: I2C funzt nicht, wenn über rs232 empfangen wurde...Hilfe!

  1. #1
    Benutzer Stammmitglied
    Registriert seit
    13.04.2005
    Beiträge
    56

    I2C funzt nicht, wenn über rs232 empfangen wurde...Hilfe!

    Anzeige

    E-Bike
    Hallo!

    Bin schon fast am verzweifeln. Folgende Situation: An meiner RN-Control hab ich das SRF10-Modul+Sevo hängen und möchte es über einen gesendeten RS232 Befehl vom PC abfragen.
    Erstmal ne Routine ohne RS232, sondern nur die Entfernung von drei Servopositionen abgefragt. Funktioniert wunderbar.
    Wenns interessiert ist hier der Code:
    Code:
    '###################################################
    'srf10_ultraschallbeispiel2.bas
    'für
    'RoboterNetz Board RN-Control (ab Version 1.1)
    'und das SRF10 Ultraschallmodul für Entfernungsmessung
    'Datenblatt zu SRF10:
    'https://www.roboternetz.de/phpBB2/dload.php?action=file&file_id=310
    'Bezug: Robotikhardware.de
    
    'Aufgabe:
    ' Gibt die Entfernung von Objekten in Zentimetern aus
    ' Die Messungen werden mit fest vorgegebenen Verstärkungsfaktor
    ' ermittelt
    
    'Autor: Frank  (Roboternetz)
    'Weitere Beispiele und Beschreibung der Hardware
    'unter http://www.Roboternetz.de oder robotikhardware.de
    '#######################################################
    
    
    Declare Function Srf10_entfernung(byval Srf10_slaveid As Byte) As Integer
    Declare Sub Srf10_reichweite(byval Srf10_slaveid As Byte , Byval Reichweite As Word)
    Declare Sub Srf10_verstaerkung(byval Srf10_slaveid As Byte , Byval Srf10_verstaerkung As Byte)
    Declare Function Srf10_firmware(byval Srf10_slaveid As Byte) As Byte
    
    $regfile = "m32def.dat"
    
    
    $crystal = 9216000                                          'Quarzfrequenz
    $baud = 19200
    
    Config Scl = Portc.2                                        'Ports fuer IIC-Bus
    Config Sda = Portc.3
    Config Pinc.0 = Output
    
    Config Servos = 1 , Servo1 = Portc.0 , Reload = 10
    Enable Interrupts
    Dim Entfernung As Integer
    
    Servo(1) = 080
       Wait 3                                                   'Warte 3 Sekunden
       I2cinit
       Print "SRF10 Testprogramm "
       Print "SRF 10 Firmware Version:" ; Srf10_firmware(&He0)
    
       Srf10_reichweite &HE0 , 5000                             'Reichweite in Zentimetern festlegen
       Srf10_verstaerkung &HE0 , 12                             'Verstärkungsfaktor
    
    
    
    
       Do
         Servo(1) = 035
         Wait 1
         Entfernung = Srf10_entfernung(&He0)
         Print "Entfernung:" ; Entfernung ; "cm"
         Wait 1
         Servo(1) = 080
         Wait 1
         Entfernung = Srf10_entfernung(&He0)
         Print "Entfernung:" ; Entfernung ; "cm"
         Wait 1
         Servo(1) = 135
         Wait 1
         Entfernung = Srf10_entfernung(&He0)
         Print "Entfernung:" ; Entfernung ; "cm"
         Wait 1
       Loop
    
    End
    
    
    
    
    Function Srf10_entfernung(byval Srf10_slaveid As Byte) As Integer
    Local Lob As Byte
    Local Hib As Byte
    Local Firmware As Byte
    Local Temp As Byte
    Local Srf10_slaveid_read As Byte
    
       Srf10_slaveid_read = Srf10_slaveid + 1
    
       'Messvorgang in starten
       I2cstart
       I2cwbyte Srf10_slaveid
       I2cwbyte 0
       I2cwbyte 81                                              'in Zentimetern messen
       I2cstop
    
    Warteaufmessung:
       Waitms 1
       Firmware = Srf10_firmware(&He0)
       If Firmware = 255 Then Goto Warteaufmessung
    
       I2cstart
       I2cwbyte Srf10_slaveid
       I2cwbyte 2                                               'Leseregister festlegen
       I2cstop
    
    
       I2cstart
       I2cwbyte Srf10_slaveid_read
       I2crbyte Hib , Ack
       I2crbyte Lob , Nack
       I2cstop
    
    
       Srf10_entfernung = Makeint(lob , Hib)
    End Function
    
    
    
    'Messreichweite in cm festlegen
    Sub Srf10_reichweite(byval Srf10_slaveid As Byte , Byval Reichweite As Word)
    Local Wert As Word
    Local Temp As Byte
    
       Wert = Reichweite / 4                                    'Ungefähre Registerberechnung
       Temp = Low(wert)
    
       I2cstart
       I2cwbyte Srf10_slaveid
       I2cwbyte 2                                               'Register
       I2cwbyte Temp
       I2cstop
    
    End Sub
    
    
    'Verstärung  festlegen
    Sub Srf10_verstaerkung(byval Srf10_slaveid As Byte , Byval Srf10_verstaerkung As Byte)
       I2cstart
       I2cwbyte Srf10_slaveid
       I2cwbyte 1                                               'Register
       I2cwbyte Srf10_verstaerkung
       I2cstop
    
    End Sub
    
    
    
    Function Srf10_firmware(byval Srf10_slaveid As Byte) As Byte
    Local Firmware As Byte
    Local Srf10_slaveid_read As Byte
    
       Srf10_slaveid_read = Srf10_slaveid + 1
    
       I2cstart
       I2cwbyte Srf10_slaveid
       I2cwbyte 0                                               'Leseregister festlegen
       I2cstop
    
       I2cstart
       I2cwbyte Srf10_slaveid_read
       I2crbyte Firmware , Nack
       I2cstop
    
       Srf10_firmware = Firmware
    End Function
    Ist das bekannte Programm vom SRF10.
    Nun möchte ich aber einen seriellen Befehl vom PC in meinem Fall ein "t" schicken, um die Messung auszulösen. (der Code kommt unten) Jetzt fährt der Servo in die erste Position und die Portlämpchen für den SCL/SDA-Port in meinem fall c.2 und c.3 flackern. Schaut so aus als hätt sich der M32 aufgehangen. Wenn ich nun ein paar Knöpfe auf der Tastatur drück, hört das Leuchten auf und ich bekomm eine 0 vom SRF zurück. Der Servo fährt in die zweite Position und das Spiel beginnt von vorne, bis er alle drei Messungen hat. Hab die SDA-Leitung auch schon mit nem 10k-Pullupwiederstand versehen, allerdings bessert sich da leider nix. Sitz schon seit heute Mittag dran und find den Fehler einfach nicht.
    Könntet ihr euch bitte meinen Code anschauen wo da der Wurm drinsteckt...
    Hier der Code:
    Code:
    Declare Function Srf10_entfernung(byval Srf10_slaveid As Byte) As Integer
    Declare Sub Srf10_reichweite(byval Srf10_slaveid As Byte , Byval Reichweite As Word)
    Declare Sub Srf10_verstaerkung(byval Srf10_slaveid As Byte , Byval Srf10_verstaerkung As Byte)
    Declare Function Srf10_firmware(byval Srf10_slaveid As Byte) As Byte
    
    $regfile = "m32def.dat"
    
    
    $crystal = 9216000                                          'Quarzfrequenz
    $baud = 19200
    
    Config Scl = Portc.2                                        'Ports fuer IIC-Bus
    Config Sda = Portc.3
    Config Pinc.0 = Output
    Config Pinc.1 = Output
    
    Config Servos = 2 , Servo1 = Portc.0 , Servo2 = Portc.1 , Reload = 10
    
    Dim Entfernung As Integer
    Dim I As String * 1
    Config Timer1 = Pwm , Pwm = 10 , Compare A Pwm = Clear Down , Compare B Pwm = Clear Down
    Pwm1a = 0
    Pwm1b = 0
    Tccr1b = Tccr1b Or &H02
    
    On Urxc Onrxd
    Enable Urxc
    Enable Interrupts
    
    Servo(1) = 080
    
       I2cinit
       Wait 1
       Print "SRF10 Testprogramm "
       Print "SRF 10 Firmware Version:" ; Srf10_firmware(&He0)
       Srf10_reichweite &HE0 , 5000                             'Reichweite in Zentimetern festlegen
       Srf10_verstaerkung &HE0 , 12                             'Verstärkungsfaktor
    
    
    
    
       Do
         Gosub Rs232abfrage                                     'Hauptschleife
         Wait 3
    
       Loop
    
    End
    
    
    
    
    Function Srf10_entfernung(byval Srf10_slaveid As Byte) As Integer
    Local Lob As Byte
    Local Hib As Byte
    Local Firmware As Byte
    Local Temp As Byte
    Local Srf10_slaveid_read As Byte
    
       Srf10_slaveid_read = Srf10_slaveid + 1
    
       'Messvorgang in starten
       I2cstart
       I2cwbyte Srf10_slaveid
       I2cwbyte 0
       I2cwbyte 81                                              'in Zentimetern messen
       I2cstop
    
    Warteaufmessung:
       Waitms 1
       Firmware = Srf10_firmware(&He0)
       If Firmware = 255 Then Goto Warteaufmessung
    
       I2cstart
       I2cwbyte Srf10_slaveid
       I2cwbyte 2                                               'Leseregister festlegen
       I2cstop
    
    
       I2cstart
       I2cwbyte Srf10_slaveid_read
       I2crbyte Hib , Ack
       I2crbyte Lob , Nack
       I2cstop
    
    
       Srf10_entfernung = Makeint(lob , Hib)
    End Function
    
    
    
    'Messreichweite in cm festlegen
    Sub Srf10_reichweite(byval Srf10_slaveid As Byte , Byval Reichweite As Word)
    Local Wert As Word
    Local Temp As Byte
    
       Wert = Reichweite / 4                                    'Ungefähre Registerberechnung
       Temp = Low(wert)
    
       I2cstart
       I2cwbyte Srf10_slaveid
       I2cwbyte 2                                               'Register
       I2cwbyte Temp
       I2cstop
    
    End Sub
    
    
    'Verstärung  festlegen
    Sub Srf10_verstaerkung(byval Srf10_slaveid As Byte , Byval Srf10_verstaerkung As Byte)
       I2cstart
       I2cwbyte Srf10_slaveid
       I2cwbyte 1                                               'Register
       I2cwbyte Srf10_verstaerkung
       I2cstop
    
    End Sub
    
    
    
    Function Srf10_firmware(byval Srf10_slaveid As Byte) As Byte
    Local Firmware As Byte
    Local Srf10_slaveid_read As Byte
    
       Srf10_slaveid_read = Srf10_slaveid + 1
    
       I2cstart
       I2cwbyte Srf10_slaveid
       I2cwbyte 0                                               'Leseregister festlegen
       I2cstop
    
       I2cstart
       I2cwbyte Srf10_slaveid_read
       I2crbyte Firmware , Nack
       I2cstop
    
       Srf10_firmware = Firmware
    End Function
    
    Onrxd:
    I = I + Chr(udr)
    Return
                                                                         'Testroutine
    Test:
    Servo(1) = 035
         Wait 1
         Entfernung = Srf10_entfernung(&He0)
         Print "Entfernung:" ; Entfernung ; "cm"
         Wait 1
         Servo(1) = 080
         Wait 1
         Entfernung = Srf10_entfernung(&He0)
         Print "Entfernung:" ; Entfernung ; "cm"
         Wait 1
         Servo(1) = 135
         Wait 1
         Entfernung = Srf10_entfernung(&He0)
         Print "Entfernung:" ; Entfernung ; "cm"
         Wait 1
    Return
    
    Rs232abfrage:
    
    If Len(i) = 1 Then
    Select Case I
    
         Case "t"
         Gosub Test
    
         Case Else
         I = ""
    
    End Select
    Print "OK"
    I = ""
    End If
    
    Return
    Hoff mir kann jemand helfen

    Gruß

  2. #2
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    22.05.2005
    Ort
    12°29´ O, 48°38´ N
    Beiträge
    2.731
    Hallo,
    ich probiers mal,
    einfach mal was mir dazu einfällt:

    - Die Variable I ist nur ein Zeichen lang, in der ISR wird aber immer ein weiteres drangehängt, kann sich auch mal überschneiden mit dem löschen von I ( länger dimesionieren)

    - I wird nicht initialisiert, ich weiss nicht wie Bascom das macht

    - Es wird der Timer1 verwendet, gebe nur zu bedenken, das bei Software-I2C auch ein Timer gebraucht wird ... nicht das das dergleiche ist.

    - wenn man das "t" abfrägt, und das entsprechende Unterprogramm ausführt, könnten in der Zeit weitere Zeichen über UART kommen ... evtl. in der ISR kein I = I + ... sondern nur ein I = chr (UDR) !

  3. #3
    Benutzer Stammmitglied
    Registriert seit
    13.04.2005
    Beiträge
    56
    Hi!

    Danke für deine Hilfe! Hab die Sachen gleich ausgebessert. Bin jetzt selbst auf den fatalen Fehler gekommen.
    Hab das hier in der Anfangsbedingung vergessen:

    $framesize = 42
    $swstack = 42
    $hwstack = 42

    Jetzt funktioniert es wunderbar!
    Mich würd nun interessieren, was die drei Ausdrücke für eine Auswirkung haben. Könnte mir das jemand ein wenig erleutern?

    Grüsse aus dem Süden!

  4. #4
    Administrator Robotik Visionär Avatar von Frank
    Registriert seit
    30.10.2003
    Beiträge
    5.116
    Blog-Einträge
    1
    Das sind die Anweisungen die die Größe des Stacks festlegen. Diese Speicherbereiche werden genutzt wenn bei Funktionen lokale Variaben, oder Parameter benutzt werden. Irgendwo müssen die ja kurzfristig auch gespeichert werden. Je mehr lokale Variablen pro Funktion desto größer muss dieser sein. Zudem wird er für Rücksprungadressen benutzt wenn Subroutinen oder Interrupts angesprungen werden. In der Bascom Hilfe steht etwas mehr dazu. Man sollte sich dran gewöhnen das immer am Programmanfang reinzuschreiben. Die genaue Größe ist nicht so ganz einfach zu ermitteln, die 42 ist so ein Schätzwert mit Reserve. Spätestens wenns ungeklärte Programmprobleme/Abstürze gibt, sollte man überlegen ob der Wert erhöht werden muss. Aber ca. 30 bis 40 reicht für die meisten Programme. Zuviel ist nie schlimm, wenn man den Speicher hat.

    Gruß aus der Mitte

Berechtigungen

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

12V Akku bauen