Tiny Zoo

2026-10-13 robots / python / html5
Remote Control Microscopy

Australia has many excellent zoos of varying size, but this is (probably) the smallest, at approximately one billionth the size of Werribee Open Range Zoo. Parking would be kind of a hassle, but you can visit online SOON at tiny.zoic.org.

This article discusses the history and aims of the project. For more technical specifics of the software, see the Tiny Zoo repo.

Species

The microscope is powerful enough to see various microfauna which can grow to about grow up to 500µm long.

I also found one enormous larva (coleoptera?) which came zipping past like an express train.

The aim is to observe living creatures and their behaviours in their environment. Eventually I hope to have OpenCV detect, record and follow interesting species.

This project may also owe just a little something to reading James Blish’s Surface Tension at an impressionable age.

Camera & Optics

Currently a 12Mpix USB webcam capable of capturing JPEGs at about 20fps, see Using the Waveshare IMX577 Camera from Python

Lenses

I’ve got the setup working with two lenses:

I did try out a “10x” microscope objective but getting it to focus proved very difficult. It might be practical with autofocus and maybe an improved Z axis. Or maybe this lens is just no good with this setup.

I’d like to look at upgrading to an infinity corrected lens setup as well. These lenses are more expensive but may offer better sharpness and a more convenient geometry.

I’m also considering mounting two cameras and lenses side by side and allowing zoom to switch between them, to cover a wider range of zoom than the digital zoom can allow.

Autofocus

The depth of field of microscope lenses is very shallow: a matter of microns! Jogging the Z axis back and forth a micron at a time is pretty tedious. Some form of autofocus will be very helpful to the user.

There are various methods of measuring focus which can be combined with small movements of the Z axis to automatically fine-tune focus. I’ve tried out variance-of-laplacian and it seems to give a pretty clear peak.

I’ve also looked at Deep learning for single-shot autofocus microscopy which seems like a really interesting way to do autofocus more efficiently. I’ve noticed when manually focussing that it’s often possible to estimate if the focal plane is too high or too low just by looking at the shape of the blur, so this technique seems promising.

Lighting

Lighting is definitely a big issue here, and I’ve been experimenting with lighting from above, below, on the sides, etc. I think it might end up needing to have several lights so that lighting can be adjusted depending on the situation.

So far the best setup has been a ring of six LEDs with the lens peeking through the center. These are too bright sometimes though, overloading the sensor, so PWM control of the lights would make sense.

I’m also quite taken with the appearance of dark field microscopy for this and stumbled upon the Arlow-Abbe Condenser which looks like an interesting concept as it would make it possible to switch lighting options under software control. The condenser would have to move with the lens though, which would require significant changes to the stage setup.

Motion Platform & Controller

The stage is approx 100x100x100 mm using 3 stepper axes with about 1.25µm resolution:

See Three-axis motion with GRBL.

More details TBC and 3D models for the parts connecting the stages will be included under models/.

Improved Z axis

The useful range of the Z axis for focussing is only 2-3mm which makes using a 100mm stage seem a bit silly. I’m thinking of replacing it with a shorter, lighter, more precise stage.

With a microscope lens on board and the long tube (~180mm) required to adapt it to the camera, there’s a noticeable vibration in the image when moving unless acceleration is severely limited. A more rigid stage and/or more sophisticated kinematics might help.

GRBL Controller

A 3-axis GRBL controller board drives the three axes and has microstepping drivers so the steppers can be run at 1, 2, 4, 8 or 16 microsteps per step.

This board can potentially control the lighting as well, there are several interfaces for laser and/or spindle control which I could repurpose to drive LED lights.

Server Software

A really simple aiohttp based server is under server/. Static files including HTML, CSS and Javscript are under server/static/.

This software is simple enough that it could run easily on an RPi or similar SBC. It currently doesn’t do any image processing, just picks the frames up and sends them.

Autofocus and video clip recording will need more processing power and OpenCV for image processing so the plan is to run it on a Jetson Nano I happen to have laying around, which has good GPU capabilities plus a MIPI-CSI2 interface for the camera.

Streaming Images

Images are captured at 1024x768 pixels and served up as JPEG frames in a multipart/x-mixed-replace Motion JPEG (MJPG) stream. Clients only recieve frames when they’re ready for them, as a primitive form of throttling.

Capturing Video

Movement is a really important part of identifying small, semi-transparent creatures, so as well as screenshots users can capture small videos.

To capture video, a /vid handler starts a task to enqueue frames, and spawns a process which uses OpenCV) to encode frames into an AVI file using an XVID (MPEG4) codec. The output video is written to a temporary FIFO which is streamed to the client as it becomes available.

At the moment, videos are 200 frames (about 10 seconds) long, less than 2MB in size.

User Interface

Simple Javascript UI should mostly just display the image received, but also should allow control through many different mechanisms:

A “map” of the whole area in reduced resolution would be nice too, and a scale indicator in mm.

Control of lighting might be useful as well.

Communicating with the GRBL controller

The server communicates with the server using G-code over serial over USB. The serial port on this particular controller appears as /dev/ttyACM0 or similar under Linux with identifiers 0483:5740 STMicroelectronics Virtual COM Port.

The server sends G0 commands to move the stages and also polls their position using the ? realtime command. A separate task listens to the serial data received from the controller for position updates and relays these to each connected client.

Eventually some more sophisticated movement may be implemented but this will do for now.

Reflector

Eventually it might be a good idea to implement an intelligent proxy which can receive a single stream from the (each!) microscope and multiplex them out to multiple destinations. I did get as far as setting up a linode to host this and configuring letsencrypt.

Other Thoughts