Thanks guys. I kinda get the feeling that this HAT is gonna be a bunch of headache to get it to do what I want. Not that there’s necessarily anything wrong with the HAT itself, because as it is, it’s working. Channel 0 is what runs the fan, and I can steal that signal, which is running about 40%.
This is the example that they provide for Python, if this helps clear up anything. Unfortunately, I don’t know enough yet about doing this to look at this code and pick out the important bits:
#!/usr/bin/python
import time
import math
import smbus
============================================================================
Raspi PCA9685 16-Channel PWM Servo Driver
============================================================================
class PCA9685(object):
# Registers/etc.
__SUBADR1 = 0x02
__SUBADR2 = 0x03
__SUBADR3 = 0x04
__MODE1 = 0x00
__PRESCALE = 0xFE
__LED0_ON_L = 0x06
__LED0_ON_H = 0x07
__LED0_OFF_L = 0x08
__LED0_OFF_H = 0x09
__ALLLED_ON_L = 0xFA
__ALLLED_ON_H = 0xFB
__ALLLED_OFF_L = 0xFC
__ALLLED_OFF_H = 0xFD
def __init__(self, address=0x40, debug=False):
self.bus = smbus.SMBus(1)
self.address = address
self.debug = debug
if (self.debug):
print("Reseting PCA9685")
self.write(self.__MODE1, 0x00)
def write(self, reg, value):
"Writes an 8-bit value to the specified register/address"
self.bus.write_byte_data(self.address, reg, value)
if (self.debug):
print("I2C: Write 0x%02X to register 0x%02X" % (value, reg))
def read(self, reg):
"Read an unsigned byte from the I2C device"
result = self.bus.read_byte_data(self.address, reg)
if (self.debug):
print("I2C: Device 0x%02X returned 0x%02X from reg 0x%02X" % (self.address, result & 0xFF, reg))
return result
def setPWMFreq(self, freq):
"Sets the PWM frequency"
prescaleval = 25000000.0 # 25MHz
prescaleval /= 4096.0 # 12-bit
prescaleval /= float(freq)
prescaleval -= 1.0
if (self.debug):
print("Setting PWM frequency to %d Hz" % freq)
print("Estimated pre-scale: %d" % prescaleval)
prescale = math.floor(prescaleval + 0.5)
if (self.debug):
print("Final pre-scale: %d" % prescale)
oldmode = self.read(self.__MODE1);
newmode = (oldmode & 0x7F) | 0x10 # sleep
self.write(self.__MODE1, newmode) # go to sleep
self.write(self.__PRESCALE, int(math.floor(prescale)))
self.write(self.__MODE1, oldmode)
time.sleep(0.005)
self.write(self.__MODE1, oldmode | 0x80)
def setPWM(self, channel, on, off):
"Sets a single PWM channel"
self.write(self.__LED0_ON_L+4*channel, on & 0xFF)
self.write(self.__LED0_ON_H+4*channel, on >> 8)
self.write(self.__LED0_OFF_L+4*channel, off & 0xFF)
self.write(self.__LED0_OFF_H+4*channel, off >> 8)
if (self.debug):
print("channel: %d LED_ON: %d LED_OFF: %d" % (channel,on,off))
def setServoPulse(self, channel, pulse):
pulse = pulse*4095/100
self.setPWM(channel, 0, int(pulse))
If anyone has a suggestion of an easier way to achieve my goal, other than using a soft pwm from the gpio pins, I don’t mind buying other little boards.
Allow me to explain what exactly I’m doing with this project. I am building a toy hauler RV trailer, and am using the PI to control essentially everything. Multiple dimming channels for LED lighting, multiple relays controlled to turn on/off various things. This will all be interfaced through a 7" touch screen.
I also have another PI (3B) running the same 7" screen, but running Victron’s Venus OS. This will run everything to do with the solar system, and all of that is up and running already.
I need to have about a dozen pwm channels for dimming, and am using 8 straight outputs and a few inputs as well. Looking to also control temp of the electrical enclosure with a temp sensor I already have, and two Noctua pwm fans. This part may or may not be taken care of though the solar system, not sure just yet as that would mean the fans would just be on/off, not pwm.