Drums trigger LED with a Mic

Hi!
First of all, I have no clue of what is going on with code and etc.
I'm a drummer, and I wanted to make my drums light a LED for a millisecond, for a "blink", when I hit them.
I didn't find any service that make this stuff and sends it to my country, so I found a nice guide in a site called ADAFRUIT, and there they have a nice guide of how to make this happen, but not with a piezo sensor, but with a small mic.
The problem that there is too much bleed from other drums, so all the drums light up together when 1 drum being hit.
I wanted to switch the whole setup to a piezo, but I can't write any code and I failed to find one online that works, plus heard some stuff about piezo sending too much voltage, so I would like to avoid it.
Anyhow, I really want someone to help me to break down the code ADAFRUIT gave me, to understand which one of the unknowns is the one the it's value decides if to light up the LED, or not, and which lines is the one that decides the thershold.
At Adafruit I found no help, not from support even and not in the forums.
Cheers :slight_smile:

The code:


/* LED "Color Organ" for Adafruit Trinket and NeoPixel LEDs.

Hardware requirements:
 - Adafruit Trinket or Gemma mini microcontroller (ATTiny85).
 - Adafruit Electret Microphone Amplifier (ID: 1063)
 - Several Neopixels, you can mix and match
   o Adafruit Flora RGB Smart Pixels (ID: 1260)
   o Adafruit NeoPixel Digital LED strip (ID: 1138)
   o Adafruit Neopixel Ring (ID: 1463)

Software requirements:
 - Adafruit NeoPixel library

Connections:
 - 5 V to mic amp +
 - GND to mic amp -
 - Analog pinto microphone output (configurable below)
 - Digital pin to LED data input (configurable below)

Written by Adafruit Industries.  Distributed under the BSD license.
This paragraph must be included in any redistribution.
*/
#include <Adafruit_NeoPixel.h>

#define N_PIXELS  60  // Number of pixels you are using
#define MIC_PIN   A1  // Microphone is attached to Trinket GPIO #2/Gemma D2 (A1)
#define LED_PIN    0  // NeoPixel LED strand is connected to GPIO #0 / D0
#define DC_OFFSET  0  // DC offset in mic signal - if unusure, leave 0
#define NOISE     440  // Noise/hum/interference in mic signal
#define SAMPLES   60  // Length of buffer for dynamic level adjustment
#define TOP       (N_PIXELS +1) // Allow dot to go slightly off scale
// Comment out the next line if you do not want brightness control or have a Gemma
#define POT_PIN    3  // if defined, a potentiometer is on GPIO #3 (A3, Trinket only) 

byte
  peak      = 0,      // Used for falling dot
  dotCount  = 0,      // Frame counter for delaying dot-falling speed
  volCount  = 0;      // Frame counter for storing past volume data
  
int
  vol[SAMPLES],       // Collection of prior volume samples
  lvl       = 0,     // Current "dampened" audio level
  minLvlAvg = 0,      // For dynamic adjustment of graph low & high
  maxLvlAvg = 0;

Adafruit_NeoPixel  strip = Adafruit_NeoPixel(N_PIXELS, LED_PIN, NEO_GRB + NEO_KHZ800);

void setup() {
  //memset(vol, 0, sizeof(vol));
  memset(vol,0,sizeof(int)*SAMPLES);//Thanks Neil!
  strip.begin();
}
void loop() {
  uint8_t  i;
  uint16_t minLvl, maxLvl;
  int      n, height;
  n   = analogRead(MIC_PIN);                 // Raw reading from mic 
  n   = abs(n - 512 - DC_OFFSET);            // Center on zero
  n   = (n <= NOISE) ? 0 : (n - NOISE);      // Remove noise/hum
  lvl = ((lvl * 7) + n) >> 3;    // "Dampened" reading (else looks twitchy)
  
  // Calculate bar height based on dynamic min/max levels (fixed point):
  height = TOP * (lvl - minLvlAvg) / (long)(maxLvlAvg - minLvlAvg);

  if(height < 0L)       height = 0;      // Clip output
  else if(height > TOP) height = TOP;
  if(height > peak)     peak   = height; // Keep 'peak' dot at top

// if POT_PIN is defined, we have a potentiometer on GPIO #3 on a Trinket 
//    (Gemma doesn't have this pin)
  uint8_t bright = 255;   
#ifdef POT_PIN            
   bright = analogRead(POT_PIN);  // Read pin (0-255) (adjust potentiometer 
                                  //   to give 0 to Vcc volts
#endif
  strip.setBrightness(bright);    // Set LED brightness (if POT_PIN at top
                                  //  define commented out, will be full)
  // Color pixels based on rainbow gradient
  for(i=0; i<N_PIXELS; i++) {  
    if(i >= height)               
       strip.setPixelColor(i,   0,   0, 0);
    else 
       strip.setPixelColor(i,Wheel(map(i,0,strip.numPixels()-1,30,150)));
    } 

   strip.show(); // Update strip

  Serial.println (n),
  vol[volCount] = n;                      // Save sample for dynamic leveling

  if(++volCount >= SAMPLES) volCount = 0; // Advance/rollover sample counter

  // Get volume range of prior frames
  minLvl = maxLvl = vol[0];
  for(i=1; i<SAMPLES; i++) {
    if(vol[i] < minLvl)      minLvl = vol[i];
    else if(vol[i] > maxLvl) maxLvl = vol[i];
  }
  // minLvl and maxLvl indicate the volume range over prior frames, used
  // for vertically scaling the output graph (so it looks interesting
  // regardless of volume level).  If they're too close together though
  // (e.g. at very low volume levels) the graph becomes super coarse
  // and 'jumpy'...so keep some minimum distance between them (this
  // also lets the graph go to zero when no sound is playing):
  if((maxLvl - minLvl) < TOP) maxLvl = minLvl + TOP;
  minLvlAvg = (minLvlAvg * 63 + minLvl) >> 6; // Dampen min/max levels
  maxLvlAvg = (maxLvlAvg * 63 + maxLvl) >> 6; // (fake rolling average)
}

// Input a value 0 to 255 to get a color value.
// The colors are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
  if(WheelPos < 85) {
   return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
  } else if(WheelPos < 170) {
   WheelPos -= 85;
   return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  } else {
   WheelPos -= 170;
   return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
}

Hi

Imagine this led strip going around your battery....

I used a pro-mini, a sound sensor module and a strip with 60 LEDs.

" Imgur: The magic of the Internet "

That's quite a bit different from the Adafruit project with Neopixels. And a 1ms flash is too short to see and/or it will appear very dim.

I didn't completely study the code but the comments say the sensitivity adjusts automatically. That's more likely to give you false-triggers from other drums or other sounds.

There is a potential issue with what you're doing... The Arduino is only reading the input for one instant every time through the loop. Drum hits are very-short duration so you can easily miss the actual hit. The Neopixel stuff takes extra time, making the situation worse. The drum rings long-enough that you'll should be able to read it but if you increase the sensitivity too much, you'll get false triggers.

You can use interrupts (so you don't have to wait for the loop to come-around) but they need a digital input so you'd need additional circuitry to "condition" the trigger signal. There is also an analog circuit called a peak detector that can "stretch-out" the analog signal (for a few milliseconds) so the software will read it when it comes-around in the loop.

...I once made a little example project that's similar to what you said... It flashes one LED (no Neopixels) with "loudness", but it also has automatic adjustment. (The LED is on when the it's louder than average and off when it's below average. You can try my code as-is but if you can understand what it's doing you'll probably want to take-out all of the averaging stuff. There are other things you can take-out too...

The "important part" of my example is:

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

But again, you probably just want a fixed threshold instead of the average, and you might want to stretch-out the on-time for several milliseconds. But don't use delay() because you'll slow-up the loop and you are likely to miss some hits.

I think the way forward is to post your original code and circuit schematic where you got the sound bleed effect.
That seems to be the best way to start and get you to a point where you want to be.

1 Like

Thank you for the detailed explanation! really.
But sadly, I don't really get what you're saying.

  1. the Neopixels take time? when I upload the code i'v attached to my Gemma (the Adafruit platform) When I hit the drum it blink exactly as I will want it to, all the LEDs light up together and turn off together, for just the split second that I need. Works great in a dark room :slight_smile:
  2. Miss the actual hit? How?
  3. additional circuitry to "condition" the trigger signal?
  4. The example project you did sound like the simple code I need! just need to figure out how to change the number of LEDs that light up and delete the averages. Might be a headache for a guy like me but the sure sounds like a start! I'd be happy if you could post the code :smiley:

Thank you Mike,
Yea alright, i'l gladly post them

Here is the schematic: (I didn't use alligators, I'v soldered)

And heres the code:

/* LED "Color Organ" for Adafruit Trinket and NeoPixel LEDs.

Hardware requirements:
 - Adafruit Trinket or Gemma mini microcontroller (ATTiny85).
 - Adafruit Electret Microphone Amplifier (ID: 1063)
 - Several Neopixels, you can mix and match
   o Adafruit Flora RGB Smart Pixels (ID: 1260)
   o Adafruit NeoPixel Digital LED strip (ID: 1138)
   o Adafruit Neopixel Ring (ID: 1463)

Software requirements:
 - Adafruit NeoPixel library

Connections:
 - 5 V to mic amp +
 - GND to mic amp -
 - Analog pinto microphone output (configurable below)
 - Digital pin to LED data input (configurable below)

Written by Adafruit Industries.  Distributed under the BSD license.
This paragraph must be included in any redistribution.
*/
#include <Adafruit_NeoPixel.h>

#define N_PIXELS  60  // Number of pixels you are using
#define MIC_PIN   A1  // Microphone is attached to Trinket GPIO #2/Gemma D2 (A1)
#define LED_PIN    0  // NeoPixel LED strand is connected to GPIO #0 / D0
#define DC_OFFSET  0  // DC offset in mic signal - if unusure, leave 0
#define NOISE     100  // Noise/hum/interference in mic signal
#define SAMPLES   60  // Length of buffer for dynamic level adjustment
#define TOP       (N_PIXELS +1) // Allow dot to go slightly off scale
// Comment out the next line if you do not want brightness control or have a Gemma
#define POT_PIN    3  // if defined, a potentiometer is on GPIO #3 (A3, Trinket only) 

byte
  peak      = 0,      // Used for falling dot
  dotCount  = 0,      // Frame counter for delaying dot-falling speed
  volCount  = 0;      // Frame counter for storing past volume data
  
int
  vol[SAMPLES],       // Collection of prior volume samples
  lvl       = 10,     // Current "dampened" audio level
  minLvlAvg = 0,      // For dynamic adjustment of graph low & high
  maxLvlAvg = 512;

Adafruit_NeoPixel  strip = Adafruit_NeoPixel(N_PIXELS, LED_PIN, NEO_GRB + NEO_KHZ800);

void setup() {
  //memset(vol, 0, sizeof(vol));
  memset(vol,0,sizeof(int)*SAMPLES);//Thanks Neil!
  strip.begin();
}
void loop() {
  uint8_t  i;
  uint16_t minLvl, maxLvl;
  int      n, height;
  n   = analogRead(MIC_PIN);                 // Raw reading from mic 
  n   = abs(n - 512 - DC_OFFSET);            // Center on zero
  n   = (n <= NOISE) ? 0 : (n - NOISE);      // Remove noise/hum
  lvl = ((lvl * 7) + n) >> 3;    // "Dampened" reading (else looks twitchy)
  
  // Calculate bar height based on dynamic min/max levels (fixed point):
  height = TOP * (lvl - minLvlAvg) / (long)(maxLvlAvg - minLvlAvg);

  if(height < 0L)       height = 0;      // Clip output
  else if(height > TOP) height = TOP;
  if(height > peak)     peak   = height; // Keep 'peak' dot at top

// if POT_PIN is defined, we have a potentiometer on GPIO #3 on a Trinket 
//    (Gemma doesn't have this pin)
  uint8_t bright = 255;   
#ifdef POT_PIN            
   bright = analogRead(POT_PIN);  // Read pin (0-255) (adjust potentiometer 
                                  //   to give 0 to Vcc volts
#endif
  strip.setBrightness(bright);    // Set LED brightness (if POT_PIN at top
                                  //  define commented out, will be full)
  // Color pixels based on rainbow gradient
  for(i=0; i<N_PIXELS; i++) {  
    if(i >= height)               
       strip.setPixelColor(i,   0,   0, 0);
    else 
       strip.setPixelColor(i,Wheel(map(i,0,strip.numPixels()-1,30,150)));
    } 

   strip.show(); // Update strip

  vol[volCount] = n;                      // Save sample for dynamic leveling
  if(++volCount >= SAMPLES) volCount = 0; // Advance/rollover sample counter

  // Get volume range of prior frames
  minLvl = maxLvl = vol[0];
  for(i=1; i<SAMPLES; i++) {
    if(vol[i] < minLvl)      minLvl = vol[i];
    else if(vol[i] > maxLvl) maxLvl = vol[i];
  }
  // minLvl and maxLvl indicate the volume range over prior frames, used
  // for vertically scaling the output graph (so it looks interesting
  // regardless of volume level).  If they're too close together though
  // (e.g. at very low volume levels) the graph becomes super coarse
  // and 'jumpy'...so keep some minimum distance between them (this
  // also lets the graph go to zero when no sound is playing):
  if((maxLvl - minLvl) < TOP) maxLvl = minLvl + TOP;
  minLvlAvg = (minLvlAvg * 63 + minLvl) >> 6; // Dampen min/max levels
  maxLvlAvg = (maxLvlAvg * 63 + maxLvl) >> 6; // (fake rolling average)
}

// Input a value 0 to 255 to get a color value.
// The colors are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
  if(WheelPos < 85) {
   return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
  } else if(WheelPos < 170) {
   WheelPos -= 85;
   return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  } else {
   WheelPos -= 170;
   return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
}

Well it is not a schematic is it? It is just a photograph of a lot of parts and a bunch of wires. It is almost impossible to see what you have and how it is wired up.
Can you post a link to all those parts you use?

The code is not what you say you wanted in your initial post, are you just basing your project on what scraps of code you can find on the internet?

This code is a sort of VU display with a peak indicator dot at he highest point. This is about 500% more complex than your initial requirements.

So do you want an LED strip? Do you want it to flash once on a drum hit?
What colours do you want on these LED strips?

1 Like

Yea its not most understandable,
Here is the site I'v took it from, its a very friendly guide and this is why I choose this one to make this project of, maybe the first image on this page is more of schematic ?

The schematic in my words:
Mic wired to Gemma (the platform) -> Out wired to D2 | Gnd to Gnd | Ucc to 3V.
Neopixel wired to Gemma -> Gnd to Gnd | Din to D0 | 5v to Vbat (or out I think)
Lithium battery plugged into the Gemma with a switch on the red wire.

The code that I'v originally posted, and to be honest was kinda of accidentally, apologise, I wanted to post the original code but posted the code I'v been messing around with.
The only difference are:
I'v decreased the "maxlvlavg" to 0 because it made all LED flash together, and shortly.
I'v increased the NOISE to 440 from 100 because helps the threshold to increase, but also decrease the dynamic range, and after 440 not all the LEDs light up.
A serial.println that I added that displays the value of N because from what I tried to understand It looks like he is the one responsible for the value that decides when to light up.

For the final question,
I want LED to flash once, and shortly, when I hit the specific drum that LED is attached to.
The colors arn't important to me know because I'm not sure which I want, for now this code gave me some kind of a rainbow color, seems like it would fit to my vision.

Hope that is some helpful intel on this code.

OK fine.
The microphone board has an amplifier, in the data sheet for it it says

On the back, we include a small trimmer pot to adjust the gain. You can set the gain from 25x to 125x.

Have you set that to fully anti clockwise, in other words has it been turned down to the minimum extent? If you have do you still get reaction from the other drums?

Basically this amplifier is too sensitive and what we need to do is to make it less sensitive. This can be done by hardware or by software. However, there is a balance to be struck between the sensitivity of the target drum ( the one you hit ) and the other drums producing a false trigger. This is a limit of the design choice of using a microphone.

The problem with the software you are posting is that it is constantly trying to adjust the thresholds to give maximum sensitivity. I think we would be much better off using simpler software.

I will see what I can come up with for this.
In the mean time have a look at this video I made for a repeating pattern set of drums.
Drum Like Me

When you say LED here do you want a single LED or the LED strip?

1 Like

OK here is what a schematic really looks like for this project.

Things to note - The pins on the schematic do not physically match where the pins are on the real component, this simplifies the layout without removing any information because all pins are labelled. The Ground is shown going to a ground symbol, this means all pins with this symbol are all connected together.
I have added a series resistor to the data in of the LED strip, just say it is good practice at the moment. Also note the break in the line from this resistor to show that it is not joined to the capacitor but goes under it. I have also added a capacitor across the LED strip to help reduce noise.

Now I have written a piece of simple code you can start from. It compiles but I have not tried it because I don't have the microphone module you have.
Note the threshold value at the start, make that bigger to reduce the sensitivity. Anything over 1023 will result in it not triggering at all. The delay value will govern how long the flash is. Note while the LED is on the light will not trigger again.

// Simple drum light by Grumpy Mike

#include <Adafruit_NeoPixel.h>

#define N_PIXELS  6  // Change this to the number of pixels you are using
#define MIC_PIN   A1  // Microphone is attached to Trinket GPIO #2/Gemma D2 (A1)
#define DRIVER_PIN    0  // NeoPixel LED strand is connected to GPIO #0 / D0
int threshold = 600; // change this number to change the sensitivity range 512 to 1023

Adafruit_NeoPixel  strip = Adafruit_NeoPixel(N_PIXELS, DRIVER_PIN, NEO_GRB + NEO_KHZ800);

void setup() {
  strip.begin(); // start off Neopixel driver
  clearStrip() ; // blank out any start up rubbish
}

void loop() {
  if(analogRead(MIC_PIN) >= threshold) {
    fillStrip();
    delay(500); // show for half a second (500mS) change for length of flash
    clearStrip(); // turn LEDs off    
  }
}

void fillStrip() {
  for(int i=0; i<N_PIXELS; i++) {  
       strip.setPixelColor(i,Wheel(map(i,0,strip.numPixels()-1,30,150)));
    } 
   strip.show(); // Update strip
}

void clearStrip() {
  for(int i=0; i<N_PIXELS; i++) {  
       strip.setPixelColor(i,0);
    } 
   strip.show(); // Update strip
}

uint32_t Wheel(byte WheelPos) {
  if(WheelPos < 85) {
   return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
  } else if(WheelPos < 170) {
   WheelPos -= 85;
   return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  } else {
   WheelPos -= 170;
   return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
}
1 Like

Mike, I really can't thank you enough for this.
Seriously, Deeply, Thank you.

Yea, LED strip.
Got to be more precise, guess I have a lack of terms at programming.

Yea I did, and It didn't help, it helped a bit but not enough.

I wanted also to ask, what is the 330R in the middle of the schematic between the Data - D0?

I tried your code, and It still didn't work.
Took the threshold to the max, and the drums still trigger each other.
I tried to monitor the values from the mic to see the values when I hit adjacent drums, and when I hit the drum itself, and I got only 9-9-9-9-9 even on a hit.
But I guess It doesn't matter much, I think the mic is clipping anyhow.
I think the best option is to switch the mic to a piezo, which seems easy after reading your code, right?
I just need to define it in the begging of the code instead of the mic_pin, and understand what value to right on the threshold.
So I also wanted to ask, how did you know what value to enter in the threshold int?

Other than that, I heard putting a pot might help, but If the mic is clipping, is there really any use for this?

Cool video by the way :slight_smile: I enjoyed it.

Thank you again.

Well I did say

But if you want the full explanation it does two things.

  1. It protects the data input pin of the first neopixel in the string, under the fault conditions where you apply a signal to the data input of the strip but you don't power up the strip. This causes the strip to get parasitically powered by the data signal. This means it is drawing too much current from the strip and can damage the strip and the Arduino.

  2. It improves the signal integrity. Fast signals bounce backwards and forwards along a wire carrying rapid changing digital signals. This is caused by the transmission line effect when the wire meets an impedance discontinuity. Like the end of the wire. I took these two oscilloscope traces with and without the resistor.

Yes many people don't use them because they "get away with it" That is they don't see any downside to not having them. But it takes them one step closer to problems. We say "it degrades the noise performance" that is it makes it more susceptible to any extra noise from outside sources.

Yes it is clipping but that is not important in this application, you are not after a perfect reproduction of the sound, you are only going to light an LED.

I take an educated guess.
The analogue input returns numbers between 0 and 1023. The output from the microphone is biased at the mid point, that means when there is silence it will give roughly a reading of half the maximum 512. When it gets a sound that number changes it goes in turn both above and below this number. The louder the sound the more it deviates from that number. As you only want to trigger an LED I thought that 600 was a good starting point as it should have stopped it triggering from random electrical noise.

What do you mean by

Yes you can reduce the signal level using a pot, i would try that first.

Yes the code would be no different. But make sure you use a circuit like this

Because it is very easy to destroy the Arduino pin if you just wire a piezo direct to the pin, especially on a 3V3 processor. So you need a 2N7000 FET, a 1N486 diode to prevent negative voltages getting into the Arduino and a 3V3 zener diode to limit the positive signal to 3V3. You should also have a resistor of about 10K from the Arduino input pin to 3V3.

1 Like

Hi mike
Thanks for the detailed explanation about the resistor, is important to know that.

How did you understand that those are the numbers?

But I don't get it, lets say "X = max value", so It won't confuse the conversation.
So If I hit the drum with the mic inside it, its sends X value, means the mic is clipping.
If I hit an another drums that is 2 feet away, the mic is also sending X value.
So I I put a pot in the middle of the mic to the Arduino Input, It will decrease the value sent by the mic the same as if I hit the other drum and the drum with the mic inside it.
So what does a pot can really help? is there something I'm missing?

Thank you once more, for the detailed explanation on the way to use a piezo, I do need it, because I think I won't find a solution to the mic situation other than replacing it.

The A/D converter in the Arduino is a 10 bit converter, it says that in the data sheet. That means it can do the conversion to ten binary bits. So when all these bits are zero the number is zero. When all these bits are ones the number will be two to the power 10 minus one which is 1023.
If your have a n bit converter the numbers will range from zero to two to the power n minus one.

No the converter just does the job of converting the input voltage in the range 0 to 5V into the range of numbers given by the number of bits of the converter.

Yes but it is my fault for not describing how you put a pot in. I will post that when I have had time to draw you another diagram.

1 Like

OK what you need to do is to use a pot to control the gain of the amplifier. It is the amplifier that is clipping not the microphone. So rather than use an external pot, after reviewing the schematic of the microphone board I think it is best to make the sensitivity pot have a wider range. You can do that by shorting out the 22K resistor next to the pot on the back of the board. This is shown in this photo as a green line. There is no need to remove the resistor but you can if you want. Just a thin wire soldered across this resistor will do. It will let you turn down the gain down to zero. The gain wont go quite as high as it used to but then it was too high anyway.

1 Like

Hi Mike,
Thats sounds like a good plan before moving to the piezo plan, Thank you.
So you mean, I only need to solder a wire from one end of the resistor to the other? I don't need to add a pot in the middle of that wire? Like This:

        ____________Pot______________                   
       |                            |
       |    _____________________   |
       |—- >|   22K resistor    |<—-|
            |                   |
            |     Microphone    |
            |___________________|

From my understanding, I should do like this:

        _____________________________ =(Just a regular wire)        
       |                            |
       |    _____________________   |
       |—- >|   22K resistor    |<—-|
            |                   |
            |     Microphone    |
            |___________________|

Yes that is right. The pot that is already on the board can now turn the gain to less than it was before, so remember to turn it up a bit or it won’t trigger at all.

1 Like

Hi Mike,
Thank you so very much for all the help, I have enough knowledge to pull this off.
Il post on this forum a guide when I'm finished, the least contribution that I can give back, and some drummers might need it.

1 Like

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