{"id":4824,"date":"2025-05-19T07:43:27","date_gmt":"2025-05-19T12:43:27","guid":{"rendered":"https:\/\/lab.rapternet.us\/?p=4824"},"modified":"2025-05-14T21:41:08","modified_gmt":"2025-05-15T02:41:08","slug":"catomater","status":"publish","type":"post","link":"https:\/\/lab.rapternet.us\/?p=4824","title":{"rendered":"Catomater"},"content":{"rendered":"\n<p>I saw this model while looking for some type of laser toy for a cat. It looked neat, integrated with home assistant, and it didn&#8217;t require many parts, so I figured why not try and see if my cat would be interested with it.<\/p>\n\n\n\n<!--more-->\n\n\n\n<h2 class=\"wp-block-heading\">Parts<\/h2>\n\n\n\n<p>Theres basically 3 parts outside the 3d printed parts. The one I found hard to find was a 5v laser online that wasn&#8217;t a line laser \/ laser level and was reasonable quality. I ended up on the listing below, though one of the two lasers is missing a lens to focus it, so your mileage may vary.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/amzn.to\/3S21lXH\">2 9g servos<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/amzn.to\/436ZEgs\">1 5v laser pointer<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/amzn.to\/43ghqy5\">Esp32<\/a><\/li>\n\n\n\n<li>3 M2 x 12 screws<\/li>\n\n\n\n<li>3 M2 Nuts<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Assembly<\/h2>\n\n\n\n<p>The assembly starts with the head of the unit that houses the two servos that handle movement. These are built entirely into the printed parts, and the wiring takes a bit of finesse to get into place. The first servo is mounted in a standing position with the wire wrapping around the outside of the servo and then down the side of the housing.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"769\" src=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250407_2055014622415959389509246660-1024x769.jpg\" alt=\"\" class=\"wp-image-4826\" srcset=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250407_2055014622415959389509246660-1024x769.jpg 1024w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250407_2055014622415959389509246660-300x225.jpg 300w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250407_2055014622415959389509246660-768x577.jpg 768w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250407_2055014622415959389509246660-1536x1154.jpg 1536w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250407_2055014622415959389509246660.jpg 2000w\" sizes=\"auto, (max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><figcaption class=\"wp-element-caption\">Wire underneath and behind servo<\/figcaption><\/figure>\n\n\n\n<p>The second servo is mounted laying down with the wire passing underneath the servo once it&#8217;s in place.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"769\" src=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250407_2056048385685743396787536804-1024x769.jpg\" alt=\"\" class=\"wp-image-4827\" srcset=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250407_2056048385685743396787536804-1024x769.jpg 1024w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250407_2056048385685743396787536804-300x225.jpg 300w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250407_2056048385685743396787536804-768x577.jpg 768w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250407_2056048385685743396787536804-1536x1154.jpg 1536w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250407_2056048385685743396787536804.jpg 2000w\" sizes=\"auto, (max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><\/figure>\n\n\n\n<p>This servo should be held in place while putting the other side together with it to ensure it doesn&#8217;t wiggle, letting the wire get in the way.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"769\" src=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250407_2056156707973504009345147114-1024x769.jpg\" alt=\"\" class=\"wp-image-4828\" srcset=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250407_2056156707973504009345147114-1024x769.jpg 1024w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250407_2056156707973504009345147114-300x225.jpg 300w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250407_2056156707973504009345147114-768x577.jpg 768w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250407_2056156707973504009345147114-1536x1154.jpg 1536w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250407_2056156707973504009345147114.jpg 2000w\" sizes=\"auto, (max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><figcaption class=\"wp-element-caption\">Writing underneath servo<\/figcaption><\/figure>\n\n\n\n<p>Smash the two sides together, each with it&#8217;s respective servo and both wires coming out the same side and then it&#8217;s off to the races.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"769\" src=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250407_2056332236553278968370899908-1024x769.jpg\" alt=\"\" class=\"wp-image-4829\" srcset=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250407_2056332236553278968370899908-1024x769.jpg 1024w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250407_2056332236553278968370899908-300x225.jpg 300w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250407_2056332236553278968370899908-768x577.jpg 768w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250407_2056332236553278968370899908-1536x1154.jpg 1536w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250407_2056332236553278968370899908.jpg 2000w\" sizes=\"auto, (max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><figcaption class=\"wp-element-caption\">Wires routed out<\/figcaption><\/figure>\n\n\n\n<p>I used 3 M2 x 12 screws with nuts to assemble the two halves together. These had enough length to make it through but not too much overlap (and also were a length of screw I had around).<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"769\" src=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250408_0114305664240536708006391029-1024x769.jpg\" alt=\"\" class=\"wp-image-4831\" srcset=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250408_0114305664240536708006391029-1024x769.jpg 1024w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250408_0114305664240536708006391029-300x225.jpg 300w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250408_0114305664240536708006391029-768x577.jpg 768w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250408_0114305664240536708006391029-1536x1154.jpg 1536w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250408_0114305664240536708006391029.jpg 2000w\" sizes=\"auto, (max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><figcaption class=\"wp-element-caption\">3 x m2x12 screws here<\/figcaption><\/figure>\n\n\n\n<p>For the bottom servo, I had to trim the servo horn a bit, and widen the hole in order for it to fit in its housing. Once it was in place, I could just screw it in place to the servo for a solid fit.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"769\" src=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250413_2332268557791671326080031180-1024x769.jpg\" alt=\"\" class=\"wp-image-4834\" srcset=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250413_2332268557791671326080031180-1024x769.jpg 1024w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250413_2332268557791671326080031180-300x225.jpg 300w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250413_2332268557791671326080031180-768x577.jpg 768w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250413_2332268557791671326080031180-1536x1154.jpg 1536w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250413_2332268557791671326080031180.jpg 2000w\" sizes=\"auto, (max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><\/figure>\n\n\n\n<p>After that, I had to install the laser. The original mount was for a smaller diameter laser than I had, so I <a href=\"https:\/\/www.printables.com\/model\/1264526-catomater-12mm-laser-diode-adapter\">modeled a new mount for it<\/a>. After printing out the mount, it worked on the first try, so I glued it to the base plate and screw that onto the head of the unit.<\/p>\n\n\n\n<figure class=\"wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-1 is-layout-flex wp-block-gallery-is-layout-flex\">\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"769\" data-id=\"4833\" src=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250413_2331598024559647253735433296-1024x769.jpg\" alt=\"\" class=\"wp-image-4833\" srcset=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250413_2331598024559647253735433296-1024x769.jpg 1024w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250413_2331598024559647253735433296-300x225.jpg 300w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250413_2331598024559647253735433296-768x577.jpg 768w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250413_2331598024559647253735433296-1536x1154.jpg 1536w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250413_2331598024559647253735433296.jpg 2000w\" sizes=\"auto, (max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><figcaption class=\"wp-element-caption\">Original mount<\/figcaption><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"769\" data-id=\"4836\" src=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250413_233208066678522637633545369-1024x769.jpg\" alt=\"\" class=\"wp-image-4836\" srcset=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250413_233208066678522637633545369-1024x769.jpg 1024w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250413_233208066678522637633545369-300x225.jpg 300w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250413_233208066678522637633545369-768x577.jpg 768w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250413_233208066678522637633545369-1536x1154.jpg 1536w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250413_233208066678522637633545369.jpg 2000w\" sizes=\"auto, (max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><figcaption class=\"wp-element-caption\">My modified mount<\/figcaption><\/figure>\n<\/figure>\n\n\n\n<figure class=\"wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-2 is-layout-flex wp-block-gallery-is-layout-flex\">\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"769\" data-id=\"4838\" src=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250413_2353176038723521551351840973-1024x769.jpg\" alt=\"\" class=\"wp-image-4838\" srcset=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250413_2353176038723521551351840973-1024x769.jpg 1024w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250413_2353176038723521551351840973-300x225.jpg 300w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250413_2353176038723521551351840973-768x577.jpg 768w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250413_2353176038723521551351840973-1536x1154.jpg 1536w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250413_2353176038723521551351840973.jpg 2000w\" sizes=\"auto, (max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><figcaption class=\"wp-element-caption\">Modified laser mount<\/figcaption><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"769\" data-id=\"4835\" src=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250413_2332183686304743549732120358-1024x769.jpg\" alt=\"\" class=\"wp-image-4835\" srcset=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250413_2332183686304743549732120358-1024x769.jpg 1024w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250413_2332183686304743549732120358-300x225.jpg 300w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250413_2332183686304743549732120358-768x577.jpg 768w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250413_2332183686304743549732120358-1536x1154.jpg 1536w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250413_2332183686304743549732120358.jpg 2000w\" sizes=\"auto, (max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><figcaption class=\"wp-element-caption\">Glued in place<\/figcaption><\/figure>\n<\/figure>\n\n\n\n<p>The head mounts onto the other servo arm and basically clips into place. You can also adjust the position relative to the servo&#8217;s position in order to skew the distance available one way or another (to have maximum range).<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"769\" src=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250413_2333506324501513857061948111-1024x769.jpg\" alt=\"\" class=\"wp-image-4839\" srcset=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250413_2333506324501513857061948111-1024x769.jpg 1024w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250413_2333506324501513857061948111-300x225.jpg 300w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250413_2333506324501513857061948111-768x577.jpg 768w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250413_2333506324501513857061948111-1536x1154.jpg 1536w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250413_2333506324501513857061948111.jpg 2000w\" sizes=\"auto, (max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><\/figure>\n\n\n\n<p>I soldered in connectors to the ESP32 for the servos and laser. The cables were then routed to the base of the unit where the ESP32 just barely fits. Its not the prettiest wiring, but its also not the worst that I&#8217;ve done.<\/p>\n\n\n\n<figure class=\"wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-3 is-layout-flex wp-block-gallery-is-layout-flex\">\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"769\" data-id=\"4837\" src=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250413_2332314182642941286007449209-1024x769.jpg\" alt=\"\" class=\"wp-image-4837\" srcset=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250413_2332314182642941286007449209-1024x769.jpg 1024w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250413_2332314182642941286007449209-300x225.jpg 300w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250413_2332314182642941286007449209-768x577.jpg 768w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250413_2332314182642941286007449209-1536x1154.jpg 1536w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250413_2332314182642941286007449209.jpg 2000w\" sizes=\"auto, (max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"769\" data-id=\"4840\" src=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250414_0017404828864289286873860975-1024x769.jpg\" alt=\"\" class=\"wp-image-4840\" srcset=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250414_0017404828864289286873860975-1024x769.jpg 1024w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250414_0017404828864289286873860975-300x225.jpg 300w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250414_0017404828864289286873860975-768x577.jpg 768w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250414_0017404828864289286873860975-1536x1154.jpg 1536w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250414_0017404828864289286873860975.jpg 2000w\" sizes=\"auto, (max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"769\" height=\"1024\" data-id=\"4842\" src=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250416_0059296285222818107969085068-769x1024.jpg\" alt=\"\" class=\"wp-image-4842\" srcset=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250416_0059296285222818107969085068-769x1024.jpg 769w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250416_0059296285222818107969085068-225x300.jpg 225w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250416_0059296285222818107969085068-768x1023.jpg 768w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250416_0059296285222818107969085068-1154x1536.jpg 1154w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/pxl_20250416_0059296285222818107969085068.jpg 1502w\" sizes=\"auto, (max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><\/figure>\n<\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">ESPHome Configuration<\/h2>\n\n\n\n<p>My ESPHome configuration is below. The ranges on the servos will have to be adjusted depending on how the unit is built and where the zero positions are in the build. I&#8217;ve added comments otherwise around for various aspects of it. I&#8217;ve also uploaded my <a href=\"https:\/\/github.com\/AeroSteveO\/ESP-Projects\/tree\/main\/catomater\">configuration and scripts to Github here<\/a>.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">esphome:<br>  name: \"catomater-1\"<br>  #name: catomater-1<br>  friendly_name: Catomater-1<br>  min_version: 2024.11.0<br>  name_add_mac_suffix: false<br><br>esp32:<br>  board: esp32dev<br>  framework:<br>    type: esp-idf<br><br># Enable logging<br>logger:<br><br># Enable Home Assistant API<br>api:<br>  services:<br>    # goes from about -70 to 100<br>    # 70 is facing forward<br>  - service: servo_y<br>    variables:<br>      level: float<br>    then:<br>      - servo.write:<br>          id: servo_y<br>          level: !lambda 'return level \/ 100.0;'<br>    # goes from about -80 to 100<br>    # 0 is centered<br>  - service: servo_x<br>    variables:<br>      level: float<br>    then:<br>      - servo.write:<br>          id: servo_x<br>          level: !lambda 'return level \/ 100.0;'<br><br># Allow Over-The-Air updates<br>ota:<br>- platform: esphome<br><br>wifi:<br>  ssid: !secret wifi_ssid<br>  password: !secret wifi_password<br><br>output:<br>  - platform: ledc<br>    id: pwm_1<br>    pin: GPIO21<br>    frequency: 100 Hz<br>  - platform: ledc<br>    id: pwm_2<br>    pin: GPIO16<br>    frequency: 100 Hz<br><br>servo:<br>  - id: servo_y<br>    output: pwm_1<br>    # transition_length: \"10s\"<br>    auto_detach_time: 1s<br>  - id: servo_x<br>    output: pwm_2<br>    # transition_length: \"10s\"<br>    auto_detach_time: 1s<br><br># input_number:<br>  # x_servo_control:<br>    # initial: 0<br>    # min: -100<br>    # max: 100<br>    # step: 1<br>    # mode: slider<br>  # y_servo_control:<br>    # initial: 0<br>    # min: -100<br>    # max: 100<br>    # step: 1<br>    # mode: slider<br><br># Example configuration entry<br>switch:<br>  - platform: gpio<br>    id: laser<br>    pin: <br>      number: GPIO17<br>      mode:<br>        output: true<br>    name: \"Laser Pointer\"<br>    internal: true<br>    <br>    restore_mode: ALWAYS_OFF<br>  - platform: template<br>    name: \"Laser Pointer\"<br>    lambda: |-<br>      if (id(laser).state) {<br>        return true;<br>      } else {<br>        return false;<br>      }<br>    turn_on_action:<br>      - switch.turn_on: laser<br>    turn_off_action:<br>      - switch.turn_off: laser<br>    assumed_state: false<br><br>binary_sensor:<br>  - platform: status<br>    name: \"Catomater Status\"<br>  # - platform: homeassistant<br>  #   id: switch1<br>  #   entity_id: input_boolean.switch1<br>  #   internal: true<br># alias: Cat Laser - Park position<br># sequence:<br>#  - service: switch.turn_off<br>#    data: {}<br>#    target:<br>#      entity_id: switch.cat_laser_laser_pointer<br>#  - variables:<br>#      park_x: -25<br>#      park_y: 75<br>#  - service: esphome.cat_laser_servo_x<br>#    data:<br>#       level: \"{{ park_x }}\"<br>#  - service: esphome.cat_laser_servo_y<br>#    data:<br>#       level: \"{{ park_y }}\"<br># mode: single<br># icon: mdi:cat<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Home Assistant<\/h2>\n\n\n\n<p>The scripts to run it are fairly simple. There is a run script and a park script. The park script sets the servos to pre-determined zero locations and turns off the laser. The run script moves the servos to random locations in a loop until the counter runs out and it turns everything off.<\/p>\n\n\n\n<p>Running it<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"819\" height=\"1024\" src=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/image-5-819x1024.png\" alt=\"\" class=\"wp-image-4913\" srcset=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/image-5-819x1024.png 819w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/image-5-240x300.png 240w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/image-5-768x960.png 768w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/image-5-1229x1536.png 1229w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/image-5.png 1439w\" sizes=\"auto, (max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"226\" src=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/image-6-1024x226.png\" alt=\"\" class=\"wp-image-4914\" srcset=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/image-6-1024x226.png 1024w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/image-6-300x66.png 300w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/image-6-768x169.png 768w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/image-6.png 1491w\" sizes=\"auto, (max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><\/figure>\n\n\n\n<p>Parking it<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"833\" src=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/image-7-1024x833.png\" alt=\"\" class=\"wp-image-4915\" srcset=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/image-7-1024x833.png 1024w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/image-7-300x244.png 300w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/image-7-768x625.png 768w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2025\/04\/image-7.png 1467w\" sizes=\"auto, (max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<p>Even though my cat seems more interested in the noise the catomater makes and the unit itself moving around, rather than the laser. Its still a success, the unit works well, integrates well in home assistant, and was pretty fun to build.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Resources<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/esphome.io\/components\/servo.html\">Servo Component in ESPHome<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/www.printables.com\/model\/579611-the-catomater-v-19-a-cat-automater-maybe-ceilingwa\">Catomater<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/www.printables.com\/model\/1264526-catomater-12mm-laser-diode-adapter\">My 12mm Laser Adapter<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/github.com\/AeroSteveO\/ESP-Projects\/tree\/main\/catomater\">Github page with my configuration<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/siytek.com\/esphome-servo-example\">ESPHome Servo Example<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>I saw this model while looking for some type of laser toy for a cat. It looked neat, integrated with home assistant, and it didn&#8217;t require many parts, so I figured why not try and see if my cat would be interested with it.<\/p>\n","protected":false},"author":1,"featured_media":4840,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[56],"tags":[18,74,39,49],"class_list":["post-4824","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-making","tag-3d-printing","tag-esphome","tag-home-assistant","tag-smart-home"],"_links":{"self":[{"href":"https:\/\/lab.rapternet.us\/index.php?rest_route=\/wp\/v2\/posts\/4824","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/lab.rapternet.us\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/lab.rapternet.us\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/lab.rapternet.us\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/lab.rapternet.us\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=4824"}],"version-history":[{"count":16,"href":"https:\/\/lab.rapternet.us\/index.php?rest_route=\/wp\/v2\/posts\/4824\/revisions"}],"predecessor-version":[{"id":4964,"href":"https:\/\/lab.rapternet.us\/index.php?rest_route=\/wp\/v2\/posts\/4824\/revisions\/4964"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/lab.rapternet.us\/index.php?rest_route=\/wp\/v2\/media\/4840"}],"wp:attachment":[{"href":"https:\/\/lab.rapternet.us\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=4824"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/lab.rapternet.us\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=4824"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/lab.rapternet.us\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=4824"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}