# Looking for cheap daisy-chainable ADC

#### sminded

Joined Nov 22, 2015
22
Does anyone know of a ADC that meets below specs?

* Daisy-chainable
* SPI
* 8 bit
* >= 100 ks/S
* 8 channels
* Single-ended
* Cost less than $5 #### JohnInTX Joined Jun 26, 2012 4,113 Not sure what you mean by 'daisy chained' in the multichannel ADC sense, but if you are looking for cheap ADC's that can have multiple units on a bus check out Microchip's offerings. MCP3008 is 10bits, 8 channels, SPI$2.32 Qty 1 from Mouser or Microchip Direct. These are successive approx. SPI units. uCHIP has other types/resolutions/channels.

Many other manufacturers like Maxim, Analog Devices and TI come to mind as well. I am the most familiar with Microchip for average to good stuff and Analog Devices for their high end stuff. Although Max and TI are good outfits too, I just don't know their products lines as well.

#### Attachments

• 614.2 KB Views: 0
Last edited:

#### sminded

Joined Nov 22, 2015
22
14 pins 8 channels $0.53/5K 16F1503 et al Both have 10bit ADCs (can use 8MSbits) and internal reference. Really nice, the 8 channel could work, I will read up on it... thanks #### joeyd999 Joined Jun 6, 2011 4,401 I like the idea.. are you suggesting that I can make it act as a SPI slave and daisy chain the PICs? And, if you are *really* clever, you'll program each with "boot" code that will allow reprogramming each MCU via the same serial wire. Thread Starter #### sminded Joined Nov 22, 2015 22 And, if you are *really* clever, you'll program each with "boot" code that will allow reprogramming each MCU via the same serial wire. I will definitely do that Thread Starter #### sminded Joined Nov 22, 2015 22 #### JohnInTX Joined Jun 26, 2012 4,113 The PIC16F527 seems to fit the bill perfectly with 8 ADC channels and SPI-support, it also has 2 built-in opamps and 2 analog comparators which could come in handy. http://www.microchip.com/wwwproducts/Devices.aspx?product=PIC16F527 Which programmer will be suitable, will the PICIT3 work? @sminded I would not recommend the '527 or any of the midrange PICs when the Enhanced Midrange is available (16F1xxx). They are much more up to date, have many more resources and don't suffer from r-m-w I/O problems (which could easily become an issue driving SPI wires) and have the sparkling -ME2 debugger available. PICkit3 should work - I'll check the DTS and verify that and give you some links to the debugger. If you are thinking about a bootloader, you'll appreciate the 16F1xxx a lot. I just did a couple of projects with this setup: 16F1825 - Max memory for development, you can downshift later if everything fits. Note that its internal oscillator can run at 32MHz vs 8 for the '527. If you are going to bitbang SPI, you'll appreciate that. PICkit3 - The basic programmer/debugger. I use RealICE but PK3 is certainly serviceable and considerably cheaper. It provides basic debugging using the chip's resources. Using PK3 by itself will consume the ICSP pins for debugging and be limited to the on-chip resources (limited breakpoints etc. See MPLABX Help Files for particulars) AC244043 - Debug header. This recovers the pins used by ICSP but doesn't add much else. Some of these recover the chip's memory used by the on-chip debugger. But for the small price difference get: AC244063 -ME2 Emulation Extension Pack instead. This is close to a full-blown emulator - I use the -ME2 and its great. Check the features list. That's what I would do. Would you use C or assembler? Last edited: Thread Starter #### sminded Joined Nov 22, 2015 22 @sminded I would not recommend the '527 or any of the midrange PICs when the Enhanced Midrange is available (16F1xxx). They are much more up to date, have many more resources and don't suffer from r-m-w I/O problems (which could easily become an issue driving SPI wires) and have the sparkling -ME2 debugger available. Ok, I hear you, and agree 16F1 it is. @smindedI just did a couple of projects with this setup: 16F1825 - Max memory for development, you can downshift later if everything fits. Note that its internal oscillator can run at 32MHz vs 8 for the '527. If you are going to bitbang SPI, you'll appreciate that. Ok, nice idea, they seem to be pin compatible and all. Have I understood correctly that I can use 8 analog pins, and 4 other pins for SPI, and two of those SPI pins can handle interrupts? So RA0--RA2 + RA4 + RC0--RC3 will be my analog pins and I can use RA3 + RA5 with SPI and interrupts and also RC5--RC6 aswell for SPI. I guess the SPI-function in the PIC is only for Master SPI, so I'll be implementing some kind of statemachine thing driven by interrupt on the CS and CLK pins. For example CS (RA3) high will reset the statemachine and CS low will initialize it. And then the CLK (RA5) signal will be on interrupt so I can read and write data on DOUT correctly. Can I have four interrupts, two for falling and rising edge on CS and two for falling/rising edge on CLK? My idea would be to have the first byte send out from the master to the PICS after a CS falling edge to be configuration + command. So with this byte I can tell the PIC to calibrate channel 1 (RA0) or read from channel 1 (first 4 bits could be the command and last 4 could be channel number). I could also send threshold values this way. You asked about the clock speed of the SPI before, it will be fine tuned obviously, but I will aim for something like 2-8 Mhz. If I don't need to send the full analog value through SPI per channel, but only ON/OFF bit then I can keep the Mhz down to 2 Mhz perhaps. The only down side to using the PIC as compared to a real ADC is that with the real ADC I could send the data as the conversion is going on bit by bit, but with the PIC I guess I have to sample and hold the whole board and then go into SPI transfer. No big issue but it decreases the throughput somewhat. - The basic programmer/debugger. I use RealICE but PK3 is certainly serviceable and considerably cheaper. It provides basic debugging using the chip's resources. Using PK3 by itself will consume the ICSP pins for debugging and be limited to the on-chip resources (limited breakpoints etc. See MPLABX Help Files for particulars) AC244043 - Debug header. This recovers the pins used by ICSP but doesn't add much else. Some of these recover the chip's memory used by the on-chip debugger. But for the small price difference get: AC244063 -ME2 Emulation Extension Pack instead. This is close to a full-blown emulator - I use the -ME2 and its great. Check the features list. Ok, great, I will try to make it so that I can program one board 4x4 cells, two PICS, or if possible the whole table (16 boards +) using one programming header on the board, using bootloader and ICSP. @smindedWould you use C or assembler? I will definitely use C, so which compiler would be the best? #### JohnInTX Joined Jun 26, 2012 4,113 Sorry for late reply and style, on a little tablet.. I would start with XC8 and MPLABX from uCHIP. Xc8 does a decent job in free mode - check price for PRO version. You can develop in free mode and try a one time upgrade to PRO that lasts 30? Days. I have roughed out some intermals for you and will post when back in office - I had to convince myself it would work. It will. Grab the datasheet and rough out a pinout starting with the analog chamels (look at ADCconfig stuff for pin availability) then do the SPI link. If this has to plug into an extisting system, hook this up the same then post the sketch and the serial info so we can kick around how to use the interupts etc. to best advantage.Fun! Thread Starter #### sminded Joined Nov 22, 2015 22 Sorry for late reply and style, on a little tablet.. I would start with XC8 and MPLABX from uCHIP. Xc8 does a decent job in free mode - check price for PRO version. You can develop in free mode and try a one time upgrade to PRO that lasts 30? Days. I have roughed out some intermals for you and will post when back in office - I had to convince myself it would work. It will. Grab the datasheet and rough out a pinout starting with the analog chamels (look at ADCconfig stuff for pin availability) then do the SPI link. If this has to plug into an extisting system, hook this up the same then post the sketch and the serial info so we can kick around how to use the interupts etc. to best advantage.Fun! Hi John, thanks for all the help, I have ordered the parts from china, i.e PIC:s and programmer and some soic to DIP adapters. I will update my schematics with the two PIC:s asap. #### JohnInTX Joined Jun 26, 2012 4,113 @sminded I have ordered the parts from china, i.e PIC:s and programmer and some soic to DIP adapters. Hmmm.. I wish I had known that. Hopefully by 'China' you mean from uCHIP direct in China (a lot comes from their ops in Taiwan) but I don't recommend any of the third party stuff nor any purchase of parts from China. Many problems posted here revolve around 3rd party stuff and counterfeit parts from China. If you can bail on that, I would and get them from uCHIP or a franchised distributor. Thread Starter #### sminded Joined Nov 22, 2015 22 I understand the general problem with China parts, however, I regularly buy things from China, and it has always worked so far without any problems. When I bye from US I always get slammed with VAT and import fees from the swedish agencys so I end up paying double price at least as compared to China. I only bought 6 pieces for a few$, and there is a good chance it can be original parts (as stated in the ad from the seller).
I checked out the uchip store, but there you need to bye at least a tube.

EDIT: I cancelled the China order, and got the parts from Digikey UK store

Last edited:

#### sminded

Joined Nov 22, 2015
22
Ok, here is the schematic part with touch sensors and PIC MCU:s acting as SPI-enabled daisy-chained ADC:s.
Imagine many 4x4 boards being daisy-chained with angled male/female IDC-headers connecting the boards.
The board will have incoming headers on left and top side and outgoing headers on right and bottom side.
With jumpers it will be possible to decide if the inputs will come from top or left side.
Using this way you can build up a bigger rectangular board using for example 16 4x4 boards, where all the data signals will be daisy chained, so the initial signals from the controller (Teensy 3.1) will be connected using a flat cable to the first board and ripple through to the last board, and from the last board, the output header/signals will be connected back to the controller board using another flat cable.
All boards, including the controller board will be individually powered from a single 10A 5V DC adapter using a 2-pin screw terminal on each board.

Explanation of signals:
IR_EN: enables the four 800mA transistors which powers the IR leds. Will be set at the start of a sample and reset after the ADC:s have done the sample and hold.
IR1--IR16: This is the output from the phototransistor 0-5V, proportional to the touch distance and will be connected to the PIC:s
IR_CKI: SPI clock line for the PICs
IR_LD: Resets all the PICs and makes them ready for a new command
IR_SDI: This is the serial data in for this board, can come from either the controller or a previous board
IR_SDO> This is the serial data out, can be connected to the next board, or if this is the last board in the chain, the teensy controller

The good thing with this solution is that I can let the PICs do the ADC stuff and send out one bit per channel ON/OFF. The pixel/cell will be regarded as ON when the voltage on the corresponding channel reaches the treshold value for this particular cell.
The treshold can be individually calibrated from the Teensy by sending a calibration command with a channel number to a specific PIC in the chain, and just a NOOP command to the rest of the PICs. The user will touch the specific cell to be calibrated and that value will be used.
Perhaps two values will be stored per cell at each calibration, the untouched value and the touched value. Then (if needed) continously or at startup the controller can order all the PIC:s to register the idle value (not touched) of each channel,

Last edited:

#### JohnInTX

Joined Jun 26, 2012
4,113
Sorry again for the delay - moderator duties are consuming a lot of time these days..

Anyway, thanks for the skiz and description. The way you have the serial is more like a daisy chained shift registers than SPI (but you did say you were replacing 74165's) so yeah! That should do the trick. You've done a good job of assigning pins (clock and load on interrupt-on-change, nice) and you'll be bit banging the serial link. My original sketch daisy chained the MSSP/SPI to avoid big banging but I see that you've matched the new circuit to your old one..

I assumed that you were going to send 8*8bit ADC readings and had a nice little data stack cooked up but having the ADC value simply compared to a threshold makes it easier yet. Very cool.

I don't know if you've figured out how to organize the code but here's how I probably would approach it:
Run the internal oscillator as fast as it will go.
Run the ADC by converting each channel in a continuous round robin sequence. When one conversion is done, read the data and change the ADC channel and start the conversion on that channel. Next, process the data (average a few values if you need to then compare to the reference value. Post the result bit in a holding register (ADC_RESULTS). Just keep doing this as often as you can. The holding register will always contain the latest result of the conversion process.
When the LATCH signal happens, the interrupt immediately copies ADC_RESULTS to the shift register (that way new ADC results can be posted without clobbering the shift process).
As you shift each bit out, shift one in to a separate receive register, keeping a bit count. When the count is 8, transfer the receive register to the transmit register and continue. The 8 bit values from each PIC will be propagated along the line as long as the clock is going.
Restart the process for each latch pulse - copy the updated ADC_RESULTS to the shift register and shift as many bytes as you get clocks.
This approach works for any number of PICs on the chain - just hit the latch pulse and send 8x clocks. The PICs don't know the difference.

As the new ADC_RESULT data is shifted out, you shift in any command data you need byte by byte. The command bytes wind up aligned in the receive registers and are examined after the last data shift. You'll need a way to know when that is and what the commands are. That may in fact require knowing how many PICs are on the chain (after all bytes shifted out, what's in the receive register is a command). Alternatively, you might be able to come up with a method of using the latch and clock signals to indicate whether a command follows the data shift i.e. latch with the clock = 1: no command follows the data shift operation; latch with the clock=0, command follows.. something like that.

I would keep the ADC scheduler as a non-interrupt routine so that you can respond to the clock and keep your speed up. Just run the ADC as the main task whose job it is to post bits into the ADC_RESULTS register. If getting a shift clock happens while you are changing channels, it doesn't matter because you already loaded the shift register with the ADC_RESULTS.
See if you can do the latch/shift without a state machine - again for speed.
The 16F1xxx have very quick interrupt response because all of the important registers are saved automatically in hardware - faster even than the 18F's and WAY better than that lame '527.
I can see it working already.
Nice job!

#### sminded

Joined Nov 22, 2015
22
Thanks again for the input.

The way you have the serial is more like a daisy chained shift registers than SPI (but you did say you were replacing 74165's) .....//...... My original sketch daisy chained the MSSP/SPI to avoid big banging but I see that you've matched the new circuit to your old one..
Yea, true, I have just replaced the shift registers with these PICs, but how can I avoid bit banging? I have no problem adapting the schematics if I can find a better solution.

I assumed that you were going to send 8*8bit ADC readings and had a nice little data stack cooked up but having the ADC value simply compared to a threshold makes it easier yet. Very cool.
I was thinking that I probably don't need to know the full value range 0-4096 or whatever I will get from the ADC:s in the Teensy controller, as I'm not planning to have any application that will behave upon touch distance. The games/features I forsee will only need to know if a cell/pixel have been touched or not.
And obviously the less data I need to shift in each sample, the better

I don't know if you've figured out how to organize the code but here's how I probably would approach it:
Run the internal oscillator as fast as it will go.
Run the ADC by converting each channel in a continuous round robin sequence. When one conversion is done, read the data and change the ADC channel and start the conversion on that channel. Next, process the data (average a few values if you need to then compare to the reference value. Post the result bit in a holding register (ADC_RESULTS). Just keep doing this as often as you can. The holding register will always contain the latest result of the conversion process.
When the LATCH signal happens, the interrupt immediately copies ADC_RESULTS to the shift register (that way new ADC results can be posted without clobbering the shift process).
As you shift each bit out, shift one in to a separate receive register, keeping a bit count. When the count is 8, transfer the receive register to the transmit register and continue. The 8 bit values from each PIC will be propagated along the line as long as the clock is going.
Restart the process for each latch pulse - copy the updated ADC_RESULTS to the shift register and shift as many bytes as you get clocks.
This approach works for any number of PICs on the chain - just hit the latch pulse and send 8x clocks. The PICs don't know the difference.

As the new ADC_RESULT data is shifted out, you shift in any command data you need byte by byte. The command bytes wind up aligned in the receive registers and are examined after the last data shift. You'll need a way to know when that is and what the commands are. That may in fact require knowing how many PICs are on the chain (after all bytes shifted out, what's in the receive register is a command). Alternatively, you might be able to come up with a method of using the latch and clock signals to indicate whether a command follows the data shift i.e. latch with the clock = 1: no command follows the data shift operation; latch with the clock=0, command follows.. something like that.

I would keep the ADC scheduler as a non-interrupt routine so that you can respond to the clock and keep your speed up. Just run the ADC as the main task whose job it is to post bits into the ADC_RESULTS register. If getting a shift clock happens while you are changing channels, it doesn't matter because you already loaded the shift register with the ADC_RESULTS.
See if you can do the latch/shift without a state machine - again for speed.
The 16F1xxx have very quick interrupt response because all of the important registers are saved automatically in hardware - faster even than the 18F's and WAY better than that lame '527.
I can see it working already.
Nice job!
Wow.. thanks for the insights.. I will again look at this when its time for the programming of the PIC:s

#### JohnInTX

Joined Jun 26, 2012
4,113
I have just replaced the shift registers with these PICs, but how can I avoid bit banging?
At this point, I think you'd have to go to the '1829. It has more pins and more importantly, using the hardware SPI doesn't eat up the analog channels that you need. Tables 1 and 2 in the datasheet tell the tale. For the 1825, SDI shares RC1 with AN5 and its not relocatable. That means no hardware SPI or no 8 channels of ADC leaving you with bit banging. I thought about it and don't see why you could not daisy chain the hardware SPI if you had it. Probably the thing to do at this point is take the hardware you have and get the data link working. If you can use the 1829 in your final design, I'd try the data link with the hardware SPI with dummy ADC data for now. If it works OK, order some 1829s and start the ADC code. If you must use the 1825, then you'll be bit banging and just have to keep the code tight as possible. This would probably be a good time as well to see how much data rate you actually need vs. what you originally indicated.

I was thinking that I probably don't need to know the full value range 0-4096 or whatever I will get from the ADC:s in the Teensy controller, as I'm not planning to have any application that will behave upon touch distance. The games/features I forsee will only need to know if a cell/pixel have been touched or not.
And obviously the less data I need to shift in each sample, the better
Agreed. The key is to design the basic code structure so that if you want to get analog values someday, you don't have to start from scratch.

thanks for the insights..
You're welcome. Its fun to think about stuff like this.