Bascom -Hilfe gesucht

Hallo Zusammen,
gibt es hier Leute die sich mit Bascom auskennen ????

Und gerne behilflich sind ???

Gruß Thomas
 
Zuletzt bearbeitet von einem Moderator:
Hallo Uwe,
danke für dein Feedback.
Folgendes möchte mir gerne eine Automatische Glühung für mein Viertakter Bauen.
Dazu hab ich aus meinem Bascom Buch auch schon einen passenden code der auch ganz gut Funktioniert
Knüppelstellung unten LED1 an (den Ausgang benötige ich nur) Knüppelstellung mitte LED2 an Knüppelstellung oben LED 3 an
nur wenn ich mit
Select Case Servowert
Case 980 To 1030 versuch den wert zu änder passiert gar nichts der Einschaltpunkt bleibt immer bei ca 40% wenn ich auf ca 500 gehe geht die LED gar nicht mehr aus
500 sind doch eigentlich die 0,5 ms sprich links Anschlag vom Servo !!

Oder bin ich kpl falsch??

Anbei den Code

Code:
' BASCOM-Programm
' Stefan Hoffmann 2009
' Auswertung eines Servosignals
'
' In:  Servosignal an  d.2  =  Int0  Gnd von Input mit Gnd von AVR verbinden.
' Out: b.1 bis b.3 LEDs
'
$regfile = "m8adef.dat"
$crystal = 1000000
$prog &HFF , &HC1 , &HD9 , &H00                             ' generated. Take care that the chip supports all fuse bytes.

$hwstack = 32                                               ' default use 32 for the hardware stack
$swstack = 10                                               ' default use 10 for the SW stack
$framesize = 40                                             ' default use 40 for the frame space

Config Portb = Output
Led1 Alias Portb.1
Led2 Alias Portb.2
Led3 Alias Portb.3

Config Portd.2 = Input
Portd.2 = 1
Eingang Alias Pind.2

Config Int0 = Change
On Int0 Signalmessung
Enable Interrupts
Enable Int0

' Bei Timer1 (65536) mit 1 MHz und Prescaler=1
' 1 Tick:  1/1000000   *1  =  1 us

Config Timer1 = Timer , Prescale = 1
Timer1 = 0
On Timer1 Timer1_isr
Enable Timer1
Enable Interrupts


Dim Servowert As Word                                       'Wert in us. Normal: ca. 1000..2000


Do

Select Case Servowert
  Case 980 To 1030 :
    Led1 = 1 : Led2 = 0 : Led3 = 0
  Case 1030 To 980 :
    Led1 = 1 : Led2 = 0 : Led3 = 0
  Case 1667 To 2500 :
    Led1 = 0 : Led2 = 0 : Led3 = 1
End Select

Waitms 100

Loop
End


Signalmessung:
If Eingang = 1 Then                                         'Wenn Signal=1 dann
  Timer1 = 0                                                '  bei Null im us Takt
  Start Timer1                                              '  anfangen zu zaehlen                                              '
Else                                                        'sonst
  Stop Timer1                                               '  Timer stoppen und
  Servowert = Timer1                                        '  Wert uebergeben
End If
Return


Timer1_isr:                                                 'Fehleranzeige..
Led1 = 1                                                    ' ..sollte nicht eintreten
Led2 = 1
Led3 = 1
Wait 5
Return
 

Uwe Gartmann

Vereinsmitglied
Hallo Thomas

Sieht soweit nicht schlecht aus. Es gibt aber ein paar Punkte.

Ich schreibs mal direkt in dein Programm mit '***

Code:
' BASCOM-Programm
' Stefan Hoffmann 2009
' Auswertung eines Servosignals
'
' In:  Servosignal an  d.2  =  Int0  Gnd von Input mit Gnd von AVR verbinden.
' Out: b.1 bis b.3 LEDs
'
$regfile = "m8adef.dat"
$crystal = 1000000
$prog &HFF , &HC1 , &HD9 , &H00                             ' generated. Take care that the chip supports all fuse bytes.

$hwstack = 32                                               ' default use 32 for the hardware stack
$swstack = 10                                               ' default use 10 for the SW stack
$framesize = 40                                             ' default use 40 for the frame space

Config Portb = Output
Led1 Alias Portb.1
Led2 Alias Portb.2
Led3 Alias Portb.3

Config Portd.2 = Input
Portd.2 = 1                  '*** Soll hier der Pullupwiderstand gesetzt werden, wenn ja wozu?
Eingang Alias Pind.2

Config Int0 = Change
On Int0 Signalmessung
Enable Interrupts         '*** Dieser Befehl wird zweimal deklariert. Ich würde ihn als letzten Befehl vor Do : Loop setzen
Enable Int0

' Bei Timer1 (65536) mit 1 MHz und Prescaler=1
' 1 Tick:  1/1000000   *1  =  1 us

Config Timer1 = Timer , Prescale = 1
Timer1 = 0
On Timer1 Timer1_isr
Enable Timer1
Enable Interrupts


Dim Servowert As Word                                       'Wert in us. Normal: ca. 1000..2000


Do

Select Case Servowert
  Case 980 To 1030 :
    Led1 = 1 : Led2 = 0 : Led3 = 0
  Case 1030 To 980 :                    '*** Dieser Case ist doppelt, wenn er denn auch funktioniert?
    Led1 = 1 : Led2 = 0 : Led3 = 0
  Case 1667 To 2500 :
    Led1 = 0 : Led2 = 0 : Led3 = 1
End Select

Waitms 100

Loop
End


Signalmessung:
If Eingang = 1 Then                                         'Wenn Signal=1 dann
  Timer1 = 0                                                '  bei Null im us Takt
  Start Timer1                                              '  anfangen zu zaehlen                                              '
Else                                                        'sonst
  Stop Timer1                                               '  Timer stoppen und
  Servowert = Timer1                                        '  Wert uebergeben
End If
Return


Timer1_isr:                                                 'Fehleranzeige..
Led1 = 1                                                    ' ..sollte nicht eintreten
Led2 = 1
Led3 = 1
Wait 5                   '*** In einer Interruptroutine darf nicht gewartet werden. Einfach ein Fehlerflag setzen: Timer1Error = 1, und im Hauptprogramm auswerten.
Return

Noch was zu Servoimpulsen: Hier muss man heute differenzieren. Welchen Empfänger benutzt Du? Viele haben heute eine erhöhte Impulswiederholrate, Standard ist (war) 20ms. Sendet der Empfänger negative Impulse (Futaba) oder Positive?

Ein Servo hat in der Regel ein Mittensignal von 1500ms. Ein Ende hat 1000ms das andere 2000ms. Deine Select Case Abfrage bildet diesen Umstand aber nicht ab. Korrekt wäre:

Code:
Select Case Servowert
  Case 1000 To 1300 :
    Led1 = 1 : Led2 = 0 : Led3 = 0
  Case 1400 To 1600 :
    Led1 = 0 : Led2 = 1 : Led3 = 0
  Case 1700 To 2000 :
    Led1 = 0 : Led2 = 0 : Led3 = 1
End Select

Idealerweise setzt Du vor DO:LOOP alles auf null: Led1 = 0 : Led2 = 0 : Led3 = 0
Wenn der Knüppel in Bereiche gelangt wo die Auswertung Lücken hat, wird einfach der letzte Status beibehalten. Diese Hysterese ist wichtig, da kein Empfänger aufs Digit stabile Werte liefern kann. Damit wird ein hin und herschalten im 0.1 Sekundentakt vermieden.


Die Interruptroutine für die Signalmessung ist perfekt.
Die Routine Timer1_isr: sollte aber geändert werden.

Grundsätzliches: Interrrupts werden dazu verwendet, die Aufmerksamkeit des Prozessors auf etwas zu lenken, dass soeben stattgefunden hat und er sofort darauf reagieren muss weil ansonsten der Zustand der den Interrupt erzeugt hat, nicht mehr vorhanden ist. Dies trifft exakt auf die Routine Signalmessung zu. Checken welchen Pegel das Signal hat und dann den Timer neu starten oder stoppen und den Wert an eine globale Variable übergeben.

In der Zeit in der eine Interruptroutine ausgeführt wird, steht das Hauptprogramm still. Wenn während der Ausführung weitere Interrupts eintreffen, werden diese zwar registriert aber nicht abgearbeitet. Erst beim Verlassen der aktiven Interruptroutine wird der nächste, höchstprioritäre Interrupt an die Reihe kommen.

Wenn Du jetzt in Timer1_isr: den Befehl 'Wait 5' verwendest, steht der Prozessor komplette 5 Sekunden still. Besser ist hier die Verwendung einer globalen Variablen oder noch besser für diesen Fall einen FehlerCounter. Die Interruptroutine setzt diesen Counter auf 50. Im Hauptprogramm wird dieser Wert auf >0 geprüft. Ist das der Fall werden alle LEDs aktiviert und der Wert um eins verringert. Bei Null wird wieder der Wert der Signalmessung ausgewertet.

Beispiel:
Code:
Do

  If Timer1Error > 0 then
    Led1 = 1 : Led2 = 1 : Led3 = 1
    Decr Timer1Error
  Else
    Select Case Servowert
      Case 1000 To 1300 :
        Led1 = 1 : Led2 = 0 : Led3 = 0
      Case 1400 To 1600 :
        Led1 = 0 : Led2 = 1 : Led3 = 0
      Case 1700 To 2000 :
        Led1 = 0 : Led2 = 0 : Led3 = 1
    End Select
  End If
  Waitms 100
Loop

Timer1_isr:                                                 'Fehleranzeige..
  Timer1Error = 50
Return


Ich wende folgendes Schema bei BASCOM Programmen an.

Deklaration Prozessor und seine Werte für Takt, Stack etc.
Deklaration Constanten, hier vorallem True=1 und False=0 sowohl auch andere Werte die bereits feststehen.
Deklaration Variablen
Deklaration von Alias für Ein- und Ausgänge

Setzen der Ein- und Ausgänge
Setzen von Pullups für Eingänge

Configurieren von Signal-Interrupts, Aktivieren der Interrupts
Configurieren von Timern, Aktivieren von Timerinterrupts

Vor DO: LOOP aktivieren => Enable Interrupts

Noch Fragen?
Gerne bitte

Gruss
Uwe
 

Alwin

User gesperrt
Moin zusammen,

****
Case 980 To 1030 versuch den wert zu änder passiert gar nichts der Einschaltpunkt bleibt immer bei ca 40% wenn ich auf ca 500 gehe geht die LED gar nicht mehr aus
500 sind doch eigentlich die 0,5 ms sprich links Anschlag vom Servo !!
****

das hört sich irgendwie nach falschen >Timing an.
Hast du wirklich einen Quarz mit 1 MHz? ($crystal = 1000000)

Alwin
 
Hallo Uwe Hallo Alwin,
sorry das ich mich jetzt erst melde, habe einfach zu viele Kriegsplätze am laufen.

Uwe vielen dank für Deine Hilfe, leider konnte ich deine Erklärung nicht bis zu 100 % folgen, dazu ist leider mein Wissen noch zu beschränkt.
Jedoch konnte ich das Programm so abändern das es jetzt so funktioniert wie ich es haben möchte :);):cool::D ( das ich die Glühung im unteren Bereich zu schalten kann )
Jetzt muß ich nur noch an der HW schauen , das ich sauber meine Glühkerzen schalten kann denke das ich ein MOSFET nehme.
Und ein paar starke Widerstände so das ich mit einer Lipo Zelle die Glühung Speisen kann !!!

Anbei noch der kpl CODE falls jemand ebenfalls eine Glühung nachbauen möchte.
Werde noch weiter berichten !!

Code:
$regfile = "m8adef.dat"
$prog &HFF , &HE1 , &HD9 , &HFD                             ' generated. Take care that the chip supports all fuse bytes.


$crystal = 1000000

$hwstack = 32                                               ' default use 32 for the hardware stack
$swstack = 10                                               ' default use 10 for the SW stack
$framesize = 40                                             ' default use 40 for the frame space

Config Portb = Output
Led1 Alias Portb.1
Led2 Alias Portb.2
Led3 Alias Portb.3

Config Portd.2 = Input
Portd.2 = 1
Eingang Alias Pind.2

Config Int0 = Change
On Int0 Signalmessung

Enable Int0

' Bei Timer1 (65536) mit 1 MHz und Prescaler=1
' 1 Tick:  1/1000000   *1  =  1 us

Config Timer1 = Timer , Prescale = 1
Timer1 = 0
On Timer1 Timer1_isr
Enable Timer1
Enable Interrupts


Dim Servowert As Word                                       'Wert in us. Normal: ca. 1000..2000
Enable Interrupts

Do

Select Case Servowert
  Case 900 To 1100 :
    Led1 = 1 : Led2 = 0 : Led3 = 0
  Case 1110 To 1600 :
    Led1 = 0 : Led2 = 1 : Led3 = 0
  Case 1700 To 2000 :
    Led1 = 0 : Led2 = 0 : Led3 = 1
End Select

Waitms 100

Loop
End


Signalmessung:
If Eingang = 1 Then                                         'Wenn Signal=1 dann
  Timer1 = 0                                                '  bei Null im us Takt
  Start Timer1                                              '  anfangen zu zaehlen                                              '
Else                                                        'sonst
  Stop Timer1                                               '  Timer stoppen und
  Servowert = Timer1                                        '  Wert uebergeben
End If
Return


Timer1_isr:                                                 'Fehleranzeige..
Led1 = 1                                                    ' ..sollte nicht eintreten
Led2 = 1
Led3 = 1
Wait 5
Return

Gruß und Danke nochmal.

Thomas
 
Ansicht hell / dunkel umschalten
Oben Unten