Forum: PC-Programmierung PWM in Visual Basic


von NikWin (Gast)


Lesenswert?

Hallo,
ich stehe vor folgendem Problem:
füre ein Projekt will ich eine HP-Led (NoName China Led) am seriellen 
Port des PCs dimmen.
Bisher klappt das aber nur mäßíg, das einzige was ich zu stande bringe 
ist ein einfaches blinken.
Die Blinkgeschwindigkeit wird von einer Scrollleiste, die von 50 bis 500 
geht gesteuert.
Die gibt dann dem Timer die Geschwindigkeit an.
Welche Freuquenz brauche ich für ein PWM Dimmen???

Declare Function OPENCOM Lib "RSLINE.DLL" (ByVal A As Integer) As 
Integer
Declare Sub Delay Lib "RSLINE.DLL" (ByVal Zeit As Integer)
Declare Sub DTR Lib "RSLINE.DLL" (ByVal An As Integer)
Declare Sub RTS Lib "RSLINE.DLL" (ByVal An As Integer)
Declare Sub TXD Lib "RSLINE.DLL" (ByVal An As Integer)
Declare Function CTS Lib "RSLINE.DLL" () As Integer
Declare Function DCD Lib "RSLINE.DLL" () As Integer
Declare Function DSR Lib "RSLINE.DLL" () As Integer
Declare Function RI Lib "RSLINE.DLL" () As Integer
Declare Sub TimeINIT Lib "RSLINE.DLL" ()
Declare Function TIMEREAD Lib "RSLINE.DLL" () As Integer

Dim Ausgang1 As Integer
Dim Ausgang2 As Integer




Sub Command2_Click ()
Timer1.Enabled = False
End Sub

Sub Form_Load ()
 If App.PrevInstance Then
    msg$ = App.EXEName & " wurde bereits gestartet "
    MsgBox msg$, 48
    End
 End If
 i = OPENCOM(2)
 If i = 0 Then
    i = OPENCOM(1)
    Option1.Value = True
 End If
 If i = 0 Then MsgBox ("Schnittstelle nicht verfügbar")

 Timer1.Enabled = False
 Ausgang1 = 1
 Ausgang2 = 1
 DTR 0
 RTS 0
 TXD 1
End Sub

Sub HScroll1_Change ()
 Timer1.Interval = Hscroll1.Value + 10
End Sub

Sub Option1_Click ()
 i = OPENCOM(1)
 If i = 0 Then MsgBox ("COM1 nicht verfügbar")
 DTR 0
 RTS 0
 TXD 1
End Sub

Sub Option2_Click ()
 i = OPENCOM(2)
 If i = 0 Then MsgBox ("COM2 nicht verfügbar")
 DTR 0
 RTS 0
 TXD 1
End Sub

Sub Start_Click ()
  Timer1.Interval = Hscroll1.Value + 10
  Ausgang1 = 1
  Ausgang2 = 0


Danke

von spess53 (Gast)


Lesenswert?

Hi

>Welche Freuquenz brauche ich für ein PWM Dimmen???

Auf jeden Fall eine höhere, als du mit dem Windowstimer erreichen 
kannst.
Meiner Erfahrung nach, kann man den unterhalb von 70ms knicken.

MfG Spess

von NikWin (Gast)


Lesenswert?

Und wie mache ich das sonst?

von Helmut L. (helmi1)


Lesenswert?

>Und wie mache ich das sonst?

An die Schnittstelle einen AVR anschliessen und den Programmieren

Gruss Helmi

von Hannes Lux (Gast)


Lesenswert?

> Und wie mache ich das sonst?

Schau Dir die ELEXS.dll an, sie erlaubt kleinere Zeiten für die 
COM-Pins.

Wobei ich allerdings das Betreiben einer LED am COM-Port nich gerade als 
erstrebenswert sehe. Die bessere Lösung ist der Einsatz eines 
Mikrocontrollers, der seine Daten per UART vom PC empfängt.

...

von NikWin (Gast)


Lesenswert?

Ok, hab die Elexs.ddl gedownloadet, funktioniert auch super.

Welche Werte in meinem Programm soll ich jetzt wie ändern um mit der 
Scrollleiste die Helligkeit der Led zu verändern???

von Sven P. (Gast)


Lesenswert?

Am Rande:
Nimm mal deinen Versuch mit dem Timer-Bedienelement und lass das laufen. 
Dann pack mit dem Mauszeiger das Fenster und verschieb es, beobachte 
dabei, was der Timer macht :-)

Obs heute noch so ist, weiß ich nicht, früher(tm) jedenfalls blieb der 
dann einfach stehen.

von Hannes Lux (Gast)


Lesenswert?

> Ok, hab die Elexs.ddl gedownloadet, funktioniert auch super.

Na prima. Ich habe sie genutzt, um Schieberegisterketten anzusteuern.

> Welche Werte in meinem Programm soll ich jetzt wie ändern um mit der
> Scrollleiste die Helligkeit der Led zu verändern???

Schau Dir doch einfach mal die Projekte bei Elexs an. Da steht viel über 
die Möglichkeitenden des Missbrauchs des COM-Ports und deren Grenzen 
geschrieben.

...

von NikWin (Gast)


Lesenswert?

Aber da steht nix über PWM.

von Hannes Lux (Gast)


Lesenswert?

> Aber da steht nix über PWM.

Definiere mal "PWM".

Definiere mal "Blinken"

Definiere mal den Unterschied zwischen Beiden.

...

von Z8 (Gast)


Lesenswert?

>Auf jeden Fall eine höhere, als du mit dem Windowstimer erreichen
>kannst.
>Meiner Erfahrung nach, kann man den unterhalb von 70ms knicken.

so ein Quatsch!

http://msdn.microsoft.com/en-us/library/ms644904.aspx

von Sven P. (Gast)


Lesenswert?

Z8 schrieb:
>>Auf jeden Fall eine höhere, als du mit dem Windowstimer erreichen
>>kannst.
>>Meiner Erfahrung nach, kann man den unterhalb von 70ms knicken.
>
> so ein Quatsch!
>
> http://msdn.microsoft.com/en-us/library/ms644904.aspx

So ein Quatsch!
Du musst immer noch mit Schleifen rumwursteln, und dieser hochgenaue 
Timer hilft dir dabei auch nicht. Genau wird das sowieso nicht, da 
Windows nicht mit 'Echtzeit' klarkommt.

von Z8 (Gast)


Lesenswert?

'** für hochauflösenden Timer
   Private Declare Function QueryPerformanceFrequency Lib "kernel32" 
(lpFrequency As Any) As Long
   Private Declare Function QueryPerformanceCounter Lib "kernel32" 
(lpPerformanceCount As Any) As Long

   Private Type Large
     LSW As Long
     MSW As Long
   End Type

Public Sub WaitTime(DelayMilliSec As Single)
  '** Hochauflösend bis auf ca. 0.2 Millisekunden genau
  '** Kontroliert mit Überlauf am 26.10.2001 Z8
  Dim Wert As Large

  '** es werden nur 27 Bit genutzt
  Const LetzterTimerTakt As Long = &H7FFFFFF '&H7FFFFFFF
  Dim StartZeitPunkt As Long
  Dim EndZeitpunkt As Long
  Dim AnzahlTakte As Long
  Dim AktWert As Long

  QueryPerformanceFrequency Wert
  '** jetz steht (Wert.LSW And LetzterTimerTakt) die Frequenz des 
Hochauflösenden Timers
  AnzahlTakte = DelayMilliSec * (Wert.LSW And LetzterTimerTakt) / 1000
  '** Startzeitpunkt der Counters hohlen
  QueryPerformanceCounter Wert
  StartZeitPunkt = Wert.LSW And LetzterTimerTakt
  '** Endzeitpunkt errechnen
  EndZeitpunkt = StartZeitPunkt + AnzahlTakte
  If EndZeitpunkt > LetzterTimerTakt Then 'Überlauf eingeplant
    '** Timerüberlauf tritt ca. alle 20 Sec Rechnerlaufzeit auf
    '** neuen EndZeitpunkt errechnen erstmal bis Überlauf warten
    EndZeitpunkt = EndZeitpunkt - LetzterTimerTakt
    Do
      '** warten bis Überlauf
      QueryPerformanceCounter Wert
      AktWert = Wert.LSW And LetzterTimerTakt
    Loop Until AktWert < StartZeitPunkt
    While AktWert < EndZeitpunkt
      '** und dann von Null bis Restliche Takte warten
      QueryPerformanceCounter Wert
      AktWert = Wert.LSW And LetzterTimerTakt
    Wend
  Else
    Do
      '** Zeitschleife bis Endzeitpunkt erreicht ist
      '** oder Timer überschnappt
      QueryPerformanceCounter Wert
      AktWert = (Wert.LSW And LetzterTimerTakt)
    Loop Until (AktWert > EndZeitpunkt) Or (AktWert < StartZeitPunkt)
  End If
End Sub


... so mein Freund haku,
    diese Sub WaitTime geht auf ca. 0.2ms genau!
    Genauer braucht man es für eine PWM nicht.

von JojoS (Gast)


Lesenswert?

oha, da lässt man einen Ghz schnellen Pentium in Endlosschleifen zig 
Watt verbraten um ein paar ms zu warten... Suche lieber nach 
'SetWaitableTimer' und den verwanten Funktionen. Bei hoher Prozessprio 
läuft das schon recht stabil, obwohl man sicher auch 10ms Aussetzter im 
Lich sieht und als störend empfindet. Aber das man mit Fensterwackeln 
alles ausbremst war mal zu Win3.1 und Win95 Zeiten.

von Karl H. (kbuchegg)


Lesenswert?

Z8 schrieb:

>     diese Sub WaitTime geht auf ca. 0.2ms genau!
>     Genauer braucht man es für eine PWM nicht.

Und dann kommt dein Windows und entscheidet, dass es wieder mal Zeit ist 
den Festplattencache aufzuräumen. Was denkst du wird dann wohl mit 
deinen Warteschleifen schönes passieren :-)

von Hannes Lux (Gast)


Lesenswert?

Wäre es nicht langsam Zeit, diesen Thread nach PC-Programmierung zu 
verschieben?

...

von Karl H. (kbuchegg)


Lesenswert?

Hannes Lux schrieb:
> Wäre es nicht langsam Zeit, diesen Thread nach PC-Programmierung zu
> verschieben?
>
> ...

Da hat er recht :-) Done

von Sven P. (Gast)


Lesenswert?

Z8 schrieb:
> ... so mein Freund haku,
>     diese Sub WaitTime geht auf ca. 0.2ms genau!
>     Genauer braucht man es für eine PWM nicht.

Is ja Wahnsinn. Wovon träumst du eigentlich nachts?

Ich werf mal son paar Schlüsselworte in die Runde:
- usleep()
- ualarm()
- Multitasking
- Effizienz

Und deine Routine geht auch nicht genau, das garantiere ich dir. Plan 
mal lieber noch Portzugriffe ein. 2,5 bzw. 5 kHz geben übrigens einen 
ganz schön nervigen Ton ab :-)

von Z8 (Gast)


Lesenswert?

nun werfe ich zurück:

Private Declare Function SetPriorityClass Lib "kernel32" (ByVal hProcess 
As Long, ByVal dwPriorityClass As Long) As Long

:)

mfg Z8

von Sven P. (Gast)


Lesenswert?

Aber selbst damit bist du nicht der einzige im System.

von Z8 (Gast)


Lesenswert?

... doch mit dem Parameter "REALTIME_PRIORITY_CLASS" bin ich das!
    Alles schläft Festplattencacheing, Mouse, ... einfach alles.

Z8

von Karl H. (kbuchegg)


Lesenswert?

Z8 schrieb:
> ... doch mit dem Parameter "REALTIME_PRIORITY_CLASS" bin ich das!
>     Alles schläft Festplattencacheing, Mouse, ... einfach alles.

Dein Benutzer wird es dir danken und dich mit Geschenken überhäufen :-)

von Sven P. (Gast)


Lesenswert?

Was passiert denn mit den anderen Prozessen, die als 
REALTIME_PRIORITY_CLASS laufen?

von JojoS (Gast)


Lesenswert?

...womit man sich ruck zuck Deadlocks einhandelt weil der hochpriore 
Prozess dann auf Sachen wartet die ihm ein niederpriorer nicht liefern 
kann. Die Echtzeitprio ist noch über dem Win OS, und da muss man 
höllisch aufpassen was man tut. Und VB6 Programme erledigen alles in der 
MessageLoop, die wird vom OS gefüttert. Also Multimedia Timer oder 
Waitable Timer, aber das ist in VB auch kein Vergnügen. Da wäre ein 
ATMega8 und ein paar Kleinteile doch sinnvoller, vor allem kann es dann 
auch leuchten wenn der PC aus ist. Ansteuerungen für LEDs gibts hier im 
Forum auch reichlich.

von Z8 (Gast)


Lesenswert?

Heee!

Das ist für kurze Reservierungszeiten gedacht!
Für eine PWM über die RS232 völlig überzogen.

Hab das mal für eine Schrittmotorsteuertung im Prototypenstadium 
gebraucht.
(W98-Zeiten)

Oben wurde mal "SetWaitableTimer", "CreatWaitableTimer" erwähnt, das 
wäre heute die Wahl.

Ich würde das auch mit einem µC realiesieren. (µC macht die 
Kommunikation
über RS232 und nebenbei die PWM.

Bevor ihr mich weiter angreift, ich halte das auch nicht für besonders 
geschickt.

Grüße Z8

von Z8 (Gast)


Lesenswert?

>Was passiert denn mit den anderen Prozessen, die als
>REALTIME_PRIORITY_CLASS laufen?

... gibt es nicht, wer zuerst kommt hat das Sagen!
    ähnlich den Interups bei AVR Tiny und Mega. Z8

von Sven P. (Gast)


Lesenswert?

Am Rande:

Z8 schrieb:
>>Was passiert denn mit den anderen Prozessen, die als
>>REALTIME_PRIORITY_CLASS laufen?
>
> ... gibt es nicht, wer zuerst kommt hat das Sagen!
>     ähnlich den Interups bei AVR Tiny und Mega. Z8
Mal vorausgesetzt, man möchte noch mit dem System arbeiten, währen das 
Programm läuft:
Dann ist es ja wieder nicht Echtzeit, denn die Prioritätsklasse müsste 
regelmäßig wieder abgetreten werden, damit der Rest im System 
nachkommt...

Aber wie schon gesagt: ATtiny dran und fertig.
Zur Not geht auch nochn Schieberegister, welches man vorladen kann. Dann 
reihum takten.

von Micha (Gast)


Lesenswert?

Hallo! Ichj habe mal den langen Code (0,2ms Auflösung) in ein leeres 
Projekt kopiert. Funzt überhaupt gar nicht erst. Was mach ich denn da 
falsch? Kann mir das bitte einer sagen oder besser der Autor des 
Beitrages? Danke schön

von Sven P. (Gast)


Lesenswert?

PWM aus VB heraus bringt es nicht, das wurde doch hier ausreichend 
erläutert, oder?

von Sigint 112 (sigint)


Lesenswert?


von zwieblum (Gast)


Lesenswert?

he ho, leute, mal langsam. die serielle kann man durchaus als PWM 
missbrauchen, nur hganz dunkel wirds halt nicht und ganz auch nicht. der 
trick ist, einfach die höchste baudrate (115200 oder mehr) einstellen, 
wenns geht mehr als 8 datenbits, und dann einfach daten rausschieben. 
led zwischen TX und GND. nicht das gelbe vom ei, aber funktioniert.

wenns besser gehen soll dann kann man lpt verwenden, da fehlen dann die 
start/stop-bits.

von Sven P. (Gast)


Lesenswert?

zwieblum schrieb:
> wenns besser gehen soll dann kann man lpt verwenden, da fehlen dann die
> start/stop-bits.

Und was hilft uns das, wenn wir mit Visual Basic arbeiten und mit bzw. 
gegen unbestimmbares Timing durch Multitasking kämpfen?

von zwieblum (Gast)


Lesenswert?

das timing vom druckerport kannst einstellen, brauchst nur eine 
verzögerung swischen STROBE und ACK (schau in die doku von der 
centronics schnittstelle).

ach ja, du musst natürlich vorher vorbereiten, was du zum drucker 
schickst - die ausgabe erledigt ja das OS, das soll aber dafür  länger 
als eine sekunde brauchen.

von Micha (Gast)


Lesenswert?

Ne Jungs, ich habe nicht das Problem, mir eine PWM bauen zu wollen, das 
würd ich anders machen  :-). Ich brauche etwas, was dem Rechner immer 
die Millisekunden entlockt, und zwar jede einzelne oder noch besser. Da 
klingt 0,2ms gut. Nur kommt bei dem Code von z8 bei mir immer die 
Fehlermeldung: "Benutzerdefinierter Typ nicht definiert". Was muß ich 
denn noch alles definieren? Ich dachte, hier stellt mal einer einen 
gängigen Beispielcode ein, alles andere verwirrt einen doch nur noch 
mehr, wenn da die Hälfte nicht geht.
Was ganz interessant ist, wenn ich zu meinem Projekt einfach im 
Hintergrund den Windows Mediaplayer öffne, dann funzt es mit jeder 
einzelnen ms, wenn er nicht an ist, nur 100stel sec. Genauso verhält es 
sich mit einer Flashdatei in nem Browser, wenn da eine Seite mit Flash 
geladen ist, geht in meinem Projekt jede ms abzurufen.
Das Problem muß doch mal einer kennen und nachvollziehen können, es gibt 
doch so viele Schaumschläger :-)
Ich hoffe, ihr habt mein Problem verstanden und noch mehr auf eine 
Lösung, danke! g

von zwieblum (Gast)


Lesenswert?

in welcher zeile kommt der fehler?

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

> Was ganz interessant ist, wenn ich zu meinem Projekt einfach im
> Hintergrund den Windows Mediaplayer öffne, dann funzt es mit jeder
> einzelnen ms, wenn er nicht an ist, nur 100stel sec.

Dafür gibt es eine Erklärung. Der Windows-Scheduler arbeitet 
üblicherweise mit 10 msec Auflösung. Es ist aber möglich, diese 
Auflösung auf 1 msec zu erhöhen, und das geschieht mit den sogenannten 
Multimedia-Timer-Funktionen.

  timeBeginPeriod(UINT uPeriod);

Deklariert in mmsystem.h

uPeriod ist die gewünschte Timerauflösung in msec.

Um den Ausgangszustand wiederherzustellen, ist die korrespondierende 
Funktion

  timeEndPeriod(UINT uPeriod);

aufzurufen, Parameter ist hier die zu deaktivierende Timerauflösung in 
msec, also der gleiche Wert, der auch timeBeginPeriod übergeben wurde.

Programme wie der Mediaplayer und offensichtlich auch das Flash-Plugin 
nutzen diese Funktionen.

Es ist übrigens nicht möglich, ohne spezielle Devicetreiber mit einem 
Windows-Usermode-Programm eine höhere Timerauflösung als 1 msec zu 
erzielen; der Versuch, eine PWM durch schnelles Wackeln an irgendwelchen 
Portpins zu erzeugen, ist auch deswegen zum Scheitern verurteilt.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.