Electronics

How to fix KiBot ‘KiBoM not installed or too old’

Problem:

When running kibot-check, you see the following warning message:

* KiBoM not installed or too old
  Visit: https://github.com/INTI-CMNB/KiBoM
  Download it from: https://github.com/INTI-CMNB/KiBoM/releases
  - Mandatory for `kibom`

but even installing kibom using pip install kibom, the warning does not disappear.

Solution:

You need to install a specific fork of KiBom:

pip install git+https://github.com/INTI-CMNB/KiBoM

After that, the warning will disappear.

Posted by Uli Köhler in Electronics, KiCAD, Python

How to see PlatformIO actual commands during build or upload

Having a look at the actual commands being used by PlatformIO is pretty easy:

Instead of clicking Build or Upload, open the Advanced folder and select Verbose Build or Verbose Upload.

This will show you all raw commands such as esptool.py commands that are being run.

Posted by Uli Köhler in PlatformIO

How to fix /dev/ttyUSB0 or /dev/ttyACM0 permission error

Problem:

When trying to connect to a USB device, you see an error like

[Errno 13] Permission denied: '/dev/ttyUSB0'

and the USB connection can’t be established.

Solution:

On Debian & Ubuntu, the /dev/ttyUSBx and /dev/ttyACMx devices are owned by the dialout group. Therefore, the solution is to add your user to the dialout group:

sudo usermod -a -G dialout $USER

After that, you need to logout completely and login again (if in doubt, reboot your computer)!

While you can sometimes quickly solve this issue by running whatever command you want to use as root using sudo, this is not a recommended solution since it will allow the program you’re calling full access to the entire computer – not just access restricted to the USB device. Therefore, this approach poses a significant security risk and additionally, some programs don’t work properly when called using sudo.

Posted by Uli Köhler in Embedded, Linux

How to install ESP32 esptool / esptool.py on Ubuntu

The recommended way is to install the current version using pip since the version installed using apt might be out of date:

sudo pip install esptool

After that, you can use esptool.py – note that you need to call it as esptool.py, not just as esptool!

In case you are missing pip , install python3-dev using apt:

sudo apt -y install python3-pip

 

Posted by Uli Köhler in ESP8266/ESP32, Linux, Python

Which MikroTik switch can you use with 100M SFP modules?

Generally, 100M SFP modules can not be used with SFP+ ports. They sometimes can be used with SFP ports, however there is no guarantee it will work properly until you’ve actually tested the compatibility of the hardware!

Compatible devices

The MikroTik help page lists the CRS106-5S-1C as being compatible with both 100M and 1G SFP modules:

This unit is compatible with 100Mbit and 1.25G SFP modules

It has 5 SFP ports and 1 Combo SFP or GigE port.

Besides manually searching the MikroTik site for other compatible devices, I also used Google to search for similar sentences on the MikroTik site. I could not find any other MikroTik device for which any statement about 100Mbit SFP compatibility is being made.

Incompatible devices

For the following devices I have checked the respective MikroTik help page and it does not list compatibility with 100M SFP modules. This does not automatically mean they aren’t compatible but it’s much less likely. Possibly the help page will be updated in the future to indicate compatibility. I have not physically tested any of those devices with 100M transceivers.

  • CRS310-1G-5S-4S+IN
  • CRS112-8P-4S-IN
  • hEX S
  • CRS109-8G-1S-2HnD-IN
  • CRS212-1G-10S-1S+IN

Often, the help pages with read something like Compatible with 1.25G SFP modules. This means that standard 100Mbit SFP modules are incompatible.

Posted by Uli Köhler in Electronics, MikroTik, Networking

How to enable USB-C host mode on Raspberry Pi

If you want to connect an USB device such as a 3D printer mainboard to your Raspberry Pi 4 using the USB-C connector as opposed to the larger USB-A connector, you need to first configure the Raspberry Pi kernel to use host mode for the USB-C connector.

To temporarily enable it:

sudo modprobe -r dwc2 && sudo dtoverlay dwc2 dr_mode=host && sudo modprobe dwc2

This method has the advantage of not requiring a reboot.

To permanently enable it:

Edit /boot/config.txt and add

dtoverlay=dwc2,dr_mode=host

at the end of the file (in the [all] section). Then

reboot

Posted by Uli Köhler in Raspberry Pi

How to flash Marlin 2.x to BTT SKR 1.4 using PlatformIO

The best way to flash Marlin via PlatformIO onto the LPC1768 MCU on a BTT SKR v1.4 board is to insert an SD card into it, connect the computer via USB and use the mbed as upload_protocol.

In order to do this, edit ini/lpc176x.ini from within Visual Studio Code and add the following new code to [env:LPC1768]:

upload_protocol = mbed
upload_port=/media/uli/A87B-A154/

with upload_port being the directory where the SD card is mounted (while you can do this using an SD card reader, it is so much easier by just connecting the BTT SKR v1.4 via USB directly to your computer, allowing both serial port and SD card access at the same time).

Full example of the [env:LPC1768] section:

[env:LPC1768]
platform = ${common_LPC.platform}
extends  = common_LPC
board    = nxp_lpc1768
upload_protocol = mbed
upload_port=/media/uli/A87B-A154/

In the PlatformIO menu, choose LPC1768/Upload. There is no special configuration for the BTT SKR v1.4 but of course you need to configure Configuration.h etc correctly – see https://www.makenprint.uk/3d-printing/3d-printing-guides/skr-v1-4-configuration-h-marlin-2-setup-part-2/

After uploading, press the reset button on the Board to apply the firmware update. You can use picocom to connect to your printer, see How to connect to your 3D printer using picocom, e.g.:

picocom -b 115200 /dev/ttyACM0 --imap lfcrlf --ech

Enter M115 to check if you have correctly updated the fiwa

You might need to manually re-mount the SD card using your file manager after a firmware update in order to enabled PlaformIO doing another update.

Posted by Uli Köhler in 3D printing, Embedded, PlatformIO

How to install tailscale on Ubuntu

In order to instal tailscale, on any Ubuntu version, you can use the official tailscale install command:

sudo apt -y install curl apt-transport-https
curl -fsSL https://tailscale.com/install.sh | sh
Posted by Uli Köhler in Headscale, Raspberry Pi, VPN

Fullscreen camera view using libcamera-vid

libcamera-vid --width 1920 --height 1080 -f -t 10000000000

-t 10000000000 means to run for 10000000000 milliseconds (almost 4 months)

Posted by Uli Köhler in Audio/Video, Electronics, Raspberry Pi

How to fix raspistill ERROR: the system should be configured for the legacy camera stack

Problem:

While trying to capture an image using raspistill, you see the following error message

ERROR: the system should be configured for the legacy camera stack

and no image is being produced

Solution 1 (recommended): Use libcamera

Recent versions of Raspbian use libcamera instead of the broadcom legacy camera API. You can capture an image using libcamera-still similarly to raspistill:

libcamera-still -o test.jpg

Solution 2: Enable legacy camera API

If you absolutely need raspistill specifically to work, you can still enable the legacy camera API using rpi-config:

sudo raspi-config

Go to:

  • 3 Interface Config
  • I1 Legacy Camera

and choose Yes to enable the legacy camera API.

Posted by Uli Köhler in Audio/Video, Raspberry Pi

Raspberry Pi libcamera VLC livestreaming (1920×1080)

On the Pi, run

libcamera-vid -t 0 --width 1920 --height 1080 --codec h264 --inline --listen -o tcp://0.0.0.0:8888

On the client, run

vlc tcp/h264://192.168.1.185:8888/

where 192.168.1.185 is the IP address of the Raspberry Pi.

Posted by Uli Köhler in Audio/Video, Raspberry Pi

How to DC-sweep resistive voltage divider using PySpice

The following code simulates a resistive 10kΩ / 1kΩ voltage divider using PySpice using a DC sweep and can serve as a suitable starting point for simulating simple circuits. We sweep from 0V to 5V in steps of 10mV.

Also see our previous post How to simulate resistive voltage divider using PySpice for an alternate version using transient analysis:

import PySpice.Logging.Logging as Logging
logger = Logging.setup_logging()

from PySpice.Probe.Plot import plot
from PySpice.Spice.Netlist import Circuit
from PySpice.Unit import *

circuit = Circuit("MyCircuit")
# Create voltage source: 5V DC
source = circuit.VoltageSource('in', 'in', circuit.gnd, [email protected]_V)
# Create resistor divider
r1 = circuit.R('R1', 'in', 'n1', [email protected]_kΩ)
r2 = circuit.R('R2', 'n1', circuit.gnd, [email protected]_kΩ)
# Simulate for 1 second with steps of 1 millisecond
simulator = circuit.simulator(temperature=25, nominal_temperature=25)
analysis = simulator.dc(Vin=slice(0, 5.0, 0.01))

You can access the array of output voltages of the divider (i.e. node n1) using analysis['n1']Keep in mind that if the first argument of circuit.VoltageSource is 'in', the argument to simulator.dc will be valled Vin,  not just  in! A Vwill automatically be  prepended!

 

This is the code we used to plot this:

import matplotlib.ticker as mtick
import matplotlib.pyplot as plt
from UliEngineering.EngineerIO import format_value

def format_volts(value, pos=None):
    return format_value(value, 'V')

plt.style.use("ggplot")
plt.xlabel("Input voltage")
plt.xlabel("Divider output voltage")
plt.gca().yaxis.set_major_formatter(mtick.FuncFormatter(format_volts))
plt.gca().xaxis.set_major_formatter(mtick.FuncFormatter(format_volts))
plt.gcf().set_size_inches(8,5)
plt.plot(analysis["in"], analysis["n1"], label="Input voltage")
plt.savefig("/ram/PySpice-Voltage-Divider-Sweep.svg")
Posted by Uli Köhler in Electronics, Python, SPICE

How to simulate resistive voltage divider using PySpice

The following code simulates a resistive 10kΩ / 1kΩ voltage divider using PySpice and can serve as a good starting point for simulating simple circuits.

This post shows you how to simulate the voltage divider using transient analysis. Also see an alternative variant of this post using DC sweep analysis instead: How to DC-sweep resistive voltage divider using PySpice

import PySpice.Logging.Logging as Logging
logger = Logging.setup_logging()

from PySpice.Probe.Plot import plot
from PySpice.Spice.Netlist import Circuit
from PySpice.Unit import *

circuit = Circuit("MyCircuit")
# Create voltage source: 5V DC
source = circuit.VoltageSource('V1', 'in', circuit.gnd, [email protected]_V)
# Create resistor divider
r1 = circuit.R('R1', 'in', 'n1', [email protected]_kΩ)
r2 = circuit.R('R2', 'n1', circuit.gnd, [email protected]_kΩ)
# Simulate for 1 second with steps of 1 millisecond
simulator = circuit.simulator(temperature=25, nominal_temperature=25)
analysis = simulator.transient([email protected]_ms, [email protected]_s)

You can access the array of output voltages of the divider (i.e. node n1) using analysis['n1']:

This is the code we used to plot this:

import matplotlib.ticker as mtick
import matplotlib.pyplot as plt
from UliEngineering.EngineerIO import format_value

def format_volts(value, pos=None):
    return format_value(value, 'V')

plt.style.use("ggplot")
plt.xlabel("Time [ms]")
plt.ylim([0.0, 5.5])
plt.gca().yaxis.set_major_formatter(mtick.FuncFormatter(format_volts))
plt.gcf().set_size_inches(8,5)
plt.plot(analysis["in"], label="Input voltage")
plt.plot(analysis["n1"], label="Voltage divider output")
plt.gca().legend()
plt.savefig("/ram/PySpice-Voltage-Divider.svg")

 

Posted by Uli Köhler in Electronics, Python, SPICE

How to create resistor in PySpice: Minimal example

This creates a resistor named R1 which has its + pin connected to node n1 and its - pin connected to GND. The value of the resistor is set to 1kΩ.

r1 = circuit.R('R1', 'n1', circuit.gnd, [email protected]_kΩ)

Full example:

import PySpice.Logging.Logging as Logging
logger = Logging.setup_logging()

from PySpice.Probe.Plot import plot
from PySpice.Spice.Netlist import Circuit
from PySpice.Unit import *

circuit = Circuit("MyCircuit")
r1 = circuit.R('R1', 'n1', circuit.gnd, [email protected]_kΩ)

 

Posted by Uli Köhler in Electronics, Python, SPICE

How to create constant voltage source in PySpice

This creates a voltage source named V1 which has its + pin connected to node n1 and its - pin connected to GND. The voltage source is set to 5V DC.

source = circuit.VoltageSource('V1', 'n1', circuit.gnd, [email protected]_V)

Full example:

import PySpice.Logging.Logging as Logging
logger = Logging.setup_logging()

from PySpice.Probe.Plot import plot
from PySpice.Spice.Netlist import Circuit
from PySpice.Unit import *

circuit = Circuit("MyCircuit")
source = circuit.VoltageSource('V1', 'n1', circuit.gnd, [email protected]_V)

 

Posted by Uli Köhler in Electronics, Python, SPICE

Simple OpAmp selectable gain amplifier: Select gain 1x or 10x via GPIO

Download KiCAD 6.x Selectable gain amplifier schematic SGA.kicad_sch

This circuit is a simple variant of a selectable gain amplifier.

If CTRL is pulled low (i.e. to GND), effectively the circuit will look like this:

Due to negligible input bias current for JFET opamps like the TL084 (i.e. most modern opamps below 100 MHz GBW), this circuit is basically just a Gain 1 buffer.

If CTRL is pulled high (i.e. pulled to 5V for example), the circuit effectively looks like this:


which has a gain of (\frac{10 k\Omega}{10 k\Omega + 90 k\Omega} = \frac{10 k\Omega}{100 k\Omega} = 10. Adjust these

One aspect to consider here is the RDSon of the MOSFET Q1. This is added to R1 and introduces a gain error to the system. The BSS123, for example, has a relatively high RDSon of up to 10 Ohms at VGS = 4.5V. For R1 = 10kOhm, the effective worst-case gain is:

\frac{10 k\Omega + 10 \Omega}{10 k\Omega + 10 \Omega + 90 k\Omega} = \frac{10 k\Omega}{100 k\Omega} = 10.001  or 0.01%. For most applications this does not matter since other aspects like the resistnance tolerance or resistance coefficient of temperature will affect the system error orders of magnitude This gain error will vary with temperature since the RDSon is temperature-sensitive and often the variation will be a larger issue than the gain error itself.

One way to mitigate is to choose large values for R1 and R2. Choosing R1=100kOhm and R2=900kOhm in this example will reduce both the gain error and the gain error temperature coefficient from the RDSon of Q1 by an order of magnitude. I recommend not to choose resistors larger than 1 MOhm without taking further consideration of opamp bias current, bias current temperatur drift etc, since those start to get relevant even for JFET input opamps when exceeding a couple of Megaohms.

Note that the RDSon of the MOSFET will be worse for VGS=3.3V will be worse and some MOSFETs will not switch on properly at this voltage. Choose a MOSFET that fits both your logic voltage and the RDSon i.e. gain error requirements. I often start with the BSS138 since I have many of those in stock, which tends to have less than 1 Ohm resistance in most practical conditions.

Another consideration for this circuit is that the MOSFET body diode will conduct if the voltage at the inverting input of the opamp will go beyond the Vf of the MOSFET body diode (typically you should use 0.7V here even if the specified body diode voltage is slightly higher, in order to have sufficient headroom). In effect, this typically means that you should not use this circuit without modification when using bipolar supplies and signals that go more negative than GND.

Posted by Uli Köhler in Analog, Electronics

How to check only a single schematic symbol against KLC (KiCAD library conventions)

In our previous post How to check KiCAD symbol library against KLC (KiCAD library conventions) we showed how to use check_symbol.py to check a symbol library against the KiCAD library guidelines.

You can also use it to check only a specific symbol in that library by name, which removes most of the clutter from the output. Use -c "CD4066B" to just check the component named CD4066B.

~/kicad-library-utils/klc-check/check_symbol.py MyLibrary.kicad_sym -vv -c "CD4066B"

This will print, for example:

Checking symbol 'Analog_Switch:CD4066B':
  Violating S3.1
    Origin is centered on the middle of the symbol
    Symbol unit 3 slightly off-center
     -   Center calculated @ (-25, -25)
    Symbol unit 4 slightly off-center
     -   Center calculated @ (-25, -25)
    Symbol unit 5 not centered on origin
     - Center calculated @ (-100, 0)
  Violating S4.1
    General pin requirements
    Pins not located on 100mil (=2.54mm) grid:
     - Pin C (6) @ (-400,50) 
     - Pin C2 (9) @ (350,-100) 
     - Pin D2 (10) @ (350,-100) 
     - Pin D (12) @ (-400,50) 
  Violating S5.2
    Footprint filters should match all appropriate footprints
    No footprint filters defined

 

Posted by Uli Köhler in Electronics, KiCAD

How to check KiCAD symbol library against KLC (KiCAD library conventions)

First, clone kicad-library-utils using

git clone https://gitlab.com/kicad/libraries/kicad-library-utils.git

Then, run the check script against your library using

~/kicad-library-utils/klc-check/check_symbol.py MyLibrary.kicad_sym -vv

You might need to adjust the path to kicad-library-utils accordingly.

This will provide colored output on the command line such as

Checking symbol 'Analog_Switch:FSA3157L6X':
Checking symbol 'Analog_Switch:NC7SB3157P6X':
  Violating S3.1
    Origin is centered on the middle of the symbol
    Symbol unit 1 not centered on origin
     - Center calculated @ (0, -112)
  Violating S3.6
    Pin name position offset
    Pin offset outside allowed range
     - Pin offset (5) should not be below 20mils

 

Posted by Uli Köhler in Electronics, KiCAD