Monday, June 5, 2023

Nanlite USB-C DMX Cable Instead of Aputure USB-C/ DMX Cable?

Out of curiosity, and because they are nearly half the price of the Aputure USB-C/DMX cable, I really wanted to know if the Nanlite USB-C/DMX cable would work as a suitable replacement for the Aputure USB-C/DMX cable. After getting zero information from both Nanlite and US retailers (uh-hem... B&H), I decided to purchase one to see if the similar looking Nanlite cable would work instead. Here is what I found.

Unfortunately, the Nanlite USB-C/DMX cable uses D+/D- and GND to transmit DMX data, so it sadly is not compatible with the Aputure USB-C/DMX cable which uses A10/A11 (and B10/B11) and GND. 

Wednesday, May 10, 2023

PyInstaller - Include sv-ttk Sun Valley TTK Theme in build


Trying to build a python application using tkinter and ttk Sun Valley theme using pyinstaller, the finished build would throw errors unable to find the tcl file and related theme data. Pyinstaller does a pretty good job finding and including related python files and modules, but it doesn't do so well with other assets and this theme uses other assets.


The brute force method is just to include the tcl file and theme resources manually when building the program.

pyinstaller --onefile --noconsole --add-data "<path to python modules>\Lib\site-packages\sv_ttk\sv.tcl;sv_ttk\" --add-data "<path to python modules>\Lib\site-packages\sv_ttk\theme\*;sv_ttk\theme" .\

This should produce the bundled application with the resource files all embedded where the scripts expect to find them. 

Thursday, March 23, 2023

Notes on Getting Python to Talk to FTDI FT232 chipset for USB Serial Communication

NOTE: This is incomplete and is nothing more than just notes for myself. It is not yet part of a complete solution and I don't fully understand all the consequences that may be involved. Follow at your own risk.

To get python to talk to FTDI FT232 chip for USB Serial Communication (Windows)

Replace the existing FTDI Driver with libusb-win32 using Zadig (Reference

Now the device shows up when searched for using VID and PID:

import usb
import usb.util
print(usb.core.find(idVendor=0x0403, idProduct=0x6001))

It WILL NO LONGER list under:


# List all available COM ports
ports = list(

# Print information for each port that is currently in use
for port in ports:
    if is not None and port.vid is not None:
        print(f"Port: {port.device} - VID: {hex(port.vid)} - PID: {hex(} - Description: {port.description}")

but now pyftdi can now connect using VID and PID:

import time
from pyftdi.ftdi import Ftdi, FtdiError

    ftdi = Ftdi(), product=0x6001)

    while ftdi.is_connected:
            status = ftdi.modem_status()
        except FtdiError:


Sunday, March 19, 2023

Unreal Engine 5 Development Resources

These are some very helpful resources I've compiled for getting started with UE5 development (especially if you don't have strong C++ experience).

If things aren't working or aren't building properly, close your code editor and Unreal editor delete Binaries and Intermediate in the project directory, and relaunch Unreal. (This has solved issues where Hot load modules prevented Live Coding to not work, and when an OnComponentHit callback wasn't being called. 

UE5 Quick Start: 

UE5 General Development Info: 

Titled: Unreal Engine C++ Complete Guide:


This may feel slightly under documented, as it fails to provide excess explanations, but it does include quite a bit that helps including which modules you need to include, which headers, and the general signature to methods. 

UE Slackers Common Problems:

This is great for understanding why you are getting the errors you get. 

Unreal Engine 5 C++ Developer: Learn C++ & Make Video Games (Paid)

I don't know if I benefit or not from the link, but either way this course is a great primer into UE game engine development and C++ (even if you are not very familiar with either). This is a paid resource, but wait for it and it will go on sale for like $20 -- although it is probably fair at $110 for how much you get our of it. (I paid about $20 and it was worth every penny). 

Monday, February 27, 2023

OpenAI / Github Copilot - It's not quite ready yet... but maybe it is for some. (Updated)

Update - It might be ready for some:

Like most things, you can find value if you lean into the strengths. I've continued to try and work with this and I admit there are times where it saves me some steps. For examples:
  • In both flutter and Postgres, I found that it recognizes sequences and assists to finish entering them in.
  • In classes, if I'm adding a function to convert the internal units of distance from meters to miles - Copilot quickly identified what I was trying to do, and wrote code to do the conversion including null checks. 
  • Writing out a comment for refactoring and having it modify existing code with the refactoring in place

In these cases, it was actually about 95% correct (meaning no additional changes were required on my part). I'm not yet convinced we are seeing a value worth $10 / mo yet, but it's probably worth half that. I'll document more as I use it further. 

Original Post:

OpenAI / chatGPT / Github Copilot:

Having kept up with the chatGPT craze, I was excited to try out Github Copilot. It promises many great benefits, including:

  • Converting comments to code
  • Creating unit tests
  • Writing SQL queries

Having used OpenAI before via chatGPT for code generation/review, I knew it was capable of much more. I suppose to be fair, I did not test the touted features (list of 3 above) of this platform specifically - at least not line-by-line like their examples, but I feel like my expectations were reasonable for a service like this.

What I've tried it with so far: 

  • Flutter / dart development including implementing the supabase library
  • Programming C++ for Unreal, specifically writing a custom DMX Modulator for RGB to HSI conversion
  • Converting SQL queries for Postgres


  • Many suggestions were invalid. This is likely due to that fact that the training data for this model cuts off back in 2021. Anything produced since then is more or less unknown. This was evident with the outdated suggestions on Unreal and outdated library suggestions for supabase. 
  • The SQL conversions were only partially correct. It was unable to do the full conversion.
  • Before Copilot, I used chatGPT to seek assistance with some issues, I was met with conflicting results. The first was the outdated code problem, but the second was that when I would tell it the code was wrong, it would apologize, admit that a correction was necessary due to a newer version and then print new code which usually ends up being a mash-up of old library calls and a few lines updated for the new library. When I asked what it knew about the new library (citing the same reference it gave before) it said it knew nothing of anything from after the cut-off date. The outdated code issue was also present in the IDE with suggestions the Copilot gives. Many of these were incorrect.
  • Lack of customizations / rules. AFAIK there is no interface with the service from my IDE (Visual Studio Code) at this time. This means you can't customize how and when copilot does it's thing, other than completely enabling or disabling the service. 


I imagine a lot of this is actually fairly well-known already by those building the service or having been using the service for much time. The only real benefit (maybe) to this point has been the auto completion a couple times. Certainly not worth the $10 / mo price tag right now. I would love to have a UI that let's me direct the service in how I want it's help or even an icon that pops up that I can click on to see the suggested improvements / optimizations.  

These should be a standard part of the service:

  • Reduce bugs
  • Bring knowledge base up-to-date
  • Add/Improve UI in the IDE
  • Add knowledge for the code-base as a whole
  • Identify programming patterns in-use, and be consistent with them with suggestions (I actually do not know if this is available, but since it doesn't seem to know the other files in your project, I assume it is not)

Once these are implemented, I think this service would be amazing at $10 / mo.

A final word about ethics. Some people have criticized these kinds of AI services (i.e. Midjourney, OpenAI, etc.) because they produce value based on the analysis of existing works (i.e. art, public code repositories). Many of these works are protected or licensed, however what is being produced is derivative which to my knowledge, generally has certain allowances legally (I'm not a lawyer). The question I come back to is: Are original works, actually original works, or simply derivations of other inspiring things? If I create something artistic after visiting a museum, writing a song after hearing another inspirational song, or write a story after reading an inspirational story, am I really creating original art? There is a reason there is an entire field of law dedicated to these questions. But the bottom line seems to be, if you don't feel right about it, don't support it.

As a bonus, I ran the content above through chatGPT to "make it better", lol:

As someone who has been following the chatGPT craze, I was excited to try out Github Copilot and see what it could offer. Its promise of converting comments to code, creating unit tests, and writing SQL queries seemed like a game-changer.

However, my experience with Copilot has been mixed. While I've used OpenAI before via chatGPT for code generation and review, I found Copilot's suggestions to be sometimes invalid and outdated. This is likely due to the fact that the model's training data only goes up to 2021, leaving it unable to provide accurate suggestions for newer libraries and frameworks.

For instance, I encountered issues with outdated library suggestions for supabase and Unreal, and SQL conversions were only partially correct. When I sought assistance with some issues using chatGPT, I received conflicting results. While it would apologize and admit that corrections were necessary due to a newer version, it was limited by the cut-off date of its training data and could not provide knowledge beyond that point.

Another issue was the lack of customization options, as there is currently no way to customize when and how Copilot functions within my IDE (Visual Studio Code). This means that I can only enable or disable the service entirely.

In my opinion, Copilot needs to reduce bugs and bring its knowledge base up-to-date. It also needs to add an interface within the IDE to allow for customization, provide suggestions based on programming patterns, and identify consistent coding practices. If these improvements were made, I believe the service would be worth its $10/month price tag.

On the topic of ethics, some have criticized these types of AI services for producing value based on existing works, including licensed or protected code. While derivative works may have certain legal allowances, it's important to consider whether original works truly exist or are simply inspired by existing ideas. Ultimately, it's up to individuals to decide whether they feel comfortable using such services.

In summary, while Copilot has its benefits, it still has room for improvement. With updates to reduce bugs, improve the knowledge base, and provide customization options, it could be a game-changer for developers. As for ethics, it's a complex issue, and individuals must make their own decisions based on their personal values.

Friday, February 24, 2023

Unreal Engine 5 Development - Quick Checklist

Since I have done this more than once, I figured I would make myself a quick cheat sheet for setting up to develop for Unreal Engine. 

* Unreal Engine 5 installed (including: Editor Symbols)

* The optional stuff for Visual Studio

* Visual Studio Code with C++ Extension


Unreal - Visual Studio Code includePath error: Invalid escape character in string.


Recently, I began working with C++ for Unreal Engine 5.1. As part of the setup process, you configure your development to be done with Visual Studio Code. Details here:

However, they mention adding the follow code to your c_cpp_properties.json:

"includePath": [ "${workspaceFolder}\\Plugins\\**", "C:\\${workspaceFolder}\\Source\\**", "${workspaceFolder}\\Intermediate\\**" ], 

This will produce an error: Invalid escape character in string. jsonc(261)


This pretty close, but is missing a second forward slash "\" required to accurately set these glob patterns:

"includePath": [ "${workspaceFolder}\\Plugins\\**", "C:\\${workspaceFolder}\\Source\\**", "${workspaceFolder}\\Intermediate\\**" ], 

Saturday, February 18, 2023

Electron IPC Channel Subscriptions


While working on an Electron program that has multiple windows, I knew I needed the windows to be able to talk to each other. This is usually done with each window establishing a connection with the main script, and then the main script facilitating the communication between each window. This way works fine, but seems very manual and then became a bit more convoluted when multiple windows need to get the same information. 


To solve this, I decided to implement a very simple subscription style connection:

const ChannelSubscribeAction = 'channel-subscribe';
const ChannelUnsubscribeAction = 'channel-unsubscribe';
const ErrorDataChannel = 'error-data';

// handle channel subscriptions
const channelWindowMap = new Map();
ipcMain.on(ChannelSubscribeAction, (event, channel) => {
    if (!channelWindowMap.has(channel)){
        channelWindowMap.set(channel, new Set());
        ipcMain.on(channel, (event, data) => handleChannelEvent(channel, event, data));
    channelWindowMap.set(channel, channelWindowMap.get(channel).add(event.sender));
ipcMain.on(ChannelUnsubscribeAction, (event, channel) => {
    if (!channelWindowMap.has(channel)) return;
    channelWindowMap.set(channel, channelWindowMap.get(channel).remove(event.sender));
function handleChannelEvent(channel, event, data){
    if (!channelWindowMap.has(channel)) return;
    channelWindowMap.get(channel).forEach((webContentWin) => {
        webContentWin.send(channel, data);
        // if we get an error, open dev tools for the window that had the error
        if (channel == ErrorDataChannel){

This allows for any window to subscribe to any channel, and then later unsubscribe if desired. In my code here, I also am detecting when script errors occur and triggering the dev tools to open for that specific window to have a closer look. 

The channels are all defined in a single simple enum file and then when each window starts up, it calls in: 

ipcRenderer.send(ChannelSubscribeAction, Channels.MainChannel);

Note: There may be some vulnerabilities that come with this approach.

Tuesday, January 24, 2023

Blackmagic Workflow Integration using JavaScript/Electron - Node Modules


While building an electron application for Blackmagic Workflow Integration, I found that installing modules would present some errors specifically related to the Node-API version. 

For example, after installing sqlite3 the project would say can't find module: napi-v3-win32-unknown-x64\node_sqlite3.node

Looking at node_modules/ I noticed that the sqlite3 node build contained napi-v6-win32-unknown-x64\node_sqlite3.node


After a bit, it dawned on me that DaVinci Resolve was using it's own nodejs which would likely not be the version I have installed on my terminal. Launching the integration from Resolve with dev tools open, I quickly checked the version of node running: process.version and found that in my instance it was v12.13.0. Using NVM, I changed my terminal installed nodejs to be the same version and installed the node module once again. This produced the correct result.

Another way to find out the version of everything is to find and launch the electron application bundled with Resolve (Windows: C:\Program Files\Blackmagic Design\DaVinci Resolve\Electron) which will show you an application screen with information like this: 

Wednesday, January 4, 2023

Unreal to DMX Fixture using USB DMX and QLC+

While working on a building a small virtual production test studio, one of my tasks was being charged with building DMX light panels, and connecting up existing DMX lights to Unreal. The first version of this included using ESP8266 boards and Art-Net to receive the Art-Net broadcasts from Unreal. This works fine and there is a lot of great information online about how to accomplish this. We quickly found that when adding a lot more lights and universes that there seem to be some performance issues. Ultimately, instead of improving the existing setup, it was decided to abandon WiFi in favor of a more stable wired setup. 

Wired Connections

Some of the lights we are working with are Amaran T2c and T4c RGBWW lights. These are DMX capable over USB-C (3.0/3.1) using RX1/TX1 (which are internally connected to RX2/TX2 to allow chaining). The USB-C DMX cables aren't available at the time of writing this from Aputure, so I built several (thanks for YouTube Larry for the breakdown). Keep in mind that RS485-A is generally the non-inverted signal, and RS485-B is the inverted signal - also be sure to connect ground.


To complete the test setup, I have a USB DMX converter cable which terminates in a 3-pin XLR style pinout. I connected a junction which adapted the 3-pin connector to a USB-C breakout board and tested to ensure I was getting the right ground, signal, and inverted signal using an oscilloscope, then I connected the Amaran light. 

Now it was time to send some DMX data to the light to test the wired connection. Having tried Freestyler and not exactly loving it, I tried QLC+ this time around. The light's intensity was able to be controlled over channel 1 (see T2c/T4c DMX Weirdness below for more on this). 

Unreal Art-Net

To use DMX in Unreal, you need to install some plug-ins. The full setup would be to lengthy for this post, so I am going to start with the assumption that you have data set-up to Universe 1, Channel 1 (i.e. Pixel Mapping, DMX Library Fixtures, etc.). To make sure Unreal is sending DMX over Art-Net, go to Project Setting and search for DMX. Make sure to set the Protocol Name to Art-Net and choose the correct Network Interface Card IP Address (this could be the loopback address or the loopback over the assigned machine IP [in my case:] or whatever address your QLC+ is running on).

QLC+ Set-up

Because Unreal only supports DMX over Art-net and sACN, it will not connect directly to the USB DMX cable. To solve this problem, QLC+ comes with a mapping utility that lets you specify and input (i.e. Art-Net) and an output (USB-DMX). Here is how I set this up in QLC+. 

On the Inputs/Outputs tab at the bottom, go to the panel on the right-side called Mapping. Find the ArtNet Device with the IP associated with your Unreal instance (or loopback address on same machine) and check the box for Input. Now check the Output box for you USB-DMX device.

Select the row for Art-Net again and look for the Screw-driver/Wrench icon under the Mapping panel.  Click that button.

In the window that comes up, be sure to select the Art-Net universe associated with your Unreal Instance, then click OK.

Last, you have to enable the Universe in QLC+ to be a passthrough Universe. You do this by checking the Passthrough checkbox at the top of the Universe list on the left side of the screen (with the configured Universe selected).

In my case, the Art-Net plugin came with QLC+, but if yours does not, you may need to find and install it separately. 

Now, choose the Simple Desk tab at the bottom of the screen in QLC+, you should see the sliders adjust automatically to the channel values from from Unreal. If the slider is red, click the X button below it to allow it to show the values received from Unreal. Oddly, the slider being red does not override the values being passed through - it just will not show you them in this screen.

T2c/T4c DMX Weirdness

Aputure released a document a June 2022, which has DMX specs broken down. Unfortunately, my personal experience showed this document to be less than helpful. For starters, it does not define how you set modes on the light which in turn will define how the channel values will affect the light (i.e. mode, color, etc.). I've reached out to Aputure (who has been very helpful in the past) to get clarification on how to properly set this up and they have offered to assist. I'll update this post with more information as it and my time becomes available :)

Update: After working with Aputure support, they determined that the problem was in using an iOS phone to update the firmware for the lights. Switching to an Android and using the Sidus Link app, I was prompted to install the latest firmware which included capabilities for setting DMX profiles which better match up with their documentation, but not quite. Fortunately, you can kind of decipher which each mode and the channels they use from the menu. You may have to reach out though if you find there is not enough information.