1

I'm building a small device that will read in numerical data from a Mitutoyo indicator, record and chart this data on the screen. These indicators use an "SPC" protocol that has a single input "request" pin that once set low will cause the device to start sending a clock and data signals for a total of 52 bits. Explanation of the data stream can be found here

I've got a simple python script written that "waits" for the next pulse using a while loop waiting for the clock pin to go low before reading the next bit; similar to this arduino project I found. this sort-of works, but on occasion it seems as those it either misses a bit or accidentally reads a bit twice and then it gets out of sync and the whole thing stops working.

There must be a better way to do this. Is there a way to instruct the Pi that "this pin is a clock, expect 52 bits on the data line" and have it read in more efficiently. I need to read in pulses from a cycle counter and there are other functions that this Pi will need to perform in concert with taking the occasional readings from the indicator, I fear that once it starts doing other things at the same time the bad reads/sync issues will get even worse.

2

My pigpio library probably offers the most reliable way of reading such data.

Here is an example to monitor SPI traffic in Python.

http://abyz.me.uk/rpi/pigpio/examples.html#Python_SPI_mon_py

If you look at the callback function you could modify it for your SPC data stream.

#!/usr/bin/env python

# SPC.py
# 2016-12-04
# Public Domain

import time
import pigpio

REQ=5
CLK=6
DATA=7

# The callback implements the Mitutoyo SPC protocol
# 13 4-bit nibbles, least significant bit first.

def cbf(gpio, level, tick):
   global in_data, bit, nibble, nibbles, data_level
   if gpio == REQ:
      nibble = 0
      bit = 0
      nibbles = [0]*13
      in_data = True
   elif gpio == DATA:
      data_level = level
   else: # CLK
      if in_data:
         nibbles[nibble] |= (data_level << bit)
         bit += 1
         if bit > 3:
            bit = 0
            nibble += 1
            if nibble > 12:
               print(nibbles)
               in_data = False

pi = pigpio.pi()
if not pi.connected:
   exit()

in_data = False
bit = 0
nibble = 0
nibbles = [0]*13
data_level = pi.read(DATA)

cb1 = pi.callback(REQ, pigpio.FALLING_EDGE, cbf)
cb2 = pi.callback(CLK, pigpio.FALLING_EDGE, cbf)
cb3 = pi.callback(DATA, pigpio.EITHER_EDGE, cbf)

time.sleep(300)

cb1.cancel()
cb2.cancel()
cb3.cancel()

pi.stop()
  • Thank you for the code. This looks like the kind of solution I've been looking for. I haven't been able to get it to work though. I installed and started PIGPIO an it gets past the connection so I assume that's working. the "request" link is meant to be an output, the Pi will set the request line high (it's attacked to an inverting transistor) to ask the indicator to start sending data. and the indicator will continue to send data 52 bits at a time until the request line is set low again. I've added pi.set_mode(REQ, pigpio.OUTPUT) and pi.write(REQ, 1) but the request pin remains low. – user3406369 Dec 5 '16 at 18:41
  • nevermind I had set the wrong pin number for the request line. It's all working now. For anyone else that comes across this the CLK and DATA lines need to be pulled up as well. pi.set_pull_up_down(CLK, pigpio.PUD_UP) Thank you again for the excellent answer – user3406369 Dec 5 '16 at 18:59

Not the answer you're looking for? Browse other questions tagged or ask your own question.