PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : RS485 Empfang ohne Input/waitkey, und mit 0Byte



Lucky1001
18.12.2010, 14:41
Hallo, ich bin neu hier im forum, und habe auch erst gerade mit Bascom angefangen

Mein Projekt:
Ich möchte 30 Ladegeräte per RS485 Steuern/Abfragen
Die Geräte werden den Kommando K01 M(CR/LF) für Gerät 1 nach Messwerten gefragt, die Antwort ist denn ein 18 Zeichen langen string, der mit P01 ... anfängt.
Desweitern gibt es noch ander Kommandos, die aber erstmal nicht wichtig sind, es geht mir jetzt nur darum die Kommunikation herzustellen

also z.b.
Sende: K01 M(CR/LF)
Antwort: P01 VT-EEE-EEE-EEE(CR/LF)

Das Problem:
Es muss sichergestellt sein, das wenn ein Gerät gefragt wurde, und es nicht, oder Falsch antwortet (was durchaus vorkommen kann, z.b. Defekter Optokoppler im Gerät), das Programm nicht stehen bleibt, sondern das nächste Gerät abfragt.

Deshalb kommen wohl INPUT und WAITKEY nicht infrage weil sie warten würden, und INKEY wegen der 0 auch nicht ?! (wenn falsch bitte korrigieren)

Ich habe bereits eine LabView Anwendung geschrieben die die Geräte effizient Steuert/Abfragt, doch einige bereiche sollen jetzt in den Atmega ausgelagert werden um einen Ausfall das PCs mittelfristig zu überbrücken

Ich habe übrigens die möglichkeit die Aktivität auf dem Bus mit zu Logger und im Terminal zu sehen

Mein bisheriger code funktioniert, aber ich weis nicht wie ich die antwort anders empfangen könnte.




$regfile = "M88def.dat"
$crystal = 1000000
$hwstack = 100
$swstack = 100
$framesize = 100


Config Com1 = 4800 , Synchrone = 0 , Parity = Even , Stopbits = 1 , Databits = 7 , Clockpol = 0
Config Print = Portd.2 , Mode = Set
Config Pind.2 = Output


Led1 Alias Portb.0
Config Led1 = Output

Led2 Alias Portd.7
Config Led2 = Output

Led3 Alias Portd.4
Config Led3 = Output

Taster1 Alias Pind.5
Config Taster1 = Input

Taster2 Alias Pind.6
Config Taster2 = Input



Dim Test As String * 20

Do
Gosub Mess

If Len(test) = 19 Then
Led2 = 1
Else
Led2 = 0
End If

Loop


Mess:
Waitms 5
Print "K02 M"
Input Test Noecho
Return


schonmal vielen dank für eure Antworten ;-)

PicNick
18.12.2010, 16:33
Wenn du von einem Gerät daten kriegst oder auch nicht, würde ich empfehlen,
1) mit "config serialin=buffered, .... " (-->bascom help) den Empfang asynchron (mit Interrupt) zu machen
2) parallel dazu einen Timer laufen zu lassen. Durch ein Zeitfenster kannst du erkennen, ob irgendein Gerät offensichtlich keine oder eine verstümmelte Antwort liefert

Richard
18.12.2010, 18:33
Hallo, ich bin neu hier im forum, und habe auch erst gerade mit Bascom angefangen

Mein Projekt:
Ich möchte 30 Ladegeräte per RS485 Steuern/Abfragen
Die Geräte werden den Kommando K01 M(CR/LF) für Gerät 1 nach Messwerten gefragt, die Antwort ist denn ein 18 Zeichen langen string, der mit P01 ... anfängt.
Desweitern gibt es noch ander Kommandos, die aber erstmal nicht wichtig sind, es geht mir jetzt nur darum die Kommunikation herzustellen

also z.b.
Sende: K01 M(CR/LF)
Antwort: P01 VT-EEE-EEE-EEE(CR/LF)

Das Problem:
Es muss sichergestellt sein, das wenn ein Gerät gefragt wurde, und es nicht, oder Falsch antwortet (was durchaus vorkommen kann, z.b. Defekter Optokoppler im Gerät), das Programm nicht stehen bleibt, sondern das nächste Gerät abfragt.

Deshalb kommen wohl INPUT und WAITKEY nicht infrage weil sie warten würden, und INKEY wegen der 0 auch nicht ?! (wenn falsch bitte korrigieren)

Ich habe bereits eine LabView Anwendung geschrieben die die Geräte effizient Steuert/Abfragt, doch einige bereiche sollen jetzt in den Atmega ausgelagert werden um einen Ausfall das PCs mittelfristig zu überbrücken

Ich habe übrigens die möglichkeit die Aktivität auf dem Bus mit zu Logger und im Terminal zu sehen

Mein bisheriger code funktioniert, aber ich weis nicht wie ich die antwort anders empfangen könnte.




$regfile = "M88def.dat"
$crystal = 1000000
$hwstack = 100
$swstack = 100
$framesize = 100


Config Com1 = 4800 , Synchrone = 0 , Parity = Even , Stopbits = 1 , Databits = 7 , Clockpol = 0
Config Print = Portd.2 , Mode = Set
Config Pind.2 = Output


Led1 Alias Portb.0
Config Led1 = Output

Led2 Alias Portd.7
Config Led2 = Output

Led3 Alias Portd.4
Config Led3 = Output

Taster1 Alias Pind.5
Config Taster1 = Input

Taster2 Alias Pind.6
Config Taster2 = Input



Dim Test As String * 20

Do
Gosub Mess

If Len(test) = 19 Then
Led2 = 1
Else
Led2 = 0
End If

Loop


Mess:
Waitms 5
Print "K02 M"
Input Test Noecho
Return


schonmal vielen dank für eure Antworten ;-)

Lese einmal......

http://www.rowalt.de/mc/avr/avrboard/06/avrb06.htm



Gruß Richard

Lucky1001
18.12.2010, 20:42
Danke euch beiden für die Antworten !

@PicNick, das mit dem Timer ist eine gute idee ! habe das jetzt mit eingebaut, und scheint auch zu laufen :-D

@Richard, das habe ich schon versucht (hab das buch von Roland Walter hier)
aber leider hatte ich damit keinen erfolg, wenn ich das so einbaue, wird mein ausgehenden string verstümmelt, es fehlen dann CR/LF ! vielleicht liegt es daran das ja ein Interrupt ausgelöst wird wenn der sendebefehl noch nicht ganz raus ist. Zur info, ich Arbeit mit R485 in Half Duplex

ich habe jetzt mal folgendes probiert, scheint soweit auch zu laufen, jedenfalls hängt das Programm micht mehr wenn keine Antwort kommt


$regfile = "M88def.dat"
$crystal = 1000000
$hwstack = 100
$swstack = 100
$framesize = 100


Config Com1 = 4800 , Synchrone = 0 , Parity = Even , Stopbits = 1 , Databits = 7 , Clockpol = 0
Config Print = Portd.2 , Mode = Set
Config Pind.2 = Output
Config Timer0 = Timer , Prescale = 1024
'Enable Timer0
'Enable Interrupts
'On Timer0 Ontimer0

Led1 Alias Portb.0
Config Led1 = Output

Led2 Alias Portd.7
Config Led2 = Output

Led3 Alias Portd.4
Config Led3 = Output

Taster1 Alias Pind.5
Config Taster1 = Input

Taster2 Alias Pind.6
Config Taster2 = Input
'-----------------------Dim's--------------------------------------------------
Dim Test As String * 20
Dim A As Byte
Dim Kreisz As Byte
Dim Adresse As String * 2

'----------------------Haubtschleife-------------------------------------------
Do
For Kreisz = 1 To 10 Step 1

Adresse = Str(kreisz)
Adresse = Format(adresse , "00")

If Len(test) >= 18 Then
Test = ""
Led2 = 1
Else
Led2 = 0
End If
Gosub Mess
Next Kreis
Loop

'------------------Messwerte anfordern-----------------------------------------
Mess:
Waitms 100
Print "K" ; Adresse ; " " ; "M"

Do
A = Ischarwaiting()
If A = 1 Then
Led1 = 1
A = Inkey()
Test = Test + Chr(a)
End If

Loop Until Len(test) >= 18 Or Timer0 = 200

Led1 = 0
Timer0 = 0
Return

Mitch64
18.12.2010, 23:16
Hallo,

hab grad den thread gelesen.
Mir fällt dazu folgendes ein:

Anstelle eines Timers kann auch das Statement $TIMEOUT verwendet werden. Einfach mal in der Basdcom-Hilfe dazu schauen.

Mitch.

Vitis
20.12.2010, 10:40
ach so, einen Tip hab ich auch noch, anstatt eines Max485 oder LTC485, die man
aktiv zwischen Senden und Empfangen umschalten muss kann man auch
sehr oft aus dem CAN-Netz den PCA82C250 nehmen, da hat man die
Umschalterei aus dem Kreuz.

edit:

Die config Print Geschichte ist ganz nett, hab aber schon öfter festgestellt,
das beim Senden mitunter zu schnell zurück geschaltet wird, wodurch das
letzte Byte verstümmelt wird.

Mitch64
20.12.2010, 11:00
Das letzte Byte wird nicht verstümmelt, wenn man das Bit TXC im Register UCSRA abfrägt, ob der Transfer complet ist. Und erst dann wieder auf Empfang geht.

Vitis
20.12.2010, 15:31
Das letzte Byte wird nicht verstümmelt, wenn man das Bit TXC im Register UCSRA abfrägt, ob der Transfer complet ist. Und erst dann wieder auf Empfang geht.

nix anderes passiert wenn man die config print anweisung verwendet.
aber je nach terminierung des bus kann ein zu schnelles freigeben
beim empfänger als bitfehler ... framing error ankommen.
ein paar µs wartezeit kann da wunder wirken.

Mitch64
20.12.2010, 17:53
Cool, den kannte ich nicht nicht.
Config Print muss ich mir merken!

Is doch mal ein schöner Tipp am Rande.

Lucky1001
23.12.2010, 13:48
Danke für eure hilfe,
Ich habe alle drei möglichkeiten ausprobiert, also mit timer, Timeout und interrupt, habs jetzt aber beim timer belassen, damit läuft es bis jetzt ganz gut !

ich habe hab noch eine andere frage:
Ich möchte den wert einer Integer Variable als HEX senden
die Variable hat dezimal den wert 2400 also in HEX 960 !

wenn ich es so schreibe, wird 0960 satt nur 960 gesendet, was der empfäger nicht versteht. wie kann man es anstellen das wirklich nur 960 ohne 0 gesendet wird ? mir würde nur einfallen den HEX wert in einen String zu wandeln und den zu stutzen, aber geht das nicht auch anders ?


Steuern:

Prozedur = Lad
S_adresse = "02"
Real_soll_u = 12
Real_soll_i = 1

Soll_u = Real_soll_u * 200
Soll_i = Real_soll_i * 80

Print "K" ; S_adresse ; " " ; Prozedur 'Prozedur Senden
Waitms 100
Print "K" ; S_adresse ; " " ; "U" ; Hex(soll_u) 'Spannung Senden
Waitms 100
Print "K" ; S_adresse ; " " ; "I" ; Hex(soll_i) 'Strom Senden
Waitms 100
Print "K" ; S_adresse ; " " ; "S" 'Sollwert Anfordern

Lucky1001
25.12.2010, 12:13
keiner ne idee?, kann ich mir nicht vorstellen O:)

Mitch64
25.12.2010, 15:57
und woher weis der Empfänger, dass nur 3 Zeichen den Wert darstellen?
Was ist, wenn ich 5000 als Wert übertrage? Das wäre Hex 1388. Woher weis das jetzt der Empfänger, dass 4 Zeichen den Wert darstellen und nicht 3?

Bist du sicher, dass als ACII übertragen wird und das in Hex-Schreibweise?
Ich kenne dein Protokoll nicht, deshalb ist das schwierig. Was wird als Endekennung für eine Übertragung verwendet?

Woher weis der Empfänger ob ein Sollwert oder etwas anderes kommt?

Vitis
26.12.2010, 15:57
und woher weis der Empfänger, dass nur 3 Zeichen den Wert darstellen?
Was ist, wenn ich 5000 als Wert übertrage? Das wäre Hex 1388. Woher weis das jetzt der Empfänger, dass 4 Zeichen den Wert darstellen und nicht 3?

Bist du sicher, dass als ACII übertragen wird und das in Hex-Schreibweise?
Ich kenne dein Protokoll nicht, deshalb ist das schwierig. Was wird als Endekennung für eine Übertragung verwendet?

Woher weis der Empfänger ob ein Sollwert oder etwas anderes kommt?

Wenn ich so nen Käse lese ...
ACII übertragen wird und das in Hex-Schreibweise? ......

Es werden Bytes übertragen, das sind 8 Bit, in welcher Art die dargestellt werden ist doch komplett wurst. Ob sich der ANwender die Bytes als Bitfolge, oktal, dezimal, sedezimal oder als ASCII-String anzeigen lässt hat mit den übertragenen Bit und Byte nix zu tun.

Wenn der TO im Hyperterminal oder was weiß ich in welcher Terminalsoftware einen lesbaren Text erhält, der einigermaßen sinnig und schlüssig lesbar ist, dann wird das Übertragungsprotokoll mit hoher Wahrscheinlichkeit Klartext sein und keine Hex-Darstellung von Bytewerten eines Strings ....

Richard
26.12.2010, 16:21
[quote=Mitch64]
Wenn ich so nen Käse lese ...
ACII übertragen wird und das in Hex-Schreibweise? ......


Na ja, eine DWort Variable hat bei kleineren Werten in Hex halt führende Nullen. Wenn die nicht mit übertragen werden sollen muß man das DWort halt in Einzel Bytes zerlegen und führende "0" werte beim Übertragen überspringen. Wozu das auch immer gut sein soll? Ohne führende "0" kann man schnell vermuten das es sich um eine dezimal zahl handelt....

Gruß Richard