Uli Köhler

How to compute Buck/Boost/LDO output voltage by feedback resistors using Python

You can use the UliEngineering library in order to compute the output voltage of your voltage converter.

First, you need to know Vfb, the feedback voltage of your converter IC, which you need to read from the datasheet. For this example, we’ll use the AP3012‘s feedback voltage of 1.25V.

from UliEngineering.Electronics.VoltageDivider import feedback_actual_voltage
from UliEngineering.EngineerIO import auto_format


# Compute voltage
output_voltage = feedback_actual_voltage("220k", "12.1k", vfb="1.25V")
# output_voltage == 23.97727272727273

# ... or format and print it
auto_format(feedback_actual_voltage, "220k", "12.1k", vfb="1.25V") #  Prints "24.0V"

 

Posted by Uli Köhler in Electronics, Python

How to construct C++ chrono::time_point from a milliseconds-since-epoch timestamp

#include <chrono>

size_t myMillisecondsSinceEpochTimestamp = 1680978404374;
std::chrono::time_point<std::chrono::system_clock> myChronoTimestamp(
    std::chrono::milliseconds(myMillisecondsSinceEpochTimestamp)
);

 

Posted by Uli Köhler in C/C++

heatshrink compression library: How to compress data from a buffer

This is a starting point for how to compress data from a buffer using heatshrink and write the data into an output buffer:

Note that this has not been thoroughly tested, but at least it doesn’t crash 🙂

// TODO Your code goes here
const size_t outbuf_size = filesize + 128;
char* outbuf = new char[outbuf_size];
heatshrink_encoder* encoder = heatshrink_encoder_alloc(10, 4);
size_t tosink = filesize;
size_t output_size = 0;
while(tosink > 0) {
    size_t sunk = 0;
    auto err = heatshrink_encoder_sink(encoder, reinterpret_cast<uint8_t*>(buf), (size_t)filesize, &sunk);
    if(err != HSER_SINK_OK) {
        std::cerr << "Error sinking data" << std::endl;
        break;
    }
    if(sunk == 0) {
        std::cerr << "No data sunk" << std::endl;
        break;
    }
    // Check how much has been sunk & update tosink
    tosink -= sunk;
    // Poll for output
    size_t polled = 0;
    auto err2 = heatshrink_encoder_poll(encoder, reinterpret_cast<uint8_t*>(outbuf + output_size), outbuf_size - output_size, &polled);
    if(err2 == HSER_POLL_ERROR_NULL || err2 == HSER_POLL_ERROR_MISUSE) {
        std::cerr << "Error polling data" << std::endl;
        break;
    }
    output_size += polled;
}
// Input data finished
auto err3 = heatshrink_encoder_finish(encoder);
// Poll for final output
// Poll for output
size_t polled = 0;
auto err2 = heatshrink_encoder_poll(encoder, reinterpret_cast<uint8_t*>(outbuf + output_size), outbuf_size - output_size, &polled);
if(err2 == HSER_POLL_ERROR_NULL || err2 == HSER_POLL_ERROR_MISUSE) {
    std::cerr << "Error finally polling data" << std::endl;
}
output_size += polled;

cout << "Original size: " << filesize << ", compressed size: " << output_size << endl;

 

Posted by Uli Köhler in C/C++, Embedded

How to read C++ binary file into a buffer (C++17 way)

#include <iostream>
#include <fstream>
#include <filesystem>

// Get size of file to know how much memory to allocate
std::uintmax_t filesize = std::filesystem::file_size("C037B221110.bin");

// Allocate buffer to hold file
char* buf = new char[filesize];
// Read file
std::ifstream fin("C037B221110.bin", std::ios::binary);
fin.read(buf, filesize);
if(!fin) {
    std::cerr << "Error reading file, could only read " << fin.gcount() << " bytes" << std::endl;
}
// Close file
fin.close();

 

Posted by Uli Köhler in C/C++

How to include current directory using CMake

It is often helpful to include the current directory for C++ projects. When using GCC directly, this can be done using -I., whereas for CMake you need to use the following statement:

target_include_directories(myexe PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})

Remember to replace myexe by the name of your executable target.

Posted by Uli Köhler in CMake

How to get filesize in C++ using C++17’s std::filesystem

Recent versions of C++ have a built-in cross-platform filesystem library which supports many useful operations such as getting the filesize.

#include <filesystem>

// Usage example:
std::filesystem::file_size("myfile.bin");

Full example:

#include <filesystem>
#include <iostream>

int main() {
    std::uintmax_t filesize = std::filesystem::file_size("myfile.bin");
    std::cout << "Filesize in bytes is " << filesize << std::endl;
    return 0;
}

 

Posted by Uli Köhler in C/C++

How to disable telnet on RouterOS or CHR (Cloud Hosted Router)

When you have a fresh install of RouterOS or CHR (MikroTik Cloud Hosted Router), telnet access is enabled by default. Since you typically want to access the router using SSH, WinBox or WebFig instead of telnet, you can – and should – disable it entirely.

In order disable telnet, login to your router using SSH or WinBox and run the following command:

/ip/service/disable telnet

 

Posted by Uli Köhler in MikroTik, Networking

How to enable NTP client on RouterOS or CHR (Cloud Hosted Router)

When you have a fresh install of RouterOS or CHR (MikroTik Cloud Hosted Router), the NTP client is not enabled by default.

In order to enable it, login to your router using SSH or WinBox and run the following command:

/system/ntp/client/ set enabled=yes servers=de.pool.ntp.org

Depending on your location, you might want to choose a suitable pool of NTP servers.

Posted by Uli Köhler in MikroTik, Networking

How to use Let’s Encrypt certificate for HTTPS API service on MikroTik RouterOS or CHR (Cloud Hosted Router)

Once you’ve setup a Let’s Encrypt certificate on your MikroTik RouterOS or CHR router, you can configure the API service to use it.

Login to your router using ssh, e.g. ssh [email protected].

Now copy-and-paste the following:

/ip/service set api-ssl certificate=[/certificate find where name~"^letsencrypt.*"]

This has been tested only in the circumstance that one letsencrypt certificate exists. I will update this post once I get around to testing it with multiple (renewed) certificates.

Posted by Uli Köhler in MikroTik, Networking

How to enable Let’s Encrypt & HTTPS on MikroTik CHR (Cloud hosted router)

Once you have installed your MikroTik CHR router on your server, you don’t want to access the webinterface using the unencrypted HTTP protocol.

Instead, follow these steps to enable HTTPS using Let’s Encrypt certificates which come built-in with recent RouterOS versions.

First, configure your DNS to point some domain name – e.g. chr.mydomain.com to your server’s IP address. TCP port 80 on the IP address the domain name points to must reach the CHR server.

Then, login to the CHR using ssh. This connection is encrypted. Run the following commands:

/certificate/enable-ssl-certificate dns-name=chr.mydomain.com

and

/ip/service/enable www-ssl

Example output:

[admin@MikroTik] > /certificate/enable-ssl-certificate dns-name=chr.mydomain.com
  progress: [success] ssl certificate updated

[admin@MikroTik] > /ip/service/enable www-ssl

After that (if the certificate could be generated successfully), your router will be reachable via https://chr.mydomain.com

Posted by Uli Köhler in MikroTik, Networking

How to install pip (Python) on pfSense

Once you have installed python on your pfSense, you might notice that it is missing pip:

[2.6.0-RELEASE][[email protected]]/root: pip
pip: Command not found.

and also python3.8 -m pip doesn’t work:

[2.6.0-RELEASE][[email protected]]/root: python3.8 -m pip
/usr/local/bin/python3.8: No module named pip

Installing it is rather easy, however:

python3.8 -m ensurepip

After that, you can run pip using

python3 -m pip

 

Posted by Uli Köhler in Networking, Python

How to install python3 on pfSense

First, login to your pfSense as root using ssh.

Then use

pkg search python

to show which python versions are available. Output on pfSense 2.6.0:

frr7-pythontools-7.5.1_3       Provide configuration reload functionality for FRR
py38-gitpython-3.1.24          Python Git Library
python38-3.8.12_1              Interpreted object-oriented programming language

Now run e.g.

pkg install python38-3.8.12_1

On my pfSense, python3.8 was already installed.

Remember that in order to run python, you need to explicitly run python3.8, just running python or python3 won’t work!

Posted by Uli Köhler in Networking, Python

OpenPnP script to apply global rotation offset to board

This script applies a rotation offset such as -90° to every component in a OpenPNP .board.xml file.

#!/usr/bin/env python3
import sys
import argparse
import xml.etree.ElementTree as ET

def rotate_placements(board_file, rotation_offset):
    tree = ET.parse(board_file)
    root = tree.getroot()

    for placement in root.iter('placement'):
        location = placement.find('location')
        if location is not None:
            rotation = float(location.get('rotation', 0))
            new_rotation = (rotation + rotation_offset) % 360
            location.set('rotation', str(new_rotation))
            print(rotation, new_rotation)

    tree.write(board_file, encoding="utf-8", xml_declaration=True)

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="Rotate placements in an OpenPnP board.xml file")
    parser.add_argument("board_file", type=str, help="Path to the board.xml file")
    parser.add_argument("-r", "--rotation-offset", required=True, type=float, help="Rotation offset in degrees")

    args = parser.parse_args()

    rotate_placements(args.board_file, args.rotation_offset)

 

Posted by Uli Köhler in LumenPnP

How to fix Angular “ng build” not producing index.html

Unless you have errors in your build (which is clearly visible from looking at the ng build output), the reason why ng build doesn’t produce an index.html is that the resulting bundle exceeds the maximum allowed size.

This is evident from the output such as

Error: bundle initial exceeded maximum budget. Budget 1.00 MB was not met by 3.73 kB with a total of 1.00 MB.

In order to fix it, either shrink your application by removing unneeded features or libraries or splitting off certain features into extra modules or, at least temporarily, increase the allowable budget.

In order to do that, open angular.json and look for the "budgets": {... section:

"budgets": [
  {
    "type": "initial",
    "maximumWarning": "500kb",
    "maximumError": "1mb"
  },
  {
    "type": "anyComponentStyle",
    "maximumWarning": "2kb",
    "maximumError": "4kb"
  }
],

Increase the maximumError value for "type": "initial" (the first entry in the list shown above).

For example, you could increase it from 1mb to 4mb to fix your build.

After that, run your ng build command again and index.html should be generated.

Be aware, however, that having huge JS bundles can really slow down your web application especially for mobile users.

Posted by Uli Köhler in Angular

How to query USB device information using udev

You can use udevadm to query information such as the USB device path for a given USB device such as /dev/usbtmc0:

udevadm info -q all /dev/usbtmc0

Example output:

P: /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb1/1-1/1-1.3/1-1.3:1.0/usbmisc/usbtmc0
N: usbtmc0
L: 0
E: DEVPATH=/devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb1/1-1/1-1.3/1-1.3:1.0/usbmisc/usbtmc0
E: DEVNAME=/dev/usbtmc0
E: MAJOR=180
E: MINOR=176
E: SUBSYSTEM=usbmisc

 

Posted by Uli Köhler in Linux

Thorlabs PM100(D) USB-TMC udev rules

SUBSYSTEMS=="usb", ACTION=="add", ATTRS{idVendor}=="1313", ATTRS{idProduct}=="8078", GROUP="dialout", MODE="0666"

How to install:

sudo cp 99-thorlabs-pm100.rules /etc/udev/rules.d/
sudo udevadm control --reload-rules && sudo udevadm trigger

 

Posted by Uli Köhler in Linux

How to fix PyVISA ValueError: Please install PyUSB to use this resource type

Problem:

When trying to run a Python script using PyVISA with a USB instrument, you see the following error message:

ValueError: Please install PyUSB to use this resource type.
No module named 'usb'

Solution:

On Linux distributions such as Ubuntu, you can fix this using

sudo apt-get -y install python3-usb

This will install the Python3 usb package and the libusb system packages.

Posted by Uli Köhler in Python

What is the default IP address for the NETGEAR MS108EUP?

The default IP address for the Netgear MS108EUP PoE switch is 192.168.0.239.

Posted by Uli Köhler in Networking

What is the default password for the NETGEAR MS108EUP?

The default password for the Netgear MS108EUP PoE switch is password.

Posted by Uli Köhler in Networking

How to connect the INHibit/Enable input of the 74HC4051 analog multiplexer?

The 74HC4051 and its variants such as the CD74HC4051 have an input called INH or ~E depending on the manufacturer.

Typically you should hard-connect this pin to GND in order to always enable the multiplexer.

Whenever you want to disable the multiplexer (i.e. none of the inputs is connected to the output, connect this pin to Vcc temporarily.

 

Source: This NXP datasheet, section 7.

Posted by Uli Köhler in Components, Electronics