Erweiterte Ambilight Windows Software für Adalight (Arduino)

Du brauchst Grafiken, gute Programme oder Leute die dir helfen? Frag hier.
Benutzeravatar
Hoto
Beiträge: 294
Registriert: 01.09.2004 22:51

Erweiterte Ambilight Windows Software für Adalight (Arduino)

Beitrag von Hoto »

Ich habe mir Anfang des Monats ein Ambilight (ein YT Video) für meinen PC / Monitor gebastelt. Da ich PC Gamer bin und sonst fast auch alles am PC mache (Netflix etc.), bot sich das eigentlich schon länger an. Keine Ahnung wieso ich das erst jetzt umgesetzt habe, Anleitungen (Stichwörter: DIY PC Arduino Ambilight) dazu gibt es schon seit Jahren im Netz und teuer ist es auch nicht wirklich (ca. 70 Euro waren es bei mir).

Warum aber nun mein Projekt ist, eine Ambilight Software mit PureBasic zu schreiben? Weil ich nach etwas testen schnell gemerkt habe, dass es zwar Software gibt, die an sich auch gut funktioniert, aber mit dessen Ergebnissen und Funktionsumfang ich nicht wirklich zufrieden war, das geht definitiv besser.

Aktuell sieht das Projekt so aus:

- Desktop Inhalt per Desktop Duplication API (DX11) auslesen.
- Bildbereiche für die einzelnen LEDs festlegen und die Position der LEDs dazu.
- Senden der berechneten Farben per COM Schnittstelle mit dem Adalight Protocol an den Ardunio.

Soweit die Grundfunktion, letzteres läuft bereits einwandfrei, an zweiterem (der Berechnung) arbeite ich gerade anhand von einzelnen Testbildern, weil ich mit ersterem einfach nicht weiter komme (siehe Thread im Windows Forum), bleibt mir gerade nichts anderes übrig.

Was soll die Software dann mehr können als Andere?

- Berechnen der Farbe Anhand größerer Bildbereiche und der LED Position (letzteres berücksichtigt bisher keine Software).
- Automatische Nutzungs Profile, je nach dem welche Software gerade aktiv ist.
- Tageszeit Modus - eine Farbe oder ein Farbmuster je nach Tageszeit (alles einstellbar), für den normalen Arbeitsbetrieb.
- Verschiedene anpassbare Farb Profile für das berechnen der Farben, z.B. eines eher für Filme, eines eher für Spiele etc.
- Anpassbare Farbkorrektur (bei dunklen Mischfarben erzeugen meine LED Strips gerne falsche Farben, z.B. statt einem Braun hat man eher ein Grün).
- möglichst überall flexibel anpassbar.

Letzteres könnte man sicherlich auch in die Arduino Software schreiben, könnte aber auch die PC Software übernehmen.

Weitere Ideen könnten sicherlich noch folgen, aber erst mal diese Dinge umsetzen.

Die Software will ich dann als Freeware zum Download zur Verfügung stellen.

Hilfe bräuchte ich aktuell nur bei der Desktop Duplication API (siehe Thread im Windows Unterforum) und später beim testen und verbessern der Software. Sollte ich später neben Adalight noch andere Ambilight Schnittstellen unterstützen, werde ich sicherlich auch dort Hilfe brauchen.
Benutzeravatar
RSBasic
Admin
Beiträge: 8022
Registriert: 05.10.2006 18:55
Wohnort: Gernsbach
Kontaktdaten:

Re: Erweiterte Ambilight Windows Software für Adalight (Ardu

Beitrag von RSBasic »

Willkommen zurück.
Hoto hat geschrieben:- Desktop Inhalt per Desktop Duplication API (DX11) auslesen.
Das habe ich mich schon in deinem anderen Thread gefragt, wozu du das eigentlich brauchst.
Reicht es nicht aus, ein paar Pixel mit der WinAPI-Schnitstelle auszulesen? Warum muss das DirectX sein?
Aus privaten Gründen habe ich leider nicht mehr so viel Zeit wie früher. Bitte habt Verständnis dafür.
Bild
Bild
Benutzeravatar
Hoto
Beiträge: 294
Registriert: 01.09.2004 22:51

Re: Erweiterte Ambilight Windows Software für Adalight (Ardu

Beitrag von Hoto »

Wegen Geschwindigkeit und Delay.

Meines Wissenstands nach (vor Jahren schon genutzt) ist die WinApi Lösung schlicht zu langsam und würde es niemals schaffen eine 4K Auflösung aller min. 15x in der Sekunde zu capturen und genug Zeit zu lassen das alles auch noch vor dem nächsten Bild auszuwerten, so das zwischen Bildschirm Inhalt und LED Farben ein so geringer Delay wie möglich ist. Dazu braucht es die schnellste Methode und nach rumsuchen in den letzten Tagen ist die Desktop Duplication Api scheinbar die schnellste und funktioniert definitiv auch in allen DX11 und DX12 Spielen.

Ein paar Pixel reichen da nicht, für ein gutes Ergebnis brauche ich da deutlich mehr (schätze grob 80% des Bildes für meine Methode). Ich könnte zwar nur jeden 2. Pixel auslesen, aber das würde schon wieder das Ergebnis je nach Bildinhalt mehr oder weniger verfälschen. Und jeden Pixel einzeln auszulesen dürfte dennoch nicht sonderlich schnell sein (bei mir sind das 115 RGB LEDs, die einzeln berechnet werden müssen). Und gerade das Ergebnis besser zu machen als es in den anderen Programmen ist, war ja mein Hauptgrund selbst eines zu schreiben.

Auch kenne ich diverse Software, die den Desktop in 3D Anwendungen (VR Bereich) einblenden und dort erst mit der Desktop Duplication Api ausreichend FPS mit keinem spürbaren Delay erreicht haben. Nur als Beispiel: die Api schafft es 1080p mit 120 FPS in 120 FPS zu capturen.
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8675
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 32 GB DDR4-3200
Ubuntu 22.04.3 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken
Kontaktdaten:

Re: Erweiterte Ambilight Windows Software für Adalight (Ardu

Beitrag von NicTheQuick »

Da diese API über C++ ansprechbar ist, wird es schwierig oder zumindest unnötig schwer das ganze auf Purebasic zu portieren, da Purebasic kein OOP kann. Vielleicht solltest du die API von C++ aus nutzen und dann die Daten an Purebasic weitergeben. Damit kannst du dann eine GUI bauen und die Daten an die RGB-LEDs weitergeben. Aber über den COM-Port ist das schon etwas blöd, oder? Wie wäre es direkt über USB und einem kleinen Mikrocontroller auf der anderen Seite, der die LEDs ansteuert?
Bild
Benutzeravatar
Hoto
Beiträge: 294
Registriert: 01.09.2004 22:51

Re: Erweiterte Ambilight Windows Software für Adalight (Ardu

Beitrag von Hoto »

Könnte man damit vielleicht etwas anfangen? Vielleicht eine DLL die PB aufruft?

https://github.com/bryal/DXGCap

Mit C++ und OOP kenne ich mich rein überhaupt nicht aus.

Dachte eigentlich diese Funktion gehört zu DX11 und wäre daher vielleicht Bestandteil des DX11 Subsystems in PB? Vielleicht hab ich das aber auch falsch verstanden, hab noch nie etwas im 3D Bereich gemacht, nur einmal DX9 benutzt und das war nur wegen dem DDS Texture Format, da hatte ich aber eine Code Basis zur Verfügung.

Ist ja über USB. Der Arduino, der die LEDs ansteuert, wir per COM Schnittstelle angesprochen, hängt aber per USB am PC. Da wird dann ein 6 Byte Header gesendet und im Anschluss nur noch die Farben getrennt nach R,G,B (0-255) für jede einzelne LED Byte für Byte hintereinander weg. Völlig easy umzusetzen.

Edit: ok, wenn ich DXGCap mit VS C++ kompiliere, kommt u.a. eine DXGCap.dll und DXGCap.lib bei raus (kann PB nicht solche lib Dateien nutzen?). Muss ich mal weiter suchen... jetzt bin ich neugierig das nicht doch selbst hin zu kriegen mit der Vorlage. ;)

Edit2: so, ich habs tatsächlich halb hingekriegt, allerdings hab ich beim Bild im Speicher nur 0en, die Buffer Größe stimmt aber mit Höhe*Breite*4 (inkl. Alphakanal) überein, der get_frame_bytes() Befehl an sich scheint also zu arbeiten. Aber keine Ahnung wo der Fehler liegen könnte (vielleicht falscher Bildschirm? Hab aber nur einen aktiviert und laut Debug Teil im C++ Code geht es auch ohne setzen einer Bildschirm Quelle).

Aktuell sieht der Test Code so aus:

Edit: siehe Code weiter unten

Hier die nötigen lib/dll Dateien für den Code oben. Vielleicht sieht ja Jemand direkt wo das Problem liegen könnte. Ich schau mir das später noch mal an.

Nur quick und dirty zum testen. Das Bild speichern brauche ich ja eh nicht, eher das Ganze in ein Array speichern. CatchImage() erwartet wohl ein Header?
Zuletzt geändert von Hoto am 21.06.2018 21:37, insgesamt 1-mal geändert.
Benutzeravatar
RSBasic
Admin
Beiträge: 8022
Registriert: 05.10.2006 18:55
Wohnort: Gernsbach
Kontaktdaten:

Re: Erweiterte Ambilight Windows Software für Adalight (Ardu

Beitrag von RSBasic »

Hoto hat geschrieben:Dachte eigentlich diese Funktion gehört zu DX11 und wäre daher vielleicht Bestandteil des DX11 Subsystems in PB?
Grundsätzlich schon, aber dafür muss Fred/freak diese Funktion auch anbieten. Ich bin mir nicht sicher, aber vielleicht ist es mit dem Schlüsselwort Import/ImportC möglich, darauf zuzugreifen, ohne eine DLL-Datei extra mitzuliefern.
Aus privaten Gründen habe ich leider nicht mehr so viel Zeit wie früher. Bitte habt Verständnis dafür.
Bild
Bild
Benutzeravatar
Hoto
Beiträge: 294
Registriert: 01.09.2004 22:51

Re: Erweiterte Ambilight Windows Software für Adalight (Ardu

Beitrag von Hoto »

Wenn es über die DLL oben laufen würde wäre das ja schon mal etwas. Aktuell stehe ich da aber schon etwas auf dem Schlauch wieso das nicht funktioniert, da er die korrekte Bildschirmauflösung ausspuckt, scheint definitiv der Bildschirm als Quelle gesetzt zu sein, neige daher dazu, dass es dann auch eher nicht daran liegen kann, da muss wo anders der Bock drin stecken. Leider fehlt ein Beispiel Code um die DLL selbst direkt testen zu können.

Ich hab keine Ahnung wie ich das testen/rausfinden kann, man findet nicht gerade viel über das DirectX11 Subsystem in PureBasic.

Edit: ich hab mir jetzt einfach mal die Subsystems Files im PB Verzeichnis mit dem Texteditor angesehen und wenn das was man lesen kann alles ist, dann ist es sehr beschränkt und hat definitiv nicht diese Funktionen.

Edit3: poste es doch noch mal hier:

Es läuft nun aber so sollte man es definitiv nicht 1:1 verwenden, rein zum testen in der IDE gedacht:

Code: Alles auswählen

EnableExplicit
CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
  #ImportLib$ = "DXGCapx64.lib"
CompilerElse
  #ImportLib$ = "DXGCapx86.lib" 
CompilerEndIf

Define cs = 0, Width.i, Height.i, buf_size.i, *buf, o_size.i, *o_bytes, *dxgi_manager
Define x = 0, y = 0, z = 0

#CR_OK = 0
#CR_ACCESS_DENIED = 1
#CR_ACCESS_LOST = 2
#CR_TIMEOUT = 3
#CR_FAIL = 4

Import #ImportLib$
  create_dxgi_manager()
  delete_dxgi_manager(*dxgi_manager)
  get_capture_source(*dxgi_manager)
  get_frame_bytes(*dxgi_manager, o_size, *o_bytes)
  get_output_dimensions(*dxgi_manager, Width, Height)
  refresh_output(*dxgi_manager)
  set_capture_source(*dxgi_manager,cs)
  set_timeout(*dxgi_manager,timeout)
EndImport

*dxgi_manager = create_dxgi_manager()

get_output_dimensions(*dxgi_manager,@Width,@Height)

Debug "w:"+Str(Width) + " h:" + Str(Height)
Debug get_capture_source(*dxgi_manager)

*buf = AllocateMemory(Width*Height*4)

Repeat
  Select get_frame_bytes(*dxgi_manager, @buf_size, @*buf)
    Case #CR_OK
      ; all ok
    Case #CR_ACCESS_DENIED
      Debug "Access Denied"
      Break
    Case #CR_ACCESS_LOST
      Debug "Access lost"
      Break
    Case #CR_TIMEOUT
      Debug "Timeout"
      Break
    Case #CR_FAIL
      Debug "General failure"
      Break
  EndSelect
Until PeekS(*buf)

CreateImage(0,Width,Height,32,RGBA(255,255,255,255))
StartDrawing(ImageOutput(0))
  DrawingMode(#PB_2DDrawing_Default)
  For y = 0 To Height-10
    For x = 0 To Width-1 
      Plot(x,y,RGBA(PeekA(*buf+z+2),PeekA(*buf+z+1),PeekA(*buf+z),PeekA(*buf+z+3))) ; *buf content is in BGRA 0-255 Subpixel order 
      z + 4
    Next
    Debug PeekA(*buf+z)
  Next
StopDrawing()

SaveImage(0,"DXGCap_Test_Screenshot.bmp",#PB_ImagePlugin_BMP)

delete_dxgi_manager(*dxgi_manager)
http://www.stepload.de/uploads/f1mOg_MC ... 6dYYilldF/

Die Zip Datei mit nun Dateien für 32 und 64 Bit und entsprechend die DLLs benannt, sind also neu kompiliert, wie im Code zu sehen wird automatisch die richtige Version gewählt.

Danke erst mal für die Hilfen hier, selbst kleine Schubser helfen doch immer wieder, da man doch gerne mal den Wald vor lauter Bäume nicht sieht.
Zuletzt geändert von Hoto am 04.07.2018 05:54, insgesamt 1-mal geändert.
Benutzeravatar
Hoto
Beiträge: 294
Registriert: 01.09.2004 22:51

Re: Erweiterte Ambilight Windows Software für Adalight (Ardu

Beitrag von Hoto »

Da ich das mit der DXGCap und dem dort verkleinern des Bildes nicht hinkriege, hab ich jetzt mal den Author auf Github angeschrieben (bzw. ein Issue eröffnet). Mal sehen ob er sich überhaupt meldet.

Muss die Funktion halt noch etwas warten, dennoch kann ich ja schon mal am Programm und den anderen Funktionen arbeiten, das Capturen des Bildes ist ja nur eine von vielen Funktionen, wird mich aber vermutlich auch zukünftig noch einiges an Zeit kosten.
fabulouspaul
Beiträge: 120
Registriert: 01.04.2011 21:59

Re: Erweiterte Ambilight Windows Software für Adalight (Ardu

Beitrag von fabulouspaul »

Ich habe mal bei RSBasic geklaut, um mal zu prüfen wie man das (fast) mit PB-Bordmitteln lösen kann.

Dabei ist das herausgekommen:

Code: Alles auswählen

EnableExplicit

Enumeration
  #desktop
EndEnumeration

Define hDcDesktop
Define hDC
Define desktops, hoehe, breite
Define timer, counter
Define i

; Schleife mal 1 Sekunde durchlaufen lassen und zählen wie of das gelingt
timer = ElapsedMilliseconds()
Repeat
  desktops = ExamineDesktops()
  If desktops > 0
    hoehe  = DesktopHeight(1)
    breite = DesktopWidth(1)
  EndIf
  
  ; Device context (DC) zum Desktop
  hDcDesktop  = GetDC_(GetDesktopWindow_())
  
  ; PB-Image mit entsprechender Größe dazu erzeugen
  CreateImage(#desktop, breite, hoehe)
  
  ; Desktop ins Image kopieren
  hDC = StartDrawing(ImageOutput(#desktop))
  BitBlt_(hDC, 0, 0, breite, hoehe, hDcDesktop, 0, 0, #SRCCOPY)
  StopDrawing()
  
  ; DC zum Desktop freigeben
  ReleaseDC_(GetDesktopWindow_(), hDcDesktop)
  
  ; Image um Faktor 2 verkleinern
  ResizeImage(#desktop, breite * 0.5, hoehe * 0.5, #PB_Image_Raw)
  
  counter + 1
Until (ElapsedMilliseconds() - timer) > 1000
timer = ElapsedMilliseconds() - timer

MessageRequester("Screenshot-Test", "Durchschnittliche Zeit pro Durchlauf: " + Str(timer/counter) + "ms" + #LF$ + "Durchläufe pro Sek.: " + Str(counter))

End
Auf meine kleinen Testsystem i5-6500 @ 3.20GHz / Auflösung: 1920 x 1200, dauert ein Schleifendurchlauf 50ms, wenn die Schleife nach 1 Sek. beendet wird, gab es also 20 Durchläufe.

OK, die Auswertung der Pixel zur Ermittlung der Farben für die 150 LEDs wird auch nochmal etwas Zeit benötigen, die Datenübertragung zum Arduino wird auch noch Zeit benötigen, der Arduino braucht etwas Zeit für die Ansteuerung der LEDs und letztlich hat so eine LED auch noch eine kleine Latenz.

Für 15 Durchläufe in der Sekunde bleiben für all das 66ms... das ist schon eine Herausforderung :D

Die Frage ist, ob es für eine Ambilight-Lösung notwendig ist die LEDs derart häufig zu refreshen oder ob eine Frequenz von 5 Hertz nicht vielleicht auch ausreicht.
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8675
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 32 GB DDR4-3200
Ubuntu 22.04.3 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken
Kontaktdaten:

Re: Erweiterte Ambilight Windows Software für Adalight (Ardu

Beitrag von NicTheQuick »

Ich würde vermuten, dass 5 Hz ganz und gar nicht ausreichen werden. Du solltest wenigstens über die 24 FPS kommen, damit das Auge kein Flackern wahr nimmt. Auch die Farben am Rand des Bildschirms können sich mehrmals pro Sekunde ändern (Maschinengewehrfeuer, sonstige grellen Lichtblitze oder wilde Kamerafahrten). Da möchte man sicherlich kein Gefühl des Ruckelns bekommen. Reine Theorie meinerseits, aber ich stelle es mir mit wenigen FPS nicht besonders erträglich vor.
Bild
Antworten