Team 1


Multi Channel Light Sensing ADC
Katarzyna Terek
Robert David Brinzer


                This project is a Multi Channel Light Sensing ADC system where an oscilloscope software is used to interact with some light sensing hardware to show off the capabilities of the ADC. The hardware consists of two light sensor circuits using light dependent resistors as sensors, each connected to a separate channel. The oscilloscope software can sample both channels and produce a graph each at a variety of settings. The emphasis of this project was on the oscilloscope software and interaction with the ADC rather than on complicated hardware capable of sampling unusual precepts.


                The hardware consists of two light sensing units, each connected to a channel of the AD7705 board. Each sensor is composed of NORP12 Light Dependent Resistor in series with 1kOhm Resistor. The circuit is powered with a supply voltage of 3.3V provided by Vout pin4 on each channel. The Light Dependent resistor varies its resistance accordingly to the level of light it is exposed to. NOR-P12 reaches its highest resistance of 1MOhm in complete darkness and decreases its resistance to negligible values while exposed to direct sunlight. It's typical operational resistance is 800kOhm for 100ftc, which makes it most suitable for indoor Tungsten light measurements.

Circuit Diagram for Light Sensors

                The input voltage of the AD7705 was measured across the 1kOhm resistor and it used nearly the full available range between 0.003V and 3.3V. However in the laboratory environment typical values varied between 1.8V and 3.3V.

                This configuration for light sensing hardware is commonly used and very cheap to make. The only disadvantage is that it might not be capable of using the full ADC quantisation range for meaningful measurements which is only a problem if very precise measurements are required. Such precision was not the intent of this project.


                A large emphasis was placed on software and signal processing to show off the capabilities of a raspberry pi. A number of features were added including adjustable sample rate, multi-channel sampling and frequency analysis. There were also a number of improvements applied to the base software such as fixing specification violations and improving performance.

Base Improvements

                In the base code given there was a specification violation when setting up the general purpose clock 0 which could potentially cause it to malfunction if any other software manipulated it. In order to configure the general purpose clock the clock must first be stopped or there is a chance of it producing unpredictable results or even freezing. The base code assumed the general purpose clock was set only by itself, so although there was a check if the clock had stopped before making changes, changes could still be made if the general purpose clock was set up differently than by the base code. The code wrote an arbitrary value to one of the general purpose clock registers before it was stopped as part of the stopping process which violates the specification as it could change registers that must only be changed when the clock is stopped. A fix was applied by first reading the register and using bit manipulation so that only the required bit fields of the register were changed to initiate the stopping process while the other bits that cannot be changed while the clock is active were left unmodified. This fault went unobserved because the general purpose clock 0 is only used for running the ADC board in the context of this course.

                The ADC sampling procedure in the base software was ordered incorrectly. The fault originates in a mistake in the data sheet (AD7705/AD7706: 3V/5V, 1 mW, 2-/3-Channel, 16-Bit, Sigma-Delta ADC Data Sheet (Rev C, 05/2006)) as the document only gave the case of reading samples continuously from a single channel despite the ADC supporting multiple channels. A follow-up document (How do I use the serial interface on the AD7705/06/07 ADC?) explained the correct sampling procedure and how to apply it for multiple channels. In order to read a sample a write to the communication register requesting a read from the data register must first be issued and then the system must wait on the DRDY (Data Ready) pin falling low signalling a ready sample before reading in the sampled data. The reason for this is that the read from the data register sets up the ADC to generate a sample which is especially important in multiple channel operation as it specifies which channel the sample will come from. The base software followed the method given in the technical specification document which was to wait for the DRDY pin to fall low and then write to the communication register immediately followed by reading in the sampled data. This works fine for sampling continuously from the same channel as the ADC is working in continuous sampling mode so sample setup is not required but does not allow for multiple channel sampling. A fix was applied by moving the write to the communication register to before waiting on the DRDY pin and then reading afterwards.

                The interface provided for the ADCReader object was inefficient if more than 1 element was buffered. Only one sample could be pulled from the buffer at a time, even if it held multiple samples resulting in excessive function calls and memory move operations as each sample was added to the plot arrays separately. A new method was created that would transfer the entire content of the sample buffer in a single call to the plot array with using only a single memory move. Especially at high sample rates where more than 1 sample is present in the buffer this would result in a large optimization in execution efficiency.

ADC Sampling Improvements

                It was observed that the ADC board was prone to entering an unresponsive state during testing, possibly as a result of lose contacts resulting in temporary power loss or communication errors. This required that the entire program be restarted in order to restart the ADC board with the base software which resulted in poor usability. As a timeout on the DRDY pin could detect the board entering such a state an automatic recovery system was added. This involves keeping track of all the values that should be in the key registers of the ADC and then restoring the device back to the desired state when it becomes unresponsive. By building the initialization routines for both the ADC (reset to known state) and the individual channels (instead of sampling from the channel) into the sampling loop it was possible to create a fully automatic recovery system. When the device was detected as unresponsive all that had to be done was declare the ADC and channels as uninitialized and they would be re-initialized in subsequent sample loops. The effectiveness of this recovery process was such that the entire ADC board could be removed and plugged in while the software was running and it would resume sampling.

                Being able to change the sample rate and gain of channels while the system was running was considered a useful function. This was not possible with the base software as it only supported channel initialization at the start of the program. Due to the modifications for automatic recovery it was easy to add this feature. All that was necessary to change sample rate or gain was that the recorded register state for the channel be updated to reflect the desired change and the channel be marked as uninitialized. The automatic recovery process would then update the registers and re-calibrate the channel next time it goes to sample it.

                Multiple channel support was decided to be one of the main features of the software. Although the ADC does not support sampling multiple channels simultaneously it does allow channels to be multiplexed at the cost of a 3 sample delay (digital buffer needs to be refilled) every time channels are swapped over. By fixing the specification violation with sampling in the base software it was easy to implement multiple channel support. Each channel was given a dedicated buffer and state so they could operate independently of each other. The sample loop then used a round robin style scheduler for the channels to provide fair sampling. A channel number parameter was added to interface methods to allow each channel to be controlled separately. This allowed multiple channels to be configured and read from easily. Multiplexing multiple channels comes at a huge cost to sample rate since the sample period of any channel becomes three times the sum of the sample period of all channels.

Using Discrete Fourier Transforms

                Discrete Fourier transforms are very useful when analysing signals as they separate the phase and magnitude of frequencies contained in a sampled signal in an easy to access form. By using such a transform a frequency analyser could be made. Programming up an efficient and correct system for performing discrete Fourier transforms from scratch would take considerable time however there are ready to use open source packages available that provide the functionality.

                FFTW3 (Fastest Fourier Transform in the West) was chosen for its open source nature and easy to install and use interface. Its GNU licence made it perfect for use in this project. It also fully supports Linux and there was no problem installing it on a Raspberry Pi. Unlike some pure FFT implementations it also supports arbitrary sized input while retaining high efficiency. Unfortunately the Raspberry Pi does not support the advanced profiling feature of the package due to the lack of hardware timers which might limit maximum performance however the estimate mode was efficient enough for the purposes of this project.

                A use of discrete Fourier transforms is for generating interpolation data when changing sample rate. In order to keep output plots the same length in time (seconds), the number of samples used by the plot must be changed to reflect the new sample rate. If samples were translated to this new sample space directly there would be distortions and discontinuities that were not present at the lower sample rate. By transforming the sample space into a frequency space and adjusting the length of this space (Nyquist frequency) it is possible to generate a more natural conversion between sample rates. This only uses a half transform (no mirror frequencies) as the input is purely real, a case especially supported by FFTW3. After resizing in frequency space it is converted back into sample space to produce a graph that retains features that were sampled at the previous sample rate in a continuous and meaningful way.

                Another use of discrete Fourier transforms is for converting sample space into frequency space when plotting to show the user the frequency spectrum of the signal. This was done by having separate data arrays for the frequency spectrum which were filled with the absolute value of each complex frequency produced from the sampled data arrays. Even with the data not being aligned to powers of two or caching intermediate buffers it still worked amply fast for the purposes of the project.

Software Features

                The program features two graphs, three knobs and two check boxes. The graphs will show either sampled value against time or amplitude against frequency depending on mode of operation. The top graph represents channel 1 and the bottom channel 2. The duration or frequency range of the plots can be altered using the dials. Due to the range of inputs an automatic Y scale was used.

                The filter selection is controlled by the first knob. The filter selection is responsible for controlling the output sample rate of the ADC. The plot is automatically adjusted to reflect this change in sample rate using discrete Fourier transforms to produce interpolated data. Changes to the filter selection cause the ADC to become unresponsive for a few samples while the channels are recalibrated.

                The second knob controls the channel gain. This is much like the knob that was in the base software however instead of applying the gain at the software level it will change the gain value in the setup register. This has several advantages with the output signal quality as the combination of gain and filter selection control signal to noise ratio and maximum bandwidth as explained in the technical specification document. Changes to gain require the channels to recalibrate so cause the ADC to become unresponsive for a few samples.

                The duration (in seconds) of the plots in sample space is controlled by the last knob (bottom). The range can be adjusted between 1 second or 10 seconds. The oldest samples are affected by this with 0.0 padding or sample truncation being used. In frequency space this has the effect on the lowest detectable non-DC frequency.

                A check box was added to toggle between sample and frequency space. The frequency range in frequency space depends on the sample rate. The time taken for the frequency plots to settle when changing parameters or signals depends on the sample length as the sample buffer must be completely filled with your signal for the output spectrum to be correct. Unless sub-hertz frequencies are specifically required it is recommended to set the sample length to only one or two seconds when using this mode.

                Due to the sample rate penalty when sampling from two or more channels, a check box was added to turn off channel 2. This allows channel 1 to be sampled at a considerably higher frequency allowing it to handle higher frequency signals. The sample space size and frequency space Nyquist frequency automatically update to reflect this increase in sample rate. Unless you specifically require multiple channels it is recommended to use channel 1 in this mode.

                For debugging purposes every time a knob or check box is changed or the ADC becomes unresponsive it is printed to standard error. This is also useful for knowing what setting changes registered as the knobs do not align to whole units due to a bug in QwT so do exhibit some freedom of movement without registering a change. An error message is also sent when the ADC intermediate buffer overflows to warn the user that measurements might be compromised. A QwT bug prevented plots for both channels being on the same graph as it would not display more than one plot on a single graph despite the interface claiming it supported it.


                The software was capable of picking up both a 1Hz and 10Hz signals from a signal generator. These signals were correctly plotted in the frequency space showing that the sample rates matched those that were expected. Both channels were also shown to act independently of each other with exception of minor cross coupling due to them sharing a common ground and voltage supply.

                Performance was tested in the worst case. This is when single channel sampling is enabled, filter selection is at 3 (500 Hz sampling rate) and sample length is set to 10 seconds (5,000 samples). It was observed to suffer from buffer overflows even with 64 sample buffers. Making the buffers larger (128, 256 etc) reduce the overflows at the cost of more memory used. Interestingly it was able to function in frequency space mode with only the occasional buffer overflow (buffer size 64 samples, occurrence seems to be scheduling related) despite the extra overhead of having to perform a discrete Fourier transform on 5,000 samples and plotting 2,500 results. From this it can be concluded that the major performance constraint is plotting the data and not performing discrete Fourier transforms or sampling the data since the reduction from 5,000 points to 2,500 points in the plot saved more time than the discrete Fourier transform took to perform.

                When operating in dual channel mode it was noted that channel 2 seems to have a larger DC offset compared to channel 1. An ADC board was tested from another group which produced exactly the same results. It was concluded that this must be an inherit design flaw with the ADC board and not a software defect. It was also noted that increasing filter selection increased DC offset. For this reason it is recommended that the ADC board be used for low frequency signals at the lowest filter selection sample rate.

Future Work

                Although the ADC is advertised as supporting two channels, it actually supports four (two main, a signal to noise tester and a pseudo channel). Instead of hard coding in two plots for supporting the two main channels, the plots could be promoted to separate elements handled by methods in parallel. This would allow for all four channels to any single channel to be sampled as required.

                The channel scheduling algorithm when sampling from multiple channels is currently round robin so gives each channel an equal sample rate. Using an unfair algorithm and some data interpolation it might be possible to bias channels and get them to produce samples at different rates.

                DC and 50Hz (60Hz in some countries) noise is undesirable in signals as it makes analysing them more difficult. A check box for IIR filters to remove such noise cold be added. A really sophisticated system allowing customization of IIR filters could be made for removal of other frequencies.

                As the evaluation showed, generating the plots takes considerable resources. The Raspberry Pi specification mentions a GPU that is capable of graphics similar to or better than game consoles like the Sony Playstation 2 and original Xbox. By offloading plot generation to the GPU using OpenGL it should be possible to dramatically improve performance. The generated plots might also be a higher quality as techniques like anti-aliasing could be used to produce smoother lines or the graph could be animated to produce smooth movement when sampling below 60 Hz (the standard display refresh rate).

                Often data capture is required so that it can be analysed in greater detail using post processing techniques that are too expensive to run in real time or for logging purposes. This is not as straight forward as it might seem as I/O could potentially block for extended periods so cannot be used in the same thread as the plots are generated to avoid responsiveness problems. Adding functionality to allow data capture in a separate thread might be useful.

                Consistent timing is crucial for discrete sampled systems. Without each sample being precisely timed processes such as filtering do not produce meaningful results. Although timing is reasonably accurate as the ADC produces a constant stream of samples there are times where sampling is interrupted. When the ADC becomes unresponsive or during channel recalibration (such as after a change) it might be good to produce interpolated results to keep the sample rate consistent during this period.

                The ADC used is just one of many commercial ADCs. It also uses a non-standard interface making it incompatible with most ADCs. The comedi project designed a standard interface for Linux to interact with ADCs. Since these are kernel level components they are a lot more efficient than the approach adopted by this project. Not only could this particular ADC configuration be given a comedi driver but the program could be changed to work with any comedi compatible ADC making it a lot more portable.

                A Raspberry Pi is often not the easiest device to interact with. It might not have a display or it could have no input devices. However it can still be connected to an Ethernet network which supports reasonable transmission rates. Since the ADC used has a low sample speed (max 500 Hz it is more than viable to pipe samples in real time through the Ethernet network using a TCP channel to another more convenient and more powerful system. This system could then perform all the plotting and analysis required. Like with any form of I/O, network communication could block for extended periods of times so it would need to be run on a separate thread to avoid making the system unresponsive. Some form of round trip time detection might be required so that the latency of the samples can be factored in for critical real time usage.

                The Digital Signal Processing M course run last semester showed how a FIR filter could be used in signal detection for an ECG. Seeing how the Raspberry Pi has no problems performing dozens of discrete Fourier transforms on thousands of samples a second it should have no problem applying a FIR filter in real time. By combining this with some post processing it should be possible to turn any complex signal (like an ECG) into a pulse train given the right FIR template. The time between these pulses could be measured to give a frequency of a signal (like the heart rate). A framework to support this functionality could be made that allows customization of the FIR template and the ability to produce various measurements.

                The plots and knobs lack labels making it confusing for anyone to use who has not read the report. A UI should be clear and easy to use for most people. Improvements to the usability of the UI could be made so that people are more easily able to use the software.

                Currently automatic scales are used for the sample space and frequency space plots. These adequate for some signals but others would be better shown on a logarithmic scale. Adding the ability to choose the type of scale and range of scale would be very useful.


                The produced software shows off a variety of data acquisition and processing techniques in real time. Aimed for more general use than a specific hardware configuration it demonstrates many of the features of the ADC. The more complex ADC features are shown such as the ability to sample from two channels at once and to change channel configurations in real time. The result is a type of general purpose oscilloscope which can  be used to test hardware for the ADC board and to find the optimum ADC settings to interact with that hardware.

The source code for the project can be found at: