TF-Luna Security System
This project is an evolution of my arduino-security-system. It uses a TF-Luna lidar to detect when someone passes through my bedroom door and then, it triggers an ESP-CAM to take a picture. This picture is then sent to an application (Home Assistant or similar) using the ESP's Wi-Fi. It will even recognize if the person in the picture is me or not. The project will have a PCB and custom 3D printed case.
Created by
pro-grammer 🚀
Tier 3
8 views
0 followers
pro-grammer 🚀
added to the journal ago
Finishing the Project and Filming a Demo
As soon as I received the sensor, I got straight to work finishing the project. I began by connecting the sensor to the Uno, and sure enough, it worked exactly as intended.

Then, I made some changes to the code. I gave the web app a new look and added a baseline, an automatic page refresh, and more. Even without the TF-Luna connected to the PCB, I connected to the web page and was very happy with the result.
Now it was the moment of truth: connecting the TF-Luna to see if the baseline updated and the measurements came out correctly. I disconnected the PCB from power, connected the TF-Luna, and then powered it back up.
I reset the system and waited to see if the baseline distance would appear correctly. My heart completely dropped when “Monitoring” appeared in the top-right corner, and there was still no baseline.

Fearing the worst, I carefully disconnected the sensor from the PCB and connected it to the Uno to see if it was still alive… but it wasn’t. I was very disappointed. I had bought a new 30 euro sensor and managed to break it within minutes.
Two days passed without me trying anything, but on the third day, I decided to connect the sensor to the PCB to see if it had somehow started working again.
I noticed the red light on the left side of the sensor and immediately wondered if it was somehow working again. I refreshed the web page a few times and started seeing accurate baseline distances. I was very confused about how this had happened, but I certainly wasn’t disappointed.
It was still somewhat damaged, as it could only take a few readings before the measurements became unstable and I had to reconnect the USB cable. However, even with the unstable measurements, it was still able to detect a few baseline breaks.
The only explanation I could find was that connecting it to the Uno and then to the PCB somehow damaged the sensor, or that there might be a fault in the PCB.
I continued updating the web app carefully, making sure not to connect the TF-Luna to the Uno anymore. Some of the changes I made involved adding reset functions to see if the TF-Luna could run properly for longer without needing to reconnect the USB cable. Unfortunately, this didn’t work, and I still had to reconnect the cable.
I also added a picture gallery showing the last 100 captured images, along with a warning at the top to notify the user when the TF-Luna measurements become inaccurate.
Gallery:

Inaccurate Measurements Warning:

Although the system wasn’t fully working, as I had to constantly unplug and reconnect the USB-C cable, I still made a demo video of it. This took a long time, and the editing took even longer than I’d like to admit.
Still, in my opinion, the final video turned out great. I created and published a YouTube video, and I also added links in the README where it can be watched and downloaded.
Readme: https://github.com/adrirubio/tf-luna-security-system/blob/main/README.md
Youtube Video: https://youtu.be/43d7Ib5dUhA
I am very happy with how this project turned out, and the fact that the final version actually works is something I am very proud of. After countless hours of designing, building, and coding, I ended up with a finished product.
In the future, I might buy another TF-Luna and see if I can get the project running consistently, or if it will run into the same problems. Still, this was a great experience and definitely worth it!
pro-grammer 🚀
submitted TF-Luna Security System for ship review ago
Souptik Samanta 🚀
requested changes for TF-Luna Security System ago
Unless you make cad pcb and everything by yourself blueprint wont fund it!
And i see none in your repo
pro-grammer 🚀
submitted TF-Luna Security System for ship review ago
Logan Peterson
requested changes for TF-Luna Security System ago
Theres no demos linked for this project! (please add one)
Tier: 3
pro-grammer 🚀
submitted TF-Luna Security System for ship review ago
pro-grammer 🚀
added to the journal ago
Coding the PCB and Debugging the TF-Luna
I started by connecting the ESP32 to my computer over USB and began coding. I used Claude Code to help me write and debug the code as I worked through the project. First, the obvious thing to do was to see what the ESP32 detected, and from there we could start making the project code.
Turns out the code detected the TF-Luna on the I2C bus at 0x10, it could turn the red detection LED on and off, the green power-on LED was working, and to check if the camera was working I just had to get the correct camera pin map.
I began by trying the CAMERAMODELESPEYE pin map, but it resulted in a hard crash in espcamera_init(). Because I knew the other parts of the project were working, I started testing the camera directly in the CameraWebServer example.
At this point, I remembered that earlier in the project I had tested which pin map worked with the camera module on the ESP32 S3 WROOM 1. The camera pin map that had worked was the CAMERAMODELESP32S3_EYE. So, logically, I tried it again, expecting to get the webserver working.
Instead, I got a camera probe failure, meaning that the camera sensor ID did not match a supported or expected sensor for that configuration. This was surprising because the same pin map had worked before, and the ESP32 and camera module were the same.
Another thing I tried was the S3-test code in the project GitHub. The goal of the code was to save an image on the ESP32, but it resulted in the same error as before. At this point, I was very confused because the same code that had worked before was not working anymore.
This made me think it was a hardware-related issue. I did some more debugging with different AIs, and it turned out that the SIOD pin on the ESP32 camera and the red LED were both connected to GPIO 4. This caused electrical interference on the line, preventing proper communication with the camera sensor.
Because the camera was one of the biggest parts of the project, I decided to remove the red LED’s 60 ohm resistor, which was the one connected to GPIO 4. This made the red LED unusable but hopefully fixed the camera problems.
Sure enough, after removing the resistor, the ESP32 camera started working and successfully saved an image on the ESP32.

Now that everything was working, I, with Claude Code’s help, created the project code. Essentially, what it would do was this:
When the PCB got power, it would wait a few seconds, then the TF-Luna would set a baseline distance to the ground. Then, as soon as the baseline was broken, it would instantly take a picture using the ESP32 camera module and show that picture in a web app that the ESP32 hosted locally using the house Wi-Fi.
Once the code was created and I had double-checked that everything should work, I connected the USB cable to the ESP32 and ran the code. Upon running it, I could tell something was not working. In the serial monitor, I could see garbage baseline values like 5000 cm, 7000 cm, and so on.
Clearly, the TF-Luna wasn’t working correctly. I would like to mention that the code changed a lot during these stages, and I will try to report the sequence of events as accurately as I can.
After realizing the TF-Luna wasn’t working properly, I decided to try to get more information about what the ESP32 was receiving on the I2C bus. Sometimes, the I2C scanner would report dozens of devices on the bus, maybe 50 or even 100. Other times, it would only detect one random address, such as 0x20.
I spent hours trying to get the TF-Luna to work with my PCB and ESP32 setup. I have two TF-Lunas, so I kept swapping between them to check whether the issue was in the code, the wiring, or one of the sensors.
After a while, I also connected the other USB-C cable from the board itself so that both USB connections were plugged in at the same time. Unfortunately, the same problems continued. The scanner still showed random addresses, and I was not getting proper measurements.
At this point, I removed the TF-Lunas from the PCB and tried them separately with an Arduino Uno, just to verify that the sensors were still functioning. It would sometimes detect a random I2C address, but the values it returned were just garbage and nowhere near real distance readings.
I began to suspect I had somehow fried the TF-Lunas because both of them were acting up. I kept testing different combinations, reconnecting one sensor and then the other, hoping to see some consistent behavior.
But the results were always inconsistent. Sometimes a device would appear on the bus, and other times nothing would show up at all. Even when something was detected, the readings were clearly incorrect.
After a while, Claude Code updated the code to include a stronger reset, and one of the TF-Lunas began returning actual distance measurements. The values made sense, and the sensor showed a red light in its left “eye,” so I knew it was at least functioning.
The second TF-Luna still didn’t work, so I continued using the one that did. I then moved on to testing the full project, including the web app hosted on the ESP32.
From that point on, I was careful with how I tested. I only connected the USB cable to the ESP32 when uploading code, and I made sure the TF-Luna was disconnected while I did that. After flashing the code, I reconnected everything and tested it on the PCB.
With this approach, the system started working. The web app showed consistent readings, and the baseline distance looked correct. After a while, though, I realized that the readings started becoming unstable again and would only stabilize if I reconnected the PCB. This made me think that the TF-Luna have already been partially damaged.

While trying to improve the behavior, I made a big mistake: I accidentally connected the USB cable to the ESP32 while the TF-Luna was still attached. After that, the sensor stopped working properly. It only returned a baseline of 0 and no longer gave valid measurements.
I tested it again separately on the Nano, but it only showed random I2C addresses and no usable data. At that point, it seemed likely that the sensor had been damaged.
After this, I had a long conversation with ChatGPT, where I explained everything that had happened throughout the debugging process. Based on that, it said that the issue was likely caused by a combination of factors rather than a single mistake.
It included unstable communication on the bus, repeatedly connecting and disconnecting the TF-Luna while powered, and testing it on different setups. All of these, together, likely stressed the sensor over time until it stopped working properly.

It’s a bit frustrating to think that if I hadn’t made that mistake, I might have been able to get the project fully working. I think it stopped working after that mistake due to unstable electrical conditions, such as connecting the sensor while powered or possible voltage inconsistencies on the I2C lines, which may have stressed or damaged the sensor.
Another thing this mistake showed is that the PCB is likely still fine, and the only component that seems to be damaged is the TF-Luna. Because of this, I decided, or rather my dad decided, to buy another TF-Luna so I can try again.
The code for the project is already finished and flashed onto the ESP32, so all that’s left is to connect the new TF-Luna and test it. This time, I will be extremely careful with how I set everything up and test it, since I don’t want to risk damaging another sensor.

Unfortunately, the TF-Luna will arrive after Blueprint is over, which means I won’t be able to fully test the project before the deadline, but I’m confident it will work once I receive the new TF-Luna.
Still, I assembled the project by placing the PCB inside the case, routing the TF-Luna cable through the hole in the cover, and screwing the (currently broken) TF-Luna into place before closing the case.
I also connected a small power bank to the PCB through the USB cable cutout. Even though the project isn’t fully finished yet, everything is set up and ready for when I receive the new TF-Luna.




pro-grammer 🚀
added to the journal ago
Soldering the PCB
I received both the PCB and the 3D-printed case for Odin’s Eye a few weeks after placing the order.
PCBs:


Case and cover:

The 3D case for the TF-Luna Security System is the one on the left side of the picture.
After a few busy weeks, I finally had some free time and began soldering the PCB. I had to be careful because I'd spent a lot of money on the PCB and its components, and if I made a mistake, I would have to repurchase the parts and pay for shipping all over again.
Unfortunately, when I was about to begin soldering, I realized that I was missing another 1Ă—10 header for the ESP32 and one or two resistors. I was sure I had set the product quantities correctly in my last order, but it turned out I had only ordered one of each item.
So I placed another order, but when I tried to add the 1Ă—10 connector, it was out of stock. After searching for a while, I decided to buy two 1Ă—5 connectors, which I could solder next to each other.
This order delayed the TF-Luna Security System build by about a week. I received the parts the following week and prepared to solder that weekend.

I got everything set up and began soldering the 1×10 and the two 1×5 connectors for the ESP32. These didn’t take long, but were a bit tedious. After a while, I had both of them soldered.


After the connectors, I soldered the resistors. I placed them in their positions, soldered them, and then trimmed the ends of the leads. These were easy to do, but it took longer because I kept pausing to trim the leads, and the iron took some time to heat up again.
Then, I moved on to the hardest part to solder: the TF-Luna connector. Since the pins were small and close together, it was easy to make mistakes and harder to solder cleanly. Before soldering, I checked which side to mount the connector on.
It turned out that I had accidentally set the pins the wrong way around. 5V was on the right instead of the left, and so on. I decided to fix this by soldering the TF-Luna connector on the back of the board. This way, I could pass the cable through the space that will be on the front of the board once it's inside the case.
This solution also helps manage the cable better, since there isn’t much space between the PCB and the top of the case. It’s a good thing I checked the position of the connector, because otherwise I could have soldered it incorrectly.
How the connector should look:

How the connector looked:

Overall, I did a pretty good job when soldering. I checked, and I am quite sure there are no bridges. This is how it looks:


Lastly, I moved on to the LEDs. To get the correct distance for these, I slotted the PCB into the case and checked how far I needed to position the LEDs so they would align with the two LED cutouts on the cover. I then soldered them, and they turned out nicely.


I still haven’t connected the ESP32 to my PC to check if it detects everything correctly. I plan to do that next week, and if everything goes to plan, I would like to write the code and start testing.
The PCB build is complete for now:

I also created a README for the project and pushed all the changes to GitHub: https://github.com/adrirubio/tf-luna-security-system
pro-grammer 🚀
added to the journal ago
Ordering PCB and 3D Case
Now that I had prepared the PCB order, the next step was to order it along with the 3D case. I began by downloading both STL files (base and cover), which could be used to print the case.
STL files: https://github.com/adrirubio/tf-luna-security-system/tree/main/security-system-case/STL-files
Then, I got in contact with Pegoku from Spain, whom I found on the printing-legion website. He was very helpful and started printing straight after I gave him the four STL files (I also gave him two STL files from another project).
After about a day, all the parts were 3D printed. I shared my location with him, and he shipped them. I paid him 7.04 euros for shipping, which was very cheap, and in a few days the prints should arrive.
Now that the 3D case was on its way, I decided to also buy the PCB and the parts from Mouser. It didn’t take too long to order, and everything should arrive in 3-4 days.
JLCPCB order:

Mouser order:

pro-grammer 🚀
added to the journal ago
Preparing PCB Order
Obviously, the next step in the project is ordering the PCB and the 3D-printed case. So I didn’t waste any time preparing the PCB order. I used JLCPCB as the PCB manufacturer.
I started by uploading the Gerbers to get an instant quote. While reviewing the settings and checking exactly what I wanted, I realized I had specified a 4-layer board even though I only used 2 layers, and JLCPCB charges more for 4-layer boards.
I updated this in KiCad by changing the board to 2 copper layers in the board setup and then generated the v1.4 Gerbers. When I uploaded the Gerbers again, the price was lower, only $2.00, and $3.20 (total) after selecting Lead-Free HASL.
I also selected PCB assembly on the top side and chose "Yes" to confirm parts placement. Next, for JLCPCB to know what to assemble, they needed the PCB BOM and CPL (Pick-and-Place).
So, I downloaded these two files and followed a JLCPCB guide to prepare them for processing. Because I only wanted the SMT USB-C connector to be soldered onto the board, I created the assembly BOM specifically for the USB-C component.
JLCPCB guide: https://jlcpcb.com/help/article/How-to-generate-the-BOM-and-Centroid-file-from-KiCAD
BOM:

CPL:

Then, I selected the USB-C connector to verify the part and confirmed the 3D component placement, as everything was correct.
Finally, I received the final order quote, and the total price for PCB production, soldering, and shipping was $35.81.

I also added all the needed parts for the project to a cart on Mouser. These will be soldered by me when the PCB arrives.

pro-grammer 🚀
added to the journal ago
Finishing 3D Case Design
The Freenove team didn’t take long to respond, and they provided me with some very useful information. Specifically, they gave me the STEP file for the ESP32 board. With this, I was able to obtain the camera dimensions and its exact position on the board.
Freenove response:

I loaded the file into FreeCAD and got all the camera dimensions I needed, and then made the camera cutout on the case cover.
Freenove ESP32:

Cutout:

Loading the ESP32 STEP file made me wonder if I could also import it into my existing 3D case and compare it to the cutout I had just made. Sure enough, I found an import button and, after some positioning, managed to get this:

This led me to look in KiCad for a way to export a STEP file for the PCB. I soon found one, exported it, and imported it into the case. After some more positioning:


Now that I had imported these two models, I decided to look for a TF-Luna STEP file to finish this part of the design. After a bit of searching, I found a design on GrabCAD. I created an account and downloaded the model.
Design: https://grabcad.com/library/benewake-tf-luna-1
After importing it and placing it on the cover, I found that the original TF-Luna cutout aligned perfectly with the downloaded design.


Lastly, I added the STEP file for the socket that connects to the two rows of pins on the ESP32 header. I loaded two into the design, one for each row. Now the ESP32 connection to the PCB looks more accurate.

I’d like to point out that, in reality, the process of placing each component in its position is very tedious, and over the course of these changes I found easier ways to do it, such as installing the Manipulator add-on.
Most of the measurements on both the PCB and the 3D case were correct and aligned well, but there were a few that needed adjustment. For example, the original camera cutout was too far to the right, and importing all these files allowed me to fix it.
Towards the end, I also adjusted the USB-C cutout size because I realized that, since the USB-C connector doesn’t protrude from the case, I needed to make the opening slightly larger so the USB-C cable could fit through.

I made sure all the cutouts were correct and all the measurements were accurate. I pushed everything to GitHub and this is what the finished 3D case looks like:



GitHub: https://github.com/adrirubio/tf-luna-security-system
pro-grammer 🚀
added to the journal ago
Finishing 3D Case Design
While I waited for the Freenove team to respond, I decided to work on the USB-C cutout on the cover and fix a brainless mistake I made earlier in the schematic.
I placed the USB-C cutout 5mm above the mounting pillars. This offset would account for the PCB thickness and some mounting space. I also made the cutout a bit bigger than the actual USB-C port just to be on the safe side.

While I was double-checking everything, I found a mistake I had made in the schematic. Specifically, I had connected the intruder/blinking LED to a 5V input, which meant it would always turn on.
I fixed it by connecting it to GPIO4 on the ESP32, and I also updated the resistor because the ESP32 outputs 3.3V and I had calculated the original value (120 ohms) for 5V.
The updated resistance value is 60 ohms, but I settled for a 75-ohm resistor on Mouser because I couldn’t find a suitable 60-ohm YAGEO resistor.
75-ohm resistor: https://www.mouser.es/ProductDetail/YAGEO/MFR-25FTE52-75R?qs=sGAEpiMZZMsPqMdJzcrNwvki5I7GwxKeqMNLFU28wfg%3D

After updating the schematic, I modified the PCB with the changes and generated the v1.3 Gerbers. The previous versions were just small tweaks here and there.
Because the Freenove team didn’t respond on Friday and now it’s Saturday, I’ll have to wait until Monday, when I hopefully get a response. For now, the case is finished except for the missing camera cutout.

I also pushed all the changes to GitHub: https://github.com/adrirubio/tf-luna-security-system
pro-grammer 🚀
added to the journal ago
Continuing 3D Case Design
I began work on the LED cutouts on the cover. Using measurements from the PCB design, I soon had the cutouts aligned exactly where the LEDs sit inside the case.

Next, I worked on the TF-Luna cutout. In my other project (odins-eye), I approached this differently, but I found that the method used here was the easiest and most efficient way to mount the sensor.
All you have to do is screw the TF-Luna into the cover holes sized for M2 heat-set inserts, and then pass the cable through the slot inside to the Molex connector.

Now it was time for the ESP32 camera module cutout. This was the most challenging and time-consuming cutout, which led to another message to the FREENOVE team and various changes to the 3D case.
The difficulty with this cutout was that the camera module is connected to the ESP32, but needs to reach the top of the case. If it sat underneath the cover, it would take a picture of the underside of the cover instead of the intruder.
For a while, I thought a good solution would be to make a 14mm cutout. However, I decided this was a bad idea because the position was a bit of a guess, and honestly, I didn't feel satisfied with the design.

I had to find an alternative.
The obvious solution would be to lower the height of the case. However, since I plan to mount a power bank (approx. 50mm high) to the side of the 55mm tall case, I couldn't make the case any smaller.
Next, I thought about buying another camera module with a longer flat ribbon cable to connect to the ESP32's ZIF connector. Unfortunately, after looking at some candidates, I realized it would be very difficult to mount them to the cover.
My solution was to pad the bottom of the case by 20mm, leaving 30mm of free space. I also removed my old cutout for the PCB and added the mounting holes directly to the bottom of the case.

However, I found two problems with this solution. First, I calculated (with some help from ChatGPT) that there would still be a gap of approx. 10mm between the camera and the cover. Second, that amount of padding would waste a huge amount of filament.
After thinking it over, I came up with an idea: four pillars that rise from the bottom of the case and have the PCB mounting holes.
This way, the PCB could be ventilated and stable without wasting filament, and I could make the pillars 30mm high, leaving a perfect amount of space for the camera module.

Now that I knew the camera module would be very close to the cover, I realized I needed a precise cutout. However, just as before, I couldn't find the dimensions of the camera module or its exact position on the board.
Since the FREENOVE team was very helpful and quick to respond last time, I sent them another message asking for the camera dimensions and its position on the board.

Once I receive a response, I will update the cover and add the finishing touches to the 3D case.
pro-grammer 🚀
added to the journal ago
Started 3D Case Design
The final step in completing the security system was the 3D case design, so I didn’t waste any time getting started. I opened FreeCAD, created a new project, and began designing.
I began by creating the shape of the case. I made it 108 mm Ă— 76 mm Ă— 53 mm (length, width, and height). The inside of the box is 102 mm Ă— 70 mm Ă— 50 mm, with the wall thickness extending outward. I used these dimensions so that I could make a cutout for the PCB to slot in.

Next, I made the inside corners of the case slightly bigger by adding quarter-circle extensions. This created enough space to add the screw holes. I then added holes sized for M5 screws and applied fillets to the side and bottom corners.

After that, I worked on the cutout where the PCB would mount onto the base. First, I added four mounting holes to the PCB, each with its center 3.5 mm from the edge and with a 2.2 mm diameter. I had to rearrange some components to do this, but it wasn’t too difficult.

At this point, I made the case base a bit taller, which allowed me to give the base a 3 mm cutout (enough so that the PCB can fit well) matching the height and width of the PCB.
Lastly, I added four mounting holes with the correct diameter and depth to fit M2 heat-set inserts. Specifically, I used these heat-set inserts: https://www.amazon.es/-/en/HANGLIFE-Thermal-Threaded-Printing-Components/dp/B0CS6WXQPM/ref=sr_1_5

Finally, I added a cover to the case with the same dimensions, along with four recessed pockets for the screws that hold the case and cover together. This is what the 3D case currently looks like:

pro-grammer 🚀
added to the journal ago
Finished PCB Design
The PCB design is finished for now and looks good overall. I took into account how it would be placed inside the 3D-printed case and made a few changes based on that. Because of this, I think the version at the end of this journal is a near-final version of the PCB.
I started the design by adding a JLCPCB KiCad template, importing the footprints into the PCB editor and looking for ideal positions for the components. Since I wanted the camera on the ESP32 to come after (to the right of) the TF-Luna, I placed the TF-Luna on the left side of the PCB.
JLCPCB KiCad board settings: https://github.com/sethhillbrand/kicad_templates
Another decision I made was to have all the components on the left of the ESP32, because otherwise it would make the board too tall and leave too much unused space. After some trial and error, I ended up with this positioning.

When I added the outline of the board, it turned out to be a 41 × 102 mm board, which was perfect. I then began routing, which went smoothly. One change I did make was flipping the ESP32 footprint. This way, the pins didn’t need to be routed very far.
I also added a fill zone to connect GND for the leftover copper. At this point, I added some niceties, like giving the footprints names and adding cleanups here and there.

Next, I ran the DRC to see if there were any violations. I found a few. To fix most of them (about 40), I had to change the text size for the ESP32 header because JLCPCB’s minimum was 0.8 mm.
To fix another four violations, I made four of the USB-C pad connections solid instead of using thermal relief. The last four DRC errors were due to the hole clearance being 0.2 mm instead of 0.194 mm (a tiny difference). I didn’t change the board settings because they were already loaded from JLCPCB. Instead, I added a small note underneath the USB-C to let JLCPCB know.
I found a Reddit post mentioning that "JLCPCB basically ignores the hole clearance issue", which was reassuring.
Reddit post: https://www.reddit.com/r/KiCad/comments/16pkxiv/clearance_violation_issue/
DRC:

Finally, I gave the PCB a title, date, my name, and two Hack Club logos.

I was about to start the journal when I realized a key issue: there would be no space for the TF-Luna in the case because the LEDs were placed horizontally.
Instead, I positioned the LEDs vertically and put the resistors on the right. This way, the LEDs could be stacked one on top of the other, the TF-Luna would sit where the resistors and part of the ESP32 are, and the ESP32 camera would be to the right of the TF-Luna (also thanks to the ESP32 flip I had made earlier).
This is the finished PCB design and 3D view.
PCB:

Fill zone view:

3D views:


PCB quote from JLCPCB:

pro-grammer 🚀
added to the journal ago
Updated Freenove ESP32-S3 Header
The Freenove support team got back to me much sooner than I expected. They gave me all the measurements I needed, and honestly, I couldn't be more satisfied with the support they provided.
Freenove response:

Messages exchanged between the Freenove team and me are included in this project’s journal with their permission.
As soon as I saw their response, I thanked the Freenove team and got to work. The file they provided had every measurement I needed, though none of the measurements I had matched theirs exactly.
Freenove ESP32-S3-WROOM-1 measurements:

I started by changing the distances from the sides, then the top and bottom ones, and finally the MINI-ANT-TYPEB antenna measurements. It was quite a tedious job, because changing one measurement, like the width, meant changing other parts as well, such as the distance of the pins from the side.
Having all the measurements meant there was no guessing involved like before. Soon, I had a version that I thought was correct, so I verified all the distances, saved the footprint, and started work on the PCB design.

pro-grammer 🚀
added to the journal ago
ESP32-S3 Dev Module Header Footprint
I didn't think creating a footprint for the ESP32-S3 would be as difficult as it became. Eventually, I found a solution that works for now.
I started by creating a new footprint library and designing the footprint. I named it esp32-header. Next, I had to search for a datasheet with the board dimensions that I could use to make the footprint.
At this point, an important distinction I had to make was that the datasheet I was looking for was for the ESP32-S3-WROOM-1 DevKit, not the bare module. In my search for the datasheet, I found Espressif's official ESP32-S3-DevKit dimensions datasheet:
https://dl.espressif.com/dl/schematics/esp_idf/DXF_ESP32-S3-DevKitC-1_V1.1_20220429.pdf
I began using these dimensions to make the outline for the board and its pins. After some time, I realized an important detail: this board had 22 pins, while my board only had 20 pins. That's when I realized the board I had was the FREENOVE ESP32-S3-WROOM-1 and not the Espressif WROOM-1.
My board: https://www.amazon.es/dp/B0BMQ8F7FN?th=1
But this wasn't too big of a problem because I could find the FREENOVE WROOM-1 datasheet and give the board the right dimensions. However, I couldn't find a datasheet with the dimensions for the FREENOVE board anywhere. Because I didn't have the board with me, and I wouldn't have it until after the holidays, I couldn't get the measurements from there.
After more searching for the Freenove datasheet than I would like to admit, I sent Freenove support a message explaining my situation and asking for an official mechanical datasheet. Their website says they reply within one working day, and because I had to get a move on with the PCB design, I needed to find an alternative.
Freenove email:

I ended up making the footprint from dimensions that I estimated or got from different sources. I started with the board outline (length and width), which didn't have to be too precise (specifically the length of the board). I got these two from the Amazon page of the product (I know, not very precise), but I confirmed the width of the board from a video where it’s measured.
Amazon measurements: https://www.amazon.es/dp/B0BMQ8F7FN?th=1
Now I had to get the distance from the side of the board to the pin holes. This is the most important measurement because this would determine if the board fit, since we can more or less rely on the width of the board from those two sources.
To get the distance from the side of the board to the pin holes, I used a measurement from the Espressif DevKit dimensions datasheet, though I can't fully rely on this measurement.

From the Amazon page, I got that the length of the board was 57 mm. After setting up the 40 pins (pad diameter of 1.7 mm and hole diameter of 1 mm), I estimated that the distance from the top and bottom pins to the top and bottom edge of the board was about 2 mm, which left approx. 5 mm for the top MINI-ANT-TYPEB (antenna connector).
MINI-ANT-TYPEB:

I added some final details to the header and finished it for now. I'm not relying on the measurements to be fully accurate, and hopefully, when Freenove support responds, I'll be able to update the measurements.
I also found a 1x20 pin socket because I don't want the Freenove ESP32 to solder directly to the PCB. This way I can buy two of these, one for each side, and solder them, and then plug the ESP32 on: https://www.mouser.es/ProductDetail/TE-Connectivity/6-534237-8?qs=xDp7PGUNC%252BtPvTSnQ1ELZA%3D%3D
ESP32 header footprint:

Footprints:

pro-grammer 🚀
added to the journal ago
Assigning Footprints
Now that the schematic was finished, the next step was assigning footprints to the schematic symbols in KiCad. I usually assign footprints by finding the part on Mouser and then assigning the corresponding footprint in KiCad.
First, I had a look at the two LEDs. I already had a brief look at the LEDs in the last journal, so I selected and double-checked the resistor values I needed. I found this green LED, which is the same one I used in the Odins-Eye project: https://www.mouser.es/ProductDetail/Lumex/SSL-LX5093GD-125?qs=sGAEpiMZZMvVL5Kk7ZYykVwAM0Y%252B7BnPXhjUQ8KQTN8%3D
Then, I searched for a red LED and chose this one as it fit the requirements: https://www.mouser.es/ProductDetail/NKK-Switches/AT617C?qs=44TLCAUTxJvMB9aSr%252BpEZw%3D%3D
Next, I looked at the TF-Luna 6-pin connector. I already knew this was a Molex PicoBlade connector, so I found the same Molex 0530470610 in KiCad and on Digi-Key: https://www.digikey.es/es/products/detail/molex/0530470610/242857?s=N4IgTCBcDaIKwGYAMAWA7EgbARiSAugL5A
After that, I looked at the USB-C receptacle. In KiCad, I used the USBCReceptacleGCTUSB4105-xx-A16PTopMnt_Horizontal. It ended up being an SMT USB-C receptacle because I couldn’t find any through-hole USB-C connectors that would work. Thankfully, I found the same USB4105-GF-A on Mouser: https://www.mouser.es/ProductDetail/640-USB4105-GF-A
Lastly, I looked at the resistors. All the resistors I chose are through-hole, 1% tolerance, and 1/4 W. First, I found the 120-ohm resistor for the green LED: https://www.mouser.es/ProductDetail/YAGEO/MFR-25FRF52-120R?qs=oAGoVhmvjhydMkhPrSnrfg%3D%3D
Next, the 150-ohm resistor for the red LED: https://www.mouser.es/ProductDetail/YAGEO/MFR-25FTE52-150R?qs=sGAEpiMZZMsPqMdJzcrNwiweiCzxKzWLoYNKeVGvTMs%3D
And finally, the two 5.1k resistors for the USB-C: https://www.mouser.es/ProductDetail/YAGEO/MFR-25FBF52-5K1?qs=oAGoVhmvjhxSFmIFo3hmQQ%3D%3D
I am still missing the header footprint for the ESP32-S3 dev module, but I decided to make its footprint myself in the next journal. For now, the footprints and corresponding parts are nearly finished.


pro-grammer 🚀
added to the journal ago
Building The Schematic
The next step in building the security system was the PCB design. I started working on the schematic by listing the parts I needed and finding the right symbols I could use in KiCad's Schematic editor.
I started with the USB-C connector. Because I only needed it for power, I settled for the USBCReceptacleUSB2.016P. I used the 16-pin version instead of the 14-pin one because the 16-pin symbol has a corresponding footprint.
Next, I moved on to the TF-Luna; for this, I used a simple 6-pin connector. Then, I added two LEDs, one green and one red. The green one is for power-on, and the red one is the intruder LED.
After that, I had to find a symbol for the ESP32-S3-WROOM-1. I found one in the symbol editor and started using it. Unfortunately, I didn’t realize that the symbol was actually for the bare ESP32-WROOM-1 module and didn’t represent the actual board. This mistake led me to build an AMS1117 regulator to turn the USB’s 5V into the ESP’s 3.3V. Thankfully, it didn’t take me too long to find my mistake and fix it.
AMS1117 regulator:

I fixed this mistake by removing the AMS1117 regulator and creating my own footprint for the ESP32-S3 development board. I got the pinout from a file I downloaded here: https://github.com/Freenove/Freenove_ESP32_S3_WROOM_Board/archive/refs/heads/main.zip.
It took me a while to do this because I had to set up 40 pins, each with a corresponding number and pin name. Soon, I got it set up and began wiring everything.

I wired the USB-C by adding 5V and GND. I gave CC1 and CC2 both 5.1k pull-down resistors and wired them to GND. Next, on the TF-Luna, I wired it using I2C because it works better than UART for this project (tested in another project POC). To the ESP32 header, I wired 5V, 3.3V, and GND. I also wired the SDA and SCL from the TF-Luna. From here, I wired the LEDs: the green one uses a 120-ohm resistor, and the red one uses a 150-ohm resistor. I calculated this using some baseline LEDs I found on Mouser.

Lastly, I ran the ERC to check if there were any problems with the schematic. It reported three errors. To fix them, I added two power flags to the USB’s 5V and the ESP32’s 3.3V. I didn’t fix the last error because it was also a “power pin not driven” error, but on GND. Instead, I added a note underneath the GND on the USB-C.
With that, I finished the schematic for now. I ended by pushing the schematic changes to GitHub.
Schematic: https://github.com/adrirubio/tf-luna-security-system/tree/main/security-system-pcb/security-system-schematic

pro-grammer 🚀
added to the journal ago
POC (Proof Of Concept)
I happen to already have an ESP32-S3-WROOM-1 that has a camera on it, so I wanted to do a Proof of Concept to see if I could get the camera working and check whether the image quality was good enough to use in the project.
I already had the Arduino IDE and ESP32 library installed, so I skipped those steps. To get the camera working, though, I had to change some settings in the Tools section of the IDE. Specifically, I had to match these settings: https://github.com/Freenove/Freenove_ESP32_S3_WROOM_Board/blob/main/Arduino_Configuration_USB_UART.png. To test the camera, I used the CameraWebServer example. Inside the CameraWebServer boardconfig.h file, I had to comment out ESPEYE and uncomment ESP32S3_EYE so the example would compile and run correctly for the ESP32-S3 camera board I am using.
CameraWebServer:

Board Setup:

I didn’t get all these settings right the first time, but after a bit of trial and error, I eventually succeeded in getting the WebServer up and running. The footage was streamed on the WebServer, despite this, there was relatively low lag, and I can assure the image quality is more than enough for this project.
![]()
I wanted to see what the code for taking just a single image would look like, so I asked Claude to make some test code. I tested it and it works, although because the image is saved on the ESP32, it is harder to extract. Nonetheless, I found that taking an image on the ESP32 is easy and the quality is quite good.
Code: https://github.com/adrirubio/tf-luna-security-system/tree/main/firmware/S3-test
pro-grammer 🚀
added to the journal ago
Updated Project Design And Created BOM
After exploring different design options, I came to the conclusion that using two separate PCBs is not practical for my setup. Here are some reasons why:
- My wardrobe is directly in front of my bedroom door, which makes it harder to mount a PCB/Case
- A single PCB would simplify assembly
- A single PCB would lower cost
- A single PCB would make the project easier for others to build
The only downside to this decision is that the pictures taken when someone walks in or leaves my bedroom will be taken from above rather than directly in front. However, that’s not a big deal, because this project isn’t meant to be a real security system and is mainly for learning purposes. A picture from above is more than enough.
Another change I made to the design was swapping the original idea of using a female barrel jack to supply power to the circuit. Instead, I decided it would be better to use a power bank that can be mounted to the case and only needs to be charged every once in a while.
I made a sketch that demonstrates the complete project idea for now.
I also created the project BOM. I kept it fairly general rather than overly detailed, but it includes all the components we will need.
BOM: https://github.com/adrirubio/tf-luna-security-system/blob/main/bom.cvs

pro-grammer 🚀
added to the journal ago
Project Research
This project is the evolution of my earlier project: Arduino-Security-System
My earlier project consisted of two breadboards: one with a laser module and the other with a laser receiver. When the beam is broken, an alarm goes off. Now I want to take this project to the next level and actually use the system in my bedroom. To do this, I thought that I couldn't have an alarm because it would get annoying. After some brainstorming, I decided that what I really wanted was to track who came into my bedroom and when.
I also realized that using a laser and a receiver was a bad idea for the following reasons:
- It emits light, which can become annoying
- The laser has to hit the receiver perfectly for it to detect that there’s no object in front
- It's two separate pieces
- Only works reliably in certain lighting conditions
And so I looked for solutions. After a bit of thinking, I came up with the idea of using an ultrasonic sensor to detect if anyone passes through the door. But when I was researching it, I found a problem. Ultrasonic sensors send out a cone-shaped beam that widens as it travels. This means that if I place the PCB with the ultrasonic sensor on the ceiling of my bedroom next to the door, it could detect me even if I’m just standing near the door and think I’m an intruder.
After a bit more brainstorming, I found the best possible solution: a TF-Luna lidar.
- It doesn't emit any visible light
- It's very fast (100Hz)
- Its beam is very focused (2 degrees)
- It's very compact and lightweight
- It works in various lighting conditions
- It's only one piece
- Less prone to interference from walls and false positives
And the best part is I've already got an extra one because I bought two for my last project (odins-eye) and only ended up using one. After brainstorming some more, I came up with this as my base idea:
A PCB with a 3D-printed case will be mounted on the ceiling. It will have a TF-Luna, an ESP32, and 2 LEDs. One for ON/OFF and a red one that blinks when there is an intruder. On the wall in front of the door will be another PCB with an ESP32-CAM and another ON/OFF LED. Both of these boards will get power from two female barrel jacks. When the system is turned on, the TF-Luna will measure a baseline (distance to the floor). When an intruder steps into the bedroom and the baseline changes, it instantly triggers the camera on the wall to take a picture via the ESP’s Wi-Fi. This picture is then saved to an application like Home Assistant. In the future, the picture could be passed through an AI to detect if it’s me or not, and if it isn't, the application will notify me.
Once I was happy with the base idea, I made some sketches.
I also created the project GitHub: https://github.com/adrirubio/tf-luna-security-system


pro-grammer 🚀
started TF-Luna Security System ago
12/20/2025 11 AM - Project Research
This project is the evolution of my earlier project: Arduino-Security-System
My earlier project consisted of two breadboards: one with a laser module and the other with a laser receiver. When the beam is broken, an alarm goes off. Now I want to take this project to the next level and actually use the system in my bedroom. To do this, I thought that I couldn't have an alarm because it would get annoying. After some brainstorming, I decided that what I really wanted was to track who came into my bedroom and when.
I also realized that using a laser and a receiver was a bad idea for the following reasons:
- It emits light, which can become annoying
- The laser has to hit the receiver perfectly for it to detect that there’s no object in front
- It's two separate pieces
- Only works reliably in certain lighting conditions
And so I looked for solutions. After a bit of thinking, I came up with the idea of using an ultrasonic sensor to detect if anyone passes through the door. But when I was researching it, I found a problem. Ultrasonic sensors send out a cone-shaped beam that widens as it travels. This means that if I place the PCB with the ultrasonic sensor on the ceiling of my bedroom next to the door, it could detect me even if I’m just standing near the door and think I’m an intruder.
After a bit more brainstorming, I found the best possible solution: a TF-Luna lidar.
- It doesn't emit any visible light
- It's very fast (100Hz)
- Its beam is very focused (2 degrees)
- It's very compact and lightweight
- It works in various lighting conditions
- It's only one piece
- Less prone to interference from walls and false positives
And the best part is I've already got an extra one because I bought two for my last project (odins-eye) and only ended up using one. After brainstorming some more, I came up with this as my base idea:
A PCB with a 3D-printed case will be mounted on the ceiling. It will have a TF-Luna, an ESP32, and 2 LEDs. One for ON/OFF and a red one that blinks when there is an intruder. On the wall in front of the door will be another PCB with an ESP32-CAM and another ON/OFF LED. Both of these boards will get power from two female barrel jacks. When the system is turned on, the TF-Luna will measure a baseline (distance to the floor). When an intruder steps into the bedroom and the baseline changes, it instantly triggers the camera on the wall to take a picture via the ESP’s Wi-Fi. This picture is then saved to an application like Home Assistant. In the future, the picture could be passed through an AI to detect if it’s me or not, and if it isn't, the application will notify me.
Once I was happy with the base idea, I made some sketches.
I also created the project GitHub: https://github.com/adrirubio/tf-luna-security-system

12/20/2025 2 PM - Updated Project Design And Created BOM
After exploring different design options, I came to the conclusion that using two separate PCBs is not practical for my setup. Here are some reasons why:
- My wardrobe is directly in front of my bedroom door, which makes it harder to mount a PCB/Case
- A single PCB would simplify assembly
- A single PCB would lower cost
- A single PCB would make the project easier for others to build
The only downside to this decision is that the pictures taken when someone walks in or leaves my bedroom will be taken from above rather than directly in front. However, that’s not a big deal, because this project isn’t meant to be a real security system and is mainly for learning purposes. A picture from above is more than enough.
Another change I made to the design was swapping the original idea of using a female barrel jack to supply power to the circuit. Instead, I decided it would be better to use a power bank that can be mounted to the case and only needs to be charged every once in a while.
I made a sketch that demonstrates the complete project idea for now.
I also created the project BOM. I kept it fairly general rather than overly detailed, but it includes all the components we will need.
BOM: https://github.com/adrirubio/tf-luna-security-system/blob/main/bom.cvs
12/20/2025 6 PM - POC (Proof Of Concept)
I happen to already have an ESP32-S3-WROOM-1 that has a camera on it, so I wanted to do a Proof of Concept to see if I could get the camera working and check whether the image quality was good enough to use in the project.
I already had the Arduino IDE and ESP32 library installed, so I skipped those steps. To get the camera working, though, I had to change some settings in the Tools section of the IDE. Specifically, I had to match these settings: https://github.com/Freenove/Freenove_ESP32_S3_WROOM_Board/blob/main/Arduino_Configuration_USB_UART.png. To test the camera, I used the CameraWebServer example. Inside the CameraWebServer boardconfig.h file, I had to comment out ESPEYE and uncomment ESP32S3_EYE so the example would compile and run correctly for the ESP32-S3 camera board I am using.
CameraWebServer:

Board Setup:

I didn’t get all these settings right the first time, but after a bit of trial and error, I eventually succeeded in getting the WebServer up and running. The footage was streamed on the WebServer, despite this, there was relatively low lag, and I can assure the image quality is more than enough for this project.
![]()
I wanted to see what the code for taking just a single image would look like, so I asked Claude to make some test code. I tested it and it works, although because the image is saved on the ESP32, it is harder to extract. Nonetheless, I found that taking an image on the ESP32 is easy and the quality is quite good.
Code: https://github.com/adrirubio/tf-luna-security-system/tree/main/firmware/S3-test
12/22/2025 - Building The Schematic
The next step in building the security system was the PCB design. I started working on the schematic by listing the parts I needed and finding the right symbols I could use in KiCad's Schematic editor.
I started with the USB-C connector. Because I only needed it for power, I settled for the USBCReceptacleUSB2.016P. I used the 16-pin version instead of the 14-pin one because the 16-pin symbol has a corresponding footprint.
Next, I moved on to the TF-Luna; for this, I used a simple 6-pin connector. Then, I added two LEDs, one green and one red. The green one is for power-on, and the red one is the intruder LED.
After that, I had to find a symbol for the ESP32-S3-WROOM-1. I found one in the symbol editor and started using it. Unfortunately, I didn’t realize that the symbol was actually for the bare ESP32-WROOM-1 module and didn’t represent the actual board. This mistake led me to build an AMS1117 regulator to turn the USB’s 5V into the ESP’s 3.3V. Thankfully, it didn’t take me too long to find my mistake and fix it.
AMS1117 regulator:

I fixed this mistake by removing the AMS1117 regulator and creating my own footprint for the ESP32-S3 development board. I got the pinout from a file I downloaded here: https://github.com/Freenove/Freenove_ESP32_S3_WROOM_Board/archive/refs/heads/main.zip.
It took me a while to do this because I had to set up 40 pins, each with a corresponding number and pin name. Soon, I got it set up and began wiring everything.

I wired the USB-C by adding 5V and GND. I gave CC1 and CC2 both 5.1k pull-down resistors and wired them to GND. Next, on the TF-Luna, I wired it using I2C because it works better than UART for this project (tested in another project POC). To the ESP32 header, I wired 5V, 3.3V, and GND. I also wired the SDA and SCL from the TF-Luna. From here, I wired the LEDs: the green one uses a 120-ohm resistor, and the red one uses a 150-ohm resistor. I calculated this using some baseline LEDs I found on Mouser.

Lastly, I ran the ERC to check if there were any problems with the schematic. It reported three errors. To fix them, I added two power flags to the USB’s 5V and the ESP32’s 3.3V. I didn’t fix the last error because it was also a “power pin not driven” error, but on GND. Instead, I added a note underneath the GND on the USB-C.
With that, I finished the schematic for now. I ended by pushing the schematic changes to GitHub.
Schematic: https://github.com/adrirubio/tf-luna-security-system/tree/main/security-system-pcb/security-system-schematic
12/23/2025 - Assigning Footprints
Now that the schematic was finished, the next step was assigning footprints to the schematic symbols in KiCad. I usually assign footprints by finding the part on Mouser and then assigning the corresponding footprint in KiCad.
First, I had a look at the two LEDs. I already had a brief look at the LEDs in the last journal, so I selected and double-checked the resistor values I needed. I found this green LED, which is the same one I used in the Odins-Eye project: https://www.mouser.es/ProductDetail/Lumex/SSL-LX5093GD-125?qs=sGAEpiMZZMvVL5Kk7ZYykVwAM0Y%252B7BnPXhjUQ8KQTN8%3D
Then, I searched for a red LED and chose this one as it fit the requirements: https://www.mouser.es/ProductDetail/NKK-Switches/AT617C?qs=44TLCAUTxJvMB9aSr%252BpEZw%3D%3D
Next, I looked at the TF-Luna 6-pin connector. I already knew this was a Molex PicoBlade connector, so I found the same Molex 0530470610 in KiCad and on Digi-Key: https://www.digikey.es/es/products/detail/molex/0530470610/242857?s=N4IgTCBcDaIKwGYAMAWA7EgbARiSAugL5A
After that, I looked at the USB-C receptacle. In KiCad, I used the USBCReceptacleGCTUSB4105-xx-A16PTopMnt_Horizontal. It ended up being an SMT USB-C receptacle because I couldn’t find any through-hole USB-C connectors that would work. Thankfully, I found the same USB4105-GF-A on Mouser: https://www.mouser.es/ProductDetail/640-USB4105-GF-A
Lastly, I looked at the resistors. All the resistors I chose are through-hole, 1% tolerance, and 1/4 W. First, I found the 120-ohm resistor for the green LED: https://www.mouser.es/ProductDetail/YAGEO/MFR-25FRF52-120R?qs=oAGoVhmvjhydMkhPrSnrfg%3D%3D
Next, the 150-ohm resistor for the red LED: https://www.mouser.es/ProductDetail/YAGEO/MFR-25FTE52-150R?qs=sGAEpiMZZMsPqMdJzcrNwiweiCzxKzWLoYNKeVGvTMs%3D
And finally, the two 5.1k resistors for the USB-C: https://www.mouser.es/ProductDetail/YAGEO/MFR-25FBF52-5K1?qs=oAGoVhmvjhxSFmIFo3hmQQ%3D%3D
I am still missing the header footprint for the ESP32-S3 dev module, but I decided to make its footprint myself in the next journal. For now, the footprints and corresponding parts are nearly finished.

12/24/2025 - ESP32-S3 Dev Module Header Footprint
I didn't think creating a footprint for the ESP32-S3 would be as difficult as it became. Eventually, I found a solution that works for now.
I started by creating a new footprint library and designing the footprint. I named it esp32-header. Next, I had to search for a datasheet with the board dimensions that I could use to make the footprint.
At this point, an important distinction I had to make was that the datasheet I was looking for was for the ESP32-S3-WROOM-1 DevKit, not the bare module. In my search for the datasheet, I found Espressif's official ESP32-S3-DevKit dimensions datasheet:
https://dl.espressif.com/dl/schematics/esp_idf/DXF_ESP32-S3-DevKitC-1_V1.1_20220429.pdf
I began using these dimensions to make the outline for the board and its pins. After some time, I realized an important detail: this board had 22 pins, while my board only had 20 pins. That's when I realized the board I had was the FREENOVE ESP32-S3-WROOM-1 and not the Espressif WROOM-1.
My board: https://www.amazon.es/dp/B0BMQ8F7FN?th=1
But this wasn't too big of a problem because I could find the FREENOVE WROOM-1 datasheet and give the board the right dimensions. However, I couldn't find a datasheet with the dimensions for the FREENOVE board anywhere. Because I didn't have the board with me, and I wouldn't have it until after the holidays, I couldn't get the measurements from there.
After more searching for the Freenove datasheet than I would like to admit, I sent Freenove support a message explaining my situation and asking for an official mechanical datasheet. Their website says they reply within one working day, and because I had to get a move on with the PCB design, I needed to find an alternative.
Freenove email:

I ended up making the footprint from dimensions that I estimated or got from different sources. I started with the board outline (length and width), which didn't have to be too precise (specifically the length of the board). I got these two from the Amazon page of the product (I know, not very precise), but I confirmed the width of the board from a video where it’s measured.
Amazon measurements: https://www.amazon.es/dp/B0BMQ8F7FN?th=1
Now I had to get the distance from the side of the board to the pin holes. This is the most important measurement because this would determine if the board fit, since we can more or less rely on the width of the board from those two sources.
To get the distance from the side of the board to the pin holes, I used a measurement from the Espressif DevKit dimensions datasheet, though I can't fully rely on this measurement.

From the Amazon page, I got that the length of the board was 57 mm. After setting up the 40 pins (pad diameter of 1.7 mm and hole diameter of 1 mm), I estimated that the distance from the top and bottom pins to the top and bottom edge of the board was about 2 mm, which left approx. 5 mm for the top MINI-ANT-TYPEB (antenna connector).
MINI-ANT-TYPEB:

I added some final details to the header and finished it for now. I'm not relying on the measurements to be fully accurate, and hopefully, when Freenove support responds, I'll be able to update the measurements.
I also found a 1x20 pin socket because I don't want the Freenove ESP32 to solder directly to the PCB. This way I can buy two of these, one for each side, and solder them, and then plug the ESP32 on: https://www.mouser.es/ProductDetail/TE-Connectivity/6-534237-8?qs=xDp7PGUNC%252BtPvTSnQ1ELZA%3D%3D
ESP32 header footprint:

Footprints:
12/25/2025 - Updated Freenove ESP32-S3 Header
The Freenove support team got back to me much sooner than I expected. They gave me all the measurements I needed, and honestly, I couldn't be more satisfied with the support they provided.
Freenove response:

Messages exchanged between the Freenove team and me are included in this project’s journal with their permission.
As soon as I saw their response, I thanked the Freenove team and got to work. The file they provided had every measurement I needed, though none of the measurements I had matched theirs exactly.
Freenove ESP32-S3-WROOM-1 measurements:

I started by changing the distances from the sides, then the top and bottom ones, and finally the MINI-ANT-TYPEB antenna measurements. It was quite a tedious job, because changing one measurement, like the width, meant changing other parts as well, such as the distance of the pins from the side.
Having all the measurements meant there was no guessing involved like before. Soon, I had a version that I thought was correct, so I verified all the distances, saved the footprint, and started work on the PCB design.
12/26/2025 - Finished PCB Design
The PCB design is finished for now and looks good overall. I took into account how it would be placed inside the 3D-printed case and made a few changes based on that. Because of this, I think the version at the end of this journal is a near-final version of the PCB.
I started the design by adding a JLCPCB KiCad template, importing the footprints into the PCB editor and looking for ideal positions for the components. Since I wanted the camera on the ESP32 to come after (to the right of) the TF-Luna, I placed the TF-Luna on the left side of the PCB.
JLCPCB KiCad board settings: https://github.com/sethhillbrand/kicad_templates
Another decision I made was to have all the components on the left of the ESP32, because otherwise it would make the board too tall and leave too much unused space. After some trial and error, I ended up with this positioning.

When I added the outline of the board, it turned out to be a 41 × 102 mm board, which was perfect. I then began routing, which went smoothly. One change I did make was flipping the ESP32 footprint. This way, the pins didn’t need to be routed very far.
I also added a fill zone to connect GND for the leftover copper. At this point, I added some niceties, like giving the footprints names and adding cleanups here and there.

Next, I ran the DRC to see if there were any violations. I found a few. To fix most of them (about 40), I had to change the text size for the ESP32 header because JLCPCB’s minimum was 0.8 mm.
To fix another four violations, I made four of the USB-C pad connections solid instead of using thermal relief. The last four DRC errors were due to the hole clearance being 0.2 mm instead of 0.194 mm (a tiny difference). I didn’t change the board settings because they were already loaded from JLCPCB. Instead, I added a small note underneath the USB-C to let JLCPCB know.
I found a Reddit post mentioning that "JLCPCB basically ignores the hole clearance issue", which was reassuring.
Reddit post: https://www.reddit.com/r/KiCad/comments/16pkxiv/clearance_violation_issue/
DRC:

Finally, I gave the PCB a title, date, my name, and two Hack Club logos.

I was about to start the journal when I realized a key issue: there would be no space for the TF-Luna in the case because the LEDs were placed horizontally.
Instead, I positioned the LEDs vertically and put the resistors on the right. This way, the LEDs could be stacked one on top of the other, the TF-Luna would sit where the resistors and part of the ESP32 are, and the ESP32 camera would be to the right of the TF-Luna (also thanks to the ESP32 flip I had made earlier).
This is the finished PCB design and 3D view.
PCB:

Fill zone view:

3D views:


PCB quote from JLCPCB:
12/30/2025 - Started 3D Case Design
The final step in completing the security system was the 3D case design, so I didn’t waste any time getting started. I opened FreeCAD, created a new project, and began designing.
I began by creating the shape of the case. I made it 108 mm Ă— 76 mm Ă— 53 mm (length, width, and height). The inside of the box is 102 mm Ă— 70 mm Ă— 50 mm, with the wall thickness extending outward. I used these dimensions so that I could make a cutout for the PCB to slot in.

Next, I made the inside corners of the case slightly bigger by adding quarter-circle extensions. This created enough space to add the screw holes. I then added holes sized for M5 screws and applied fillets to the side and bottom corners.

After that, I worked on the cutout where the PCB would mount onto the base. First, I added four mounting holes to the PCB, each with its center 3.5 mm from the edge and with a 2.2 mm diameter. I had to rearrange some components to do this, but it wasn’t too difficult.

At this point, I made the case base a bit taller, which allowed me to give the base a 3 mm cutout (enough so that the PCB can fit well) matching the height and width of the PCB.
Lastly, I added four mounting holes with the correct diameter and depth to fit M2 heat-set inserts. Specifically, I used these heat-set inserts: https://www.amazon.es/-/en/HANGLIFE-Thermal-Threaded-Printing-Components/dp/B0CS6WXQPM/ref=sr_1_5

Finally, I added a cover to the case with the same dimensions, along with four recessed pockets for the screws that hold the case and cover together. This is what the 3D case currently looks like:
1/1/2026 - Continuing 3D Case Design
I began work on the LED cutouts on the cover. Using measurements from the PCB design, I soon had the cutouts aligned exactly where the LEDs sit inside the case.

Next, I worked on the TF-Luna cutout. In my other project (odins-eye), I approached this differently, but I found that the method used here was the easiest and most efficient way to mount the sensor.
All you have to do is screw the TF-Luna into the cover holes sized for M2 heat-set inserts, and then pass the cable through the slot inside to the Molex connector.

Now it was time for the ESP32 camera module cutout. This was the most challenging and time-consuming cutout, which led to another message to the FREENOVE team and various changes to the 3D case.
The difficulty with this cutout was that the camera module is connected to the ESP32, but needs to reach the top of the case. If it sat underneath the cover, it would take a picture of the underside of the cover instead of the intruder.
For a while, I thought a good solution would be to make a 14mm cutout. However, I decided this was a bad idea because the position was a bit of a guess, and honestly, I didn't feel satisfied with the design.

I had to find an alternative.
The obvious solution would be to lower the height of the case. However, since I plan to mount a power bank (approx. 50mm high) to the side of the 55mm tall case, I couldn't make the case any smaller.
Next, I thought about buying another camera module with a longer flat ribbon cable to connect to the ESP32's ZIF connector. Unfortunately, after looking at some candidates, I realized it would be very difficult to mount them to the cover.
My solution was to pad the bottom of the case by 20mm, leaving 30mm of free space. I also removed my old cutout for the PCB and added the mounting holes directly to the bottom of the case.

However, I found two problems with this solution. First, I calculated (with some help from ChatGPT) that there would still be a gap of approx. 10mm between the camera and the cover. Second, that amount of padding would waste a huge amount of filament.
After thinking it over, I came up with an idea: four pillars that rise from the bottom of the case and have the PCB mounting holes.
This way, the PCB could be ventilated and stable without wasting filament, and I could make the pillars 30mm high, leaving a perfect amount of space for the camera module.

Now that I knew the camera module would be very close to the cover, I realized I needed a precise cutout. However, just as before, I couldn't find the dimensions of the camera module or its exact position on the board.
Since the FREENOVE team was very helpful and quick to respond last time, I sent them another message asking for the camera dimensions and its position on the board.

Once I receive a response, I will update the cover and add the finishing touches to the 3D case.
1/3/2026 - Finishing 3D Case Design
While I waited for the Freenove team to respond, I decided to work on the USB-C cutout on the cover and fix a brainless mistake I made earlier in the schematic.
I placed the USB-C cutout 5mm above the mounting pillars. This offset would account for the PCB thickness and some mounting space. I also made the cutout a bit bigger than the actual USB-C port just to be on the safe side.

While I was double-checking everything, I found a mistake I had made in the schematic. Specifically, I had connected the intruder/blinking LED to a 5V input, which meant it would always turn on.
I fixed it by connecting it to GPIO4 on the ESP32, and I also updated the resistor because the ESP32 outputs 3.3V and I had calculated the original value (120 ohms) for 5V.
The updated resistance value is 60 ohms, but I settled for a 75-ohm resistor on Mouser because I couldn’t find a suitable 60-ohm YAGEO resistor.
75-ohm resistor: https://www.mouser.es/ProductDetail/YAGEO/MFR-25FTE52-75R?qs=sGAEpiMZZMsPqMdJzcrNwvki5I7GwxKeqMNLFU28wfg%3D

After updating the schematic, I modified the PCB with the changes and generated the v1.3 Gerbers. The previous versions were just small tweaks here and there.
Because the Freenove team didn’t respond on Friday and now it’s Saturday, I’ll have to wait until Monday, when I hopefully get a response. For now, the case is finished except for the missing camera cutout.

I also pushed all the changes to GitHub: https://github.com/adrirubio/tf-luna-security-system
1/5/2026 9 PM - Finishing 3D Case Design
The Freenove team didn’t take long to respond, and they provided me with some very useful information. Specifically, they gave me the STEP file for the ESP32 board. With this, I was able to obtain the camera dimensions and its exact position on the board.
Freenove response:

I loaded the file into FreeCAD and got all the camera dimensions I needed, and then made the camera cutout on the case cover.
Freenove ESP32:

Cutout:

Loading the ESP32 STEP file made me wonder if I could also import it into my existing 3D case and compare it to the cutout I had just made. Sure enough, I found an import button and, after some positioning, managed to get this:

This led me to look in KiCad for a way to export a STEP file for the PCB. I soon found one, exported it, and imported it into the case. After some more positioning:


Now that I had imported these two models, I decided to look for a TF-Luna STEP file to finish this part of the design. After a bit of searching, I found a design on GrabCAD. I created an account and downloaded the model.
Design: https://grabcad.com/library/benewake-tf-luna-1
After importing it and placing it on the cover, I found that the original TF-Luna cutout aligned perfectly with the downloaded design.


Lastly, I added the STEP file for the socket that connects to the two rows of pins on the ESP32 header. I loaded two into the design, one for each row. Now the ESP32 connection to the PCB looks more accurate.

I’d like to point out that, in reality, the process of placing each component in its position is very tedious, and over the course of these changes I found easier ways to do it, such as installing the Manipulator add-on.
Most of the measurements on both the PCB and the 3D case were correct and aligned well, but there were a few that needed adjustment. For example, the original camera cutout was too far to the right, and importing all these files allowed me to fix it.
Towards the end, I also adjusted the USB-C cutout size because I realized that, since the USB-C connector doesn’t protrude from the case, I needed to make the opening slightly larger so the USB-C cable could fit through.

I made sure all the cutouts were correct and all the measurements were accurate. I pushed everything to GitHub and this is what the finished 3D case looks like:



GitHub: https://github.com/adrirubio/tf-luna-security-system
1/5/2026 11 PM - Preparing PCB Order
Obviously, the next step in the project is ordering the PCB and the 3D-printed case. So I didn’t waste any time preparing the PCB order. I used JLCPCB as the PCB manufacturer.
I started by uploading the Gerbers to get an instant quote. While reviewing the settings and checking exactly what I wanted, I realized I had specified a 4-layer board even though I only used 2 layers, and JLCPCB charges more for 4-layer boards.
I updated this in KiCad by changing the board to 2 copper layers in the board setup and then generated the v1.4 Gerbers. When I uploaded the Gerbers again, the price was lower, only $2.00, and $3.20 (total) after selecting Lead-Free HASL.
I also selected PCB assembly on the top side and chose "Yes" to confirm parts placement. Next, for JLCPCB to know what to assemble, they needed the PCB BOM and CPL (Pick-and-Place).
So, I downloaded these two files and followed a JLCPCB guide to prepare them for processing. Because I only wanted the SMT USB-C connector to be soldered onto the board, I created the assembly BOM specifically for the USB-C component.
JLCPCB guide: https://jlcpcb.com/help/article/How-to-generate-the-BOM-and-Centroid-file-from-KiCAD
BOM:

CPL:

Then, I selected the USB-C connector to verify the part and confirmed the 3D component placement, as everything was correct.
Finally, I received the final order quote, and the total price for PCB production, soldering, and shipping was $35.81.

I also added all the needed parts for the project to a cart on Mouser. These will be soldered by me when the PCB arrives.
1/20/2026 - Ordering PCB and 3D Case
Now that I had prepared the PCB order, the next step was to order it along with the 3D case. I began by downloading both STL files (base and cover), which could be used to print the case.
STL files: https://github.com/adrirubio/tf-luna-security-system/tree/main/security-system-case/STL-files
Then, I got in contact with Pegoku from Spain, whom I found on the printing-legion website. He was very helpful and started printing straight after I gave him the four STL files (I also gave him two STL files from another project).
After about a day, all the parts were 3D printed. I shared my location with him, and he shipped them. I paid him 7.04 euros for shipping, which was very cheap, and in a few days the prints should arrive.
Now that the 3D case was on its way, I decided to also buy the PCB and the parts from Mouser. It didn’t take too long to order, and everything should arrive in 3-4 days.
JLCPCB order:

Mouser order:
3/26/2026 - Soldering the PCB
I received both the PCB and the 3D-printed case for Odin’s Eye a few weeks after placing the order.
PCBs:


Case and cover:

The 3D case for the TF-Luna Security System is the one on the left side of the picture.
After a few busy weeks, I finally had some free time and began soldering the PCB. I had to be careful because I'd spent a lot of money on the PCB and its components, and if I made a mistake, I would have to repurchase the parts and pay for shipping all over again.
Unfortunately, when I was about to begin soldering, I realized that I was missing another 1Ă—10 header for the ESP32 and one or two resistors. I was sure I had set the product quantities correctly in my last order, but it turned out I had only ordered one of each item.
So I placed another order, but when I tried to add the 1Ă—10 connector, it was out of stock. After searching for a while, I decided to buy two 1Ă—5 connectors, which I could solder next to each other.
This order delayed the TF-Luna Security System build by about a week. I received the parts the following week and prepared to solder that weekend.

I got everything set up and began soldering the 1×10 and the two 1×5 connectors for the ESP32. These didn’t take long, but were a bit tedious. After a while, I had both of them soldered.


After the connectors, I soldered the resistors. I placed them in their positions, soldered them, and then trimmed the ends of the leads. These were easy to do, but it took longer because I kept pausing to trim the leads, and the iron took some time to heat up again.
Then, I moved on to the hardest part to solder: the TF-Luna connector. Since the pins were small and close together, it was easy to make mistakes and harder to solder cleanly. Before soldering, I checked which side to mount the connector on.
It turned out that I had accidentally set the pins the wrong way around. 5V was on the right instead of the left, and so on. I decided to fix this by soldering the TF-Luna connector on the back of the board. This way, I could pass the cable through the space that will be on the front of the board once it's inside the case.
This solution also helps manage the cable better, since there isn’t much space between the PCB and the top of the case. It’s a good thing I checked the position of the connector, because otherwise I could have soldered it incorrectly.
How the connector should look:

How the connector looked:

Overall, I did a pretty good job when soldering. I checked, and I am quite sure there are no bridges. This is how it looks:


Lastly, I moved on to the LEDs. To get the correct distance for these, I slotted the PCB into the case and checked how far I needed to position the LEDs so they would align with the two LED cutouts on the cover. I then soldered them, and they turned out nicely.


I still haven’t connected the ESP32 to my PC to check if it detects everything correctly. I plan to do that next week, and if everything goes to plan, I would like to write the code and start testing.
The PCB build is complete for now:

I also created a README for the project and pushed all the changes to GitHub: https://github.com/adrirubio/tf-luna-security-system
3/28/2026 - Coding the PCB and Debugging the TF-Luna
I started by connecting the ESP32 to my computer over USB and began coding. I used Claude Code to help me write and debug the code as I worked through the project. First, the obvious thing to do was to see what the ESP32 detected, and from there we could start making the project code.
Turns out the code detected the TF-Luna on the I2C bus at 0x10, it could turn the red detection LED on and off, the green power-on LED was working, and to check if the camera was working I just had to get the correct camera pin map.
I began by trying the CAMERAMODELESPEYE pin map, but it resulted in a hard crash in espcamera_init(). Because I knew the other parts of the project were working, I started testing the camera directly in the CameraWebServer example.
At this point, I remembered that earlier in the project I had tested which pin map worked with the camera module on the ESP32 S3 WROOM 1. The camera pin map that had worked was the CAMERAMODELESP32S3_EYE. So, logically, I tried it again, expecting to get the webserver working.
Instead, I got a camera probe failure, meaning that the camera sensor ID did not match a supported or expected sensor for that configuration. This was surprising because the same pin map had worked before, and the ESP32 and camera module were the same.
Another thing I tried was the S3-test code in the project GitHub. The goal of the code was to save an image on the ESP32, but it resulted in the same error as before. At this point, I was very confused because the same code that had worked before was not working anymore.
This made me think it was a hardware-related issue. I did some more debugging with different AIs, and it turned out that the SIOD pin on the ESP32 camera and the red LED were both connected to GPIO 4. This caused electrical interference on the line, preventing proper communication with the camera sensor.
Because the camera was one of the biggest parts of the project, I decided to remove the red LED’s 60 ohm resistor, which was the one connected to GPIO 4. This made the red LED unusable but hopefully fixed the camera problems.
Sure enough, after removing the resistor, the ESP32 camera started working and successfully saved an image on the ESP32.

Now that everything was working, I, with Claude Code’s help, created the project code. Essentially, what it would do was this:
When the PCB got power, it would wait a few seconds, then the TF-Luna would set a baseline distance to the ground. Then, as soon as the baseline was broken, it would instantly take a picture using the ESP32 camera module and show that picture in a web app that the ESP32 hosted locally using the house Wi-Fi.
Once the code was created and I had double-checked that everything should work, I connected the USB cable to the ESP32 and ran the code. Upon running it, I could tell something was not working. In the serial monitor, I could see garbage baseline values like 5000 cm, 7000 cm, and so on.
Clearly, the TF-Luna wasn’t working correctly. I would like to mention that the code changed a lot during these stages, and I will try to report the sequence of events as accurately as I can.
After realizing the TF-Luna wasn’t working properly, I decided to try to get more information about what the ESP32 was receiving on the I2C bus. Sometimes, the I2C scanner would report dozens of devices on the bus, maybe 50 or even 100. Other times, it would only detect one random address, such as 0x20.
I spent hours trying to get the TF-Luna to work with my PCB and ESP32 setup. I have two TF-Lunas, so I kept swapping between them to check whether the issue was in the code, the wiring, or one of the sensors.
After a while, I also connected the other USB-C cable from the board itself so that both USB connections were plugged in at the same time. Unfortunately, the same problems continued. The scanner still showed random addresses, and I was not getting proper measurements.
At this point, I removed the TF-Lunas from the PCB and tried them separately with an Arduino Uno, just to verify that the sensors were still functioning. It would sometimes detect a random I2C address, but the values it returned were just garbage and nowhere near real distance readings.
I began to suspect I had somehow fried the TF-Lunas because both of them were acting up. I kept testing different combinations, reconnecting one sensor and then the other, hoping to see some consistent behavior.
But the results were always inconsistent. Sometimes a device would appear on the bus, and other times nothing would show up at all. Even when something was detected, the readings were clearly incorrect.
After a while, Claude Code updated the code to include a stronger reset, and one of the TF-Lunas began returning actual distance measurements. The values made sense, and the sensor showed a red light in its left “eye,” so I knew it was at least functioning.
The second TF-Luna still didn’t work, so I continued using the one that did. I then moved on to testing the full project, including the web app hosted on the ESP32.
From that point on, I was careful with how I tested. I only connected the USB cable to the ESP32 when uploading code, and I made sure the TF-Luna was disconnected while I did that. After flashing the code, I reconnected everything and tested it on the PCB.
With this approach, the system started working. The web app showed consistent readings, and the baseline distance looked correct. After a while, though, I realized that the readings started becoming unstable again and would only stabilize if I reconnected the PCB. This made me think that the TF-Luna have already been partially damaged.

While trying to improve the behavior, I made a big mistake: I accidentally connected the USB cable to the ESP32 while the TF-Luna was still attached. After that, the sensor stopped working properly. It only returned a baseline of 0 and no longer gave valid measurements.
I tested it again separately on the Nano, but it only showed random I2C addresses and no usable data. At that point, it seemed likely that the sensor had been damaged.
After this, I had a long conversation with ChatGPT, where I explained everything that had happened throughout the debugging process. Based on that, it said that the issue was likely caused by a combination of factors rather than a single mistake.
It included unstable communication on the bus, repeatedly connecting and disconnecting the TF-Luna while powered, and testing it on different setups. All of these, together, likely stressed the sensor over time until it stopped working properly.

It’s a bit frustrating to think that if I hadn’t made that mistake, I might have been able to get the project fully working. I think it stopped working after that mistake due to unstable electrical conditions, such as connecting the sensor while powered or possible voltage inconsistencies on the I2C lines, which may have stressed or damaged the sensor.
Another thing this mistake showed is that the PCB is likely still fine, and the only component that seems to be damaged is the TF-Luna. Because of this, I decided, or rather my dad decided, to buy another TF-Luna so I can try again.
The code for the project is already finished and flashed onto the ESP32, so all that’s left is to connect the new TF-Luna and test it. This time, I will be extremely careful with how I set everything up and test it, since I don’t want to risk damaging another sensor.

Unfortunately, the TF-Luna will arrive after Blueprint is over, which means I won’t be able to fully test the project before the deadline, but I’m confident it will work once I receive the new TF-Luna.
Still, I assembled the project by placing the PCB inside the case, routing the TF-Luna cable through the hole in the cover, and screwing the (currently broken) TF-Luna into place before closing the case.
I also connected a small power bank to the PCB through the USB cable cutout. Even though the project isn’t fully finished yet, everything is set up and ready for when I receive the new TF-Luna.



4/13/2026 - Finishing the Project and Filming a Demo
As soon as I received the sensor, I got straight to work finishing the project. I began by connecting the sensor to the Uno, and sure enough, it worked exactly as intended.

Then, I made some changes to the code. I gave the web app a new look and added a baseline, an automatic page refresh, and more. Even without the TF-Luna connected to the PCB, I connected to the web page and was very happy with the result.
Now it was the moment of truth: connecting the TF-Luna to see if the baseline updated and the measurements came out correctly. I disconnected the PCB from power, connected the TF-Luna, and then powered it back up.
I reset the system and waited to see if the baseline distance would appear correctly. My heart completely dropped when “Monitoring” appeared in the top-right corner, and there was still no baseline.

Fearing the worst, I carefully disconnected the sensor from the PCB and connected it to the Uno to see if it was still alive… but it wasn’t. I was very disappointed. I had bought a new 30 euro sensor and managed to break it within minutes.
Two days passed without me trying anything, but on the third day, I decided to connect the sensor to the PCB to see if it had somehow started working again.
I noticed the red light on the left side of the sensor and immediately wondered if it was somehow working again. I refreshed the web page a few times and started seeing accurate baseline distances. I was very confused about how this had happened, but I certainly wasn’t disappointed.
It was still somewhat damaged, as it could only take a few readings before the measurements became unstable and I had to reconnect the USB cable. However, even with the unstable measurements, it was still able to detect a few baseline breaks.
The only explanation I could find was that connecting it to the Uno and then to the PCB somehow damaged the sensor, or that there might be a fault in the PCB.
I continued updating the web app carefully, making sure not to connect the TF-Luna to the Uno anymore. Some of the changes I made involved adding reset functions to see if the TF-Luna could run properly for longer without needing to reconnect the USB cable. Unfortunately, this didn’t work, and I still had to reconnect the cable.
I also added a picture gallery showing the last 100 captured images, along with a warning at the top to notify the user when the TF-Luna measurements become inaccurate.
Gallery:

Inaccurate Measurements Warning:

Although the system wasn’t fully working, as I had to constantly unplug and reconnect the USB-C cable, I still made a demo video of it. This took a long time, and the editing took even longer than I’d like to admit.
Still, in my opinion, the final video turned out great. I created and published a YouTube video, and I also added links in the README where it can be watched and downloaded.
Readme: https://github.com/adrirubio/tf-luna-security-system/blob/main/README.md
Youtube Video: https://youtu.be/43d7Ib5dUhA
I am very happy with how this project turned out, and the fact that the final version actually works is something I am very proud of. After countless hours of designing, building, and coding, I ended up with a finished product.
In the future, I might buy another TF-Luna and see if I can get the project running consistently, or if it will run into the same problems. Still, this was a great experience and definitely worth it!