PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : I2C funzt nicht, wenn über rs232 empfangen wurde...Hilfe!



Charly_cs
19.04.2006, 19:21
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:

'################################################# ##
'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:

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 8-[

Gruß

linux_80
19.04.2006, 23:37
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) !

Charly_cs
20.04.2006, 09:57
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!

Frank
20.04.2006, 11:04
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 ;-)