{"id":794,"date":"2023-06-09T10:29:45","date_gmt":"2023-06-09T10:29:45","guid":{"rendered":"https:\/\/starscape-experiences.space\/?p=794"},"modified":"2023-06-09T16:04:00","modified_gmt":"2023-06-09T16:04:00","slug":"all-sky-oculus-starlight-xpress-on-pi4","status":"publish","type":"post","link":"https:\/\/starscape-experiences.space\/index.php\/2023\/06\/09\/all-sky-oculus-starlight-xpress-on-pi4\/","title":{"rendered":"All-sky Oculus Starlight Xpress on Pi4"},"content":{"rendered":"\n<p>These days I finally got access to the Pi4 (2GB RAM) that I used for all-sky imagery on my ASI120 MC camera that I now use on my <a href=\"https:\/\/starscape-experiences.space\/index.php\/2023\/01\/05\/detecting-solar-features-automatically-using-machine-learning\/\" title=\"\">solar scope<\/a>. It had a bunch of preinstalled Python scripts for all-sky imagery including automatic meteor detection which I will talk about in a future post. Since I also had access to a <strong><a href=\"https:\/\/www.firstlightoptics.com\/starlight-xpress-cameras\/starlight-xpress-oculus-all-sky-camera.html\" title=\"\">Starlight Xpress Oculus<\/a><\/strong> all-sky camera I decided to give it a go and test it on the Pi4. Little if any information is available online for making these cameras work on the Pi4. The only code I found was <a href=\"https:\/\/github.com\/liponan\/sxccd-python\" title=\"\">this one<\/a>.  The <em>Oculus <\/em>comes with Windows drivers and simple software to capture images but nothing else. So let&#8217;s start.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"544\" src=\"https:\/\/starscape-experiences.space\/wp-content\/uploads\/2023\/06\/image-1024x544.png\" alt=\"\" class=\"wp-image-795\" srcset=\"https:\/\/starscape-experiences.space\/wp-content\/uploads\/2023\/06\/image-1024x544.png 1024w, https:\/\/starscape-experiences.space\/wp-content\/uploads\/2023\/06\/image-300x159.png 300w, https:\/\/starscape-experiences.space\/wp-content\/uploads\/2023\/06\/image-768x408.png 768w, https:\/\/starscape-experiences.space\/wp-content\/uploads\/2023\/06\/image-1536x816.png 1536w, https:\/\/starscape-experiences.space\/wp-content\/uploads\/2023\/06\/image.png 1917w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><figcaption>The simple Windows application for Oculus. Unfortunately, this is unavailable on other OSs.<\/figcaption><\/figure><\/div>\n\n\n<p>The <em>Oculus <\/em>is powered via USB but has a heating system powered by a regular power outlet. This helps prevent dew accumulation inside the acrylic dome. I did find out that the weight of the AC adapter has the tendency of pulling out the plug as it&#8217;s located right underneath the camera.<\/p>\n\n\n\n<p>The camera&#8217;s USB can be plugged into any of the Pi4&#8217;s USB ports. I opted for one of the USB2.0s.<\/p>\n\n\n\n<p>To get the camera feed data into the Pi4 some Python scripts are needed. I started from the ones I found after a bit of searching at this <a href=\"https:\/\/github.com\/liponan\/sxccd-python\" title=\"\">link<\/a> but discovered that the code has some bugs like uncaught exceptions and it does not work out of the box. Here are the updates I made to it and the reasons for them.<\/p>\n\n\n\n<ul><li>unzip the downloaded archive into a folder (say <em>sxccd-python-master<\/em>) and go to the folder using <code>cd sxccd-python-master\/ <\/code>. All commands should be run from this folder.<\/li><li>install <em>pyusb <\/em>by running <code>pip install pyusb<\/code>. The code provided requires it.<\/li><\/ul>\n\n\n\n<ul><li>Line 9 in <em>sxccd.py<\/em>: <code>self.dev = usb.core.find(manufacturer=\"Starlight Xpress\")<\/code>does not work (the vendor information was unavailable before the first handshake by the script) so I replaced it with the following in which I specified the vendor and product ID. I also added an exception in the code in case the camera is not found: <\/li><\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code># display all USB devices to identify the Oculus\/Starlight Xpress\nprint(usb.core.show_devices(True))\n# the vendor and product Ids are taken from the output of the last cmd\nself.dev = usb.core.find(idVendor=0x1278, idProduct=0x0509) \nif self.dev is None:\n        raise ValueError(\"Starlight Xpress not found\")<\/code><\/pre>\n\n\n\n<p>The first line displays all USB devices and associated information including vendor and product IDs. There are 4 ports on the Pi4 and one is used by the <em>Oculus<\/em>. To find out which is used by the Oculus I ran the previous commands twice, once with the camera plugged in and then without it to check what has changed.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"903\" height=\"450\" src=\"https:\/\/starscape-experiences.space\/wp-content\/uploads\/2023\/06\/image-2.png\" alt=\"\" class=\"wp-image-797\" srcset=\"https:\/\/starscape-experiences.space\/wp-content\/uploads\/2023\/06\/image-2.png 903w, https:\/\/starscape-experiences.space\/wp-content\/uploads\/2023\/06\/image-2-300x150.png 300w, https:\/\/starscape-experiences.space\/wp-content\/uploads\/2023\/06\/image-2-768x383.png 768w\" sizes=\"(max-width: 903px) 100vw, 903px\" \/><\/figure><\/div>\n\n\n<ul><li>Next, I found that running the function <em>model()<\/em> on line 21 in the same sxccd.py file causes a permission error as I did not have the <code>\/etc\/udev\/rules.d\/99-usbftdi.rules<\/code> file. I had to create one using <code>sudo cat \/etc\/udev\/rules.d\/99-usbftdi.rules<\/code>to get admin privileges and added the following line inside the newly created file: <code>SUBSYSTEM==\"usb\", ATTRS{idVendor}==\"1278\", MODE=\"0666\"<\/code>. The vendor code was obtained in the previous step. Then I unplugged and plugged back in the camera for the changes to take effect. After running this function in my bundle script (below)  I discovered that the model I have is the <em>SuperStarM<\/em>.<\/li><li>Apparently, the camera I have does not have a firmware version that is available via the called functions, so the <em>firmwareVersion <\/em>function on line 13 in file <em>sxccd.py<\/em> throws an exception.<\/li><li>Another thing I noticed is that since the camera outputs <strong>16-bit pixels<\/strong> they need to be correctly read by the Python scripts. The next code fragment shows how to do this. You&#8217;ll have to install OpenCV for Python: <code><code>pip install opencv-python<\/code><\/code>.<\/li><\/ul>\n\n\n\n<p>These changes allowed me to run the following script (modified from the example in the link provided earlier) to get the image data (16-bit pixels) from the Oculus. The script can be entered into a file (say <em>oculus_capture.py<\/em>) via the command line using <em>nano <\/em>or using the <em>gedit <\/em>tool from the GUI. It can then be executed with <code>python3 .\/oculus_capture.py<\/code><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import cv2\n# to make the next import work download and unzip archive from https:\/\/github.com\/liponan\/sxccd-python and place this script in the folder\nimport sxccd\n\ncamera = sxccd.Camera()\n\n# print out camera model\ncamera.model()\n\n# retrieve current camera parameters\nparams = camera.parameters()\n\n# reset camera\ncamera.reset()\n\n# echo\necho_result = camera.echo(\"Hello world!\")\nprint( echo_result )\n\n# timed exposure of 1s (1000ms)\n# according the the specs the Oculus images are 1392x1040 pixels\nimage = camera.readPixelsDelayed( exp_ms=1000, width=1392, height=1040, x_bin=1, y_bin=1, x_offset=0, y_offset=0, verbose=True)\n\n# convert the image to 16-bit and normalize colors\nimg_scaled = cv2.normalize(np.uint16(image), dst=None, alpha=0, beta=65535, norm_type=cv2.NORM_MINMAX)\n\n# display image on screen\ncv2.imshow('Oculus allsky', img_scaled)\ncv2.waitKey(0)\ncv2.destroyAllWindows()\n\n# save image to png file (jpg does no work)\ncv2.imwrite(\"image.png\", img_scaled)<\/code><\/pre>\n\n\n\n<p>And the final output can be seen below:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"771\" src=\"https:\/\/starscape-experiences.space\/wp-content\/uploads\/2023\/06\/image-4-1024x771.png\" alt=\"\" class=\"wp-image-802\" srcset=\"https:\/\/starscape-experiences.space\/wp-content\/uploads\/2023\/06\/image-4-1024x771.png 1024w, https:\/\/starscape-experiences.space\/wp-content\/uploads\/2023\/06\/image-4-300x226.png 300w, https:\/\/starscape-experiences.space\/wp-content\/uploads\/2023\/06\/image-4-768x579.png 768w, https:\/\/starscape-experiences.space\/wp-content\/uploads\/2023\/06\/image-4-508x381.png 508w, https:\/\/starscape-experiences.space\/wp-content\/uploads\/2023\/06\/image-4.png 1135w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><figcaption>Daytime snapshot of a 1ms exposure. The camera is highly sensitive and can only be used during nighttime. You can barely notice my unfocused coffee maker :).<\/figcaption><\/figure><\/div>\n\n\n<p>Despite the vendor saying that the camera should be focused, I found that it needs to be refocused by removing the acrylic dome and rotating the lens. I will post a video of this in the near future. Below is an image of the night sky out of focus and showing several dead pixels (white dots) <\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"765\" src=\"https:\/\/starscape-experiences.space\/wp-content\/uploads\/2023\/06\/test-1024x765.png\" alt=\"\" class=\"wp-image-809\" srcset=\"https:\/\/starscape-experiences.space\/wp-content\/uploads\/2023\/06\/test-1024x765.png 1024w, https:\/\/starscape-experiences.space\/wp-content\/uploads\/2023\/06\/test-300x224.png 300w, https:\/\/starscape-experiences.space\/wp-content\/uploads\/2023\/06\/test-768x574.png 768w, https:\/\/starscape-experiences.space\/wp-content\/uploads\/2023\/06\/test-508x381.png 508w, https:\/\/starscape-experiences.space\/wp-content\/uploads\/2023\/06\/test.png 1392w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><figcaption>The first attempt at a night sky all-sky image. The moon can be seen rising above the tree line.<\/figcaption><\/figure><\/div>\n\n\n<p>With these modifications, you should be able to run your Oculus from your Pi4 board. It can be further expanded to upload the image to a web server periodically to show it on your website. More in a future post. Feel free to contact me with questions if you get stuck.<\/p>\n\n\n\n<p>If you enjoyed this post consider <strong>following <\/strong>us on <a href=\"https:\/\/www.facebook.com\/profile.php?id=100085743827571\">Facebook<\/a>, <a href=\"https:\/\/www.youtube.com\/channel\/UCR6DmJ5GoOZe1KOYyCVAE0g\">Youtube<\/a>, and <a href=\"https:\/\/twitter.com\/marc_frincu\">Twitter <\/a>or <strong>donating <\/strong>on <a href=\"https:\/\/www.patreon.com\/marc_frincu\">Patreon<\/a>. Also, stay tuned for <strong>public events<\/strong> Marc hosts regularly on <a href=\"https:\/\/www.eventbrite.co.uk\/o\/marc-frincu-starscape-53843261853\">Eventbrite<\/a>.<\/p>\n<div class='watch-action'><div class='watch-position align-left'><div class='action-like'><a class='lbg-style1 like-794 jlk' href='javascript:void(0)' data-task='like' data-post_id='794' data-nonce='8aec206929' rel='nofollow'><img class='wti-pixel' src='https:\/\/starscape-experiences.space\/wp-content\/plugins\/wti-like-post\/images\/pixel.gif' title='Like' \/><span class='lc-794 lc'>0<\/span><\/a><\/div><\/div> <div class='status-794 status align-left'><\/div><\/div><div class='wti-clear'><\/div>","protected":false},"excerpt":{"rendered":"<p>These days I finally got access to the Pi4 (2GB RAM) that I used for all-sky imagery on my ASI120<\/p>\n<p><a href=\"https:\/\/starscape-experiences.space\/index.php\/2023\/06\/09\/all-sky-oculus-starlight-xpress-on-pi4\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\">All-sky Oculus Starlight Xpress on Pi4<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":809,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[9],"tags":[139,138,136,91,48,85,137,135],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/starscape-experiences.space\/index.php\/wp-json\/wp\/v2\/posts\/794"}],"collection":[{"href":"https:\/\/starscape-experiences.space\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/starscape-experiences.space\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/starscape-experiences.space\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/starscape-experiences.space\/index.php\/wp-json\/wp\/v2\/comments?post=794"}],"version-history":[{"count":24,"href":"https:\/\/starscape-experiences.space\/index.php\/wp-json\/wp\/v2\/posts\/794\/revisions"}],"predecessor-version":[{"id":884,"href":"https:\/\/starscape-experiences.space\/index.php\/wp-json\/wp\/v2\/posts\/794\/revisions\/884"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/starscape-experiences.space\/index.php\/wp-json\/wp\/v2\/media\/809"}],"wp:attachment":[{"href":"https:\/\/starscape-experiences.space\/index.php\/wp-json\/wp\/v2\/media?parent=794"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/starscape-experiences.space\/index.php\/wp-json\/wp\/v2\/categories?post=794"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/starscape-experiences.space\/index.php\/wp-json\/wp\/v2\/tags?post=794"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}