initial escape from OBSIDIAN

This commit is contained in:
Robin P. Clark 2026-05-07 16:50:14 +01:00
commit a0408e896a
87 changed files with 3487 additions and 0 deletions

0
ADCs.md Normal file
View File

19
Angular Momentum.md Normal file
View File

@ -0,0 +1,19 @@
For a point rotating around an origin:
![[angular_momentum.jpg]]
In the diagram the p vector is the momentum, i.e. the velocity times the mass.
## Moment of inertia $I$ is rotational mass
$$I = \sum mr^2$$It measures how strongly an object resists changes in its rotation
* Large $I$ → harder to start, stop, or alter rotation
- Small $I$ → easier to change rotation
It depends on **mass distribution**, not just mass:
Mass farther from the axis increases $I$ greatly.
**Gyroscope connection:**
$$L=I\omega$$
Bigger $I$ → larger angular momentum at the same spin rate → harder to tilt or redirect.
Can be thought of as: moment of inertia helps determine how “stubborn” a spinning object feels.
---

1
Biology.md Normal file
View File

@ -0,0 +1 @@
[[Human Biology]]

View File

@ -0,0 +1 @@
![[transistors.jpg]]

7
ButterworthLowPass.md Normal file
View File

@ -0,0 +1,7 @@
![[Screenshot from 2026-02-18 13-17-53.png]]
See Ti Datasheet [[ti_SBOA226]] usng this the following python code can be used to configure the values for a given $f_c$ cut off frequency.
[[Code for Butterworth Low Pass Design]]

27
Cartesian coordinates.md Normal file
View File

@ -0,0 +1,27 @@
# Cartesian Coordinate System
**A two-dimensional coordinate system in which every point is uniquely identified by a pair of signed distances to a pair of perpendicular lines.**
![[CartesianCoordinateSystem.svg]]
_A Cartesian coordinate plane_
The **Cartesian coordinate system** is a two-dimensional coordinate system that uniquely identifies each point in two-dimensional Euclidean space using an _ordered pair of signed distances_ to an ordered pair of fixed perpendicular lines known as the _axes_.
The intersection of the two axes is known as the _origin_ and is defined as .
## Higher dimensions
The Cartesian coordinate system can be generalised to _any_ -dimensional Euclidean space.
In an -dimensional Euclidean space, points are specified with an ordered set of _signed distances_ to an ordered set of fixed perpendicular _dimension hyperplanes_ instead.
![[CartesianCoordinateSystem3D.svg]]
_The Cartesian coordinate system in three dimensions with the - Cartesian coordinate plane embedded_
## Notation
In two-dimensional Cartesian coordinates, the horizontal and vertical axis are often denoted as the _-axis_ and the _-axis_, respectively. Extending into three dimensions, the third axis is often denoted the _-axis_.
The coordinates themselves are referred to, in order, as the , , and coordinates. The and coordinates may also be referred to as the _abscissa_ and the _ordinate_, respectively. Generic coordinates are thus notated as or .
The axes and coordinates may also be denoted using _subscripts_, as in , which is extendable to any -dimensions.

View File

@ -0,0 +1,198 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 240.86496 222.56749" style="enable-background:new 0 0 240.86496 222.56749;" xml:space="preserve">
<style type="text/css">
.st0{opacity:0.25;}
.st1{fill:none;stroke:#8FF4EC;stroke-miterlimit:10;}
.st2{fill:#2DE2E6;}
</style>
<g class="st0">
<g>
<g>
<line class="st1" x1="20.43248" y1="197.56749" x2="220.43248" y2="197.56749"/>
</g>
<g>
<line class="st1" x1="20.43248" y1="172.56749" x2="220.43248" y2="172.56749"/>
</g>
<g>
<line class="st1" x1="20.43248" y1="147.56749" x2="220.43248" y2="147.56749"/>
</g>
<g>
<line class="st1" x1="20.43248" y1="97.56748" x2="220.43248" y2="97.56748"/>
</g>
<g>
<line class="st1" x1="20.43248" y1="72.56748" x2="220.43248" y2="72.56748"/>
</g>
<g>
<line class="st1" x1="20.43248" y1="47.56749" x2="220.43248" y2="47.56749"/>
</g>
</g>
<g>
<g>
<line class="st1" x1="195.43248" y1="222.56749" x2="195.43248" y2="22.56749"/>
</g>
<g>
<line class="st1" x1="170.43248" y1="222.56749" x2="170.43248" y2="22.56749"/>
</g>
<g>
<line class="st1" x1="145.43248" y1="222.56749" x2="145.43248" y2="22.56749"/>
</g>
<g>
<line class="st1" x1="95.43248" y1="222.56749" x2="95.43248" y2="22.56749"/>
</g>
<g>
<line class="st1" x1="70.43248" y1="222.56749" x2="70.43248" y2="22.56749"/>
</g>
<g>
<line class="st1" x1="45.43248" y1="222.56749" x2="45.43248" y2="22.56749"/>
</g>
</g>
</g>
<g>
<line class="st1" x1="20.43248" y1="122.56748" x2="220.43248" y2="122.56748"/>
<line class="st1" x1="120.43248" y1="222.56749" x2="120.43248" y2="22.56749"/>
</g>
<g>
<path class="st2" d="M95.62669,130.76466c0.19695,0,0.40666,0,0.40666-0.2316c0-0.23343-0.20972-0.23343-0.40666-0.23343h-6.29131
c-0.19877,0-0.40848,0-0.40848,0.23343c0,0.2316,0.20971,0.2316,0.40848,0.2316H95.62669"/>
<path class="st2" d="M100.48468,125.99602c0-0.279,0-0.30088-0.26807-0.30088c-0.72031,0.74401-1.74333,0.74401-2.11534,0.74401
v0.35925c0.2316,0,0.91726,0,1.52268-0.30089v6.02325c0,0.41942-0.03465,0.55801-1.08137,0.55801h-0.37201v0.36107
c0.40665-0.03465,1.41873-0.03465,1.88374-0.03465s1.47713,0,1.88374,0.03465v-0.36107h-0.37195
c-1.04678,0-1.08144-0.12764-1.08144-0.55801V125.99602"/>
</g>
<g>
<path class="st2" d="M70.16927,130.76466c0.19688,0,0.40661,0,0.40661-0.2316c0-0.23343-0.20972-0.23343-0.40661-0.23343h-6.29128
c-0.19875,0-0.40848,0-0.40848,0.23343c0,0.2316,0.20972,0.2316,0.40848,0.2316H70.16927"/>
<path class="st2" d="M73.65269,132.54446l1.23279-1.19809c1.81447-1.60474,2.51099-2.23204,2.51099-3.39548
c0-1.32573-1.04665-2.25575-2.46547-2.25575c-1.31297,0-2.17369,1.06861-2.17369,2.1044c0,0.65102,0.58179,0.65102,0.61646,0.65102
c0.19688,0,0.60361-0.13858,0.60361-0.61637c0-0.3027-0.20798-0.60542-0.61646-0.60542c-0.09302,0-0.11484,0-0.14951,0.01277
c0.26621-0.75679,0.89539-1.18715,1.57008-1.18715c1.05773,0,1.55736,0.94279,1.55736,1.89651
c0,0.93002-0.58167,1.84911-1.22182,2.56943l-2.23205,2.48917c-0.12768,0.12764-0.12768,0.15135-0.12768,0.43036h4.31459
l0.32457-2.02417h-0.2899c-0.05836,0.35013-0.1404,0.86073-0.25525,1.0358c-0.08216,0.093-0.84987,0.093-1.10511,0.093h-2.09351"/>
</g>
<g>
<path class="st2" d="M44.6806,130.63701c0.19689,0,0.40661,0,0.40661-0.2316c0-0.23341-0.20972-0.23341-0.40661-0.23341h-6.29129
c-0.19875,0-0.40848,0-0.40848,0.23341c0,0.2316,0.20972,0.2316,0.40848,0.2316H44.6806"/>
<g>
<path class="st2" d="M50.94209,129.21828c0.95374-0.31366,1.62844-1.12697,1.62844-2.04605
c0-0.95373-1.02306-1.60474-2.13903-1.60474c-1.17443,0-2.05885,0.69661-2.05885,1.58104
c0,0.38294,0.25536,0.60542,0.59265,0.60542c0.3611,0,0.59451-0.25712,0.59451-0.59449c0-0.5817-0.54713-0.5817-0.72219-0.5817
c0.3611-0.56895,1.1288-0.72031,1.54639-0.72031c0.4778,0,1.11795,0.25529,1.11795,1.30202
c0,0.14043-0.02381,0.81514-0.32644,1.32574c-0.34837,0.55801-0.74402,0.59448-1.03579,0.60542
c-0.09301,0.01094-0.37206,0.03465-0.45224,0.03465c-0.09302,0.01277-0.17507,0.0237-0.17507,0.14041
c0,0.12766,0.08205,0.12766,0.27894,0.12766h0.51246c0.95374,0,1.38405,0.7896,1.38405,1.92932
c0,1.58287-0.80237,1.92023-1.31472,1.92023c-0.49974,0-1.37319-0.19878-1.7798-0.88443
c0.40661,0.05835,0.76772-0.19695,0.76772-0.64008c0-0.4176-0.31371-0.65102-0.651-0.65102
c-0.27905,0-0.651,0.16229-0.651,0.67473c0,1.05766,1.08131,1.82539,2.34875,1.82539c1.4187,0,2.47632-1.05768,2.47632-2.24483
C52.88412,130.37077,52.15293,129.46263,50.94209,129.21828"/>
</g>
</g>
<path class="st2" d="M125.37234,1.84079c0.0889-0.30446,0.0889-0.34893,0.0889-0.49945c0-0.39342-0.30434-0.59182-0.63274-0.59182
c-0.21894,0-0.56793,0.1334-0.76301,0.4584c-0.04445,0.10947-0.21894,0.78683-0.30783,1.18022
c-0.15063,0.56447-0.30455,1.1563-0.43438,1.7447l-0.98196,3.92726c-0.08889,0.325-1.02618,1.85415-2.46637,1.85415
c-1.112,0-1.3513-0.96128-1.3513-1.76863c0-1.00234,0.36935-2.35362,1.11178-4.27619
c0.34899-0.89288,0.43788-1.13234,0.43788-1.57023c0-0.98182-0.69798-1.78916-1.78918-1.78916
c-2.07315,0-2.88039,3.16438-2.88039,3.35939c0,0.21894,0.21895,0.21894,0.25989,0.21894c0.21895,0,0.24303-0.04449,0.35249-0.39342
c0.58829-2.04916,1.46056-2.70598,2.203-2.70598c0.17448,0,0.54385,0,0.54385,0.70129c0,0.54394-0.21894,1.11183-0.36936,1.52576
c-0.87226,2.31257-1.26569,3.5578-1.26569,4.58067c0,1.9431,1.37518,2.59649,2.66145,2.59649c0.8519,0,1.59083-0.36946,2.203-0.9818
c-0.28376,1.13576-0.54736,2.2031-1.41962,3.35937c-0.56442,0.74235-1.39574,1.37522-2.39806,1.37522
c-0.30455,0-1.28629-0.065-1.65914-0.91682c0.34899,0,0.63274,0,0.93729-0.25999c0.21895-0.19841,0.43789-0.48236,0.43789-0.89629
c0-0.67392-0.58829-0.76288-0.80724-0.76288c-0.50291,0-1.22147,0.34895-1.22147,1.41971c0,1.08786,0.95787,1.89521,2.31268,1.89521
c2.24765,0,4.49508-1.98416,5.10396-4.45068L125.37234,1.84079"/>
<path class="st2" d="M236.65363,120.68082c0.13005-0.56787,0.63297-2.57597,2.15877-2.57597c0.10947,0,0.63274,0,1.0912,0.28394
c-0.60889,0.10947-1.04677,0.65682-1.04677,1.18022c0,0.34895,0.23953,0.76288,0.83133,0.76288
c0.47882,0,1.1768-0.39341,1.1768-1.26576c0-1.13576-1.28629-1.44022-2.0287-1.44022c-1.2657,0-2.02872,1.1563-2.2921,1.65916
c-0.54385-1.44022-1.72417-1.65916-2.3569-1.65916c-2.26823,0-3.51006,2.81545-3.51006,3.35939
c0,0.21894,0.21565,0.21894,0.26009,0.21894c0.1745,0,0.23953-0.04449,0.28397-0.23948
c0.74222-2.31257,2.18263-2.85992,2.92485-2.85992c0.41402,0,1.1768,0.19843,1.1768,1.46416
c0,0.67393-0.36935,2.1381-1.1768,5.19302c-0.349,1.35126-1.1153,2.26808-2.07317,2.26808c-0.12984,0-0.63274,0-1.0912-0.28392
c0.54385-0.10947,1.0264-0.56789,1.0264-1.17681c0-0.59184-0.48254-0.7663-0.80745-0.7663
c-0.65683,0-1.20068,0.56787-1.20068,1.26575c0,1.00577,1.0912,1.44022,2.04907,1.44022c1.4402,0,2.22708-1.52573,2.2921-1.65916
c0.26338,0.80735,1.04677,1.65916,2.3569,1.65916c2.24765,0,3.48949-2.81543,3.48949-3.35937
c0-0.21894-0.19507-0.21894-0.2601-0.21894c-0.19836,0-0.2393,0.08893-0.28375,0.23946
c-0.72185,2.33652-2.2032,2.85992-2.90097,2.85992c-0.8519,0-1.2009-0.69788-1.2009-1.44022
c0-0.47894,0.13007-0.96129,0.36958-1.91915L236.65363,120.68082"/>
<path class="st2" d="M145.89749,125.99602c0-0.279,0-0.30088-0.26807-0.30088c-0.72031,0.74401-1.74333,0.74401-2.11534,0.74401
v0.35925c0.2316,0,0.91727,0,1.52269-0.30089v6.02325c0,0.41942-0.03465,0.55801-1.08138,0.55801h-0.37201v0.36107
c0.40665-0.03465,1.41873-0.03465,1.88374-0.03465s1.47713,0,1.88374,0.03465v-0.36107h-0.37195
c-1.04678,0-1.08144-0.12764-1.08144-0.55801V125.99602"/>
<path class="st2" d="M169.00829,132.54446l1.23279-1.19809c1.81447-1.60474,2.51099-2.23204,2.51099-3.39548
c0-1.32573-1.04665-2.25575-2.46547-2.25575c-1.31296,0-2.17369,1.06861-2.17369,2.1044c0,0.65102,0.58179,0.65102,0.61646,0.65102
c0.19688,0,0.60362-0.13858,0.60362-0.61637c0-0.3027-0.20798-0.60542-0.61646-0.60542c-0.09302,0-0.11484,0-0.14951,0.01277
c0.2662-0.75679,0.89539-1.18715,1.57008-1.18715c1.05772,0,1.55734,0.94279,1.55734,1.89651
c0,0.93002-0.58167,1.84911-1.22182,2.56943l-2.23204,2.48917c-0.12769,0.12764-0.12769,0.15135-0.12769,0.43036h4.31459
l0.32457-2.02417h-0.2899c-0.05835,0.35013-0.1404,0.86073-0.25525,1.0358c-0.08215,0.093-0.84987,0.093-1.1051,0.093h-2.09352"/>
<g>
<path class="st2" d="M195.90298,129.21828c0.95375-0.31366,1.62843-1.12697,1.62843-2.04605
c0-0.95373-1.02306-1.60474-2.13902-1.60474c-1.17444,0-2.05885,0.69661-2.05885,1.58104
c0,0.38294,0.25536,0.60542,0.59264,0.60542c0.3611,0,0.59451-0.25712,0.59451-0.59449c0-0.5817-0.54712-0.5817-0.72218-0.5817
c0.3611-0.56895,1.1288-0.72031,1.54639-0.72031c0.4778,0,1.11795,0.25529,1.11795,1.30202
c0,0.14043-0.0238,0.81514-0.32643,1.32574c-0.34837,0.55801-0.74402,0.59448-1.0358,0.60542
c-0.093,0.01094-0.37206,0.03465-0.45224,0.03465c-0.09302,0.01277-0.17506,0.0237-0.17506,0.14041
c0,0.12766,0.08205,0.12766,0.27893,0.12766h0.51247c0.95375,0,1.38405,0.7896,1.38405,1.92932
c0,1.58287-0.80237,1.92023-1.31473,1.92023c-0.49974,0-1.37318-0.19878-1.7798-0.88443
c0.40662,0.05835,0.76772-0.19695,0.76772-0.64008c0-0.4176-0.31371-0.65102-0.651-0.65102c-0.27905,0-0.651,0.16229-0.651,0.67473
c0,1.05766,1.0813,1.82539,2.34875,1.82539c1.41872,0,2.47632-1.05768,2.47632-2.24483
C197.84502,130.37077,197.11385,129.46263,195.90298,129.21828"/>
</g>
<path class="st2" d="M113.89749,93.99602c0-0.279,0-0.30088-0.26807-0.30088c-0.72031,0.74401-1.74333,0.74401-2.11534,0.74401
v0.35925c0.2316,0,0.91726,0,1.52268-0.30089v6.02325c0,0.41941-0.03465,0.55801-1.08137,0.55801h-0.37201v0.36107
c0.40665-0.03465,1.41873-0.03465,1.88374-0.03465s1.47713,0,1.88374,0.03465v-0.36107h-0.37195
c-1.04678,0-1.08144-0.12765-1.08144-0.55801V93.99602"/>
<path class="st2" d="M112.00829,75.54446l1.23279-1.19807c1.81446-1.60474,2.51098-2.23206,2.51098-3.39549
c0-1.32573-1.04664-2.25575-2.46546-2.25575c-1.31297,0-2.1737,1.06861-2.1737,2.1044c0,0.65102,0.58179,0.65102,0.61646,0.65102
c0.19688,0,0.60361-0.1386,0.60361-0.61638c0-0.3027-0.20797-0.60542-0.61646-0.60542c-0.09301,0-0.11484,0-0.1495,0.01277
c0.26621-0.75679,0.89539-1.18715,1.57008-1.18715c1.05773,0,1.55736,0.94279,1.55736,1.89651
c0,0.93002-0.58168,1.84911-1.22182,2.56941l-2.23205,2.48917c-0.12768,0.12764-0.12768,0.15136-0.12768,0.43036h4.3146
l0.32456-2.02417h-0.2899c-0.05836,0.35013-0.1404,0.86073-0.25524,1.03579c-0.08216,0.093-0.84987,0.093-1.10511,0.093H112.00829"
/>
<g>
<path class="st2" d="M113.90299,47.21828c0.95374-0.31366,1.62843-1.12697,1.62843-2.04605
c0-0.95373-1.02306-1.60474-2.13904-1.60474c-1.17443,0-2.05885,0.69661-2.05885,1.58104
c0,0.38295,0.25536,0.60543,0.59264,0.60543c0.36109,0,0.59451-0.25712,0.59451-0.59449c0-0.58171-0.54713-0.58171-0.72219-0.58171
c0.3611-0.56895,1.1288-0.72031,1.54639-0.72031c0.47781,0,1.11795,0.2553,1.11795,1.30202
c0,0.14042-0.0238,0.81514-0.32644,1.32574c-0.34837,0.55802-0.74402,0.59449-1.03579,0.60543
c-0.09301,0.01094-0.37206,0.03465-0.45224,0.03465c-0.09302,0.01277-0.17506,0.0237-0.17506,0.14041
c0,0.12766,0.08205,0.12766,0.27894,0.12766h0.51247c0.95374,0,1.38404,0.7896,1.38404,1.92933
c0,1.58286-0.80237,1.92021-1.31472,1.92021c-0.49974,0-1.37319-0.19876-1.7798-0.88443
c0.40661,0.05835,0.76771-0.19695,0.76771-0.64008c0-0.41759-0.31371-0.65101-0.651-0.65101c-0.27905,0-0.651,0.1623-0.651,0.67473
c0,1.05767,1.08131,1.82539,2.34875,1.82539c1.41871,0,2.47632-1.05767,2.47632-2.24482
C115.84502,48.37077,115.11385,47.46263,113.90299,47.21828"/>
</g>
<g>
<path class="st2" d="M109.03951,148.76466c0.19695,0,0.40666,0,0.40666-0.2316c0-0.23343-0.20972-0.23343-0.40666-0.23343h-6.29131
c-0.19877,0-0.40848,0-0.40848,0.23343c0,0.2316,0.20971,0.2316,0.40848,0.2316H109.03951"/>
<path class="st2" d="M113.89749,143.99602c0-0.27901,0-0.30089-0.26807-0.30089c-0.72031,0.74402-1.74333,0.74402-2.11534,0.74402
v0.35924c0.2316,0,0.91726,0,1.52268-0.30087v6.02324c0,0.41942-0.03465,0.55801-1.08137,0.55801h-0.37201v0.36107
c0.40665-0.03465,1.41873-0.03465,1.88374-0.03465s1.47713,0,1.88374,0.03465v-0.36107h-0.37195
c-1.04678,0-1.08144-0.12764-1.08144-0.55801V143.99602"/>
</g>
<g>
<path class="st2" d="M108.12367,173.76466c0.19689,0,0.40662,0,0.40662-0.2316c0-0.23343-0.20972-0.23343-0.40662-0.23343h-6.29128
c-0.19875,0-0.40848,0-0.40848,0.23343c0,0.2316,0.20972,0.2316,0.40848,0.2316H108.12367"/>
<path class="st2" d="M111.6071,175.54446l1.23279-1.19809c1.81447-1.60474,2.51099-2.23204,2.51099-3.39549
c0-1.32571-1.04664-2.25575-2.46546-2.25575c-1.31297,0-2.1737,1.06862-2.1737,2.10442c0,0.651,0.58179,0.651,0.61646,0.651
c0.19688,0,0.60361-0.13858,0.60361-0.61636c0-0.3027-0.20797-0.60542-0.61646-0.60542c-0.09302,0-0.11484,0-0.14951,0.01276
c0.26622-0.75677,0.89539-1.18713,1.57008-1.18713c1.05772,0,1.55736,0.94278,1.55736,1.8965
c0,0.93004-0.58168,1.84911-1.22182,2.56943l-2.23205,2.48917c-0.12768,0.12764-0.12768,0.15135-0.12768,0.43036h4.31459
l0.32457-2.02417h-0.2899c-0.05836,0.35013-0.1404,0.86073-0.25524,1.0358c-0.08216,0.093-0.84987,0.093-1.10512,0.093H111.6071"/>
</g>
<g>
<path class="st2" d="M108.14737,198.63701c0.19688,0,0.40661,0,0.40661-0.2316c0-0.23341-0.20972-0.23341-0.40661-0.23341h-6.29129
c-0.19875,0-0.40848,0-0.40848,0.23341c0,0.2316,0.20972,0.2316,0.40848,0.2316H108.14737"/>
<g>
<path class="st2" d="M113.40884,197.21828c0.95374-0.31366,1.62843-1.12697,1.62843-2.04605
c0-0.95374-1.02306-1.60474-2.13903-1.60474c-1.17444,0-2.05885,0.69661-2.05885,1.58104
c0,0.38293,0.25536,0.60542,0.59264,0.60542c0.3611,0,0.59451-0.25713,0.59451-0.5945c0-0.58171-0.54713-0.58171-0.72218-0.58171
c0.36109-0.56895,1.1288-0.72031,1.54639-0.72031c0.4778,0,1.11794,0.25529,1.11794,1.30202
c0,0.14043-0.0238,0.81514-0.32643,1.32574c-0.34837,0.55801-0.74402,0.59448-1.03579,0.60542
c-0.09301,0.01094-0.37206,0.03465-0.45224,0.03465c-0.09302,0.01277-0.17506,0.0237-0.17506,0.14041
c0,0.12766,0.08205,0.12766,0.27893,0.12766h0.51247c0.95374,0,1.38405,0.7896,1.38405,1.92932
c0,1.58287-0.80237,1.92023-1.31473,1.92023c-0.49974,0-1.37318-0.19878-1.7798-0.88443
c0.40662,0.05835,0.76771-0.19695,0.76771-0.64008c0-0.4176-0.31371-0.65102-0.651-0.65102
c-0.27905,0-0.65099,0.16229-0.65099,0.67473c0,1.05766,1.08131,1.82539,2.34875,1.82539
c1.41871,0,2.47632-1.05768,2.47632-2.24483C115.35088,198.37077,114.6197,197.46263,113.40884,197.21828"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 14 KiB

View File

@ -0,0 +1,95 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 237.65593 219.883" style="enable-background:new 0 0 237.65593 219.883;" xml:space="preserve">
<style type="text/css">
.st0{opacity:0.25;}
.st1{fill:none;stroke:#8FF4EC;stroke-miterlimit:10;}
.st2{fill:none;stroke:#2DE2E6;stroke-miterlimit:10;}
.st3{fill:#2DE2E6;}
</style>
<g class="st0">
<g>
<g>
<line class="st1" x1="169.40327" y1="164.59085" x2="214.17865" y2="75.17516"/>
</g>
<g>
<line class="st1" x1="144.40327" y1="164.59085" x2="189.17865" y2="75.17516"/>
</g>
<g>
<line class="st1" x1="119.40328" y1="164.59085" x2="164.17865" y2="75.17516"/>
</g>
<g>
<line class="st1" x1="69.40328" y1="164.59085" x2="114.17865" y2="75.17516"/>
</g>
<g>
<line class="st1" x1="44.40328" y1="164.59085" x2="89.17865" y2="75.17516"/>
</g>
<g>
<line class="st1" x1="19.40328" y1="164.59085" x2="64.17865" y2="75.17516"/>
</g>
</g>
<g>
<g>
<line class="st1" x1="33.58193" y1="86.35222" x2="233.58192" y2="86.35222"/>
</g>
<g>
<line class="st1" x1="27.98494" y1="97.52914" x2="227.98494" y2="97.52914"/>
</g>
<g>
<line class="st1" x1="22.38795" y1="108.70607" x2="222.38795" y2="108.70607"/>
</g>
<g>
<line class="st1" x1="11.19398" y1="131.05992" x2="211.19397" y2="131.05992"/>
</g>
<g>
<line class="st1" x1="5.59699" y1="142.23686" x2="205.59698" y2="142.23686"/>
</g>
<g>
<line class="st1" x1="0" y1="153.41379" x2="200" y2="153.41379"/>
</g>
</g>
</g>
<g>
<line class="st2" x1="16.79097" y1="119.883" x2="216.79097" y2="119.883"/>
<line class="st2" x1="94.40328" y1="164.59085" x2="139.17865" y2="75.17516"/>
<line class="st2" x1="116.79156" y1="219.883" x2="116.79037" y2="19.883"/>
</g>
<path class="st3" d="M114.13208,7.83091c1.17702-1.26283,1.80844-1.80845,2.59429-2.48447c0-0.02403,1.35204-1.18047,2.13787-1.9663
c2.07268-2.02808,2.5531-3.07471,2.5531-3.16051C121.41734,0,121.22175,0,121.17715,0c-0.15099,0-0.21963,0.04463-0.32601,0.24022
c-0.65544,1.04663-1.11526,1.39666-1.63686,1.39666c-0.52502,0-0.78583-0.32943-1.11183-0.70004
C117.68722,0.43582,117.3166,0,116.59596,0c-1.63686,0-2.63889,2.02808-2.63889,2.48792c0,0.10981,0.06519,0.2402,0.2608,0.2402
s0.24021-0.10981,0.28484-0.2402c0.41179-1.00547,1.67804-1.02605,1.85306-1.02605c0.45982,0,0.87161,0.15099,1.37607,0.32601
c0.87161,0.32943,1.11183,0.32943,1.67804,0.32943c-0.78583,0.93682-2.61831,2.50848-3.03352,2.85509l-1.96288,1.83589
c-1.48244,1.45844-2.2477,2.70411-2.2477,2.8551c0,0.21962,0.21963,0.21962,0.26424,0.21962
c0.17501,0,0.21619-0.04461,0.34659-0.28482c0.50445-0.76181,1.15645-1.35205,1.85649-1.35205
c0.50103,0,0.72065,0.1956,1.26626,0.83045c0.37061,0.4564,0.76182,0.80643,1.39323,0.80643
c2.1619,0,3.42817-2.76929,3.42817-3.35952c0-0.10981-0.08923-0.21962-0.26425-0.21962c-0.19559,0-0.2402,0.13039-0.3054,0.28481
c-0.501,1.41726-1.89767,1.83248-2.61831,1.83248c-0.4358,0-0.82701-0.1304-1.28683-0.28482
c-0.74123-0.28139-1.06723-0.37061-1.52708-0.37061C114.67427,7.76571,114.32768,7.76571,114.13208,7.83091"/>
<path class="st3" d="M151.75957,57.97247c0.0889-0.30446,0.0889-0.34893,0.0889-0.49945c0-0.39342-0.30434-0.59182-0.63275-0.59182
c-0.21893,0-0.56793,0.1334-0.763,0.4584c-0.04445,0.10947-0.21895,0.78683-0.30783,1.18022
c-0.15063,0.56447-0.30455,1.1563-0.43439,1.7447l-0.98195,3.92726c-0.0889,0.325-1.02618,1.85415-2.46637,1.85415
c-1.112,0-1.3513-0.96128-1.3513-1.76863c0-1.00234,0.36934-2.35362,1.11177-4.27619c0.349-0.89288,0.43788-1.13234,0.43788-1.57023
c0-0.98182-0.69798-1.78916-1.78917-1.78916c-2.07315,0-2.88039,3.16438-2.88039,3.35939c0,0.21894,0.21895,0.21894,0.25989,0.21894
c0.21895,0,0.24303-0.04449,0.35249-0.39342c0.58829-2.04916,1.46056-2.70598,2.203-2.70598c0.17447,0,0.54385,0,0.54385,0.70129
c0,0.54394-0.21895,1.11183-0.36937,1.52576c-0.87225,2.31257-1.26569,3.5578-1.26569,4.58067
c0,1.9431,1.37518,2.59649,2.66145,2.59649c0.8519,0,1.59082-0.36946,2.203-0.9818
c-0.28377,1.13576-0.54736,2.20309-1.41962,3.35937c-0.56442,0.74235-1.39574,1.37522-2.39807,1.37522
c-0.30455,0-1.28629-0.065-1.65913-0.91682c0.34898,0,0.63274,0,0.93729-0.25999c0.21895-0.19841,0.43788-0.48236,0.43788-0.89629
c0-0.67392-0.58829-0.76289-0.80724-0.76289c-0.50291,0-1.22148,0.34895-1.22148,1.41972c0,1.08786,0.95787,1.89521,2.31268,1.89521
c2.24765,0,4.49509-1.98416,5.10396-4.45068L151.75957,57.97247"/>
<path class="st3" d="M233.4446,117.99635c0.13005-0.56787,0.63297-2.57597,2.15877-2.57597c0.10947,0,0.63274,0,1.0912,0.28394
c-0.60889,0.10947-1.04677,0.65682-1.04677,1.18022c0,0.34895,0.23953,0.76288,0.83133,0.76288
c0.47882,0,1.1768-0.39341,1.1768-1.26576c0-1.13576-1.28629-1.44022-2.0287-1.44022c-1.2657,0-2.02872,1.1563-2.2921,1.65916
c-0.54385-1.44022-1.72417-1.65916-2.3569-1.65916c-2.26823,0-3.51006,2.81545-3.51006,3.35939
c0,0.21894,0.21565,0.21894,0.26009,0.21894c0.1745,0,0.23953-0.04449,0.28397-0.23948
c0.74222-2.31257,2.18263-2.85992,2.92485-2.85992c0.41402,0,1.1768,0.19843,1.1768,1.46416
c0,0.67393-0.36935,2.1381-1.1768,5.19302c-0.349,1.35126-1.1153,2.26808-2.07317,2.26808c-0.12984,0-0.63274,0-1.0912-0.28392
c0.54385-0.10947,1.0264-0.56789,1.0264-1.17681c0-0.59184-0.48254-0.7663-0.80745-0.7663
c-0.65683,0-1.20068,0.56787-1.20068,1.26575c0,1.00577,1.0912,1.44022,2.04907,1.44022c1.4402,0,2.22708-1.52573,2.2921-1.65916
c0.26338,0.80735,1.04677,1.65916,2.3569,1.65916c2.24765,0,3.48949-2.81543,3.48949-3.35937
c0-0.21894-0.19507-0.21894-0.2601-0.21894c-0.19836,0-0.2393,0.08893-0.28375,0.23946
c-0.72185,2.33652-2.2032,2.85992-2.90097,2.85992c-0.8519,0-1.2009-0.69788-1.2009-1.44022
c0-0.47894,0.13007-0.96129,0.36958-1.91915L233.4446,117.99635"/>
</svg>

After

Width:  |  Height:  |  Size: 5.8 KiB

266
Chemilumesence.md Normal file
View File

@ -0,0 +1,266 @@
# Chemiluminescence in Hydro-Flames — CH* and OH*
## Overview
Chemiluminescence in flames arises when chemical reactions produce **excited radicals** that emit photons as they relax.
The two most important species for combustion diagnostics are:
- CH* (≈ 431 nm, blue)
- OH* (≈ 310 nm, UV)
These are not just “present radicals” — they are **selectively excited products of specific reactions**, and their relative intensity encodes combustion chemistry.
---
## Key Reactions
### CH* Formation (fuel breakdown zone)
CH* is associated with hydrocarbon fragmentation and early flame chemistry.
Typical pathways:
$$
\mathrm{C_2H + O \rightarrow CH^* + CO}
$$
$$
\mathrm{CH_2 + O \rightarrow CH^* + OH}
$$
$$
\mathrm{C + H_2 \rightarrow CH^* + H}
$$
These reactions dominate in **fuel-rich or near-front regions** of the flame.
---
### OH* Formation (oxidation zone)
OH* is associated with high-temperature oxidation chemistry.
Typical pathways:
$$
\mathrm{H + O_2 \rightarrow OH^* + O}
$$
$$
\mathrm{O + H \rightarrow OH^*}
$$
$$
\mathrm{H_2 + O \rightarrow OH^* + H}
$$
These reactions dominate in **lean or well-oxidised regions**.
---
## Why Excited States Are Produced
A chemical reaction releases energy:
$$
\mathrm{A + B \rightarrow C + D + energy}
$$
This energy can be distributed into:
- Translational motion (heat)
- Vibrational energy
- Rotational energy
- **Electronic excitation**
If enough energy is deposited into the electronic degree of freedom:
$$
\mathrm{OH^* \rightarrow OH + h\nu}
$$
$$
\mathrm{CH^* \rightarrow CH + h\nu}
$$
The emitted photon is what we detect.
---
## Non-Equilibrium Nature
These reactions occur under:
- High temperature
- Fast radicalradical collisions
- Non-equilibrium conditions
Therefore:
> Products are often formed **directly in excited states**, rather than being thermally excited.
---
## Why Only Certain Species Emit Strongly
Not all reactions produce visible/UV light. Strong chemiluminescence requires:
- Sufficient reaction energy (~25 eV)
- Good overlap between reaction geometry and excited state (FranckCondon principle)
- Fast radiative decay
CH* and OH* satisfy these conditions.
---
## Energy Scale
Typical photon energies:
$$
E = h\nu
$$
CH* emission (~431 nm):
$$
E \approx 2.9 \text{ eV}
$$
OH* emission (~310 nm):
$$
E \approx 4.0 \text{ eV}
$$
---
## Spatial Structure of the Flame
- CH* peaks in the **reaction front** (fuel breakdown)
- OH* peaks slightly downstream in the **oxidation zone**
Thus, they probe different regions of the flame.
---
## The OH*/CH* Ratio
Define:
$$
R = \frac{OH^*}{CH^*}
$$
This ratio reflects:
$$
R \propto \frac{\text{oxidation rate}}{\text{fuel fragmentation rate}}
$$
---
### Interpretation
- Fuel-rich:
- High CH*
- Lower OH*
- $$R \text{ small}$$
- Lean:
- High OH*
- Lower CH*
- $$R \text{ large}$$
- Stoichiometric:
- Balanced
- $$R \text{ intermediate}$$
---
## Why the Ratio is Useful
Absolute intensity depends on:
- Optical alignment
- Flame size
- Window fouling
- Sensor gain
But the ratio:
$$
\frac{OH^*}{CH^*}
$$
cancels many of these effects and provides a **robust indicator of combustion state**.
---
## Physical Interpretation
- CH* → “fuel is still breaking apart”
- OH* → “oxidation is occurring”
So:
> The ratio indicates where the flame sits between **fuel-dominated** and **oxidation-dominated** chemistry.
---
## Deeper Insight
Even though both species arise from excited states:
- CH* is fed by **hydrocarbon radical pathways**
- OH* is fed by **oxidation pathways**
Thus the ratio is not just energy-related — it reflects:
> **Which chemical pathways dominate locally**
---
## Summary
- Chemiluminescence arises from **excited radicals formed during reactions**
- CH* and OH* originate from **different parts of the combustion network**
- Their ratio provides a **real-time optical measure of stoichiometry and flame structure**
---

266
Chemistry.md Normal file
View File

@ -0,0 +1,266 @@
# Chemiluminescence in Hydro-Carbon Flames — CH* and OH*
## Overview
Chemiluminescence in flames arises when chemical reactions produce **excited radicals** that emit photons as they relax.
The two most important species for combustion diagnostics are:
- CH* (≈ 431 nm, blue)
- OH* (≈ 310 nm, UV)
These are not just “present radicals” — they are **selectively excited products of specific reactions**, and their relative intensity encodes combustion chemistry.
---
## Key Reactions
### CH* Formation (fuel breakdown zone)
CH* is associated with hydrocarbon fragmentation and early flame chemistry.
Typical pathways:
$$
\mathrm{C_2H + O \rightarrow CH^* + CO}
$$
$$
\mathrm{CH_2 + O \rightarrow CH^* + OH}
$$
$$
\mathrm{C + H_2 \rightarrow CH^* + H}
$$
These reactions dominate in **fuel-rich or near-front regions** of the flame.
---
### OH* Formation (oxidation zone)
OH* is associated with high-temperature oxidation chemistry.
Typical pathways:
$$
\mathrm{H + O_2 \rightarrow OH^* + O}
$$
$$
\mathrm{O + H \rightarrow OH^*}
$$
$$
\mathrm{H_2 + O \rightarrow OH^* + H}
$$
These reactions dominate in **lean or well-oxidised regions**.
---
## Why Excited States Are Produced
A chemical reaction releases energy:
$$
\mathrm{A + B \rightarrow C + D + energy}
$$
This energy can be distributed into:
- Translational motion (heat)
- Vibrational energy
- Rotational energy
- **Electronic excitation**
If enough energy is deposited into the electronic degree of freedom:
$$
\mathrm{OH^* \rightarrow OH + h\nu}
$$
$$
\mathrm{CH^* \rightarrow CH + h\nu}
$$
The emitted photon is what we detect.
---
## Non-Equilibrium Nature
These reactions occur under:
- High temperature
- Fast radicalradical collisions
- Non-equilibrium conditions
Therefore:
> Products are often formed **directly in excited states**, rather than being thermally excited.
---
## Why Only Certain Species Emit Strongly
Not all reactions produce visible/UV light. Strong chemiluminescence requires:
- Sufficient reaction energy (~25 eV)
- Good overlap between reaction geometry and excited state (FranckCondon principle)
- Fast radiative decay
CH* and OH* satisfy these conditions.
---
## Energy Scale
Typical photon energies:
$$
E = h\nu
$$
CH* emission (~431 nm):
$$
E \approx 2.9 \text{ eV}
$$
OH* emission (~310 nm):
$$
E \approx 4.0 \text{ eV}
$$
---
## Spatial Structure of the Flame
- CH* peaks in the **reaction front** (fuel breakdown)
- OH* peaks slightly downstream in the **oxidation zone**
Thus, they probe different regions of the flame.
---
## The OH*/CH* Ratio
Define:
$$
R = \frac{OH^*}{CH^*}
$$
This ratio reflects:
$$
R \propto \frac{\text{oxidation rate}}{\text{fuel fragmentation rate}}
$$
---
### Interpretation
- Fuel-rich:
- High CH*
- Lower OH*
- $$R \text{ small}$$
- Lean:
- High OH*
- Lower CH*
- $$R \text{ large}$$
- Stoichiometric:
- Balanced
- $$R \text{ intermediate}$$
---
## Why the Ratio is Useful
Absolute intensity depends on:
- Optical alignment
- Flame size
- Window fouling
- Sensor gain
But the ratio:
$$
\frac{OH^*}{CH^*}
$$
cancels many of these effects and provides a **robust indicator of combustion state**.
---
## Physical Interpretation
- CH* → “fuel is still breaking apart”
- OH* → “oxidation is occurring”
So:
> The ratio indicates where the flame sits between **fuel-dominated** and **oxidation-dominated** chemistry.
---
## Deeper Insight
Even though both species arise from excited states:
- CH* is fed by **hydrocarbon radical pathways**
- OH* is fed by **oxidation pathways**
Thus the ratio is not just energy-related — it reflects:
> **Which chemical pathways dominate locally**
---
## Summary
- Chemiluminescence arises from **excited radicals formed during reactions**
- CH* and OH* originate from **different parts of the combustion network**
- Their ratio provides a **real-time optical measure of stoichiometry and flame structure**
---

1
Clothing.md Normal file
View File

@ -0,0 +1 @@
[[buffs]]

View File

@ -0,0 +1,25 @@
Written by ChatGPT but checked against the data-sheet calculations.
#!/usr/bin/env python3
"""
2nd-order unity-gain Butterworth Sallen-Key low-pass calculator
Based on TI SBOA226 design steps:
Usage:
For 22k resistors and a cut-off $f_c$ of 500Hz:
$ python3 --R 22E3 500
![[butter_plot.py]]
![[butter_plot.py]]
## Example
$ python3 butter_plot.py --R 22E3 500
2nd-order unity-gain Butterworth Sallen-Key LPF (ideal)
fc = 0.5 kHz
R1=R2= 22 kohm
C1 = 20.46 nF (norm 1.414)
C2 = 10.23 nF (norm 0.707)
Q = 0.707107

4
Control Engineering.md Normal file
View File

@ -0,0 +1,4 @@
[[PID]]
## Feedback and Control Systems Book
![[Feedback Control of Dynamic Systems 7th Franklin [Text].pdf]]

1
Cycling.md Normal file
View File

@ -0,0 +1 @@
![[IMG_0038.JPG_compressed.jpeg]]

97
DIV.md Normal file
View File

@ -0,0 +1,97 @@
# Divergence
**An operation on a Vector Field which returns a scalar field representing the degree to which the field flows outwards.**
The **divergence** of a vector field is a scalar field which describes the rate at which the vector field changes the volume of a region around a point as the region contracts to the point.
A physical interpretation of divergence is that it represents the amount that the vector field _flows outwards_ at every point. The terms "source" and "sink" are common ways to describe regions where the vector field originates or terminates and thus has positive or negative divergence, respectively.
## Definition
### Cartesian coordinate definition
In general, the definition of divergence using [[Cartesian coordinates]] are more commonly used and simpler than the coordinate-less definition which is defined at a point.
Divergence
The _divergence_ of a vector field $\textbf{F} =F_1 e_1 +F_2 e_2 ... +F_N e_N$ or $F(x,y,z)=(Fx,Fy,Fz)$; the scalar field where is the sum its partial derivatives:
$$div\; F = \nabla \cdot F = \frac{\partial F_x}{\partial x} +\frac{\partial F_z}{\partial z} + \frac{\partial F_y}{\partial y} $$ of the component function with respect to its axes. Note $\nabla F$ is **NORMAL to F**.
# Dot Product and Flux
## Flux through a Surface
$$
\text{Flux} = \mathbf{F} \cdot \mathbf{n}\, dS
$$
Where: - $\mathbf{F}$ = vector field
- $\mathbf{n}$ = surface normal
- $dS$ = surface element
------------------------------------------------------------------------
## Dot Product Expansion
$$
\mathbf{F} \cdot \mathbf{n} = |\mathbf{F}|\,|\mathbf{n}| \cos\theta
$$
Where: - $\theta$ = angle between the vector field and the surface
normal
------------------------------------------------------------------------
## Interpretation
Only the component of the vector field **parallel to the surface
normal** contributes to flow through the surface.
- If $\theta = 0^\circ$:
$$ \cos\theta = 1 $$
Full flow through the surface
- If $\theta = 90^\circ$:\
$$ \cos\theta = 0 $$
No flow through the surface
- If $\theta > 90^\circ$:
$$ \cos\theta < 0 $$
Flow is **into** the surface
------------------------------------------------------------------------
## Key Insight
$$
\text{Dot product} = \text{projection of the vector field onto the normal}
$$
This projection represents the **actual flow crossing the surface**.
------------------------------------------------------------------------
## Link to Divergence
$$
\nabla \cdot \mathbf{F}
$$
Represents the **net flow out of a small volume**.
$$
\iiint (\nabla \cdot \mathbf{F})\, dV = \iint \mathbf{F} \cdot \mathbf{n}\, dS
$$
------------------------------------------------------------------------
## One-Line Summary
- Dot product → flow **through** a surface
- Divergence → net flow **out of** a volume
- $\cos\theta$ → how much of the vector actually crosses the surface
---

1
DeBroglie PhD.md Normal file
View File

@ -0,0 +1 @@
![[De_Broglie_Kracklauer.pdf]]

BIN
De_Broglie_Kracklauer.pdf Normal file

Binary file not shown.

139
EN61508.md Normal file
View File

@ -0,0 +1,139 @@
# EN 61508 — Functional Safety of E/E/PE Systems
## Overview
EN 61508 is the generic functional safety standard for Electrical / Electronic / Programmable Electronic (E/E/PE) systems.
It provides a framework to ensure systems reduce risk to an acceptable level.
---
## Core Idea
Risk is defined as:
Risk = Frequency × Consequence
Safety functions reduce this risk.
---
## Key Concepts
### Safety Function
A function that:
- Detects hazardous conditions
- Takes action to prevent harm
---
### Safety Integrity Level (SIL)
| SIL | Meaning |
|-----|--------|
| SIL 1 | Low risk reduction |
| SIL 2 | Moderate |
| SIL 3 | High |
| SIL 4 | Very high |
---
### Probability of Failure
#### Low Demand Mode (PFDavg)
| SIL | Range |
|-----|-------|
| SIL 1 | 1e-2 to 1e-1 |
| SIL 2 | 1e-3 to 1e-2 |
| SIL 3 | 1e-4 to 1e-3 |
| SIL 4 | 1e-5 to 1e-4 |
#### High/Continuous Mode (PFH)
| SIL | Failures/hour |
|-----|---------------|
| SIL 1 | 1e-6 to 1e-5 |
| SIL 2 | 1e-7 to 1e-6 |
| SIL 3 | 1e-8 to 1e-7 |
| SIL 4 | 1e-9 to 1e-8 |
[[PFD_PFH_when_to_use]]
[[PFD_and_PFH]]]
---
## Safety Lifecycle
1. Hazard analysis
2. Safety requirements
3. System design
4. Hardware design
5. Software design
6. Verification & validation
7. Operation & maintenance
8. Decommissioning
---
## Hardware Reliability
- FIT = 1e-9 failures/hour
- PFH = Probability of dangerous failure/hour
- PFDavg = Probability of failure on demand
---
## Failure Types
### Random Failures
Handled statistically (FIT, PFH)
### Systematic Failures
Handled by process, reviews, and discipline
---
## Techniques
- Redundancy (1oo2, 2oo3)
- Diagnostics
- Diversity
- Formal methods (high SIL)
---
## Standard Structure
1. General
2. Hardware
3. Software
4. Definitions
57. Guidelines
---
## Related Standards
- EN 61511 (Process)
- EN 62061 (Machinery)
- ISO 26262 (Automotive)
- EN 298 (Burners)
---
## Key Takeaways
- Focus on risk reduction
- SIL is a target, not a feature
- Process matters as much as maths
- Lifecycle coverage is essential
---
## One-Line Summary
EN 61508 ensures safety systems reduce risk using quantified reliability and disciplined engineering processes.
---

12
Electronics.md Normal file
View File

@ -0,0 +1,12 @@
[[Filters]]
[[mesh]]
[[ADCs]]
[[Transistors]]
[[Valves]]
[[Optics]]
[[CANbus]]
[[Control Engineering]]
[[Peak Detector]]
[[piezo amplifiers]]

BIN
FB_IMG_1771442819534.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

5
Filters.md Normal file
View File

@ -0,0 +1,5 @@
See Analog Filter Design by Valkenburg ISBN:4-8338-0091-3
[[Simple RC low pass filter]]
[[SingleOpampCap]]
[[Sallen Key]]

Binary file not shown.

View File

@ -0,0 +1,6 @@
The following python script takes the circuit describes and plots its response.
This is for values of capacitors or resistors that deviate form stanard E values.
![[Screenshot from 2026-02-18 13-17-53.png]]
![[sallen_general.py]]
![[sallen_general.py]]

7
Hello..md Normal file
View File

@ -0,0 +1,7 @@
The wave function is $$ \psi(x) = A e^{ikx} $$
OK how quickly does it update???

3
Human Biology.md Normal file
View File

@ -0,0 +1,3 @@
![[metabolic_pathways_poster.pdf]]

Binary file not shown.

After

Width:  |  Height:  |  Size: 690 KiB

4
Juggling.md Normal file
View File

@ -0,0 +1,4 @@
![[imgp3389_20071053719_o.jpg_compressed 1.jpeg]]
[[Five Ball Exercises]]

13
Laplace Transforms.md Normal file
View File

@ -0,0 +1,13 @@
General form:
$$\int_{0-}^{\infty} f(t) e^{-st} dt$$
Note: s = $\frac{1}{time}$ and is complex. Why? Because the inverse of time is frequency! The limit $0-$ is there for the Dirac impulse function at time 0.
Also consider the step function, $1/s$. Differentiate what do you get? 1. Dirac impulse function!!!
[[Worked Example RC Low Pass]]

8
Maths.md Normal file
View File

@ -0,0 +1,8 @@
[[Quaternions]]
[[Vector_Calculus]]
[[Eigen_values_vectors_states]]
[[Laplacian]]
[[Fourier Transforms]]
[[Laplace Transforms]]
[[Calculus]]
[[Trigonometry]]

2
Music.md Normal file
View File

@ -0,0 +1,2 @@
![[circle_of_fifths.jpg]]

BIN
NONINVLP_OPAMP_BUFFER.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 371 KiB

4
Optics.md Normal file
View File

@ -0,0 +1,4 @@
[[Photo Diode Amplifier]]
[[Phototransistor Amplifier]]
.

26
PID.md Normal file
View File

@ -0,0 +1,26 @@
![[pid.png]]
## My recipe
Adjust the proportional until about 90% on target. Add in integral until very minor overshoot.
Add derivative if too much overshoot.
## PID controller explained
### **Proportional Control (P)**
The difference between the planned PID_TARGET and the actual process variable is known as the current error value, and the proportional component of a PID controller generates an output that is exactly proportionate to this value. The proportionate reaction will be large if the mistake is significant, and vice versa. The sensitivity of the controller to the mistake is determined by the proportional gain (Kp). But P control by itself is unable to get rid of the steady-state error, which results in a permanent offset.
### **Integral Control (I)**
The steady-state error is eliminated by the integral component, which gradually accumulates the error and modifies the controllers output. The mistake is added up over time and then multiplied by the integral gain (Ki). By ensuring that the total error is pushed to zero, whatever offset that the proportional control may have left behind is eliminated. On the other hand, instability and oscillations might result from excessive integral activity.
The integral term often needs limits in practice.
### **Derivative Control (D)**
Based on its rate of change, the derivative component forecasts the inaccuracy in the future. By increasing the derivative gain (Kd) by the errors derivative over time, it produces a damping effect. By doing this, the response is smoothed down and oscillations and overshoot are lessened. Derivative control, however, is susceptible to error signal noise and, if mishandled, may intensify it.
Often the derivative in not used.
---

Binary file not shown.

After

Width:  |  Height:  |  Size: 776 KiB

BIN
PXL_20260406_153419214.mp4 Normal file

Binary file not shown.

0
Peak Detector.md Normal file
View File

3
Photo Diode Amplifier.md Normal file
View File

@ -0,0 +1,3 @@
![[UV_Diode_amplifier_two_stage.png]]
This is my working photo-diode amplifier that responded well the butane gas flames in the lab.
This worked well with manf:GUVB-S11DCT-ND ( $240 \rightarrow 320nm$ $ UVB) and manf:GUVV-S10SD ($240nm \rightarrow 320nm$ UVA). Note the 7M5 feeding the vref to the first op-amp is necessary for current balancing. A multi-meter will disturb this first stage as it is amplifying pico-amps (probably!)

View File

@ -0,0 +1,4 @@
![[ir_photo_transistor_amplifier.png]]
This amplifier, when IR hits the exposed base on the photo~transistor (marked as a diode above) pulls the OPAMP minus input down. To re balance this the OPAMP output swings up in voltage to provide current via R12. This 1uA of current flowing through the photo transistor will cause $1 \mu A \times 82\times 10^3 = 82mV$. This signal is buffered by the OPAMP and thus suitable for direct reading by an ADC. Also if the OPAMP is operated from 0 to 3V3 supply, there is no need for ADC voltage scaling. The 2k2 potential divider should be connected to a port pin, so that the ADC readings and MUX can be verified.

10
Physics.md Normal file
View File

@ -0,0 +1,10 @@
[[ Schrodinger explained]]
[[DeBroglie PhD]]
[[Ideas]]
[[Complex_probabilities]]

3
Posters.md Normal file
View File

@ -0,0 +1,3 @@
![[vec_calculus.jpg_compressed.jpeg]]
![[FB_IMG_1771442819534.jpg]]

86
QM Kinetic energy.md Normal file
View File

@ -0,0 +1,86 @@
$\nabla^2 \psi$ describes kinetic energy. In QM terms this means, when it is large, the waveform is curved or stretched. One way to visualize it is, if it has low velocity, it stays in one place. If it has high velocity it describes a kind of corkscrew as it moves through free space.
$\nabla^2 \psi$ is associated with the kinetic energy operator in quantum mechanics,
$$
\hat{T} = -\frac{\hbar^2}{2m}\nabla^2
$$
A large value of the Laplacian indicates strong spatial curvature of the wave~function,
meaning the state contains higher momentum components and therefore higher kinetic energy.
This does not imply the particle is physically stretched or distorted. Rather, it reflects
how rapidly the **phase** of the wave~function varies in space.
For a slowly moving particle, the spatial phase variation is gentle. For a particle with
large momentum,
$$
p = \hbar k
$$
the wave~function phase varies rapidly. Because the complex factor
$$
e^{ikx}
$$
represents rotation in the complex plane, the real and imaginary parts may be visualized
as forming a helical or ``corkscrew-like'' structure in space.
This corkscrew picture describes phase behaviour of the quantum state, not literal motion
of the particle.
In quantum mechanics, a particles motion is encoded in the **spatial variation of the wave~functions phase**, not in the amplitude itself.
For a free particle, the wave~function has the form
$$
\psi(x,t) = A e^{i(kx - \omega t)}
$$
where the probability density
$$
|\psi(x,t)|^2 = |A|^2
$$
is constant, but the **phase** varies with position.
Momentum is directly related to how quickly the phase rotates in space:
$$
p = \hbar k
$$
A larger \( k \) means faster phase winding, corresponding to higher momentum.
Because the complex exponential represents rotation in the complex plane,
$$
e^{ikx}
$$
it may be visualized as a helical or ``corkscrew-like'' structure when separating real and imaginary parts.
Velocity (non-relativistic) follows from momentum:
$$
v = \frac{p}{m} = \frac{\hbar k}{m}
$$
So a faster particle corresponds to more rapid spatial phase variation.
Kinetic energy arises from the Laplacian of the wave~function:
$$
\hat{T} = -\frac{\hbar^2}{2m} \nabla^2
$$
High curvature i.e large $\nabla^2 \psi$, implies strong spatial variation, hence large momentum components and higher kinetic energy.
Key take~away:
* Slow phase variation $\rightarrow$ low momentum $\rightarrow$ gentle oscillation
* Rapid phase variation $\rightarrow$ high momentum $\rightarrow$ tightly wound phase rotation
The ``corkscrew'' picture describes phase behaviour, not literal particle motion.
---

6
QM.md Normal file
View File

@ -0,0 +1,6 @@
[[Vector_Calculus]]
[[QM Kinetic energy]]

146
Quantum Phase Corkscrew.md Normal file
View File

@ -0,0 +1,146 @@
# Plane Waves, Phase Twist, and the Corkscrew Picture
## Key Realisation
A quantum plane wave is **not just an oscillating wave**.
It is a wave whose **phase is continuously twisting through space**.
This spatial twist corresponds to **motion and momentum**.
---
## Start with the plane wave
$$
\psi(x,t) = e^{i(kx-\omega t)}
$$
Using Euler's identity:
$$
e^{i\theta} = \cos\theta + i\sin\theta
$$
So
$$
\psi(x,t) = \cos(kx-\omega t) + i\sin(kx-\omega t)
$$
The cosine part looks like an ordinary travelling wave.
But the deeper structure is in the **phase**.
---
## The phase
The phase is
$$
\theta(x,t) = kx - \omega t
$$
As we move through space:
$$
\frac{\partial \theta}{\partial x} = k
$$
So the phase **rotates steadily as position changes**.
At every point in space the wavefunction behaves like a **tiny rotating vector (phasor)**.
---
## Corkscrew picture
If we plot:
- x = position
- y = cos(kx)
- z = sin(kx)
the curve becomes a **helix**.
So the plane wave can be visualised as a **corkscrew twisting through space**.
The wave isn't just going up and down — its **phase is spiralling as it moves**.
---
## Momentum comes from the twist
De Broglie discovered:
$$
p = \hbar k
$$
But
$$
k = \frac{\partial \theta}{\partial x}
$$
So momentum can be written as
$$
p = \hbar \nabla \theta
$$
Meaning:
> **Momentum is the spatial rate of phase twist.**
The faster the corkscrew twists through space, the larger the momentum.
---
## Kinetic energy and curvature
Classically:
$$
T = \frac{p^2}{2m}
$$
Substituting $p = \hbar k$:
$$
T = \frac{\hbar^2 k^2}{2m}
$$
But the second derivative of the wave gives:
$$
\frac{\partial^2}{\partial x^2} e^{ikx} = -k^2 e^{ikx}
$$
So kinetic energy acting on the wave becomes
$$
T = -\frac{\hbar^2}{2m} \nabla^2
$$
This is why the **Laplacian appears in the Schrödinger equation**.
---
## Final intuition
The wavefunction contains two things:
**Amplitude**
- how much probability is present
**Phase**
- how the probability flow moves through space
The phase twists through space like a **corkscrew**, and that twist is directly related to **momentum and motion**.
---
## Oneline summary
> A quantum plane wave is a **corkscrew of phase twisting through space**, and the rate of twist determines the particle's momentum.

18
Quaternions.md Normal file
View File

@ -0,0 +1,18 @@
---
---
---
These are four dimensional numbers useful for rotation. Unlike matrices quaternions do not cause problems when rotating i.e. when the determinant is very small. Like complex number rotation, they simply wrap around.
$R,i,j,k$$ where $i,j,k$ are complex so $i*i=-1, j*j=-1, k*k=-1$. However these complex planes are orthogonal. They correspond to axes in cartesian coordinates, i.e. $i$ is the x axis, $j$ is the y axis and $k$ the z.
Also $i*j*k = -1$.
Multiplying by $i$ say rotates any vector or coordinate around $90^\circ$
The following python program allows you to play with quaternions, seeing the intermediate un-pure quaternion results as well.
![[quat_gui 1.py]]
---

BIN
SGTL5000_PIEZO_AMP.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

4
Sallen Key.md Normal file
View File

@ -0,0 +1,4 @@
[[ButterworthLowPass]]
[[General purpose python analyser]]

292
Schrodinger explained.md Normal file
View File

@ -0,0 +1,292 @@
# Schrödinger Equation Derivation — Why the Kinetic Term is $-\hbar^2/(2m)\,\nabla^2$
## Goal
Start from the **classical energy equation**, E=total energy, p=momentum, m=mass, V=potential energy. So the Hamiltonian (not the Larangian)...
$$
E = \frac{p^2}{2m} + V
$$
Note this is $E=\frac{1}{2} m v^2$. P is momentum so $p^2 = {m^2v^2}$, so dividing by 2m converts the kinetic energy a momentum equation
and show how this becomes the **time-dependent Schrödinger equation**
$$
i\hbar \frac{\partial \psi}{\partial t}
=
-\frac{\hbar^2}{2m}\nabla^2\psi + V\psi
$$
---
## 1. Slowly with classical mechanics....
For a non-relativistic particle, total energy is
$$
E = \frac{p^2}{2m} + V
$$
where:
- $E$ = total energy
- $p$ = momentum
- $m$ = mass
- $V$ = potential energy
The term
$$
\frac{p^2}{2m}
$$
is the usual classical kinetic energy.
Since
$$
p = mv
$$
we have
$$
\frac{p^2}{2m} = \frac{m^2 v^2}{2m} = \frac{1}{2}mv^2
$$
So the **divide by $2m$** simply comes from the classical kinetic energy formula.
---
## 2. Introduce a wave
Quantum mechanics uses a **wavefunction** $\psi(x,t)$.
Take a simple plane wave in 1D:
$$
\psi(x,t) = e^{i(kx-\omega t)}
$$
This is a plane wave solution. In quantum mechanics, position is not definite — the probability of finding the particle is given by $|\psi|^2$. This is similar to the position in classical physics.
This is useful because derivatives acting on exponentials bring down constants.
[[Quantum Phase Corkscrew]]
---
## 3. Differentiate with respect to position
$$
\frac{\partial \psi}{\partial t} = -i\omega\psi
$$
Note this differentiates by time. Its looking at how fast the particle waveform oscillates which is directly related to the energy via the plank constant. As for a photon this means the frequency is $\propto$ E.
Second derivative w.r.t. distance:
$$
\frac{\partial^2 \psi}{\partial x^2} = -k^2 \psi
$$
So the second derivative returns the same wave multiplied by $-k^2$ because $i^2$ is -1. The first derivative gives momentum, and the second derivative gives momentum squared, which corresponds to kinetic energy.
---
## 4. Relate $k$ to momentum
From de Broglie:
$$
p = \hbar k
$$
so
$$
k = \frac{p}{\hbar}
$$
Substitute this into the second derivative result:
$$
\frac{\partial^2 \psi}{\partial x^2}
=
-\left(\frac{p}{\hbar}\right)^2 \psi
=
-\frac{p^2}{\hbar^2}\psi
$$
Rearrange:
$$
p^2 \psi = -\hbar^2 \frac{\partial^2 \psi}{\partial x^2}
$$
Key idea:
> **Momentum squared acting on a wave becomes minus $\hbar^2$ times the second derivative.**
So in operator form,
$$
\hat{p}^2 = -\hbar^2 \frac{\partial^2}{\partial x^2}
$$
and in 3D,
$$
\hat{p}^2 = -\hbar^2 \nabla^2
$$
---
## 5. Put that into the energy equation
Start from
$$
E = \frac{p^2}{2m} + V
$$
Multiply through by $\psi$:
$$
E\psi = \frac{p^2}{2m}\psi + V\psi
$$
Replace $p^2\psi$:
$$
E\psi
=
\frac{1}{2m}\left(-\hbar^2 \frac{\partial^2 \psi}{\partial x^2}\right) + V\psi
$$
So
$$
E\psi
=
-\frac{\hbar^2}{2m}\frac{\partial^2 \psi}{\partial x^2} + V\psi
$$
This is where the factor
$$
-\frac{\hbar^2}{2m}
$$
comes from.
---
## 6. Replace energy by a time derivative
For a wave
$$
\psi(x,t) = e^{i(kx-\omega t)}
$$
Differentiate with respect to time:
$$
\frac{\partial \psi}{\partial t} = -i\omega \psi
$$
Multiply by $i\hbar$:
$$
i\hbar \frac{\partial \psi}{\partial t}
=
i\hbar (-i\omega)\psi
=
\hbar\omega \psi
$$
But Planck's relation says
$$
E = \hbar \omega
$$
So
$$
E\psi = i\hbar \frac{\partial \psi}{\partial t}
$$
Thus
$$
\hat{E} = i\hbar \frac{\partial}{\partial t}
$$
---
## 7. Substitute into the equation
We had
$$
E\psi =
-\frac{\hbar^2}{2m}\frac{\partial^2 \psi}{\partial x^2}
+ V\psi
$$
Replace $E\psi$:
$$
i\hbar \frac{\partial \psi}{\partial t}
=
-\frac{\hbar^2}{2m}\frac{\partial^2 \psi}{\partial x^2}
+ V\psi
$$
This is the **1D timedependent Schrödinger equation**.
In 3D:
$$
i\hbar \frac{\partial \psi}{\partial t}
=
-\frac{\hbar^2}{2m}\nabla^2\psi + V\psi
$$
---
## 8. Physical meaning of the second derivative
The second derivative measures **curvature** of the wavefunction.
- Gentle curvature → long wavelength → small $k$ → small momentum
- Rapid oscillation → short wavelength → large $k$ → large momentum
Since kinetic energy depends on $p^2$, it naturally connects to a **second derivative**.
---
## 9. Operator summary
Classical equation:
$$
E = \frac{p^2}{2m} + V
$$
Quantum substitutions:
$$
E \rightarrow i\hbar \frac{\partial}{\partial t}
$$
$$
p \rightarrow -i\hbar \nabla
$$
Therefore
$$
p^2 \rightarrow (-i\hbar \nabla)^2 = -\hbar^2 \nabla^2
$$
and
$$
\frac{p^2}{2m}
\rightarrow
-\frac{\hbar^2}{2m}\nabla^2
$$
So we obtain
$$
i\hbar \frac{\partial \psi}{\partial t}
=
-\frac{\hbar^2}{2m}\nabla^2\psi + V\psi
$$
---
## 10. Intuition in one sentence
The Schrödinger equation is simply
$$
\text{Energy} = \text{kinetic} + \text{potential}
$$
rewritten so **energy and momentum become differential operators acting on a wavefunction**.
---

1
Schrödinger_Equation.md Normal file
View File

@ -0,0 +1 @@
![[Schrödinger_Equation]]

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

@ -0,0 +1,22 @@
```
Vout ──[ R]──●─────────── ADC
|
|
=== C
|
GND
```
For a one pole low pass filter where $\tau=RC$ and $\omega$ is angular velocity in radians:
$$|H(j\omega)| = \frac{1}{\sqrt{1+{(\omega \tau)}^2}}$$
The -3dB point is when $\omega \tau = 1$, i.e. magnitude response is $\frac{1}{\sqrt{2}} = 0.707$
This cut off frequency is defined as $$\omega_{c} = \frac{1}{\tau}, \; f_{c} =\frac{1}{2 \pi \tau}$$
For a Laplace transform derivation see [[Worked Example RC Low Pass]]
---

32
SingleOpampCap.md Normal file
View File

@ -0,0 +1,32 @@
# Single Pole Op-AMP low pass Buffer
Note: This is a low pass amplifier/buffer. At high frequencies it has an effective gain of one. If this is used as an amplifier it will have an effect of not amplifying the higher frequencies. Hence low pass buffer, not low pass filter!
![[NONINVLP_OPAMP_BUFFER.jpg]]
A single buffer op-amp, with $R_1$ to
plus and $R_2$ as feedback, with a parallel feedback resistor, will act as a low pass filter with a 3Db cut-off point at,
$$ f_c = \frac{1}{2.\pi.R_2.C} \; .$$
The gain of the filter effect at frequency $f$ where the cut-off is $f_c$ is
$$|H| = \frac{1}{\sqrt{1+(\frac{f}{f_c})^2} + 1}$$
Note this is a single pole filter with a characteristic, past $f_c$ of
** Every *×10* increase in frequency → *20 dB*
** Every *×2* increase in frequency → 6 dB
But in this case its drop off from the Gain of the amplifier. High frequencies will have a theoretical lowest gain of one.
A double pole actual low pass filter configuration is the [[Sallen Key]].
## Example
If $R_1$, $R_2$ are 22k and the capactor $C_1$ is 1nF the $3Db$ point will be
$$ \frac{1}{2 \times \pi\times22E3\times1E-9} = 7.2E3$$ or 7.2kHz.
At 10 Mhz lets calculate the attenuation:-0=
$$ |H| = \frac{1}{\sqrt{1 +(\frac{10E6}{7.2E3})^2}} = \frac{1}{1388.9} = 720E{-6}$$
Converting this to $Amplitude \; Db$ i.e. $20 log_{10} (|H|)$ giving $-62.8 Db$
![[FB_IMG_1771442897824 3.jpg]]

4
Software.md Normal file
View File

@ -0,0 +1,4 @@
[[Git_workflows]]
[[Python General]]
[[Embedded C]]
[[Fortran77]]

18
Standards.md Normal file
View File

@ -0,0 +1,18 @@
[[EN298]]
[[EN60730]]
[[EN61508]]
[[WG17_SIL_BURNER_STANDARDS_OVERVIEW]]
![[standards_mind_map-3.pdf]]
![[standards_mind_map 2.tex]]
---

6
Straight Line Motion.md Normal file
View File

@ -0,0 +1,6 @@
$$ S = ut + \frac{1}{2} a t ^2 $$
$$v=u + at $$
$$E=\frac{1}{2} m v ^2 $$
---

3
Transistors.md Normal file
View File

@ -0,0 +1,3 @@
[[Bipolar Junction Transistors]]
[[FETS]]
[[MOSFETS]]

Binary file not shown.

After

Width:  |  Height:  |  Size: 98 KiB

1
Unicycling.md Normal file
View File

@ -0,0 +1 @@
![[PXL_20241017_144621074.jpg_compressed.jpeg]]

0
Valves.md Normal file
View File

27
VaultMain.md Normal file
View File

@ -0,0 +1,27 @@
---
# Science Stuff
[[Electronics]]
[[Chemistry]]
[[Maths]]
[[Physics]]
[[Software]]
[[Biology]]
[[Standards]]
[[Conciouness]]
---
# Other Stuff
[[Clothing]]
[[Cycling]]
[[Juggling]]
[[Unicycling]]
[[Music]]
---

View File

@ -0,0 +1,4 @@
Found on facebook one day!
![[vec_calculus.jpg]]

7
Vector_Calculus.md Normal file
View File

@ -0,0 +1,7 @@
[[Posters]]
[[DIV]]
[[GRAD]]
[[CURL]]

View File

@ -0,0 +1,77 @@
For the case where a signal is required to settle before being sampled by an ADC.
For this example the aim will be the signal is 99% settled at time of ADC~sampling.
Starting first with with an RC low pass filter: signal to R, R to C, C to ground. The voltage into the capacitor is $dv_o/dt . RC$. Where $\tau = RC$:
$$\tau \frac{dv_0}{dt} +v_0 = vi \; .$$
Take Laplace transforms (zero initial condition, i.e. capacitor not charged):
$$\tau s V_o(1+s\tau)=V_i(s) \rightarrow H(s)=\frac{V_o(s)}{V_i(s)} = \frac{1}{1+s\tau}$$
Apply the step input; consider a switch going on, applying a constant voltage, the way an ADC signal could stabalise; so $$\frac{1}{s}$$$$H(s)V_i(s) = \frac{1}{1+s\tau} . \frac{1}{s} = \frac{1}{s(1+s\tau)}$$
## Partial Fractions
Use Partial fractions to break this equation up into parts that can be individually transformed back form Laplace to real~time.
Convert to partial fractions with A,B unknown:
$$\frac{1}{s(1+s\tau)}= \frac{A}{s} + \frac{B}{(1+s\tau)}$$
rearranging to solve quickly; set s = 0 to tease out $A$
$$1 = A(1+s\tau)+ Bs$$
Set s = 0 and this shows A=1 :
so knowing A is 1:
$$ 1 = 1(1+s\tau)+Bs$$
$$ 1 = 1 + s\tau + Bs $$
$$0 - s\tau = Bs $$
$$ B= -\tau $$
s=0 and A=1 B=$-\tau$ : the equation is now in a format where the parts can be individually converted back from the $s$ domain to real time.
$$\frac{1}{s(1+s\tau)}= \frac{1}{s} - \frac{\tau}{(1+s\tau)}$$
divide the last fraction by $\tau$ on both sides, i.e. $$ \frac{\tau}{1+s\tau} \equiv \frac{1}{1/\tau +s}$$$$\frac{1}{s(1+s\tau)}= \frac{1}{s} - \tau . \frac{1}{(s+1/\tau)}$$
## Inverse Laplace -- Back to reality!
Taking inverse Laplace transforms:
$$\mathcal{L}^{-1} \Big(\frac{1}{s}\Big) = 1 $$
$$ \mathcal{L}^{-1} \Big(\tau . \frac{1}{1/\tau +s}\Big) = \tau . \frac{1}{\tau}e^{-t/\tau}$$
Now the real~time response to the step function can be applied
$$ f(t) = 1 - e^{-t/\tau} $$
This is the RC filter step response.
## Percentage step function settled
Now the percentages for settling can be determined.
where say $e^{-t/\tau} = 0.9$ for instance would determine the 90% settled point.
$$ 0.9 = 1 - e^{-t/\tau} $$
$$0.1 = e^{-t/\tau}$$
Take logs
$$ln(0.1) = {-t}{\tau}$$
$$\tau = ln(0.1)/-t$$
## Plug in some component values as a `real' example
So $\tau= -ln(0.1) = 2.3$ for 90% settled. Putting some numbers in this were the settling time to be $250\mu s $ for 90% settling of the step function:-
$$ \tau = RC = \frac{-2.3}{250E-6}= 9.21E-3$$
So RC must be 9.21E-3: Taking R as 22k $RC=9.21\times 10^{-3}$
$$ C = \frac{9.21\times10^{-3}}{22 \times10^{3}}$$
So C = 419E-9 or $418pF$.
In other words, a simple low pass filter; 22k to 418pF to ground; will settle a step function to 90% from 0V within $250 \mu s$.
## Some handy setting $\tau$ figures
$$t_{63\%} = 1τ $$
$$t_{95\%} = 3τ $$
$$t_{99\%} = 4.6τ $$
$$t_{99.9\%} = 6.9τ $$
---

BIN
angular_momentum.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 166 KiB

402
bad.md Normal file
View File

@ -0,0 +1,402 @@
# Schrödinger Equation Derivation — Why the Kinetic Term is $\hbar^2/(2m)\,\nabla^2$
## Goal
Start from the **classical energy equation**
$$
E = \frac{p^2}{2m} + V
$$
and show how this becomes the **time-dependent Schrödinger equation**
$$
i\hbar \frac{\partial \psi}{\partial t}
=
-\frac{\hbar^2}{2m}\nabla^2\psi + V\psi
$$
---
## 1. Start with classical mechanics
For a non-relativistic particle, total energy is
$$
E = \frac{p^2}{2m} + V
$$
where:
- \(E\) = total energy
- \(p\) = momentum
- \(m\) = mass
- \(V\) = potential energy
The term
$$
\frac{p^2}{2m}
$$
is just the usual classical kinetic energy.
Since
$$
p = mv
$$
we have
$$
\frac{p^2}{2m} = \frac{m^2 v^2}{2m} = \frac{1}{2}mv^2
$$
So the mysterious **divide by \(2m\)** is simply inherited from the ordinary formula for kinetic energy.
---
## 2. Introduce a wave
Quantum mechanics uses a **wavefunction** \(\psi(x,t)\).
Take a simple plane wave in 1D:
$$
\psi(x,t) = e^{i(kx-\omega t)}
$$
This is useful because derivatives acting on exponentials bring down constants.
---
## 3. Differentiate with respect to position
First derivative:
$$
\frac{\partial \psi}{\partial x} = ik\psi
$$
Second derivative:
$$
\frac{\partial^2 \psi}{\partial x^2} = -k^2 \psi
$$
So the second derivative returns the same wave multiplied by \(-k^2\).
---
## 4. Relate \(k\) to momentum
From de Broglie:
$$
p = \hbar k
$$
so
$$
k = \frac{p}{\hbar}
$$
Substitute this into the second derivative result:
$$
\frac{\partial^2 \psi}{\partial x^2}
=
-\left(\frac{p}{\hbar}\right)^2 \psi
=
-\frac{p^2}{\hbar^2}\psi
$$
Rearrange:
$$
p^2 \psi = -\hbar^2 \frac{\partial^2 \psi}{\partial x^2}
$$
This is the key step:
> **Momentum squared acting on a wave becomes minus \(\hbar^2\) times the second derivative.**
So in operator form,
$$
\hat{p}^2 = -\hbar^2 \frac{\partial^2}{\partial x^2}
$$
and in 3D,
$$
\hat{p}^2 = -\hbar^2 \nabla^2
$$
---
## 5. Put that into the energy equation
Start from
$$
E = \frac{p^2}{2m} + V
$$
Multiply through by \(\psi\):
$$
E\psi = \frac{p^2}{2m}\psi + V\psi
$$
Now replace \(p^2\psi\) by the differential form:
$$
E\psi
=
\frac{1}{2m}\left(-\hbar^2 \frac{\partial^2 \psi}{\partial x^2}\right) + V\psi
$$
So:
$$
E\psi
=
-\frac{\hbar^2}{2m}\frac{\partial^2 \psi}{\partial x^2} + V\psi
$$
This is exactly where the factor
$$
-\frac{\hbar^2}{2m}
$$
comes from.
### Why the divide by \(2m\) stays there
Because the classical kinetic energy was already
$$
\frac{p^2}{2m}
$$
and the quantum substitution only changes **what \(p^2\) means**:
$$
p^2 \rightarrow -\hbar^2 \frac{\partial^2}{\partial x^2}
$$
It does **not** change the prefactor \(1/(2m)\).
So:
$$
\frac{p^2}{2m}
\rightarrow
\frac{1}{2m}\left(-\hbar^2 \frac{\partial^2}{\partial x^2}\right)
=
-\frac{\hbar^2}{2m}\frac{\partial^2}{\partial x^2}
$$
---
## 6. Replace energy by a time derivative
For a wave,
$$
\psi(x,t) = e^{i(kx-\omega t)}
$$
differentiate with respect to time:
$$
\frac{\partial \psi}{\partial t} = -i\omega \psi
$$
Multiply by \(i\hbar\):
$$
i\hbar \frac{\partial \psi}{\partial t}
=
i\hbar (-i\omega)\psi
=
\hbar\omega\psi
$$
But Planck says
$$
E = \hbar \omega
$$
so
$$
E\psi = i\hbar \frac{\partial \psi}{\partial t}
$$
Thus the energy operator is
$$
\hat{E} = i\hbar \frac{\partial}{\partial t}
$$
---
## 7. Substitute into the equation
We had
$$
E\psi
=
-\frac{\hbar^2}{2m}\frac{\partial^2 \psi}{\partial x^2}
+
V\psi
$$
Replace $E\psi$ with $i\hbar \partial \psi / \partial t$:
$$
i\hbar \frac{\partial \psi}{\partial t}
=
-\frac{\hbar^2}{2m}\frac{\partial^2 \psi}{\partial x^2}
+
V\psi
$$
This is the **1D time-dependent Schrödinger equation**.
In 3D it becomes
$$
i\hbar \frac{\partial \psi}{\partial t}
=
-\frac{\hbar^2}{2m}\nabla^2\psi + V\psi
$$
---
## 8. What the second derivative means physically
The second derivative measures **curvature** of the wavefunction.
- Gentle curvature -> long wavelength -> small \(k\) -> small momentum
- Rapid wiggles -> short wavelength -> large \(k\) -> large momentum
Since kinetic energy depends on \(p^2\), it makes sense that it is linked to a **second** derivative.
So the Laplacian term is really the quantum version of kinetic energy.
---
## 9. Compact operator summary
The classical energy equation is
$$
E = \frac{p^2}{2m} + V
$$
Quantum substitutions:
$$
E \rightarrow i\hbar \frac{\partial}{\partial t}
$$
$$
p \rightarrow -i\hbar \nabla
$$
Therefore:
$$
p^2 \rightarrow (-i\hbar \nabla)^2 = -\hbar^2 \nabla^2
$$
and so
$$
\frac{p^2}{2m}
\rightarrow
-\frac{\hbar^2}{2m}\nabla^2
$$
Hence:
$$
i\hbar \frac{\partial \psi}{\partial t}
=
-\frac{\hbar^2}{2m}\nabla^2\psi + V\psi
$$
---
## 10. Intuition in one sentence
The Schrödinger equation is basically the classical statement
$$
\text{Energy} = \text{kinetic} + \text{potential}
$$
rewritten so that **energy and momentum act as differential operators on a wavefunction**.
---
## 11. Tiny memory aid
A good way to remember the kinetic term is:
1. Classical kinetic energy is
$$
\frac{p^2}{2m}
$$
2. In quantum mechanics
$$
p \rightarrow -i\hbar \nabla
$$
3. Therefore
$$
\frac{p^2}{2m}
\rightarrow
\frac{(-i\hbar \nabla)^2}{2m}
=
-\frac{\hbar^2}{2m}\nabla^2
$$
That is the whole story.
---
## 12. One last link to \(F=ma\)
Newton's law tells you how **position** changes with time.
Schrödinger's equation tells you how the **wavefunction** changes with time.
So it is fair to think of it as the quantum analogue of a fundamental equation of motion — even though mathematically it comes more directly from the **energy equation** than from \(F=ma\).
---
## Possible next page
A natural next step is to derive the **time-independent Schrödinger equation**
$$
-\frac{\hbar^2}{2m}\nabla^2\phi + V\phi = E\phi
$$
by assuming
$$
\psi(x,t) = \phi(x)e^{-iEt/\hbar}
$$
which turns the problem into an eigenvalue equation.

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 KiB

1
buffs.md Normal file
View File

@ -0,0 +1 @@
![[buff-headwear.jpg_compressed.jpeg]]

107
butter_plot.py Normal file
View File

@ -0,0 +1,107 @@
#!/usr/bin/env python3
"""
2nd-order unity-gain Butterworth low-pass (Sallen-Key design) calculator + Bode plots.
- Computes R1=R2=R (user-chosen) and C1,C2 from TI normalized values:
C1n=1.414, C2n=0.707, with scaling C = Cn/(R*ω0), ω0=2πfc
- Plots magnitude (dB) and phase (deg) of the ideal 2nd-order Butterworth:
H(s) = ω0^2 / (s^2 + (ω0/Q)s + ω0^2), Q=1/2
Usage:
python3 butterworth_sallenkey_bode.py 10000 --R 10000
"""
import argparse
import math
import numpy as np
import matplotlib.pyplot as plt
C1N = 1.414
C2N = 0.707
Q_BUTTERWORTH = 1.0 / math.sqrt(2.0)
def format_si(x, unit=""):
if x == 0:
return f"0 {unit}".strip()
prefixes = [
(1e-12, "p"), (1e-9, "n"), (1e-6, "u"), (1e-3, "m"),
(1, ""), (1e3, "k"), (1e6, "M"), (1e9, "G")
]
ax = abs(x)
# choose prefix so scaled value is ~[1..1000)
best = min(prefixes, key=lambda p: abs(math.log10(ax/p[0])))
scale, pref = best
return f"{x/scale:.4g} {pref}{unit}".strip()
def butterworth_H(jw, w0, Q=Q_BUTTERWORTH):
# H(jw) = w0^2 / ( (jw)^2 + (w0/Q)*(jw) + w0^2 )
s = 1j * jw
return (w0**2) / (s**2 + (w0/Q)*s + w0**2)
def main():
ap = argparse.ArgumentParser(description="Butterworth Sallen-Key LPF (2nd order) calculator + Bode plotter.")
ap.add_argument("fc", type=float, help="Cutoff frequency (Hz), e.g. 10000")
ap.add_argument("--R", type=float, default=10_000.0, help="Choose R1=R2=R in ohms (default 10000)")
ap.add_argument("--fmin", type=float, default=None, help="Plot min frequency (Hz). Default fc/100")
ap.add_argument("--fmax", type=float, default=None, help="Plot max frequency (Hz). Default fc*100")
ap.add_argument("--points", type=int, default=2000, help="Number of frequency points (default 2000)")
ap.add_argument("--save", type=str, default=None, help="Save plot to PNG path instead of showing it")
args = ap.parse_args()
fc = args.fc
R = args.R
w0 = 2.0 * math.pi * fc
# Component calculation (ideal per TI normalized values)
C1 = C1N / (R * w0)
C2 = C2N / (R * w0)
print("2nd-order unity-gain Butterworth Sallen-Key LPF (ideal)")
print(f"fc = {format_si(fc, 'Hz')}")
print(f"R1=R2= {format_si(R, 'ohm')}")
print(f"C1 = {format_si(C1, 'F')} (norm 1.414)")
print(f"C2 = {format_si(C2, 'F')} (norm 0.707)")
print(f"Q = {Q_BUTTERWORTH:.6g}")
print()
# Frequency axis for Bode plot
fmin = args.fmin if args.fmin is not None else fc / 100.0
fmax = args.fmax if args.fmax is not None else fc * 100.0
if fmin <= 0:
fmin = fc / 100.0
f = np.logspace(np.log10(fmin), np.log10(fmax), args.points)
w = 2.0 * np.pi * f
H = butterworth_H(w, w0, Q_BUTTERWORTH)
mag_db = 20.0 * np.log10(np.abs(H))
phase_deg = np.unwrap(np.angle(H)) * 180.0 / np.pi
# Plot
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(9, 7), sharex=True)
ax1.semilogx(f, mag_db)
ax1.axvline(fc, linestyle="--", linewidth=1)
ax1.axhline(-3.0, linestyle="--", linewidth=1)
ax1.set_ylabel("Magnitude (dB)")
ax1.grid(True, which="both", linestyle=":")
ax2.semilogx(f, phase_deg)
ax2.axvline(fc, linestyle="--", linewidth=1)
ax2.set_ylabel("Phase (deg)")
ax2.set_xlabel("Frequency (Hz)")
ax2.grid(True, which="both", linestyle=":")
fig.suptitle(f"2nd-order Butterworth LPF (fc={fc:g} Hz, R={R:g} Ω)")
fig.tight_layout()
if args.save:
plt.savefig(args.save, dpi=200)
print(f"Saved plot to: {args.save}")
else:
plt.show()
if __name__ == "__main__":
main()

BIN
circle_of_fifths.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 153 KiB

71
fix_obsidian_links.py Normal file
View File

@ -0,0 +1,71 @@
#!/usr/bin/env python3
import re
from pathlib import Path
from urllib.parse import quote
root = Path(".").resolve()
def find_note(target):
"""Find target.md anywhere in the tree."""
target = target.strip()
target = target.split("#")[0].split("|")[0].strip()
if not target.endswith(".md"):
target += ".md"
matches = list(root.rglob(target))
if matches:
return matches[0]
return None
def convert_link(match, current_file):
raw = match.group(1).strip()
# Ignore embeds for now: ![[image.png]]
if raw.lower().endswith((".png", ".jpg", ".jpeg", ".gif", ".pdf")):
return match.group(0)
# Obsidian alias: [[PID|my PID note]]
if "|" in raw:
target, label = raw.split("|", 1)
label = label.strip()
else:
target = raw
label = raw.split("#")[0].strip()
# Obsidian heading link: [[PID#Some heading]]
if "#" in target:
filename, heading = target.split("#", 1)
anchor = "#" + quote(heading.strip().lower().replace(" ", "-"))
else:
filename = target
anchor = ""
found = find_note(filename)
if found:
rel = found.relative_to(current_file.parent.resolve())
link = quote(str(rel).replace("\\", "/"))
return f"[{label}]({link}{anchor})"
# Fallback: assume same directory
fallback = filename.strip()
if not fallback.endswith(".md"):
fallback += ".md"
fallback = quote(fallback)
return f"[{label}]({fallback}{anchor})"
for md in root.rglob("*.md"):
text = md.read_text(encoding="utf-8", errors="ignore")
# Convert [[...]] but not ![[...]]
new_text = re.sub(
r"(?<!!)\[\[([^\]]+)\]\]",
lambda m: convert_link(m, md),
text
)
if new_text != text:
md.write_text(new_text, encoding="utf-8")
print(f"fixed {md}")
print("Done.")

Binary file not shown.

After

Width:  |  Height:  |  Size: 707 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 707 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

0
mesh.md Normal file
View File

Binary file not shown.

BIN
pid.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

1
piezo amplifiers.md Normal file
View File

@ -0,0 +1 @@
![[SGTL5000_PIEZO_AMP.png]]

376
quat_gui 1.py Normal file
View File

@ -0,0 +1,376 @@
#!/usr/bin/env python3
"""
Quaternion GUI workbench + interactive 3D axes visualiser (NO normalisation).
- QA * QB is exactly ONE Hamilton product (no hidden extra maths)
- Plotting does NOT normalise the quaternion and does NOT do q*p*q̄ (no "two multiplies" for plotting)
- Still plots axes for "impure" cases, but overlays a warning on the graph
- Your rule: IMPURE if R >= 1e-6 (note: not abs(), exactly as stated)
- Shows a RED vector arrow for the vector part (i, j, k)
Dependencies:
python -m pip install numpy matplotlib
"""
import math
import tkinter as tk
from tkinter import ttk, messagebox
import numpy as np
import matplotlib
matplotlib.use("TkAgg")
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
from matplotlib.figure import Figure
EPS_IMPURE_R = 1e-6
EPS_NORM = 1e-12
class Quaternion:
__slots__ = ("w", "x", "y", "z")
def __init__(self, w: float, x: float, y: float, z: float):
self.w = float(w)
self.x = float(x)
self.y = float(y)
self.z = float(z)
def as_tuple(self):
return (self.w, self.x, self.y, self.z)
def norm2(self) -> float:
return self.w * self.w + self.x * self.x + self.y * self.y + self.z * self.z
def norm(self) -> float:
return math.sqrt(self.norm2())
def conjugate(self):
return Quaternion(self.w, -self.x, -self.y, -self.z)
def inverse(self):
n2 = self.norm2()
if n2 < EPS_NORM:
raise ZeroDivisionError("Quaternion norm is ~0; cannot invert.")
c = self.conjugate()
return Quaternion(c.w / n2, c.x / n2, c.y / n2, c.z / n2)
# "impure" if |R|>= 1e-6
def is_impure(self, eps_r=EPS_IMPURE_R) -> bool:
return self.w >= abs(eps_r)
def __add__(self, other):
return Quaternion(self.w + other.w, self.x + other.x, self.y + other.y, self.z + other.z)
def __sub__(self, other):
return Quaternion(self.w - other.w, self.x - other.x, self.y - other.y, self.z - other.z)
def __mul__(self, other):
# Hamilton product
w1, x1, y1, z1 = self.as_tuple()
w2, x2, y2, z2 = other.as_tuple()
return Quaternion(
w1 * w2 - x1 * x2 - y1 * y2 - z1 * z2,
w1 * x2 + x1 * w2 + y1 * z2 - z1 * y2,
w1 * y2 - x1 * z2 + y1 * w2 + z1 * x2,
w1 * z2 + x1 * y2 - y1 * x2 + z1 * w2,
)
def __truediv__(self, other):
return self * other.inverse()
def quat_to_matrix_no_normalise(q: Quaternion) -> np.ndarray:
"""
Standard quaternion->matrix formula, but DOES NOT normalise q.
If q is not unit, the resulting matrix will generally not be orthonormal.
That's useful here for visualising intermediates without 'helpful' coercion.
"""
w, x, y, z = q.w, q.x, q.y, q.z
r00 = 1.0 - 2.0 * (y * y + z * z)
r01 = 2.0 * (x * y - w * z)
r02 = 2.0 * (x * z + w * y)
r10 = 2.0 * (x * y + w * z)
r11 = 1.0 - 2.0 * (x * x + z * z)
r12 = 2.0 * (y * z - w * x)
r20 = 2.0 * (x * z - w * y)
r21 = 2.0 * (y * z + w * x)
r22 = 1.0 - 2.0 * (x * x + y * y)
return np.array([[r00, r01, r02],
[r10, r11, r12],
[r20, r21, r22]], dtype=float)
class App(tk.Tk):
def __init__(self):
super().__init__()
self.title("Quaternion Workbench + Axes Visualiser (raw quaternion)")
self.geometry("1180x700")
# QA, QB default to identity
self.qa_vars = [
tk.StringVar(value="1.0"),
tk.StringVar(value="0.0"),
tk.StringVar(value="0.0"),
tk.StringVar(value="0.0"),
]
self.qb_vars = [
tk.StringVar(value="1.0"),
tk.StringVar(value="0.0"),
tk.StringVar(value="0.0"),
tk.StringVar(value="0.0"),
]
self.qr_vars = [
tk.StringVar(value=""),
tk.StringVar(value=""),
tk.StringVar(value=""),
tk.StringVar(value=""),
]
self.status_var = tk.StringVar(value="Ready.")
self._build_ui()
self._build_plot()
self._update_plot_from_result(None)
# ---------------- UI ----------------
def _build_ui(self):
outer = ttk.Frame(self, padding=10)
outer.pack(fill="both", expand=True)
left = ttk.Frame(outer)
left.pack(side="left", fill="y", padx=(0, 12))
right = ttk.Frame(outer)
right.pack(side="right", fill="both", expand=True)
qa_frame = ttk.LabelFrame(left, text="Quaternion QA (R, i, j, k)", padding=10)
qb_frame = ttk.LabelFrame(left, text="Quaternion QB (R, i, j, k)", padding=10)
btn_frame = ttk.LabelFrame(left, text="Operations", padding=10)
qr_frame = ttk.LabelFrame(left, text="Result QR (R, i, j, k)", padding=10)
qa_frame.pack(fill="x", pady=(0, 10))
qb_frame.pack(fill="x", pady=(0, 10))
btn_frame.pack(fill="x", pady=(0, 10))
qr_frame.pack(fill="x", pady=(0, 10))
self._make_quat_row(qa_frame, self.qa_vars)
ttk.Button(qa_frame, text="Conjugate QA", command=self.on_conjugate_qa).grid(
row=2, column=0, columnspan=4, sticky="ew", pady=(8, 0)
)
self._make_quat_row(qb_frame, self.qb_vars)
self._make_quat_row(qr_frame, self.qr_vars, readonly=True)
ttk.Button(btn_frame, text="QA + QB", command=lambda: self.on_op("+")).grid(row=0, column=0, sticky="ew", padx=2, pady=2)
ttk.Button(btn_frame, text="QA - QB", command=lambda: self.on_op("-")).grid(row=0, column=1, sticky="ew", padx=2, pady=2)
ttk.Button(btn_frame, text="QA * QB", command=lambda: self.on_op("*")).grid(row=1, column=0, sticky="ew", padx=2, pady=2)
ttk.Button(btn_frame, text="QA / QB", command=lambda: self.on_op("/")).grid(row=1, column=1, sticky="ew", padx=2, pady=2)
ttk.Separator(btn_frame, orient="horizontal").grid(row=2, column=0, columnspan=2, sticky="ew", pady=(10, 10))
ttk.Button(btn_frame, text="Copy QR → QA", command=self.copy_qr_to_qa).grid(row=3, column=0, sticky="ew", padx=2, pady=2)
ttk.Button(btn_frame, text="Copy QR → QB", command=self.copy_qr_to_qb).grid(row=3, column=1, sticky="ew", padx=2, pady=2)
ttk.Button(btn_frame, text="Clear Result", command=self.clear_result).grid(row=4, column=0, columnspan=2, sticky="ew", padx=2, pady=(8, 2))
for c in range(2):
btn_frame.columnconfigure(c, weight=1)
status = ttk.Label(left, textvariable=self.status_var, wraplength=360, foreground="#444")
status.pack(fill="x", pady=(6, 0))
plot_frame = ttk.LabelFrame(
right,
text="3D View (interactive: drag to rotate, scroll to zoom)",
padding=8,
)
plot_frame.pack(fill="both", expand=True)
self.plot_frame = plot_frame
def _make_quat_row(self, parent, vars4, readonly=False):
labels = ["R", "i", "j", "k"]
for idx, lab in enumerate(labels):
ttk.Label(parent, text=lab).grid(row=0, column=idx, sticky="w")
for idx, var in enumerate(vars4):
ent = ttk.Entry(parent, textvariable=var, width=10)
if readonly:
ent.state(["readonly"])
ent.grid(row=1, column=idx, sticky="ew", padx=2)
parent.columnconfigure(idx, weight=1)
# ---------------- Plot ----------------
def _build_plot(self):
fig = Figure(figsize=(6.4, 5.4), dpi=100)
ax = fig.add_subplot(111, projection="3d")
self.fig = fig
self.ax = ax
canvas = FigureCanvasTkAgg(fig, master=self.plot_frame)
canvas.draw()
canvas.get_tk_widget().pack(fill="both", expand=True)
toolbar = NavigationToolbar2Tk(canvas, self.plot_frame)
toolbar.update()
self.canvas = canvas
def _draw_axes(self, ax, origin, basis, label_prefix="A", alpha=1.0):
o = origin
for idx, name in enumerate(["x", "y", "z"]):
d = basis[:, idx]
ax.quiver(o[0], o[1], o[2], d[0], d[1], d[2], length=1.0, normalize=True, alpha=alpha)
tip = o + d
ax.text(tip[0], tip[1], tip[2], f"{label_prefix}{name}", alpha=alpha)
def _finalise_axes(self, ax):
ax.set_xlim(-1.2, 1.2)
ax.set_ylim(-1.2, 1.2)
ax.set_zlim(-1.2, 1.2)
ax.set_xlabel("X")
ax.set_ylabel("Y")
ax.set_zlabel("Z")
ax.view_init(elev=20, azim=35)
def _update_plot_from_result(self, q: Quaternion | None):
"""
Plotting rules:
- DO NOT normalise q for plotting
- DO NOT do q*p*q̄ (no quaternion multiplies needed for the plot)
- Always draw R axes, even in 'impure' cases
- Overlay warning when (rule) R >= 1e-6
"""
ax = self.ax
ax.clear()
# World axes
self._draw_axes(ax, origin=np.zeros(3), basis=np.eye(3), label_prefix="W", alpha=0.25)
if q is None:
ax.set_title("No result quaternion yet")
self._finalise_axes(ax)
self.canvas.draw()
return
# RED vector arrow for vector part (i, j, k)
v = np.array([q.x, q.y, q.z], dtype=float)
if float(np.linalg.norm(v)) > 0:
ax.quiver(
0, 0, 0,
v[0], v[1], v[2],
length=1.0,
#normalize=True,
normalize=False,
alpha=0.95,
color="red",
)
ax.text(v[0], v[1], v[2], "v=(i,j,k)", alpha=0.95)
else:
ax.text(0, 0, 0, "v=(0,0,0)", alpha=0.95)
# Degenerate quaternion (can't form meaningful axes)
if q.norm() < EPS_NORM:
ax.text2D(0.03, 0.95, "⚠ Quaternion norm ~0 — cannot show axes", transform=ax.transAxes)
ax.set_title("Degenerate quaternion")
self._finalise_axes(ax)
self.canvas.draw()
return
# Result axes from raw quaternion -> matrix (no normalisation)
Rm = quat_to_matrix_no_normalise(q)
basis = np.column_stack([Rm[:, 0], Rm[:, 1], Rm[:, 2]])
self._draw_axes(ax, origin=np.zeros(3), basis=basis, label_prefix="R", alpha=0.9)
# Warning overlay per your rule: impure if R >= 1e-6
if q.is_impure(EPS_IMPURE_R):
ax.text2D(
0.03, 0.95,
"⚠ IMPURE (rule: |R| ≥ 1e-6)\nAxes drawn from RAW quaternion (no normalisation)",
transform=ax.transAxes
)
ax.set_title("Result axes + IMPURE warning")
else:
ax.set_title("Result axes (raw quaternion; no normalisation)")
self._finalise_axes(ax)
self.canvas.draw()
# ---------------- Actions ----------------
def parse_quat(self, vars4, name: str) -> Quaternion:
try:
vals = [float(v.get().strip()) for v in vars4]
return Quaternion(*vals)
except ValueError:
raise ValueError(f"{name}: please enter numeric values for R, i, j, k.")
def set_result(self, q: Quaternion):
for var, val in zip(self.qr_vars, q.as_tuple()):
var.set(f"{val:.12g}")
self._update_plot_from_result(q)
def clear_result(self):
for var in self.qr_vars:
var.set("")
self.status_var.set("Ready.")
self._update_plot_from_result(None)
def copy_qr_to_qa(self):
if not self.qr_vars[0].get().strip():
return
for src, dst in zip(self.qr_vars, self.qa_vars):
dst.set(src.get())
self.status_var.set("Copied QR → QA")
def copy_qr_to_qb(self):
if not self.qr_vars[0].get().strip():
return
for src, dst in zip(self.qr_vars, self.qb_vars):
dst.set(src.get())
self.status_var.set("Copied QR → QB")
def on_conjugate_qa(self):
try:
qa = self.parse_quat(self.qa_vars, "QA")
qc = qa.conjugate()
for var, val in zip(self.qa_vars, qc.as_tuple()):
var.set(f"{val:.12g}")
self.status_var.set("QA conjugated.")
except Exception as e:
messagebox.showerror("Error", str(e))
def on_op(self, op: str):
try:
qa = self.parse_quat(self.qa_vars, "QA")
qb = self.parse_quat(self.qb_vars, "QB")
if op == "+":
qr = qa + qb
elif op == "-":
qr = qa - qb
elif op == "*":
qr = qa * qb
elif op == "/":
qr = qa / qb
else:
raise ValueError("Unknown operation")
self.set_result(qr)
self.status_var.set(f"Computed QR = QA {op} QB")
except Exception as e:
messagebox.showerror("Error", str(e))
if __name__ == "__main__":
App().mainloop()

376
quat_gui.py Normal file
View File

@ -0,0 +1,376 @@
#!/usr/bin/env python3
"""
Quaternion GUI workbench + interactive 3D axes visualiser (NO normalisation).
- QA * QB is exactly ONE Hamilton product (no hidden extra maths)
- Plotting does NOT normalise the quaternion and does NOT do q*p*q̄ (no "two multiplies" for plotting)
- Still plots axes for "impure" cases, but overlays a warning on the graph
- Your rule: IMPURE if R >= 1e-6 (note: not abs(), exactly as stated)
- Shows a RED vector arrow for the vector part (i, j, k)
Dependencies:
python -m pip install numpy matplotlib
"""
import math
import tkinter as tk
from tkinter import ttk, messagebox
import numpy as np
import matplotlib
matplotlib.use("TkAgg")
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
from matplotlib.figure import Figure
EPS_IMPURE_R = 1e-6
EPS_NORM = 1e-12
class Quaternion:
__slots__ = ("w", "x", "y", "z")
def __init__(self, w: float, x: float, y: float, z: float):
self.w = float(w)
self.x = float(x)
self.y = float(y)
self.z = float(z)
def as_tuple(self):
return (self.w, self.x, self.y, self.z)
def norm2(self) -> float:
return self.w * self.w + self.x * self.x + self.y * self.y + self.z * self.z
def norm(self) -> float:
return math.sqrt(self.norm2())
def conjugate(self):
return Quaternion(self.w, -self.x, -self.y, -self.z)
def inverse(self):
n2 = self.norm2()
if n2 < EPS_NORM:
raise ZeroDivisionError("Quaternion norm is ~0; cannot invert.")
c = self.conjugate()
return Quaternion(c.w / n2, c.x / n2, c.y / n2, c.z / n2)
# "impure" if |R|>= 1e-6
def is_impure(self, eps_r=EPS_IMPURE_R) -> bool:
return self.w >= abs(eps_r)
def __add__(self, other):
return Quaternion(self.w + other.w, self.x + other.x, self.y + other.y, self.z + other.z)
def __sub__(self, other):
return Quaternion(self.w - other.w, self.x - other.x, self.y - other.y, self.z - other.z)
def __mul__(self, other):
# Hamilton product
w1, x1, y1, z1 = self.as_tuple()
w2, x2, y2, z2 = other.as_tuple()
return Quaternion(
w1 * w2 - x1 * x2 - y1 * y2 - z1 * z2,
w1 * x2 + x1 * w2 + y1 * z2 - z1 * y2,
w1 * y2 - x1 * z2 + y1 * w2 + z1 * x2,
w1 * z2 + x1 * y2 - y1 * x2 + z1 * w2,
)
def __truediv__(self, other):
return self * other.inverse()
def quat_to_matrix_no_normalise(q: Quaternion) -> np.ndarray:
"""
Standard quaternion->matrix formula, but DOES NOT normalise q.
If q is not unit, the resulting matrix will generally not be orthonormal.
That's useful here for visualising intermediates without 'helpful' coercion.
"""
w, x, y, z = q.w, q.x, q.y, q.z
r00 = 1.0 - 2.0 * (y * y + z * z)
r01 = 2.0 * (x * y - w * z)
r02 = 2.0 * (x * z + w * y)
r10 = 2.0 * (x * y + w * z)
r11 = 1.0 - 2.0 * (x * x + z * z)
r12 = 2.0 * (y * z - w * x)
r20 = 2.0 * (x * z - w * y)
r21 = 2.0 * (y * z + w * x)
r22 = 1.0 - 2.0 * (x * x + y * y)
return np.array([[r00, r01, r02],
[r10, r11, r12],
[r20, r21, r22]], dtype=float)
class App(tk.Tk):
def __init__(self):
super().__init__()
self.title("Quaternion Workbench + Axes Visualiser (raw quaternion)")
self.geometry("1180x700")
# QA, QB default to identity
self.qa_vars = [
tk.StringVar(value="1.0"),
tk.StringVar(value="0.0"),
tk.StringVar(value="0.0"),
tk.StringVar(value="0.0"),
]
self.qb_vars = [
tk.StringVar(value="1.0"),
tk.StringVar(value="0.0"),
tk.StringVar(value="0.0"),
tk.StringVar(value="0.0"),
]
self.qr_vars = [
tk.StringVar(value=""),
tk.StringVar(value=""),
tk.StringVar(value=""),
tk.StringVar(value=""),
]
self.status_var = tk.StringVar(value="Ready.")
self._build_ui()
self._build_plot()
self._update_plot_from_result(None)
# ---------------- UI ----------------
def _build_ui(self):
outer = ttk.Frame(self, padding=10)
outer.pack(fill="both", expand=True)
left = ttk.Frame(outer)
left.pack(side="left", fill="y", padx=(0, 12))
right = ttk.Frame(outer)
right.pack(side="right", fill="both", expand=True)
qa_frame = ttk.LabelFrame(left, text="Quaternion QA (R, i, j, k)", padding=10)
qb_frame = ttk.LabelFrame(left, text="Quaternion QB (R, i, j, k)", padding=10)
btn_frame = ttk.LabelFrame(left, text="Operations", padding=10)
qr_frame = ttk.LabelFrame(left, text="Result QR (R, i, j, k)", padding=10)
qa_frame.pack(fill="x", pady=(0, 10))
qb_frame.pack(fill="x", pady=(0, 10))
btn_frame.pack(fill="x", pady=(0, 10))
qr_frame.pack(fill="x", pady=(0, 10))
self._make_quat_row(qa_frame, self.qa_vars)
ttk.Button(qa_frame, text="Conjugate QA", command=self.on_conjugate_qa).grid(
row=2, column=0, columnspan=4, sticky="ew", pady=(8, 0)
)
self._make_quat_row(qb_frame, self.qb_vars)
self._make_quat_row(qr_frame, self.qr_vars, readonly=True)
ttk.Button(btn_frame, text="QA + QB", command=lambda: self.on_op("+")).grid(row=0, column=0, sticky="ew", padx=2, pady=2)
ttk.Button(btn_frame, text="QA - QB", command=lambda: self.on_op("-")).grid(row=0, column=1, sticky="ew", padx=2, pady=2)
ttk.Button(btn_frame, text="QA * QB", command=lambda: self.on_op("*")).grid(row=1, column=0, sticky="ew", padx=2, pady=2)
ttk.Button(btn_frame, text="QA / QB", command=lambda: self.on_op("/")).grid(row=1, column=1, sticky="ew", padx=2, pady=2)
ttk.Separator(btn_frame, orient="horizontal").grid(row=2, column=0, columnspan=2, sticky="ew", pady=(10, 10))
ttk.Button(btn_frame, text="Copy QR → QA", command=self.copy_qr_to_qa).grid(row=3, column=0, sticky="ew", padx=2, pady=2)
ttk.Button(btn_frame, text="Copy QR → QB", command=self.copy_qr_to_qb).grid(row=3, column=1, sticky="ew", padx=2, pady=2)
ttk.Button(btn_frame, text="Clear Result", command=self.clear_result).grid(row=4, column=0, columnspan=2, sticky="ew", padx=2, pady=(8, 2))
for c in range(2):
btn_frame.columnconfigure(c, weight=1)
status = ttk.Label(left, textvariable=self.status_var, wraplength=360, foreground="#444")
status.pack(fill="x", pady=(6, 0))
plot_frame = ttk.LabelFrame(
right,
text="3D View (interactive: drag to rotate, scroll to zoom)",
padding=8,
)
plot_frame.pack(fill="both", expand=True)
self.plot_frame = plot_frame
def _make_quat_row(self, parent, vars4, readonly=False):
labels = ["R", "i", "j", "k"]
for idx, lab in enumerate(labels):
ttk.Label(parent, text=lab).grid(row=0, column=idx, sticky="w")
for idx, var in enumerate(vars4):
ent = ttk.Entry(parent, textvariable=var, width=10)
if readonly:
ent.state(["readonly"])
ent.grid(row=1, column=idx, sticky="ew", padx=2)
parent.columnconfigure(idx, weight=1)
# ---------------- Plot ----------------
def _build_plot(self):
fig = Figure(figsize=(6.4, 5.4), dpi=100)
ax = fig.add_subplot(111, projection="3d")
self.fig = fig
self.ax = ax
canvas = FigureCanvasTkAgg(fig, master=self.plot_frame)
canvas.draw()
canvas.get_tk_widget().pack(fill="both", expand=True)
toolbar = NavigationToolbar2Tk(canvas, self.plot_frame)
toolbar.update()
self.canvas = canvas
def _draw_axes(self, ax, origin, basis, label_prefix="A", alpha=1.0):
o = origin
for idx, name in enumerate(["x", "y", "z"]):
d = basis[:, idx]
ax.quiver(o[0], o[1], o[2], d[0], d[1], d[2], length=1.0, normalize=True, alpha=alpha)
tip = o + d
ax.text(tip[0], tip[1], tip[2], f"{label_prefix}{name}", alpha=alpha)
def _finalise_axes(self, ax):
ax.set_xlim(-1.2, 1.2)
ax.set_ylim(-1.2, 1.2)
ax.set_zlim(-1.2, 1.2)
ax.set_xlabel("X")
ax.set_ylabel("Y")
ax.set_zlabel("Z")
ax.view_init(elev=20, azim=35)
def _update_plot_from_result(self, q: Quaternion | None):
"""
Plotting rules:
- DO NOT normalise q for plotting
- DO NOT do q*p*q̄ (no quaternion multiplies needed for the plot)
- Always draw R axes, even in 'impure' cases
- Overlay warning when (rule) R >= 1e-6
"""
ax = self.ax
ax.clear()
# World axes
self._draw_axes(ax, origin=np.zeros(3), basis=np.eye(3), label_prefix="W", alpha=0.25)
if q is None:
ax.set_title("No result quaternion yet")
self._finalise_axes(ax)
self.canvas.draw()
return
# RED vector arrow for vector part (i, j, k)
v = np.array([q.x, q.y, q.z], dtype=float)
if float(np.linalg.norm(v)) > 0:
ax.quiver(
0, 0, 0,
v[0], v[1], v[2],
length=1.0,
#normalize=True,
normalize=False,
alpha=0.95,
color="red",
)
ax.text(v[0], v[1], v[2], "v=(i,j,k)", alpha=0.95)
else:
ax.text(0, 0, 0, "v=(0,0,0)", alpha=0.95)
# Degenerate quaternion (can't form meaningful axes)
if q.norm() < EPS_NORM:
ax.text2D(0.03, 0.95, "⚠ Quaternion norm ~0 — cannot show axes", transform=ax.transAxes)
ax.set_title("Degenerate quaternion")
self._finalise_axes(ax)
self.canvas.draw()
return
# Result axes from raw quaternion -> matrix (no normalisation)
Rm = quat_to_matrix_no_normalise(q)
basis = np.column_stack([Rm[:, 0], Rm[:, 1], Rm[:, 2]])
self._draw_axes(ax, origin=np.zeros(3), basis=basis, label_prefix="R", alpha=0.9)
# Warning overlay per your rule: impure if R >= 1e-6
if q.is_impure(EPS_IMPURE_R):
ax.text2D(
0.03, 0.95,
"⚠ IMPURE (rule: |R| ≥ 1e-6)\nAxes drawn from RAW quaternion (no normalisation)",
transform=ax.transAxes
)
ax.set_title("Result axes + IMPURE warning")
else:
ax.set_title("Result axes (raw quaternion; no normalisation)")
self._finalise_axes(ax)
self.canvas.draw()
# ---------------- Actions ----------------
def parse_quat(self, vars4, name: str) -> Quaternion:
try:
vals = [float(v.get().strip()) for v in vars4]
return Quaternion(*vals)
except ValueError:
raise ValueError(f"{name}: please enter numeric values for R, i, j, k.")
def set_result(self, q: Quaternion):
for var, val in zip(self.qr_vars, q.as_tuple()):
var.set(f"{val:.12g}")
self._update_plot_from_result(q)
def clear_result(self):
for var in self.qr_vars:
var.set("")
self.status_var.set("Ready.")
self._update_plot_from_result(None)
def copy_qr_to_qa(self):
if not self.qr_vars[0].get().strip():
return
for src, dst in zip(self.qr_vars, self.qa_vars):
dst.set(src.get())
self.status_var.set("Copied QR → QA")
def copy_qr_to_qb(self):
if not self.qr_vars[0].get().strip():
return
for src, dst in zip(self.qr_vars, self.qb_vars):
dst.set(src.get())
self.status_var.set("Copied QR → QB")
def on_conjugate_qa(self):
try:
qa = self.parse_quat(self.qa_vars, "QA")
qc = qa.conjugate()
for var, val in zip(self.qa_vars, qc.as_tuple()):
var.set(f"{val:.12g}")
self.status_var.set("QA conjugated.")
except Exception as e:
messagebox.showerror("Error", str(e))
def on_op(self, op: str):
try:
qa = self.parse_quat(self.qa_vars, "QA")
qb = self.parse_quat(self.qb_vars, "QB")
if op == "+":
qr = qa + qb
elif op == "-":
qr = qa - qb
elif op == "*":
qr = qa * qb
elif op == "/":
qr = qa / qb
else:
raise ValueError("Unknown operation")
self.set_result(qr)
self.status_var.set(f"Computed QR = QA {op} QB")
except Exception as e:
messagebox.showerror("Error", str(e))
if __name__ == "__main__":
App().mainloop()

140
sallen_general.py Normal file
View File

@ -0,0 +1,140 @@
#!/usr/bin/env python3
"""
Sallen-Key low-pass: plot magnitude + phase from actual R/C values,
and optionally do Monte-Carlo tolerance sweeps to see "wonkiness".
Model (standard Sallen-Key LPF, non-inverting gain K):
H(s) = K / ( s^2*R1*R2*C1*C2 + s*(R1*C1 + (R1+R2)*C2 - K*R1*C2) + 1 )
Usage examples:
python3 sallen_key_plot.py --R1 22000 --R2 22000 --C1 22e-9 --C2 10e-9
python3 sallen_key_plot.py --R1 22k --R2 22k --C1 22n --C2 10n --K 1.0 --fc_guess 700
python3 sallen_key_plot.py --R1 22k --R2 22k --C1 22n --C2 10n --mc 200 --tolR 0.01 --tolC 0.05
Notes:
- Needs numpy + matplotlib. On Ubuntu: sudo apt install python3-numpy python3-matplotlib
"""
import argparse
import math
import re
import numpy as np
import matplotlib.pyplot as plt
SI = {
"p": 1e-12, "n": 1e-9, "u": 1e-6, "µ": 1e-6, "m": 1e-3,
"k": 1e3, "K": 1e3, "M": 1e6, "G": 1e9,
}
def parse_si(s: str) -> float:
"""Parse numbers like '22k', '10n', '1.5M', '22e-9'."""
s = s.strip()
# plain float
try:
return float(s)
except ValueError:
pass
m = re.fullmatch(r"([0-9]*\.?[0-9]+)\s*([pnumµmkKMG])", s)
if not m:
raise ValueError(f"Can't parse value '{s}'. Use e.g. 22000, 22k, 10n, 22e-9")
val = float(m.group(1))
suf = m.group(2)
return val * SI[suf]
def H_sallen_key(jw: np.ndarray, R1: float, R2: float, C1: float, C2: float, K: float) -> np.ndarray:
s = 1j * jw
a2 = R1 * R2 * C1 * C2
a1 = (R1 * C1) + ((R1 + R2) * C2) - (K * R1 * C2)
den = (a2 * s * s) + (a1 * s) + 1.0
return K / den
def estimate_fc(R1, R2, C1, C2) -> float:
"""Rough natural frequency estimate for guidance (not exact fc at -3 dB)."""
w0 = 1.0 / math.sqrt(R1 * R2 * C1 * C2)
return w0 / (2.0 * math.pi)
def main():
ap = argparse.ArgumentParser(description="Sallen-Key LPF plotter from actual R/C values (+ Monte-Carlo tolerances).")
ap.add_argument("--R1", required=True, type=str, help="Ohms (e.g. 22000 or 22k)")
ap.add_argument("--R2", required=True, type=str, help="Ohms (e.g. 22000 or 22k)")
ap.add_argument("--C1", required=True, type=str, help="Farads (e.g. 22e-9 or 22n)")
ap.add_argument("--C2", required=True, type=str, help="Farads (e.g. 10e-9 or 10n)")
ap.add_argument("--K", default="1.0", type=str, help="Non-inverting gain (default 1.0)")
ap.add_argument("--fmin", type=float, default=None, help="Plot min freq Hz (default: fc_est/100)")
ap.add_argument("--fmax", type=float, default=None, help="Plot max freq Hz (default: fc_est*100)")
ap.add_argument("--points", type=int, default=2000, help="Plot points (default 2000)")
ap.add_argument("--mc", type=int, default=0, help="Monte-Carlo runs (default 0)")
ap.add_argument("--tolR", type=float, default=0.0, help="R tolerance as fraction (e.g. 0.01 for 1%%)")
ap.add_argument("--tolC", type=float, default=0.0, help="C tolerance as fraction (e.g. 0.05 for 5%%)")
ap.add_argument("--seed", type=int, default=None, help="Random seed for Monte-Carlo")
ap.add_argument("--save", type=str, default=None, help="Save PNG to this path instead of showing")
args = ap.parse_args()
R1 = parse_si(args.R1)
R2 = parse_si(args.R2)
C1 = parse_si(args.C1)
C2 = parse_si(args.C2)
K = float(parse_si(args.K))
fc_est = estimate_fc(R1, R2, C1, C2)
fmin = args.fmin if args.fmin is not None else max(fc_est / 100.0, 0.1)
fmax = args.fmax if args.fmax is not None else fc_est * 100.0
f = np.logspace(np.log10(fmin), np.log10(fmax), args.points)
w = 2.0 * np.pi * f
# Nominal response
H0 = H_sallen_key(w, R1, R2, C1, C2, K)
mag0 = 20.0 * np.log10(np.abs(H0))
ph0 = np.unwrap(np.angle(H0)) * 180.0 / np.pi
# Figure
fig, (axm, axp) = plt.subplots(2, 1, figsize=(10, 7), sharex=True)
# Monte-Carlo sweeps (optional)
if args.mc and (args.tolR > 0 or args.tolC > 0):
rng = np.random.default_rng(args.seed)
for _ in range(args.mc):
# uniform tolerance: value*(1 + u), u in [-tol, +tol]
r1 = R1 * (1.0 + rng.uniform(-args.tolR, args.tolR))
r2 = R2 * (1.0 + rng.uniform(-args.tolR, args.tolR))
c1 = C1 * (1.0 + rng.uniform(-args.tolC, args.tolC))
c2 = C2 * (1.0 + rng.uniform(-args.tolC, args.tolC))
Hi = H_sallen_key(w, r1, r2, c1, c2, K)
axm.semilogx(f, 20.0*np.log10(np.abs(Hi)), linewidth=0.8, alpha=0.15)
axp.semilogx(f, np.unwrap(np.angle(Hi))*180.0/np.pi, linewidth=0.8, alpha=0.15)
# Nominal on top
axm.semilogx(f, mag0, linewidth=2.0)
axp.semilogx(f, ph0, linewidth=2.0)
axm.set_ylabel("Magnitude (dB)")
axp.set_ylabel("Phase (deg)")
axp.set_xlabel("Frequency (Hz)")
axm.grid(True, which="both", linestyle=":")
axp.grid(True, which="both", linestyle=":")
title = (
f"Sallen-Key LPF | R1={R1:g}Ω R2={R2:g}Ω C1={C1:g}F C2={C2:g}F K={K:g}\n"
f"w0 est: {2*math.pi*fc_est:.3g} rad/s, f0 est: {fc_est:.3g} Hz"
)
if args.mc and (args.tolR > 0 or args.tolC > 0):
title += f" | Monte-Carlo: {args.mc} runs (tolR={args.tolR:.3g}, tolC={args.tolC:.3g})"
fig.suptitle(title)
fig.tight_layout()
if args.save:
plt.savefig(args.save, dpi=200)
print(f"Saved plot to {args.save}")
else:
plt.show()
if __name__ == "__main__":
main()

BIN
sboa226.pdf Normal file

Binary file not shown.

1
ti_SBOA226.md Normal file
View File

@ -0,0 +1 @@
![[sboa226.pdf]]

BIN
transistors.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 409 KiB

BIN
vec_calculus.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 530 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 512 KiB