Math is not my thing; help, please?!

wapo54001

Senior Member
I am designing a board for audio line-level (preamp) equipment that is intended to prevent large startup and shutdown pulses from reaching the power amp, and I’m trying to make it fairly universal by compensating for power supply voltages of 10~30 volts and permitting user selected startup delays of zero to 60 seconds (in evenly split wiper travel ranges of 0~10 and 10~60 seconds) and adjustable instantaneous shutdown when power supply level drops to a chosen point in the range of 50% to 100% of nominal.

I’ve got the dual-range startup delay done, it was pretty simple.

For me, the shutdown when power voltage drops to a certain percentage of normal is another matter. From looking at it, the range of values I have to deal with – small to large -- seem to prevent me from using my normal brute-force Picaxe math without sacrificing accuracy at the lower values. Any help or suggestions greatly appreciated! (schematic attached).

For this task, I have two inputs:

A: A 10K linear potentiometer across the Picaxe 5V supply which is used to select the cutoff value (a percentage of nominal supply) in the range of 50~100% of normal input voltage by using readADC10 to find the percentage of the 5V supply as selected by the potentiometer (0~1023 = 50%~100%).

B: The 10~30V supply goes through a voltage divider of 10K and 2K resistors so that the readADC10 voltage at the Picaxe chip will be 5V at 30V supply and about 1.66V at 10V supply. This reading has two functions:

1) at startup, to determine nominal power supply voltage, the voltage is read several times over a few seconds, and

2) to continuously check the voltage in a tight loop during operation to immediately disconnect the audio output relay (5V latching) whenever the power supply voltage drops below the threshold which was previously determined per the (A) potentiometer either due to power disconnection or as selected by a manual “mute” switch which is also connected to the junction of the two resistors.

How can I do the needed calculations with precision to accurately cover the entire range of possibilities and wind up with a count that I can compare to the instantaneous readADC10 reading per (B) Is there a clean way to deal with these fractions?
 

Attachments

hippy

Technical Support
Staff member
All untested but I believe the theory is sound.

This will allow you to read your instantaneous PSU voltage as a 'psu' word value between 0 and 65535 which is the maximum of 16-bit, so highest resolution -
Code:
ReadPsu:
  ReadAdc10 PSU_ADC, psu       ; 0000 00ab cdef ghij
  psu = psu * 64               ; abcd efgh ij00 0000
  psu = psu / $0400 | psu      ; abcd efgh ijab cdef
  Return
You can determine what the 'nominal' PSU voltage word value is by averaging the 'psu' value or by determining its maximum over a number of cycles. I would favour the later -
Code:
CalculateNominalAverage:
  nominal = 0
  For w0 = 1 To 64
    Gosub ReadPsu
    nominal = psu / 64 + nominal
  Next
  Return
Code:
CalculateNominalMax:
  nominal = 0
  For w0 = 1 To 64
    Gosub ReadPsu
    If psu > nominal Then
      nominal = psu
    End If
  Next
  Return
From the pot you can calculate a 50% to 100% of a 65535 value and pretend that was the 'pot' reading -
Code:
ReadPot:
  ReadAdc10 POT_ADC, pot       ; 0000 00ab cdef ghij
  pot = pot * 32 + $8000       ; 1abc defg hij0 0000
  pot = pot / $0800 | pot      ; 1abc defg hij1 abcd
  Return
We could potentially calculate what the 'cutoff' value for the nominal voltage would be from a 'pot' value of 0 to 65535 with -

cutoff = nominal * pot / 65535

But alas, overflow. However we can pretend 65535 was actually 65536 and use the '**' operator without much loss of accuracy -
Code:
CalculateCutOff:
  cutoff = nominal ** pot      ; cutoff = nominal * pot / 65536
  Return
So putting that all together, something like -
Code:
MainLoop:
  Gosub CalculateNominalMax
  Do
    Gosub ReadPsu
    Gosub ReadPot
    Gosub CalculateCutOff
    If psu < cutoff Then
      Gosub KillThePower
    End If
  Loop
 

wapo54001

Senior Member
All untested but I believe the theory is sound.

This will allow you to read your instantaneous PSU voltage as a 'psu' word value between 0 and 65535 which is the maximum of 16-bit, so highest resolution -
Code:
ReadPsu:
  ReadAdc10 PSU_ADC, psu       ; 0000 00ab cdef ghij
  psu = psu * 64               ; abcd efgh ij00 0000
  psu = psu / $0400 | psu      ; abcd efgh ijab cdef
  Return
You can determine what the 'nominal' PSU voltage word value is by averaging the 'psu' value or by determining its maximum over a number of cycles. I would favour the later -
Code:
CalculateNominalAverage:
  nominal = 0
  For w0 = 1 To 64
    Gosub ReadPsu
    nominal = psu / 64 + nominal
  Next
  Return
Code:
CalculateNominalMax:
  nominal = 0
  For w0 = 1 To 64
    Gosub ReadPsu
    If psu > nominal Then
      nominal = psu
    End If
  Next
  Return
From the pot you can calculate a 50% to 100% of a 65535 value and pretend that was the 'pot' reading -
Code:
ReadPot:
  ReadAdc10 POT_ADC, pot       ; 0000 00ab cdef ghij
  pot = pot * 32 + $8000       ; 1abc defg hij0 0000
  pot = pot / $0800 | pot      ; 1abc defg hij1 abcd
  Return
We could potentially calculate what the 'cutoff' value for the nominal voltage would be from a 'pot' value of 0 to 65535 with -

cutoff = nominal * pot / 65535

But alas, overflow. However we can pretend 65535 was actually 65536 and use the '**' operator without much loss of accuracy -
Code:
CalculateCutOff:
  cutoff = nominal ** pot      ; cutoff = nominal * pot / 65536
  Return
So putting that all together, something like -
Code:
MainLoop:
  Gosub CalculateNominalMax
  Do
    Gosub ReadPsu
    Gosub ReadPot
    Gosub CalculateCutOff
    If psu < cutoff Then
      Gosub KillThePower
    End If
  Loop
O.M.G.

Well, I have a much better chance of understanding this than I would have had to create it myself but it's still a challenge!

I'm already beginning to follow but need to study it more. It's the overflow issue that stopped me, I need to look at this for a while to understand. I remembered that the "**" existed from reading about it long, long ago, but there is no way I could have used it today.

hippy, thanks for this, I need to go away and really look at it and refer back to the manual.

PS I don't know if anyone noticed but in the schematic I posted the wiring of the relay device was not ideal. The preferred method is to simply ground the signal output of the preamp to signal ground as per this corrected schematic.
 

Attachments

hippy

Technical Support
Staff member
PS I don't know if anyone noticed but in the schematic I posted the wiring of the relay device was not ideal.
I hadn't spotted that. I would be more concerned about driving the relay direct from two I/O pins, wondering how much strain is being put on those. Using a transistor or FET would remove that concern.

I would also be a little concerned about the 5V regulator dropping 25V from 30V. If that's a linear regulator that can be quite a lot of power to dissipate even at lower currents and some aren't rated for such input voltages.
 

wapo54001

Senior Member
I would be more concerned about driving the relay direct from two I/O pins, wondering how much strain is being put on those. Using a transistor or FET would remove that concern.

I would also be a little concerned about the 5V regulator dropping 25V from 30V. If that's a linear regulator that can be quite a lot of power to dissipate even at lower currents and some aren't rated for such input voltages.
Well, I confess that I have no training in electronics so it's all practical assumptions on my part. Please point out any flaws in my reasoning below.

Since the relay is the latching variety, using a FET would be quite complicated and, I hope, unnecessary.

The relay is 5V 20mA, drawing current during switching only, and the coil is 250R. The relay 'must switch' voltage is 3.75V and it switches in less than 4 milliseconds. Other than the moment of switching the circuit draws no current other than capacitor leakage of C3. So, maximum current is less than 20mA (since logic doesn't rise to the full 5V level) and the real duration of current flow is the time it takes to charge/discharge the 120uF capacitor. I reduce the load on the Picaxe pins (rated at 20mA max per pin) by using 2 pins (always switching to INPUT before switching between HIGH and LOW). Since the relay takes several milliseconds to switch and I assume the Picaxe pins change state in microseconds, I'm assuming that my technique is at least somewhat useful and provides a theoretical 40mA of source to drive the 20mA required by the relay over most of the time that the relay is drawing current. I didn't use balancing resistors, maybe that's a problem?

I did some experimenting with an earlier design that does not include the adjustable variables. With regard to the power supply, the circuit at rest (relay not switching) draws a measured 4mA. When the relay switches the current does spike momentarily to, I assume, 4mA+20mA =24mA, though I cannot see it because I gave up my 'scope when we moved to our retirement community. But I think that calculates to regulator dissipation of 0.1W continuous and 0.6W for less than one second on a very intermittent basis. It seems that most simple 3-pin fixed 5V regulators are rated for 30V input for 5V out, a maximum of 100mA, and internally limited power out.

I'm working through your code from above, converting the hex to decimal (thinking in hex is beyond me!) and beginning to see what you've done. The "**" and "|" manipulations will probably remain forever above my paygrade. :(
 

regpye

New Member
I would also be a little concerned about the 5V regulator dropping 25V from 30V. If that's a linear regulator that can be quite a lot of power to dissipate even at lower currents and some aren't rated for such input voltages.
I had the same on a few of my solar powered projects, the high voltage coming off a solar array was just too much for the 5V reg and I found that if I inserted a 10V reg before the 5V reg it overcame the problem.
Maybe not the best way to do it, but it works fine for me.
 

hippy

Technical Support
Staff member
I found that if I inserted a 10V reg before the 5V reg it overcame the problem.
Maybe not the best way to do it, but it works fine for me.
'Divide and conquer', spreading the drop through a series of regulators, usually does work. The main argument for not doing that is it can end up wasting a huge amount of energy as heat, but it's not so bad when it's overcoming a voltage issue for something which doesn't need much current.

The recommended solution would usually be something switch-mode which is much more energy efficient when efficiency is more important.
 

wapo54001

Senior Member
'Divide and conquer', spreading the drop through a series of regulators, usually does work. The main argument for not doing that is it can end up wasting a huge amount of energy as heat, but it's not so bad when it's overcoming a voltage issue for something which doesn't need much current.

The recommended solution would usually be something switch-mode which is much more energy efficient when efficiency is more important.
The LM340AZ seems to have a maximum input voltage of 35V which gives me a 5V cushion and, as has been noted, the current is typically 4-5mA baseline with very infrequent blips of 24mA for 10ms decreasing toward baseline over 90ms.

A switching regulator has drawbacks here -- potentially putting hash on the line in a quiet audio environment is one, the lack of through-hole devices for the target hobbyist group is another. The need to keep the pcb as small as possible makes the dual regulator solution undesirable. I could use a TO-220 but what overkill . . .
 
Top