PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : SerialPort & Visual Studio 2008



fat tony
09.03.2009, 09:12
Hallo zusammen.

Bin gerade dabei einen Elektronischen Kompass zu Programmieren.
Benutze da zu einen ATMega2560 mC in Verbindung mit einem Kompassmodul.
Die Ausgabe des Winkels funktioniert mittlerweile ganz gut über das Terminal in Bascom AV.
Nun habe ich über Visual Studio eine passende Oberfläche entworfen.
Nun stellt sich mir jedoch die Frage wie ich die Winkelübergabe über USB (COM4) am besten umsetze.
Kann mir da jemand weiter helfen ?

vklaffehn
09.03.2009, 09:17
Moin!
Welche Programmiersprache nutzt Du? VB, C#, C++?
Und was genau meinst Du mit 'umsetzen'? Die Übertragung an sich, oder die Visualisierung oder ???
Mot DotNet kommt man super an die seriellen Ports ran, für C++ habe ich eine kleine Klasse, die ohne MFC und so auskommt...
MfG
Volker

fat tony
09.03.2009, 09:43
Ich programmiere mit Basic.
Mit umsetzen meine ich wie ich den Winkel (die Abweichung von Norden) von dem mC an VB übergeben kann.
Visual Basic stellt ja bei den Tools schon ein Serial Port bereit , weiß nur nicht wie ich den einbinden muss.

Das ist der Code des mC, zum senden :

....
Config Com4 = 9600 , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0
Open "com4:" For Binary As #4
....

....
Print #4 , Himmelsrichtung
....

pacer_one
09.03.2009, 09:58
Ist zwar nicht viel, aber durch diesen Artikel bin ich auch darauf aufmerksam geworden:
https://www.roboternetz.de/wissen/index.php/Windows_Programm_zum_Steuern_des_AVR%27s

fat tony
09.03.2009, 10:50
Die Seite ist gut aber irgendwie geht es bei mir immer noch nicht :(

Habe mir mal folgendes Testprogramm geschrieben:

VB

Public Class Form1

Private Sub Form1_Activated(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Activated
Me.InitializeComponent()
SerialPort1.Open()
End Sub

Private Sub cmdEingabe1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles cmdEingabe1.Click
SerialPort1.Write(1)
End Sub

Private Sub cmdEingabe2_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles cmdEingabe2.Click
SerialPort1.Write(2)
End Sub

Private Sub cmdEingabe3_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles cmdEingabe3.Click
SerialPort1.Write(3)
End Sub

Private Sub cmdReset_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles cmdReset.Click
SerialPort1.Write("r")
End Sub

Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
If SerialPort1.BytesToRead > 0 Then
Do
txtAnzeige.AppendText(Chr(SerialPort1.ReadByte))
txtAnzeige.ScrollToCaret()
If SerialPort1.BytesToRead = 0 Then
Exit Do
End If
Loop
End If
End Sub

End Class

Und in BascomAVR

$prog , 255 , &B11011001 , 'Quarz an / Teiler aus / Jtag aus

$regfile = "m2560def.dat"
$hwstack = 82 '80
$framesize = 68 ' 64
$swstack = 68 '44

$crystal = 16000000 'Quarzfrequenz

Config Pind.5 = Output
Led Alias Portd.5

Config Pine.5 = Input
Usb Alias Pine.5 'Ist 1 wenn USB angeschlossen

Config Com4 = 9600 , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0
Open "com4:" For Binary As #4 'USB Buchse



Dim A As Byte

Do
A = Inkey()
If A > 0 Then
Select Case A
Case 49 'Das ist der ASCII Code für Taste "1"
Print #4 , "Taste 1 wurde gedrückt!"
Case 50 'Das ist der ASCII Code für Taste "2"
Print #4 , "Taste 2 wurde gedrückt!"
Case 51 'Das ist der ASCII Code für Taste "3"
Print #4 , "Taste 3 wurde gedrückt!"
Case 114 'Das ist der ASCII Code für Taste "r"
Print #4 , "Reset..."
Goto 0
End Select
End If
Loop

End

Was bewirkt den das "Inkey()" da eigentlich ? Dachte das nimmt man für Tasten die auf dem Board sind und nicht über einen Port kommen ?

veit
09.03.2009, 15:54
nimm mal statt serialport1.write(..) lieber serialport1.basestream.writebyte(...)

und bei bascom hab ich waitkey statt inkey genommen..

genauere hintergründe kann ich dir auch nicht nennen, aber so gehts bei mir :)

Netzman
09.03.2009, 17:04
der Unterschied ist schnell erklärt und steht auch schön in der Hilfe drin:

While Inkey() returns a character from the serial buffer too, INKEY() continues when there is no character. Waitkey() waits until there is a character received. This blocks your program.

mfg

veit
09.03.2009, 17:25
hab eine zeile nach dem waitkey noch nen timeout gesetzt, geht prima und man verpasst das zeichen nicht ...

aber sowieso VIEL besser löst man das mit nem interrupt

fat tony
09.03.2009, 17:31
ok und wie mache ich das ?
Hast du mal ein Beispiel Prog. für mich ?

veit
09.03.2009, 17:33
ja, ich schreibs später rein, bin mal eben ne halbe stunde weg

pacer_one
09.03.2009, 17:35
würde gern mal wissen wollen wo ich sowas wie eine Befehlsübersicht finde die sich auf ein bestimmtes Elemtent (Bspw. ein Button) bezieht.
Gibt es sowas überhaupt? Mit der Hilfe bin ich da noch nicht warmgeworden.
Bei einem Mikrocontroller ist das ja recht einfach, da schaue ich einfach in die Befehlsreferenz und kann mal mit leichten Programmen anfangen. Bei Visual Studio steh ich wie der Ochs vorm Berg.

holzi
09.03.2009, 17:47
Reichen die Antworten im Microcoller-Forum nicht schon aus?

Peter

fat tony
09.03.2009, 17:53
Hör bloß auf , die Texten mich allo voll das ich das mit den Ports am mC falsch habe und schauen danach dann mal in das Datenblatt um festzustellen das ich es doch richtig gemacht habe :(
Das bringt einen nicht wirklich weiter.

veit
09.03.2009, 18:03
hmmm sehe gerade du willst ja nur vom uC lesen ... da brauchst du ja interrupts im visual studio ... hab ich auch noch nciht gemacht ...

willst du jetzt ständig von uC schicken oder erst auf kommando oder wie?

fat tony
09.03.2009, 18:53
Also sobald ich in VB einen Knopf betätige soll jeweils eine 1, 2, 3 oder ein r für reset gesandt werden.
Diese Zahl bzw das "r" für reset soll dann vom Controler ausgewertet werden und dem entsprechend soll er "Taste X wurde gedrückt!" zurück an den PC senden wo es dann in der Textbox ausgegeben wird.

Netzman
09.03.2009, 19:28
dafür reichts µC-seitig mit Waitkey allemal.
in VB kannst du das zb. per Polling abfragen (ein Timer der alle Hausnummer mSec nachschaut, ob im Puffer Daten sind und diese ausliest
SerPort.BytesToRead()) oder, was viel eleganter ist,
SerPort.ReceivedBytesThreshold = wievieleZeichenwillstdu, den Serport mit
Private WithEvents SerPort As System.IO.Ports.SerialPort = New System.IO.Ports.SerialPort initialisieren und eine Funktion erstellen:
Private Sub Serial_BytesReceived(ByVal sender As System.Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerPort.DataReceived

End Sub

Damit wird der Sub aufgerufen wenn x Bytes angekommen sind.
Aufpassen musst du dann nur noch mit der Zuweisung auf die Textbox, das geht nicht so einfach. Mit einem Umweg über eine extra Variable gehts, also SerPort-Sub->Variable->Textbox.

Wo liegt dein Problem mit der Hilfe? Wenn du den Cursor auf die Instanz der gewünschten Klasse setzt und F1 drückst, werden schön alle Mitglieder, Methoden, Eigenschaften etc. der Klasse aufgelistet...

mfg

fat tony
09.03.2009, 19:57
Hab jetzt mal bei der TextBox noch ne Variable zwischen gepackt.
Die .BytesToRead() verwende ich ja bereits in Verbindung mit einem TimerIntervall.

Hier noch mal der Aktuelle Code:

VB


Public Class Form1
Dim Text As String
Private Sub Form1_Activated(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Activated
Me.InitializeComponent()
SerialPort1.Open()
End Sub

Private Sub cmdEingabe1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles cmdEingabe1.Click
SerialPort1.BaseStream.WriteByte(1)
End Sub

Private Sub cmdEingabe2_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles cmdEingabe2.Click
SerialPort1.BaseStream.WriteByte(2)
End Sub

Private Sub cmdEingabe3_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles cmdEingabe3.Click
SerialPort1.BaseStream.WriteByte(3)
End Sub

Private Sub cmdReset_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles cmdReset.Click
SerialPort1.BaseStream.WriteByte("r")
End Sub

Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
If SerialPort1.BytesToRead > 0 Then
Do
Text = SerialPort1.ReadByte
txtAnzeige.AppendText(Text)
txtAnzeige.ScrollToCaret()
If SerialPort1.BytesToRead = 0 Then
Exit Do
End If
Loop
End If
End Sub

End Class


Bascom

$prog , 255 , &B11011001 , 'Quarz an / Teiler aus / Jtag aus

$regfile = "m2560def.dat"
$hwstack = 82 '80
$framesize = 68 ' 64
$swstack = 68 '44

$crystal = 16000000 'Quarzfrequenz

Config Pind.5 = Output
Led Alias Portd.5

Config Pine.5 = Input
Usb Alias Pine.5 'Ist 1 wenn USB angeschlossen

Config Com4 = 9600 , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0
Open "com4:" For Binary As #4 'USB Buchse



Dim A As Byte

Do
A = Waitkey()
Waitms 20
If A > 0 Then
Select Case A
Case 49 'Das ist der ASCII Code für Taste "1"
Led = 1
Waitms 200
Led = 0
Print #4 , "Taste 1 wurde gedrückt!"
Case 50 'Das ist der ASCII Code für Taste "2"
Led = 1
Waitms 200
Led = 0
Waitms 100
Led = 1
Waitms 200
Led = 0
Print #4 , "Taste 2 wurde gedrückt!"
Case 51 'Das ist der ASCII Code für Taste "3"
Print #4 , "Taste 3 wurde gedrückt!"
Case 114 'Das ist der ASCII Code für Taste "r"
Print #4 , "Reset..."
Goto 0
End Select
End If
Loop

End
Habe jetzt mal noch eine LED mit eingebaut um zu sehen ob der Eingangsbefehl auch ankommt.

Was ich nicht ganz bei dem Basecom verstehe , ich schreibe den Wert den ich von Waitkey() bekomme in A und springe dann je nach Wert in die entsprechenden Case. Nur steht im Testprogramm

Case 49 'Das ist der ASCII Code für Taste "1"
Aber der ASCII für 1 ist doch 0x31 oder ?

Netzman
09.03.2009, 20:07
du musst in VB aber auch den ASCII Code für "1" senden ;)
BaseStream.WriteByte verlangt als Argument ein Byte...
also

Private Sub cmdEingabe1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles cmdEingabe1.Click
SerialPort1.BaseStream.WriteByte(49)
End Sub
mfg

fat tony
09.03.2009, 20:44
Ok ich hab einen kleinen Erfolg :)
Zumindest Daten empfangen läuft jetzt :)

fat tony
09.03.2009, 21:11
Kann es sein das ich da noch einen Fehler in dem Controller Programm habe ?
Wie kann ich den mal Testen ob mein VB Programm die Daten über den COM sendet ?

Netzman
09.03.2009, 21:40
Dafür verwende ich ein virtuelles Nullmodem - com0com, das erstellt 2 virtuelle serielle Ports die miteinander verbunden sind, an einen "hängst" du dein VB-Programm, an den anderen ein Terminal (bei mir Docklight).
Das funktioniert leider nicht mit dem Bascom-Simulator, habe zu diesem Problem schon hier und im englischen Forum gepostet und auch an den Support geschrieben, ohne Ergebnis...

Hardwaremäßig funktioniert die Verbindung? schon durchgemessen, wenn dein VB-Programm sendet ob was am Controller ankommt und umgekehrt?

mfg

fat tony
10.03.2009, 08:16
Ok hab das jetzt mal mit com0com und Docklight aufgebaut.
Mein VB Prog sendet einwandfrei .Danke für den Tipp Netzman das sind echt mal nützliche tools.

Also liegt mein Fehler in Basecom.
Was ist denn mit Waitkey() oder Inkey() ? Gibt es da keine anderen Aufruf um Daten aus dem Buffer zu lesen ?

Netzman
10.03.2009, 10:49
Gibt es, Inputbin liest die Daten binär in eine Variable, soviele Bytes wie die Variable groß ist, beginnend mit dem MSB.

mfg

fat tony
10.03.2009, 13:59
Hab das ganze jetzt mal noch einfacher versucht :

Config Com4 = 9600 , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0
Open "com4:" For Binary As #4 'USB Buchse

Dim My_byte As Byte
Dim My_string As String * 1

Do
My_byte = Waitkey()
Print #4 , "Empfangen: " ; My_byte 'Gibt den ASCII-Code des Zeichens zurück

My_string = Waitkey()
Print #4 , "Empfangen: " ; My_string 'Gibt den Text zurück
Loop
End
Geht aber immer noch nicht :(

Netzman
10.03.2009, 14:34
Was genau geht nicht?
Codemäßig sollte das IMHO hinhauen.
Wie gesagt, der Simulator hat ein Problem mit seriellen Terminals, er empfängt nichts, senden geht aber.
Wenn du InSystem testest, würde ich wie schon erwähnt prüfen ob auch die Signale dort ankommen wo sie sollten.

mfg

fat tony
10.03.2009, 14:49
Also das VB Prog läuft so wie es soll.
Habe mit dem com0com die Buttons empfangen und umgekehrt wurden die Zahlen oder Zeichen die ich in Docklight eingab auch in dem VB Fenster ausgegeben.
Klemme ich jetzt mein VBprog an den mC und lasse den mC irgendwas senden kommt das auch im Fenster an.
Wenn ich aber versucht mit dem Oben stehenden Prog die Sachen die ich an den mC sender von diesem einfach wieder zurück zu schicken zu lassen macht er das nicht.

fat tony
10.03.2009, 21:56
Also ich bin jetzt schon mal einen Schritt weiter , das Problem war das der "Print #4 , Wert " immer noch ein CR und LF mitschickt die ich jedoch in meiner Abfrage nicht berücksichtigt hatte, hab jetzt
jetzt noch ein ";" dahinter gehangen und schon läuft die Kiste :)

fat tony
11.03.2009, 12:27
So hab jetzt alles am laufen.
Das Problem war das ich einmal nicht nur das Zeichen sondern auch den CR und LF sendete und zum anderen hatte ich "inputbin A" anstelle von "Inputbin #4 , A" geschrieben.

Noch mal vielen Dank für eure Hilfe.
Vor Allen an Netzman , ohne die Tools hätte ich das nicht so schnell herausgefunden.

pacer_one
11.03.2009, 12:39
Hallo tony,

der Quellcode von deinem VB-Programm wäre sicher von allgemeinen Interesse. Ich für meinen Teil interessiere mich auf jeden Fall dafür.
Würde mich freuen, wenn du deinen Quellcode hier posten würdest.

An Netman ebenfalls mein Dank, hätte mir schon fast für viel Geld ein Nullmodemkabel gekauft. Eventuell wäre es hilfreich den von mir geposteten Wiki-Eintrag um einen kurzen Hinweis zu diesem Programm zu erweitern.

Gruß, pacer

fat tony
11.03.2009, 17:07
Hier einmal die Bedienoberfläche zu dem Programm :

http://picfront.de/d/Gx15Vvlqlu/Unbenannt-1Kopie.gif

Und hier der VB Code :

Public Class Form1

Dim Anzeigewert As String

Private Sub Form1_Activated(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Activated
SerialPort1.Open()
End Sub

Private Sub cmdEingabe1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles cmdEingabe1.Click
SerialPort1.Write(1)
End Sub

Private Sub cmdEingabe2_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles cmdEingabe2.Click
SerialPort1.Write(2)
End Sub

Private Sub cmdEingabe3_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles cmdEingabe3.Click
SerialPort1.Write(3)
End Sub

Private Sub cmdReset_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles cmdReset.Click
SerialPort1.Write("r")
End Sub

Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
If SerialPort1.BytesToRead > 0 Then
Do
Anzeigewert = Chr(SerialPort1.ReadByte)
txtAnzeige.AppendText(Anzeigewert)
txtAnzeige.ScrollToCaret()
If SerialPort1.BytesToRead = 0 Then
Exit Do
End If
Loop
End If
End Sub

End Class


Und der Basecom-AVR:

$prog , 255 , &B11011001 , 'Quarz an / Teiler aus / Jtag aus

$regfile = "m2560def.dat"
$hwstack = 82 '80
$framesize = 68 ' 64
$swstack = 68 '44

$crystal = 16000000 'Quarzfrequenz

Config Pind.5 = Output
Led Alias Portd.5


Config Com4 = 9600 , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0
Open "com4:" For Binary As #4 'USB Buchse



Dim A As Byte
Led = 1

Do
Inputbin #4 , A
If A > 0 Then
Select Case A
Case 49 'Das ist der ASCII Code für Taste "1"
Led = 0
Print #4 , "LED = Ein"
Case 50 'Das ist der ASCII Code für Taste "2"
Led = 1
Print #4 , "LED = Aus"
Case 51 'Das ist der ASCII Code für Taste "3"
Print #4 , "Taste 3 wurde gedrückt!"
Case 114 'Das ist der ASCII Code für Taste "r"
Print #4 , "Reset..."
Goto 0
Case Else
Print #4 , "Error"
End Select
End If
Loop

End

DEAF BOY
09.01.2012, 15:09
Hab ähnliche Problem. Ich kann von 1 bis 9 steuern. Von 10 bis 255 nicht.

Insgesamt sind 11 Buttons eingabaut.

1 = Unten links
2 = Unten
3 = Unten rechts
4 = Links
5 = Motorstopp
6 = Rechts
7 = Oben links
8 = Oben
9 = Oben rechts
10 = Stift runter
11 = Stift hoch

Visual Basic 2010

Private Sub Button10_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button10.Click
SerialPort1.Open()
SerialPort1.Write("10")
SerialPort1.Close()
End Sub

BASCOM-AVR

.
.
Dim B as String * 2

Do
B = Waitkey()

Select Case B

Case "10" : Gosub Kpd_plus

End Select

Loop

Stift fährt nicht runter.

PicNick
09.01.2012, 15:26
"Waitkey() liest ja nur ein Byte. (also "1"-"9")
"10"-"255" sind aber zwei bis drei Zeichen