How to initialize your KiCAD 8 project on the command line

TL;DR:

Inside the directory where you want to create the project, run

wget -qO- https://raw.githubusercontent.com/ulikoehler/KiCAD-ProcessAutomation/master/InitializeKiCad8Project.sh | bash /dev/stdin MyProject

You should replace MyProject (at the end of the command) with your project name.

Note: This will initialize an empty KiCAD project without any libraries. This is equivalent to creating a new project in KiCAD itself (using the GUI).

Continue reading →

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

How to fix pyspice OSError: cannot load library ‘libngspice.so’

Problem:

When trying to run a PySpice program, you see an error message such as

OSError: cannot load library 'libngspice.so': libngspice.so: cannot open shared object file: No such file or directory.  Additionally, ctypes.util.find_library() did not manage to locate a library called 'libngspice.so'

Solution:

Install libngspice, often called libngspice0.

On Ubuntu, install it using

sudo apt -y install libngspice0-dev

You need to install the -dev library since libngspice0 only contains libngspice.so.0 whereas the -dev library contains libngspice.so which is required by pyspice.

Posted by Uli Köhler in Python, SPICE

STM32 HAL PlatformIO LED blink example

In the autogenerated main.c, use the following while() loop:

/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
  /* USER CODE END WHILE */

  /* USER CODE BEGIN 3 */
  HAL_GPIO_WritePin(LD1_GPIO_Port, LD1_Pin, GPIO_PIN_SET);
  HAL_Delay(1000);
  HAL_GPIO_WritePin(LD1_GPIO_Port, LD1_Pin, GPIO_PIN_RESET);
  HAL_Delay(1000);
}
/* USER CODE END 3 */

On STM32H7 Nucleo boards, this will toggle the green LED.

Posted by Uli Köhler in C/C++, PlatformIO, STM32

How to fix Nextcloud docker container permissions

docker-compose exec nextcloud chown -vR www-data:www-data /var/www/html

 

Posted by Uli Köhler in Nextcloud

What are the cheapest general purpose SMD diodes?

Typically some 1N4001…1N4007 in SOD-123 or SOD-123FL package is the cheapest available diode. It is available from many manufacturers and at all distributors.

The typical rating is:

  • 1A forward current
  • 1000V reverse voltage
  • Instantaneous forward voltage of <=1V @1A

On LCSC, a full reel (3000pcs) of SOD4007-MS by MSKSemi costs just 6,60€

Posted by Uli Köhler in Components

What cheap general purpose MOSFET to use?

The 2N7002 or 2N7002K MOSFET is one of the best MOSFETs to use if you just want to have a general purpose switching FET.

  • 60Vds
  • 300mA
  • 1.9Ohm RDSon

It or its variants is available from many manufacturers and at all distributors.

On LCSC, for example, one reel of 2N7002 from chinese manufacturer HL, only costs 15.90€, that is 0,0053€/pc

Posted by Uli Köhler in Components, Electronics

JST VH contact picture

JST SVH-21T-P1.1 contact, for inventory management etc.

This picture is my own work and hereby released under CC0-1.0-Universal.

Posted by Uli Köhler in Electronics

How to set pandoc PDF page border on the command line

Add these command line options:

-V geometry:margin=20mm

-V is short-form for --variable

This will configure the default LaTeX template to use

\usepackage[margin=20mm]{geometry}
Posted by Uli Köhler in LaTeX

How to fix apt-update NO_PUBKEY E88979FB9B30ACF2

sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys E88979FB9B30ACF2

 

Posted by Uli Köhler in Linux

Angular: How to inject child component class by ID via ViewChild

<app-my-component #myId></app-dynamic-plot>
@ViewChild('myid', {read: MyComponent}) myComponent!: MyComponent;

 

Posted by Uli Köhler in Angular

How to fix Hugo access denied: “asciidoctor” is not whitelisted in policy “security.exec.allow”; the current security configuration is:

Problem:

When compiling your Hugo page, you see an error message such as

ERROR render of "section" failed: "/home/uli/klc/themes/hugo-theme-techdoc/layouts/_default/list.html:3:4": execute of template failed: template: _default/list.html:3:4: executing "main" at <.Content>: error calling Content: "/home/uli/klc/content/footprint/F2/_index.adoc:1:1": access denied: "asciidoctor" is not whitelisted in policy "security.exec.allow"; the current security configuration is:

Solution:

You need to edit your Hugo configuration file and add asciidoctor or whatever program caused the error, to the list of allowed programs to execute.

For TOML config files, add the following section which consists of the default value plus asciidoctor

[security]
    [security.exec]
    allow = ['^(dart-)?sass(-embedded)?$', '^go$', '^npx$', '^postcss$', '^asciidoctor$']

After that, recompile your Hugo page.

Posted by Uli Köhler in Python

How to fix Python cache3 ImportError: cannot import name ‘SafeCache’ from ‘cache3’

Problem:

You want to use cache3‘s SafeCache as shown in the Quickstart

from cache3 import SafeCache
cache = SafeCache()

but you instead see the following error message:

ImportError: cannot import name 'SafeCache' from 'cache3' (/usr/local/lib/python3.10/dist-packages/cache3/__init__.py)

Solution:

cache3 has been updated, but the documentation still has not been fixed. This is a known bug.

The closest equivalent is Cache() with thread_safe=True, an in-memory cache which supports tagging:

from cache3 import Cache
cache = Cache(name="mycache", thread_safe=True)

In case you don’t need tagging,  consider MiniCache:

from cache3 import MiniCache
cache = MiniCache(name="mycache", thread_safe=True)

 

Posted by Uli Köhler in Python

How to fix PySpice WARNING – Unsupported Ngspice version 36

Problem:

When you try to run your PySpice script, you see an error log such as

PySpice.Spice.NgSpice.Shared.NgSpiceShared._send_char - WARNING - spinit was not found
PySpice.Spice.NgSpice.Shared.NgSpiceShared._send_char - ERROR - Note: can't find init file.
PySpice.Spice.NgSpice.Shared.NgSpiceShared._init_ngspice - WARNING - Unsupported Ngspice version 36

Solution:

Your PySpice is too new for the ngspice version installed on your system.

Typically, it’s easiest to install a slightly older PySpice version:

sudo pip3 install -U "pyspice<1.5"

(but you can also update your ngspice).

Posted by Uli Köhler in Electronics, Python

How to install pip on Docker container without ensurepip

python3 -c "import urllib.request; urllib.request.urlretrieve('https://bootstrap.pypa.io/get-pip.py', 'get-pip.py')"
python3 get-pip.py --break-system-packages

 

Posted by Uli Köhler in Docker, Python

KiKit V-Cut panelization script template

#!/bin/sh
export DIRECTORY=panel
export PROJNAME=MyProject
mkdir -p $DIRECTORY
kikit panelize \
    --layout 'grid; rows: 4; cols: 2' \
    --tabs 'full' \
    --cuts 'vcuts ; layer: Edge.Cuts ; clearance: 0.4mm' \
    --post 'millradius: 2mm' \
    ${PROJNAME}.kicad_pcb ${DIRECTORY}/${PROJNAME}.kicad_pcb

Posted by Uli Köhler in KiCAD

KiKit breakaway tab panelization script template

#!/bin/sh
export DIRECTORY=panel
export PROJNAME=MyPCB
mkdir -p $DIRECTORY
kikit panelize \
    --layout 'grid; rows: 4; cols: 2; space: 2mm' \
    --tabs 'fixed; width: 5mm' \
    --cuts 'mousebites; drill: 0.5mm; spacing: 0.8mm; offset: -0.2mm' \
    --post 'millradius: 1mm' \
    ${PROJNAME}.kicad_pcb ${DIRECTORY}/${PROJNAME}.kicad_pcb

Posted by Uli Köhler in KiCAD

How to compute MOSFET gate charge loss power using Python

You can use the UliEngineering library to compute the power lost to charging a particular MOSFET to a particular gate voltage a given number of times a second:

from UliEngineering.Electronics.MOSFET import mosfet_gate_charge_losses
from UliEngineering.EngineerIO import auto_format

auto_format(mosfet_gate_charge_losses, "31nC", "9V", "1MHz")
# Prints '279 mW'

 

Posted by Uli Köhler in Python

How many MCPWM peripherals does the ESP32-S2 have?

The ESP32-S2 has no MCPWM (Motor control PWM) periperal.

However, the related ESP32-S3 features two MCPWM peripherals.

Source: Datasheet

Posted by Uli Köhler in ESP8266/ESP32

CadQuery example: Latching pin

import cadquery as cq
import math

# Set parameters
n = 2 # Number of pins
P = 3.96 # mm pin pitch
C1 = 6.8 # mm Height of bottom plate
H1 = 9.4 # mm Height of latching plate
O1 = 2 # mm Vertical offset pin-center to bottom plate border
D1 = 3.2 # mm Total depth of bottom plate
Pw = 1.14 # mm Width & height of square pin
D2 = 1.3 # mm (Measured) depth of latching plate (narrowest section)
Wx1 = 1.0 # mm (Measured) Width of the topmost part of the latching plate
Hx1 = 0.5 # mm (Measured) Height of the latching surface facing away from the pins
alpha = 90 # ° Angle of the latching surface. Shown by the datasheet as ~45°but real parts have 90°
beta = 15 # ° (Estimated) Latching plate tapering angle
WL1 = 1.27 # mm (Measured) With of the section of the bottom plate where there is no latching plate per side)
Dlatch = 1.75 # mm (Measured) Total depth of latching plate
delta = 70 # ° (Estimated) Taper angle of the pin top & bottoms
FilletRadiusBaseplate = 0.4 # mm

# Compute derived variables
A1 = ( n - 1 ) * P # Total width of all pins (center of last pin distance to center of first pin)
B1 = A1 + ( 1.95 * 2 ) # Width of bottom plate
LLatch = B1 - ( WL1 * 2 ) # Length of the latching plate
LPinTop = 7.7 + D1 # Length of the pin measured from the bottom plane to the top of the pin (away from PCB)
LPinBottom = 14.6 - LPinTop # Length of the pin in bottom direction, measured from the bottom plane
Pin1XOffset = ( ( n - 1 ) * P ) / 2 # First pin X offset measured from the X axis

# Compute asymmetric chamfer with constant angle triangle lengths
# Note: Top-facing angle of the chamfering triangle is [beta]
opposing_side = (Dlatch - Wx1) / 2 # Compute so that remaining part of latch is Wx1 wide
adjacent_side = opposing_side * (1/math.tan(math.radians(beta)))

# Start just outside the bottom plate
xstart = C1/2
xend = xstart + Dlatch
h1MinusChamfer = H1 - adjacent_side
latchPlate = (cq.Workplane("YZ")
    .sketch()
    # From bottom to start of chamfer
    .segment((xstart, 0), (xstart, h1MinusChamfer))
    # Chamfer edge
    .segment((xstart + opposing_side, H1))
    # Top side of latch (straight line) (up to begin of other side chamfer)
    .segment((xend - opposing_side, H1))
    # Chamfer edge
    .segment((xend, h1MinusChamfer))
    # move down to begin of latching surface
    .segment((xend, h1MinusChamfer - Hx1))
    # Move inwards (-X) for latching surface. NOTE: we assume 90° angle here
    # NOTE: D2 is the depth of the latching plate below the latching surface
    .segment((xstart + D2, h1MinusChamfer - Hx1))
    # From latching surface inside to bottom
    .segment((xstart + D2, 0))
    .close()
    .assemble(tag="face")
    .finalize()
    .extrude(1.0)
)
latchPlate

 

Posted by Uli Köhler in CadQuery, Python

CadQuery: How to fix cq.Location() error: TypeError: Expected three floats, OCC gp_, or 3-tuple

Problem

You are trying to construct a cq.Location object using code like

cq.Location(1, 2, 3)

however when you run it, you see the following error message:

File ~\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\LocalCache\local-packages\Python39\site-packages\cadquery\occ_impl\geom.py:1011, in Location.__init__(self, *args)
   1008 else:
   1009     t, ax, angle = args
   1010     T.SetRotation(
-> 1011         gp_Ax1(Vector().toPnt(), Vector(ax).toDir()), angle * math.pi / 180.0
   1012     )
   1013     T.SetTranslationPart(Vector(t).wrapped)
   1015 self.wrapped = TopLoc_Location(T)

File ~\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\LocalCache\local-packages\Python39\site-packages\cadquery\occ_impl\geom.py:91, in Vector.__init__(self, *args)
     89         fV = gp_Vec(args[0])
     90     else:
---> 91         raise TypeError("Expected three floats, OCC gp_, or 3-tuple")
     92 elif len(args) == 0:
     93     fV = gp_Vec(0, 0, 0)

TypeError: Expected three floats, OCC gp_, or 3-tuple

Solution:

Don’t pass three separate parameters to cq.Location() – pass a tuple with three numbers by adding an additional set of braces:

cq.Location((1, 2, 3))

 

Posted by Uli Köhler in CadQuery, Python
This website uses cookies to improve your experience. We'll assume you're ok with this, but you can opt-out if you wish. Cookie settingsACCEPTPrivacy &amp; Cookies Policy