042117_1148_TinkeringTu2.jpg

Tinkering Tuesday – HUEify – JN5168 to Arduino Mega PWM extension

The JN5168 chip itself has only 5 PWM outputs and thus is not able to control more than one RGB LED strip. To overcome this I want to connect an Arduino Mega to the JN5168. The Mega has 15 PWM outputs so up to 5 RGB strips can be connected. To connect the two devices I chose to use the standard UART serial interface that is activated by default in the NXP demos. In this post I will describe how to connect the two devices and what to do to make the Arduino understand commands from the JN5168.

Hardware serial connection from JN5168 to the Arduino

As the Arduino is using 5V level on the serial connection and the JN5168 is using 3.3V a logic level converter (LLC) has to be used. This little device connects the two serial interfaces shifting from 5V to 3.3V. The connection can be seen in the following image (to drive the JN5168 from the Arduino connect an additional wire from the 3V3 pin of the Arduino to PIN 17 of the JN5168):

Connecting the JN5168 to the Arduino Mega via logic level converter
Connecting the JN5168 to the Arduino Mega via logic level converter

Software serial connection from JN5168 to the Arduino (JN5168 program)

I used the default UART port of the JN5168 because of two reasons:

  1. It is activated by default and the demos are already making use of the output
  2. I didn’t connect any additional wires than the ones that need to be connected to flash the chip and use the PWM output and the default UART is also used to flash the firmware

To have a more stable connection to the Arduino I reduced the baud rate from 115600, which is the default rate, to 9600 which the Arduino can handle better. To do this in the file app_start_light.c go to the function vAppMain() and search for the line :

DBG_vUartInit(DBG_E_UART_0, DBG_E_UART_BAUD_RATE_115200);

and change it to:

DBG_vUartInit(DBG_E_UART_0, DBG_E_UART_BAUD_RATE_9600);

Do the same in the function vInitialiseApp() in the same file.

I tried two different approaches to send output to the arduino:

  1. Use the debug output of the TRACE_LIGHT_TASK / DEBUG_LIGHT_TASK
  2. Define a custom debug flag to directly output the PWM signal.

As I didn’t have success yet creating multiple RGB endpoints and am waiting for PeeVeeOne to publish his work on multiple endpoints, I first went with option 2 which is currently not able to hand over an identifier for the endpoint which the option 1 is able to. The second option has the advantage that it handles smooth transitions, which the other one doesn’t. Once I am able to create more endpoints I may create another output. I will describe both solutions anyway:

Option 1: TRACE_LIGHT_TASK

First, activate the debug flag in the Makefile:

CFLAGS += -DDEBUG_LIGHT_TASK

Then go to the file app_zcl_light_task.c and search for

DBG_vPrintf(TRACE_LIGHT_TASK

I modified the first appearance (in APP_ZCL_cbEndpointCallback) of the function, where it outputs a new line and the RGBL (Red, Green, Blue, Level) values to include an identifiying symbol (§) and the endpoint:

DBG_vPrintf(TRACE_LIGHT_TASK, "\n§ EP %d R %d G %d B %d L %d ",
psEvent->u8EndPoint, u8Red, u8Green, u8Blue, sLight.sLevelControlServerCluster.u8CurrentLevel);

There is a second appearance in the same file and the same function (APP_ZCL_cbEndpointCallback ) where I did the same thing again.

In the file App_Light_ColorLight.c there are two other usages of the function which handle the identification effect. In the function APP_vHandleIdentify() there is currently no handle for the endpoint available so I didn’t modify this one. In the vIdEffectTick() there is an endpoint reference available so I added this similar to the function call above.

DBG_vPrintf(TRACE_LIGHT_TASK, "§ EP %d R %d G %d B %d L %d Hue %d Sat %d\n",
u8Endpoint,
u8Red,
u8Green,
u8Blue,
sLight.sLevelControlServerCluster.u8CurrentLevel,
sLight.sColourControlServerCluster.u8CurrentHue,
sLight.sColourControlServerCluster.u8CurrentSaturation);

In the end the Arduino will receive a message will look like this:

§ EP 10 R 255 G 227 B 139 L 147 Hue 0 Sat 0 X 24939 Y 24701 M 1 On 1 OnTime 0 OffTime 0

This one call will result in 10 PWM changes in the JN5168 to have a nice transition. This is why I currently go with the second option:

Option 2: TRACE_PWM

First, I defined and enabled a new debug flag in the Makefile:

CFLAGS += -DDEBUG_PWM

Then in the file DriverBulb_JN516X_RGB.c I added the following to the definition section at the beginning:

#ifdef DEBUG_PWM
#define TRACE_PWM TRUE
#else
#define TRACE_PWM FALSE
#endif

Then, in the function DriverBulb_vOutput() I added the following after the calls to vAHI_TimerStartRepeat at the end:

#if TRACE_PWM
DBG_vPrintf(TRACE_PWM, "\n# EP %d On %d R %d G %d B %d L %d",
(uint8)10,
bIsOn,
u8Red,
u8Green,
u8Blue,
u8CurrLevel
);
#endif

Together with the first option this will result in the following output (as I said it produces a smooth transition):

§ EP 10 R 255 G 227 B 139 L 147 Hue 0 Sat 0 X 24939 Y 24701 M 1 On 1 OnTime 0 OffTime 0
# EP 10 On 1 R 170 G 151 B 92 L 170
# EP 10 On 1 R 167 G 148 B 91 L 167
# EP 10 On 1 R 165 G 146 B 89 L 165
# EP 10 On 1 R 162 G 144 B 88 L 162
# EP 10 On 1 R 160 G 142 B 87 L 160
# EP 10 On 1 R 157 G 139 B 85 L 157
# EP 10 On 1 R 154 G 137 B 83 L 154
# EP 10 On 1 R 152 G 135 B 82 L 152
# EP 10 On 1 R 149 G 132 B 81 L 149
# EP 10 On 1 R 147 G 130 B 80 L 147

You can also see that the RGB values changed. This is according to the level value. The calculation is:

/* Scale colour for brightness level */
u8Red = (uint8)(((uint32)u8CurrRed * (uint32)u8CurrLevel) / (uint32)255);
u8Green = (uint8)(((uint32)u8CurrGreen * (uint32)u8CurrLevel) / (uint32)255);
u8Blue = (uint8)(((uint32)u8CurrBlue * (uint32)u8CurrLevel) / (uint32)255);

The level is not really necessary in the output because the RGB values are already adjusted. I kept them anyway.

Software serial connection from JN5168 to the Arduino (Arduino program)

For the Arduino part I first setup the serial connection (I connected it to Serial2) and read the input. Based on the first character (§ or # are the relevant ones for the two options) the program decides whether the whole line is relevant.

Then it parses the input line using the function strtok(). Then I set the PWM using analogWrite(pin, value).

The serial input is lagging sometimes (though I think this is only the case when using the serial output to the other serial port) so garbage is getting read as a line. In case of not set values I checked whether the value is correctly set. Otherwise the old value is used. This may lead to wrong values but better than nothing.

My currently used Arduino sketch (using only one PWM output) can be downloaded here:

SerialReadPWMFromJN5168

Conclusion

This may not be the best way of communication (SPI may be better) but it is the easiest to setup. To command 4 separate endpoints I may have to use option 1 and go without transitions or implement them myself on the arduino. The bottle neck seems to be the serial connection as the arduino seems to be too slow to process the serial input fast enough. This is another argument for option 1 as it sends fewer lines. Although it is sending more than one line for a simple light change, too. Maybe the app itself also sends several commands to have a nice transition. I may check this later on. In any case I recommend disabling all other debug outputs to make better use of the serial communication and loose fewer lines.

Currently I am also building a board to connect everything together. It will not be very professional (as I will be using many jumper wires instead of connecting everything directly but I want to be flexible) but should work for me. It will be hidden away anyway. The board connected to the Arduino and the serial connection to the JN5168 can be seen in the upper left with one temporarily connected RGB strip. In the final version they will be connected with screw terminals. The LLC will also go from the breadboard to the custom board.

The completed serial connection from JN5168 to Arduino Mega and custom PWM to RGB LED adapter board
The completed serial connection from JN5168 to Arduino Mega and custom PWM to RGB LED adapter board

This is the current progress with connections ready for two RGB strips.

Custom PWM to RGB LED strip adapter board (work in progress)
Custom PWM to RGB LED strip adapter board (work in progress)

There will be 4 RGB connections in the final version to be connected with screw terminals, the LLC and a connection for an external power source. This is all still work in progress so I will publih the final schematics when I am ready and know that everything is working as expected. And of course I hope that the weather will be getting better here so I can disassemble our night desks and get them to my workbench (actually my balcony which is why I am hoping for good weather 😉

021717_1339_FotoFridayX5.png

Foto Friday – Xiaomi Yi HD RAW komfortabel in DNG konvertieren

In meinem letzten Foto Friday habe ich ja schon über die Möglichkeit geschrieben mit der Xiaomi YI Fotos im RAW Format aufzunehmen. Im dort referenzierten Beitrag im Dashcam Forum gibt es auch gesammelte Tools zum Postprocessing:

https://dashcamtalk.com/forum/threads/the-definitive-xiaomi-yi-raw-guide.13079/

Das Vorgehen, das dort beschrieben wird ist jedoch mit einigem manuellen Aufwand verbunden. Wer Photoshop und/oder Lightroom nutzt, der bekommt dort auch ein Lens Profile. Da ich das nicht nutze ist das für mich nicht interessant, könnte aber ganz praktisch sein.

Auf der Seite http://www.tawbaware.com/xiaomiyi.htm gibt es ebenfalls noch ein paar gute Tipps über das Hacking der Yi und auch ein Skript um die RAWs umzuwandeln (leider nur die unkomprimierten, die per Skript, Einzelfoto oder Timer, nicht aber Burstmodus oder der Standard Timelapse-Modus, erstellt werden). Das finde ich das beste und einfachste Tool. Die Einrichtung ist aber nicht ganz intuitiv weil man sich die Programme noch zusammensammeln muss und entsprechend einrichten, sodass es einfach zu bedienen ist (ist dort im Grunde fast alles beschrieben, allerdings nicht als zusammenhängende Anleitung und an verschiedenen Stellen):

  1. Unten auf der Seite http://www.tawbaware.com/xiaomiyi.htm gibt es ein ZIP-File herunterzuladen:
  2. Den Inhalt entpackt man sich bestenfalls in einen Ordner auf C:\. Im Skript ist der Ordner C:\utilities vorgesehen, ich habe meinen Tools genannt. In den gleichen Ordner habe ich die beiden Programme raw2dng und exiftool gepackt. Die muss man sich nochmal separat besorgen.
  3. Raw2dng bekommt man auf der Seite http://e2500.narod.ru/raw2dng_e.htm (Download als .7z-File, man benötigt also 7-zip oder ein kompatibles Entpackprogramm). Hierin sind mehrere Dateien enthalten:
    Gebraucht wird aber nur die Datei raw2dng.exe, welches die Kommandozeilenversion ist. Der Download aus dem Dashcam-Forum nutzt z.B. die raw2dng_en.exe, welches die Version mit einer grafischen Oberfläche ist.
  4. Exiftool bekommt man auf der Seite http://www.sno.phy.queensu.ca/~phil/exiftool/. Hier lädt man sich die Windows-Executable herunter:
    Die Datei dann in den gleichen Ordner wie die anderen Dateien entpacken und wie auf der Seite beschrieben in exiftool.exe umbenennen.
  5. Im Skript selbst muss man nun die Pfade zu den Programmen eintragen. Dazu die xiaomi_dng.bat mit dem Texteditor der Wahl öffnen und in den Zeilen 33 und 34 den Pfad anpassen. Bei mir wäre das:
    Und wo wir dort gerade sind: Standardmäßig ist die Ausgabe des Skripts sehr umfangreich. Deswegen am besten in der ersten Zeile das „rem“ entfernen, also die Zeile
    @rem echo off
    ändern in
    @ echo off
  6. Nun wäre das Tool schon einsatzbereit indem man die RAW-Dateien einfach auf die BAT-Datei zieht. Aber man kann sich das Leben noch etwas komfortabler machen indem man einen neuen „Senden an…“ Eintrag im Windows Explorer Kontextmenü hinzufügt. Dazu öffnet man einen Windows Explorer und fügt in die Adresszeile
    shell:sendto
    ein. Das ist ein Shortcut für den Ordner C:\Users\<username>\AppData\Roaming\Microsoft\Windows\SendTo
    Dort fügt man jetzt einfach eine Verknüpfung zur xiaomi_dng.bat ein (z.B. „Rechtsklick – Verknüpfung erstellen“ oder Drag & Drop unter festhalten der Alt-Taste). Den Namen der Verknüpfung kann man frei wählen, ich habe mich z.B. für „Xiaomi RAW 2 DNG Converter“ entschieden.
  7. Jetzt kann man ganz einfach seine RAWs im Windwos Explorer markieren und im Kontextmenü an den Converter senden:
  8. Es öffnet sich ein Command Fenster und die Dateien werden verarbeitet. Am Ende wird dann die Meldung „Conversion Complete“ ausgegeben und mit einer beliebigen Taste kann das Fenster geschlossen werden:

Komprimierte RAWs

Das Prozedere funktioniert wie schon gesagt leider nur für die unkomprimierten RAWs (um die 31 MB), nicht für die 13 MB großen komprimierten.

Dashcam User AndreaPaco hat ein wenig Zeit investiert um auch die komprimierten, 13 MB großen Files nutzbar zu machen. Mit den folgenden Einstellungen für raw2dng kann man zumindest das Bild erahnen, es ist aber weit entfernt von nutzbar:

13492224, 0, 4608, 3456, 7, 3904, 16, 4, XIAOMI-YI-COMP

Siehe: https://dashcamtalk.com/forum/threads/the-definitive-xiaomi-yi-raw-guide.13079/page-4#post-250926

Das Ergebnis sieht wie folgt aus:

Auf der linken Seite ist das Bild grob zu erkennen. Mehr aber auch nicht. Leider ist dort seit Mai 2016 nichts mehr passiert, sodass ich hier keine Hoffnung mehr habe (vor allem auch, da ja der Nachfolger mit der Yi 4K schon lange raus ist und dessen Nachfolger auch in den Startlöchern steht).

Rotstich

Sollte das RAW sehr rotstichig sein, so hat die Umwandlung mit dem Exiftool nicht funktioniert:

Sollte eher so aussehen (nach erfolgreicher Umwandlung):