February 17, 2012
Varför?
Som de flesta av mina hemmaprojekt rotar sig det här i ett I-landsproblem i kombination med en vilja att lära mig någonting nytt.
Sedan ett tag tillbaka har jag använt en stor datorskärm (Philips BDM4065UC) istället för en TV. Detta av flera anledningar, en av de främsta var att skärmen kopplades till en HDMI-förstärkare, och att förstärkaren skötte växlingen mellan olika bildingångar. Skärmen går automatiskt ner i viloläge när förstärkaren gör det, så faktumet att BDM4065UC inte har någon fjärrkontroll spelade inte så stor roll. Sen att skärmen inte har någon TV-mottagare och därmed inte omfattas av TV-avgiften flög såklart inte heller under radarn… 🙂
Men under hösten 2017 började jag studera på heltid och flyttade till en liten studentlägenhet på 26 kvadratmeter. Som konsekvens fick TV-hörnan och datorhörnan bli en och samma. Jag valde att prioritera arbetsyta framför uppdateringsfrekvens (och därmed prioritera plugg och jobb framför spel), så Philips-skärmen fick hänga med som primär datorskärm. Lämpligt nog står soffan på lagom avstånd för att datorhörnan även ska agera filmhörna.
Min förstärkare har dock inte stöd för HDMI 2.0. Det innebär att jag måste använda Displayport direkt på skärmen för att kunna använda köra 60 Hz med full upplösning (3 840 x 2 160). Samtidigt vill jag koppla alla mina andra HDMI-prylar (Apple TV, Chromecast, PS4) till förstärkaren, dels för ljudets skull och dels för att smidigt kunna byta bildingång mellan dessa utan att resa mig från soffan. Om jag ska byta ingång från dator till exempelvis PS4 behöver jag därmed dels byta ingång på förstärkaren och dels byta ingång på skärmen genom att fysiskt sträcka mig efter knappen på baksidan.
Det är exakt ett steg för mycket, men inte ett tillräckligt stort problem för att jag ska köpa en ny förstärkare för att komma runt det. Istället tänker jag vara lat och hemmasnickra en lösning.
Därför är min plan att använda skärmens seriellport (RS232) för att göra en egen fjärrkontrollslösning via en Raspberry Pi. Jag har tidigare skrivit fjärrstyrningsmjukvara till förstärkaren i både Autoit och Swift, så tanken är att utöka denna så att jag kan styra både skärmen och förstärkaren från samma ställe. Min Raspberry Pi kan sedan agera hub för all möjlig hemautomation med enkla tillägg.
Mål:
- Ett underliggande API i C# som kan fjärrstyra förstärkaren och RPi via nätverket
- Skrivbordsappar till Windows och Mac som använder detta API
- Ett webbgränssnitt för att styra detta från mobila enheter
- Ett passivt program som kan köra i bakgrunden och automatiskt anpassa ingångar och ljud på skärmen baserat på vad förstärkaren använder för ingång, och vice versa
Utrustning:
- Raspberry Pi 3 (och minneskort)
- Plastskal till RPi
- RS232-USB-adapter
- Terminalblock till 2,5mm och RS232
- Kablar
- Kardborreband
Steg 1: Seriellanslutningen
Till vissa varianter av Philips BDM4065UC medföljer en seriellkabel i kartongen, men det är tyvärr ingenting jag har lyckats hitta till mitt exemplar. Däremot hade jag en seriell-till-USB-adapter liggandes, och att adaptera den kontakten till skärmen är varken dyrt eller komplicerat.
Jag köpte två terminalblock på Kjell & Co, ett för 4-pols 2,5mm (för att koppla till skärmen) och ett för RS232. Blocken är små nog för att inte vara särskilt i vägen, och har skruvfästen för kablarna så att jag slipper gräva fram lödkolven.
Installationen blir inte bedårande vacker, men är diskret nog att inte synas framifrån skärmen och blir lagom för att få fram en fungerande lösning. I framtiden kommer jag nog vilja byta ut kabeln mot en snyggare installation, men just nu vill jag komma igång med mjukvaran 🙂
February 17, 2012
Steg 2: Fjärrstyrningsmjukvaran
Som tur är har jag inte behövt uppfinna hjulet på nytt, och jag är inte den första som har försökt fjärrstyra just den här skärmen. Via ett HIFI-forum hittade jag ett enkelt grafiskt program till Windows med färdiga funktioner för att koda de signaler jag behöver och skicka dem seriellt till skärmen.
Skärmen tar emot en ström byte-värden (byte i C#, eller char), som skickas som en array bestående av en header för en viss typ av kommando (exempelvis läsning eller skrivning, eller beroende på om det är bildskärmsingång eller volym som efterfrågas).
Eftersom jag vill styra skärmen över nätverket behöver jag bygga om programmet så att det kan användas via kommandoraden istället. Programmet är skrivet i C#, så som ett första steg lyfter jag ut grundfunktionaliteten till ett klassbibliotek. Jag klipper bort alla GUI-relaterade metoder och ändrar konstruktorn en aning, så att vilken seriellport som används bestäms utanför klassen och skickas in som en parameter. Jag exponerar även en uppsättning enkla metoder i stil med turnOff(), så att andra program kan använda klassen och skicka kommandon till skärmen utan att behöva bry sig om alla kommandon kodas och skickas via seriellporten.
Det här klassbiblioteket fungerar sedan som en grund som jag kan bygga andra applikationer runt, antingen grafiskt eller scriptat. I längden kommer jag vilja bygga grafiska program till både Windows och Mac baserat på klassbiblioteket, men i första hand är det scriptfunktionerna jag vill åt.
Källkoden till klassbiblioteket finns på Github för den som är intresserad: https://github.com/CarHol/BDM4.....ControlAPI
Jag har använt Jetbrains Rider för utvecklingen, men kod och projektfiler är kompatibla med Visual Studio som är gratis att ladda ner från Microsoft.
Kommandoradsverktyg
Efter klassbiblioteket är klart kan jag bygga ett kommandoradsverktyg runt det, som tar enkla kommandon. Ett typiskt kommando ser ut ungefär så här:
PhilipsSerialCMD.exe -p COM4 -setinput HDMI
Vilket innebär att programmet ska leta efter skärmen på seriellporten COM4 och byta bildingång till HDMI.
En fördel med att skriva såväl klassbibliotek som kommandoradsverktyg i C# är att mjukvaran dels fungerar direkt på Windows, men även att det går att köra på Linux och macOS via Mono, utan att behöva ändra någonting i koden. Mono kan köra .exe-filer, så programmet behöver inte ens kompileras om till andra operativsystem utan kan köras rakt av. Eftersom Mono används som mellanlager går det till och med att köra binärfiler som kompilerats på en PC med X86 på en linuxdator med ARM-processor - såsom Raspberry Pi.
Det finns fortfarande lite saker att finslipa hos kommandoradsverktyget, exempelvis att jag använder ett hemmasnickrat tolkningssystem för parametrarna. Framöver kommer jag att byta ut det mot ett mer finslipat sådant som är lättare att bygga ut med nya parametrar efter hand, men det blir relevant först när jag lyckas få de sista funktionerna hos skärmen att fungera smärtfritt.
Det jag fortfarande inte har fått att fungera bra är volymjustering (värdena tolkas fel av någon anledning) och picture-in-picture-inställningar. Sistnämnda vill jag gärna få att funka, men det får bli en uppdatering i nästa version.
Nu är nästa steg dels att testa programmet på en Raspberry Pi, och dels att skriva ett grafiskt gränssnitt som jag kan använda praktiskt på mobilen eller datorn 🙂
February 17, 2012
Steg 3: Konfigurera Raspberry Pi
Tanken är att en Raspberry Pi ska skicka seriellsignalen till skärmen, och kunna ta emot kommandon via nätverket på olika sätt. Till att börja med vill jag kunna styra skärmen via ett webbgränssnitt, så att jag kan använda telefonen eller surfplattan som fjärrkontroll.
Jag utgår ifrån Raspberry Pi:s sedvanliga operativsystem Raspbian och börjar med att installera några av de verktyg jag kommer behöva, bland annat:
- Mono (Paket: mono-runtime) - för att köra mitt fjärrstyrningsprogram
- Apache (Paket: apache2) - webbserver
- Pure-ftpd (Paket: pure-ftpd) - FTP-server för att utveckla webbappen på en annan dator och föra över filerna via nätverket
- PHP (Paket: php5) - för att webbappen ska kunna starta fjärrstyrningsprogrammet på Raspberry Pi
Raspberryn kommer arbeta helt via nätverket, så all konfiguration sker via SSH.
Jag installerar först Mono och kopplar in serielladaptern till Raspberry Pi för att se så att seriellstyrningen fungerar som tänkt även på Linux. Seriellporten som på Windows hette COM4 eller COM5 beroende på port heter nu /dev/ttyUSB0, så jag testar att helt enkelt skicka in det som argument till programmet och köra det som vanligt.
Efter att ha verifierat att seriellporten fungerar med mitt kommandoradsverktyg är det dags att börja fila på själva användargränssnittet. Men innan jag gör det vill jag korta ner kommandot som krävs för att använda programmet, så jag stuvar in det i några enkla bash-script:
Scriptet innehåller ingen logik, utan agerar helt enkelt som en genväg för att slippa kalla på Mono och skriva in alla parametrar varje gång programmet ska köras. Vill jag exempelvis stänga av skärmen kan jag använda kommandot "sh turnMonitorOff.sh" istället. Däremot visade sig Mono bete sig lite underligt i just bash-script och behöver köras som root för att fungera från scriptet. Jag låter det dock vara kvar så eftersom programmet bara kommunicerar via seriellporten och inte använder filsystemet alls.
Nu är allt grundarbete på Raspberry Pi:n egentligen klart, och det som återstår är att skriva ett användargränssnitt och montera enheten bakom skärmen.
1 Guest(s)