I have read the reference and all the IF, CONDITIONAL, WHILE sections...
but I am obviously missing something or things important!
The program I am trying to implement is really simple and small, and VERY well commented.
Could some kind soul have a look and give me a couple pointers on what I am missing?
/*Program to work as the shutdown and powerup
circuit for the Tripath TA0104a Class T (aka
Class D) audio amplifier using an 8-pin atTiny.
I'm using an 85, but even an atTiny25 is plenty -
it uses a whole 17 bytes of dynamic memory.
I just wanted a simple way to do what is needed
in a small PCB footprint. Here's what it does.
It mutes the amplifier long enough on power up
for the power supplies to stablize and mutes it
on a powerfail or being turned off. This is done
by using a single diode from the power transformer
secondary to an R-C network and a digital
transistor which pulls the powerSense pin on
the atTiny to ground when the transformer is
putting out a stream of positive pulses (because
the power to the amp is turned on). The R-C time
constant of the analog interface circuit is short
(about 50 milliseconds or so) so that the LOW
drive to the powerSense goes HIGH when you (or
something) cuts off the AC power, aka mains power.
The little analog interface is for ruggedness.
The Tripath module is muted by setting pin 4 on
the Tripath module HIGH. Th e Tripath MUTE pin
is is connected to the output of pin 5 on the
atTINY85 DIP package, aka PB0 in AVR parlance.
The circuit also checks for input overdrive\output
clipping and lights an LED connected to the output
of the atTINY85 DIP package pin 3 (aka PB4). The
atTiny program includes a "pulse stretcher" which
makes very brief amp clipping visible by keeping
the LED on for at least the LED stretch time (so
you won't miss seeing when occasional peaks are
being clipped). The atTiny circuit will also mute
the amplifier (which stops the Tripath driver from
sending pulses to the output MOSFETs)if prolonged
clipping is present to protect the speakers as
well as the amplifier.
If the overdrive has been going on too long, the
atTiny85 circuit will latch the amplifier in MUTE
which requires the power to be cycled to restart
the amp, or you can have a reset switch connected
to the atTiny85 DIP package pin 1 to pull the pin
LOW if you want a switch for this function.
Designed by MR COFFEE September 14, 2015
Modified: not yet*/
// ATMEL ATTINY85 / ARDUINO
//
// +-\/-+
// Ain0 (D 5) PB5 1| |8 Vcc
// Ain3 (D 3) PB3 2| |7 PB2 (D 2) Ain1 (powersense input)
// (clip LED out) Ain2 (D 4) PB4 3| |6 PB1 (D 1) pwm1 (clipping input)
// GND 4| |5 PB0 (D 0) pwm0 (mute output)
// +----+
// CONSTANTS
// Set pin numbers:
// below is the number of the ATtiny INPUT
// pin that is connected to the power sense
// circuit through a transistor inverter. It
// goes LOW when power is good. The "pin"
// number isn't the actual pin number on
// the IC package - it is the "Port pin"
// number which corresponds to the actual
// pin number on the 8-pin DIP. It is:
const int powerSense = 2; // port pin 2 is on DIP pin 7
// below is the number of the ATtiny INPUT
// pin which will be connected to Pin 2
// on Tripath module. Pin 2 on the Tripath
// module goes LOW when the amp clips. The
// "pin" number isn't the actual pin
// number on the chip - it is the "Port pin"
// number which corresponds to the actual
// pin number on the 8-pin DIP. It is:
const int clip = 1; // port pin 1 is on DIP pin 6
// below is the number of the ATtiny OUTPUT
// pin that is connected to the connected to
// Pin 4 (the MUTE input) on Tripath module.
// The "pin" number isn't the actual pin
// number on the IC package - it is the
// "Port pin" number which corresponds to
// the actual pin number on the 8-pin DIP. It is:
const int mute = 0; // port pin 0 is on DIP pin 5
// below is the number of the ATtiny OUTPUT
// pin that is connected to the connected to
// a LED overload indicator. The pin goes
// HIGH on clipping peaks with a stretched
// output duration to ensure visibility.
// The "pin" number isn't the actual pin
// number on the IC package - it is the
// "Port pin" number which corresponds to
// the actual pin number on the 8-pin DIP. It is:
const int overloadIndicator = 4; // port pin 4 is DIP pin 3
// PROGRAM CONSTANTS THAT MAY NEED TO BE CHANGED
// These values will need to be tweaked
// Values in (roughly) multiples of loop time
const long startUpDelay = 32000L;
const long ODtooLong = 300L;
const long tolerableClipping = 50L;
const long LEDstretchTime = 30L;
// VARIABLES
// counts time after some overdrive has
// occurred so occasional peaks don't
// cause unneeded muting\shutdown
long timeWithoutOverdrive = 0L;
// counts time that overdrive has been
// occurring to trigger muting the amp
long overdriveDuration = 0L;
// count how long the power to
// the Amplifier has been good
long powerGoodDetected = 0L;
void setup()
{
// Set pins as inputs or outputs
pinMode(clip, INPUT_PULLUP);
pinMode(powerSense, INPUT_PULLUP);
pinMode(mute, OUTPUT);
pinMode(overloadIndicator, OUTPUT);
// Initialize output pins to start-up state
// initially Tripath should be MUTE, which
// requires holding the MUTE pin HIGH
digitalWrite(mute,HIGH);
// initially the overload indicator should be off
digitalWrite(overloadIndicator,LOW);
}
// MAIN LOOP:
void loop()
{
// Make sure the amp isn't already shutdown. If it is shutdown,
// terminate the loop
while(overdriveDuration < ODtooLong)
{
// Check if power to the amp is good and had time to stabilize
if (digitalRead(powerSense) == LOW && powerGoodDetected > startUpDelay)
digitalWrite(mute,LOW);
// Check if power to the amp just came up
if (digitalRead(powerSense) == LOW && powerGoodDetected < startUpDelay)
powerGoodDetected = powerGoodDetected ++;
// Check if the amp is clipping but has NOT
// been clipping for very long or clipping a lot
if (digitalRead(clip) == LOW && overdriveDuration < ODtooLong)
{
digitalWrite(overloadIndicator, HIGH);
overdriveDuration = overdriveDuration ++;
}
// Check if the amp is clipping and has been clipping
// for too long a time or at least clipping a lot recently
if (digitalRead(clip) == LOW && overdriveDuration > ODtooLong)
{
// this means the amp is clipping continuously
// or at least quite a bit in a short time
// so shut it down NOW before you damage it
digitalWrite(mute,HIGH);
digitalWrite(overloadIndicator, HIGH);
}
// Now if the amp isn't clipping now, begin backing off
// the overdrive counter so it won't overflow with occasional
// clipped peaks. Check that the counter won't go below
// zero before doing the subtraction, and skip it if it already
// very close to zero and would underflow.
if (digitalRead(clip) == HIGH && overdriveDuration >= tolerableClipping)
overdriveDuration = (overdriveDuration - tolerableClipping);
delay(250);
} // end of while
} // end of main loop
I'm changing things guessing at what I may not be getting about how the C++ compiler works - do I just need to re-do this as a pile of nested if-else statements? Do IF conditions need to be computed before the IF statement, like in a simple little procedure?
Please don't just tell me I need to read some more - just a few clues would help a lot!!!
mr coffee