TCD1304 on macOS


Image from

One of the spin-offs of the raman spectrometer is a small, entirely 3D-printed VIS-spectrometer, that I thought could compete with the relatively expensive commercial USB-spectrometers at my school.

The spectrometer costs less than 80$ in parts and has a resolution of around 2nm. The project page on hackaday is here: Ottervis-lgl-spectrophotometer  but as always, the hackaday layout/interface is not really very easy to navigate and/or maintain, so I’ve created a separate page for the project here: OtterVIS.wordpress

One of the biggest problems of bringing the spectrometer into the classroom is that the students all use either macOS/OSX or Windows[1] – and the interface software is made for linux. I will probably never get around to making a Windows-version was already difficult to learn serial programming for linux.

But as most people know, there’s a UNIX under the apple’s skin, so porting from linux to macOS can be very straightforward. In the case of the Otterly CCD CLI, it’s as simple as installing xcode, glib and pkg-config and changing the makefile slightly.

Of course not everyone needs to compile the CLI for themselves, and installing glib will be the only step required before running a precompiled binary. So with that, it should be possible to get the students to be able to use the spectrometer.

Goto for slightly more details and a download of the sourcecode, new makefile and precompiled binary, all in one zip.

[1] In my six years of teaching, I’ve taught around 400 students. Only one of them used linux. The remaining 399 used macOS and Windows – roughly 50/50 with a slight lead to Apple.

Just a close-up

I received an old Olympus CHB microscope and immediately took a close-up of the TCD1304. I don’t have a camera adapter for the microscope, so I borrowed my girlfriends smartphone to take the picture.

I have no I idea what is what, except that the black area in between the two silvery things contains the pixels. The magnification is 100x.


First steps towards a new PCB

This entire time I’ve been content with the very simple drive circuit from the TCD1304’s datasheet:

tcd1304 typical drive circuitIt has a low parts count, it’s easy to understand and it performs reasonably well.

However, after reading through the Audine project, I’ve realized how elegant TEC can be done, and how inelegant I had planned to do it. So I decided to make a new PCB with a cut-out for a cold tip, and while I was at it I also wanted to try David Allmon’s solution for conditioning the output to the ADC.

And here it is:

Of course it doesn’t work.

Continue reading

Line camera command line

Command line line camera! Line camera line commander? DIY command line camera!? I thought I would be able to make a cool combination with these four words, but obviously not..

I’ve been looking more and more at how Hr. Fröhlich has continued to improve the interface for the linear CCD firmware, and I’ve come to the conclusion that I cannot possibly write a very good GUI.

What the world really needs is something that will make the linear CCD module more modular on the software side, making it much easier to tailor the hardware to your software.

So here it is: A command line interface for the linear CCD module.

There’s also a new SPI-firmware revision, to make the SPI-firmware “pin-compatible” with the UART-firmware and give it all the bells and whistles of the UART-version.

It will be followed up with a similar CLI for the UART, hopefully tomorrow (march 19).


The UART-CLI telling you how to push its buttons.

new box, new setup, new alignment

It’s winter vacation, so I’m out of the classroom for a little while. I’ve looking forward to it for some time and like a good little squirrel, I’ve been stocking up on parts and stuff to do.

I bought new boxes for the Raman spectrometer – the old ones were slim and sexy but I was getting tired of the constraints on my lebensraum:


Initial alignment of the optics in the Raman box. The new box is so spacious.

Continue reading

Firmware revision

I’ve been looking at noise from different angles and the result is a new firmware release for the TCD1304 driver.

There are few important changes, like new GPIOs for the connection to the CCD and I will update the site in the coming days.

If you cannot wait, everything (I hope) is of course documented in the source code.

TCD1304 driver firmware for STM32F401RE nucleo board. Rev. 020217

And below are the boring details:

1: Crosstalk between analog and digital lines

I have no idea how the circuit is laid out inside the STM32F401RE, but on the outside it looks like this:


The previous firmwares had output on PA0 and PA1. Right next to Vref+ and Vref- which the ADC measures input against. The alternate-function mapping didn’t allow for moving the output on PA1, but the output on PA0 has now been moved to a physically more distant GPIO.  For reasons I can’t remember I also moved fM away from PA6.

PA0, PC2 PB0 and PB2 are now pulled down and can be connected to GND to make for a virtual ground at GPIOs around the ADC and the noisy high frequency fM.

2: Speed limits

The GPIO speed has been limited to 25 MHz for all communication and driving pulses.

3: Typical CCD driving and ADC sampletime

The datasheet for the TCD1304 specifies 2.0 MHz as the typical master clock. I have no idea if driving at other frequencies will degrade the performance of the CCD, but the fM has now been increased from 1.4 to 2.0 MHz.

The fM is now defined in main.h and the clocks and periods for the timers for all the other driving pulses are derived from this. You can even change the system core clock and still have proper output, because fM-period is calculated from the APB1-clock,

On the same note the ADC sampletime has been increased from 3 ADC clockcycles to 15.

4: Proper flushing

Obviously this gives a cleaner everything. Seriously though, with proper attention to the pulse sequences just before data-acquisition, the linear CCD module performs much better.

5: Bug fixed

The annoying bug described in the previous post has been squashed. Still the occasional connection issue persists.

Troubles from the past

Jens-Ulrich Fröhlich built my  OtterVIS-LGL spectrophotometer and he reported that changing the pulse counter in the interrupt handler from 2 to 3 improved stability of the readings.

This is correct, so I decided to figure out why, after all I don’t want to wait one integration too long (or too short) for getting a proper reading.

The situation with a pulse counter of 2 looks like this:


The blue trace is the ICG pulse, which determines when the pixels are dumped into the TCD1304’s shift registers and read by the ADC. The ICG timer runs with a certain period (the first four pulses) until the MCU receives the new settings (pulse #5) somewhere after the fourth pulse. Then follows 2 pulses with a short period to clear the CCD, and then the ADC is started.

Of course this is undesirable, and with a pulse counter of 3 the new trace looks like:


The ADC start trace (red) is actually a GPIO that’s set high at ADC-DMA Half-Transfer interrupt and set low again at ADC-DMA Transfer-Complete, in case your wondering why it doesn’t start right when ICG goes high.

Here is a close-up of TIM4 (that paces the ADC) tied to a GPIO together with ICG:


fM (not shown) is 2.0 MHz and TIM4 is fM/4 ie. 0.50 MHz. The timer starts with a negligible delay¹ after ICG goes high, and is turned off 7.4 ms later, just as expected (3964 / 0.50 MHz = 7.4 ms).

I’ve also checked if the DMA_SxNDTR is counting properly, and at 3.7 ms after ICG it’s 1848 and at 7.4 ms it’s 3693 (the DMA is circular and NDTR is reset at the end).

In short I’m fairly certain the timers and their interrupts are behaving consistently and as expected.²

Now comes the puzzling part. Spending the entire weekend looking at the output, I’ve realized that someting odd is going on:

When new settings are received, the MCU is supposed to wait for the ADC-DMA Transfer-Complete interrupt before transmitting the collected pixel values back to the PC. However this is apparently not the case. There are owles in the marsh (as we say in Denmark).

  • For long ICG-periods the consequence is that the MCU transmits the contents of aTxBuffer before it’s updated, ie. you get the previous reading. For some applications this is not a problem. You just collect twice, but if your sample is changing with time this is of not very desirable.
  • For shorter ICG-periods you will see part of a new read and part of the old, and the frame shifts at pixel number: ICG/170. Again you can just collect twice and the problems goes away – if you can collect twice..

The behaviour is of course unacceptable and will be fixed. For now you know it exists!


¹ There are 32 dummy pixels, so with fM = 2.0 MHz theres 16 µs to eat at, but enabling and disabling TIM4 by manipulating directly with the TIM_CR1 register is fast enough that TIM4 is running even before ICG goes low.

² The timer update interrupt appears to also be called when the timer settings are changed. I’ve not looked into the reference manual, but the answer is most certainly there.