import spidev import time DEBUG = False class MCP3208: def __init__(self, bus=0, device=0): # Initialize SPI bus and device self.spi = spidev.SpiDev() self.spi.open(bus, device) # Default SPI bus 0, device 0 (you can change as needed) self.spi.max_speed_hz = 1000000 # Adjust based on your needs (e.g., 1MHz) self.spi.mode = 0b00 # Set SPI mode (Mode 0 for MCP3208) def read(self, channel): """ Read the ADC value from the specified channel (0-7). """ # MCP3208 is a 12-bit SPI ADC. Communication requires sending a 3-byte command and receiving a 3-byte response. # The bits in the command sequence are structured as follows: # Command Byte (8 bits): # | Start (1) | Mode (1) | Channel (3) | Padding (3) | # The MCP3208 responds with 3 bytes: # - Byte 1: Contains the highest bit (bit 11) of the 12-bit ADC result. # - Byte 2: Contains bits 10-3 of the ADC result. # - Byte 3: Contains bits 2-0 of the ADC result. # Ensure the channel is valid (0-7) if channel < 0 or channel > 7: raise ValueError(f"Channel must be between 0 and 7. (current channel={channel})") # Construct the command byte sequence: # - Start bit (1) -> 1000 0000 (0x80) # - Single-ended (1) -> 1100 0000 (0xC0) # - Channel (3 bits) shifted into position cmd = 0x80 # Start bit: 1000 0000 cmd |= 0x40 # Single-ended mode: 1100 0000 cmd |= (channel & 0x07) << 3 # Move channel number to bits 5-3 # Send the command and receive the 3-byte response ret = self.spi.xfer2([cmd, 0x00, 0x00]) # Send 3 bytes, receive 3 bytes if DEBUG: print(f"result[0]: {bin(ret[0])}, result[1]: {bin(ret[1])}, result[2]: {bin(ret[2])}") # Extract the 12-bit ADC result from the received bytes: val = (ret[0] & 0x01) << 11 # Extract bit 11 (MSB) val |= ret[1] << 3 # Extract bits 10-3 val |= ret[2] >> 5 # Extract bits 2-0 (shift down) return val & 0x0FFF # Mask to ensure only the lower 12 bits are used def close(self): """Close SPI connection.""" self.spi.close() # Example usage: if __name__ == "__main__": adc = MCP3208() try: while True: for i in range(8): adc_value = adc.read(i) print(f'ADC[{i}]: {adc_value}') time.sleep(0.5) finally: adc.close()