In the process of building a power amp, I had the opportunity to look at a number of speaker protection boards. They are all basically a μPC1237 with all of its features:
All very nice, but something is missing. The relay only disconnects the speakers. I needed something to protect the amplifier, too. If there is a DC offset, there is likely something burning in the amplifier, and I want to power it off as well as disconnect the speakers. Related to that is the heatsink temperature. If it is too high, there is something wrong. I want to disconnect the speakers and power off the amplifier. When the temperature drops below a set threshold, I want the amplifier to go through a startup sequence again - amp powered up, delay, speakers connected. That takes more smarts than a μPC1237 has, so the project needs a micro of some kind.
Because I wanted to use python to code it, I decided to use a RPi Pico as the controller. It's easy to program - you just plug it in, drop a file in a folder on the Pico, and python grabs it and installs it. They used to be $2 each before the apocalypse, now it's hard to find them for $6. I picked up a pair at Amazon for $14 with tax.
So here are the features I decided on:
To accomplish these, I cheated and used a μPC1237HA to detect the DC offset, and use the Pico to read two 18S20 temperature sensors, one on each heatsink. The Pico times the delay and determines when the two relays should be closed or open. The μPC1237 has been wired to ignore AC voltage, DC voltage, and power on delay. The board gets its power from a small 50VA transformer, which is powered as long as the AC cord is plugged in. The power switch is wired to the board - not the incoming AC voltage. When the power switch is pushed to the on position, the board powers up the main transformer, delays for 3 seconds, then connects the speakers to the amplifier output. The Pico then enters NORMAL mode, where the amplifier is on, the speakers are connected, and everything is fine.
When the power switch is pushed again, releasing it, the Pico turns off the speaker relay, then the power relay, and goes to IDLE mode. It reads the sensors and buttons in a fairly tight loop, but when it is delaying between power up and speaker connection, it sleeps in one second intervals. The Pico looks at the heatsink temperatures and the power switch to see if it is time to turn on, and that the temps are below the low-water mark of 50°C. If all is well, the power relay is closed, the mode changed to DELAYING, and the Pico goes into a 1-second sleep, three times. When it wakes up, it turns on the speaker relay, entering NORMAL mode again.
Should the temperatures rise to a point above the high-water mark of 60°C the speaker relay will be opened, the power relay opened, and the mode will be set to OVERHEATED. In this mode, the amplifier power will not be turned on until the heatsink temperatures are both under the low-water mark again. If there is a DC offset, the amp will be turned on and then immediately turn off.
The board is 95mm x 75mm, and contains all the circuitry except the relays. They mount on the rear panel of the amplifier. The relays are 24V coil, 30A contact, DPDT. The board is laid out so that the Pico can be surface mounted or socketed (with pins). All wire connections are screw terminals, on 5mm centers. There is a cutout on one edge of the board to provide room for the USB-C connector to clear, for when the Pico needs an update. A Schottky diode blocks the on-board power supply when the USB-C is plugged in.
import machine import time import onewire import ds18x20 from machine import timer from machine import Pin from micropython import const class C1237: def __init__(self, pin): self.relay = Pin(pin, Pin.IN, Pin.PULL_UP) def read(self): if self.relay.value(): return False else: return True class PowerSwitch: def __init__(self, pin): self.switch = Pin(pin, Pin.IN, Pin.PULL_UP) def read(self): if self.switch.value(): return False else: return True class Heatsink: HI_WATER = const(60) LO_WATER = const(50) def __init__(self, pin, name): self.name = name self.temperature = 0.0 self.ow = onewire.OneWire(Pin(pin)) self.ds = ds18x20.DS18X20(self.ow) self.rom = self.ds.scan()[0] self.ds.convert_temp() def read(self): self.temperature = self.ds.read(self.rom) self.ds.convert_temp() if __name__ == "__main__": IDLE = const(0) NORMAL = const(1) OVERHEATED = const(2) DELAYING = const(3) DELAY_TIME = 3 PWR_SW = const(0) RLY_IN = const(1) L_SINK = const(2) R_SINK = const(3) AMP_RLY = const(4) PWR_RLY = const(5) #The main power relay. pwrRelay = Pin(PWR_RLY) # The amplifier output relay. ampRelay = Pin(AMP_RLY) # The C1237HA relay output. c1237 = C1237(RLY_IN) # The front panel power switch. powerSwitch = PowerSwitch(PWR_SW) ampRelay.off() pwrRelay.off() # The left and right heatsinks. leftHeatsink = Heatsink(L_SINK, "left") rightHeatsink = Heatsink(R_SINK, "right") # Wait for the temps to calculate. time.sleep_ms(800) # Init the state machine operationalState = IDLE while True: leftTemperature = leftHeatsink.read() rightTmperature = rightHeatsink.read() if operationalState == OVERHEATED: if leftTemperature <= Heatsink.LO_WATER and rightTemperature <= Heatsink.LO_WATER: if powerSwitch.read(): pwrRelay.on() operationalState = DELAYING if operationalState == DELAYING: # Sleep for 3 seconds or so and then turn the amp relay on. time.sleep(DELAY_TIME) ampRelay.on() operationalState = NORMAL if operationalState == NORMAL: # Heatsink(s) too hot? # The UPC1237HA says there is a DC offset? # The power switch is off? if leftTemperature >= Heatsink.HI_WATER or \ rightTemperature >= Heatsink.HI_WATER: ampRelay.off() pwrRelay.off() operationalState = OVERHEATED elif not c1237.read() or not powerSwitch.read(): ampRelay.off() pwrRelay.off() operationalState = IDLE if operationalState == IDLE: # Don't turn it on unless the power switch is on and the sinks are cool. if leftTemperature <= Heatsink.LO_WATER and \ rightTemperature <= Heatsink.LO_WATER and\ c1237.read() and powerSwitch.read(): pwrRelay.on() operationalState = DELAYING time.sleep_ms(750)
Copyright ©2000 - 2025 David Allmon All rights reserved. | Privacy Policy | Cookie Policy