113 lines
3.7 KiB
Python
113 lines
3.7 KiB
Python
"""
|
|
NOVA_G1
|
|
|
|
Micropython library for the NOVA_G1(PWM*6, IO*2, ADC*1)
|
|
=======================================================
|
|
|
|
#Preliminary composition 20240222
|
|
|
|
@dahanzimin From the Mixly Team
|
|
"""
|
|
from micropython import const
|
|
from mixgo_nova import onboard_i2c
|
|
|
|
_NOVA_G1_ADDRESS = const(0x25)
|
|
_NOVA_G1_ID = const(0x00)
|
|
_NOVA_G1_ADC = const(0x01)
|
|
_NOVA_G1_IO = const(0x03)
|
|
_NOVA_G1_PWM = const(0x04)
|
|
|
|
class NOVA_G1:
|
|
def __init__(self, i2c_bus, addr=_NOVA_G1_ADDRESS):
|
|
self._i2c = i2c_bus
|
|
self._addr = addr
|
|
if self._rreg(_NOVA_G1_ID) != 0x25:
|
|
raise AttributeError("Cannot find a NOVA_G1")
|
|
self.reset()
|
|
|
|
def _wreg(self, reg, val):
|
|
'''Write memory address'''
|
|
try:
|
|
self._i2c.writeto_mem(self._addr, reg, val.to_bytes(1, 'little'))
|
|
except:
|
|
return 0
|
|
|
|
def _rreg(self, reg, nbytes=1):
|
|
'''Read memory address'''
|
|
try:
|
|
self._i2c.writeto(self._addr, reg.to_bytes(1, 'little'))
|
|
return self._i2c.readfrom(self._addr, nbytes)[0] if nbytes <= 1 else self._i2c.readfrom(self._addr, nbytes)[0:nbytes]
|
|
except:
|
|
return 0
|
|
|
|
def reset(self):
|
|
"""Reset all registers to default state"""
|
|
for reg in range(_NOVA_G1_PWM, _NOVA_G1_PWM + 6):
|
|
self._wreg(reg, 0x00)
|
|
|
|
def varistor(self, ratio=100/1023):
|
|
'''Read battery power'''
|
|
_adc = self._rreg(_NOVA_G1_ADC) << 2 | self._rreg(_NOVA_G1_ADC+1) >> 6
|
|
return round(_adc * ratio)
|
|
|
|
def pwm(self, index, duty=None):
|
|
"""Motor*2*2 & USB*2 PWM duty cycle data register"""
|
|
if duty is None:
|
|
return self._rreg(_NOVA_G1_PWM + index)
|
|
else:
|
|
duty = min(255, max(0, duty))
|
|
self._wreg(_NOVA_G1_PWM + index, duty)
|
|
|
|
def motor(self, index, action, speed=0):
|
|
if not 0 <= index <= 1:
|
|
raise ValueError("Motor port must be a number in the range: 0~1")
|
|
speed = min(100, max(speed, -100))
|
|
if action == "N":
|
|
self.pwm(index * 2, 0)
|
|
self.pwm(index * 2 + 1, 0)
|
|
elif action == "P":
|
|
self.pwm(index * 2, 255)
|
|
self.pwm(index * 2 + 1, 255)
|
|
elif action == "CW":
|
|
if speed >= 0:
|
|
self.pwm(index * 2, 0)
|
|
self.pwm(index * 2 + 1, speed * 255 // 100)
|
|
else:
|
|
self.pwm(index * 2, 0)
|
|
self.pwm(index * 2 + 1, - speed * 255 // 100)
|
|
elif action == "CCW":
|
|
if speed >= 0:
|
|
self.pwm(index * 2, speed * 255 // 100)
|
|
self.pwm(index * 2 + 1, 0)
|
|
else:
|
|
self.pwm(index * 2, - speed * 255 // 100)
|
|
self.pwm(index * 2 + 1, 0)
|
|
elif action == "NC":
|
|
return round(self.pwm(index * 2) * 100 / 255), round(self.pwm(index * 2 + 1) * 100 / 255)
|
|
else:
|
|
raise ValueError('Invalid input, valid are "N","P","CW","CCW"')
|
|
|
|
def usb_pwm(self, index, duty=None):
|
|
if not 0 <= index <= 1:
|
|
raise ValueError("USB-2.0 port must be a number in the range: 0~1")
|
|
if duty is None:
|
|
return round((self.pwm(index + 4) * 100 / 255))
|
|
else:
|
|
self.pwm(index + 4, duty * 255 // 100)
|
|
|
|
def spk_en(self, onoff=True):
|
|
if onoff:
|
|
self._wreg(_NOVA_G1_IO, (self._rreg(_NOVA_G1_IO)) | 0x02)
|
|
else:
|
|
self._wreg(_NOVA_G1_IO, (self._rreg(_NOVA_G1_IO)) & 0xFD)
|
|
|
|
def ldo_en(self, onoff=True):
|
|
if onoff:
|
|
self._wreg(_NOVA_G1_IO, (self._rreg(_NOVA_G1_IO)) | 0x01)
|
|
else:
|
|
self._wreg(_NOVA_G1_IO, (self._rreg(_NOVA_G1_IO)) & 0xFE)
|
|
|
|
|
|
# Constructor
|
|
ext_g1 = NOVA_G1(onboard_i2c)
|