The problem
We down-graded but up-sized our car, to a Vauxhall / Opel Zafira. It’s only a 2002 model but does come with cruise control, air con and all electric windows, mirrors, etc. However, unlike our old Peugeot 307, it doesn’t tell you what you’ve set the cruise control to. Or, in fact, a very accurate speed reading. And the built-in trip computer only shows one piece of information at a time; you have to scroll all the way round 7 options to get from average MPG to instant, for example.
The stock display (not mine)
The Solution – A Raspberry Pi, of course!
I got myself an OBD II bluetooth interface off ebay for about £7. The OBD port on the Zafira sits just underneath the handbrake lever, and gets you connected to the engine ECU, as well as the ABS and power steering ECUs.
I started experimenting with some android apps to start with. Most of these use the open PIDS available here on Wikipedia. The Mode 1 PIDS give you a fair amount of information – officially. But on my car, they didn’t. I could get RPM, speed and water temperature, but not much else. To replace my OEM display, I’d need at least to get hold of the Miles Per Gallon and as many other readings as I could. So, I found a couple of Opel-specific apps that gave some other bits of information – MAF flow rate, injection fuel quantity, fuel temperature, and lots of other goodies. That’s enough to work out MPG! If only I could get my hands on these manufacturer-specific PIDs, I’d be able to get the same readings on my Pi and display them nicely.
Hacking the bluetooth comms
At this point I had Xbian running on the R-pi, and had installed a bluetooth dongle and got comms established between the Pi and the scanner. See this page on how TODO!. I tried looking for ways to snoop the serial comms between my android phone and the scanner. Apparently, eavesdropping on bluetooth comms is extremely difficult, since it channel-hops constantly and you won’t know which channel it about to hop to unless you were there and on the right channel at the start of the conversation. Suffice to say, a standard £1 bluetooth dongle won’t let you eavesdrop on communications.
The OBD comms
So, how do I find out what to send to my ECU to get the needed telemetry?
Strace!
Strace is a linux command that helps you debug processes. Importantly for us, it logs writes to the serial port. So, run it on android as root and it’ll tell you what your processes are talking about.
Below is a snippet of what I got back from strace after attaching it to the right process. I had to root my phone, copy in an strace binary, run it as root, and point it to the right Process ID.
syscall_983042(0x5dde6edc, 0x5dde6ee0, 0, 0xfff, 0x408d5110, 0x5dde6edc, 0x5dde5831, 0xf0002, 0, 0x5dde6ee0, 0xfca8f7fe, 0x2, 0, 0xbec9b7b8, 0x408a9b6 3, 0x400e4918, 0x40000010, 0x5dde6edc, 0, 0, 0xc764, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) = 0 write(56, "A", 1) = 1 write(56, "T", 1) = 1 write(56, "E", 1) = 1 write(56, "0", 1) = 1 write(56, "\r\n", 2) = 2 write(56, "A", 1) = 1 write(56, "T", 1) = 1 write(56, "L", 1) = 1 write(56, "0", 1) = 1 write(56, "\r\n", 2) = 2 write(56, "A", 1) = 1 write(56, "T", 1) = 1 write(56, "A", 1) = 1 write(56, "L", 1) = 1 write(56, "\r\n", 2) = 2 syscall_983042(0x5dddf6c4, 0x5dddf6c8, 0, 0xfff, 0x408d5110, 0x5dddf6c4, 0x5dde6eb5, 0xf0002, 0, 0x5dddf6c8, 0xfbf6f007, 0x2, 0, 0xbec9b7b8, 0x408a9b6 3, 0x400e4918, 0x40000010, 0x5dddf6c4, 0, 0, 0xc764, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) = 0 write(56, "A", 1) = 1 write(56, "T", 1) = 1 write(56, "S", 1) = 1 write(56, "P", 1) = 1 write(56, "5", 1) = 1 syscall_983042(0x5dde79cc, 0x5dde79dc, 0, 0xfff, 0x5dde79cc, 0x408cff90, 0x56e67af8, 0xf0002, 0x408d5110, 0x1fe9, 0, 0x408d5190, 0, 0xbec9b7a8, 0x408a 9b63, 0x400e4918, 0x40000010, 0x5dde79cc, 0, 0, 0xc764, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) = 0 write(56, "\r\n", 2) = 2 syscall_983042(0x5ddda8ac, 0x5ddda8b0, 0, 0xfff, 0x408d5110, 0x5ddda8ac, 0x5dde7599, 0xf0002, 0, 0x5ddda8b0, 0xfe74f00c, 0x2, 0, 0xbec9b7b8, 0x408a9b6 3, 0x400e4918, 0x40000010, 0x5ddda8ac, 0, 0, 0xc764, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) = 0 write(56, "A", 1) = 1 write(56, "T", 1) = 1 write(56, "H", 1) = 1 write(56, "1", 1) = 1 write(56, "\r\n", 2) = 2 syscall_983042(0x5dde7db4, 0x5dde7db8, 0, 0xfff, 0x408d5110, 0x5dde7db4, 0x5dde7ef1, 0xf0002, 0, 0x5dde7db8, 0x4300e09c, 0x2, 0, 0xbec9b7b8, 0x408a9b6 3, 0x400e4918, 0x40000010, 0x5dde7db4, 0, 0, 0xc764, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) = 0 write(56, "A", 1) = 1 write(56, "T", 1) = 1 write(56, "S", 1) = 1 write(56, "T", 1) = 1 write(56, "F", 1) = 1 write(56, "F", 1) = 1 write(56, "\r\n", 2) = 2 write(56, "A", 1) = 1 write(56, "T", 1) = 1 write(56, "S", 1) = 1 syscall_983042(0x5dde79c0, 0x5dde79c4, 0, 0xfff, 0x408d5110, 0x5dde79c0, 0x5dde7f31, 0xf0002, 0, 0x5dde79c4, 0x4300e2b6, 0x2, 0, 0xbec9b7b8, 0x408a9b6 3, 0x400e4918, 0x40000010, 0x5dde79c0, 0, 0, 0xc764, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) = 0 write(56, "H", 1) = 1 write(56, "8", 1) = 1 write(56, "1", 1) = 1 write(56, "1", 1) = 1 write(56, "1", 1) = 1 write(56, "F", 1) = 1 syscall_983042(0x5dde85c8, 0x5dde85cc, 0, 0xfff, 0x408d5110, 0x5dde85c8, 0x5dde72a9, 0xf0002, 0, 0x5dde85cc, 0xfe6ef7fe, 0x2, 0, 0xbec9b7b8, 0x408a9b6 3, 0x400e4918, 0x40000010, 0x5dde85c8, 0, 0, 0xc764, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) = 0 write(56, "1", 1) = 1 write(56, "\r\n", 2) = 2 syscall_983042(0x5dde77f4, 0x5dde7804, 0, 0xfff, 0x5dde77f4, 0x408cff90, 0x56e939e8, 0xf0002, 0x408d5110, 0x1fd5, 0, 0x408d5190, 0, 0xbec9b7a8, 0x408a 9b63, 0x400e4918, 0x40000010, 0x5dde77f4, 0, 0, 0xc764, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) = 0 syscall_983042(0x5dde89bc, 0x5dde89c0, 0, 0xfff, 0x408d5110, 0x5dde89bc, 0x5dde8b0d, 0xf0002, 0, 0x5dde89c0, 0x4300e0a6, 0x2, 0, 0xbec9b7b8, 0x408a9b6 3, 0x400e4918, 0x40000010, 0x5dde89bc, 0, 0, 0xc764, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) = 0 syscall_983042(0x5dde8b48, 0x5dde8b4c, 0, 0xfff, 0x408d5110, 0x5dde8b48, 0x5dde89fd, 0xf0002, 0, 0x5dde8b4c, 0x4300e758, 0x2, 0, 0xbec9b7b8, 0x408a9b6 3, 0x400e4918, 0x40000010, 0x5dde8b48, 0, 0, 0xc764, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) = 0 write(56, "3", 1) = 1 write(56, "E", 1) = 1 write(56, "\r\n", 2) = 2 syscall_983042(0x5dde6d70, 0x5dde6d74, 0, 0xfff, 0x408d5110, 0x5dde6d70, 0x5dde8eb5, 0xf0002, 0, 0x5dde6d74, 0xf8a0f002, 0x2, 0, 0xbec9b7b8, 0x408a9b6 3, 0x400e4918, 0x40000010, 0x5dde6d70, 0, 0, 0xc764, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) = 0 syscall_983042(0x5dde8f10, 0x5dde8f20, 0, 0xfff, 0x5dde8f10, 0x408cff90, 0x56d91908, 0xf0002, 0x408d5110, 0x1fb7, 0, 0x408d5190, 0, 0xbec9b7a8, 0x408a 9b63, 0x400e4918, 0x40000010, 0x5dde8f10, 0, 0, 0xc764, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) = 0 syscall_983042(0x5dde8f04, 0x5dde8f08, 0, 0xfff, 0x408d5110, 0x5dde8f04, 0x5dde8f71, 0xf0002, 0, 0x5dde8f08, 0x4300e034, 0x2, 0, 0xbec9b7b8, 0x408a9b6 3, 0x400e4918, 0x40000010, 0x5dde8f04, 0, 0, 0xc764, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) = 0 syscall_983042(0x5dde5ba0, 0x5dde5ba4, 0, 0xfff, 0x408d5110, 0x5dde5ba0, 0x5dde7599, 0xf0002, 0, 0x5dde5ba4, 0xfcfaf001, 0x2, 0, 0xbec9b7b8, 0x408a9b6 3, 0x400e4918, 0x40000010, 0x5dde5ba0, 0, 0, 0xc764, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) = 0 syscall_983042(0x5dde6514, 0x5dde6518, 0, 0xfff, 0x408d5110, 0x5dde6514, 0x5dde9449, 0xf0002, 0, 0x5dde6518, 0xff98f002, 0x2, 0, 0xbec9b7b8, 0x408a9b6 3, 0x400e4918, 0x40000010, 0x5dde6514, 0, 0, 0xc764, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) = 0 syscall_983042(0x5dde77e8, 0x5dde77ec, 0, 0xfff, 0x408d5110, 0x5dde77e8, 0x5dde8769, 0xf0002, 0, 0x5dde77ec, 0xffbef000, 0x417321d8, 0, 0xbec9b7b8, 0x 408a9b63, 0x400e4918, 0x40000010, 0x5dde77e8, 0, 0, 0xc764, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) = 0 write(56, "1", 1) = 1 write(56, "A", 1) = 1 write(56, "8", 1) = 1 write(56, "0", 1) = 1 write(56, "\r\n", 2) = 2
If you’re familiar with AT commands at all, you may recognize some of the command sent. Either way, the ELM327 AT commands sheet has them all listed. Of course, my £7 dongle is not an official ELM327 based device, it’s a Chinese copy! But they did keep the AT commands the same for compatibility.
So, here’s how one piece of software initializes the bus:
atz #reset ete0 #echo off ATL0 #linefeeds off ATAL #allow long messages >7 ATSP5 #Set protocol ISO 14230-4 (KWP FAST) ATH1 #headers on ATSTFF #timeout big (ST32 is good) ATSH8111F1 #header 8111F1
I already know from research that my Bosch EDC15M ECU communicates over KWP, but what’s really interesting here is the header, 8111F1. Thanks to a Russian site with an explanation of KWP, I could work out what this header means (see below). The communications continue:
3E #tester present 1A80 #ECU ID table 1A81 1800FF00 #Mode 18 request for DTCs 3E 82 ATZ ATSH8128F1 #28 is the ABS 3E 3E 3E 82 ATZ ATSH8131F1 #31 is the EPS 3E 1A80 1A81 2101 2101 2101
KWP
The KeyWord Protocol, KWP2000 is not very well documented as far as I can find. One amazingly helpful resource was a Russian site with a document detailing one Russian ECU manufacturer’s implementation of KWP. Of course, their implementation is not exactly the same as Opel/Vauxhall’s, but it gives an insight into ISO 14230, which otherwise is inaccessible to those not willing to pay tens of thousands for access to the standard. It’s worth a read – open the page in Chrome if you do want a look, and it’ll translate it into English-ish for you.
Here’s my notes on it:
Header: Format – Target – Source – [Len]
Rest of message: Sld Data (63bytes)[255] Checksum
So, the header 81 11 F1 means: Format 81 (Start Comms, as per below) —– TO 11 (as above, 28 refers to the ABS in this car and 31 is the EPS controller) —– FROM F1 (I think this is abritrary, as long as it’s no used on the bus)
Format name Answer (id always 7f; bit 6=1) 81 startComms c1 82 stopComms c2 01 readDataByPID 10 startDiagnosticSess 50 20 stopDiags 60 11 ecuReset 51 12 freezeframeData 14 clearDTC 54 18 readDTCs 58 1A readECUID 5A 21 readDatabyLocID 61 22 readDatabyCommonID + 2 bytes 23 readMembyAddr 63 25 StopRepeatedDatatrans 26 SetDataRate 27 SecurityAccess 28 DisableNormComms 2C DefineLocalID 2E WriteDatabyCommonID 2F IOcontrolByCommonID 30 ioControlByLocID 70 3B writeDataByLocID 7B Corresponding to 21 3E testerPresent 7E Apparently send this every 2.5s GMLAN-specific: A2 ReportProgrammingState A5 EnterProgramming A9 CheckCodes AA ReadDPID AE DeviceControl
So those are the header types, now for the query payload:
10 startDiagnosticSess packet can be followed with 81 (diagnostic mode pls) and baud rate (0A, normal:26, high:39, enhanced) To stop send a 20 (should get 60 back. 7F is bad news) 3E Testerpresent followed by 01 (reponse pls) or 02 (its ok don't reply) 11 ecuReset followed by 01 for power on 1A ecuID followed by 1 byte: 80 - complete table. 1A 80 response: 5a 80 [3-21]VIN [22-37]ECUhardwareno [38-57]sysSupplierECUSW [58-72]Engine [73-79]repairshopCode [80-89]progDate [90-97]vehManECUID 5A 90 91 92 93 94 98 9f 1A A0 possibly ODO reading? 1A 90 VIN 14 clearDTC followed by 0000 Pwertrain or FF00 All systems. 54 reply contains same 2 bytes 18 ReadDTCs complicated 21 readDatabylocID: 01 - AftersalesServiceRecord (->128b) 02 - endOfAssemblyLine (->128) 03 - factoryTest (->128) A0 - immobilizerRecord (2) A1 - Body serial No (7) A2 - Engine Serial No (7) A3 - Manufacture date (10) A1 for example gives 61 A1 +7 bytes returned C3 - Possibly TRANS C4 - Aircon request at byte 1 D3 - Cruise control switches?? 21 A0 Immobilizer record 21 30 IO control 21 30 IObelow Param state IOs: 01 injector1OutputControl This setting informs the control unit, the tester prompts direct control of the nozzle 1. I1OC 02 injector2OutputControl This setting informs the control unit, the tester prompts direct control nozzle 2. I2OC 03 injector3OutputControl This setting informs the control unit, the tester prompts direct control of the nozzle 3. I3OC 04 injector4OutputControl This setting informs the control unit, the tester prompts direct control nozzle 4. I4OC 05 ignition1OutputControl This setting informs the control unit, the tester prompts direct control of the ignition coil 1 and 4 cylinders. IGN1OC 06 ignition2OutputControl This setting informs the control unit, the tester prompts direct control of the ignition coil 2 and 3 cylinders. IGN2OC 09 fuelPumpRelayOutputControl This setting informs the control unit, the tester prompts direct control of the fuel pump relay. FPROC 0A coolingSytemFanRelayOutputControl This setting informs the control unit, the tester prompts direct control of the cooling fan relay motor. CSFROC 0B airConditionRelayOutputControl This setting informs the control unit, the tester prompts direct control relay unit. ACROC 0C malfunctionIndicationLampOutputControl This setting informs the control unit, the tester prompts direct control of the MIL. MILOC 0 D canisterPurgeValve OutputControl This setting informs the control unit, the tester prompts direct control canister purge valve. CPV OC 41 idleStepMotorPositionAdjustment This setting informs the control unit, the tester prompts direct position control idle speed regulator. ISMPA 42 idleEngineSpeedAdjustment This setting informs the control unit, the tester prompts direct control idle speed. IESA Params: 00 returntoECU. 01 reportState. 02 reportIOconditions. 03 reportIOscaling. 04 resetDefault. 05 freezeCurr. 06 executeControlOption. 07 shortTermAdjust. 08 longTermAdjust. 09 reportIOcalibration --------------- --------------- 23 Read mem by address 23 MemType=0 AddrMSB AddrLSB Memsize Response 63 xx xx xx xx ----- 3B Write Data by LocID 90 - VIN 98 - RepairShopCode A1 bodySerNum A2 engineSerNum A3 manufactDate Eg. 3B 90 + 19 ASCII chars 3B 90 xx xx xx xx -> Wait for flow control??? 30 00 00 Response 7B 90 or 7F 3B errCode ------------ 27 Security 27 subFunct 01 SeedRequest 02 KeyResponse 03 SeedAnother 04 ResponseAnother.....
Bored yet?
I won’t go on too much more about KWP, suffice to say sending a header 8111F1 and payload 2101 gives the “AftersalesServiceRecord”, which contains all the data we need:
2101: 80 F1 11 4C 61 01 00 00 00 00 00 00 00 00 0C 0C 00 00 0B C1 00 00 02 4C 00 00 00 00 03 E3 00 00 00 00 32 C8 03 E7 04 29 03 38 E5 62 00 00 00 00 03 84 00 00 00 00 09 3D 00 00 0C 09 A0 00 01 90 00 00 A9 00 00 20 00 00 01 BD 0C 2F 03 E8 00 02 9D
The response starts 80 F1 11 (Response, TO F1, from 11 (ECU)
Then 4C = Error (OK) code, and:
21 01 Responses: # 1 Positive response readDataByLocalIdentifier 61 no # 2 afterSalesServiceRecordLocalIdentifier 01 no # 3 Word of equipment 1 08 no # 4 Word of picking 2 35 no # 5 The word mode 1 XX no # 6 Word of mode 2 XX no # 7 Memory word current faults 1 XX no # 8 Memory word current faults 2 XX no # 9 Memory word current faults 3 XX no # 10 Memory word fault current 4 XX no
Then things get interesting. The following pairs of bytes (WORDs) give all sorts of info: Throttle position, coolant, air and oil temperature, desired & actual RPM, desired & actual boost pressure, EGR pulse ratio, road speed, cruise control set speed, battery voltage, brake pedal position, MAF flow rate, air pressure and others.
Which byte is which?
Sorry, I’m not going to tell you that! It took ages of getting sensor readings under different conditions – different temperatures, different load conditions, lots of throttle blipping to figure out which reading is the ‘desired’ value and which is the ‘actual’ value for many of the values. Oh, and things like the temperatures being measured in Kelvin instead of degrees (free clue!)
EDIT:
That wasn’t very nice, sorry. The info is all in the Github project XBMC-rpi-service.skin.OBD and some explanation is in my followup post here
Excel PID working out – This .xlsx file has my workings out of how I figured out which byte of the 2101 response was which. It’s not nicely formatted but scroll to the right to see my formulae and adjusted values
2101-on.txt has the original values used to create the above spreadsheet
I seem to have lost the original python code used to generate that .txt file, but it’s pretty straightforward: I just kept sending 2101 requests after setting the header ATSH8111F1. Once I figured out that the values came in byte pairs, I used excel to translate these to numbers, and a knowledge of how the engine works to figure out which data should trend which way.
Back to the Pi
So, how does the Pi work?
The Raspberry Pi is running the Xbian build of XBMC – it’s the fastest by far, and has most bits you’ll need pre-installed.
One thing that got missed out for some reason is libtiff. If you get error messages like the below in your logs (/home/xbian/.xbmc/temp/xbmc.log), you’ll need to install libtiff4.
15:46:20 T:2913350720 DEBUG: Loading: /usr/local/lib/xbmc/system/ImageLib-arm.so 15:46:20 T:2913350720 ERROR: Unable to load /usr/local/lib/xbmc/system/ImageLib-arm.so, reason: libtiff.so.4: cannot open shared object file: No such file or directory 15:46:20 T:2837853248 DEBUG: SECTION:LoadDLL(special://xbmcbin/system/ImageLib-arm.so) 15:46:20 T:2837853248 DEBUG: Loading: /usr/local/lib/xbmc/system/ImageLib-arm.so 15:46:20 T:2837853248 ERROR: Unable to load /usr/local/lib/xbmc/system/ImageLib-arm.so, reason: libtiff.so.4: cannot open shared object file: No such file or directory ^C [email protected]:/home/xbian# apt-get install libtiff4
I did a lot of work on getting the GPIO working in and out straight from the XBMC skin. I’ll cover that in a separate post.
Bluetooth
Here’s what I did to get bluetooth connecting to the ELM327 scanner:
[email protected]:/home/xbian# apt-get install bluez [email protected]:/home/xbian# hcitool scan Scanning ... 00:01:E3:8B:AE:43 Mark 00:01:E3:8E:F4:E9 Ant Dect 00:0D:18:27:FA:E6 Vgate [email protected]:/home/xbian# cat /etc/bluetooth/rfcomm.conf # # RFCOMM configuration file. # rfcomm99 { bind yes; device 00:0D:18:27:FA:E6; channel 1; comment "ELM327 based OBD II test tool"; } [email protected]:~# cat /etc/udev/rules.d/99-custom.rules KERNEL=="rfcomm99", ATTR{address}=="00:0d:18:27:fa:e6", ATTR{channel}=="1", OWNER="xbian", GROUP="dialout", SYMLINK+="elm327" cat /etc/init.d/elm327 #!/bin/bash DevNum=99 # DevNum is depending on the rfcom settings /etc/bluetooth/rfcom.cfg case $1 in start) rfcomm bind $DevNum ;; stop) rfcomm release $DevNum ;; status) rfcomm show $DevNum ;; *) cat<
And some testing:
apt-get install python-serial screen /dev/rfcomm99 38400 python to start Python. import serial ser = serial.Serial('/dev/rfcomm99', 38400, timeout=1) Nser.write("01 0D \r") speed_hex = ser.readline().split(' ') speed = float(int('0x'+speed_hex[3], 0 )) print 'Speed: ', speed, 'km/h'
See my followup post for more info and links to github projects
Good afternoon could you please inform wtich skin do you used for display de speed and were to find it? Thank you
Good afternoon could you please inform wtich skin do you used for display de speed and were to find it? Thank you
Hi, I was just wondering when you might right up that second blog post about the skin customisation. What you have done is incredible and I’d like to replace my dash gauges with an LCD panel connected to the pi, with a custom xbmc skin like yours!
Thankyou!
Hi
this is a very good proyect. I’m trying to make a display with an Arduino that tell’s me the consumptions and some other things form the engine ecu.
I can make a connection with the ecu, but i can´t throw the sensor data to the computer.
what AT commands and sequence did you used for the live sensor data?
regards
I think that a lot of this information is just something we already know … And all of us, who came here trough the search engine, are expecting to see the actual integration and code base. What I mean is the following:
1) Where did you get the XBMC (which distro with what additional settings a link would work just fine).
2) Where did you get the interface or you wrote it yourself? If the latter – how? Some code? Git hub etc…
3) What kind of OBD addapter, display, remote control,
4) Power – where does it come from.
5) Readings – ok we all know that certain bites are corresponding to certain data, we came here to learn which for what….
6) GPIO – How?
Great job! But it isn’t useful for people who want to replicate your project. In fact nobody can replicate your project or if somebody can it will take that somebody the same (or more) amount of time struggling to bring it together.
Don’t take it personally, I am not trying to hate you, I am just saying the the information provided isn’t very helpful. See all of the struggles you’ve been trough are actually not shared and nobody can get any “profit” (understand the knowledge) of it. It isn’t even worthy for you any more as it is probably a finished piece of work.
Share the specifics please.
Best Regards 🙂
hey, is it possible to get you skin? course the 7tft skin isn`t compatible with xbmc 13.
sry for my english! thank you
Good project! What do you think about our Raspberry Pi Car PC project – http://i-carus.com ?
Hi Ant,
thank you for your impressive project.
I hope i will be able to do a similiar project.
Can you please upload your complete project, with the skins and more information?
Thank you
Tim
Yes, I’m sorry this has taken so long. I will dig out the info and post it soon!
Looks interesting, sold any yet? You spelt amplifier wrong (amplifyer)
Yes, it took a bit of work to get it working but I’ll post it here soon
please send me the Skin:)
Sorry this took so long – see my followup post here with links to github projects