Question about the Line input and silence detection section

My project is a church clock (already operational for years , that i have now been asked to modfiy it by adding the options to play a set of chimes for either wedding, funeral or general sevrvice, this has been complicated by a request to include a line input section and later bluetooth (just to make use of amplifier at other times.

My problem is , i last coded an arduino in 2015 and then as a beginner, (still at that stage now but learning by doing , so my knowledge is still limited)

The problem i have is in trying to monitor the line input for audio (or lack of) so that i can give back amplifier control to either the hourly clock chime or the bells selections (these sections all function (may not be the best coded ,happy for any advice on it).

the code i tried uses a dc bias simple circuit of a voltage divder (2 x 10k resistors) and a 1mf capacitor to feed the audio in. I realise after testing the code seprately that its demo code, is there a better way to write it, or another method i could try to acheive what i need. As it is now if line input is selected i cant figure a way to disconnect it while it is possibly still in use.

on the seperate test i can get readings in serial monitor but they dont go to 512 (approx) on silence , I am using a cd player line sockets for the audio feed which should be at least 1v p-p.


```cpp
/***********************************************************/
//church bells control 08/04/2024 part of clock / bells / bt & line in system
// Hardware: yx5300, relays 2 x dpdt, plus 1 x amplifier control relay, 5 puhsbuttons,
// Board:  Arduino Nano x2 in finshed version.
//


#include <SoftwareSerial.h>
#define ARDUINO_RX 5  //should connect to TX of the Serial MP3 Player module
#define ARDUINO_TX 6  //connect to RX of the module
SoftwareSerial mySerial(ARDUINO_RX, ARDUINO_TX);
static int8_t Send_buf[8] = { 0 };
static uint8_t ansbuf[10] = { 0 };  // Buffer for the answers.    // BETTER LOCALLY
String mySerialAnswer;              // Answer from the MP3.

/************ Command byte **************************/
#define CMD_NEXT_SONG 0X01  // Play next song.
#define CMD_PREV_SONG 0X02  // Play previous song.
#define CMD_PLAY_W_INDEX 0X03
#define CMD_VOLUME_UP 0X04
#define CMD_VOLUME_DOWN 0X05
#define CMD_SET_VOLUME 0X06

#define CMD_SNG_CYCL_PLAY 0X08  // Single Cycle Play.
#define CMD_SEL_DEV 0X09
#define CMD_SLEEP_MODE 0X0A
#define CMD_WAKE_UP 0X0B
#define CMD_RESET 0X0C
#define CMD_PLAY 0X0D
#define CMD_PAUSE 0X0E
#define CMD_PLAY_FOLDER_FILE 0X0F

#define CMD_STOP_PLAY 0X16
#define CMD_FOLDER_CYCLE 0X17
#define CMD_SHUFFLE_PLAY 0x18   //
#define CMD_SET_SNGL_CYCL 0X19  // Set single cycle.

#define CMD_SET_DAC 0X1A
#define DAC_ON 0X00
#define DAC_OFF 0X01
#define CMD_SEL_DEV 0X09
#define DEV_TF 0X02

#define CMD_PLAY_W_VOL 0X22
#define CMD_PLAYING_N 0x4C
#define CMD_QUERY_STATUS 0x42
#define CMD_QUERY_VOLUME 0x43
#define CMD_QUERY_FLDR_TRACKS 0x4e
#define CMD_QUERY_TOT_TRACKS 0x48
#define CMD_QUERY_FLDR_COUNT 0x4f

const int clkChime = 2;       // clock chime amp trigger set
const int lineRelay = 3;      // line input switching relay
const int switch4Pin = 4;     // line input selector switch
const int switch1Pin = 7;     // S1 switch connected to digital pin 7
const int switch2Pin = 8;     // S2 switch connected to digital pin 8
const int switch3Pin = 9;     // S3 switch connected to digital pin 9
const int ampMute = 10;       // amp mute relay control
const int relaycontrol = 11;  // clock / bells audio switch relay
const int w1Led = A1;         // A1 to A4 button leds
const int w2Led = A2;         // A1 to A4 button leds
const int w3Led = A3;         // A1 to A4 button leds
const int w4Led = A4;         // A1 to A4 button leds
bool state = true;

unsigned long previousMillis = 0;  // will store last time LED was updated
const long interval = 200;

// analogue sense init.
// Global Variables
int Bias = 512;           //Nominally half of the 1023 range = 512.  Adjust as necessary
int NoiseThreshold = 6;  //Increase to minimize false triggers with silence or background noise
int Analog;               // The analog reading (with the bias subtracted-out)
int Max;                  // The waveform peak over a short period of time
int Average;              // A "sampled" moving average of Max values used as the LED-on threshold (not the true-average).

unsigned long ReadStartTime;   //millis() used to set time
int SampleTime = 50;           //Sample for short time to find waveform peak
unsigned long ArrayStartTime;  //millis() again
int ArrayTime = 1000;          //Update array once per second

const int ArraySize = 20;     // 20 values in the moving-average array
int ArrayIndex = 0;           // Index/pointer
int AverageArray[ArraySize];  // Saves a sample of 20 Max values for averaging

//Function prototype
int UpdateAverage(int Max);  //UpdateAverage() function prototype

// end of analogue sense init

void setup() {
  pinMode(switch1Pin, INPUT_PULLUP);  // Set the S1 switch pin as input with internal pull-up resistor enabled
  pinMode(switch2Pin, INPUT_PULLUP);  // Set the S2 switch pin as input with internal pull-up resistor enabled
  pinMode(switch3Pin, INPUT_PULLUP);  // Set the S3 switch pin as input with internal pull-up resistor enabled
  pinMode(switch4Pin, INPUT_PULLUP);  // Set the S4 switch pin as input with internal pull-up resistor enabled
  pinMode(relaycontrol, OUTPUT);      // Set the relaycontrol pin as output
  pinMode(lineRelay, OUTPUT);         // Set the line in sellector relay pin as output
  pinMode(clkChime, INPUT_PULLUP);    // Set the clock module amp in pin as input
  pinMode(ampMute, OUTPUT);
  digitalWrite(relaycontrol, HIGH);
  pinMode(w1Led, OUTPUT);         // Set the switch LED as output
  pinMode(w2Led, OUTPUT);         // Set the switch LED as output
  pinMode(w3Led, OUTPUT);         // Set the switch LED as output
  pinMode(w4Led, OUTPUT);         // Set the switch LED as output
  digitalWrite(w1Led, LOW);       // Set the switch LED off initially
  digitalWrite(w2Led, LOW);       // Set the switch LED off initially
  digitalWrite(w3Led, LOW);       // Set the switch LED off initially
  digitalWrite(w4Led, LOW);       // Set the switch LED off initially
  digitalWrite(lineRelay, HIGH);  //initial state of line in relay output
  mySerial.begin(9600);
  Serial.begin(9600);
  delay(500);                        //Wait chip initialization is complete
  sendCommand(CMD_SEL_DEV, DEV_TF);  //select the TF card
  delay(500);                        //wait for 200ms

 
  for (int i = 0; i < 20; i++)
    AverageArray[i] = 0;  //initialize the array with zeros
}



void loop() {
  int switch1State = digitalRead(switch1Pin);  // Read the state of S1 switch
  int switch2State = digitalRead(switch2Pin);  // Read the state of S2 switch
  int switch3State = digitalRead(switch3Pin);  // Read the state of S3 switch
  int switch4State = digitalRead(switch4Pin);  // Read the state of S3 switch
  int lineInState = digitalRead(lineRelay);    // Read the state of line input relay output
  int relayState = digitalRead(relaycontrol);  // read state of main amp / audio path relay
  unsigned long currentMillis = millis();


  if (switch1State == LOW && (relayState == 1)) {  // Check if S1 switch is pressed and if relaycontrol is high
    if (currentMillis - previousMillis >= interval) {
      previousMillis = currentMillis;
      digitalWrite(lineRelay, HIGH);
      digitalWrite(relaycontrol, LOW);
      switchLed1();
      if (currentMillis - previousMillis >= interval)
        previousMillis = currentMillis;
    }
    sendCommand(CMD_PLAY_W_VOL, 0X1E01);  //play the frirst track with volume 30 class
  }

  if (switch2State == LOW && (relayState == 1)) {  // Check if S2 switch is pressed and if relaycontrol is high
    if (currentMillis - previousMillis >= interval) {
      previousMillis = currentMillis;
      digitalWrite(lineRelay, HIGH);
      digitalWrite(relaycontrol, LOW);
      switchLed2();
      if (currentMillis - previousMillis >= interval)
        previousMillis = currentMillis;
    }
    sendCommand(CMD_PLAY_W_VOL, 0X1E02);  //play the second track withme 30 class
  }

  if (switch3State == LOW && (relayState == 1)) {  // Check if S3 switch is pressed and if relaycontrol is high
    if (currentMillis - previousMillis >= interval) {
      previousMillis = currentMillis;
      digitalWrite(lineRelay, HIGH);
      digitalWrite(relaycontrol, LOW);
      switchLed3();
      if (currentMillis - previousMillis >= interval)
        previousMillis = currentMillis;
    }
    sendCommand(CMD_PLAY_W_VOL, 0X1E03);  //play the second track with volume 30 class
  }
  if (switch4State == LOW && (relayState == 1)) {  // Check if S4 switch is pressed and if relaycontrol is high
    if (currentMillis - previousMillis >= interval) {
      previousMillis = currentMillis;
      digitalWrite(relaycontrol, HIGH);
![BLOCKdChurch|690x297](upload://7GZezcjiWzOQoa8mI6Jib9HslP6.jpeg)

      digitalWrite(lineRelay, LOW);  //line in relay on
      switchLed4();
      if (currentMillis - previousMillis >= interval)
        previousMillis = currentMillis;
    }
    sendCommand(CMD_PAUSE, 0);
  }

  ampControl();

  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;
    decodemySerialAnswer();
    if (state == 0) {
      digitalWrite(relaycontrol, HIGH);
      digitalWrite(lineRelay, HIGH);
      state = 1;
      switchLedclear();

      // line in analogue sense (silence)
      Max = 0;
      //Initilize/reset before running while() loop
      ReadStartTime = millis();  //Save/update loop-starting time

      while (millis() - ReadStartTime < SampleTime) {
        Analog = abs(analogRead(A0) - Bias);  // Read, take out the 2.5V bias/offset, make positive.

              if (Analog > Max)  //Find Max before exiting loop
          Max = Analog;
      }  // End waveform peak loop

       if (Average < NoiseThreshold)             // Make sure LED is off with silence or background noise
    Average = NoiseThreshold;         

  if(Max > Average)                         //If the latest Max reading is > average, turn-on the LED
    digitalWrite(LED_BUILTIN, HIGH);        //Turn the LED on
  else  
    digitalWrite(LED_BUILTIN, LOW);         //Turn the LED off

  if (millis() - ArrayStartTime > ArrayTime)  // Time to update array?
    Average = UpdateAverage(Max);            // Call the UpdateAverage() function once per second

      int lineInState = digitalRead(lineRelay);

      if ((Average >= 20 ) && (lineInState == LOW))
        digitalWrite(lineRelay, HIGH);
        digitalWrite(ampMute, LOW);       //Turn the relay off to test , will be other way around when corredct relay used
        //digitalWrite(LED_BUILTIN, HIGH);  //Turn the LED off

      // end analogue sense 
    } 
  } 
} 


void sendCommand(int8_t command, int16_t dat) {
  delay(20);
  Send_buf[0] = 0x7e;                //starting byte
  Send_buf[1] = 0xff;                //version
  Send_buf[2] = 0x06;                //the number of bytes of the command without starting byte and ending byte
  Send_buf[3] = command;             //
  Send_buf[4] = 0x01;                //0x00 = no feedback, 0x01 = feedback
  Send_buf[5] = (int8_t)(dat >> 8);  //datah
  Send_buf[6] = (int8_t)(dat);       //datal
  Send_buf[7] = 0xef;                //ending byte
  for (uint8_t i = 0; i < 8; i++)    //
  {
    mySerial.write(Send_buf[i]);
  }
}


/*Function decodeMP3Answer: Decode MP3 answer.                                  */
/*Parameter:-void                                                               */
/*Return: The                                                  */

String decodemySerialAnswer() {
  String decodedmySerialAnswer = "";


  decodedmySerialAnswer += sanswer();

  switch (ansbuf[3]) {

    case 0x3D:
      decodedmySerialAnswer += " -> Completed play num " + String(ansbuf[6], DEC);
      if ((ansbuf[3] == 0x3D))
        ;
      {
        state = false;  // flag for end of track
        break;
      }

    case 0x4C:
      decodedmySerialAnswer += " -> Playing: " + String(ansbuf[6], DEC);
      break;
  }

  return decodedmySerialAnswer;
}


/*Function: sbyte2hex. Returns a byte data in HEX format.                 */
/*Parameter:- uint8_t b. Byte to convert to HEX.                                */
/*Return: String                                                                */


String sbyte2hex(uint8_t b) {
  String shex;

  shex = "0X";

  if (b < 16) shex += "0";
  shex += String(b, HEX);
  shex += " ";
  return shex;
}


/*Function: sanswer. Returns a String answer from mp3 UART module.          */
/*Parameter:- uint8_t b. void.                                                  */
/*Return: String. If the answer is well formated answer.                        */

String sanswer(void) {
  uint8_t i = 0;
  String mySerialAnsweranswer = "";

  // Get only 10 Bytes
  while (mySerial.available() && (i < 10)) {
    uint8_t b = mySerial.read();
    ansbuf[i] = b;
    i++;

    mySerialAnswer += sbyte2hex(b);
  }

  // if the answer format is correct.
  if ((ansbuf[0] == 0x7E) && (ansbuf[9] == 0xEF)) {
    return mySerialAnswer;
  }

  return "???: " + mySerialAnswer;
}

//analogues sense

// UpdateAverage() function =================================================================================
// Takes-in latest Max reading, updates the array, returns the average


int UpdateAverage(int Max) {
  int Sum = 0;                     // Initialize/reset Sum before calculating average
  AverageArray[ArrayIndex] = Max;  //Update one array element with the latest Max

  for (int i = 0; i < 20; i++)  //Sum-up the data in the array
  {
    Sum = Sum + AverageArray[i];
  }

  Average = Sum / 20;  // Find average of the saved Max values

  ArrayIndex++;  //Next index for next time
  if (ArrayIndex > 19)
    ArrayIndex = 0;  //Back to the beginning of the circuar buffer

  ArrayStartTime = millis();  //New Array Start Time

  return Average;
}

// end analogue sense


void switchLed1() {
  digitalWrite(w1Led, HIGH);
  digitalWrite(w2Led, LOW);
  digitalWrite(w3Led, LOW);
  digitalWrite(w4Led, LOW);
}


void switchLed2() {
  digitalWrite(w1Led, LOW);
  digitalWrite(w2Led, HIGH);
  digitalWrite(w3Led, LOW);
  digitalWrite(w4Led, LOW);
}


void switchLed3() {
  digitalWrite(w1Led, LOW);
  digitalWrite(w2Led, LOW);
  digitalWrite(w3Led, HIGH);
  digitalWrite(w4Led, LOW);
}


void switchLed4() {
  digitalWrite(w1Led, LOW);
  digitalWrite(w2Led, LOW);
  digitalWrite(w3Led, LOW);
  digitalWrite(w4Led, HIGH);
}

void switchLedclear() {
  digitalWrite(w1Led, LOW);
  digitalWrite(w2Led, LOW);
  digitalWrite(w3Led, LOW);
  digitalWrite(w4Led, LOW);
}

void ampControl() {
  int relayState2 = digitalRead(relaycontrol);
  int lineInState2 = digitalRead(lineRelay);
  int clkChime2 = digitalRead(clkChime);
  if (relayState2 == LOW || lineInState2 == LOW || clkChime2 == HIGH) {
    digitalWrite(ampMute, HIGH);  //  nb reverse logic for test with active high relay
  } else {
    digitalWrite(ampMute, LOW);
  }
}

Where did you get the code, and what exactly is the circuit? Post a ,ink to it if it's someone else's work, or post the sketch and even a hand drawn schematic.

Forget the rest of the code for the moment, and focus just on being able to, say, illuminate one LED when the channel is quiet, and another when it is not. Super simlple, no distractions.

Ok I read through the code you posted and see that a substantial portion is given to this detecting.

I think you could do better on the input side, and I think a different filtering approach would be better, specifically a low pass filter, very easy to implement and might detect better than a simple average.

Or…


There are a few variations on this module. I can't speak for any, and the cost is so low I wonder if they hope one of the five will even work. But ppl use it or that which it is a counterfeit of alla time.

a7

thanks for the reply , the code i found was this below, which i realise now is over complicated , i tried posting a block diagram of the system but it just put up a sort of link is that what it will do? , but i will draw the circuit by hand, and will do what you suggest with lighting just one led

i cant use a mic sound detector as the speakers are in the bell tower of the church , could you give me an example of a low pass filter , i will google as well and try that also

//==============================================================================================================
// SimplestEffect.ino
// "World's simplest" sound activated lighting effect
// Flickers the built-in pin-13 LED with the sound.  
// The LED flashes-on when the signal is above the moving average and off when below average.
// The LED is on half of the time for a good effect with loud or quiet songs.
// Works with a line-level or headphone-level signal.
// As usual, the input is biased at Vcc/2 for a reading of ~512 with no signal.
// Also works with most microphone boards that have amplified & biased outputs.
// Do NOT connect a "speaker" output as these can exceed the 0-5V limits and fry the Arduino
// It uses a 20-second moving average.  This array contains 20 "sampled" Max readings, not "the" maximum and not "the average".
// 20 seconds allows it to automatically adjust/calibrate to volume changes without getting out of calibration between songs. 
// With music or other "program material" wait 20 seconds for it to self-calibrate.
// Reads input A0


//============================================================================================================== 
// Global Variables
int Bias = 512;                           //Nominally half of the 1023 range = 512.  Adjust as necessary
int NoiseThreshold = 30;                   //Increase to minimize false triggers with silence or background noise
int Analog;                               // The analog reading (with the bias subtracted-out)
int Max;                                  // The waveform peak over a short period of time
int Average;                              // A "sampled" moving average of Max values used as the LED-on threshold (not the true-average).

unsigned long ReadStartTime;             //millis() used to set time
int SampleTime = 50;                     //Sample for short time to find waveform peak 
unsigned long ArrayStartTime;            //millis() again 
int ArrayTime = 1000;                    //Update array once per second 

const int ArraySize = 20;                // 20 values in the moving-average array
int ArrayIndex = 0;                      // Index/pointer
int AverageArray[ArraySize];             // Saves a sample of 20 Max values for averaging

//Function prototype
int UpdateAverage(int Max);               //UpdateAverage() function prototype

int ledOn = 9;
int lightLed = 10;
int LED = 1; 
int Test = 0;


//==============================================================================================================  
void setup()
{   
  pinMode(LED_BUILTIN, OUTPUT);        // initialize digital pin LED_BUILTIN as an output.
  pinMode (lightLed, OUTPUT);
  pinMode (ledOn, INPUT_PULLUP);

  Serial.begin(9600);

  for(int i = 0; i < 20; i++)
    AverageArray[i] = 0;              //initialize the array with zeros 
}
 

// Start main loop ============================================================================================
void loop()
{
  Max = 0;                                  //Initilize/reset before running while() loop
  ReadStartTime = millis();                 //Save/update loop-starting time

  // Find waveform peak loop ==================================================================================
  // Takes readings in a "fast loop" to find the waveform peak.
  // At 20Hz a half-cycle is 25mS, so 25ms is the minimum time to find the peak (at deep bass frequencies).
  // A longer sample of about 100mS may work better with incancescant lamps (allowing the light to reach full-brightness).  
  
  while (millis() - ReadStartTime < SampleTime)
  {
    Analog = abs(analogRead(A0) - Bias);                 // Read, take out the 2.5V bias/offset, make positive. 

    if (Analog > Max)                                    //Find Max before exiting loop 
      Max = Analog; 
  }// End waveform peak loop ==================================================================================

  //TURN THE LED ON/OFF =================================================================================== 
  if (Average < NoiseThreshold)             // Make sure LED is off with silence or background noise
    Average = NoiseThreshold;         

  if(Max > Average)                         //If the latest Max reading is > average, turn-on the LED
    digitalWrite(LED_BUILTIN, HIGH);        //Turn the LED on
  else  
    digitalWrite(LED_BUILTIN, LOW);         //Turn the LED off

  if (millis() - ArrayStartTime > ArrayTime)  // Time to update array?
    Average = UpdateAverage(Max);            // Call the UpdateAverage() function once per second

    LED =0;
    if( (Max ==3) && (Test ==0) )
     LED = Max;
    //Serial.print ("led value = ");
     // Serial.println (LED);

}  // End of main loop ==========================================================================================
 


// UpdateAverage() function =================================================================================
// Takes-in latest Max reading, updates the array, returns the average
int UpdateAverage(int Max) 
{ 
  int Sum = 0;    // Initialize/reset Sum before calculating average
  AverageArray[ArrayIndex] = Max;                //Update one array element with the latest Max 

  for(int i = 0; i < 20; i++)                    //Sum-up the data in the array
  {
    Sum = Sum + AverageArray[i];  
  }

  Average = Sum/20;                              // Find average of the saved Max values

  ArrayIndex++;                                  //Next index for next time
  if (ArrayIndex > 19)
    ArrayIndex = 0;                              //Back to the beginning of the circuar buffer

  //Print information (Optional, once per second for testing/debugging)
  Serial.print (" Average = ");
 Serial.print (Average);
    Serial.print (" Max = ");
       Serial.println (Max);
        Serial.print (" Analog = ");
          Serial.println (Analog);
  
  ArrayStartTime = millis();                     //New Array Start Time  
  
  return Average;        
} // End UpdateAverage() =========================================

Oops, I see.

This thread/post has more what I would expect to see for audio detecting. When I am at a real computer I will look, it is possible the cheap moduke develops its digital sound-no sound output in such a way as the mice can be bypassed.

I will link to the filter demo when I find it. It is known colloquially as the "leaky integrator" and as I might have said, naturally gives more weight to recent readings.

a7

Ok so i did what you suggested to strip this right back , i found part of this code on the forum and just modified a few lines to light an led , its pretty consistent in its results , but if canj be made more stable with a low pass filter and sort the logic for how to sense when no audio while giving time to allow for gaps in speech or music , work out how long for the silence to be present before i disable the line input feed, i can test the presence when the clock needs to chime , if the bells section(wedding etc) button is pressed it overrides the line in anyway , as its an event done by human intervention and so must be ok.


```cpp
int analogPin = A0; 
int val = 0; 
int timer = 0;
int maxi = 0;
int noAudio;

void setup() {
  Serial.begin(9600); 
  pinMode (LED_BUILTIN, OUTPUT);
   digitalWrite(LED_BUILTIN, LOW);

}

void loop() {
  val = abs (analogRead(analogPin) - 511); 
  noAudio = val;

    
     
     
  if (val<0){  
    val = -val;
  }

  if (maxi<val) {
    maxi = val;
  }

  delay(10);
  timer = timer + 1;



  if (timer>50){  
    Serial.println(maxi); 
    maxi = 0;
    timer = 0;
  
if (noAudio <=2) {
     digitalWrite(LED_BUILTIN, HIGH);
     } else {
     digitalWrite(LED_BUILTIN, LOW);
     Serial.println(noAudio); 
   
      
  }
}
}

OK, good.

Now the sketch you posted is useful for seeing the maximum value over a window period, but it reacts to only one reading, the last of the fifty that are scheduled at 10 millisecond intervals. As far as the LED behavoiur goes, this is similar, except it will flicker the LED as it reports:

void loop() {
  val = abs (analogRead(analogPin) - 511); 
  noAudio = val;

  if (noAudio <=2) {
    digitalWrite(LED_BUILTIN, HIGH);
  }
  else {
    digitalWrite(LED_BUILTIN, LOW);
    Serial.println(noAudio); 
  }
}

So a variety of conditioning or filtering could be done to develop a sound/no sound decision variable, true or false.

Then that signal can be the input to a higher level of processing. So there is sound, maybe that means switching on the LED (and whatever else) as long as there has been sound within the last N seconds. This is easy and can be modeled and tested with a pushbutton acting as proxy for what will be the sound/no sound flag.

I see the threshold for noAudio is quite low, a few units off the DC biased audio is all it takes. This absolute value is what might be filtered, here is the examlke of the leaky integration and perhaps your introduction to the wokwi simukator. Take the further link in my post and play with it.


The usual signal in this case would be coming from having rectified and filtered the audio in hardware, that is what is going on in the circuit on the thread I linked previously. It could be as simple as a capacitor, resistor and diode if, for example, you were dealing with lone level audio. This is above my pay grade so let us hope one of the heavies is reading along and jumps in.

Here it might be worth just leaky integrating the direct capture of the absolute value of the instant audio level.

Sry I cannot reproduce your input and circuit. Try the leaky integrator with a simple delay(x) to fix the loop rate, so you'd have a few parameters to vary for some experiments - loop rate, the integrator convergence constant and the threshold that is audio/noAudio.

As for the second part, keeping the light on for a stab meant to roll over gaps of some kind in the audio input, I have a demo for that I'll try to find faster. It's dead easy and should be something you know how to do no matter it is useful or not here.

Looking now.

a7

OK, someone who refuses to be named found it.

In the demo, the LED stays on as long as the button is being pressed. Release the button and stay off of it, the LED remains in for a set period.

I hope you can see this logic serving to keep the audio switched somewhat firmly. Again, the time constant would be something to tune when it is functioning. A few seconds.

Now it occurs to me that a noise gate might work well. So I'll have her look for that (!), might be a bit spendy.

a7

Ok i will sit and read my way through what you have just sent , i tried a little more with the simple code as well (see below)
one thing i did realise as i was using this with the led once the level drops and the led is lit , it will release a relay , that drops the line input connection back to clock or bells use (which is what i want) line input selection again would have to be by human intervention (button press) , whish is why i need to know (as far as practical ) that the line input use by the user is no longer needed for now, if that makes sense .
i want to make it as error proof as possible so avoiding false silences is important .
Thank you for all the time you are giving me to this , thats appreciated , i will go read all the new stuff you have sent me .


```cpp
int analogPin = A0;
int val = 0;
int timer = 0;
int maxi = 0;
int noAudio;

void setup() {
  Serial.begin(9600);
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, LOW);
}

void loop() {
  val = abs(analogRead(analogPin) - 511);
  noAudio = val;




  if (val < 0) {
    val = -val;
  }

  if (maxi < val) {
    maxi = val;
  }

  Serial.println(maxi);
  maxi = 0;

const unsigned long interval = 5 * 60 * 1000L;     // 2 minutes
    static unsigned long lastTime;
    unsigned long msec = millis ();
    if (msec - lastTime >= interval)  {
        lastTime = lastTime + interval;

    if (noAudio <= 4) {
      digitalWrite(LED_BUILTIN, HIGH);
    } else {
      digitalWrite(LED_BUILTIN, LOW);
      Serial.println(noAudio);
    }

  }
}

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.