initial escape from OBSIDIAN
19
Angular Momentum.md
Normal 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
@ -0,0 +1 @@
|
||||
[[Human Biology]]
|
||||
1
Bipolar Junction Transistors.md
Normal file
@ -0,0 +1 @@
|
||||
![[transistors.jpg]]
|
||||
7
ButterworthLowPass.md
Normal 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
@ -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.
|
||||
198
CartesianCoordinateSystem.svg
Normal 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 |
95
CartesianCoordinateSystem3D.svg
Normal 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
@ -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 radical–radical 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 (~2–5 eV)
|
||||
|
||||
- Good overlap between reaction geometry and excited state (Franck–Condon 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
@ -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 radical–radical 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 (~2–5 eV)
|
||||
|
||||
- Good overlap between reaction geometry and excited state (Franck–Condon 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
@ -0,0 +1 @@
|
||||
[[buffs]]
|
||||
25
Code for Butterworth Low Pass Design.md
Normal 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
@ -0,0 +1,4 @@
|
||||
[[PID]]
|
||||
## Feedback and Control Systems Book
|
||||
|
||||
![[Feedback Control of Dynamic Systems 7th Franklin [Text].pdf]]
|
||||
1
Cycling.md
Normal file
@ -0,0 +1 @@
|
||||
![[IMG_0038.JPG_compressed.jpeg]]
|
||||
97
DIV.md
Normal 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
@ -0,0 +1 @@
|
||||
![[De_Broglie_Kracklauer.pdf]]
|
||||
BIN
De_Broglie_Kracklauer.pdf
Normal file
139
EN61508.md
Normal 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
|
||||
5–7. 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
@ -0,0 +1,12 @@
|
||||
|
||||
[[Filters]]
|
||||
[[mesh]]
|
||||
[[ADCs]]
|
||||
[[Transistors]]
|
||||
[[Valves]]
|
||||
[[Optics]]
|
||||
[[CANbus]]
|
||||
[[Control Engineering]]
|
||||
[[Peak Detector]]
|
||||
|
||||
[[piezo amplifiers]]
|
||||
BIN
FB_IMG_1771442819534.jpg
Normal file
|
After Width: | Height: | Size: 77 KiB |
BIN
Feedback Control of Dynamic Systems 7th Franklin [Text].pdf
Normal file
5
Filters.md
Normal file
@ -0,0 +1,5 @@
|
||||
See Analog Filter Design by Valkenburg ISBN:4-8338-0091-3
|
||||
|
||||
[[Simple RC low pass filter]]
|
||||
[[SingleOpampCap]]
|
||||
[[Sallen Key]]
|
||||
BIN
FiveBallEx_PXL_20260406_153419214.mp4
Normal file
6
General purpose python analyser.md
Normal 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
@ -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
@ -0,0 +1,3 @@
|
||||
|
||||
![[metabolic_pathways_poster.pdf]]
|
||||
|
||||
BIN
IMG_0038.JPG_compressed.jpeg
Normal file
|
After Width: | Height: | Size: 690 KiB |
4
Juggling.md
Normal file
@ -0,0 +1,4 @@
|
||||
![[imgp3389_20071053719_o.jpg_compressed 1.jpeg]]
|
||||
|
||||
|
||||
[[Five Ball Exercises]]
|
||||
13
Laplace Transforms.md
Normal 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
@ -0,0 +1,8 @@
|
||||
[[Quaternions]]
|
||||
[[Vector_Calculus]]
|
||||
[[Eigen_values_vectors_states]]
|
||||
[[Laplacian]]
|
||||
[[Fourier Transforms]]
|
||||
[[Laplace Transforms]]
|
||||
[[Calculus]]
|
||||
[[Trigonometry]]
|
||||
BIN
NONINVLP_OPAMP_BUFFER.jpg
Normal file
|
After Width: | Height: | Size: 371 KiB |
4
Optics.md
Normal file
@ -0,0 +1,4 @@
|
||||
[[Photo Diode Amplifier]]
|
||||
[[Phototransistor Amplifier]]
|
||||
|
||||
.
|
||||
26
PID.md
Normal 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 controller’s 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 error’s 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.
|
||||
|
||||
---
|
||||
BIN
PXL_20241017_144621074.jpg_compressed.jpeg
Normal file
|
After Width: | Height: | Size: 776 KiB |
BIN
PXL_20260406_153419214.mp4
Normal file
0
Peak Detector.md
Normal file
3
Photo Diode Amplifier.md
Normal 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!)
|
||||
4
Phototransistor Amplifier.md
Normal 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
@ -0,0 +1,10 @@
|
||||
|
||||
|
||||
|
||||
|
||||
[[ Schrodinger explained]]
|
||||
[[DeBroglie PhD]]
|
||||
|
||||
[[Ideas]]
|
||||
|
||||
[[Complex_probabilities]]
|
||||
3
Posters.md
Normal file
@ -0,0 +1,3 @@
|
||||
![[vec_calculus.jpg_compressed.jpeg]]
|
||||
![[FB_IMG_1771442819534.jpg]]
|
||||
|
||||
86
QM Kinetic energy.md
Normal 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 particle’s motion is encoded in the **spatial variation of the wave~function’s 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.
|
||||
|
||||
---
|
||||
146
Quantum Phase Corkscrew.md
Normal 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**.
|
||||
|
||||
---
|
||||
|
||||
## One‑line 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
@ -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
|
After Width: | Height: | Size: 106 KiB |
4
Sallen Key.md
Normal file
@ -0,0 +1,4 @@
|
||||
|
||||
[[ButterworthLowPass]]
|
||||
|
||||
[[General purpose python analyser]]
|
||||
292
Schrodinger explained.md
Normal 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 time‑dependent 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
@ -0,0 +1 @@
|
||||
![[Schrödinger_Equation]]
|
||||
BIN
Screenshot from 2026-02-18 13-17-53.png
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
Screenshot from 2026-02-24 14-53-34.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
22
Simple RC low pass filter.md
Normal 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
@ -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
@ -0,0 +1,4 @@
|
||||
[[Git_workflows]]
|
||||
[[Python General]]
|
||||
[[Embedded C]]
|
||||
[[Fortran77]]
|
||||
18
Standards.md
Normal 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
@ -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
@ -0,0 +1,3 @@
|
||||
[[Bipolar Junction Transistors]]
|
||||
[[FETS]]
|
||||
[[MOSFETS]]
|
||||
BIN
UV_Diode_amplifier_two_stage.png
Normal file
|
After Width: | Height: | Size: 98 KiB |
1
Unicycling.md
Normal file
@ -0,0 +1 @@
|
||||
![[PXL_20241017_144621074.jpg_compressed.jpeg]]
|
||||
27
VaultMain.md
Normal file
@ -0,0 +1,27 @@
|
||||
|
||||
---
|
||||
|
||||
# Science Stuff
|
||||
|
||||
[[Electronics]]
|
||||
[[Chemistry]]
|
||||
[[Maths]]
|
||||
[[Physics]]
|
||||
[[Software]]
|
||||
[[Biology]]
|
||||
[[Standards]]
|
||||
[[Conciouness]]
|
||||
|
||||
---
|
||||
|
||||
|
||||
# Other Stuff
|
||||
|
||||
[[Clothing]]
|
||||
[[Cycling]]
|
||||
[[Juggling]]
|
||||
[[Unicycling]]
|
||||
[[Music]]
|
||||
|
||||
|
||||
---
|
||||
4
VectorCalculus fb poster.md
Normal file
@ -0,0 +1,4 @@
|
||||
|
||||
Found on facebook one day!
|
||||
|
||||
![[vec_calculus.jpg]]
|
||||
7
Vector_Calculus.md
Normal file
@ -0,0 +1,7 @@
|
||||
|
||||
|
||||
[[Posters]]
|
||||
[[DIV]]
|
||||
[[GRAD]]
|
||||
[[CURL]]
|
||||
|
||||
77
Worked Example RC Low Pass.md
Normal 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
|
After Width: | Height: | Size: 166 KiB |
402
bad.md
Normal 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.
|
||||
BIN
buff-headwear.jpg_compressed.jpeg
Normal file
|
After Width: | Height: | Size: 126 KiB |
107
butter_plot.py
Normal 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
|
After Width: | Height: | Size: 153 KiB |
71
fix_obsidian_links.py
Normal 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.")
|
||||
BIN
imgp3389_20071053719_o.jpg_compressed 1.jpeg
Normal file
|
After Width: | Height: | Size: 707 KiB |
BIN
imgp3389_20071053719_o.jpg_compressed.jpeg
Normal file
|
After Width: | Height: | Size: 707 KiB |
BIN
ir_photo_transistor_amplifier.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
ir_photo_transistor_amplifier.xcf
Normal file
BIN
metabolic_pathways_poster.pdf
Normal file
1
piezo amplifiers.md
Normal file
@ -0,0 +1 @@
|
||||
![[SGTL5000_PIEZO_AMP.png]]
|
||||
376
quat_gui 1.py
Normal 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
@ -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
@ -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
1
ti_SBOA226.md
Normal file
@ -0,0 +1 @@
|
||||
![[sboa226.pdf]]
|
||||
BIN
transistors.jpg
Normal file
|
After Width: | Height: | Size: 409 KiB |
BIN
vec_calculus.jpg
Normal file
|
After Width: | Height: | Size: 530 KiB |
BIN
vec_calculus.jpg_compressed.jpeg
Normal file
|
After Width: | Height: | Size: 512 KiB |