Heuristic42
Blog
Opengl
Meta
Rendering
0
comment
Dec 15 at 4:39
Matrices
Hello! Are you looking to elevate your online business with a p…
–
anonymous
comment
Nov 27 at 0:30
DerBard: Custom Split Mechanical Keyboard Prototype
hello
–
anonymous
comment
Nov 19 at 15:47
Matrices
[deleted]
–
anonymous
created
Oct 20 at 20:30
Iterators: pointers vs cursors
You're already doing both of these by hand. This post emphaisze…
–
pknowles
comment
Oct 10 at 10:27
Matrices
[deleted]
–
anonymous
comment
Oct 4 at 19:12
Matrices
[deleted]
–
anonymous
comment
Sep 30 at 18:51
Matrices
[deleted]
–
anonymous
comment
Sep 23 at 16:15
Matrices
[deleted]
–
anonymous
comment
Sep 21 at 6:52
Contributing
I kind of predicted what was bound to happen when my favourite …
–
anonymous
comment
Sep 7 at 1:21
Route contention when running docker and a VPN
Thank you for this. Between this and the overwriting of iptabl…
–
anonymous
comment
Sep 6 at 17:57
Making a real EMF Reader
Sorry for the random quoted text comments. I am one of those p…
–
anonymous
comment
Sep 6 at 17:48
Making a real EMF Reader
["ove! Play a tone with a buzzer and has 5 LEDs to show the “EM…
–
anonymous
comment
Sep 6 at 17:47
Making a real EMF Reader
["easure direction Measure the magnetic fie"](#q107-644-685)
–
anonymous
comment
Aug 20 at 17:01
Matrices
[deleted]
–
anonymous
comment
Aug 11 at 22:32
Matrices
[deleted]
–
anonymous
edited
Jun 8 at 22:29
Rethinking writing files with memory mapping and C++
This post introduces the motivation behind the [decodless C++ o…
–
admin
created
Jun 8 at 22:16
Rethinking writing files with memory mapping and C++
This post introduces the motivation behind the [decodless C++ o…
–
pknowles
comment
Jun 5 at 13:36
Contributing
[deleted]
–
anonymous
comment
Apr 19 at 11:24
Matrices
[deleted]
–
anonymous
comment
Apr 13 at 0:25
Matrices
[deleted]
–
anonymous
comment
Apr 5 at 9:43
Matrices
[deleted]
–
anonymous
comment
Mar 27 at 17:19
Matrices
[deleted]
–
anonymous
comment
Mar 25 at 4:59
Matrices
[deleted]
–
anonymous
comment
Mar 5 at 15:39
Matrices
[deleted]
–
anonymous
…
View All
Log in
Making a real EMF Reader
leave this field blank to prove your humanity
Article title
*
Article revisions must have a non-empty title
Article body
*
The game **phasmophobia** by [Kinetic Games](https://kineticgames.co.uk/) ([on steam](https://store.steampowered.com/app/739630/Phasmophobia/)) is about finding and identifying a ghost. It is unique in that it's just about identifying the ghost. There is no combat. Players use various items to help narrow down which ghost it is. One item is an [EMF reader](https://phasmophobia.fandom.com/wiki/EMF_Reader) that detects ghost activity. With an ameteur electronics background and a new 3D printer I built a real one as a gift. It actually works! It will "find ghosts" (with clever use of `rand()`) and actually measure magnetic fields. ![enter image description here][1] # Details It uses a MEMS magnetometer and an arduino nano to control everything. It's powered with the insides of an off-the-shelf battery pack. It can... - Measure direction - Measure the magnetic field strength - Generate random "ghost events", which may occur at a given direction or field strength and then move! - Play a tone with a buzzer and has 5 LEDs to show the "EMF level" - Charge via USB - yes, it's bettery powered - Be re-programmed by the same USB - Change modes with the press of a button, e.g. to adjust the "sensitivity" and display debug information - Display the magnetic field strength (one debug mode) and coarse direction (3 debug modes for each plane) # Pictures ![outside][2] ![inside][3] ![button][4] # Building The 3D model was built in fusion360. You can download it on [thingiverse](https://www.thingiverse.com/thing:5185602). It's based on a few reference screenshots taken at 4k. I've included them at the bottom of the page. Scale was actually loosely based on an arduino uno before I changed plans to use a nano. Point being it's likely inaccurate but still sits comfortably in the hand. It's designed to print without support and clip together with friction. ![enter image description here][5] ![enter image description here][6] The print went surprisingly well, with the exception of the part shrinking and lifting up off the bed. This is the first large print I've done and it was a new experience. It wasn't such a problem on the base, but there's a giant gap between the the two parts at the back when they're connected. I gather a hotter bed temperature might help, but I should also give more base surface area to the model for better adhesion. ![enter image description here][7] ![enter image description here][8] The label was created by hand too. I exported a fusion360 sketch to inkscape, then adding the colored bars and text with a mixture of fonts. I printed it with a regular inkjet and covered it with clear tape before cutting it out with a hobby blade. The SVG is included in the model download. ![enter image description here][9] The most physically challenging part was probably soldering the data lines from the battery pack's micro USB plug to the arduino nano's USB cable. That this worked was one of my favorite parts of this build. There's a surprising lack of information out there about getting a rechargable power pack that works with arduino projects. I'd highly recommend this approach, but I wish off the shelf kits with a separate battery and power module/charging controller existed. The battery pack was just a cheap one I found on amazon. ![enter image description here][10] The functional button for changing modes was actually an afterthought. I had modelled the button to match the game and be pressable, but hadn't had time to think about hooking it up to a real momentary button. By chance, the battery added the perfect height to be able to sit a push button between it and the top of the device. OK, I had to file down the plastic bit of the momentary button ~1mm but then it worked perfectly. Matching the notches in the battery pack's charging board to the 3D model didn't go so well and I needed to scrape away a lot of plastic before it would sit correctly. I also ended up drilling a hole for an M2 bolt to hold the board down as friction was not enough. If I printed it again this would need reworking! I almost superglued the power switch slider and luckily forcing it one way and the other unstuck it before it dried. ![enter image description here][11] # Magnetometer There are a few devices that measure magnetic fields. Initially I bought a Hall effect sensor. This was not what I wanted and not nearly sensitive The most challenging part of the software was calibrating the magnetometer. It works great out of the box with nothing nearby, but as soon as there's a giant batter right next to the sensor suddenly all the readings are way off. ![enter image description here][12] ![enter image description here][13] I started with the simple approach of an offline calibration step. I tried MotionCal from [adafruit.com](https://learn.adafruit.com/adafruit-sensorlab-magnetometer-calibration?view=all) which gets you to run some precompiled exe from the net (fun times) but that project wasn't able to parse the samples from the serial connection that I was printing. At least this is my guess after looking at [the code](https://github.com/PaulStoffregen/MotionCal/blob/master/serialdata.c#L197). I ended up cobbling together my own calibration in a python script. This reads magnetometer samples --- three x,y,z values --- from the arduino's serial output, displays them and re-runs calibration in realtime to see what's happening. It also caches them to disk so that sampling can be done just once while reworking the calibration algorithm. Code is available on [github](https://github.com/pknowles/emf_reader). At first I tried some random sphere fitting algorithms I found online, but they were not giving satisfying results at all. Perhaps this was because they were trying to maintain direction accuracy. An accurate direction was much less important for me in this project as I mainly wanted the magnetic field strength. To this end, I used least squares to take the output of the above algorithms and arbitrarily tweak all 12 calibration values to better fit the samples to a sphere. This was done with scipy's "optimize" library, where the 12 values were a standard 3x3 matrix and x,y,z offset. The result is shown below: ![enter image description here][14] I would have loved to make the calibration keep happening dynamically over time. This is pretty simple to do but without some useful libraries such as Eigen I couldn't be bothered. There is an Eigen for Arduino (including one that is meant to fit in the limited program space of a Nano) but it's pretty involved to set up especially when it needs some STL. # Software There's not much going on in the software really. In the default state the EMF reader sits in a delay() loop, waking up randomly to trigger a ghost event. An event is either a target direction or magnitude (or a constant always-on state just for fun). The target value interpolates between two values over time to make the "ghost" appear to move. The thresholds are chosen to be near the current values to increase the chance of detection, but also require you to be moving the device around in order to "find" the ghost event. When the current measurement gets close enough to the value, it displays a reading and generates a tone. The EMF level is based on the current magnitude, but may as well just be random. Surprisingly, many electronics and wiring in walls alters the magnetic field enough for the magnitude events to be meaningful. I.e. moving the device near a wall will actually trigger a reading. In other cases, the direction reading works OK too, but it's pretty clear that it's a direction and not near some physical object in the house. For the tone, I think the frequency from the game is ~650-700hz and it wobbles a bit during a hunt. # Reference images ![enter image description here][15] ![enter image description here][16] ![enter image description here][17] ![enter image description here][18] ![enter image description here][19] [1]: https://img.heuristic42.com/img/74e8a5b99881.jpg [2]: https://img.heuristic42.com/img/61b4f000faed.jpg [3]: https://img.heuristic42.com/img/fed216813218.jpg [4]: https://img.heuristic42.com/img/c465daf0ae46.jpg [5]: https://img.heuristic42.com/img/aae3a250f736.jpg [6]: https://img.heuristic42.com/img/46d9c47fefff.jpg [7]: https://img.heuristic42.com/img/f0ccf682d218.jpg [8]: https://img.heuristic42.com/img/aecc4832c12e.jpg [9]: https://img.heuristic42.com/img/a66d6ddde375.jpg [10]: https://img.heuristic42.com/img/ad5ccfab6b4a.jpg [11]: https://img.heuristic42.com/img/126f231a7570.jpg [12]: https://img.heuristic42.com/img/47a5e4385e8c.jpg [13]: https://img.heuristic42.com/img/0f388f0930df.jpg [14]: https://img.heuristic42.com/img/d573e5e5cbb7.png [15]: https://img.heuristic42.com/img/644112b7ae7b.jpg [16]: https://img.heuristic42.com/img/fb6e5f79bc53.jpg [17]: https://img.heuristic42.com/img/38bbd2b7aad5.jpg [18]: https://img.heuristic42.com/img/1536b85bcd46.jpg [19]: https://img.heuristic42.com/img/0a9e3e860748.jpg
Toggle Preview
Edit message
*
A description of the changes made
Discard Draft
Save Draft
leave this field blank to prove your humanity
Flag
the thing you clicked
for moderator attention.
Reason choice:
Spam, promoting, advertising without disclosure
Rude, inappropriate, generally offensive
Too arrogant or demeaning to others
Other
Reason:
The reason for raising the flag
Error