Największymi trudnościami w sterowaniu zimnymi katodami są ich wyłączanie i liniowe ściemnianie. Niewyłączanie prowadzi do efektu widzianego tu, gdy ekran wyświetla całkiem czarny obraz, a z tyłu widać niebieską poświatę. W pokazywanym projekcie MoMoLight, podłączono zimne katody w ten sposób. Przy sterowaniu PWM, obniżenie "mocy" świetlówki poniżej 10%, powoduje mruganie, także przy wypełnieniu zbliżającym się do zera. Łatwo można poprawić ten schemat, podłączając kondensator (4.7uF) między masą inwertera, a masą układu. Pozwala to zejść do 1% mocy.
Zejście to ma spore znaczenie, gdyż CCFL są nieliniowe (bądź odbieranie światła przez ludzkie oko jest nieliniowe), czyli jeśli zielonej świetlówce zwiększymy moc dwukrotnie, nie uzyskamy dwukrotnie jaśniejszego światła. Podobne zjawisko występuje w monitorach, ale jest korygowane bez wiedzy użytkownika. Reakcje CCFL jest funkcją logarytmiczną (tu jest wykres), czyli dla niskich wartości rośnie szybko, a dla wysokich powoli. Czyli różnica między 50%, a 100% mocy będzie dla nas mniej zauważalna, niż między 5%, a 10% mocy. Teraz już rozumiemy, dlaczego zwiększenie dolnego zakresu do 1% było tak ważne. Prawidłowe wykorzystanie tych możliwości, aby osiągnąć zwiększony kontrast wirtualnego ekranu (powierzchni oświetlonej przez CCFL), polega na użyciu korekcji gamma, czyli pomnożeniu funkcji logarytmicznej CCFL przez funkcję wykładniczą, co dla pewnych parametrów powinno dać liniowe odwzorowanie kolorów na CCFL.
Ucieszyłem się jak zobaczyłem na twoim blogu że robisz ambilighta. Ja swoja naukę programowania kontrolerów (AVR + C) zacząłem właśnie od planu zrobienia prostego ambilighta, ale napotkałem problemy które były dla mnie za duże.
Problemami było m.in. to co piszesz w przypadku CCFL, czyli nieliniowe narastanie jasności diód (bo na nich robiłem). Zrobiłem tablicę 256 docelowych jasności z już skorygowaną gammą, ale wtedy robiły się "schodki" jak się powoli zapalało (najwyraźniej 8-bitowe PWM to za mała rozdzielczość).
Ponadto, nie wiedziałem jak podłączyć USB.
Myślalem też o podpięciu więcej diód niż trzy, ale "emulacja" PWM na zwykłych wyjściach dała taki wynik, że diody co jakiś czas błyskały jasno lub gasły na ułamek sekundy, po czym wnioskuję że PWM nie był "równomierny".
Dobiło mnie na dodatek to, że z elektroniki jestem noga (zdecydowanie wolę pisać kod...) i nie wiedziałem jak podłączyć tranzystory, mimo szukania w necie informacji.
A teraz już na mojej specjalizacji (robotyka) nie mam kontrolerów, i nie za bardzo mam czas, więc póki co nie wracam do tego.
Dlatego trzymam kciuki za AmaLight, i mam szczerą nadzieję że jeśli oublikujesz źródła i płytki, to coś się z tego nauczę i uda mi się to zrobić u siebie
(A przy okazji przeportować to na Linuxa, bo z windowsa nie korzystam :>
Fluxid - 26 listopada 2008 17:29:40
Do etapu korygowania jasności do tej na ekranie nie doszedłem - niebieskie CCFL wciąż do mnie nie dotarły. Korzystam z firmwarowego PWMa, jakby nie patrzeć, nie ma AVRów ze sprzętowym PWMem na dziewięć wyjść. Dodałeś kondensator na wyjście emulowanego PWMa? Powinien wygładzić sygnał.
Robiłeś to na LEDach dużej mocy? Pewien nie jestem, ale połączenie takie jak w linku (z dodatkowym rezystorem) mogłoby zadziałać.
>A przy okazji przeportować to na Linuxa, bo z windowsa nie korzystam
Ja nie korzystam z linuksa, przynajmniej prywatnie nie.
remiq - 26 listopada 2008 20:02:39
hej,
dlaczego nie zrobić tego na paskach LED? 3 krotkie listwy RGB laczane z kazdej strony dalyby piorunujacy efekt
jak w philips
wtedy latwobyloby zrobic tak potrzebne funkcje jak regulacja sily swiecenia
zrealizowanie pobierania kolorow pod VISTA jest stosunkowo proste (o ile wlaczone jest aero) spokojnie mozna sie posluzyc metodami getpixel
w przypadku odtwarzania przez directX trzeba uzywac odpowiedniego filtra
system musi byc koniecznie konfigurowalny tak aby nie mial opoznien, jesli beda opozniania bedzie denerwujacy, swiatlo nei moze byc zbyt dynamiczne i mrugac po pokoju co by sie na ekranie dzialo ma sie delikatnie zmieniac i najwazniejsze by w sytuacji ciemnosci na ekranie swiatlo sei znacznie zmiejszalo, reszta nie ejst tak naprawde wazna
kolejna sprawa to opracowac system oswietlenia ktory dzialalby niezaleznie od systemu, ambilight nie steroweany przez komputer
czyli prosty system szarego oswietlenia ktore ma regulowana jasnosc za pomoca jakiegos fotodetektora, np. fotorezystora ktory mierzylby natezenie swiatla z monitora i uzaleznial od tego sile swiecenia podswietlenia tv
co sadzisz o moich pomyslach remiq?
daj znac, moge pomoc, wiem jak oprogramowac to
jacie - 27 listopada 2008 18:40:30
> dlaczego nie zrobić tego na paskach LED?
Jak zaczynałem planować, nie widziałem jeszcze telewizora z ambilight. Zdecydowałem się na CCFL, bo przy ich użyciu światło jest równomierne, nie jak przy LEDach punktowe. Telewizory, które oglądałem, miały paski LEDów RGB, ale miały one połączenie każdy osobno, a nie jedno na cały pasek (połowa zmieniała kolor, druga połowa nie). LEDy też są nieliniowe.
Pobieranie kolorów już jest, screeny są tutaj: http://remiq.jogger.pl/2008/11/16/amalight-czym-jest-amalight/
Co do oświetlenia białego, nowe monitory mają DCR, czyli dynamiczny kontrast. Działa to w ten sposób, że CCFLe, które podświetlają ekran, dostają sygnał wewnątrz monitora. Najprostszy mod, to podpięcie się pod to i sterowanie tym sygnałem dodatkowymi CCFLami na zewnątrz.
W razie problemów, napiszę na blogu.
remiq - 27 listopada 2008 20:59:20
nie widzę tam informacji w jaki sposób softwarowo to rozwiązałeś? rozumiem że to działa w każdym windowsie? w Vista też?
rozwiązanie które proponujesz dla wielu będzie nie do zniesienia, ja wolałbym prosty układ z czujnikiem światła co delikatnie podświetla tył telewizora, odpowidnio rozproszone listwy led (jakikolwiek filtr, papier chociaż) dają naprawdę ładne równomierne światło
jacie - 28 listopada 2008 01:09:47
Korzystam z GDI, ale nie po pojedynczych pikselach, tylko kopiuje cały ekran do bufora. Wszystkie aktualnie wspierane windowsy mają GDI, Vista również.
remiq - 28 listopada 2008 12:13:21
GDI jest dosc wolne pod Vista - jesli jest wlaczone Aero w Vista to juz wogole jest problem.
[DllImport("User32.dll"
]
public static extern IntPtr GetDC(int hWnd);
GlobalVariables.DeskDC = User32.GetDC(0);
temp = GDI32.GetPixel(GlobalVariables.DeskDC, PixelX + MyScreen.Bounds.Left, PixelY + MyScreen.Bounds.Top);
GetPixel z GDI32 pod Vista dziala strasznie topornie...
Znalazlem inny sposob ktory pod Aero przynajmniej dziala:
public void GetDesktop()
{
int screenLeft = Screen.AllScreens[GlobalVariables.SelectedDisplay].Bounds.Left;
int screenTop = Screen.AllScreens[GlobalVariables.SelectedDisplay].Bounds.Top;
int screenX = Screen.AllScreens[GlobalVariables.SelectedDisplay].Bounds.Width + screenLeft;
int screenY = Screen.AllScreens[GlobalVariables.SelectedDisplay].Bounds.Height + screenTop;
IntPtr hBmp;
IntPtr hdcScreen = User32.GetDC(0);
// IntPtr hdcScreen = GetDC(GetDesktopWindow());
IntPtr hdcCompatible = GDI32.CreateCompatibleDC(hdcScreen);
// Bitmap bmp;
hBmp = GDI32.CreateCompatibleBitmap(hdcScreen, screenX, screenY);
if (hBmp != IntPtr.Zero)
{
IntPtr hOldBmp = (IntPtr)GDI32.SelectObject(hdcCompatible, hBmp);
// BitBlt(hdcCompatible, 0, 0, screenX, screenY, hdcScreen, 0, 0, 13369376);
GDI32.BitBlt(hdcCompatible, 0, 0, screenX, screenY, hdcScreen, 0, 0, 13369376);
GDI32.SelectObject(hdcCompatible, hOldBmp);
GDI32.DeleteDC(hdcCompatible);
User32.ReleaseDC(User32.GetDC(0), hdcScreen);
// bmp = System.Drawing.Image.FromHbitmap(hBmp);
myBitmap = System.Drawing.Image.FromHbitmap(hBmp);
GDI32.DeleteObject(hBmp);
GC.Collect();
// return bmp;
}
// return null;
}
private uint ColorToUIntBGR(Color color)
{
return (uint)((color.A << 24) | (color.B << 16) |
(color.G << 8) | (color.R << 0));
}
GetDesktop(); // -> myBitmap
myColor = myBitmap.GetPixel(PixelX + MyScreen.Bounds.Left, PixelY + MyScreen.Bounds.Top);
temp = ColorToUIntBGR(myColor);
ale niestety nadal rewelacja to nie jest...
teoretycznie GDI dziala dobrze pod XP - szybko... i na tym koniec.
czy ma ktos lepsze rozwiazanie?
SiLAS - 23 marca 2009 03:06:54
Poniższy kod działa całkiem szybko:
int nScreenWidth = GetSystemMetrics(SM_CXSCREEN);
int nScreenHeight = GetSystemMetrics(SM_CYSCREEN);
int loop = 1;
int loopi=0;
HDC hdc=NULL;
DWORD *pBuf=NULL;
BITMAPINFO bmpInfo;
// to save as bmp
BITMAPFILEHEADER bmpFileHeader;
FILE* fp=NULL;
COLORREF crColorLeft, crColorTop, crColorRight;
HBITMAP hCaptureBitmap;
HWND hDesktopWnd = GetDesktopWindow();
HDC hDesktopDC = GetDC(hDesktopWnd);
HDC hCaptureDC = CreateCompatibleDC(hDesktopDC);
hdc=GetDC(NULL);
ZeroMemory(&bmpInfo,sizeof(BITMAPINFO));
bmpInfo.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
int pasek = 200;
hCaptureBitmap =CreateCompatibleBitmap(hDesktopDC, nScreenWidth, nScreenHeight);
SelectObject(hCaptureDC,hCaptureBitmap);
BitBlt(hCaptureDC,0,0,nScreenWidth,nScreenHeight,hDesktopDC,0,0,SRCCOPY);
GetDIBits(hdc,hCaptureBitmap,0,0,NULL,&bmpInfo,DIB_RGB_COLORS);
if(bmpInfo.bmiHeader.biSizeImage<=0)
bmpInfo.bmiHeader.biSizeImage=bmpInfo.bmiHeader.biWidth*abs(bmpInfo.bmiHeader.biHeight)*(bmpInfo.bmiHeader.biBitCount+7)/8;
//pBuf = malloc(bmpInfo.bmiHeader.biSizeImage);
pBuf = malloc(nScreenWidth*nScreenHeight*(32+7)/8);
bmpInfo.bmiHeader.biCompression=BI_RGB;
GetDIBits(hdc,hCaptureBitmap,0,nScreenHeight,pBuf, &bmpInfo, DIB_RGB_COLORS);
// czesc 4 (patrz numpad)
crColorLeft = avgFromRect3(pBuf, nScreenWidth, 0, (nScreenHeight/3) , (nScreenWidth/3), (nScreenHeight/3) );
---
COLORREF avgFromRect3(DWORD *pSource, int nScreenWidth, int x, int y, int width, int height)
{
int divide = 4;
int divcount = 0;
unsigned int iR = 0;
unsigned int iG = 0;
unsigned int iB = 0;
unsigned int iC = 0;
int i,j,k;
k=0;
for(i=x+width ; i>x ; i--)
for(j=y+height ; j>y ; j--)
{
//printf("%i <- %i\n", (i+(width*j)), (x+(nScreenWidth*y)) );
iR += (long)GetRValue( pSource[i+(nScreenWidth*j)] );
iG += (long)GetGValue( pSource[i+(nScreenWidth*j)] );
iB += (long)GetBValue( pSource[i+(nScreenWidth*j)] );
iC++;
}
iR = iR / iC;
iG = iG / iC;
iB = iB / iC;
return RGB(iR, iG, iB);
}
Przy włączonym Aero, nie ma problemu z przetwarzaniem obrazu w rozdzielczości 1680x1050.
remiq - 23 marca 2009 13:30:31
!Ona (0/0)