You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
			
				
					83 lines
				
				2.4 KiB
			
		
		
			
		
	
	
					83 lines
				
				2.4 KiB
			| 
								 
											5 years ago
										 
									 | 
							
								#!/usr/bin/env python3
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# Python library to control Zookeeper
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								import ft4222
							 | 
						||
| 
								 | 
							
								import ft4222.I2CMaster
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								DEBUG = False
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								INA231_ADDR = 0x40
							 | 
						||
| 
								 | 
							
								INA231_REG_CONFIG = 0x00
							 | 
						||
| 
								 | 
							
								INA231_REG_SHUNT_VOLTAGE = 0x01
							 | 
						||
| 
								 | 
							
								INA231_REG_BUS_VOLTAGE = 0x02
							 | 
						||
| 
								 | 
							
								INA231_REG_POWER = 0x03
							 | 
						||
| 
								 | 
							
								INA231_REG_CURRENT = 0x04
							 | 
						||
| 
								 | 
							
								INA231_REG_CALIBRATION = 0x05
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								INA231_BUS_LSB = 1.25e-3
							 | 
						||
| 
								 | 
							
								INA231_SHUNT_LSB = 2.5e-6
							 | 
						||
| 
								 | 
							
								SHUNT_RESISTOR = 30e-3
							 | 
						||
| 
								 | 
							
								CURRENT_LSB = 1e-5
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class Zookeeper:
							 | 
						||
| 
								 | 
							
								  def __init__(self):
							 | 
						||
| 
								 | 
							
								    if ft4222.createDeviceInfoList() < 2:
							 | 
						||
| 
								 | 
							
								      raise Exception("No connected zookeeper found!")
							 | 
						||
| 
								 | 
							
								    self.dev_a = ft4222.openByDescription("FT4222 A")
							 | 
						||
| 
								 | 
							
								    self.dev_b = ft4222.openByDescription("FT4222 B")
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if DEBUG:
							 | 
						||
| 
								 | 
							
								      for i in range(ft4222.createDeviceInfoList()):
							 | 
						||
| 
								 | 
							
								        print(f"Device {i}: {ft4222.getDeviceInfoDetail(i, False)}")
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    # Setup GPIO
							 | 
						||
| 
								 | 
							
								    self.dev_b.gpio_Init(gpio2=ft4222.Dir.OUTPUT, gpio3=ft4222.Dir.OUTPUT)
							 | 
						||
| 
								 | 
							
								    self.dev_b.setSuspendOut(False)
							 | 
						||
| 
								 | 
							
								    self.dev_b.setWakeUpInterrut(False)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    # Setup I2C
							 | 
						||
| 
								 | 
							
								    self.dev_a.i2cMaster_Init(kbps=400)
							 | 
						||
| 
								 | 
							
								    self._initialize_ina()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  # Helper functions
							 | 
						||
| 
								 | 
							
								  def _read_ina_register(self, register, length):
							 | 
						||
| 
								 | 
							
								    self.dev_a.i2cMaster_WriteEx(INA231_ADDR, data=register, flag=ft4222.I2CMaster.Flag.REPEATED_START)
							 | 
						||
| 
								 | 
							
								    return self.dev_a.i2cMaster_Read(INA231_ADDR, bytesToRead=length)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  def _write_ina_register(self, register, data):
							 | 
						||
| 
								 | 
							
								    msg = register.to_bytes(1, byteorder="big") + data.to_bytes(2, byteorder="big")
							 | 
						||
| 
								 | 
							
								    self.dev_a.i2cMaster_Write(INA231_ADDR, data=msg)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  def _initialize_ina(self):
							 | 
						||
| 
								 | 
							
								    # Config
							 | 
						||
| 
								 | 
							
								    self._write_ina_register(INA231_REG_CONFIG, 0x4127)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    # Calibration
							 | 
						||
| 
								 | 
							
								    CAL_VALUE = int(0.00512 / (CURRENT_LSB * SHUNT_RESISTOR))
							 | 
						||
| 
								 | 
							
								    if DEBUG:
							 | 
						||
| 
								 | 
							
								      print(f"Calibration value: {hex(CAL_VALUE)}")
							 | 
						||
| 
								 | 
							
								    self._write_ina_register(INA231_REG_CALIBRATION, CAL_VALUE)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  def _set_gpio(self, number, enabled):
							 | 
						||
| 
								 | 
							
								    self.dev_b.gpio_Write(portNum=number, value=enabled)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  # Public API functions
							 | 
						||
| 
								 | 
							
								  def set_device_power(self, enabled):
							 | 
						||
| 
								 | 
							
								    self._set_gpio(2, enabled)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  def set_device_ignition(self, enabled):
							 | 
						||
| 
								 | 
							
								    self._set_gpio(3, enabled)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  def read_current(self):
							 | 
						||
| 
								 | 
							
								    # Returns in A
							 | 
						||
| 
								 | 
							
								    return int.from_bytes(self._read_ina_register(INA231_REG_CURRENT, 2), byteorder="big") * CURRENT_LSB
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  def read_power(self):
							 | 
						||
| 
								 | 
							
								    # Returns in W
							 | 
						||
| 
								 | 
							
								    return int.from_bytes(self._read_ina_register(INA231_REG_POWER, 2), byteorder="big") * CURRENT_LSB * 25
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  def read_voltage(self):
							 | 
						||
| 
								 | 
							
								    # Returns in V
							 | 
						||
| 
								 | 
							
								    return int.from_bytes(self._read_ina_register(INA231_REG_BUS_VOLTAGE, 2), byteorder="big") * INA231_BUS_LSB
							 |