Blame view
software/common_class/mcp3551.py
5.03 KB
14b996da3
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 |
# -*- coding: utf-8 -*- """ author Benoit Dubois licence GPL v3+ brief STM32 driver for MCP3551 ADC device """ import pyb class Mcp3551(object): """Handle communication with ADC MCP3551 through SPI bus on STM32F4. Note: baudrate_max = MHz """ NUM_BITS = 22 MAX_VALUE = (1 << (NUM_BITS-1)) - 1 MIN_VALUE = -(1 << (NUM_BITS-1)) def __init__(self, bus, baudrate, rdy_b_pin, cs_pin, v_ref): """ :param bus: SPI bus number (int) :param baudrate: SPI bus (data) baudrate (int) :param rdy_b_pin: Pin in use for rdy_b (SDO/MISO) signal (str) :param cs_pin: Pin in use for cs signal (str) :param v_ref: Reference voltage value of ADC (float) """ self.baudrate = baudrate self.v_ref = v_ref self.rdy_b = pyb.Pin(rdy_b_pin, pyb.Pin.IN) self.cs_b = pyb.Pin(cs_pin, pyb.Pin.OUT_PP) self.spi = pyb.SPI(bus) self.cs_b.high() self.cs_b.low() def single_read(self): """Read one value then stop acquisition. """ self.cs_b.low() data = self.read() self.cs_b.high() return data def _bin2volt(self, value): """Note: does not check sign of data, so negative value are affected of a small error due to normalisation with MAX_VALUE instead of MIN_VALUE. """ return value * self.v_ref / self.MAX_VALUE def volt(self): """Note: does not check sign of data, so negative value are affected of a small error due to normalisation with MAX_VALUE instead of MIN_VALUE. """ return self._bin2volt(self.single_read(), self.v_ref, self.MAX_VALUE) def continous_mode(self, value=True): """Set/Deset continous acquisition mode. """ if value is False: self.cs_b.high() else: self.cs_b.low() def read(self): """Note1: The ADC allows operation over [-Vref; +Vref] range. This capability is not implemented. Note2: If ADC does not respond (i.e. /RDY does not falling), return 0. """ wd = 0 buf = bytearray(3) while self.rdy_b.value() == 1: if wd > 100: # Watchdog on MCP response return 0 else: wd += 1 pyb.delay(1) self.spi.init(pyb.SPI.MASTER, baudrate=self.baudrate, polarity=1, phase=1) self.spi.recv(buf, timeout=500) self.spi.deinit() if buf[0] & 256 == 1: # Overflow high return self.MAX_VALUE if buf[0] & 128 == 1: # Overflow low return self.MIN_VALUE data = (buf[0] << 16) + (buf[1] << 8) + buf[2] return self.twos_comp(data, self.NUM_BITS) @staticmethod def twos_comp(val, bits): """compute the 2's complement of int value val of lenght bits. """ if (val & (1 << (bits - 1))) != 0: # if sign bit is set val = val - (1 << bits) # compute negative value return val # return positive value as is class Mcp3551Temp(Mcp3551): """Handle "slow_adc_shield" of Cyrus Rocher ie a board including conditionning of a RTD and the A to D conversion with a MCP3551 device. """ def __init__(self, bus, baudrate, rdy_b_pin, cs_pin, v_ref=2.5, r_0=100, alpha=0.00385, r_ref=2.5e3): """ :param r_0: resistance of RTD @ 0°C (int) :param alpha: 1st order sensitivity of RTD (ohm/ohm/°C) (float) :param r_ref: resistance defining current through RTD (int) """ super().__init__(bus, baudrate, rdy_b_pin, cs_pin, v_ref) self.r_0 = r_0 self.r_ref = r_ref self.k = 1 / alpha / r_0 @staticmethod def bin2resistance(bin_value, r_ref, bin_max): """Convert binary value to resistance value. """ return bin_value * r_ref / bin_max @staticmethod def bin2temperature(bin_value, k, r_0, r_ref, bin_max): """Convert binary value to temperature value. """ return k * (bin_value * r_ref / bin_max - r_0) def resistance(self): """Convert binary value to resistance value. """ return self.bin2resistance(self.single_read(), self.r_ref, self.MAX_VALUE) def temperature(self): """Convert binary value to temperature value. """ return self.bin2temperature(self.single_read(), self.k, self.r_0, self.r_ref, self.MAX_VALUE) if __name__ == '__main__': ADC_SPI_CH = 1 ADC_V_REF = 2.5 ADC_SPI_BAUDRATE = 1000000 ADC_PIN_CS = 'PA4' ADC_PIN_RDY_B = 'PA6' ADC = Mcp3551(bus=ADC_SPI_CH, baudrate=ADC_SPI_BAUDRATE, rdy_b_pin=ADC_PIN_RDY_B, cs_pin=ADC_PIN_CS, v_ref=ADC_V_REF) ADC.continous_mode(True) ACQ_NB = 0 while True: pyb.delay(10) # in ms print(ACQ_NB, ADC.read()) ACQ_NB += 1 |