Initial release of the pest detector project

This repository contains an attempt to detect wood pests
using three piezo sensors.
Each sensor records the time of flight of a noise source in their enclosing
area and calculates the coordinate as best it can.

This utilizes an ESP32's motor controller peripheral for exact timestamping
of three sensor events, which is then processed by a Python script.
The Python script takes the timestamps of an event,
and a photo of the sensor arrangement and places a marker where the noise
originates.
This commit is contained in:
Dominic Höglinger 2025-05-20 19:56:33 +02:00
commit 78102e2f02
28 changed files with 20595 additions and 0 deletions

View File

@ -0,0 +1,9 @@
EESchema-DOCLIB Version 2.0
#
$CMP ADG839YKSZ-REEL7
D ANALOG DEVICES - ADG839YKSZ-REEL7 - ANALOGUE SW, SINGLE, SPDT, SC70-6
K
F https://componentsearchengine.com/Datasheets/2/ADG839YKSZ-REEL7.pdf
$ENDCMP
#
#End Doc Library

View File

@ -0,0 +1,64 @@
(kicad_symbol_lib (version 20211014) (generator SamacSys_ECAD_Model)
(symbol "ADG839YKSZ-REEL7" (in_bom yes) (on_board yes)
(property "Reference" "S" (at 21.59 7.62 0)
(effects (font (size 1.27 1.27)) (justify left top))
)
(property "Value" "ADG839YKSZ-REEL7" (at 21.59 5.08 0)
(effects (font (size 1.27 1.27)) (justify left top))
)
(property "Footprint" "SOT65P210X110-6N" (at 21.59 -94.92 0)
(effects (font (size 1.27 1.27)) (justify left top) hide)
)
(property "Datasheet" "https://componentsearchengine.com/Datasheets/2/ADG839YKSZ-REEL7.pdf" (at 21.59 -194.92 0)
(effects (font (size 1.27 1.27)) (justify left top) hide)
)
(property "ki_description" "ANALOG DEVICES - ADG839YKSZ-REEL7 - ANALOGUE SW, SINGLE, SPDT, SC70-6" (at 21.59 -294.92 0)
(effects (font (size 1.27 1.27)) (justify left top) hide)
)
(property "Height" "1.1" (at 21.59 -394.92 0)
(effects (font (size 1.27 1.27)) (justify left top) hide)
)
(property "Mouser Part Number" "584-ADG839YKSZ-R7" (at 21.59 -494.92 0)
(effects (font (size 1.27 1.27)) (justify left top) hide)
)
(property "Mouser Price/Stock" "https://www.mouser.co.uk/ProductDetail/Analog-Devices/ADG839YKSZ-REEL7?qs=BpaRKvA4VqERXVZBPxrlrA%3D%3D" (at 21.59 -594.92 0)
(effects (font (size 1.27 1.27)) (justify left top) hide)
)
(property "Manufacturer_Name" "Analog Devices" (at 21.59 -694.92 0)
(effects (font (size 1.27 1.27)) (justify left top) hide)
)
(property "Manufacturer_Part_Number" "ADG839YKSZ-REEL7" (at 21.59 -794.92 0)
(effects (font (size 1.27 1.27)) (justify left top) hide)
)
(rectangle
(start 5.08 2.54)
(end 20.32 -7.62)
(stroke (width 0.254) (type default))
(fill (type background))
)
(pin passive line (at 0 0 0) (length 5.08)
(name "IN" (effects (font (size 1.27 1.27))))
(number "1" (effects (font (size 1.27 1.27))))
)
(pin passive line (at 0 -2.54 0) (length 5.08)
(name "VDD" (effects (font (size 1.27 1.27))))
(number "2" (effects (font (size 1.27 1.27))))
)
(pin passive line (at 0 -5.08 0) (length 5.08)
(name "GND" (effects (font (size 1.27 1.27))))
(number "3" (effects (font (size 1.27 1.27))))
)
(pin passive line (at 25.4 0 180) (length 5.08)
(name "S2" (effects (font (size 1.27 1.27))))
(number "6" (effects (font (size 1.27 1.27))))
)
(pin passive line (at 25.4 -2.54 180) (length 5.08)
(name "D" (effects (font (size 1.27 1.27))))
(number "5" (effects (font (size 1.27 1.27))))
)
(pin passive line (at 25.4 -5.08 180) (length 5.08)
(name "S1" (effects (font (size 1.27 1.27))))
(number "4" (effects (font (size 1.27 1.27))))
)
)
)

View File

@ -0,0 +1,27 @@
EESchema-LIBRARY Version 2.3
#encoding utf-8
#SamacSys ECAD Model ADG839YKSZ-REEL7
#/953412/1184508/2.50/6/3/Switch
DEF ADG839YKSZ-REEL7 S 0 30 Y Y 1 F N
F0 "S" 850 300 50 H V L CNN
F1 "ADG839YKSZ-REEL7" 850 200 50 H V L CNN
F2 "SOT65P210X110-6N" 850 100 50 H I L CNN
F3 "https://componentsearchengine.com/Datasheets/2/ADG839YKSZ-REEL7.pdf" 850 0 50 H I L CNN
F4 "ANALOG DEVICES - ADG839YKSZ-REEL7 - ANALOGUE SW, SINGLE, SPDT, SC70-6" 850 -100 50 H I L CNN "Description"
F5 "1.1" 850 -200 50 H I L CNN "Height"
F6 "584-ADG839YKSZ-R7" 850 -300 50 H I L CNN "Mouser Part Number"
F7 "https://www.mouser.co.uk/ProductDetail/Analog-Devices/ADG839YKSZ-REEL7?qs=BpaRKvA4VqERXVZBPxrlrA%3D%3D" 850 -400 50 H I L CNN "Mouser Price/Stock"
F8 "Analog Devices" 850 -500 50 H I L CNN "Manufacturer_Name"
F9 "ADG839YKSZ-REEL7" 850 -600 50 H I L CNN "Manufacturer_Part_Number"
DRAW
X IN 1 0 0 200 R 50 50 0 0 P
X VDD 2 0 -100 200 R 50 50 0 0 P
X GND 3 0 -200 200 R 50 50 0 0 P
X S2 6 1000 0 200 L 50 50 0 0 P
X D 5 1000 -100 200 L 50 50 0 0 P
X S1 4 1000 -200 200 L 50 50 0 0 P
P 5 0 1 6 200 100 800 100 800 -300 200 -300 200 100 N
ENDDRAW
ENDDEF
#
#End Library

View File

@ -0,0 +1,69 @@
PCBNEW-LibModule-V1 2024-05-05 19:52:51
# encoding utf-8
Units mm
$INDEX
SOT65P210X110-6N
$EndINDEX
$MODULE SOT65P210X110-6N
Po 0 0 0 15 6637d583 00000000 ~~
Li SOT65P210X110-6N
Cd 6-Lead SC70-ren1
Kw Switch
Sc 0
At SMD
AR
Op 0 0 0
T0 0 0 1.27 1.27 0 0.254 N V 21 N "S**"
T1 0 0 1.27 1.27 0 0.254 N I 21 N "SOT65P210X110-6N"
DS -1.7 -1.25 1.7 -1.25 0.05 24
DS 1.7 -1.25 1.7 1.25 0.05 24
DS 1.7 1.25 -1.7 1.25 0.05 24
DS -1.7 1.25 -1.7 -1.25 0.05 24
DS -0.625 -1 0.625 -1 0.1 24
DS 0.625 -1 0.625 1 0.1 24
DS 0.625 1 -0.625 1 0.1 24
DS -0.625 1 -0.625 -1 0.1 24
DS -0.625 -0.35 0.025 -1 0.1 24
DS -0.1 -1 0.1 -1 0.2 21
DS 0.1 -1 0.1 1 0.2 21
DS 0.1 1 -0.1 1 0.2 21
DS -0.1 1 -0.1 -1 0.2 21
DS -1.45 -1.2 -0.45 -1.2 0.2 21
$PAD
Po -0.95 -0.65
Sh "1" R 0.4 1 0 0 900
At SMD N 00888000
Ne 0 ""
$EndPAD
$PAD
Po -0.95 0
Sh "2" R 0.4 1 0 0 900
At SMD N 00888000
Ne 0 ""
$EndPAD
$PAD
Po -0.95 0.65
Sh "3" R 0.4 1 0 0 900
At SMD N 00888000
Ne 0 ""
$EndPAD
$PAD
Po 0.95 0.65
Sh "4" R 0.4 1 0 0 900
At SMD N 00888000
Ne 0 ""
$EndPAD
$PAD
Po 0.95 0
Sh "5" R 0.4 1 0 0 900
At SMD N 00888000
Ne 0 ""
$EndPAD
$PAD
Po 0.95 -0.65
Sh "6" R 0.4 1 0 0 900
At SMD N 00888000
Ne 0 ""
$EndPAD
$EndMODULE SOT65P210X110-6N
$EndLIBRARY

View File

@ -0,0 +1,39 @@
(module "SOT65P210X110-6N" (layer F.Cu)
(descr "6-Lead SC70-ren1")
(tags "Switch")
(attr smd)
(fp_text reference S** (at 0 0) (layer F.SilkS)
(effects (font (size 1.27 1.27) (thickness 0.254)))
)
(fp_text user %R (at 0 0) (layer F.Fab)
(effects (font (size 1.27 1.27) (thickness 0.254)))
)
(fp_text value "SOT65P210X110-6N" (at 0 0) (layer F.SilkS) hide
(effects (font (size 1.27 1.27) (thickness 0.254)))
)
(fp_line (start -1.7 -1.25) (end 1.7 -1.25) (layer F.CrtYd) (width 0.05))
(fp_line (start 1.7 -1.25) (end 1.7 1.25) (layer F.CrtYd) (width 0.05))
(fp_line (start 1.7 1.25) (end -1.7 1.25) (layer F.CrtYd) (width 0.05))
(fp_line (start -1.7 1.25) (end -1.7 -1.25) (layer F.CrtYd) (width 0.05))
(fp_line (start -0.625 -1) (end 0.625 -1) (layer F.Fab) (width 0.1))
(fp_line (start 0.625 -1) (end 0.625 1) (layer F.Fab) (width 0.1))
(fp_line (start 0.625 1) (end -0.625 1) (layer F.Fab) (width 0.1))
(fp_line (start -0.625 1) (end -0.625 -1) (layer F.Fab) (width 0.1))
(fp_line (start -0.625 -0.35) (end 0.025 -1) (layer F.Fab) (width 0.1))
(fp_line (start -0.1 -1) (end 0.1 -1) (layer F.SilkS) (width 0.2))
(fp_line (start 0.1 -1) (end 0.1 1) (layer F.SilkS) (width 0.2))
(fp_line (start 0.1 1) (end -0.1 1) (layer F.SilkS) (width 0.2))
(fp_line (start -0.1 1) (end -0.1 -1) (layer F.SilkS) (width 0.2))
(fp_line (start -1.45 -1.2) (end -0.45 -1.2) (layer F.SilkS) (width 0.2))
(pad 1 smd rect (at -0.95 -0.65 90) (size 0.4 1) (layers F.Cu F.Paste F.Mask))
(pad 2 smd rect (at -0.95 0 90) (size 0.4 1) (layers F.Cu F.Paste F.Mask))
(pad 3 smd rect (at -0.95 0.65 90) (size 0.4 1) (layers F.Cu F.Paste F.Mask))
(pad 4 smd rect (at 0.95 0.65 90) (size 0.4 1) (layers F.Cu F.Paste F.Mask))
(pad 5 smd rect (at 0.95 0 90) (size 0.4 1) (layers F.Cu F.Paste F.Mask))
(pad 6 smd rect (at 0.95 -0.65 90) (size 0.4 1) (layers F.Cu F.Paste F.Mask))
(model ADG839YKSZ-REEL7.stp
(at (xyz 0 0 0))
(scale (xyz 1 1 1))
(rotate (xyz 0 0 0))
)
)

View File

@ -0,0 +1,9 @@
EESchema-DOCLIB Version 2.0
#
$CMP DG9431EDV-T1-GE3
D Analog Switch ICs SPDT 1pC; 100pA TSOP-6
K
F https://componentsearchengine.com/Datasheets/2/DG9431EDV-T1-GE3.pdf
$ENDCMP
#
#End Doc Library

View File

@ -0,0 +1,64 @@
(kicad_symbol_lib (version 20211014) (generator SamacSys_ECAD_Model)
(symbol "DG9431EDV-T1-GE3" (in_bom yes) (on_board yes)
(property "Reference" "IC" (at 21.59 7.62 0)
(effects (font (size 1.27 1.27)) (justify left top))
)
(property "Value" "DG9431EDV-T1-GE3" (at 21.59 5.08 0)
(effects (font (size 1.27 1.27)) (justify left top))
)
(property "Footprint" "SOT95P284X110-6N" (at 21.59 -94.92 0)
(effects (font (size 1.27 1.27)) (justify left top) hide)
)
(property "Datasheet" "https://componentsearchengine.com/Datasheets/2/DG9431EDV-T1-GE3.pdf" (at 21.59 -194.92 0)
(effects (font (size 1.27 1.27)) (justify left top) hide)
)
(property "ki_description" "Analog Switch ICs SPDT 1pC; 100pA TSOP-6" (at 21.59 -294.92 0)
(effects (font (size 1.27 1.27)) (justify left top) hide)
)
(property "Height" "1.1" (at 21.59 -394.92 0)
(effects (font (size 1.27 1.27)) (justify left top) hide)
)
(property "Mouser Part Number" "78-DG9431EDV-T1-GE3" (at 21.59 -494.92 0)
(effects (font (size 1.27 1.27)) (justify left top) hide)
)
(property "Mouser Price/Stock" "https://www.mouser.co.uk/ProductDetail/Vishay-Siliconix/DG9431EDV-T1-GE3?qs=fA06TrWLL4d9tWXRkFAHiA%3D%3D" (at 21.59 -594.92 0)
(effects (font (size 1.27 1.27)) (justify left top) hide)
)
(property "Manufacturer_Name" "Vishay" (at 21.59 -694.92 0)
(effects (font (size 1.27 1.27)) (justify left top) hide)
)
(property "Manufacturer_Part_Number" "DG9431EDV-T1-GE3" (at 21.59 -794.92 0)
(effects (font (size 1.27 1.27)) (justify left top) hide)
)
(rectangle
(start 5.08 2.54)
(end 20.32 -7.62)
(stroke (width 0.254) (type default))
(fill (type background))
)
(pin passive line (at 0 0 0) (length 5.08)
(name "IN" (effects (font (size 1.27 1.27))))
(number "1" (effects (font (size 1.27 1.27))))
)
(pin passive line (at 0 -2.54 0) (length 5.08)
(name "V+" (effects (font (size 1.27 1.27))))
(number "2" (effects (font (size 1.27 1.27))))
)
(pin passive line (at 0 -5.08 0) (length 5.08)
(name "GND" (effects (font (size 1.27 1.27))))
(number "3" (effects (font (size 1.27 1.27))))
)
(pin passive line (at 25.4 0 180) (length 5.08)
(name "NO" (effects (font (size 1.27 1.27))))
(number "6" (effects (font (size 1.27 1.27))))
)
(pin passive line (at 25.4 -2.54 180) (length 5.08)
(name "COM" (effects (font (size 1.27 1.27))))
(number "5" (effects (font (size 1.27 1.27))))
)
(pin no_connect line (at 25.4 -5.08 180) (length 5.08)
(name "NC" (effects (font (size 1.27 1.27))))
(number "4" (effects (font (size 1.27 1.27))))
)
)
)

View File

@ -0,0 +1,27 @@
EESchema-LIBRARY Version 2.3
#encoding utf-8
#SamacSys ECAD Model DG9431EDV-T1-GE3
#/1162323/1184508/2.50/6/3/Integrated Circuit
DEF DG9431EDV-T1-GE3 IC 0 30 Y Y 1 F N
F0 "IC" 850 300 50 H V L CNN
F1 "DG9431EDV-T1-GE3" 850 200 50 H V L CNN
F2 "SOT95P284X110-6N" 850 100 50 H I L CNN
F3 "https://componentsearchengine.com/Datasheets/2/DG9431EDV-T1-GE3.pdf" 850 0 50 H I L CNN
F4 "Analog Switch ICs SPDT 1pC; 100pA TSOP-6" 850 -100 50 H I L CNN "Description"
F5 "1.1" 850 -200 50 H I L CNN "Height"
F6 "78-DG9431EDV-T1-GE3" 850 -300 50 H I L CNN "Mouser Part Number"
F7 "https://www.mouser.co.uk/ProductDetail/Vishay-Siliconix/DG9431EDV-T1-GE3?qs=fA06TrWLL4d9tWXRkFAHiA%3D%3D" 850 -400 50 H I L CNN "Mouser Price/Stock"
F8 "Vishay" 850 -500 50 H I L CNN "Manufacturer_Name"
F9 "DG9431EDV-T1-GE3" 850 -600 50 H I L CNN "Manufacturer_Part_Number"
DRAW
X IN 1 0 0 200 R 50 50 0 0 P
X V+ 2 0 -100 200 R 50 50 0 0 P
X GND 3 0 -200 200 R 50 50 0 0 P
X NO 6 1000 0 200 L 50 50 0 0 P
X COM 5 1000 -100 200 L 50 50 0 0 P
X NC 4 1000 -200 200 L 50 50 0 0 N
P 5 0 1 6 200 100 800 100 800 -300 200 -300 200 100 N
ENDDRAW
ENDDEF
#
#End Library

View File

@ -0,0 +1,69 @@
PCBNEW-LibModule-V1 2024-05-06 17:09:16
# encoding utf-8
Units mm
$INDEX
SOT95P284X110-6N
$EndINDEX
$MODULE SOT95P284X110-6N
Po 0 0 0 15 663900ac 00000000 ~~
Li SOT95P284X110-6N
Cd TSOP 6
Kw Integrated Circuit
Sc 0
At SMD
AR
Op 0 0 0
T0 0 0 1.27 1.27 0 0.254 N V 21 N "IC**"
T1 0 0 1.27 1.27 0 0.254 N I 21 N "SOT95P284X110-6N"
DS -2.1 -1.8 2.1 -1.8 0.05 24
DS 2.1 -1.8 2.1 1.8 0.05 24
DS 2.1 1.8 -2.1 1.8 0.05 24
DS -2.1 1.8 -2.1 -1.8 0.05 24
DS -0.812 -1.512 0.812 -1.512 0.1 24
DS 0.812 -1.512 0.812 1.512 0.1 24
DS 0.812 1.512 -0.812 1.512 0.1 24
DS -0.812 1.512 -0.812 -1.512 0.1 24
DS -0.812 -0.562 0.138 -1.512 0.1 24
DS -0.4 -1.512 0.4 -1.512 0.2 21
DS 0.4 -1.512 0.4 1.512 0.2 21
DS 0.4 1.512 -0.4 1.512 0.2 21
DS -0.4 1.512 -0.4 -1.512 0.2 21
DS -1.85 -1.575 -0.75 -1.575 0.2 21
$PAD
Po -1.3 -0.95
Sh "1" R 0.55 1.1 0 0 900
At SMD N 00888000
Ne 0 ""
$EndPAD
$PAD
Po -1.3 0
Sh "2" R 0.55 1.1 0 0 900
At SMD N 00888000
Ne 0 ""
$EndPAD
$PAD
Po -1.3 0.95
Sh "3" R 0.55 1.1 0 0 900
At SMD N 00888000
Ne 0 ""
$EndPAD
$PAD
Po 1.3 0.95
Sh "4" R 0.55 1.1 0 0 900
At SMD N 00888000
Ne 0 ""
$EndPAD
$PAD
Po 1.3 0
Sh "5" R 0.55 1.1 0 0 900
At SMD N 00888000
Ne 0 ""
$EndPAD
$PAD
Po 1.3 -0.95
Sh "6" R 0.55 1.1 0 0 900
At SMD N 00888000
Ne 0 ""
$EndPAD
$EndMODULE SOT95P284X110-6N
$EndLIBRARY

View File

@ -0,0 +1,39 @@
(module "SOT95P284X110-6N" (layer F.Cu)
(descr "TSOP 6")
(tags "Integrated Circuit")
(attr smd)
(fp_text reference IC** (at 0 0) (layer F.SilkS)
(effects (font (size 1.27 1.27) (thickness 0.254)))
)
(fp_text user %R (at 0 0) (layer F.Fab)
(effects (font (size 1.27 1.27) (thickness 0.254)))
)
(fp_text value "SOT95P284X110-6N" (at 0 0) (layer F.SilkS) hide
(effects (font (size 1.27 1.27) (thickness 0.254)))
)
(fp_line (start -2.1 -1.8) (end 2.1 -1.8) (layer F.CrtYd) (width 0.05))
(fp_line (start 2.1 -1.8) (end 2.1 1.8) (layer F.CrtYd) (width 0.05))
(fp_line (start 2.1 1.8) (end -2.1 1.8) (layer F.CrtYd) (width 0.05))
(fp_line (start -2.1 1.8) (end -2.1 -1.8) (layer F.CrtYd) (width 0.05))
(fp_line (start -0.812 -1.512) (end 0.812 -1.512) (layer F.Fab) (width 0.1))
(fp_line (start 0.812 -1.512) (end 0.812 1.512) (layer F.Fab) (width 0.1))
(fp_line (start 0.812 1.512) (end -0.812 1.512) (layer F.Fab) (width 0.1))
(fp_line (start -0.812 1.512) (end -0.812 -1.512) (layer F.Fab) (width 0.1))
(fp_line (start -0.812 -0.562) (end 0.138 -1.512) (layer F.Fab) (width 0.1))
(fp_line (start -0.4 -1.512) (end 0.4 -1.512) (layer F.SilkS) (width 0.2))
(fp_line (start 0.4 -1.512) (end 0.4 1.512) (layer F.SilkS) (width 0.2))
(fp_line (start 0.4 1.512) (end -0.4 1.512) (layer F.SilkS) (width 0.2))
(fp_line (start -0.4 1.512) (end -0.4 -1.512) (layer F.SilkS) (width 0.2))
(fp_line (start -1.85 -1.575) (end -0.75 -1.575) (layer F.SilkS) (width 0.2))
(pad 1 smd rect (at -1.3 -0.95 90) (size 0.55 1.1) (layers F.Cu F.Paste F.Mask))
(pad 2 smd rect (at -1.3 0 90) (size 0.55 1.1) (layers F.Cu F.Paste F.Mask))
(pad 3 smd rect (at -1.3 0.95 90) (size 0.55 1.1) (layers F.Cu F.Paste F.Mask))
(pad 4 smd rect (at 1.3 0.95 90) (size 0.55 1.1) (layers F.Cu F.Paste F.Mask))
(pad 5 smd rect (at 1.3 0 90) (size 0.55 1.1) (layers F.Cu F.Paste F.Mask))
(pad 6 smd rect (at 1.3 -0.95 90) (size 0.55 1.1) (layers F.Cu F.Paste F.Mask))
(model DG9431EDV-T1-GE3.stp
(at (xyz 0 0 0))
(scale (xyz 1 1 1))
(rotate (xyz 0 0 0))
)
)

View File

@ -0,0 +1,9 @@
EESchema-DOCLIB Version 2.0
#
$CMP SJ-43515TS-SMT-TR
D 3.50mm (0.141", 1/8", Mini Plug) - Headphone Phone Jack Stereo (4 Conductor, TRRS) Connector Solder
K
F https://www.cuidevices.com/product/resource/sj-4351x-smt.pdf
$ENDCMP
#
#End Doc Library

View File

@ -0,0 +1,60 @@
(kicad_symbol_lib (version 20211014) (generator SamacSys_ECAD_Model)
(symbol "SJ-43515TS-SMT-TR" (in_bom yes) (on_board yes)
(property "Reference" "J" (at 34.29 7.62 0)
(effects (font (size 1.27 1.27)) (justify left top))
)
(property "Value" "SJ-43515TS-SMT-TR" (at 34.29 5.08 0)
(effects (font (size 1.27 1.27)) (justify left top))
)
(property "Footprint" "SJ43515TSSMTTR" (at 34.29 -94.92 0)
(effects (font (size 1.27 1.27)) (justify left top) hide)
)
(property "Datasheet" "https://www.cuidevices.com/product/resource/sj-4351x-smt.pdf" (at 34.29 -194.92 0)
(effects (font (size 1.27 1.27)) (justify left top) hide)
)
(property "ki_description" "3.50mm (0.141\", 1/8\", Mini Plug) - Headphone Phone Jack Stereo (4 Conductor, TRRS) Connector Solder" (at 34.29 -294.92 0)
(effects (font (size 1.27 1.27)) (justify left top) hide)
)
(property "Height" "5.3" (at 34.29 -394.92 0)
(effects (font (size 1.27 1.27)) (justify left top) hide)
)
(property "Mouser Part Number" "490-SJ43515TS-SMT-TR" (at 34.29 -494.92 0)
(effects (font (size 1.27 1.27)) (justify left top) hide)
)
(property "Mouser Price/Stock" "https://www.mouser.co.uk/ProductDetail/CUI-Devices/SJ-43515TS-SMT-TR?qs=WyjlAZoYn50eO9pw4mW8cQ%3D%3D" (at 34.29 -594.92 0)
(effects (font (size 1.27 1.27)) (justify left top) hide)
)
(property "Manufacturer_Name" "CUI Devices" (at 34.29 -694.92 0)
(effects (font (size 1.27 1.27)) (justify left top) hide)
)
(property "Manufacturer_Part_Number" "SJ-43515TS-SMT-TR" (at 34.29 -794.92 0)
(effects (font (size 1.27 1.27)) (justify left top) hide)
)
(rectangle
(start 5.08 2.54)
(end 33.02 -7.62)
(stroke (width 0.254) (type default))
(fill (type background))
)
(pin passive line (at 0 0 0) (length 5.08)
(name "SLEEVE" (effects (font (size 1.27 1.27))))
(number "1" (effects (font (size 1.27 1.27))))
)
(pin passive line (at 0 -2.54 0) (length 5.08)
(name "TIP" (effects (font (size 1.27 1.27))))
(number "2" (effects (font (size 1.27 1.27))))
)
(pin passive line (at 0 -5.08 0) (length 5.08)
(name "RING_1" (effects (font (size 1.27 1.27))))
(number "3" (effects (font (size 1.27 1.27))))
)
(pin passive line (at 38.1 0 180) (length 5.08)
(name "RING_2" (effects (font (size 1.27 1.27))))
(number "4" (effects (font (size 1.27 1.27))))
)
(pin passive line (at 38.1 -2.54 180) (length 5.08)
(name "TIP_SWITCH" (effects (font (size 1.27 1.27))))
(number "5" (effects (font (size 1.27 1.27))))
)
)
)

View File

@ -0,0 +1,26 @@
EESchema-LIBRARY Version 2.3
#encoding utf-8
#SamacSys ECAD Model SJ-43515TS-SMT-TR
#/644640/1184508/2.50/5/3/Connector
DEF SJ-43515TS-SMT-TR J 0 30 Y Y 1 F N
F0 "J" 1350 300 50 H V L CNN
F1 "SJ-43515TS-SMT-TR" 1350 200 50 H V L CNN
F2 "SJ43515TSSMTTR" 1350 100 50 H I L CNN
F3 "https://www.cuidevices.com/product/resource/sj-4351x-smt.pdf" 1350 0 50 H I L CNN
F4 "3.50mm (0.141\", 1/8\", Mini Plug) - Headphone Phone Jack Stereo (4 Conductor, TRRS) Connector Solder" 1350 -100 50 H I L CNN "Description"
F5 "5.3" 1350 -200 50 H I L CNN "Height"
F6 "490-SJ43515TS-SMT-TR" 1350 -300 50 H I L CNN "Mouser Part Number"
F7 "https://www.mouser.co.uk/ProductDetail/CUI-Devices/SJ-43515TS-SMT-TR?qs=WyjlAZoYn50eO9pw4mW8cQ%3D%3D" 1350 -400 50 H I L CNN "Mouser Price/Stock"
F8 "CUI Devices" 1350 -500 50 H I L CNN "Manufacturer_Name"
F9 "SJ-43515TS-SMT-TR" 1350 -600 50 H I L CNN "Manufacturer_Part_Number"
DRAW
X SLEEVE 1 0 0 200 R 50 50 0 0 P
X TIP 2 0 -100 200 R 50 50 0 0 P
X RING_1 3 0 -200 200 R 50 50 0 0 P
X RING_2 4 1500 0 200 L 50 50 0 0 P
X TIP_SWITCH 5 1500 -100 200 L 50 50 0 0 P
P 5 0 1 6 200 100 1300 100 1300 -300 200 -300 200 100 N
ENDDRAW
ENDDEF
#
#End Library

View File

@ -0,0 +1,88 @@
PCBNEW-LibModule-V1 2024-05-06 16:34:13
# encoding utf-8
Units mm
$INDEX
SJ43515TSSMTTR
$EndINDEX
$MODULE SJ43515TSSMTTR
Po 0 0 0 15 6638f875 00000000 ~~
Li SJ43515TSSMTTR
Cd SJ-43515TS-SMT-TR-3
Kw Connector
Sc 0
At STD
AR
Op 0 0 0
T0 0.000 -0 1.27 1.27 0 0.254 N V 21 N "J**"
T1 0.000 -0 1.27 1.27 0 0.254 N I 21 N "SJ43515TSSMTTR"
DS -8.5 -3 7 -3 0.1 24
DS 7 -3 7 3.8 0.1 24
DS 7 3.8 -8.5 3.8 0.1 24
DS -8.5 3.8 -8.5 -3 0.1 24
DS -11 -6 11 -6 0.1 24
DS 11 -6 11 6 0.1 24
DS 11 6 -11 6 0.1 24
DS -11 6 -11 -6 0.1 24
DS -8.5 2.5 -10 2.5 0.1 24
DS -10 2.5 -10 -2.5 0.1 24
DS -10 -2.5 -8.5 -2.5 0.1 24
DS -3.4 3.8 2.9 3.8 0.2 21
DS 7 0.6 7 3.8 0.2 21
DS 7 3.8 5.9 3.8 0.2 21
DS -1.6 -3 7 -3 0.2 21
DS 7 -3 7 -2.4 0.2 21
DS -9.4 2.5 -10 2.5 0.2 21
DS -10 2.5 -10 -2.5 0.2 21
DS -10 -2.5 -8.5 -2.5 0.2 21
DS -8.5 1.5 -8.5 -3 0.2 21
DS -8.5 -3 -4.75 -3 0.2 21
DS -7.9 5.55 -7.9 5.55 0.1 21
DS -7.9 5.45 -7.9 5.45 0.1 21
DA -7.9 5.5 -7.900 5.55 -1800 0.1 21
DA -7.9 5.5 -7.900 5.45 -1800 0.1 21
$PAD
Po -7.900 3.5
Sh "1" R 2.000 3.000 0 0 0
At SMD N 00888000
Ne 0 ""
$EndPAD
$PAD
Po 4.500 3.5
Sh "2" R 2.000 3.000 0 0 0
At SMD N 00888000
Ne 0 ""
$EndPAD
$PAD
Po -3.200 -3.5
Sh "3" R 2.000 3.000 0 0 0
At SMD N 00888000
Ne 0 ""
$EndPAD
$PAD
Po -5.000 3.5
Sh "4" R 2.000 3.000 0 0 0
At SMD N 00888000
Ne 0 ""
$EndPAD
$PAD
Po 8.500 -0.8
Sh "5" R 2.000 3.000 0 0 900
At SMD N 00888000
Ne 0 ""
$EndPAD
$PAD
Po -4.000 0
Sh "MH1" C 0.950 0.950 0 0 900
Dr 1.9 0 0
At STD N 00E0FFFF
Ne 0 ""
$EndPAD
$PAD
Po 3.000 0
Sh "MH2" C 0.950 0.950 0 0 900
Dr 1.9 0 0
At STD N 00E0FFFF
Ne 0 ""
$EndPAD
$EndMODULE SJ43515TSSMTTR
$EndLIBRARY

View File

@ -0,0 +1,50 @@
(module "SJ43515TSSMTTR" (layer F.Cu)
(descr "SJ-43515TS-SMT-TR-3")
(tags "Connector")
(fp_text reference J** (at 0.000 -0) (layer F.SilkS)
(effects (font (size 1.27 1.27) (thickness 0.254)))
)
(fp_text user %R (at 0.000 -0) (layer F.Fab)
(effects (font (size 1.27 1.27) (thickness 0.254)))
)
(fp_text value "SJ43515TSSMTTR" (at 0.000 -0) (layer F.SilkS) hide
(effects (font (size 1.27 1.27) (thickness 0.254)))
)
(fp_line (start -8.5 -3) (end 7 -3) (layer F.Fab) (width 0.1))
(fp_line (start 7 -3) (end 7 3.8) (layer F.Fab) (width 0.1))
(fp_line (start 7 3.8) (end -8.5 3.8) (layer F.Fab) (width 0.1))
(fp_line (start -8.5 3.8) (end -8.5 -3) (layer F.Fab) (width 0.1))
(fp_line (start -11 -6) (end 11 -6) (layer F.CrtYd) (width 0.1))
(fp_line (start 11 -6) (end 11 6) (layer F.CrtYd) (width 0.1))
(fp_line (start 11 6) (end -11 6) (layer F.CrtYd) (width 0.1))
(fp_line (start -11 6) (end -11 -6) (layer F.CrtYd) (width 0.1))
(fp_line (start -8.5 2.5) (end -10 2.5) (layer F.Fab) (width 0.1))
(fp_line (start -10 2.5) (end -10 -2.5) (layer F.Fab) (width 0.1))
(fp_line (start -10 -2.5) (end -8.5 -2.5) (layer F.Fab) (width 0.1))
(fp_line (start -3.4 3.8) (end 2.9 3.8) (layer F.SilkS) (width 0.2))
(fp_line (start 7 0.6) (end 7 3.8) (layer F.SilkS) (width 0.2))
(fp_line (start 7 3.8) (end 5.9 3.8) (layer F.SilkS) (width 0.2))
(fp_line (start -1.6 -3) (end 7 -3) (layer F.SilkS) (width 0.2))
(fp_line (start 7 -3) (end 7 -2.4) (layer F.SilkS) (width 0.2))
(fp_line (start -9.4 2.5) (end -10 2.5) (layer F.SilkS) (width 0.2))
(fp_line (start -10 2.5) (end -10 -2.5) (layer F.SilkS) (width 0.2))
(fp_line (start -10 -2.5) (end -8.5 -2.5) (layer F.SilkS) (width 0.2))
(fp_line (start -8.5 1.5) (end -8.5 -3) (layer F.SilkS) (width 0.2))
(fp_line (start -8.5 -3) (end -4.75 -3) (layer F.SilkS) (width 0.2))
(fp_line (start -7.9 5.55) (end -7.9 5.55) (layer F.SilkS) (width 0.1))
(fp_line (start -7.9 5.45) (end -7.9 5.45) (layer F.SilkS) (width 0.1))
(fp_arc (start -7.9 5.5) (end -7.900 5.55) (angle -180) (layer F.SilkS) (width 0.1))
(fp_arc (start -7.9 5.5) (end -7.900 5.45) (angle -180) (layer F.SilkS) (width 0.1))
(pad 1 smd rect (at -7.900 3.5 0) (size 2.000 3.000) (layers F.Cu F.Paste F.Mask))
(pad 2 smd rect (at 4.500 3.5 0) (size 2.000 3.000) (layers F.Cu F.Paste F.Mask))
(pad 3 smd rect (at -3.200 -3.5 0) (size 2.000 3.000) (layers F.Cu F.Paste F.Mask))
(pad 4 smd rect (at -5.000 3.5 0) (size 2.000 3.000) (layers F.Cu F.Paste F.Mask))
(pad 5 smd rect (at 8.500 -0.8 90) (size 2.000 3.000) (layers F.Cu F.Paste F.Mask))
(pad MH1 np_thru_hole circle (at -4.000 0) (size 1.9 1.9) (drill 1.9) (layers *.Cu *.Mask))
(pad MH2 np_thru_hole circle (at 3.000 0) (size 1.9 1.9) (drill 1.9) (layers *.Cu *.Mask))
(model SJ-43515TS-SMT-TR.stp
(at (xyz 0 0 0))
(scale (xyz 1 1 1))
(rotate (xyz 0 0 0))
)
)

View File

@ -0,0 +1,306 @@
(footprint "LOGO" (version 20221018) (generator bitmap2component)
(layer "F.Cu")
(attr board_only exclude_from_pos_files exclude_from_bom)
(fp_text reference "G***" (at 0 0) (layer "F.SilkS")
(effects (font (size 1.5 1.5) (thickness 0.3)))
(tstamp b73c791f-b4ef-4063-bbe0-091bab5125df)
)
(fp_text value "LOGO" (at 0.75 0) (layer "F.SilkS") hide
(effects (font (size 1.5 1.5) (thickness 0.3)))
(tstamp 85766754-2895-449b-b17e-686a6fab1207)
)
(fp_poly
(pts
(xy 1.894447 -0.209938)
(xy 1.916656 -0.178385)
(xy 2.076372 -0.040858)
(xy 2.215313 0.000000)
(xy 2.333997 0.025351)
(xy 2.351574 0.134075)
(xy 2.330630 0.232660)
(xy 2.262972 0.446338)
(xy 2.192693 0.505586)
(xy 2.096386 0.424026)
(xy 2.067411 0.385851)
(xy 1.976592 0.289707)
(xy 1.950019 0.343324)
(xy 1.950026 0.343651)
(xy 2.000513 0.504013)
(xy 2.077026 0.630016)
(xy 2.198632 0.908582)
(xy 2.153778 1.194108)
(xy 1.944472 1.476442)
(xy 1.902054 1.515229)
(xy 1.698032 1.672542)
(xy 1.528313 1.766401)
(xy 1.478721 1.778000)
(xy 1.361850 1.813690)
(xy 1.345013 1.841500)
(xy 1.310334 2.156682)
(xy 1.326902 2.348497)
(xy 1.393606 2.452516)
(xy 1.535421 2.521639)
(xy 1.591288 2.521804)
(xy 1.694993 2.560565)
(xy 1.706034 2.582334)
(xy 1.654454 2.640005)
(xy 1.499128 2.681641)
(xy 1.305443 2.699494)
(xy 1.138783 2.685819)
(xy 1.076474 2.656919)
(xy 1.030813 2.534085)
(xy 1.016000 2.373489)
(xy 0.982373 2.169479)
(xy 0.921760 2.056294)
(xy 0.896886 1.959129)
(xy 0.997527 1.816150)
(xy 1.099489 1.719050)
(xy 1.371458 1.476046)
(xy 1.024396 1.128984)
(xy 0.816973 0.900861)
(xy 0.712177 0.713218)
(xy 0.678390 0.503322)
(xy 0.677334 0.440350)
(xy 0.709633 0.180398)
(xy 0.798749 0.066389)
(xy 0.933012 0.106671)
(xy 1.019984 0.195278)
(xy 1.149152 0.307849)
(xy 1.293032 0.285552)
(xy 1.338297 0.262761)
(xy 1.505889 0.118834)
(xy 1.654517 -0.091510)
(xy 1.656979 -0.096228)
(xy 1.751402 -0.265402)
(xy 1.815122 -0.298421)
)
(stroke (width 0.000000) (type solid)) (fill solid) (layer "F.SilkS") (tstamp 62bb745c-d62a-4887-81b2-c395012e9d83))
(fp_poly
(pts
(xy 2.728013 0.218421)
(xy 2.755035 0.238626)
(xy 2.944232 0.381000)
(xy 2.778348 0.614305)
(xy 2.671577 0.774299)
(xy 2.664418 0.851632)
(xy 2.758005 0.901391)
(xy 2.784446 0.911229)
(xy 2.900236 0.999557)
(xy 2.895811 1.072927)
(xy 2.805849 1.125271)
(xy 2.638520 1.065699)
(xy 2.628424 1.060344)
(xy 2.414733 0.876491)
(xy 2.358254 0.634123)
(xy 2.437994 0.365626)
(xy 2.530418 0.191206)
(xy 2.608795 0.149466)
)
(stroke (width 0.000000) (type solid)) (fill solid) (layer "F.SilkS") (tstamp c97da42e-780b-4fc2-b156-5e7a52c15a9f))
(fp_poly
(pts
(xy -0.103272 0.047706)
(xy 0.178128 0.118626)
(xy 0.186446 0.122140)
(xy 0.345819 0.152686)
(xy 0.406477 0.137418)
(xy 0.461657 0.175313)
(xy 0.489248 0.331895)
(xy 0.489385 0.336286)
(xy 0.526173 0.581152)
(xy 0.586853 0.751138)
(xy 0.659937 0.920307)
(xy 0.642271 1.003360)
(xy 0.519419 1.000656)
(xy 0.276944 0.912556)
(xy -0.042333 0.766827)
(xy -0.648991 0.503427)
(xy -1.154514 0.338098)
(xy -1.547127 0.274235)
(xy -1.716089 0.284573)
(xy -1.890896 0.311882)
(xy -1.920379 0.290839)
(xy -1.832031 0.215081)
(xy -1.614978 0.119911)
(xy -1.282095 0.053218)
(xy -0.884864 0.017373)
(xy -0.474763 0.014746)
)
(stroke (width 0.000000) (type solid)) (fill solid) (layer "F.SilkS") (tstamp 2b3a4eab-afb1-47fb-b4ce-1ebcf5d50feb))
(fp_poly
(pts
(xy -2.032000 0.381000)
(xy -2.074333 0.423334)
(xy -2.116666 0.381000)
(xy -2.074333 0.338667)
)
(stroke (width 0.000000) (type solid)) (fill solid) (layer "F.SilkS") (tstamp b1b90741-0dee-4caf-b44e-a274e7dce1d0))
(fp_poly
(pts
(xy 1.521898 -0.618404)
(xy 1.558711 -0.468607)
(xy 1.558402 -0.337934)
(xy 1.499476 -0.107342)
(xy 1.379027 0.103463)
(xy 1.235672 0.235696)
(xy 1.169554 0.254000)
(xy 1.078844 0.186475)
(xy 1.044965 0.122692)
(xy 1.060352 -0.029778)
(xy 1.162006 -0.194808)
(xy 1.305036 -0.385074)
(xy 1.383786 -0.534533)
(xy 1.456331 -0.648552)
)
(stroke (width 0.000000) (type solid)) (fill solid) (layer "F.SilkS") (tstamp 9460f215-1a27-41a8-b9ae-644d2d763d2a))
(fp_poly
(pts
(xy 3.130207 -0.104904)
(xy 3.132667 -0.084666)
(xy 3.068238 -0.002460)
(xy 3.048000 0.000000)
(xy 2.965794 -0.064429)
(xy 2.963334 -0.084666)
(xy 3.027763 -0.166873)
(xy 3.048000 -0.169333)
)
(stroke (width 0.000000) (type solid)) (fill solid) (layer "F.SilkS") (tstamp 5636bc0d-d738-40e4-acad-d2b651b0c885))
(fp_poly
(pts
(xy 1.668742 -1.257385)
(xy 1.735667 -1.236650)
(xy 1.955273 -1.129014)
(xy 2.032000 -1.000084)
(xy 2.096223 -0.845310)
(xy 2.212464 -0.729867)
(xy 2.339609 -0.580346)
(xy 2.342121 -0.471066)
(xy 2.315299 -0.373394)
(xy 2.359220 -0.348239)
(xy 2.505812 -0.394370)
(xy 2.663342 -0.458681)
(xy 2.858018 -0.529596)
(xy 2.954148 -0.523103)
(xy 2.999289 -0.451757)
(xy 3.045367 -0.289474)
(xy 3.005611 -0.269811)
(xy 2.955490 -0.312643)
(xy 2.829313 -0.356838)
(xy 2.637990 -0.287765)
(xy 2.358210 -0.185254)
(xy 2.117731 -0.212301)
(xy 1.873191 -0.379470)
(xy 1.749267 -0.504312)
(xy 1.515673 -0.817983)
(xy 1.439334 -1.084345)
(xy 1.448682 -1.242771)
(xy 1.509010 -1.292155)
)
(stroke (width 0.000000) (type solid)) (fill solid) (layer "F.SilkS") (tstamp 34732204-2222-409d-9cdf-915af1bb0e71))
(fp_poly
(pts
(xy 3.217334 -0.381000)
(xy 3.175000 -0.338666)
(xy 3.132667 -0.381000)
(xy 3.175000 -0.423333)
)
(stroke (width 0.000000) (type solid)) (fill solid) (layer "F.SilkS") (tstamp a40b24eb-8581-40e0-9eec-7e3d058a6bcc))
(fp_poly
(pts
(xy 2.219764 -2.794387)
(xy 2.271531 -2.732380)
(xy 2.515595 -2.530258)
(xy 2.846638 -2.400218)
(xy 3.086108 -2.370666)
(xy 3.296450 -2.300234)
(xy 3.448078 -2.124496)
(xy 3.523731 -1.896787)
(xy 3.506147 -1.670446)
(xy 3.378065 -1.498808)
(xy 3.369968 -1.493565)
(xy 3.191684 -1.451963)
(xy 2.983420 -1.488528)
(xy 2.813403 -1.581047)
(xy 2.749429 -1.695615)
(xy 2.705249 -1.895633)
(xy 2.646463 -1.944588)
(xy 3.185935 -1.944588)
(xy 3.192131 -1.890889)
(xy 3.276315 -1.787937)
(xy 3.311059 -1.778000)
(xy 3.380293 -1.845650)
(xy 3.386667 -1.890889)
(xy 3.319251 -1.992569)
(xy 3.267739 -2.003778)
(xy 3.185935 -1.944588)
(xy 2.646463 -1.944588)
(xy 2.602200 -1.981449)
(xy 2.493838 -1.944155)
(xy 2.354801 -1.886642)
(xy 2.295559 -1.899092)
(xy 2.188558 -1.900797)
(xy 2.170716 -1.881623)
(xy 2.202766 -1.820131)
(xy 2.282013 -1.801580)
(xy 2.442766 -1.736561)
(xy 2.631983 -1.593016)
(xy 2.653299 -1.572337)
(xy 2.832749 -1.426700)
(xy 2.986319 -1.355952)
(xy 3.001818 -1.354666)
(xy 3.118340 -1.310973)
(xy 3.104202 -1.210919)
(xy 2.981776 -1.110537)
(xy 2.816865 -1.084883)
(xy 2.621943 -1.192050)
(xy 2.335134 -1.320002)
(xy 2.049914 -1.338503)
(xy 1.774255 -1.353199)
(xy 1.574237 -1.447496)
(xy 1.463571 -1.545944)
(xy 1.240315 -1.769200)
(xy 1.390782 -2.133433)
(xy 1.522142 -2.442619)
(xy 1.586888 -2.568975)
(xy 2.044906 -2.568975)
(xy 2.062548 -2.403998)
(xy 2.119646 -2.280434)
(xy 2.249990 -2.146844)
(xy 2.401115 -2.122295)
(xy 2.489139 -2.187535)
(xy 2.480043 -2.309233)
(xy 2.383296 -2.465051)
(xy 2.248621 -2.590098)
(xy 2.154199 -2.624666)
(xy 2.044906 -2.568975)
(xy 1.586888 -2.568975)
(xy 1.619256 -2.632142)
(xy 1.709702 -2.739984)
(xy 1.821053 -2.804127)
(xy 1.899301 -2.833866)
(xy 2.087525 -2.871585)
)
(stroke (width 0.000000) (type solid)) (fill solid) (layer "F.SilkS") (tstamp 8e6fcddd-2dfd-49d7-91a3-beaad47ddbe9))
(fp_poly
(pts
(xy 2.285099 -2.472688)
(xy 2.316618 -2.413000)
(xy 2.322679 -2.303762)
(xy 2.292401 -2.286000)
(xy 2.202235 -2.353312)
(xy 2.170716 -2.413000)
(xy 2.164654 -2.522237)
(xy 2.194932 -2.540000)
)
(stroke (width 0.000000) (type solid)) (fill solid) (layer "F.SilkS") (tstamp d43dcdcd-9785-4cff-a783-4ecea50e6721))
)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,131 @@
{
"board": {
"active_layer": 0,
"active_layer_preset": "All Layers",
"auto_track_width": true,
"hidden_netclasses": [],
"hidden_nets": [],
"high_contrast_mode": 0,
"net_color_mode": 1,
"opacity": {
"images": 0.6,
"pads": 1.0,
"shapes": 1.0,
"tracks": 1.0,
"vias": 1.0,
"zones": 0.6
},
"selection_filter": {
"dimensions": true,
"footprints": true,
"graphics": true,
"keepouts": true,
"lockedItems": false,
"otherItems": true,
"pads": true,
"text": true,
"tracks": true,
"vias": true,
"zones": true
},
"visible_items": [
"vias",
"footprint_text",
"footprint_anchors",
"ratsnest",
"grid",
"footprints_front",
"footprints_back",
"footprint_values",
"footprint_references",
"tracks",
"drc_errors",
"drawing_sheet",
"bitmaps",
"pads",
"zones",
"drc_warnings",
"locked_item_shadows",
"conflict_shadows",
"shapes"
],
"visible_layers": "ffffffff_ffffffff_ffffffff_ffffffff",
"zone_display_mode": 0
},
"git": {
"repo_password": "",
"repo_type": "",
"repo_username": "",
"ssh_key": ""
},
"meta": {
"filename": "pestdetector.kicad_prl",
"version": 5
},
"net_inspector_panel": {
"col_hidden": [
false,
false,
false,
false,
false,
false,
false,
false,
false,
false
],
"col_order": [
0,
1,
2,
3,
4,
5,
6,
7,
8,
9
],
"col_widths": [
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
"custom_group_rules": [],
"expanded_rows": [],
"filter_by_net_name": true,
"filter_by_netclass": true,
"filter_text": "",
"group_by_constraint": false,
"group_by_netclass": false,
"show_unconnected_nets": false,
"show_zero_pad_nets": false,
"sort_ascending": true,
"sorting_column": 0
},
"open_jobsets": [],
"project": {
"files": []
},
"schematic": {
"selection_filter": {
"graphics": true,
"images": true,
"labels": true,
"lockedItems": false,
"otherItems": true,
"pins": true,
"symbols": true,
"text": true,
"wires": true
}
}
}

View File

@ -0,0 +1,653 @@
{
"board": {
"3dviewports": [],
"design_settings": {
"defaults": {
"apply_defaults_to_fp_fields": false,
"apply_defaults_to_fp_shapes": false,
"apply_defaults_to_fp_text": false,
"board_outline_line_width": 0.1,
"copper_line_width": 0.2,
"copper_text_italic": false,
"copper_text_size_h": 1.5,
"copper_text_size_v": 1.5,
"copper_text_thickness": 0.3,
"copper_text_upright": false,
"courtyard_line_width": 0.05,
"dimension_precision": 4,
"dimension_units": 3,
"dimensions": {
"arrow_length": 1270000,
"extension_offset": 500000,
"keep_text_aligned": true,
"suppress_zeroes": false,
"text_position": 0,
"units_format": 1
},
"fab_line_width": 0.1,
"fab_text_italic": false,
"fab_text_size_h": 1.0,
"fab_text_size_v": 1.0,
"fab_text_thickness": 0.15,
"fab_text_upright": false,
"other_line_width": 0.15,
"other_text_italic": false,
"other_text_size_h": 1.0,
"other_text_size_v": 1.0,
"other_text_thickness": 0.15,
"other_text_upright": false,
"pads": {
"drill": 0.762,
"height": 1.524,
"width": 1.524
},
"silk_line_width": 0.15,
"silk_text_italic": false,
"silk_text_size_h": 1.0,
"silk_text_size_v": 1.0,
"silk_text_thickness": 0.15,
"silk_text_upright": false,
"zones": {
"min_clearance": 0.5
}
},
"diff_pair_dimensions": [],
"drc_exclusions": [],
"meta": {
"version": 2
},
"rule_severities": {
"annular_width": "error",
"clearance": "error",
"connection_width": "warning",
"copper_edge_clearance": "error",
"copper_sliver": "warning",
"courtyards_overlap": "error",
"creepage": "error",
"diff_pair_gap_out_of_range": "error",
"diff_pair_uncoupled_length_too_long": "error",
"drill_out_of_range": "error",
"duplicate_footprints": "warning",
"extra_footprint": "warning",
"footprint": "error",
"footprint_filters_mismatch": "ignore",
"footprint_symbol_mismatch": "warning",
"footprint_type_mismatch": "ignore",
"hole_clearance": "error",
"hole_near_hole": "error",
"hole_to_hole": "error",
"holes_co_located": "warning",
"invalid_outline": "error",
"isolated_copper": "warning",
"item_on_disabled_layer": "error",
"items_not_allowed": "error",
"length_out_of_range": "error",
"lib_footprint_issues": "warning",
"lib_footprint_mismatch": "warning",
"malformed_courtyard": "error",
"microvia_drill_out_of_range": "error",
"mirrored_text_on_front_layer": "warning",
"missing_courtyard": "ignore",
"missing_footprint": "warning",
"net_conflict": "warning",
"nonmirrored_text_on_back_layer": "warning",
"npth_inside_courtyard": "ignore",
"padstack": "warning",
"pth_inside_courtyard": "ignore",
"shorting_items": "error",
"silk_edge_clearance": "warning",
"silk_over_copper": "warning",
"silk_overlap": "warning",
"skew_out_of_range": "error",
"solder_mask_bridge": "error",
"starved_thermal": "error",
"text_height": "warning",
"text_on_edge_cuts": "error",
"text_thickness": "warning",
"through_hole_pad_without_hole": "error",
"too_many_vias": "error",
"track_angle": "error",
"track_dangling": "warning",
"track_segment_length": "error",
"track_width": "error",
"tracks_crossing": "error",
"unconnected_items": "error",
"unresolved_variable": "error",
"via_dangling": "warning",
"zones_intersect": "error"
},
"rules": {
"max_error": 0.005,
"min_clearance": 0.0,
"min_connection": 0.0,
"min_copper_edge_clearance": 0.0,
"min_groove_width": 0.0,
"min_hole_clearance": 0.25,
"min_hole_to_hole": 0.25,
"min_microvia_diameter": 0.2,
"min_microvia_drill": 0.1,
"min_resolved_spokes": 2,
"min_silk_clearance": 0.0,
"min_text_height": 0.8,
"min_text_thickness": 0.08,
"min_through_hole_diameter": 0.3,
"min_track_width": 0.0,
"min_via_annular_width": 0.1,
"min_via_diameter": 0.5,
"solder_mask_clearance": 0.0,
"solder_mask_min_width": 0.0,
"solder_mask_to_copper_clearance": 0.0,
"use_height_for_length_calcs": true
},
"teardrop_options": [
{
"td_onpthpad": true,
"td_onroundshapesonly": false,
"td_onsmdpad": true,
"td_ontrackend": false,
"td_onvia": true
}
],
"teardrop_parameters": [
{
"td_allow_use_two_tracks": true,
"td_curve_segcount": 1,
"td_height_ratio": 1.0,
"td_length_ratio": 0.5,
"td_maxheight": 2.0,
"td_maxlen": 1.0,
"td_on_pad_in_zone": false,
"td_target_name": "td_round_shape",
"td_width_to_size_filter_ratio": 0.9
},
{
"td_allow_use_two_tracks": true,
"td_curve_segcount": 1,
"td_height_ratio": 1.0,
"td_length_ratio": 0.5,
"td_maxheight": 2.0,
"td_maxlen": 1.0,
"td_on_pad_in_zone": false,
"td_target_name": "td_rect_shape",
"td_width_to_size_filter_ratio": 0.9
},
{
"td_allow_use_two_tracks": true,
"td_curve_segcount": 1,
"td_height_ratio": 1.0,
"td_length_ratio": 0.5,
"td_maxheight": 2.0,
"td_maxlen": 1.0,
"td_on_pad_in_zone": false,
"td_target_name": "td_track_end",
"td_width_to_size_filter_ratio": 0.9
}
],
"track_widths": [],
"tuning_pattern_settings": {
"diff_pair_defaults": {
"corner_radius_percentage": 80,
"corner_style": 1,
"max_amplitude": 1.0,
"min_amplitude": 0.2,
"single_sided": false,
"spacing": 1.0
},
"diff_pair_skew_defaults": {
"corner_radius_percentage": 80,
"corner_style": 1,
"max_amplitude": 1.0,
"min_amplitude": 0.2,
"single_sided": false,
"spacing": 0.6
},
"single_track_defaults": {
"corner_radius_percentage": 80,
"corner_style": 1,
"max_amplitude": 1.0,
"min_amplitude": 0.2,
"single_sided": false,
"spacing": 0.6
}
},
"via_dimensions": [],
"zones_allow_external_fillets": false
},
"ipc2581": {
"dist": "",
"distpn": "",
"internal_id": "",
"mfg": "",
"mpn": ""
},
"layer_pairs": [],
"layer_presets": [
{
"activeLayer": -2,
"flipBoard": false,
"layers": [
5,
25,
31
],
"name": "Front-Silk",
"renderLayers": [
"vias",
"footprint_text",
"footprint_anchors",
"ratsnest",
"grid",
"footprints_front",
"footprints_back",
"footprint_values",
"footprint_references",
"tracks",
"drc_errors",
"drawing_sheet",
"bitmaps",
"pads",
"zones",
"drc_warnings",
"locked_item_shadows",
"conflict_shadows"
]
}
],
"viewports": []
},
"boards": [],
"cvpcb": {
"equivalence_files": []
},
"erc": {
"erc_exclusions": [],
"meta": {
"version": 0
},
"pin_map": [
[
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
2
],
[
0,
2,
0,
1,
0,
0,
1,
0,
2,
2,
2,
2
],
[
0,
0,
0,
0,
0,
0,
1,
0,
1,
0,
1,
2
],
[
0,
1,
0,
0,
0,
0,
1,
1,
2,
1,
1,
2
],
[
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
2
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
2
],
[
1,
1,
1,
1,
1,
0,
1,
1,
1,
1,
1,
2
],
[
0,
0,
0,
1,
0,
0,
1,
0,
0,
0,
0,
2
],
[
0,
2,
1,
2,
0,
0,
1,
0,
2,
2,
2,
2
],
[
0,
2,
0,
1,
0,
0,
1,
0,
2,
0,
0,
2
],
[
0,
2,
1,
1,
0,
0,
1,
0,
2,
0,
0,
2
],
[
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2
]
],
"rule_severities": {
"bus_definition_conflict": "error",
"bus_entry_needed": "error",
"bus_to_bus_conflict": "error",
"bus_to_net_conflict": "error",
"conflicting_netclasses": "error",
"different_unit_footprint": "error",
"different_unit_net": "error",
"duplicate_reference": "error",
"duplicate_sheet_names": "error",
"endpoint_off_grid": "warning",
"extra_units": "error",
"footprint_filter": "ignore",
"footprint_link_issues": "warning",
"four_way_junction": "ignore",
"global_label_dangling": "warning",
"hier_label_mismatch": "error",
"label_dangling": "error",
"label_multiple_wires": "warning",
"lib_symbol_issues": "warning",
"lib_symbol_mismatch": "warning",
"missing_bidi_pin": "warning",
"missing_input_pin": "warning",
"missing_power_pin": "error",
"missing_unit": "warning",
"multiple_net_names": "warning",
"net_not_bus_member": "warning",
"no_connect_connected": "warning",
"no_connect_dangling": "warning",
"pin_not_connected": "error",
"pin_not_driven": "error",
"pin_to_pin": "warning",
"power_pin_not_driven": "error",
"same_local_global_label": "warning",
"similar_label_and_power": "warning",
"similar_labels": "warning",
"similar_power": "warning",
"simulation_model_issue": "ignore",
"single_global_label": "ignore",
"unannotated": "error",
"unconnected_wire_endpoint": "warning",
"unit_value_mismatch": "error",
"unresolved_variable": "error",
"wire_dangling": "error"
}
},
"libraries": {
"pinned_footprint_libs": [],
"pinned_symbol_libs": []
},
"meta": {
"filename": "pestdetector.kicad_pro",
"version": 3
},
"net_settings": {
"classes": [
{
"bus_width": 12,
"clearance": 0.2,
"diff_pair_gap": 0.25,
"diff_pair_via_gap": 0.25,
"diff_pair_width": 0.2,
"line_style": 0,
"microvia_diameter": 0.3,
"microvia_drill": 0.1,
"name": "Default",
"pcb_color": "rgba(0, 0, 0, 0.000)",
"priority": 2147483647,
"schematic_color": "rgba(0, 0, 0, 0.000)",
"track_width": 0.25,
"via_diameter": 0.8,
"via_drill": 0.4,
"wire_width": 6
}
],
"meta": {
"version": 4
},
"net_colors": null,
"netclass_assignments": null,
"netclass_patterns": []
},
"pcbnew": {
"last_paths": {
"gencad": "",
"idf": "",
"netlist": "",
"plot": "",
"pos_files": "",
"specctra_dsn": "",
"step": "",
"svg": "",
"vrml": ""
},
"page_layout_descr_file": ""
},
"schematic": {
"annotate_start_num": 0,
"bom_export_filename": "${PROJECTNAME}.csv",
"bom_fmt_presets": [],
"bom_fmt_settings": {
"field_delimiter": ",",
"keep_line_breaks": false,
"keep_tabs": false,
"name": "CSV",
"ref_delimiter": ",",
"ref_range_delimiter": "",
"string_delimiter": "\""
},
"bom_presets": [],
"bom_settings": {
"exclude_dnp": false,
"fields_ordered": [
{
"group_by": false,
"label": "Reference",
"name": "Reference",
"show": true
},
{
"group_by": false,
"label": "Qty",
"name": "${QUANTITY}",
"show": true
},
{
"group_by": true,
"label": "Value",
"name": "Value",
"show": true
},
{
"group_by": true,
"label": "DNP",
"name": "${DNP}",
"show": true
},
{
"group_by": true,
"label": "Exclude from BOM",
"name": "${EXCLUDE_FROM_BOM}",
"show": true
},
{
"group_by": true,
"label": "Exclude from Board",
"name": "${EXCLUDE_FROM_BOARD}",
"show": true
},
{
"group_by": true,
"label": "Footprint",
"name": "Footprint",
"show": true
},
{
"group_by": false,
"label": "Datasheet",
"name": "Datasheet",
"show": true
}
],
"filter_string": "",
"group_symbols": true,
"include_excluded_from_bom": true,
"name": "Default Editing",
"sort_asc": true,
"sort_field": "Reference"
},
"connection_grid_size": 50.0,
"drawing": {
"dashed_lines_dash_length_ratio": 12.0,
"dashed_lines_gap_length_ratio": 3.0,
"default_line_thickness": 6.0,
"default_text_size": 50.0,
"field_names": [],
"intersheets_ref_own_page": false,
"intersheets_ref_prefix": "",
"intersheets_ref_short": false,
"intersheets_ref_show": false,
"intersheets_ref_suffix": "",
"junction_size_choice": 3,
"label_size_ratio": 0.375,
"operating_point_overlay_i_precision": 3,
"operating_point_overlay_i_range": "~A",
"operating_point_overlay_v_precision": 3,
"operating_point_overlay_v_range": "~V",
"overbar_offset_ratio": 1.23,
"pin_symbol_size": 25.0,
"text_offset_ratio": 0.15
},
"legacy_lib_dir": "",
"legacy_lib_list": [],
"meta": {
"version": 1
},
"net_format_name": "",
"page_layout_descr_file": "",
"plot_directory": "",
"space_save_all_events": true,
"spice_current_sheet_as_root": false,
"spice_external_command": "spice \"%I\"",
"spice_model_current_sheet_as_root": true,
"spice_save_all_currents": false,
"spice_save_all_dissipations": false,
"spice_save_all_voltages": false,
"subpart_first_id": 65,
"subpart_id_separator": 0
},
"sheets": [
[
"968d3551-f3b3-44c4-becc-4f99fbfd63d2",
"Root"
]
],
"text_variables": {}
}

File diff suppressed because it is too large Load Diff

460
sw/analysis/analyse.py Normal file
View File

@ -0,0 +1,460 @@
import sys
import asyncio
import serial_asyncio
import re
import numpy as np
from qasync import QEventLoop, QApplication
import pyqtgraph as pg
from pyqtgraph import functions as fn
from PyQt5 import QtWidgets, QtGui
from pyqtgraph.Qt import QtCore
from PyQt5.QtWidgets import (QMainWindow, QApplication, QVBoxLayout, QHBoxLayout,
QWidget, QGroupBox, QTextEdit, QPushButton)
from PyQt5.QtCore import pyqtSlot, QTimer
import tagfind
from trilateration import *#trilaterate, trilaterate_lin, trilaterate2
def distance(p1, p2):
return ((p2[0] - p1[0])**2 + (p2[1] - p1[1])**2)**0.5
class Calibration:
def __init__(self, ab, ac, ba, bc, ca, cb):
self.ab = ab
self.ac = ac
self.ba = ba
self.bc = bc
self.ca = ca
self.cb = cb
def get_c(self):
return (self.ab + self.ba) / 2
def get_b(self):
return (self.ac + self.ca) / 2
def get_a(self):
return (self.bc + self.cb) / 2
class OutputProtocol(asyncio.Protocol):
RX_CALIB = re.compile(r'AB: ([\d.]+)[\r\n]+AC: ([\d.]+)[\r\n]+BA: ([\d.]+)[\r\n]+BC: ([\d.]+)[\r\n]+CA: ([\d.]+)[\r\n]+CB: ([\d.]+)[\r\n]', re.MULTILINE)
RX_SIGNAL= re.compile(r'A: ([\d.]+)[\r\n]+B: ([\d.]+)[\r\n]+C: ([\d.]+)[\r\n]', re.MULTILINE)
def connection_made(self, transport):
self.transport = transport
print('port opened', transport)
transport.serial.rts = False # You can manipulate Serial object via transport
self.buffer = str()
self.incalib = False
self.calib_callback = None
self.inarm = False
self.sig_callback = None
def calibrate(self, cb):
self.buffer = str()
self.incalib = True
self.calib_callback = cb
transport.write(b'c\n')
def arm(self, cb):
self.buffer = str()
self.inarm = True
self.sig_callback = cb
transport.write(b'a\n')
def _parse_sig(self):
m = self.RX_SIGNAL.search(self.buffer)
if m:
groups = m.groups()
ts = [float(f) for f in groups]
self.sig_callback(*ts)
self.inarm = False
self.buffer = str()
def _parse_calib(self):
m = self.RX_CALIB.search(self.buffer)
if m:
groups = m.groups()
calib = Calibration(*[float(f) for f in groups])
self.calib_callback(calib)
self.incalib = False
self.buffer = str()
def data_received(self, data):
self.buffer += data.decode('ascii')
if self.incalib:
self._parse_calib()
if self.inarm:
self._parse_sig()
#print('RX', self.buffer)
def connection_lost(self, exc):
print('port closed')
self.transport.loop.stop()
def pause_writing(self):
print('pause writing')
print(self.transport.get_write_buffer_size())
def resume_writing(self):
print(self.transport.get_write_buffer_size())
print('resume writing')
def on_calib(cal):
print("Calibration data:")
print(f" - AB: {cal.ab}")
print(f" - AC: {cal.ac}")
print(f" - BA: {cal.ba}")
print(f" - BC: {cal.bc}")
print(f" - CA: {cal.ca}")
print(f" - CB: {cal.cb}")
class TriangleItem(QtWidgets.QGraphicsPolygonItem):
def __init__(self, polygon, parent=None):
super().__init__(polygon, parent)
self.setBrush(QtGui.QBrush(QtGui.QColor.fromRgb(255, 255, 255)))
class HyperTriange(pg.GraphicsObject):
"""A GraphItem displays graph information as
a set of nodes connected by lines (as in 'graph theory', not 'graphics').
Useful for drawing networks, trees, etc.
"""
def __init__(self, **kwds):
pg.GraphicsObject.__init__(self)
self.scatter = pg.ScatterPlotItem()
self.scatter.setParentItem(self)
self.points = None
self.picture = None
self.pen = 'default'
self.setData(**kwds)
def setData(self, **kwds):
"""
Change the data displayed by the graph.
============== =======================================================================
**Arguments:**
pos (N,2) array of the positions of each node in the graph.
adj (M,2) array of connection data. Each row contains indexes
of two nodes that are connected or None to hide lines
pen The pen to use when drawing lines between connected
nodes. May be one of:
* QPen
* a single argument to pass to pg.mkPen
* a record array of length M
with fields (red, green, blue, alpha, width). Note
that using this option may have a significant performance
cost.
* None (to disable connection drawing)
* 'default' to use the default foreground color.
symbolPen The pen(s) used for drawing nodes.
symbolBrush The brush(es) used for drawing nodes.
``**opts`` All other keyword arguments are given to
:func:`ScatterPlotItem.setData() <pyqtgraph.ScatterPlotItem.setData>`
to affect the appearance of nodes (symbol, size, brush,
etc.)
============== =======================================================================
"""
if 'points' in kwds:
self.points = kwds['points']
self._update()
if 'pen' in kwds:
self.setPen(kwds.pop('pen'))
self._update()
if 'symbolPen' in kwds:
kwds['pen'] = kwds.pop('symbolPen')
if 'symbolBrush' in kwds:
kwds['brush'] = kwds.pop('symbolBrush')
self.scatter.setData(**kwds)
self.informViewBoundsChanged()
def _update(self):
self.picture = None
self.prepareGeometryChange()
self.update()
def setPen(self, *args, **kwargs):
"""
Set the pen used to draw graph lines.
May be:
* None to disable line drawing
* Record array with fields (red, green, blue, alpha, width)
* Any set of arguments and keyword arguments accepted by
:func:`mkPen <pyqtgraph.mkPen>`.
* 'default' to use the default foreground color.
"""
if len(args) == 1 and len(kwargs) == 0:
self.pen = args[0]
else:
self.pen = fn.mkPen(*args, **kwargs)
self.picture = None
self.update()
def generatePicture(self):
self.picture = QtGui.QPicture()
if self.pen is None or self.points is None:
return
p = QtGui.QPainter(self.picture)
try:
pts = self.points
pen = self.pen
#p.setPen(pen)
p.setPen(fn.mkPen(color=(pen[0], pen[1], pen[2], pen[3]), width=1))
#p.setPen(fn.mkPen(color=(0xFF, 0xFF, 0xFF,0xFF), width=1))
#pen = pg.getConfigOption('foreground')
#p.setPen(fn.mkPen(pen))
p.drawLine(QtCore.QPointF(*pts[0]), QtCore.QPointF(*pts[1]))
p.drawLine(QtCore.QPointF(*pts[1]), QtCore.QPointF(*pts[2]))
p.drawLine(QtCore.QPointF(*pts[2]), QtCore.QPointF(*pts[0]))
finally:
p.end()
def paint(self, p, *args):
if self.picture is None:
self.generatePicture()
if pg.getConfigOption('antialias') is True:
p.setRenderHint(p.RenderHint.Antialiasing)
self.picture.play(p)
def boundingRect(self):
return self.scatter.boundingRect()
def dataBounds(self, *args, **kwds):
return self.scatter.dataBounds(*args, **kwds)
def pixelPadding(self):
return self.scatter.pixelPadding()
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, proto):
super().__init__()
self.proto = proto
#self.w = pg.GraphicsLayoutWidget()
#self.w = pg.GraphicsView(parent=None, useOpenGL=False)
self.w = pg.GraphicsLayoutWidget(show=True)
#self.setCentralWidget(self.w)
layout = QVBoxLayout()
#triangle = TriangleItem(p)
self.calib_triangle = HyperTriange(points=[[0, -0.5], [-0.5, 0], [0, 0.5]], pen=(255, 0, 0, 255))
#self.w.addItem(triangle)
#v_temporal = self.w.addViewBox(0, 0)
#v_temporal.setAspectLocked()
#v_temporal.addItem(self.calib_triangle)
#self.w.addLabel("Calibration", 1, 0)
self.image_plot = pg.ImageItem()
v_image = self.w.addViewBox(2, 0)
v_image.setAspectLocked(True)
v_image.addItem(self.image_plot)
#self.w.addItem(self.image_plot, 1, 0)
self.constellation = HyperTriange(points=[[0, 0], [0, 0], [0, 0]], pen=(255, 0, 0, 255))
v_image.addItem(self.constellation)
self.w.addLabel("Detection", 3, 0)
self.locations = []
self.trajectories = []
#v_image.addItem(self.location)
self.v_image = v_image
self.arm_btn = QPushButton("Arm")
self.arm_btn.clicked.connect(self.on_arm)
self.clear_btn = QPushButton("Clear")
self.clear_btn.clicked.connect(self.on_clear)
layout.addWidget(self.w)
layout.addWidget(self.arm_btn)
layout.addWidget(self.clear_btn)
widget = QWidget()
widget.setLayout(layout)
self.setCentralWidget(widget)
self.calibration = None
self.armtimer = QTimer()
self.armtimer.timeout.connect(self.on_arm)
self.status = pg.TextItem(text='READY', color=(200, 200, 200), html=None, anchor=(0, 0), border=(255,0,0), fill=(64,0,0), angle=0, rotateAxis=None, ensureInBounds=False)
v_image.addItem(self.status)
@pyqtSlot()
def on_clear(self):
for l in self.locations:
self.v_image.removeItem(l)
self.locations = []
for t in self.trajectories:
self.v_image.removeItem(t)
self.trajectories = []
@pyqtSlot()
def on_arm(self):
print('ARMING')
self.proto.arm(self.enter_signal)
self.armtimer.stop()
def enter_calib(self, calib):
self.calibration = calib
def enter_signal(self, ta, tb, tc):
#f = 2/240000000
f = 1
#t_pd = 0
#ta %= 0xFFFF
#tb %= 0xFFFF
#tc %= 0xFFFF
measurements = np.array([ta, tb, tc])
meas_sorted = np.sort(measurements)
min_idx = np.argmin(measurements)
#print("minidx", min_idx)
tmin = measurements[min_idx]
"""
diff_highest = meas_sorted[0] - meas_sorted[1]
if ((meas_sorted[0] - tmin) > diff_highest) or \
((meas_sorted[1] - tmin) > diff_highest):
print("Overflow detected")
measurements[min_idx] = measurements[min_idx] + 0xFFFFFFFF
ta, tb, tc = measurements
tmin = np.min(measurements)
"""
print("TA: ", ta)
print("TB: ", tb)
print("TC: ", tc)
print("TRA: ", ta-tmin)
print("TRB: ", tb-tmin)
print("TRC: ", tc-tmin)
t_pd = 22.8
ta -= t_pd
tb -= t_pd
tc -= t_pd
ta *= f
tb *= f
tc *= f
"""
solution,*_ = trilaterate(self.points['A'], self.points['B'], self.points['C'], ta, tb, tc)
#self.location.setData(pos=(solution[0], solution[1]))
self.location.setPos(solution[0], solution[1])
print(f"detection at {solution[0]}/{solution[1]}")
"""
#pixel_fact = 359.734/600
pixel_fact = 1
a = [c*pixel_fact for c in self.points['A']]
b = [c*pixel_fact for c in self.points['B']]
c = [c*pixel_fact for c in self.points['C']]
A = distance(b,c)
B = distance(a,c)
C = distance(a,b)
s_a = A/(self.calibration.get_a() * f)
s_b = B/(self.calibration.get_b() * f)
s_c = C/(self.calibration.get_c() * f)
#s_b *= 1000
#s_b = B/(500*f)
print("s_b", s_b)
#self.proto.arm(self.enter_signal)
self.armtimer.start(500)
"""
for l in self.locations:
self.v_image.removeItem(l)
self.locations = []
"""
#solution = tdoa(a,b,c,ta,tb,tc, v=s_b)
window = 3
v_index = 0
trajectory_x = []
trajectory_y = []
for i,v in enumerate(np.linspace(s_b/2, 5*s_b, 20)):
solution = hyper(a,b,c,ta,tb,tc, v=v)
print(f"v{i}={v}")
if (solution[0] > -self.image_width * window) and (solution[0] < self.image_width * window) and \
(solution[1] > -self.image_height * window) and (solution[1] < self.image_height * window):
trajectory_x.append(solution[0])
trajectory_y.append(solution[1])
if i == v_index:
arrow = pg.ArrowItem(pos=(solution[0]/pixel_fact, solution[1]/pixel_fact), brush=(0,255*(i/20),0), angle=-45)
self.v_image.addItem(arrow)
self.locations.append(arrow)
self.status.setText("DETECTED")
else:
self.status.setText("OUT OF BOUNDS")
plot = pg.PlotCurveItem(x=trajectory_x, y=trajectory_y, pen=(0,0,255))
self.trajectories.append(plot)
self.v_image.addItem(plot)
"""
s_b = 0.007547757513716785
solution = hyper(a,b,c,ta,tb,tc, v=s_b)
if (solution[0] > -self.image_width * window) and (solution[0] < self.image_width * window) and \
(solution[1] > -self.image_height * window) and (solution[1] < self.image_height * window):
arrow = pg.ArrowItem(pos=(solution[0]/pixel_fact, solution[1]/pixel_fact), brush=(255,0,0), angle=-45)
self.v_image.addItem(arrow)
self.locations.append(arrow)
self.status.setText("DETECTED")
else:
self.status.setText("OUT OF BOUNDS")
"""
#solutions = trilaterate_lin2(a,b,c,ta,tb,tc, v=s_b)
#solutions = trilaterate_lin(a,b,c,ta,tb,tc, v=s_b)
#solutions = trilaterate2(a, b, c, ta, tb, tc)#, v=s_b)
#solutions = trilaterate_lin(a,b,c,ta,tb,tc, v=s_b)
#for l in self.locations:
# self.v_image.removeItem(l)
# self.locations = []
#for solution in solutions:
# print("S:", solution)
# #if solution[2] < 0:
# arrow = pg.ArrowItem(pos=(solution[0]/pixel_fact, solution[1]/pixel_fact), angle=-45)
# self.v_image.addItem(arrow)
# self.locations.append(arrow)
# #else:
# # print("disregarded")
print("Solutions found: ", len(self.locations))
def set_image(self, image):
self.image_plot.setImage(image)
self.points = tagfind.find_tags(image)
self.image_width,self.image_height,_ = np.shape(image)
self.status.setPos(self.image_width/2, -10)
if self.points is None:
print("Points could not be detected")
else:
print("PA: ", self.points['A'])
print("PB: ", self.points['B'])
print("PC: ", self.points['C'])
self.constellation.setData(points=[self.points['A'], self.points['B'], self.points['C']])
app = QApplication(sys.argv)
loop = QEventLoop(app)
asyncio.set_event_loop(loop)
with loop:
coro = serial_asyncio.create_serial_connection(loop, OutputProtocol, '/dev/ttyUSB0', baudrate=115200)
transport, protocol = loop.run_until_complete(coro)
#protocol.calibrate(on_calib)
main = MainWindow(protocol)
main.show()
image = tagfind.get_image('realideal1.jpg')
main.set_image(image)
#main.enter_signal(197244236935, 197244235709, 197244236682)
#main.enter_calib(Calibration(41329.000000, 142402.000000, 1757.000000 , 110173.000000, 1593.000000, 62337.000000))
main.enter_calib(Calibration(148495.000000, 145277.000000, 59769.000000,63758.000000,157637.000000,47112.000000))
loop.run_forever()

View File

@ -0,0 +1,3 @@
cmake_minimum_required(VERSION 3.16.0)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(firmwarfe)

View File

@ -0,0 +1,39 @@
This directory is intended for project header files.
A header file is a file containing C declarations and macro definitions
to be shared between several project source files. You request the use of a
header file in your project source file (C, C++, etc) located in `src` folder
by including it, with the C preprocessing directive `#include'.
```src/main.c
#include "header.h"
int main (void)
{
...
}
```
Including a header file produces the same results as copying the header file
into each source file that needs it. Such copying would be time-consuming
and error-prone. With a header file, the related declarations appear
in only one place. If they need to be changed, they can be changed in one
place, and programs that include the header file will automatically use the
new version when next recompiled. The header file eliminates the labor of
finding and changing all the copies as well as the risk that a failure to
find one copy will result in inconsistencies within a program.
In C, the usual convention is to give header files names that end with `.h'.
It is most portable to use only letters, digits, dashes, and underscores in
header file names, and at most one dot.
Read more about using header files in official GCC documentation:
* Include Syntax
* Include Operation
* Once-Only Headers
* Computed Includes
https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html

46
sw/firmware/lib/README Normal file
View File

@ -0,0 +1,46 @@
This directory is intended for project specific (private) libraries.
PlatformIO will compile them to static libraries and link into executable file.
The source code of each library should be placed in an own separate directory
("lib/your_library_name/[here are source files]").
For example, see a structure of the following two libraries `Foo` and `Bar`:
|--lib
| |
| |--Bar
| | |--docs
| | |--examples
| | |--src
| | |- Bar.c
| | |- Bar.h
| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
| |
| |--Foo
| | |- Foo.c
| | |- Foo.h
| |
| |- README --> THIS FILE
|
|- platformio.ini
|--src
|- main.c
and a contents of `src/main.c`:
```
#include <Foo.h>
#include <Bar.h>
int main (void)
{
...
}
```
PlatformIO Library Dependency Finder will find automatically dependent
libraries scanning project source files.
More information about PlatformIO Library Dependency Finder
- https://docs.platformio.org/page/librarymanager/ldf.html

View File

@ -0,0 +1 @@
idf_component_register(SRCS "main.c")

621
sw/firmware/main/main.c Normal file
View File

@ -0,0 +1,621 @@
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "driver/periph_ctrl.h"
#include "driver/timer.h"
#include "driver/ledc.h"
#include "freertos/semphr.h"
#include <string.h>
#include "esp_system.h"
#include "esp_log.h"
#include "esp_console.h"
#include "argtable3/argtable3.h"
#include "nvs.h"
#include "nvs_flash.h"
#include "esp_private/esp_clk.h"
#include "driver/mcpwm_cap.h"
/**
* Brief:
* This test code shows how to configure multiple gpio interrupts
*
* GPIO status:
* GPIO2 : output ( built-in led on Devkit-V1 )
* GPIO34 : output ( externally pulled up )
* GPIO35 : output ( externally pulled up )
*
* Test:
* Connect GPIO34 with simple switch and ground
* Connect GPIO35 with simple switch and ground
*/
#define ESP_INTR_FLAG_DEFAULT 0
#define CALIB_N 64
#define CALIB_PAUSE 50
#define BUILTIN_LED 2
#define GPIO_INPUT_DET_A 25
#define GPIO_INPUT_CAL_A 17
#define GPIO_INPUT_DET_B 26
#define GPIO_INPUT_CAL_B 18
#define GPIO_INPUT_DET_C 33 //27
#define GPIO_INPUT_CAL_C 19
#define TIMER_DIVIDER 2 // Hardware timer clock divider
#define TIMER_SCALE (TIMER_BASE_CLK / TIMER_DIVIDER) // convert counter value to seconds
SemaphoreHandle_t xSemaphore_a = NULL;
SemaphoreHandle_t xSemaphore_b = NULL;
SemaphoreHandle_t xSemaphore_c = NULL;
bool detection_armed = false;
uint64_t a_timestamp_cal = 0ULL;
uint64_t a_timestamp_det = 0ULL;
uint64_t b_timestamp_cal = 0ULL;
uint64_t b_timestamp_det = 0ULL;
uint64_t c_timestamp_cal = 0ULL;
uint64_t c_timestamp_det = 0ULL;
float ab_delta = 0;
float ac_delta = 0;
float ba_delta = 0;
float bc_delta = 0;
float ca_delta = 0;
float cb_delta = 0;
mcpwm_cap_timer_handle_t timer_a = NULL;
mcpwm_cap_channel_handle_t cap_chan_a = NULL;
mcpwm_cap_channel_handle_t cap_chan_b = NULL;
mcpwm_cap_channel_handle_t cap_chan_c = NULL;
TaskHandle_t xDetectTask = NULL;
static bool measure_a(uint32_t *p_delta_b, uint32_t *p_delta_c)
{
bool ab_okay = false;
bool ac_okay = false;
uint64_t timestep_cal = 0ULL;
// reset timestamps
b_timestamp_det = 0;
c_timestamp_det = 0;
timer_get_counter_value(TIMER_GROUP_0, TIMER_0, &timestep_cal);
// pulse the IO
ESP_ERROR_CHECK(mcpwm_capture_channel_enable(cap_chan_b));
ESP_ERROR_CHECK(mcpwm_capture_channel_enable(cap_chan_c));
ledc_set_pin(GPIO_INPUT_CAL_A, LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0);
for (int i = 0; i < 0xFFFF; ++i);
gpio_set_direction(GPIO_INPUT_CAL_A, GPIO_MODE_INPUT);
// get the a-b delta
if (b_timestamp_det > 0)
{
uint64_t delta = b_timestamp_det - timestep_cal;
*p_delta_b = delta;
ab_okay = true;
} else ESP_ERROR_CHECK(mcpwm_capture_channel_disable(cap_chan_b));
// get the a-c delta
if (c_timestamp_det > 0)
{
uint64_t delta = c_timestamp_det - timestep_cal;
*p_delta_c = delta;
ac_okay = true;
} else ESP_ERROR_CHECK(mcpwm_capture_channel_disable(cap_chan_c));
return ab_okay && ac_okay;
}
void calibrate_a(float *p_delta_b, float *p_delta_c)
{
uint32_t delta_b = 0UL;
uint32_t delta_c = 0UL;
uint32_t sum_b = 0UL;
uint32_t sum_c = 0UL;
uint32_t samples_b = 0UL;
uint32_t samples_c = 0UL;
for (int i = 0; i < CALIB_N; ++i)
{
delta_b = 0UL;
delta_c = 0UL;
bool okay = measure_a(&delta_b, &delta_c);
if (delta_b > 0)
{
sum_b += delta_b;
samples_b++;
}
if (delta_c > 0)
{
sum_c += delta_c;
samples_c++;
}
vTaskDelay(CALIB_PAUSE/portTICK_PERIOD_MS);
}
if (samples_b > 0)
{
*p_delta_b = sum_b / samples_b;
}
if (samples_c > 0)
{
*p_delta_c = sum_c / samples_c;
}
}
static bool measure_b(uint32_t *p_delta_a, uint32_t *p_delta_c)
{
bool ba_okay = false;
bool bc_okay = false;
uint64_t timestep_cal = 0ULL;
// reset timestamps
a_timestamp_det = 0;
c_timestamp_det = 0;
timer_get_counter_value(TIMER_GROUP_0, TIMER_0, &timestep_cal);
// pulse the IO
ESP_ERROR_CHECK(mcpwm_capture_channel_enable(cap_chan_a));
ESP_ERROR_CHECK(mcpwm_capture_channel_enable(cap_chan_c));
ledc_set_pin(GPIO_INPUT_CAL_B, LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0);
for (int i = 0; i < 0xFFFF; ++i);
gpio_set_direction(GPIO_INPUT_CAL_B, GPIO_MODE_INPUT);
// get the b-a delta
if (a_timestamp_det > 0)
{
uint64_t delta = a_timestamp_det - timestep_cal;
*p_delta_a = delta;
ba_okay = true;
} else ESP_ERROR_CHECK(mcpwm_capture_channel_disable(cap_chan_a));
// get the b-c delta
if (c_timestamp_det > 0)
{
uint64_t delta = c_timestamp_det - timestep_cal;
*p_delta_c = delta;
bc_okay = true;
} else ESP_ERROR_CHECK(mcpwm_capture_channel_disable(cap_chan_c));
return ba_okay && bc_okay;
}
void calibrate_b(float *p_delta_a, float *p_delta_c)
{
uint32_t delta_a = 0UL;
uint32_t delta_c = 0UL;
uint32_t sum_a = 0UL;
uint32_t sum_c = 0UL;
uint32_t samples_a = 0UL;
uint32_t samples_c = 0UL;
for (int i = 0; i < CALIB_N; ++i)
{
delta_a = 0UL;
delta_c = 0UL;
bool okay = measure_b(&delta_a, &delta_c);
if (delta_a > 0)
{
sum_a += delta_a;
samples_a++;
}
if (delta_c > 0)
{
sum_c += delta_c;
samples_c++;
}
vTaskDelay(CALIB_PAUSE/portTICK_PERIOD_MS);
}
if (samples_a > 0)
{
*p_delta_a = sum_a / samples_a;
}
if (samples_c > 0)
{
*p_delta_c = sum_c / samples_c;
}
}
static bool measure_c(uint32_t *p_delta_a, uint32_t *p_delta_b)
{
bool ca_okay = false;
bool cb_okay = false;
uint64_t timestep_cal = 0ULL;
// reset timestamps
a_timestamp_det = 0;
b_timestamp_det = 0;
timer_get_counter_value(TIMER_GROUP_0, TIMER_0, &timestep_cal);
// pulse the IO
ESP_ERROR_CHECK(mcpwm_capture_channel_enable(cap_chan_a));
ESP_ERROR_CHECK(mcpwm_capture_channel_enable(cap_chan_b));
ledc_set_pin(GPIO_INPUT_CAL_C, LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0);
for (int i = 0; i < 0xFFFF; ++i);
gpio_set_direction(GPIO_INPUT_CAL_C, GPIO_MODE_INPUT);
// get the c-a delta
if (a_timestamp_det > 0)
{
uint64_t delta = a_timestamp_det - timestep_cal;
*p_delta_a = delta;
ca_okay = true;
} else ESP_ERROR_CHECK(mcpwm_capture_channel_disable(cap_chan_a));
// get the c-b delta
if (b_timestamp_det > 0)
{
uint64_t delta = b_timestamp_det - timestep_cal;
*p_delta_b = delta;
cb_okay = true;
} else ESP_ERROR_CHECK(mcpwm_capture_channel_disable(cap_chan_b));
return ca_okay && cb_okay;
}
void calibrate_c(float *p_delta_a, float *p_delta_b)
{
uint32_t delta_a = 0UL;
uint32_t delta_b = 0UL;
uint32_t sum_a = 0UL;
uint32_t sum_b = 0UL;
uint32_t samples_a = 0UL;
uint32_t samples_b = 0UL;
for (int i = 0; i < CALIB_N; ++i)
{
delta_a = 0UL;
delta_b = 0UL;
bool okay = measure_c(&delta_a, &delta_b);
if (delta_a > 0)
{
sum_a += delta_a;
samples_a++;
}
if (delta_b > 0)
{
sum_b += delta_b;
samples_b++;
}
vTaskDelay(CALIB_PAUSE/portTICK_PERIOD_MS);
}
if (samples_a > 0)
{
*p_delta_a = sum_a / samples_a;
}
if (samples_b > 0)
{
*p_delta_b = sum_b / samples_b;
}
}
static struct {
struct arg_end *end;
} calib_args;
static int calibrate(int argc, char **argv)
{
ab_delta = 0;
ac_delta = 0;
ba_delta = 0;
bc_delta = 0;
ca_delta = 0;
cb_delta = 0;
//for(;;)
calibrate_a(&ab_delta, &ac_delta);
calibrate_b(&ba_delta, &bc_delta);
calibrate_c(&ca_delta, &cb_delta);
printf("AB: %f\n", ab_delta);
printf("AC: %f\n", ac_delta);
printf("BA: %f\n", ba_delta);
printf("BC: %f\n", bc_delta);
printf("CA: %f\n", ca_delta);
printf("CB: %f\n", cb_delta);
return 0;
}
static void example_tg0_timer_init(int timer_idx, bool auto_reload)
{
/* Select and initialize basic parameters of the timer */
timer_config_t config = {
.divider = TIMER_DIVIDER,
.counter_dir = TIMER_COUNT_UP,
.counter_en = TIMER_PAUSE,
.alarm_en = TIMER_ALARM_EN,
.auto_reload = auto_reload,
}; // default clock source is APB
timer_init(TIMER_GROUP_0, timer_idx, &config);
/* Timer's counter will initially start from value below.
Also, if auto_reload is set, this value will be automatically reload on alarm */
timer_set_counter_value(TIMER_GROUP_0, timer_idx, 0x00000000ULL);
timer_start(TIMER_GROUP_0, timer_idx);
}
static void initialize_nvs(void) {
esp_err_t err = nvs_flash_init();
if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) {
ESP_ERROR_CHECK(nvs_flash_erase());
err = nvs_flash_init();
}
ESP_ERROR_CHECK(err);
}
static struct {
struct arg_end *end;
} arm_args;
static int arm_command(int argc, char **argv)
{
while( xSemaphoreTake( xSemaphore_a, 0 ) == pdPASS );
while( xSemaphoreTake( xSemaphore_b, 0 ) == pdPASS );
while( xSemaphoreTake( xSemaphore_c, 0 ) == pdPASS );
a_timestamp_det = 0ULL;
b_timestamp_det = 0ULL;
c_timestamp_det = 0ULL;
//ESP_ERROR_CHECK(mcpwm_capture_timer_start(timer_a));
ESP_ERROR_CHECK(mcpwm_capture_channel_enable(cap_chan_a));
ESP_ERROR_CHECK(mcpwm_capture_channel_enable(cap_chan_b));
ESP_ERROR_CHECK(mcpwm_capture_channel_enable(cap_chan_c));
detection_armed = true;
return 0;
}
void detect_task(void* arg)
{
for(;;)
{
if (detection_armed)
{
while( xSemaphoreTake( xSemaphore_a, portMAX_DELAY ) != pdPASS );
while( xSemaphoreTake( xSemaphore_b, portMAX_DELAY ) != pdPASS );
while( xSemaphoreTake( xSemaphore_c, portMAX_DELAY ) != pdPASS );
printf("A: %ju\n", a_timestamp_det);
printf("B: %ju\n", b_timestamp_det);
printf("C: %ju\n", c_timestamp_det);
detection_armed = false;
}
else
{
vTaskDelay( 250 / portTICK_PERIOD_MS);
}
}
}
static bool detection_a_callback(mcpwm_cap_channel_handle_t cap_chan, const mcpwm_capture_event_data_t *edata, void *user_data)
{
TaskHandle_t task_to_notify = (TaskHandle_t)user_data;
BaseType_t high_task_wakeup = pdFALSE;
if ((edata->cap_edge == MCPWM_CAP_EDGE_POS) && (a_timestamp_det == 0)) {
// store the timestamp when pos edge is detected
a_timestamp_det = edata->cap_value;
}
//ESP_ERROR_CHECK(mcpwm_capture_channel_disable(cap_chan_a));
ESP_ERROR_CHECK(mcpwm_capture_channel_disable(cap_chan));
xSemaphoreGiveFromISR(xSemaphore_a, NULL);
return high_task_wakeup == pdTRUE;
}
static bool detection_b_callback(mcpwm_cap_channel_handle_t cap_chan, const mcpwm_capture_event_data_t *edata, void *user_data)
{
//TaskHandle_t task_to_notify = (TaskHandle_t)user_data;
BaseType_t high_task_wakeup = pdFALSE;
if ((edata->cap_edge == MCPWM_CAP_EDGE_POS) && (b_timestamp_det == 0)) {
// store the timestamp when pos edge is detected
b_timestamp_det = edata->cap_value;
}
//ESP_ERROR_CHECK(mcpwm_capture_channel_disable(cap_chan_b));
ESP_ERROR_CHECK(mcpwm_capture_channel_disable(cap_chan));
xSemaphoreGiveFromISR(xSemaphore_b, NULL);
return high_task_wakeup == pdTRUE;
}
static bool detection_c_callback(mcpwm_cap_channel_handle_t cap_chan, const mcpwm_capture_event_data_t *edata, void *user_data)
{
//TaskHandle_t task_to_notify = (TaskHandle_t)user_data;
BaseType_t high_task_wakeup = pdFALSE;
if ((edata->cap_edge == MCPWM_CAP_EDGE_POS) && (c_timestamp_det == 0)) {
// store the timestamp when pos edge is detected
c_timestamp_det = edata->cap_value;
}
//ESP_ERROR_CHECK(mcpwm_capture_channel_disable(cap_chan_c));
ESP_ERROR_CHECK(mcpwm_capture_channel_disable(cap_chan_c));
xSemaphoreGiveFromISR(xSemaphore_c, NULL);
return high_task_wakeup == pdTRUE;
}
mcpwm_cap_timer_handle_t mcpwm_capture_init_a(mcpwm_cap_channel_handle_t *p_cap_chan_a, mcpwm_cap_channel_handle_t *p_cap_chan_b, mcpwm_cap_channel_handle_t *p_cap_chan_c)
{
uint32_t res = 0UL;
const uint32_t PRESCALER = 1;
mcpwm_cap_timer_handle_t cap_timer = NULL;
mcpwm_capture_timer_config_t cap_conf = {
.clk_src = MCPWM_CAPTURE_CLK_SRC_DEFAULT,
.group_id = 0,
};
ESP_ERROR_CHECK(mcpwm_new_capture_timer(&cap_conf, &cap_timer));
ESP_ERROR_CHECK(mcpwm_capture_timer_get_resolution(cap_timer, &res));
printf("TIMER RES: %lu\n", res);
//ESP_LOGI(TAG, "Install capture channel");
mcpwm_capture_channel_config_t cap_ch_a_conf = {
.gpio_num = GPIO_INPUT_DET_A,
.prescale = PRESCALER,
//.intr_priority = 10,
// capture on pos edge only
.flags.neg_edge = false,
.flags.pos_edge = true,
// pull up internally
.flags.pull_down = true,
};
ESP_ERROR_CHECK(mcpwm_new_capture_channel(cap_timer, &cap_ch_a_conf, p_cap_chan_a));
//ESP_LOGI(TAG, "Register capture callback");
TaskHandle_t cur_task = xTaskGetCurrentTaskHandle();
mcpwm_capture_event_callbacks_t cbs = {
.on_cap = detection_a_callback,
};
ESP_ERROR_CHECK(mcpwm_capture_channel_register_event_callbacks(*p_cap_chan_a, &cbs, cur_task));
//ESP_LOGI(TAG, "Enable capture channel");
//ESP_ERROR_CHECK(mcpwm_capture_channel_enable(*p_cap_chan_a));
mcpwm_capture_channel_config_t cap_ch_b_conf = {
.gpio_num = GPIO_INPUT_DET_B,
.prescale = PRESCALER,
//.intr_priority = 9,
// capture on pos edge only
.flags.neg_edge = false,
.flags.pos_edge = true,
// pull up internally
.flags.pull_down = true,
};
ESP_ERROR_CHECK(mcpwm_new_capture_channel(cap_timer, &cap_ch_b_conf, p_cap_chan_b));
//ESP_LOGI(TAG, "Register capture callback");
mcpwm_capture_event_callbacks_t cbs_b = {
.on_cap = detection_b_callback,
};
ESP_ERROR_CHECK(mcpwm_capture_channel_register_event_callbacks(*p_cap_chan_b, &cbs_b, cur_task));
//ESP_LOGI(TAG, "Enable capture channel");
//ESP_ERROR_CHECK(mcpwm_capture_channel_enable(*p_cap_chan_b));
mcpwm_capture_channel_config_t cap_ch_c_conf = {
.gpio_num = GPIO_INPUT_DET_C,
.prescale = PRESCALER,
//.intr_priority = 8,
// capture on pos edge only
.flags.neg_edge = false,
.flags.pos_edge = true,
// pull up internally
.flags.pull_down = true,
};
ESP_ERROR_CHECK(mcpwm_new_capture_channel(cap_timer, &cap_ch_c_conf, p_cap_chan_c));
//ESP_LOGI(TAG, "Register capture callback");
mcpwm_capture_event_callbacks_t cbs_c = {
.on_cap = detection_c_callback,
};
ESP_ERROR_CHECK(mcpwm_capture_channel_register_event_callbacks(*p_cap_chan_c, &cbs_c, cur_task));
//ESP_LOGI(TAG, "Enable capture channel");
//ESP_ERROR_CHECK(mcpwm_capture_channel_enable(*p_cap_chan_c));
//ESP_LOGI(TAG, "Enable and start capture timer");
ESP_ERROR_CHECK(mcpwm_capture_timer_enable(cap_timer));
ESP_ERROR_CHECK(mcpwm_capture_timer_start(cap_timer));
//ESP_ERROR_CHECK(mcpwm_capture_timer_stop(cap_timer));
return cap_timer;
}
void app_main(void)
{
gpio_reset_pin(GPIO_INPUT_DET_A);
gpio_reset_pin(GPIO_INPUT_DET_B);
gpio_reset_pin(GPIO_INPUT_DET_C);
//PWM
// Prepare and then apply the LEDC PWM timer configuration
ledc_timer_config_t ledc_timer = {
.speed_mode = LEDC_LOW_SPEED_MODE,
.timer_num = LEDC_TIMER_0,
.duty_resolution = LEDC_TIMER_13_BIT,
.freq_hz = 3200, // Set output frequency at 5 kHz
.clk_cfg = LEDC_AUTO_CLK
};
ESP_ERROR_CHECK(ledc_timer_config(&ledc_timer));
// Prepare and then apply the LEDC PWM channel configuration
ledc_channel_config_t ledc_channel = {
.speed_mode = LEDC_LOW_SPEED_MODE,
.channel = LEDC_CHANNEL_0,
.timer_sel = LEDC_TIMER_0,
.intr_type = LEDC_INTR_DISABLE,
.gpio_num = GPIO_INPUT_CAL_A,
.duty = 4096, // Set duty to 50%
.hpoint = 0
};
ESP_ERROR_CHECK(ledc_channel_config(&ledc_channel));
gpio_set_direction(GPIO_INPUT_CAL_A, GPIO_MODE_INPUT);
/* Set the GPIO & LED direction */
gpio_set_direction(GPIO_INPUT_CAL_A, GPIO_MODE_INPUT);
gpio_set_pull_mode(GPIO_INPUT_CAL_A, GPIO_FLOATING);
gpio_set_direction(GPIO_INPUT_CAL_B, GPIO_MODE_INPUT);
gpio_set_pull_mode(GPIO_INPUT_CAL_B, GPIO_FLOATING);
gpio_set_direction(GPIO_INPUT_CAL_C, GPIO_MODE_INPUT);
gpio_set_pull_mode(GPIO_INPUT_CAL_C, GPIO_FLOATING);
example_tg0_timer_init(TIMER_0, false);
//install ISR service with default configuration
gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT);
//semaphores
xSemaphore_a = xSemaphoreCreateBinary();
xSemaphore_b = xSemaphoreCreateBinary();
xSemaphore_c = xSemaphoreCreateBinary();
timer_a = mcpwm_capture_init_a(&cap_chan_a, &cap_chan_b, &cap_chan_c);
xTaskCreate(detect_task, "detect_task", 2048, NULL, configMAX_PRIORITIES-1, NULL);
esp_console_repl_t *repl = NULL;
esp_console_repl_config_t repl_config = ESP_CONSOLE_REPL_CONFIG_DEFAULT();
/* Prompt to be printed before each line.
* This can be customized, made dynamic, etc.
*/
repl_config.prompt = ">";
repl_config.max_cmdline_length = 255;
initialize_nvs();
esp_console_dev_uart_config_t hw_config = ESP_CONSOLE_DEV_UART_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_console_new_repl_uart(&hw_config, &repl_config, &repl));
calib_args.end = arg_end(1);
esp_console_cmd_t calib_cmd = {
.command = "c",
.help = "Perform calibration",
.func = &calibrate,
.argtable = &calib_args
};
ESP_ERROR_CHECK(esp_console_cmd_register(&calib_cmd));
arm_args.end = arg_end(1);
esp_console_cmd_t arm_cmd = {
.command = "a",
.help = "Arm detections",
.func = &arm_command,
.argtable = &arm_args
};
ESP_ERROR_CHECK(esp_console_cmd_register(&arm_cmd));
// Start the REPL
ESP_ERROR_CHECK(esp_console_start_repl(repl));
}

477
sw/firmware/main/main_isr.c Normal file
View File

@ -0,0 +1,477 @@
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "driver/periph_ctrl.h"
#include "driver/timer.h"
#include "driver/ledc.h"
#include "freertos/semphr.h"
#include <string.h>
#include "esp_system.h"
#include "esp_log.h"
#include "esp_console.h"
#include "argtable3/argtable3.h"
#include "nvs.h"
#include "nvs_flash.h"
/**
* Brief:
* This test code shows how to configure multiple gpio interrupts
*
* GPIO status:
* GPIO2 : output ( built-in led on Devkit-V1 )
* GPIO34 : output ( externally pulled up )
* GPIO35 : output ( externally pulled up )
*
* Test:
* Connect GPIO34 with simple switch and ground
* Connect GPIO35 with simple switch and ground
*/
#define ESP_INTR_FLAG_DEFAULT 0
#define CALIB_N 64
#define CALIB_PAUSE 50
#define BUILTIN_LED 2
#define GPIO_INPUT_DET_A 25
#define GPIO_INPUT_CAL_A 17
#define GPIO_INPUT_DET_B 26
#define GPIO_INPUT_CAL_B 18
#define GPIO_INPUT_DET_C 27
#define GPIO_INPUT_CAL_C 19
#define TIMER_DIVIDER 2 // Hardware timer clock divider
#define TIMER_SCALE (TIMER_BASE_CLK / TIMER_DIVIDER) // convert counter value to seconds
SemaphoreHandle_t xSemaphore_a = NULL;
SemaphoreHandle_t xSemaphore_b = NULL;
SemaphoreHandle_t xSemaphore_c = NULL;
bool detection_armed = false;
uint64_t a_timestamp_cal = 0ULL;
uint64_t a_timestamp_det = 0ULL;
uint64_t b_timestamp_cal = 0ULL;
uint64_t b_timestamp_det = 0ULL;
uint64_t c_timestamp_cal = 0ULL;
uint64_t c_timestamp_det = 0ULL;
float ab_delta = 0;
float ac_delta = 0;
float ba_delta = 0;
float bc_delta = 0;
float ca_delta = 0;
float cb_delta = 0;
void IRAM_ATTR gpio_a_isr_handler(void* arg){ //++ First ISR
timer_get_counter_value(TIMER_GROUP_0, TIMER_0, &a_timestamp_det);
gpio_intr_disable(GPIO_INPUT_DET_A);
xSemaphoreGiveFromISR(xSemaphore_a, NULL);
}
void IRAM_ATTR gpio_b_isr_handler(void* arg){ //++ Second ISR
timer_get_counter_value(TIMER_GROUP_0, TIMER_0, &b_timestamp_det);
gpio_intr_disable(GPIO_INPUT_DET_B);
xSemaphoreGiveFromISR(xSemaphore_b, NULL);
}
void IRAM_ATTR gpio_c_isr_handler(void* arg) {
timer_get_counter_value(TIMER_GROUP_0, TIMER_0, &c_timestamp_det);
gpio_intr_disable(GPIO_INPUT_DET_C);
xSemaphoreGiveFromISR(xSemaphore_c, NULL);
}
static bool measure_a(uint32_t *p_delta_b, uint32_t *p_delta_c)
{
bool ab_okay = false;
bool ac_okay = false;
uint64_t timestep_cal = 0ULL;
// reset timestamps
b_timestamp_det = 0;
c_timestamp_det = 0;
timer_get_counter_value(TIMER_GROUP_0, TIMER_0, &timestep_cal);
// pulse the IO
gpio_intr_enable(GPIO_INPUT_DET_B);
gpio_intr_enable(GPIO_INPUT_DET_C);
ledc_set_pin(GPIO_INPUT_CAL_A, LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0);
for (int i = 0; i < 0xFFFF; ++i);
gpio_set_direction(GPIO_INPUT_CAL_A, GPIO_MODE_INPUT);
// get the a-b delta
if (b_timestamp_det > 0)
{
uint64_t delta = b_timestamp_det - timestep_cal;
*p_delta_b = delta;
ab_okay = true;
}
// get the a-c delta
if (c_timestamp_det > 0)
{
uint64_t delta = c_timestamp_det - timestep_cal;
*p_delta_c = delta;
ac_okay = true;
}
return ab_okay && ac_okay;
}
void calibrate_a(float *p_delta_b, float *p_delta_c)
{
uint32_t delta_b = 0UL;
uint32_t delta_c = 0UL;
uint32_t sum_b = 0UL;
uint32_t sum_c = 0UL;
uint32_t samples = 0UL;
for (int i = 0; i < CALIB_N; ++i)
{
bool okay = measure_a(&delta_b, &delta_c);
if (okay)
{
sum_b += delta_b;
sum_c += delta_c;
samples++;
}
vTaskDelay(CALIB_PAUSE/portTICK_PERIOD_MS);
}
if (samples > 0)
{
*p_delta_b = sum_b / samples;
*p_delta_c = sum_c / samples;
}
}
static bool measure_b(uint32_t *p_delta_a, uint32_t *p_delta_c)
{
bool ba_okay = false;
bool bc_okay = false;
uint64_t timestep_cal = 0ULL;
// reset timestamps
a_timestamp_det = 0;
c_timestamp_det = 0;
timer_get_counter_value(TIMER_GROUP_0, TIMER_0, &timestep_cal);
// pulse the IO
gpio_intr_enable(GPIO_INPUT_DET_A);
gpio_intr_enable(GPIO_INPUT_DET_C);
ledc_set_pin(GPIO_INPUT_CAL_B, LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0);
for (int i = 0; i < 0xFFFF; ++i);
gpio_set_direction(GPIO_INPUT_CAL_B, GPIO_MODE_INPUT);
// get the b-a delta
if (a_timestamp_det > 0)
{
uint64_t delta = a_timestamp_det - timestep_cal;
*p_delta_a = delta;
ba_okay = true;
}
// get the b-c delta
if (c_timestamp_det > 0)
{
uint64_t delta = c_timestamp_det - timestep_cal;
*p_delta_c = delta;
bc_okay = true;
}
return ba_okay && bc_okay;
}
void calibrate_b(float *p_delta_a, float *p_delta_c)
{
uint32_t delta_a = 0UL;
uint32_t delta_c = 0UL;
uint32_t sum_a = 0UL;
uint32_t sum_c = 0UL;
uint32_t samples = 0UL;
for (int i = 0; i < CALIB_N; ++i)
{
bool okay = measure_b(&delta_a, &delta_c);
if (okay)
{
sum_a += delta_a;
sum_c += delta_c;
samples++;
}
vTaskDelay(CALIB_PAUSE/portTICK_PERIOD_MS);
}
if (samples > 0)
{
*p_delta_a = sum_a / samples;
*p_delta_c = sum_c / samples;
}
}
static bool measure_c(uint32_t *p_delta_a, uint32_t *p_delta_b)
{
bool ca_okay = false;
bool cb_okay = false;
uint64_t timestep_cal = 0ULL;
// reset timestamps
a_timestamp_det = 0;
b_timestamp_det = 0;
timer_get_counter_value(TIMER_GROUP_0, TIMER_0, &timestep_cal);
// pulse the IO
gpio_intr_enable(GPIO_INPUT_DET_A);
gpio_intr_enable(GPIO_INPUT_DET_B);
ledc_set_pin(GPIO_INPUT_CAL_C, LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0);
for (int i = 0; i < 0xFFFF; ++i);
gpio_set_direction(GPIO_INPUT_CAL_C, GPIO_MODE_INPUT);
// get the c-a delta
if (a_timestamp_det > 0)
{
uint64_t delta = a_timestamp_det - timestep_cal;
*p_delta_a = delta;
ca_okay = true;
}
// get the c-b delta
if (b_timestamp_det > 0)
{
uint64_t delta = b_timestamp_det - timestep_cal;
*p_delta_b = delta;
cb_okay = true;
}
return ca_okay && cb_okay;
}
void calibrate_c(float *p_delta_a, float *p_delta_b)
{
uint32_t delta_a = 0UL;
uint32_t delta_b = 0UL;
uint32_t sum_a = 0UL;
uint32_t sum_b = 0UL;
uint32_t samples = 0UL;
for (int i = 0; i < CALIB_N; ++i)
{
bool okay = measure_c(&delta_a, &delta_b);
if (okay)
{
sum_a += delta_a;
sum_b += delta_b;
samples++;
}
vTaskDelay(CALIB_PAUSE/portTICK_PERIOD_MS);
}
if (samples > 0)
{
*p_delta_a = sum_a / samples;
*p_delta_b = sum_b / samples;
}
}
static struct {
struct arg_end *end;
} calib_args;
static int calibrate(int argc, char **argv)
{
ab_delta = 0;
ac_delta = 0;
ba_delta = 0;
bc_delta = 0;
ca_delta = 0;
cb_delta = 0;
//for(;;)
calibrate_a(&ab_delta, &ac_delta);
calibrate_b(&ba_delta, &bc_delta);
calibrate_c(&ca_delta, &cb_delta);
printf("AB: %f\n", ab_delta);
printf("AC: %f\n", ac_delta);
printf("BA: %f\n", ba_delta);
printf("BC: %f\n", bc_delta);
printf("CA: %f\n", ca_delta);
printf("CB: %f\n", cb_delta);
return 0;
}
static void example_tg0_timer_init(int timer_idx, bool auto_reload)
{
/* Select and initialize basic parameters of the timer */
timer_config_t config = {
.divider = TIMER_DIVIDER,
.counter_dir = TIMER_COUNT_UP,
.counter_en = TIMER_PAUSE,
.alarm_en = TIMER_ALARM_EN,
.auto_reload = auto_reload,
}; // default clock source is APB
timer_init(TIMER_GROUP_0, timer_idx, &config);
/* Timer's counter will initially start from value below.
Also, if auto_reload is set, this value will be automatically reload on alarm */
timer_set_counter_value(TIMER_GROUP_0, timer_idx, 0x00000000ULL);
timer_start(TIMER_GROUP_0, timer_idx);
}
static void initialize_nvs(void) {
esp_err_t err = nvs_flash_init();
if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) {
ESP_ERROR_CHECK(nvs_flash_erase());
err = nvs_flash_init();
}
ESP_ERROR_CHECK(err);
}
static struct {
struct arg_end *end;
} arm_args;
static int arm_command(int argc, char **argv)
{
while( xSemaphoreTake( xSemaphore_a, 0 ) == pdPASS );
while( xSemaphoreTake( xSemaphore_b, 0 ) == pdPASS );
while( xSemaphoreTake( xSemaphore_c, 0 ) == pdPASS );
a_timestamp_det = 0ULL;
b_timestamp_det = 0ULL;
c_timestamp_det = 0ULL;
gpio_intr_enable(GPIO_INPUT_DET_A);
gpio_intr_enable(GPIO_INPUT_DET_B);
gpio_intr_enable(GPIO_INPUT_DET_C);
detection_armed = true;
return 0;
}
void detect_task(void* arg)
{
for(;;)
{
if (detection_armed)
{
while( xSemaphoreTake( xSemaphore_a, portMAX_DELAY ) != pdPASS );
while( xSemaphoreTake( xSemaphore_b, portMAX_DELAY ) != pdPASS );
while( xSemaphoreTake( xSemaphore_c, portMAX_DELAY ) != pdPASS );
printf("A: %ju\n", a_timestamp_det);
printf("B: %ju\n", b_timestamp_det);
printf("C: %ju\n", c_timestamp_det);
detection_armed = false;
}
else
{
vTaskDelay( 250 / portTICK_PERIOD_MS);
}
}
}
void app_main(void)
{
gpio_reset_pin(GPIO_INPUT_DET_A);
gpio_reset_pin(GPIO_INPUT_DET_B);
gpio_reset_pin(GPIO_INPUT_DET_C);
//PWM
// Prepare and then apply the LEDC PWM timer configuration
ledc_timer_config_t ledc_timer = {
.speed_mode = LEDC_LOW_SPEED_MODE,
.timer_num = LEDC_TIMER_0,
.duty_resolution = LEDC_TIMER_13_BIT,
.freq_hz = 3200, // Set output frequency at 5 kHz
.clk_cfg = LEDC_AUTO_CLK
};
ESP_ERROR_CHECK(ledc_timer_config(&ledc_timer));
// Prepare and then apply the LEDC PWM channel configuration
ledc_channel_config_t ledc_channel = {
.speed_mode = LEDC_LOW_SPEED_MODE,
.channel = LEDC_CHANNEL_0,
.timer_sel = LEDC_TIMER_0,
.intr_type = LEDC_INTR_DISABLE,
.gpio_num = GPIO_INPUT_CAL_A,
.duty = 4096, // Set duty to 50%
.hpoint = 0
};
ESP_ERROR_CHECK(ledc_channel_config(&ledc_channel));
gpio_set_direction(GPIO_INPUT_CAL_A, GPIO_MODE_INPUT);
/* Set the GPIO & LED direction */
gpio_set_direction(GPIO_INPUT_DET_A, GPIO_MODE_INPUT);
gpio_set_pull_mode(GPIO_INPUT_DET_A, GPIO_PULLDOWN_ONLY); //GPIO_PULLUP_ONLY
gpio_set_direction(GPIO_INPUT_DET_B, GPIO_MODE_INPUT);
gpio_set_pull_mode(GPIO_INPUT_DET_B, GPIO_PULLDOWN_ONLY);
gpio_set_direction(GPIO_INPUT_DET_C, GPIO_MODE_INPUT);
gpio_set_pull_mode(GPIO_INPUT_DET_C, GPIO_PULLDOWN_ONLY);
gpio_set_direction(GPIO_INPUT_CAL_A, GPIO_MODE_INPUT);
gpio_set_pull_mode(GPIO_INPUT_CAL_A, GPIO_FLOATING);
gpio_set_direction(GPIO_INPUT_CAL_B, GPIO_MODE_INPUT);
gpio_set_pull_mode(GPIO_INPUT_CAL_B, GPIO_FLOATING);
gpio_set_direction(GPIO_INPUT_CAL_C, GPIO_MODE_INPUT);
gpio_set_pull_mode(GPIO_INPUT_CAL_C, GPIO_FLOATING);
example_tg0_timer_init(TIMER_0, false);
//enable interrupt on anyedge for button pin
gpio_set_intr_type(GPIO_INPUT_DET_A, GPIO_INTR_POSEDGE);
gpio_set_intr_type(GPIO_INPUT_DET_B, GPIO_INTR_POSEDGE);
gpio_set_intr_type(GPIO_INPUT_DET_C, GPIO_INTR_POSEDGE);
//install ISR service with default configuration
gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT);
//attach the interrupt service routine
gpio_isr_handler_add(GPIO_INPUT_DET_A, gpio_a_isr_handler, NULL);
gpio_isr_handler_add(GPIO_INPUT_DET_B, gpio_b_isr_handler, NULL);
gpio_isr_handler_add(GPIO_INPUT_DET_C, gpio_c_isr_handler, NULL);
gpio_intr_disable(GPIO_INPUT_DET_A);
gpio_intr_disable(GPIO_INPUT_DET_B);
gpio_intr_disable(GPIO_INPUT_DET_C);
//semaphores
xSemaphore_a = xSemaphoreCreateBinary();
xSemaphore_b = xSemaphoreCreateBinary();
xSemaphore_c = xSemaphoreCreateBinary();
xTaskCreate(detect_task, "detect_task", 2048, NULL, configMAX_PRIORITIES-1, NULL);
esp_console_repl_t *repl = NULL;
esp_console_repl_config_t repl_config = ESP_CONSOLE_REPL_CONFIG_DEFAULT();
/* Prompt to be printed before each line.
* This can be customized, made dynamic, etc.
*/
repl_config.prompt = ">";
repl_config.max_cmdline_length = 255;
initialize_nvs();
esp_console_dev_uart_config_t hw_config = ESP_CONSOLE_DEV_UART_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_console_new_repl_uart(&hw_config, &repl_config, &repl));
calib_args.end = arg_end(1);
esp_console_cmd_t calib_cmd = {
.command = "c",
.help = "Perform calibration",
.func = &calibrate,
.argtable = &calib_args
};
ESP_ERROR_CHECK(esp_console_cmd_register(&calib_cmd));
arm_args.end = arg_end(1);
esp_console_cmd_t arm_cmd = {
.command = "a",
.help = "Arm detections",
.func = &arm_command,
.argtable = &arm_args
};
ESP_ERROR_CHECK(esp_console_cmd_register(&arm_cmd));
// Start the REPL
ESP_ERROR_CHECK(esp_console_start_repl(repl));
}

View File

@ -0,0 +1,21 @@
; PlatformIO Project Configuration File
;
; Build options: build flags, source filter
; Upload options: custom upload port, speed and extra flags
; Library options: dependencies, extra library storages
; Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html
[platformio]
src_dir = main
[env:az-delivery-devkit-v4]
platform = espressif32
board = az-delivery-devkit-v4
framework = espidf
board_build.f_cpu = 240000000L
upload_protocol = esptool
monitor_speed = 115200