Page 1 of 1

Comms for two SPI devices (PCA9685 MCP3008), 'live' tkinter

Posted: Wed Nov 16, 2016 4:42 pm
by dpmanthei
Hello all,

I have an RPi 3 and am pretty new to Python, Pi's, and Arduinos...I'll get right to it:

I have an Adafruit PCA9685 (16 channel, 12-bit PWM output device) and an MCP3008 (8 channel, 10-bit, ADC input). At the moment I have three Python 3 scripts that I wrote to test each aspect of my program: analog input reading, CSV file reading to generate PWM lookup tables, and PWM outputs. The analog inputs and PWM outputs share some pins and some communication code but since I've tested each setup separately I'm not sure how to proceed.

How do I:
a) Wire up two SPI devices so I can use both "simultaneously" (not really, but at least without requiring changes to wiring each time)?
b) Use Python to communicate with each device every 100 milliseconds while the program is running(for example, read the value from a potentiometer, do some math, and write out a value to the PWM board)?

bonus) I'd like a Tkinter window to show me the 'real-time' potentiometer value and current PWM value. Every attempt I've made at this ends 1 of 3 ways:
- tkinter window redraws itself infinitely and the CPU goes to 100%
- tkinter window shows the value that was present when it was drawn and doens't update
- Or the window draws fine and is "live", but it halts the rest of my Python script and my 100 millisecond math calculations stop happening

Any help would be greatly appreciated! Thanks!
Dylan

Also, yes I know I didn't post any code but that's because I'm currently using blatant copy-paste code for communication on both devices, and I don't think my CSV file handling or math is holding me up. I'm just very new to SPI, and can't find many examples of using two SPI devices at once. I'm also new to tkinter and haven't found any other GUI that's easier for me or clearly solves my problem.

Re: Comms for two SPI devices (PCA9685 MCP3008), 'live' tkin

Posted: Wed Nov 16, 2016 4:59 pm
by joan
There is nothing special about the SPI. Just use different slave selects for the various chips.

Here is an example driving two SPI DACs and reading the resulting voltages with a SPI ADC.

It's a pigpio example but it should map to whatever library you are using without too much effort.

Code: Select all

#!/usr/bin/env python

import time
import pigpio

AUX_SPI=256

pi = pigpio.pi()

if not pi.connected:
   exit(0)

dac1 = pi.spi_open(0, 40000, AUX_SPI) # MCP4131
dac2 = pi.spi_open(1, 40000, AUX_SPI) # MCP4251
adc  = pi.spi_open(2, 40000, AUX_SPI) # MCP3008

start = time.time()

count = 0

for l in range(100):
   for v in range(256):

      count += 5

      pi.spi_xfer(dac1, [0x00, v&127])
      pi.spi_xfer(dac2, [0x00, v])
      pi.spi_xfer(dac2, [0x10, 255-v])

      c1, d1 = pi.spi_xfer(adc, [1, 0x80, 0]) # channel 0
      c2, d2 = pi.spi_xfer(adc, [1, 0x90, 0]) # channel 1

      v1 = ((d1[1]<<8) | d1[2]) & 0x3FF
      v2 = ((d2[1]<<8) | d2[2]) & 0x3FF

      print (v1, v2)

      time.sleep(0.05)

stop = time.time()

diff = stop - start

print("{} SPI xfers in {:.2f} seconds ({}/s)".format(count, diff, int(count/diff)))

pi.spi_close(dac1)
pi.spi_close(dac2)
pi.spi_close(adc)
pi.stop()

Re: Comms for two SPI devices (PCA9685 MCP3008), 'live' tkin

Posted: Wed Nov 16, 2016 5:36 pm
by dpmanthei
Thank you! I can't get back to it until later in the week, but at a glance that looks very helpful!

Re: Comms for two SPI devices (PCA9685 MCP3008), 'live' tkin

Posted: Wed Nov 16, 2016 9:16 pm
by dpmanthei
So just to be clear, I can safely connect multiple devices to the Raspberry Pi's MOSI, MISO, CLK, and CE pins?

Re: Comms for two SPI devices (PCA9685 MCP3008), 'live' tkin

Posted: Wed Nov 16, 2016 9:28 pm
by joan
dpmanthei wrote:So just to be clear, I can safely connect multiple devices to the Raspberry Pi's MOSI, MISO, CLK, and CE pins?
Yes.

SPI is a bus system. All the chips are connected to the MOSI, MISO, and SCLK lines. Each chip has its own slave select line (called CE, chip enable, on the Pi). The Pi signals which device it wants to talk to by asserting the device's slave select signal.