[GPIO I/O] Example ADC MCP3208 & SPI


#21

My not the best to answer this BUT I think the max is 8 per 3208 , so that gives 128
Load I'd assume with increase linearly per 3208, as each is streated separately

Note: if not tried this, as I don't have any 3208s, this is based on the code and circuits I've seen here


#22

Yes, 8 MCP3208 devices is the maximum that can be addressed.
The main concern is not CPU load, but the update rate. If a single conversion is scheduled every millisecond, at 128 channels that gets you 8 samples per second. Scheduling conversions at 3kHz (control rate), gets you 24 samples per second. Scheduling faster gets tricky, as it will start to interfere with control rate.
The MCP3208 protocol requires to setup a data transaction for each conversion, it would be much nicer if it could read out its 8 channels in a single data transaction. Perhaps some other converter exists that can do this, but don't know a widely available cheap part number that can do this, but I have not searched extensively.


The Xylobox Wavetable Synthesizer (hardware + patches)
Which potentiometers should I buy?
#23

can I just understand this correctly?
so basically, because they share the same spi port, you can only address one 3208 (and one pin of it) on each cycle, and you have to issue the send and receive on different cycles.

also quick wiring question...
on the above diagram the first 3208 has a cap between pins 2 and 3, is this also required for the second (and subsequent) 3208s?

(I'll note for my usage I'm not planning on that many pots ... but thought I might have some analogue inputs that I want a high sample rates, e.g. ribbon but a fews pots that could be lower if necessary)


#24

After setup, for every transaction, you need these calls:

spiSelect(&SPID1); // START SPI
spiSend(&SPID1,3,txbuf); // send SPI data txbuf[]
spiReceive(&SPID1,3,rxbuf); // receive SPI data from MCP3208
spiUnselect(&SPID1);

I think spiSend() and spiReceive() can be merged in one call of spiExchange. But the chip select input must see a high pulse between transactions. The data sheet shows DIN is "don't care" after the first transaction.

The spiSend(), spiReceive() and spiExchange() function calls setup the transaction (using DMA), suspends the current thread so other threads can do useful work in the meantime, and when the transaction is finished, it resumes the original thread.

There are several option to schedule the transactions:

  • Making a thread with a tight loop with spiX..() is a bit too aggressive, perhaps with the spi bitrate set to the slowest possible. I would not recommend.
  • Creating a thread with chThdSleepMilliseconds() in the loop is fine, but has a 1 millisecond timing granularity (as configured in firmware: chconfig.h). This is what I'd recommend
  • Calling spiX..() at k-rate (from the dsp thread), I would not recommend as that makes the time during the transaction unavailable for audio processing... It is possible to do SPI without the spiX..() calls, by manipulating the memory-mapped IO registers defined in stm32fxxx.h, within k-rate and poll for the result at the next k-rate interval. But such an implementation is very unportable.

The capacitor between pin 2 and 3, I think you're referring to pin 14 and 15. Pin numbering start at a "mark", often a dot, then go around counter-clock-wise. As a starting point I'd suggest a 100nF capacitor across every GND/VDD pair of pins of every chip, close to each pin pair. In this case, pin 15 is the voltage reference input, I'd give it a 100nF capacitor too on each chip. The mcp3208 datasheet has a chapter on Layout Considerations, they recommend a 1uF capacitor "placed as close as possible to the device pin". Such layout considerations are not supercritical to get it to work, but certainly useful to reach best possible performance. But I would not be surprised if it also works fine without any respect for the layout recommendations.


#25

What potentiometer values I should use with MCP3208? The same as for axoloti analog inputs?
Can I use 74HC4051 or 74HC4067 multiplexer, wil the script code wil be the same?


#26

Can I connect MOSI, MISO, SCK, NSS/CS of MCP3208 to pins PB6-PB9?
Then it will be possible to use all 15 analog inputs of axoloti and 8 additional from MCP3208, so in total 23 ins?


#27

Sorry, it is not possible to move the pin assignments for MOSI, MISO and SCK.

I have not studied those, I guess it will be the same or very similar.

yeah, use the same.


Input resistance/impedance of GPIOs in AnalogIn Mode?
#28

Thank you Johannes.

I have one more question:

In this example, the MCP3208 CS pin is connected to axoloti B0(GPIOB,0) pin.

If you use more then one spi device, it's importent to disable every other spi device by switching their cs pin.
*/

uint8_t *txbuf;
uint8_t *rxbuf;
const SPIConfig spicfg_a = {NULL, GPIOA, 4, 3<<3 | SPI_CR1_LSBFIRST }; //MCP3208 pin PA4
const SPIConfig spicfg_b = {NULL, GPIOA, 3, 3<<3 | SPI_CR1_LSBFIRST }; //MCP3208 pin PA3

Does this mean that second mcp3208 CS pin connected to PA3, but not to B0(GPIOB,0) pin? Or there is somewhere mismatch in axoloti labels?


#30

Somehow I find the answer


#31

Does that mean 8 mpc3208's can be connected directly to axoloti? Or do they need to be chained? I am building an enclosure with 48 pots, 6 tact buttons, 6 leds, a 4 digit LCD display and a rotary encoder and I am trying to find out the best strategy to approach this.


#32

Hello !
I've wired my MCP3008 and seem to get an accurate reading, but like matthewcleplak a few post earlier, I can't get a value more than 3.97 and cannot figure out why..
I'm not that good with coding so i'm having troubles figuring out if it is in the script or due to the 10-bit depth of the MCP3008, or if it's a VREF problem...
I've used a 100nf cap beetwen pin 2 and 3 and a 100uf beetween the main Vdda and GND, it seem to work as there is almost no jitter. I'm using 100k pot, that works fine when connected into the Axo's DAC.
Any ideas ? I couldn't find a simple answer in that post, even though I think matthewcleplak figured it out...

EDIT : SOMEHOW, I FOUND THE ANSWER WHILE TRYING TO FIGURE OUT THE CODE; YOU NEED TO CHANGE THIS LINE, that is in the first example script :
int z = (rxbuf[1] << 8| rxbuf[0]) << 16;
to
int z = (rxbuf[1] << 8| rxbuf[0]) << 20;

The value now goes to 63.50... that'll do it for me, although I did It kinda randomly, if somebody could explain a little bit how this work and get that last 0.50...

Hope this will be useful to someone :slight_smile:


#33

Hi all,

I cascaded 3 MCP3008's and added some series resistors (47Ohm) in the CLK/MISO and MOSI lines to get the reading stable. This seems to work, but now the readings are fine till a potmeter passes half the range. Where am I missing a point...

BTW, when lowering the potmeter below the half-point, readings get stable again...

Patch used: mcp3208 tripple channel example.axp (13.2 KB)


SPI Problems with MCP3008 and MCP23s17