TCD1304-based linear CCD module driven by a Nucleo F401RE, an STM32F401 black pill or an STM32F103 blue pill
To make the experience fit your profile, pick a username and tell us what interests you.
Driving the TCD1304:
The TCD1304 requires the following input to function
The frequency of fM must be in the 0.8-4 MHz range. In this project fM = 2.0 MHz (but it is user changeable)
The SH-period defines the integration time. The ICG-pulse defines the moment the pixels are moved to the shift register.
The datasheet provides the following figure for the timing requirements for the SH and ICG pulses:
This translates to the following:
This is all taken care of by the timers in the STM32F401RE. In fact once they're set up the MCU is not doing any work. The only thing the user has to do is to choose ICG-periods that are multiples of the SH-period.
Since the timers controlling the SH- and ICG-pulses are 32 bit (and run with a frequency of 2.0 MHz) the possible integration times are in the range of 10 µs - 2147 s.
Reading the TCD1304:
The data rate of the CCD is 1/4 of fM, which means the pixels are clocked out at 0.50 MHz. The ADC in the STM32F401RE is fast enough to do 12 bit conversions at this rate. The pixel values are sent to a 16 bit array using DMA. From here they are sent to the Raspberry Pi over SPI at 16 MHz - also utilizing DMA - or through UART to a regular PC via the built-in ST-link's USB-connection.
The voltage of an "dark" pixel is around 3.0 V and a "white" pixel has a voltage of around 1.5 V. In other words the data is upside down.
Total cost of the project:
Raspberry pi zero 5$ (optional)
Nucleo F401RE 11$
TCD1304 2-3$
miscellenaeous 5$
All in all it can be built for around 25$
More information:
The source code is littered with comments as best I could, so dig into it if you want to know more details about setting up the STM32F401RE's peripherals.
This project is part of The Otter DIY Raman Spectrometer. You can read more about that here: erossel.wordpress.com
License:
Everything comes with the FreeBSD-license, so do with it what you want. The only exception is the Nucleo F401RE which is under ST's evaluation license.
Zip Archive - 139.84 kB - 10/28/2018 at 07:53
It's been on the todo list for a long time, but I've finally come around to (re)writing the firmware using the STM32CubeIDE and for a version for the stm32f401 "black pill".
It's implemented with LL and HAL. LL is used for the timers, adc, dma and gpios, while HAL is used for the virtual com port via usb.
Live-view is quite a different experience with the a frame-rate > 10 Hz compared to the UART firmware's 1,4 Hz (limited by the fixed baudrate on the nucleo-board's st-link).
As usual, find the latest source code and binaries on tcd1304.wordpress.com
So someone needed to drive and read the linear ccd TCD1254GFG and it turns out that the driving pulses has the same timing requirements as the TCD1304, so the firmware for the TCD1304 required very little modification to work with the TCD1254.
The TCD1254 comes in a different package, so it also required a little work to make a circuit board. But less saying and more doing:
but not too much doing ..for instance I didn't bother scaling the x-axis here
and also, I've only made an STM32F401RE-version ()UART). I'll get around to fixing up the STM32F103 and the STM32F405 during summer, and perhaps even that STM32F303 I started and didn't complete because life suddenly made different plans
This is not really a new feature. I made the first double-CCD firmware two years ago for a group of students in Germany. I forgot what they used it for, but they paid me in delicious german food.
I've since received a couple of requests for this feature from others, and rather than do a per-bratwurst-offering, I've decided to include it in the downloads-section at tcd1304.wordpress.com. There you'll also find a more in-depth walkthrough about considerations to make before changing the 4 or 5 lines of code required.
The long story short is that you can drive and read up to four CCDs with one STM32F401RE nucleo with an MCLK of 2,0 MHz. If you lower the CCD-clock, you can get away with up to eleven CCDs (my back-of-the-envelope calculations say). Of course you may run out of gpio's for ADC-input with that many CCDs, I haven't checked.
Anyway, here are some pictures.
One CCD is covered with M2-washers, the other with ball-point pen spring. Here's what's captured:
The pyCCDGUI has received a lot of love this weekend. I'm most proud of moving the serial port handling to a separate thread, so the GUI remains responsive during long integrations, but the most interesting new feature is probably the "live-view".
Ok, so it's not super lively with the nucleo F401 which can only transmit at a frame-rate slightly higher than 1 Hz (because of the slow UART-connection to the ST-link), but with the STM32F103 where there's real USB, the pyCCDGUI can now read the TCD1304 and update the plot at up to 9,5 Hz.
There's also a few other new things (filehandling, a flashy new progressbar, compensation for shift register imbalance and few updates to the help-section). Check it out for yourself. Files are available at tcd1304.wordpress.com
Here's a screenshot for the impatient:
I've not yet updated the firmware for the STM32F405 to support continuous output, so I cannot yet report the frame-rate with this mcu.
The blue pill is very popular (and cheap), and I've spent this weekend porting the TCD1304 driver firmware to it. It's a less capable chip than the STM32F401, there are limits to the applications. Most importantly, it doesn't support integration times longer than 82 ms.
The specifications are:
Pin-out is:
The board attaches as a virtual com-port, so the usual tools work ie. the pyCCDGUI and the CLI (UART).
Everybody loves pictures, so:
Get it while it's hot. Go to tcd1304.wordpress.com
I'll keep this short. I've written a graphical user interface for python 3. pySerial handles communication, so there are no ties to Linux and/or macOS with this one.
The program can be found in the files-section and on tcd1304.wordpress.com of course.
And here's the stand-alone windows executable
Driven by a nucleo board, the signal from the CCD in the typical drive circuit with a low-noise low drop-out voltage regulator exhibits roughly ±4 mV of noise. This figure is the same for the custom STM32F405 board, however because the opamp has a gain of ca. 2, the S/N-ratio has improved with app. 50%.
Still, the output looks kind of fuzzy, as seen in this figure showing the CCD at close to saturation:
However, because the noise-level is now a little lower, it's become very easy to estimate the CCD's register imbalance, and when correcting the data for it, the same data now looks like this:
I'm not sure I'll get a cleaner picture than this. I'm certainly not in the mood for trying.
The UART-firmware uses the USB-connection on the nucleo's ST-link, and it's limited by the bitrate of the ST-link's USB-UART connection.
The latest firmware is written for the STM32F405-board from this project:
https://hackaday.io/project/56937-stm32f4inputs
and it uses the USB-controller in full speed mode (12Mbps) to communicate directly with the PC.
I've used ST's USB-driver (SPL-version), and the MCU presents itself as a virtual com port, so the CLI and GUI for UART can be used without modification for the firmware.
Clocks, PWMs and communication are all working. I'm going drinking, so tests with a TCD1304 in place will have to wait.
oh right and the firmware can be found in the files section.
I've ben working on a custom STM32F405 board with better analog options in a separate project.
The key difference is the utilization of an opamp on the input, to squeeze the last bit out of the STM32F4's 12-bit ADC.
The opamp circuitry looks like this:
For reasons I don't fully understand, the opamp's input and feedback resistor values affect the output from the CCD's typical drive circuit, but changing the resistors to:
there's no clipping of the output. I guess my quantum chemistry professor was right, you can't measure a system without changing it.
With a slight redesign of the SPI-firmware and the accompanying command-line-interface, I'm proud to present a record high (for me at least) frame-rate for the TCD1304 of theoretically 125 Hz.
I'll be conservative and state that 100 Hz is possible. Because of x-mas I'm away from my scope, so a proper speed-test will have to wait.
The very short version of the story is that wiringpi has been replaced in favour of pigpio, and that SPI-communication is triggered by monitoring the logic state of one of the nucleos GPIOs.
Oh and you can collect 65535 integrations in one go.
https://erossel.wordpress.com/2017/12/24/high-framerate-125-hz-tcd1304-firmware/
or look in the source code.
Downloads are available at https://tcd1304.wordpress.com
The UART-firmware is still crawling away at a pace of just above 1 Hz, but with lots more convenience.
Connecting the TCD1304 board to the STM32F401RE:
Or if you went with the 2nd SMD-version:
Or the version with a regulated voltage supply:
The connections depend on the firmware. If in doubt download the latest firmware from http://tcd1304.wordpress.com and follow the instructions at that site (I don't always remember to keep HAD up-to-date.)
Ideally the TCD1304 runs on 4.0 V, but connecting V+ to the +5V pin works fine.
Connect Nucleo F401RE to Raspberry Pi:
The SPI headers on the raspberry pi are located on:
On the nucleo board these are located on:
Setting up the cross-compiler on linux:
Download the gcc-arm-none-eabi
Unzip to a directory, and add the compiler to path by adding this line to .bashrc:
export PATH=/home/user/gcc-arm-none-eabi-4_9-2015q1/bin:$PATH
Download the standard peripherals library (SPL) for the STM32F4.
Unzip.
Download the TCD1304 driver firmware for the Nucleo F401RE
Unzip to the directory the SPL unzipped to. Enter directory and type 'make'.
Upload the resulting .bin file to the nucleo board.
NB: If you haven't got a 74HC04 or other inverter between the nucleo and the TCD1304 there are a couple lines in timer_conf.c you'll want to change. Inverse the timer polarity registers.
Create an account to leave a comment. Already have an account? Log In.
Esben, thanks for sharing this work! I built it and it works!
thank you for the feedback. there' more than 120 people who've the bought PCB's and no complaints so far :)
Hi Esben ! Impressive work. We want to use it on a Michelson interferometer at the University. It would allow students to do great spectra ! I didn't managed to find the LDO PCB schematic ? Can you help me ? I want to merge the LDO PCB and the output conditioning on one Single PCB. Best Regards.
Hi Bertrand. Thank you. That sounds like a really nice project. Would it be possible to get a link or a copy of the course-ware? As for the schematic I will put the entire kicad-project library in download-section:
https://tcd1304.wordpress.com/downloads
Also I would love a copy of your final schematic. I feel quite certain I'm making lots of beginner mistakes.
I just asked the teacher in charge to contact you for the course-ware, he's a really cool astrophysicist. He'll be back on Monday. As soon as I have something working I send you the schematic. Thanks a lot !
Where can I find the schematics of the PCB? I find this site too confusing
Thanks
Hello Esben , I am trying to run your UART based GUI, however everytime i execute, and try to record, the GUI crashes immediately, and the terminal says "segmentation fault". Is there a way to fix thsi? I'm pretty new to linux, but from what i've seen this is an issue with unassigned integers . For what its worth the SPI version works perfectly, and I also tried Jens' version of the gui, but i get the same error as i do here.
Thank you
Hi Omar
Sorry for the late reply, your question somehow slipped past me.. You don't mention whether you've compiled the GUI yourself or used the precompiled binary. If the latter is the case, it could simply be that your problem is caused by 32/64-bit incompatability ..most of the stuff I've put online is made on a 12 year old ibm laptop and so the binaries are 32-bit..
Even if this is not the cause of the problem (I'm just guessing here), I would recommend you try and compile the program yourself. If nothing else you will get some compiler errors to show..
You are welcome to email me any screenshots and files. Use the contact form on tcd1304.wordpress.com then I will get back to you from my regular email address.
Last words: I don't really recommend the GUI, I think you should much rather stick to the CLI. Of course the GUI is convenient for testing, but I have a feeling it could have been programmed a lot better/elegantly..
Thanks for your answer Esben. It seems to me that pixel rate would be too low for my project. If this limited speed is due to the ccd and the spi , I guess it would be a big work for me to move to a faster ccd and a faster bus. It would makes too much changes for my limited knowlegde about electronics . I will probably try another way, using a commercial scanner , hoping that using the driver is not too much complicated.
Shape of the pixels would not be a problem for building the picture. I am more concerned about pixel rate. How to get a fast capture ? Wouls it be possible to get 500 or 1000 lines/seconde ?
The bigger the pixel, the faster the exposure time ?
Roberto
There are some built-in restraints with the CCD. For instance, the maximum MCLK is 4.0 MHz and the pixels are clocked out at a rate of MCLK/4. So the very minimum time to capture a frame is 3694/1 MHz = 3.7 ms. Add this to the transfer-time which is 4.2 ms with SPI at 16 MHz (the maximum datarate of the rpi's SPI-peripheral) you end up with a frame-rate of 1/(4.2 ms + 3.7 ms) = 126 Hz
Changing the ADC-DMA to a double-buffering scheme one can read the CCD and transmit at the same time, giving a frame-rate of 1/4.2 ms = 238 Hz with an overhead of up to 0.5 ms for exposure. This however is not implemented and would require a bit of fiddling with the setup of the peripherals. It should not be very difficult to achieve though.
Someone speculated in having two or more CCD-modules working in parallel thus reducing the time significantly, but I've not seen any updates on this:
https://midnight.computer/2016/03/08/some-notes-towards-a-scanner-camera.html
This project seems great ! Would it be possible to use it as a start for building a linescan camera , making pictures by addition of lines of pixels during a motion ?
Roberto.
Hi Roberto
I guess you could do that. In this case I would recommend to use it in conjunction with a raspberry pi to keep the transmission times low. I don't know if it's a problem or not, but the pixel size is 8x200µm, so I imagine you'll have to do some kind magic to get an undistorted image.
One solution (partly at least) to this problem could be to use the tcd1305 instead of the tcd1304. The tcd1305 has a pixel size of 8x64µm, but is otherwise identical (according to the datasheet) to the tcd1304.
I am very enthusiastic about this project. In the last few months I have built a OtterVIS-Spectrometer and connected it to a raspberry 3. I found out that setting the pulse_counter to 3 in the stm32F4xx_it.c improves the stability of the system. I put some pictures on http://science.jefro.de
Caution the blog is under construction!
That's great. Thanks for reporting. I will try that out.
And nice blog btw, I will definitely keep myself updated on it.
In case anyone thinks my graphical-user-interface is crap, then take a look at Jens-Ulrich's blog science.jefro.de . He has extended it with Octave and changed so much I can hardly take any credit for it any more.
Esben, I have received the PCB, hex inverter and transistor - thank you! My Nucleo is here and I realised you used a linux toolchain. Do you have a recommendation for a Windows-based way of getting the firmware onto the Nucleo? Sorry to be a burden but I'm branching out from my comfort zone with this project.
Also, thanks for the recent updates on UART - I definitely want to use this without the Pi if possible.
I've had a look at the CCD datasheet and can't find any spectral sensitivity information. Do you have any data on this? I'd like to use this in a ranging application so choosing a wavelength that the CCD is sensitive to is quite important for me.
I believe there's a windows version of the gcc-arm-none-eabi compiler. I've not used windows for 10+ years, so I cannot help you with the setup, but I imagine it's not to dissimilar from setting it up on linux. Alternatively you could run the compiler off of raspbian. (but isn't there a precompiled .bin file in the firmware-zip that you can just copy to the nucleo?)
there's a spectral response curve in the datasheet. I have it here as well: https://tcd1304.wordpress.com/tcd1304-specifications/
You should easily be able to use anything between 400-800 nm.
You know, I am thinking about this CCD module of yours with serious consideration for a more advanced project of mine, more within the realm of the Raman spectrometer type.
Any idea if your work can easily be adapted to more high res linear CCDs? I found another Toshiba device that's at the high end of their offering, the TCD2964BFG. http://www.glyn.com/data/glyn/media/doc/TCD2964BFG_080131_E.PDF Would be awesome to work on a scanner camera from scratch.
A quick look through the datasheet for the TCD2964BFG I'd say you'd need to rewrite the firmware quite a bit. There are more inputs, you have three outputs (so you'd probably need a faster ADC than the STM32F4's) and finally there are more timing requirements to meet.
In any case, I would take a close look at the output data rate from the CCD (if I read the datasheet correctly the lowest data rate is 3x 150 kHz) and see if the ADC in the nucleo can keep up with this.
Hey, I was wondering if you think this ccd and reader setup could be persuaded to do the duty for a low cost neato-esque lidar based on triangulation. I'm particularly interested to get something that works in daylight for a horticultural robot (along the lines of ardumower). If the processing of the brightest pixel can be done at the ARM processor, there should be a reasonably high resolution ranging system available here. I'd love to hear your thoughts on this.
I honestly have no idea about that, but I can say that it's the MCU's peripherals who do all the work, so the processor is idling something like 99% of the time, so there's plenty of free horsepower to do calculations.
Thanks Esben, I've messaged on your blog - interested if you have any spare PCBs left.
Great work! But why not swap the microcontroller for a single-channel ADC with SPI? You can control the CCD via the RPi's GPIOs and take readings with it's SPI (that can reach speeds of 125Mhz). This will reduce costs, give other users flexibility, remove the need for firmware and solve your transfer speed issue. This will of course require the firmware be ported to RPi software, but this way you should be able to push the CCD to it's limits.
The rpi doesn't have timer peripherals, so it would (for me at least) be very bothersome to create driving pulses for the CCD. I believe the Beagle-what-ever-boards would be a better option, if you absolutely don't want the nucleo-board. I'm working on a UART-firmware to get rid of the rpi ..that would give even more flexibility at lower cost still.
Hi Esben, you've had another shout out on the hackaday blog and this time it's a full post! Congrats!
Thanks for the follow btw, small world, you don't know me but we have sciencemadness forums in common.
Thx. Yes, I do believe we know each from sciencemadness :)
Wow! This is quite amazing, I have been looking for a more sophisticated CCD camera for my next spectrometer project and this is very interesting!
Hi Esben, what about adding the processing power of a complete spectroscopy software package to your hardware? I've just started working on this: https://hackaday.io/project/11264-universal-software-for-diy-spectrometers Might be a useful addition?
Hallo Friedrich
That's a nice project, and it would certainly add functionality. So far the software I've written (I'm not very experienced at coding) is merely proof of concept.
I've only had a quick glance at your project. The SPEKWIN32 looks impressive, and I will certainly take a closer look at the Useful information section on your page. I will help you all I can if you're interested in writing a windows driver for the linear CCD module.
tschüß
Currently I am busy with driving my Kickstarter campaign besides my day job But hooking up spectrometer is definitely a direction I want to go. The benefit is just so huge: to combine a fully blown spectroscopy software with your DIY spectrometer:-) As I am quite dull with low-level electronics hacking, I have to rely on folks like you...
Do you think it could work with these even cheaper STM32 Minimum Development Boards: http://www.ebay.com/itm/NEW-ARM-Cortex-M3-STM32F103C8T6-STM32-Minimum-System-Development-Board-H5-/111774405157?hash=item1a06461225:g:Wa4AAOSw37tV-rz8
I'm not an expert in ARM-programming, but from a quick look at the datasheet for the STM32F103 I'd say it has enough timers (I use 4: two 16 bit for the high frequencies (fM and ADC-trigger, and two 32 bit timers for the SH- and ICG pulses that require very long periods for long integration times).
If I understand correctly the STM32F103 has seven 16 bit timers, and no 32 bit ones, however if you're going to do photography you might not need the time the extra 16 bit buys you.
The ADC's looks ok (again no guarantees) and there are DMA- and SPI-controllers as well.
In short it has all the peripherals my firmware for the STM32F401RE utilizes, so I would expect it'd work, of course you'd need to do a bit of tailoring to make it work on this device.
There is a 16-bit prescaler for each of the timers, so you can already get long time delays. You can also link 16-bit timers in master/slave to emulate 32-bit one.
With a 3d printed enclosure and a quality camera lens, do you think this could be used as an alternative to an (expensive) industrial line scan camera?
Definitely. One thing to be aware of is that the pixels in the TCD1304 are not square. If I remember correctly they're 8 µm wide and 200 µm tall - check the datasheet.
You'd might also have to modify the firrmware to suit your needs, for instance a single line of your image would take up 7388 bytes. With a total of 512 kB of ram you're limited to an image size of max 70 lines if you don't transfer data between each reading.
As it is the data transfer between the rpi and the f401re takes around 4 ms for 3694 pixels.That should give you some indication of the minium exposure time for an image of a given size.
to follow this project and never miss any updates
this looks awesome! I’ve been hoping to make a scanning camera for years. It’s awesome to see that you’ve gotten this linear sensor working as a spectrometer!