PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Probleme bei globaler Variable in Funktion



Cyrus777
08.02.2012, 13:03
Hi,

ich habe folgendes Problem: Ich habe eine globale Variable vom Typ word, die ich in einer Sub aufrufen will. Aber wenn ich sie direkt in dieser Sub ausgebe, kommt nur 0 zurück, obwohl sie eine Aufrufstufe höher noch einen Wert hat. Warum wird sie 0?

Kampi
08.02.2012, 13:09
Zeig mal bitte deinen Quellcode.
Normalerweise wird der Wert der Variable mit in die Sub übernommen, da sie ja Global ist.
Setzt du sie vielleicht irgendwo auf 0 zurück?

Cyrus777
08.02.2012, 14:26
Hi Daniel,

ich poste den Quellcode morgen, da bin ich wieder in der FH. Ich setz sie aber nirgendswo auf null. Das Problem ist dass ich Sie direkt vor dem SUB-Aufruf noch ausgebe und sie einen bestimmten Wert hat und am anfang von der Funktion schon Null ist.

for_ro
08.02.2012, 21:22
Das Problem ist dass ich Sie direkt vor dem SUB-Aufruf noch ausgebe und sie einen bestimmten Wert hat und am anfang von der Funktion schon Null ist.

Es kann auch daran liegen, dass du zu kleine Werte für den SWStack oder den Frame angegeben hast.

Cyrus777
09.02.2012, 10:08
Hi,
also ich poste jetzt mal den ganzen Code unseres Programms. Das Fahrzeug hat zwei induktive Spursensoren (Sensor links und Sensor rechts), die analoge Werte < 10 anzeigen, wenn sie Kontakt zur Spur haben. Die Spur ist ein Draht, wo ein Signal drauf läuft. Dann haben wir noch einen IFR-Sensor zur Hinderniserkennung. Die Lenkung sitzt hinten und wird durch einen weiteren Motor realsiert. Auf der Lenkachse sitzt ein Poti, mit dem wir die Mittelstellung ermitteln.
Das Board ist das RN-Control 1.4 mit dem Atmega32. Wir befürchten, dass die 2 Kb Ram zu wenig sind, um z.b.e in Funktionen zu übergeben. Es steht ja sicher nicht umsonst in der RN-Wiki, dass man sowas vermeiden soll, um schnellen Code zu erzeugen. Ist es generell besser, auf solche Dinge zu verzichten und nur Sub Routinen ohne Parameterübergabe zu benutzen?

Ich hab die Stelle die bei der Ausgabe 0 ergibt rot und fett im Code markiert.
Danke schonmal im Voraus für die Mühe :)


'Hardwarekonfiguration
$regfile = "m32def.dat"
$framesize = 256 '32
$swstack = 256 '32
$hwstack = 256 '256
$lib "Lcd_i2c.lib" 'ersetzt die Standard LCD Library

Const Pcf8574_lcd = &H40 'I2C Adresse
Config Scl = Portc.0 'I2C SCL Pin
Config Sda = Portc.1 'I2C SDA Pin
Dim _lcd_e As Byte
_lcd_e = 128 'LCD im 4-Bit Mode betreiben

Dim I As Word
Dim N As Word
Dim Ton As Word

$crystal = 16000000 'Quarzfrequenz
$baud = 9600 'Übertragungsrate 19200 für funk

Config Adc = Single , Prescaler = Auto 'Für Tastenabfrage und Spannungsmessung

Config Pina.7 = Input 'Für Tastenabfrage
Porta.7 = 1 'Pullup Widerstand ein

Const Ref = 5 / 1023 'Für Batteriespannungsberechnung

Dim Taste As Byte
'Dim Volt As Single


'Ports für linken Motor
Config Pinc.6 = Output 'Linker Motor Kanal 1
Config Pinc.7 = Output 'Linker Motor Kanal 2
Config Pind.4 = Output 'Linker Motor PWM
'Ports für rechten Motor
Config Pinb.0 = Output 'Rechter Motor Kanal 1
Config Pinb.1 = Output 'Rechter Motor Kanal 2
Config Pind.5 = Output 'Rechter Motor PWM
Config Timer1 = Pwm , Pwm = 10 , Compare A Pwm = Clear Up , Compare B Pwm = Clear Up
Pwm1a = 0
Pwm1b = 0
Tccr1b = Tccr1b Or &H02 'Prescaler = 8





'Programm
Const Zaehler = 10 'Mittelwerte aus Zaehler. Werten
Const Max_pwm = 1023 'maximale Pulsweitenmodulation


'Fahrtprogramm
Dim Pos As Byte
Dim Lenkeinschlag As Byte
Declare Sub Fahrt() 'Hauptprogramm der Steuerung
Declare Sub Init() 'Initialisierung
Declare Sub Lenken() 'ermittelt benötigten Lenkeinschlag
Declare Sub Neue_pos() 'liefert gewünschte Lenkrichtung
Declare Sub Motor() 'liefert gewünschte Motorgeschwindigkeit


'Motorsteuerungsfunktionen
Dim Motorkraft As Word
Declare Function Motor_speed() As Word 'Abfrage Motorgeschwindigkeit
Declare Sub Motor_start() 'Motor mit Geschwindigkeit ansteuern
Declare Sub Motor_stop() 'anhalten
Declare Sub Motor_brems() 'bremsen
Declare Sub Motor_antrieb()

'Lenkungsfunktionen
Declare Sub Lenkung_stop() 'aufhören zu lenken
Declare Sub Lenkung_links() 'nach links lenken
Declare Sub Lenkung_rechts() 'nach rechts lenken
Declare Sub Motor_lenk() '

'Infrarotsensorfunktionen
Dim Ifr_sensor As Word
Const Ifr_port = 0
Declare Function Ifr_sensor_lesen() As Word 'liefert Ifr_Sensor

'Lichtschranke
Const Lichtschranke_port = 4
Declare Function Lichtschranke(byval Port As Byte) As Word 'Liefert Wert der Lichtschranke

'Spurführungssensorenfunktionen
Const Spur_rechts_port = 3
Const Spur_links_port = 2
Dim Sensor_rechts As Word
Dim Sensor_links As Word
Declare Function Spursensor_messen(byval Port As Byte) As Word 'liefert Wert für Spursensor

'Tasten
Const Tasten_port = 7
Declare Function Tastenabfrage() As Byte 'liefert gedrückte Taste

'Poti
Const Poti_port = 1
Dim Poti As Word
Dim Poti_toleranz As Word '5% Toleranz wird in init() definiert
Dim Poti_links As Word 'Wert ganz links
Dim Poti_rechts As Word 'Wert ganz rechts
Declare Function Poti_lesen() As Word 'Liest Wert des Potis
Declare Sub Poti_test()

'Errorcodes
Declare Sub Error(byval Code As Word) 'stoppt FTS und gibt Fehlermeldung aus



'Main
I = 0
Sound Portd.7 , 400 , 450 'BEEP
Sound Portd.7 , 400 , 800 'BEEP
Sound Portd.7 , 400 , 450


Cls 'loesche das LCD Display
Locate 1 , 1 'Cursor auf 1 Zeile, 1 Spalte
Lcd "FTS bereit."
Locate 2 , 1 'String auf Display anzeigen
Lcd "Taste 1 fuer"
Locate 3 , 1
Lcd "Programmstart."

Do

Taste = Tastenabfrage()
If Taste <> 0 Then
Select Case Taste
Case 1
Call Fahrt()
End Select
Sound Portd.7 , 400 , 500 'BEEP
End If

Waitms 100
Loop

End




'Diese Unterfunktion fragt die Tastatur am analogen Port ab
Function Tastenabfrage() As Byte
Local Ws As Word

Tastenabfrage = 0
Ton = 600
Start Adc
Ws = Getadc(tasten_port)
If Ws < 500 Then
Select Case Ws
Case 400 To 450
Tastenabfrage = 1
Ton = 550
Case 330 To 380
Tastenabfrage = 2
Ton = 500
Case 260 To 305
Tastenabfrage = 3
Ton = 450
Case 180 To 220
Tastenabfrage = 4
Ton = 400
Case 90 To 130
Tastenabfrage = 5
Ton = 350

End Select
Sound Portd.7 , 400 , Ton 'BEEP

End If

End Function



'Errorcodes
Sub Error(code As Word)
Motor_brems
Lenkung_stop
Cls 'Display löschen
Locate 1 , 1 '1.Zeile und 1.Zeichen
Lcd "Error " ; Code;
Do
Sound Portd.7 , 400 , 200
Wait 1
Loop
End Sub


'Motorsteuerungsfunktionen
Function Motor_speed() As Word
If Portd.5 = 1 Then
Motor_speed = Pwm1a / Max_pwm
Else
Motor_speed = 0
End If
End Function

Sub Motor_antrieb()
If Motorkraft = 0 Then
Motor_stop
Elseif Motorkraft >= 700 Then
Call Motor_start()
Elseif Motorkraft = 1 Then
Motor_brems
Else
Call Error(302)
End If
End Sub

Sub Motor_stop()
Portb.0 = 0 'Antrieb aus
Portb.1 = 1
Portd.5 = 0
Pwm1a = 0
End Sub

Sub Motor_brems()
Portd.5 = 0
Pwm1a = 0 'Antrieb aus
Portb.0 = 1 'Generator
Portb.1 = 0
Portd.5 = 1
Pwm1a = 1
Waitms 1
End Sub

Sub Motor_start()
Portb.0 = 0 'Antrieb schnell
Portb.1 = 1
Portd.5 = 1
If Motorkraft < 700 Then
Call Error(301)
Else
Pwm1a = Motorkraft * Max_pwm
End If
End Sub



'Lenkungsfunktionen
Sub Motor_lenk()
If Lenkeinschlag = 1 Then
Lenkung_links
Elseif Lenkeinschlag = 2 Then
Lenkung_stop
Elseif Lenkeinschlag = 3 Then
Lenkung_rechts
Else
Call Error(501)
End If
End Sub


Sub Lenkung_stop()
Portd.4 = 0
Pwm1b = 0
If Portc.6 = 0 Then
Portc.6 = 1
Portc.7 = 0
Else
Portc.6 = 0
Portc.7 = 1
End If
Portd.4 = 1
Pwm1b = 1
Waitms 1
Portd.4 = 0
Pwm1b = 0

End Sub


Sub Lenkung_links()
Portc.6 = 0
Portc.7 = 1
Portd.4 = 1
Pwm1b = 1023
End Sub

Sub Lenkung_rechts()
Portc.6 = 1
Portc.7 = 0
Portd.4 = 1
Pwm1b = 1023
End Sub


'Poti Funktionen
Function Poti_lesen() As Word
Local Mittelwert As Word
Local J As Byte
Mittelwert = 0
For J = 1 To 10
Mittelwert = Mittelwert + Getadc(poti_port)
Next J
Poti_lesen = Mittelwert / Zaehler
End Function


Sub Poti_test()
Do
Print Getadc(poti_port)
Loop
End Sub


'Steuert den IFR Sensor
Function Ifr_sensor_lesen() As Word
Local Mittelwert As Word
Local J As Byte

Mittelwert = 0
For J = 1 To Zaehler Step 1
'misst 10 Mal
Mittelwert = Mittelwert + Getadc(ifr_port)
Next J

Ifr_sensor_lesen = Mittelwert / Zaehler

End Function


'Steuert die Spursensoren
Function Spursensor_messen(byval Port As Byte) As Word
Local Mittelwert As Word
Local J As Byte

Mittelwert = 0
For J = 1 To Zaehler Step 1
'misst 10 Mal
Mittelwert = Mittelwert + Getadc(port)

Next J
Spursensor_messen = Mittelwert / Zaehler

End Function


'Fahrt Funktionen
Sub Neue_pos()
Print Sensor_rechts
If Sensor_links >= 700 Then
If Sensor_rechts >= 700 Then
If Pos > 5 Then
Pos = 8
Else
Pos = 0
End If
End If
If Sensor_rechts < 700 And Sensor_rechts >= 10 Then
Pos = 7
End If
If Sensor_rechts < 10 Then
Pos = 6
End If
Elseif Sensor_links < 700 And Sensor_links >= 10 Then
If Sensor_rechts < 10 Then
Pos = 5
End If
If Sensor_rechts >= 700 Then
Pos = 1
End If
Else
If Sensor_rechts < 10 Then
Pos = 4
End If
If Sensor_rechts >= 10 And Sensor_rechts < 700 Then
Pos = 3
End If
If Sensor_rechts >= 700 Then
Pos = 2
End If
End If
Print "Pos in Neue_pos(): " ; Pos

End Sub




Sub Init()
Local Poti_mitte As Word
Cls 'Display löschen
Locate 1 , 1 '1.Zeile und 1.Zeichen
Lcd "Initialisierung " ;
Call Motor_stop()
Call Lenkung_links()
Wait 2
Call Lenkung_stop()
Poti_links = Poti_lesen()
Call Lenkung_rechts()
Wait 2
Call Lenkung_stop()
Poti_rechts = Poti_lesen()
Poti_mitte = Poti_rechts + Poti_links
Poti_mitte = Poti_mitte / 2
Poti_toleranz = Poti_links - Poti_rechts
Poti_toleranz = Poti_toleranz / 20
Poti_mitte = Poti_mitte - Poti_toleranz
Call Lenkung_links
Print "poti_mitte " ; Poti_mitte
Print "poti_links " ; Poti_links
Print "poti_rechts " ; Poti_rechts

Do
Print "poti_jetzt" ; Getadc(poti_port)
Loop Until Getadc(poti_port) >= Poti_mitte
Call Lenkung_stop()
Print Poti_mitte
Wait 2
Print Getadc(poti_port)

Cls 'Display löschen
Locate 1 , 1 '1.Zeile und 1.Zeichen
Lcd "Fahrt " ;
End Sub


Sub Motor()

If Ifr_sensor < 30 Or Ifr_sensor >= 170 And Ifr_sensor < 400 Then 'anhalten
Motorkraft = 0
Elseif Ifr_sensor >= 30 And Ifr_sensor < 170 Then 'kein Hinderniss
If Lenkeinschlag >= 3 And Lenkeinschlag < 6 Then
Motorkraft = 1
Else
Motorkraft = 701
End If
Else
Motorkraft = 1 'bremsen
End If

End Sub


Sub Lenken()
Local Mitte As Word
Local Halb As Word
Local Ziel As Word
Local Max_ziel As Word
Local Min_ziel As Word

Mitte = Poti_rechts - Poti_links
Halb = Mitte - Poti_links
Halb = Halb / 2

If Pos < 2 And Pos >= 0 Then
Ziel = Poti_links
Elseif Pos < 4 And Pos >= 2 Then
Ziel = Mitte - Halb
Elseif Pos = 4 Then
Ziel = Mitte
Elseif Pos < 7 And Pos >= 5 Then
Ziel = Mitte + Halb
Elseif Pos < 9 And Pos >= 7 Then
Ziel = Poti_rechts
Else
Call Error(901)
End If

Max_ziel = Ziel + Poti_toleranz
Min_ziel = Ziel - Poti_toleranz
If Poti > Max_ziel Then
Lenkeinschlag = 1
Elseif Poti < Min_ziel Then
Lenkeinschlag = 3
Elseif Poti < Max_ziel And Poti > Min_ziel Then
Lenkeinschlag = 2
Else
Print "pos " ; Pos;
Print "Poti " ; Poti;
Print "ziel " ; Ziel;
Print "toleranz " ; Poti_toleranz;
Print "Max_Ziel " ; Max_ziel;
Print "Min_Ziel " ; Min_ziel;
Print "Poti_links " ; "Poti_links";
Print "Poti_rechts " ; "Poti_rechts";
Call Error(601)
'loesche das LCD Display

End If
End Sub


Sub Fahrt()
Local Lenkeinschlag As Byte
Local Motorkraft As Word

Local Sensor_rechts As Word
Local Sensor_links As Word
Local Poti As Word
Local Ifr_sensor As Word
Local Pos As Byte

Sensor_rechts = Spursensor_messen(spur_rechts_port)
Sensor_links = Spursensor_messen(spur_links_port)
If Sensor_rechts >= 10 Then
Call Error(702)
End If
If Sensor_links >= 10 Then
Call Error(701)
End If

Call Init
Pos = 4

Do
Sensor_rechts = Spursensor_messen(spur_rechts_port)
Print "Sensor_rechts: " ; Sensor_rechts
Sensor_links = Spursensor_messen(spur_links_port)
Print "Sensor_links: " ; Sensor_links
Poti = Poti_lesen()
Print "Poti: " ; Poti
Ifr_sensor = Ifr_sensor_lesen()
Print "Ifr_sensor: " ; Ifr_sensor


Print "vorher" ; Sensor_rechts
Call Neue_pos()
Print "Position: " ; Pos
Call Lenken()
Print "Lenkeinschlag: " ; Lenkeinschlag
Call Motor()
Print "Motor: " ; Motorkraft
Print ""


Call Motor_antrieb()
Call Motor_lenk()

Loop




End Sub

Kampi
09.02.2012, 10:51
Hast du mal versucht dieses Unterprogramm als Funktion zu deklarieren und die Variable manuell in die Funktion zu übergeben?

PicNick
09.02.2012, 11:41
Ich kann das Programm garnicht kompilieren ?

Folgende Variablen sind vorher schon definiert worden


Sub Fahrt()
' Local Lenkeinschlag As Byte
' Local Motorkraft As Word
' Local Sensor_rechts As Word
' Local Sensor_links As Word
' Local Poti As Word
' Local Ifr_sensor As Word
' Local Pos As Byte


Um welche Funktion und welche Variable geht es in deinem Problem (Im Code-Block kann man nicht fett markieren) ?

Cyrus777
09.02.2012, 12:46
Ich hab's im Gesamtcode die Variablenausgabe("Print Sensor_rechts") rot markiert. In diesem Modul tritt der Fehler auf:


'Fahrt Funktionen
Sub Neue_pos()
Print Sensor_rechts
If Sensor_links >= 700 Then
If Sensor_rechts >= 700 Then
If Pos > 5 Then
Pos = 8
Else
Pos = 0
End If
End If
If Sensor_rechts < 700 And Sensor_rechts >= 10 Then
Pos = 7
End If
If Sensor_rechts < 10 Then
Pos = 6
End If
Elseif Sensor_links < 700 And Sensor_links >= 10 Then
If Sensor_rechts < 10 Then
Pos = 5
End If
If Sensor_rechts >= 700 Then
Pos = 1
End If
Else
If Sensor_rechts < 10 Then
Pos = 4
End If
If Sensor_rechts >= 10 And Sensor_rechts < 700 Then
Pos = 3
End If
If Sensor_rechts >= 700 Then
Pos = 2
End If
End If
Print "Pos in Neue_pos(): " ; Pos

End Sub

PicNick
09.02.2012, 13:32
Naja, wenn "pos" aber doppelt definiert ist, einmal als DIM ganz oben und dann als LOCAL (bei Sub Fahrt() ), wird es Probleme geben.
Aber eigentlich beschwert sich Bascom über sowas ?

Cyrus777
09.02.2012, 14:08
so hatte es mal geändert aber es hat immer noch nicht funktioniert. Naja ich hab es jetzt alles in Fahrt() reingetan. Is zwar nicht sehr elegant aber es funktioniert...

naja vielen Dank für eure Hilfe, es wird schon :)

MagicWSmoke
09.02.2012, 14:29
naja vielen Dank für eure Hilfe, es wird schon
Du würdest eine steilere Lernkurve bekommen, wenn sich Deine Grundeinstellung ändern würde, d.h. Du auf auf Fragen und Antworten, wie von PicNick gestellt, auch reagieren würdest. Ein Mensch mag Ignoranz verzeihen, ein µC nicht :D

MagicWSmoke
09.02.2012, 14:38
Naja, wenn "pos" aber doppelt definiert ist, einmal als DIM ganz oben und dann als LOCAL (bei Sub Fahrt() ), wird es Probleme geben.
Aber eigentlich beschwert sich Bascom über sowas ?
Quote history.txt:

2.0.5.0
...
- local variables may now have the same name as global variables.