Skip to the content
2 layers61 × 36 mmEpc901-breakout, the printed circuit board in 3D

Epc901-breakout

astuder/epc90158

Experiments with ESPROS epc901 1024x1 CCD line sensor, including a spectroscope.

Size
61 × 36 mm
Copper layers
2
Thickness
1.6 mm
Parts
55
Nets
37
Pads
150
Tracks, vias
370, 41
Pours
6
Routed
Yes
KiCad
KiCad 5 (file 20171130)
Created
7 Oct 2020
Updated
3 Mar 2023

Overview

Epc901-breakout is an open-source printed circuit board by astuder, from the astuder/epc901 repository on GitHub. It is a 2-layer board of 61 × 36 mm with 55 parts on 37 nets, routed with 370 tracks and 41 vias.

Its parts include 23 resistors, 10 capacitors, 3 ICs, 1 connector and 1 inductor. It belongs with the sensors and measurement and interfaces and adapters boards of this library.

README

README.md

Introduction

The ESPROS epc901 is a CCD line sensor with a resolution of 1024 monochrome pixels.

Compared to other image sensors the epc901 is very easy to drive, requiring only one voltage, I2C, a few digital I/Os and an ADC. It is also available for $33 in single units from Digi-key. On the downside, the sensor comes in a BGA package, the evaluation kit is very expensive at $1400, and we haven't seen this sensor from any other distributors than Digi-key.

This repository contains design files to build hardware and software to interact with the sensor.

For Windows users, there's now also a version of g3gg0.de SpectrumPlotter adapted to work with my epc901 firmware.

@fmilburn3 posted a write-up of this project and a few spectroscopy experiments on element14.

Table of contents

Hardware

Software

License

Hardware

All hardware in this project is designed with KiCad version 5.1.6.

The hardware consists of a breakout board for the image sensor, and an adapter board for vertically mounting the breakout board on an ST Nulceo-144 development board.

Breakout and adapter boards mounted on a NUCLEO L496ZG

Breakout board

The folder ./hardware/breakout contains the KiCad project for the epc901 breakout board.

The image sensor comes in a 2x16, 0.5 mm pitch BGA package and looks very fragile. With careful handling and placement, we successfully assembled a few boards using a stainless steel solder stencil and an unmodified toaster oven for reflow. Reflow on a hotplate probably works as well.

In addition to the image sensor and related passives, the breakout board also integrates an ADC. Footprint and firmware are compatible with Texas Instruments ADCS7476 and Analog Devices AD7476 which are 1 MSPS 12-bit ADCs with SPI-like interface.

The PCB can be ordered from OSH Park using this link.

Connector pinout

PinFunctionComment
1GNDdigital ground
2PWR_DOWNsee epc901 datasheet
3DATA_RDYsee epc901 datasheet
4CLR_DATAsee epc901 datasheet
5SHUTTERsee epc901 datasheet
6CLR_PIXsee epc901 datasheet
7GNDAanalog ground
8VIDEO_Ppositive video signal for use w/ external ADC, see epc901 datasheet
9VIDEO_Nnegative video signal for use w/ external ADC, see epc901 datasheet
10GNDAanalog ground
11GNDdigital ground
12ADC_CLKSPI clk to on-board ADC
13ADC_DATASPI data from on-board ADC
14ADC_CSSPI chip select for on-board ADC
15GNDdigital ground
163V33.3V power supply
17GNDdigital ground
18READsee epc901 datasheet
19SDAI2C data
20SCLI2C clock

Jumpers

IDFunctionComment
JP1STAR GNDStar ground point between GND and GNDA. Close to connect, leave open if GNDA and GND are connected off-board.
JP2ADC SELECTIONSelects whether to use the on-board ADC or an external ADC. External ADC will route VIDEO_P to pin 8 in the connector.

Config resistor array

These resistors control the configuration of the image sensor on power-up. For details, see sections 4, 7.1 and 12 in the epc901 datasheet.

Physical dimensions

The size of the board is 61 x 36 mm. The mounting holes in the corners are spaced 55 x 30 mm and have a diameter of 2.2 mm, designed for M2 screws.

The mounting holes for the lens holder are located 29 mm from the left board edge and 8 mm from top and bottom board edge. They have a diameter of 2.2 mm, designed for M2 screws.

epc901-breakout dimensions

Lens holder & lens

The breakout board has space and mounting holes for a lens holder. The spacing between the mounting holes is 20mm. For full coverage, the lens should support 1/2.3" or larger sensors.

For our prototypes, we chose a M12 metal lens holder w/ 20mm hole spacing and a 25mm M12 lens for 1/2" sensors. In the US, a wide selection of lens holders and lenses can be found at M12 Lenses Inc.

For use in a spectrograph, a lens may not be required. However we recommend protecting the sensor against accidental physical damage with some sort of bracket or baffel.

Adapter board

The folder ./hardware/adapter-shield contains the KiCad project for an adapter to mount the epc901 breakout board on the NUCLEO evaluation board.

The layout of the adapter board follows the Arduino Shield standard. This means you could mount the adapter and sensor breakout board on any compatible MCU board. Though you will likely have to adapt the firmware to make it work.

The PCB can be ordered from OSH Park using this link.

Pin mapping

ArduinoNucleoL496ZGBreakoutComment
+3V3CN8 7+3V3Connected to JP1.
+5VCN8 9+5VConnected to 3.3V LDO.
GNDCN8 11GNDGND
GNDCN8 13GNDGND
D0CN10 16PD9PWR_DOWN
D1CN10 14PD8DATA_RDY
D2CN10 12PF15CLR_DATA
D3CN10 10PE13SHUTTERControlled by TIM1_CH3.
D4CN10 8PF14CLR_PIX
D9CN7 18PD15READ
D10CN7 16PD14ADC_CS
D12/MISOCN7 12PA6ADC_DATA
D13/SCKCN7 10PA5ADC_CLK
GNDCN7 8GNDGND
A0CN9 1PA3VIDEO_P
A1CN9 3PC0VIDEO_N
CN10 1AVDDConnected to JP3, reserved to supply analog power from Nucleo in future revisions.
CN10 3AVSSConnected to JP4, alternative source for analog ground from Nucleo.
CN10 5GNDGND
CN10 7PB1VIDEO_PAlternative analog pins for use with AVDD and AVSS connection in future revisions.
CN10 9PC2VIDEO_NAlternative analog pins for use with AVDD and AVSS connection in future revisions.

Jumpers

IDFunctionComment
JP13.3V VCCSelect between LDO on adapter or Nucleo (HOST) as source for 3.3V power supply to breakout board.
JP2* GNDStar ground point between GND and GNDA. Close to connect, leave open if GNDA and GND are connected on breakout board.
JP3AVDDReserved for future use to supply power to VDD_OA of the EPC901 from the Nucleo.
JP4AVSSStar ground point between analog ground of the breakout board and analog ground of the Nucleo. May be useful when using the ADCs of the STM32.

Shared

The folder ./hardware/shared contains custom KiCad symbols, footprints and 3d models that can be reused across KiCad projects in this repository.

Spectroscope tube

For spectroscopy experiments we created a tube to mount an optical slit and difraction grating. The 3D model is available in the folder ./hardware/spectroscope-tube.

Software

Firmware

The folder ./software/breakout contains the firmware to control the epc901 breakout board with an STM32L4 using the NUCLEO-L496ZG evaluation board. This specific MCU and evaluation board were chosen because we had one laying around.

The firmware is developed and built with the latest version of STM32CubeIDE (version 1.4.2 as of October 2020). To import the project into STM32CubeIDE, clone this repository, open STM32CubeIDE and import the project with File > Open Project From File System.., and select the folder ./software/breakout. Follow the standard procedure for building the firmware and programming the NUCLEO evaluation board.

Shell

The firmware exposes a command shell over serial. The parameters of the serial connection are 115200 8N1.

Preceding a command with @ will suppress local echo and command prompt, which is useful when developing an application that interacts with the shell.

Most commands that configure an aspect of the firmware return the current setting if no value is provided. For example exposure will return the currently configured exposure time.

CommandDescription
helpDisplay list of available commands.
help COMMANDDisplay help text for command.
echo ON/OFFTurn local echo on or off.
regread REGISTERRead register of image sensor over I2C.
regwrite REGISTER VALUEWrite to value to register of image sensor over I2C.
reset mcuReset the STM32 microcontroller.
reset cameraReset the camera settings, for example exposure or burst, to their defaults.
reset sensorSoftware reset of the image sensor through I2C.
exposure TIME_USSet exposure time in microseconds.
exposure maxGet maximum exposure time supported.
captureStart capture using the configured settings.
capture abortIf there's a capture in progress, abort current capture.
transferread next image from the frame buffer.
transfer allread all images available in the frame buffer.
transfer lastread last image from frame buffer, all other images will be discarded.
burst ON/OFFturn burst mode on or off.
burst fastTurn on burst mode with fast capture, where image capture and data read out overlap. This can result in noisier data than regular burst mode.
burst frames COUNTSet number of frames to capture in a burst.
burst interval TIME_MSSet interval in milliseconds at which frames are captured. 0 will capture frames at the maximum speed possible.
trigger ON/OFFEnable or disable trigger.
trigger source EXTERNAL/LEVEL/ZONESelect source of trigger signal.
trigger direction RISING/FALLINGSet which direction of a signal will trigger. for level and zone rising means above/inside level/zone, falling means NOT above/inside.
trigger level LEVELSet trigger level for level trigger source.
trigger zone X1 Y1 X2 Y2Set trigger zone defined by two corners for zone trigger source.

Capture logic

The capture command will start the image capture process based on the configuration of the camera.

First the firmware checks if there's enough space in the frame buffer for the configured number of frames (1 or burst frames). An error will be returned if there is not enoug space.

Next, if trigger is enabled, the camera waits until the configured trigger condition is met.

Next, image capture starts. If burst is enabled, it will capture the configured number of frames. All frames captured are stored in a frame buffer.

After the capture process is complete, images can be read from the frame buffer with the transfer command.

The shell will respond with BUSY if the camera is waiting for a trigger or a single image capture or burst is in progress. At any time, the command capture abort will return the camera back to idle state.

Trigger logic

External

The external trigger source is wired to pin D35/PB11 and the USER button (B1).

Trigger direction rising triggers when the signal changes from low to high, or when the button is pressed down. Trigger direction falling triggers when the signal changes from high to low, or when the button is released.

Level

The level trigger source uses live sensor data to trigger. When starting capture, the firmware will continously capture images until the trigger condition is met or capture is aborted.

Trigger direction rising triggers when a pixel is on or above the configured trigger level. Trigger direction falling triggers when no pixel is on or above the configured trigger level.

Zone

The zone trigger source uses live sensor data to trigger. When starting capture, the firmware will continously capture images until the trigger condition is met or capture is aborted.

Trigger direction rising triggers when a pixel is inside the configured trigger zone. Trigger direction falling triggers when no pixel is inside the configured trigger zone.

Transfer format

The transfer command reads images from the frame buffer and sends them over serial. Each image is sent in two chuncks, each terminated with a linefeed.

  1. Frame metadata seperated with commas: frame number, time in milliseconds since first frame, exposure time in microseconds, number of pixels in frame
  2. Frame data: a continous string with one 3-character hexadecimal number per pixel representing the brightness value

Python

The folder ./software/python contains a Python library that wraps the shell of the firmware, and a few useful Python scripts that use the library.

epc901camera.py

The Python library epc901camera.py wraps the shell exposed by the firmware into an API that's easy to use from Python.

text
from epc901camera import Camera
camera = Camera()
camera.open("my serial port")
camera.setExposure(1000)
camera.capture()
pixels = camera.getPixels()
camera.close()

You can use sendCommand() to directly interact with the shell, which can be useful for operations that are not supported by the library yet. The following snippet writes to I2C registers of the sensor to increase the gain.

text
camera.sendCommand("regwrite 2 0x99")  # turn on config via regs
camera.sendCommand("regwrite 0 0x19")  # 4x gain, read-out direction same as set by resistor

See example scripts for more details.

example scripts

There are three scripts to interact with the breakout board:

  • live.py displays output of the image sensor in realtime
  • snap.py captures one image
  • burst.py captures a series of images in a burst

The scripts are controlled with shared and a few unique command line arguments.

Argumentlive.pysnap.pyburst.pyDescription
-h, --help:heavy_check_mark::heavy_check_mark::heavy_check_mark:Display help text.
-p PORT:heavy_check_mark::heavy_check_mark::heavy_check_mark:Serial port which connects to the camera board, this is the only required argument.
-e EXPOSURE:heavy_check_mark::heavy_check_mark::heavy_check_mark:Set exposure time in microseconds. If not specified, the default exposure time is 1ms (1000us).
-t {external,level,zone}:heavy_check_mark::heavy_check_mark:Enable trigger and select trigger source. See Trigger logic.
-tdir {falling,rising}:heavy_check_mark::heavy_check_mark:Set direction of trigger logic.
-tl TRIG_LEVEL:heavy_check_mark::heavy_check_mark:Set brightness for level trigger. Valid values are 0-4095.
-tz x1,y1,x2,y2:heavy_check_mark::heavy_check_mark:Define rectangle for zone trigger. Valid x values are 0-1023, valid y values are 0-4095.
-td TRIG_DELAY:heavy_check_mark::heavy_check_mark:Set delay in milliseconds after trigger event before image capture starts.
-f FRAMES:heavy_check_mark:Number of frames to capture in a burst.
-i INTERVAL:heavy_check_mark:Set time interval in milliseconds between frames. 0 means best effort, i.e. at maximum speed possible. As it takes 1.3ms to read out a frame, effective capture rates may be lower than the configured interval.
-fast:heavy_check_mark:Enable special burst mode where frames are read out of the sensor while the next exposure is captured. This may increase noise, but will increase effective burst speeds.
-gq:heavy_check_mark::heavy_check_mark:Don't display graph window.
-g GRAPH_TYPE:heavy_check_mark:Display animated 2D graph or 3D surface plot. If argument is missing, no graph will be displayed.
-gc COLOR:heavy_check_mark:Select alternative color map for 3D graph.
-gpng GRAPH_FILE:heavy_check_mark::heavy_check_mark:Save graph as PNG file.
-png PNG_FILE:heavy_check_mark::heavy_check_mark:Save sensor data as a gray-scale bitmap in a PNG file.
-csv CSV_FILE:heavy_check_mark::heavy_check_mark:Save sensor data as CSV file.
-a:heavy_check_mark::heavy_check_mark::heavy_check_mark:Automatically scale vertical axis of graphs based on image data. If not specified, the Y axis will go from 0 to 3000.
-sx px1,w1,px2,w2:heavy_check_mark::heavy_check_mark::heavy_check_mark:Scale labels of horizontal axis of 2D graphs by linear interpolation based on two points, for example to reflect wavelengths in a spectrograph. If not specified, the X axis will be labelled with pixel positions 0-1024.

License

Unless stated otherwise, all software in this project is licensed under the terms of MIT License.

The main exception are files imported from the STM32 SDK (./software/breakout/Drivers), and a few files auto-generated by STM32CubeIDE. See source code for applicable license terms.

All hardware in this project is licensed under the terms of CERN Open Hardware Licence Version 2 - Permissive.

See LICENSE-SW and LICENSE-HW for additional details.

Parts

55
QtyValueFootprintReferences
15DNPResistor_SMD:R_0603_1608MetricR2, R10, R11, R12, R13, R14, R15, R16, R17, R19, R21, R23, R24, R25, R26
10TestPointTestPoint:TestPoint_Pad_D1.0mmTP1, TP2, TP3, TP4, TP5, TP6, TP7, TP8, TP9, TP10
51uFCapacitor_SMD:C_0603_1608MetricC1, C2, C5, C6, C7
410KResistor_SMD:R_0603_1608MetricR18, R20, R22, R27
4MountingHole_PadMountingHole:MountingHole_2.2mm_M2_DIN965_PadH1, H2, H3, H4
20.1uFCapacitor_SMD:C_0603_1608MetricC8, C10
20RResistor_SMD:R_0603_1608MetricR3, R4
22.2uFCapacitor_SMD:C_0603_1608MetricC3, C4
1100RResistor_SMD:R_0603_1608MetricR5
110uFCapacitor_SMD:C_0805_2012MetricC9
156K 1% 100ppm/KResistor_SMD:R_0603_1608MetricR1
1600R @100MInductor_SMD:L_0603_1608MetricL1
1AD747xPackage_TO_SOT_SMD:SOT-23-6U3
1Conn_02x10_Odd_EvenConnector_PinHeader_2.54mm:PinHeader_2x10_P2.54mm_VerticalJ1
1EPC901epc901:epc901U1
1Jumper_3_Bridged12Connector_PinHeader_2.54mm:PinHeader_1x03_P2.54mm_VerticalJP2
1Jumper_NC_SmallConnector_PinHeader_2.54mm:PinHeader_1x02_P2.54mm_VerticalJP1
1LensMountepc901:lensholder-m12-20mmH0
1REF3030Package_TO_SOT_SMD:SOT-23U2

More from astuder/epc901

1
  • 2 layers57.1 × 53.3 mmAdapter shield, the printed circuit board in 3D

    Adapter shield

    astuder/epc901

    Experiments with ESPROS epc901 1024x1 CCD line sensor, including a spectroscope.

    19 parts58

Similar boards

  • 2 layers229.5 × 95.1 mmSweep high, the printed circuit board in 3D

    Sweep high

    davidphilipbarr/Sweep

    Sweep - a small promicro based keyboard inspired by the Ferris.

    55 parts2.1k
  • 2 layers370 × 11 mmDaylight Disco XXL, the printed circuit board in 3D

    Daylight Disco XXL

    VoronDesign/Voron-Hardware

    Cool Hardware designed by the Voron Design group

    55 parts1.1kGPL-3.0
  • 2 layers370 × 10 mmE3NGLEDstick, the printed circuit board in 3D

    E3NGLEDstick

    hackclub/OnBoard

    💡 Join 1,000 teenagers and make your first PCB with a $100 grant!

    55 parts915
  • 2 layers139.3 × 94.8 mmFlake, the printed circuit board in 3D

    Flake

    lever-tech/flake

    An open-source, wireless, split ergonomic keyboard designed to be productive, healthy, and enjoyable. [formerly Anywhy Flake]

    55 parts531CERN-OHL-W-2.0
  • 2 layers237.5 × 102.9 mmMemory, the printed circuit board in 3D

    Memory

    jes/scamp-cpu

    A homebrew 16-bit CPU with a homebrew Unix-like-ish operating system.

    55 parts301Unlicense
  • 2 layers60.6 × 24.1 mmBlep hackerboard, the printed circuit board in 3D

    Blep hackerboard

    CRImier/MyKiCad

    My KiCad boards. Can't be bothered uploading individually anymore, so here you go.

    55 parts253GPL-3.0
  • 2 layers100 × 96.5 mmKeyboard ch552-36-lhs, the printed circuit board in 3D

    Keyboard ch552-36-lhs

    rgoulter/keyboard-labs

    Repo with my PCB designs and keyboard firmware

    55 parts236
  • 2 layers190.5 × 85.7 mmDissatisfaction30, the printed circuit board in 3D

    Dissatisfaction30

    dcpedit/dissatisfaction30

    To get the PCB manufactured, upload dissat-pcb.zip to JLCPCB, select your desired PCB color while keeping all the other default options, and place your order (minimum 5).

    55 parts147CC-BY-4.0

Questions

How big is the Epc901-breakout PCB?

It measures 61 × 36 mm and has 2 copper layers, 1.6 mm thick.

What parts does the Epc901-breakout use?

55 parts. The full list of its parts is on this page, with links to each part's symbol and footprint where PCBKit's library has them.

Where can I download the Epc901-breakout KiCad files?

From the astuder/epc901 repository on GitHub, at the commit this page was made from: the board is hardware/breakout/epc901-breakout.kicad_pcb. PCBKit opens the board in the browser, with nothing to install.

Can I use the Epc901-breakout design in my own project?

Its repository states no licence, so its author keeps all rights: ask astuder before reusing the design.