{"id":254,"date":"2022-07-03T13:32:39","date_gmt":"2022-07-03T13:32:39","guid":{"rendered":"https:\/\/www.beer.org\/blog\/?p=254"},"modified":"2022-07-04T12:15:47","modified_gmt":"2022-07-04T12:15:47","slug":"playing-with-fiducials","status":"publish","type":"post","link":"https:\/\/www.beer.org\/blog\/index.php\/2022\/07\/03\/playing-with-fiducials\/","title":{"rendered":"Playing with Fiducials."},"content":{"rendered":"\n<p>As part of some tinkering I was doing with my robotics team, I was learning about AprilTags.&nbsp; Coincidentally, I had also recently installed a gate opener at the front gate and was struggling with how to organize guest access.<\/p>\n\n\n\n<p>I grabbed my <a href=\"https:\/\/openmv.io\/\">OpenMV<\/a> camera, a spare buck\/boost converter, and an old Axis surveillance camera housing.&nbsp; Put it all together and mounted it to a post in front of the gate:<\/p>\n\n\n\n<p><\/p>\n\n\n<div class='photonic-google-stream photonic-stream ' id='photonic-google-stream-1'>\n\r\n<div class='photonic-error photonic-google-error' id='photonic-google-error-1'>\r\n\t<span class='photonic-error-icon photonic-icon'>&nbsp;<\/span>\r\n\t<div class='photonic-message'>\r\n\t\tGoogle Photos Refresh Token invalid. Please authenticate from <em>Photonic &rarr; Authentication<\/em>.<br \/>Error encountered during authentication: <br \/><pre>{\n  \"error\": \"deleted_client\",\n  \"error_description\": \"The OAuth client was deleted.\"\n}<\/pre> See <a href='https:\/\/aquoid.com\/plugins\/photonic\/google-photos\/'>here<\/a> for documentation.\r\n\t<\/div>\r\n<\/div>\n\n<\/div><!-- .photonic-stream or .photonic-panel -->\n\n\n\n<p><\/p>\n\n\n\n<p> I played with the QR Code recognition and various families of AprilTag.   While the QR Code recognition worked fine and allowed me some nice flexibility in terms of content, it was more fallible under varying light conditions.  AprilTags are more robust and recognized pretty quickly from a few feet away.<\/p>\n\n\n\n<p>The code is simple:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"python\" class=\"language-python\">import sensor, image, time, math, omv, utime\nimport pyb\nimport machine\n\n\nthresholds = ( 150,255 )\nsensor.reset()                      # Reset and initialize the sensor.\nsensor.set_pixformat(sensor.GRAYSCALE)\nsensor.set_framesize(sensor.QQVGA)\nsensor.set_auto_gain(False)\nsensor.set_auto_whitebal(False)\nsensor.skip_frames(time = 2000)     # Wait for settings take effect.\nclock = time.clock()                # Create a clock object to track the FPS.\n\ntag_families = image.TAG36H11|image.TAG36H11\n\nlast_tag = 0\ntag_repeat_cnt = 0\ntag_repeat_threshold = 5\nrtc = pyb.RTC()\n\ndef set_rtc(epoch):\n    dt=time.localtime(int(epoch))\n    rtc.datetime(tuple(dt))\n\n\nP1_PIN=\"P4\"\nP2_PIN=\"P5\"\np1 = 0\np2 = 0\n\nSTATE_NORMAL=0\nSTATE_STAY_OPEN=1\nSTATE_STAY_CLOSED=2\n\nstate = 0\nrtc_valid = 0\n\nred_led = pyb.LED(1)\ngreen_led = pyb.LED(2)\nblue_led = pyb.LED(3)\nir_leds = pyb.LED(4)\n\n# micropython Epoch is 2000-01-01.  My timezone is UTC+8.\nepoch_fixup=946728000\n\n\ndef set_p1(dur=0):\n    p1.low()\n    red_led.on()\n    time.sleep_ms(dur)\n    p1.high()\n    red_led.off()\n\n\ndef set_p2(dur=0):\n    p2.low()\n    green_led.on()\n    red_led.on()\n    if (dur == 0):\n        return\n    time.sleep_ms(dur)\n    p2.high()\n    green_led.off()\n    red_led.off()\n\ndef init_gpios():\n    p1=pyb.Pin(P1_PIN, pyb.Pin.OUT_PP, pyb.Pin.PULL_DOWN)\n    p2=pyb.Pin(P2_PIN, pyb.Pin.OUT_PP, pyb.Pin.PULL_DOWN)\n    p1.high()\n    p2.high()\n\n    return p1,p2\n\np1,p2 = init_gpios()\nblue_led.on()\n\ni=0\nwhile True:\n    if i &gt; 10:\n        sensor.sleep(True)\n        time.sleep_ms(500)\n        sensor.sleep(False)\n        i = 0\n    i = i+1\n\n    img = sensor.snapshot()         # Take a picture and return the image.\n                                    # to the IDE. The FPS should increase once disconnected.\n    tag_list = []\n\n    try:\n        tag_list.extend(img.find_apriltags(families=tag_families))\n    except (MemoryError, OSError):\n        pass\n\n    for tag in tag_list:\n        if tag.id() == last_tag:\n            tag_repeat_cnt = tag_repeat_cnt + 1\n        else:\n            tag_repeat_cnt = 0\n            last_tag = tag.id()\n\n        if tag_repeat_cnt &gt; tag_repeat_threshold:\n            if tag.id() &gt; 1 and tag.id() &lt; 100 and state==STATE_NORMAL:\n                print(\"Access granted (FRIEND): {}\".format(tag.id()))\n                set_p1(1000)<\/code><\/pre>\n\n\n\n<p>Obviously this isn&#8217;t super secure but most people who are breaking into houses aren&#8217;t sophisticated enough to know about Fiducials.  Most people will assume the camera is for someone in the house to remotely activate a switch.  I am actually using somewhat different code.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p>Because the only power I have out there is the deep cycle battery running the gate controller, I put the OpenMV to sleep for 1\/2 second at a time.  Seems to do ok and has gotten through an entire winter with temps that fell to -40C.<\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>As part of some tinkering I was doing with my robotics team, I was learning about AprilTags.&nbsp; Coincidentally, I had also recently installed a gate opener at the front gate and was struggling with how to organize guest access. I grabbed my OpenMV camera, a spare buck\/boost converter, and an old Axis surveillance camera housing.&nbsp;&#8230; <a class=\"moretag\" href=\"https:\/\/www.beer.org\/blog\/index.php\/2022\/07\/03\/playing-with-fiducials\/\">Continue reading &raquo;<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5,7],"tags":[],"class_list":["post-254","post","type-post","status-publish","format-standard","hentry","category-drivel","category-tech-stuff"],"_links":{"self":[{"href":"https:\/\/www.beer.org\/blog\/index.php\/wp-json\/wp\/v2\/posts\/254","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.beer.org\/blog\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.beer.org\/blog\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.beer.org\/blog\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.beer.org\/blog\/index.php\/wp-json\/wp\/v2\/comments?post=254"}],"version-history":[{"count":13,"href":"https:\/\/www.beer.org\/blog\/index.php\/wp-json\/wp\/v2\/posts\/254\/revisions"}],"predecessor-version":[{"id":273,"href":"https:\/\/www.beer.org\/blog\/index.php\/wp-json\/wp\/v2\/posts\/254\/revisions\/273"}],"wp:attachment":[{"href":"https:\/\/www.beer.org\/blog\/index.php\/wp-json\/wp\/v2\/media?parent=254"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.beer.org\/blog\/index.php\/wp-json\/wp\/v2\/categories?post=254"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.beer.org\/blog\/index.php\/wp-json\/wp\/v2\/tags?post=254"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}