class ad7606(): try: start_acq_fd = open("/sys/class/gpio/gpio145/value", 'w', 0) except IOError as e: print("Error opening start acquire gpio pin: %s" % e) raise def __init__(self, dev): self.dev = SpiDev() try: self.dev.open(3, dev) self.dev.mode = 2 except IOError as e: print("Error opening /dev/spidev3.%d: %s" % (dev, e)) raise def trigger_acquire(self): self.start_acq_fd.write(b'1') self.start_acq_fd.write(b'0') def read(self): self.trigger_acquire() buf = self.dev.readbytes(16) samples = [0, 0, 0, 0, 0, 0, 0, 0] for i in xrange(8): samples[i] = buf[2 * i] << 8 | buf[2 * i + 1] << 0 return samples
class ad7606(): try: start_acq_fd = open("/sys/class/gpio/gpio145/value", 'w', 0) except IOError as e: print("Error opening start acquire gpio pin: %s" % e) raise def __init__(self, dev): self.dev = SpiDev() try: self.dev.open(3,dev) self.dev.mode = 2 except IOError as e: print("Error opening /dev/spidev3.%d: %s" % (dev, e)) raise def trigger_acquire(self): self.start_acq_fd.write(b'1') self.start_acq_fd.write(b'0') def read(self): self.trigger_acquire() buf = self.dev.readbytes(16) samples = [0,0,0,0,0,0,0,0] for i in xrange(8): samples[i] = buf[2*i] << 8 | buf[2*i+1] << 0 return samples
class O2Sensor(AbstractSensor): def generateCalibCurve(self): calibFilename = "callibCurve.csv" calibFile = open(path.dirname(__file__) + "/" + calibFilename, 'r') reader = csv.reader(calibFile) xVals = [] yVals = [] for row in reader: yVals.append(float(row[0])) xVals.append(float(row[1])) calibFile.close() self.calibF = interp1d(xVals, yVals) self.calibC = 92.8009950249 self.maxOut = max(yVals) def __init__(self): AbstractSensor.__init__(self) self.measurements = { "O2": [-1, "%"], "O2voltage": [-1, "V"], } self._spi = SpiDev(0, 0) self._CS = gpiozero.DigitalOutputDevice(5, initial_value=True) #self._MISO = gpiozero.DigitalInputDevice(9) self._spi.open(0, 0) self._spi.max_speed_hz = 500 self._spi.no_cs = True self.generateCalibCurve() def reset(self): time.sleep(0.01) def poll(self): self._CS.value = False time.sleep(0.09) res = self._spi.readbytes(3) self._CS.value = True res[0] &= 0x1F resval = 0 for i in range(3): resval += res[i] << (2 - i) * 8 if res[0] & 0x10: resval = 0x0FFFFF - resval - 1 resval = resval / float(0x0FFFFF) * 3.3 self.measurements["O2voltage"][0] = resval try: concentration = float(self.calibF(resval * self.calibC).item(0)) self.measurements["O2"][0] = concentration except: self.measurements["O2"][0] = self.maxOut
class CpPhy(object): # Profibus baud-rates PB_PHY_BAUD_9600 = 0 PB_PHY_BAUD_19200 = 1 PB_PHY_BAUD_45450 = 2 PB_PHY_BAUD_93750 = 3 PB_PHY_BAUD_187500 = 4 PB_PHY_BAUD_500000 = 5 PB_PHY_BAUD_1500000 = 6 PB_PHY_BAUD_3000000 = 7 PB_PHY_BAUD_6000000 = 8 PB_PHY_BAUD_12000000 = 9 # RTS mode PB_PHY_RTS_ALWAYS_LO = 0 PB_PHY_RTS_ALWAYS_HI = 1 PB_PHY_RTS_SENDING_HI = 2 PB_PHY_RTS_SENDING_LO = 3 # GPIO numbers (BCM) GPIO_RESET = 17 GPIO_IRQ = 27 GPIO_SS = 8 GPIO_MISO = 9 GPIO_MOSI = 10 GPIO_SCK = 11 baud2id = { 9600 : PB_PHY_BAUD_9600, 19200 : PB_PHY_BAUD_19200, 45450 : PB_PHY_BAUD_45450, 93750 : PB_PHY_BAUD_93750, 187500 : PB_PHY_BAUD_187500, 500000 : PB_PHY_BAUD_500000, 1500000 : PB_PHY_BAUD_1500000, 3000000 : PB_PHY_BAUD_3000000, 6000000 : PB_PHY_BAUD_6000000, 12000000 : PB_PHY_BAUD_12000000, } def __init__(self, device=0, chipselect=0, debug=False): self.device = device self.chipselect = chipselect self.debug = debug try: try: # Initialize GPIOs GPIO.setmode(GPIO.BCM) # Use Broadcom numbers GPIO.setwarnings(False) GPIO.setup(self.GPIO_RESET, GPIO.OUT, initial=GPIO.LOW) GPIO.setup(self.GPIO_IRQ, GPIO.IN, pull_up_down=GPIO.PUD_OFF) GPIO.add_event_detect(self.GPIO_IRQ, GPIO.RISING) time.sleep(0.05) except RuntimeError as e: raise PhyError("Failed to initialize GPIOs: %s" %\ str(e)) # Initialize SPI try: self.spi = SpiDev() self.spi.open(device, chipselect) except IOError as e: raise PhyError("Failed to open SPI device %d.%d: %s" %\ (device, chipselect, str(e))) try: self.spi.mode = 0; self.spi.bits_per_word = 8; self.spi.cshigh = False self.spi.lsbfirst = False self.spi.max_speed_hz = 200000; except IOError as e: try: self.spi.close() self.spi = None except: pass raise PhyError("Failed to configure SPI device %d.%d: %s" %\ (device, chipselect, str(e))) # Get the controller out of hardware reset GPIO.output(self.GPIO_RESET, GPIO.HIGH) time.sleep(0.2) # Send a software reset self.sendReset() # Upload default config self.profibusSetPhyConfig() except: GPIO.cleanup() raise def cleanup(self): self.spi.close() self.spi = None GPIO.cleanup() # Poll for received packet. # timeout => In seconds. 0 = none, Negative = unlimited. def poll(self, timeout=0): limit = TimeLimited(timeout) while GPIO.event_detected(self.GPIO_IRQ): if limit.exceed(): return None limit.sleep(0.001) limit.add(0.5) while not limit.exceed(): fc = self.spi.readbytes(1)[0] if fc != CpPhyMessage.RPI_PACK_NOP: break else: return None reply = [ fc ] reply.extend(self.spi.readbytes(CpPhyMessage.RASPI_PACK_HDR_LEN - 1)) payloadLen = reply[1] & 0xFF if payloadLen: reply.extend(self.spi.readbytes(payloadLen)) message = CpPhyMessage(0) message.setRawData(reply) if self.debug: print("[PHY] recv msg:", message) return message def __sendMessage(self, message): if self.debug: print("[PHY] send msg:", message) self.spi.writebytes(message.getRawData()) def sendReset(self): self.__sendMessage(CpPhyMessage(CpPhyMessage.RPI_PACK_RESET)) reply = self.poll(timeout=-1) if reply.fc != CpPhyMessage.RPI_PACK_ACK: raise PhyError("Failed to reset PHY") def profibusSetPhyConfig(self, baudrate=19200, rxTimeoutMs=100, bitErrorChecks=True, rtsMode=PB_PHY_RTS_SENDING_HI): try: baudID = self.baud2id[baudrate] except KeyError: raise PhyError("Invalid baud-rate") if rxTimeoutMs < 1 or rxTimeoutMs > 255: raise PhyError("Invalid RX timeout") payload = [ baudID, rxTimeoutMs, 1 if bitErrorChecks else 0, rtsMode & 0xFF ] message = CpPhyMessage(CpPhyMessage.RPI_PACK_SETCFG, payload) self.__sendMessage(message) reply = self.poll(timeout=-1) if reply.fc != CpPhyMessage.RPI_PACK_ACK: raise PhyError("Failed to upload config") def profibusSend_SDN(self, telegramData): self.__sendMessage(CpPhyMessage(CpPhyMessage.RPI_PACK_PB_SDN, telegramData)) def profibusSend_SRD(self, telegramData): self.__sendMessage(CpPhyMessage(CpPhyMessage.RPI_PACK_PB_SRD, telegramData))
class CpPhy(object): # Profibus baud-rates PB_PHY_BAUD_9600 = 0 PB_PHY_BAUD_19200 = 1 PB_PHY_BAUD_45450 = 2 PB_PHY_BAUD_93750 = 3 PB_PHY_BAUD_187500 = 4 PB_PHY_BAUD_500000 = 5 PB_PHY_BAUD_1500000 = 6 PB_PHY_BAUD_3000000 = 7 PB_PHY_BAUD_6000000 = 8 PB_PHY_BAUD_12000000 = 9 # RTS mode PB_PHY_RTS_ALWAYS_LO = 0 PB_PHY_RTS_ALWAYS_HI = 1 PB_PHY_RTS_SENDING_HI = 2 PB_PHY_RTS_SENDING_LO = 3 # GPIO numbers (BCM) GPIO_RESET = 17 GPIO_IRQ = 27 GPIO_SS = 8 GPIO_MISO = 9 GPIO_MOSI = 10 GPIO_SCK = 11 baud2id = { 9600: PB_PHY_BAUD_9600, 19200: PB_PHY_BAUD_19200, 45450: PB_PHY_BAUD_45450, 93750: PB_PHY_BAUD_93750, 187500: PB_PHY_BAUD_187500, 500000: PB_PHY_BAUD_500000, 1500000: PB_PHY_BAUD_1500000, 3000000: PB_PHY_BAUD_3000000, 6000000: PB_PHY_BAUD_6000000, 12000000: PB_PHY_BAUD_12000000, } def __init__(self, device=0, chipselect=0, debug=False): self.device = device self.chipselect = chipselect self.debug = debug try: try: # Initialize GPIOs GPIO.setmode(GPIO.BCM) # Use Broadcom numbers GPIO.setwarnings(False) GPIO.setup(self.GPIO_RESET, GPIO.OUT, initial=GPIO.LOW) GPIO.setup(self.GPIO_IRQ, GPIO.IN, pull_up_down=GPIO.PUD_OFF) GPIO.add_event_detect(self.GPIO_IRQ, GPIO.RISING) time.sleep(0.05) except RuntimeError as e: raise PhyError("Failed to initialize GPIOs: %s" %\ str(e)) # Initialize SPI try: self.spi = SpiDev() self.spi.open(device, chipselect) except IOError as e: raise PhyError("Failed to open SPI device %d.%d: %s" %\ (device, chipselect, str(e))) try: self.spi.mode = 0 self.spi.bits_per_word = 8 self.spi.cshigh = False self.spi.lsbfirst = False self.spi.max_speed_hz = 200000 except IOError as e: try: self.spi.close() self.spi = None except: pass raise PhyError("Failed to configure SPI device %d.%d: %s" %\ (device, chipselect, str(e))) # Get the controller out of hardware reset GPIO.output(self.GPIO_RESET, GPIO.HIGH) time.sleep(0.2) # Send a software reset self.sendReset() # Upload default config self.profibusSetPhyConfig() except: GPIO.cleanup() raise def cleanup(self): self.spi.close() self.spi = None GPIO.cleanup() # Poll for received packet. # timeout => In seconds. 0 = none, Negative = unlimited. def poll(self, timeout=0): limit = TimeLimited(timeout) while GPIO.event_detected(self.GPIO_IRQ): if limit.exceed(): return None limit.sleep(0.001) limit.add(0.5) while not limit.exceed(): fc = self.spi.readbytes(1)[0] if fc != CpPhyMessage.RPI_PACK_NOP: break else: return None reply = [fc] reply.extend(self.spi.readbytes(CpPhyMessage.RASPI_PACK_HDR_LEN - 1)) payloadLen = reply[1] & 0xFF if payloadLen: reply.extend(self.spi.readbytes(payloadLen)) message = CpPhyMessage(0) message.setRawData(reply) if self.debug: print("[PHY] recv msg:", message) return message def __sendMessage(self, message): if self.debug: print("[PHY] send msg:", message) self.spi.writebytes(message.getRawData()) def sendReset(self): self.__sendMessage(CpPhyMessage(CpPhyMessage.RPI_PACK_RESET)) reply = self.poll(timeout=-1) if reply.fc != CpPhyMessage.RPI_PACK_ACK: raise PhyError("Failed to reset PHY") def profibusSetPhyConfig(self, baudrate=19200, rxTimeoutMs=100, bitErrorChecks=True, rtsMode=PB_PHY_RTS_SENDING_HI): try: baudID = self.baud2id[baudrate] except KeyError: raise PhyError("Invalid baud-rate") if rxTimeoutMs < 1 or rxTimeoutMs > 255: raise PhyError("Invalid RX timeout") payload = [ baudID, rxTimeoutMs, 1 if bitErrorChecks else 0, rtsMode & 0xFF ] message = CpPhyMessage(CpPhyMessage.RPI_PACK_SETCFG, payload) self.__sendMessage(message) reply = self.poll(timeout=-1) if reply.fc != CpPhyMessage.RPI_PACK_ACK: raise PhyError("Failed to upload config") def profibusSend_SDN(self, telegramData): self.__sendMessage( CpPhyMessage(CpPhyMessage.RPI_PACK_PB_SDN, telegramData)) def profibusSend_SRD(self, telegramData): self.__sendMessage( CpPhyMessage(CpPhyMessage.RPI_PACK_PB_SRD, telegramData))
class SPIimplementation(SPI): """SPI imlementation wrapping spidev library. Extends :class:`SPI`. Args: port (int): SPI port on raspberry pi. devive (int): SPI device of raspberry. Raises: ImportError: If spidev is not installed. """ def __init__(self, port, device): self._port = port self._device = device self._interface = None if SpiDev is None: raise ImportError('failed to import spidev') self._interface = SpiDev() self._interface.open(port, device) self._interface.max_speed_hz = 1000000 def read(self, n): """Read n words from spi Args: n (int): The number of bytes to read from spi. """ return self._interface.readbytes(n) # TODO: Check writebytes2 for large lists def write(self, data): """Write data to spi Args: data (list): A list with integers to be writter to the device. """ self._interface.writebytes2(data) def read_write(self, data): """ Writes data (a list of integer words where each word is assumed to have :attr:`bits_per_word` bits or less) to the SPI interface, and reads an equivalent number of words, returning them as a list of integers. """ return self._interface.xfer2(data) def close(self): if self._interface is not None: self._interface.close() self._interface = None def _get_clock_mode(self): return self._interface.mode def _set_clock_mode(self, value): self._interface.mode = value def _get_lsb_first(self): return self._interface.lsbfirst def _set_lsb_first(self, value): self._interface.lsbfirst = bool(value) def _get_select_high(self): return self._interface.cshigh def _set_select_high(self, value): self._interface.cshigh = bool(value) def _get_bits_per_word(self): return self._interface.bits_per_word def _set_bits_per_word(self, value): self._interface.bits_per_word = value
class SPI(object): """ classdocs """ __LOCK_TIMEOUT = 10.0 # ---------------------------------------------------------------------------------------------------------------- def __init__(self, bus, device, mode, max_speed): """ Constructor """ self.__bus = bus self.__device = device self.__mode = mode self.__max_speed = max_speed self.__connection = None # ---------------------------------------------------------------------------------------------------------------- def open(self): if self.__connection: return self.acquire_lock() self.__connection = SpiDev() self.__connection.open(self.__bus, self.__device) self.__connection.mode = self.__mode self.__connection.max_speed_hz = self.__max_speed def close(self): if self.__connection is None: return self.__connection.close() self.__connection = None self.release_lock() # ---------------------------------------------------------------------------------------------------------------- def acquire_lock(self): Lock.acquire(self.__lock_name, SPI.__LOCK_TIMEOUT) def release_lock(self): Lock.release(self.__lock_name) @property def __lock_name(self): return "%s-%s" % (self.__class__.__name__, self.__bus) # ---------------------------------------------------------------------------------------------------------------- def xfer(self, args): return self.__connection.xfer(args) def read_bytes(self, count): return self.__connection.readbytes(count) # ---------------------------------------------------------------------------------------------------------------- @property def bus(self): return self.__bus @property def device(self): return self.__device # ---------------------------------------------------------------------------------------------------------------- def __str__(self, *args, **kwargs): return "SPI:{bus:%d, device:%s, mode:%d, max_speed:%d, connection:%s}" % \ (self.__bus, self.__device, self.__mode, self.__max_speed, self.__connection)