Skip to content

czbiohub-sf/portable-luminometer

Repository files navigation

High-sensitivity Portable SiPM Luminometer

Introduction

This repository contains the electronics design and control software for a portable, low-cost luminescence reader developed by the BioE team at Chan Zuckerberg Biohub San Francisco (CZ Biohub SF). This instrument was developed in response to the need for a device to read out a split-luciferase luminescence assay for a sars-cov-2 antibody test compatible with remote, low-resource settings. The assay itself was developed by Susanna Elledge et al. in Jim Wells' lab at the University of California San Francisco (UCSF), in collaboration with Cristina Tato (CZ Biohub SF).

Link to preprint: https://www.medrxiv.org/content/10.1101/2023.05.18.23290120v1

Like many assays, the split-luciferase assay was developed on a high-performance benchtop luminometer with sub-attomole limit of detection for luciferase. Unfortunately, there is an orders-of-magnitude performance gap between these devices and available handheld luminometers. The need for the equivalent performance level but in a robust, handheld format was identified by Cristina Tato, and together with Senjuti Saha at CHRF Dhaka, is leading an effort to map coronavirus immunity across rural regions in Bangladesh.

In response to this need, the BioE team developed a portable Silicon Photomultipler (SiPM) - based luminometer. The device accepts 1-2 PCR tubes, and reports on luminescence levels using sensors that are read out by a 24-bit analog-to-digital converter. The device includes a shutter system that repeatedly blocks and unblocks the signal from reaching the sensor, thereby continuously performing dark measurements in order to stabilize the baseline of the measurement against drift, achieving sub-attomole performance on par with high-end benchtop instruments costing an order of magnitude more.

The software was written to run on the Raspberry Zero W inside the device, which interfaces with custom PCBs that perform the physical measurements. The user interacts with the device with side-mounted buttons, and results are displayed on a low-power, e-ink screen.

Full user guide here:

https://tinyurl.com/3p8p7axm

Mechanical model here:

https://cad.onshape.com/documents/681017372753852c73b577a8/w/f1f724f31d32967117942551/e/8bf7604225c699873e8675c3

Organization

The structure of this repo is illustrated below. Note: the 'Electronics design' and 'Early calculations' directories were truncated for brevity.

├── CHANGES.md
├── Early calculations
├── Electronics design
├── LICENSE
├── README.md
├── RPi Config
│	└── config.txt
├── gpclk_config
│	├── README.md
│	└── dt-blob.dts
├── luminometer
│	├── __init__.py
│	├── adc_constants.py
│	├── adc_phat_example.py
│	├── adc_reader.py
│	├── ads131m08_reader.py
│	├── crc.py
│	├── luminometer.py
│	├── luminometer_constants.py
│	├── lumiscreen.py
│	├── menu.py
│	├── no_sensor_validation.py
│	├── pwm_test.py
│	├── screen_test.py
│	└── temp_coeffs.json
└── setup.py

Installation and Use

Option 1: Clone the SD Card

  1. Flash our pre-existing 16gb SD card onto a new card. The latest image can be downloaded from Google Drive here. After downloading the image, use the recommended Raspberry Pi Imager, select the "Use Custom" option, and select the downloaded image to flash it onto the 16gb SD card.

Option 2: Manual install

  1. Install the latest Raspbian OS on a micro-SD card by following the instructions at: https://www.raspberrypi.org/software/
    • The config.txt has been validated with RPi OS (full w/ recommended software) version 5.10.17+
      • We may want to switch to RPi Lite (smaller size, stripped away of superfluous services which may help w/ more "real-time" timing), but we have not validated it yet.
  2. After the OS is loaded on the micro-SD card and while still loaded in your mac/PC/linux machine, replace /boot/config.txt with the version found in this repo. This configures the SPI bus on the device, turns off audio processing and the HDMI driver (to save power), and turns off the on-board activity light (to reduce stray light inside the device).
  3. Follow the instructions to set up the RPi 'headless' (no keyboard or monitor), using WiFi.
  4. ssh into the device
    • Remember to change the hostname after ssh'ing in:
      • sudo raspi-config (see here for more, note that the raspi-config menu may look slightly different than what the documentation shows, but the option to configure the hostname will still be there somewhere in the menu)
  5. Create and activate a virtual environment with Python3:
  • TODO: convert the following three commands into a single command once the repo has been made public
cd /home/pi/Documents/
python3 -m venv lumi
source lumi/bin/activate
  1. Install the display driver from Pimoroni, answering 'y' when prompted.
curl https://get.pimoroni.com/inky | bash
  1. Clone this repository and navigate to the base:
git clone https://github.com/czbiohub/ulc-tube-reader/
cd ulc-tube-reader
  1. Install setuptools:
pip install setuptools
  1. Install wheel
pip install wheel
  1. Install module
pip install .
  1. Follow the instructions in gpclk_configi/README.md in order to configure the general purpose clock on-board the RPi, which the ADC requires as input.
  2. Configure the RPi to run the luminometer software after boot is completed. After these commands are entered, the RPi will automatically start executing the luminometer software upon startup, but it will still be possible to ssh into the device at the same time.
sudo nano /lib/systemd/system/lumiboot.service

In the newly-opened text file, paste the following text:

  • TODO: add in a command to activate the virtualenv on boot as well
[Unit]
Description=Luminometer boot command
After=multi-user.target

[Service]
Type=idle
ExecStart=/usr/bin/python3 /home/pi/Documents/ulc-tube-reader/luminometer/luminometer.py
Restart=on-failure

[Install]
WantedBy=multi-user.target

Now enter the following commands in the terminal to activate the boot service:

ExecStart=/usr/bin/python3 /home/pi/Documents/ulc-tube-reader/luminometer/luminometer.py > /home/pi/lumilog.log 2>&1
sudo chmod 644 /lib/systemd/system/lumiboot.service
sudo systemctl daemon-reload
sudo systemctl enable lumiboot.service
  1. Run the following command to start the pigpiod daemon on startup:
sudo systemctl enable pigpiod
  1. Power down the RPi: sudo poweroff
  2. Attach the Inky pHat to the GPIO header, then securely plug the RPi into the socket header on the luminometer board.
  3. Power on the device and make measurements.

ADC Driver

gpclk_config/ - contains the dt-blob.dts file required to run the ADC. See the README for instructions on setting up the Raspberry Pi.

adc_reader.py - defines the ADCReader abstract base class, includes the basic operations for ADC drivers for this project

ads131m08_reader.py - defines the ADS131M08Reader driver for the ADS131M08. The if __name__ == '__main__' block at the bottom of the file has an example of running the software.

consts.py - defines specific constants for the ADS131M08Reader class, such as register addresses, commands, e.t.c.

crc.py - defines the CRC functions for communications with the ADC.

Updating Module from Repository

  1. Pull changes from remote repository
  2. Activate virtual environment with previous install
  3. Navigate to the module directory
  4. Update module (pip install . --upgrade)

Note regarding licenses:

Two different licenses are used in this repo. The BSD 3-Clause License is applied to the entire repo except for the hardware design files contained in the Electronics design directory, which are separately licensed by the CERN Open Hardware Licence Version 2 - Weakly Reciprocal, contained in that directory.