Op het laatste moment het gemiddelde van geluid krijgen

Ik lees elke 60 seconden de geluidsinvoer en ik zou graag het gemiddelde geluid in die periode willen berekenen met behulp van niet-blokkerende code; wat moet ik doen om de manier te veranderen waarop ik het in een afzonderlijke functie bereken, omdat ik iets anders met andere sensoren moet doen?

int calculateSoundValue(){
    int average = analogRead(0);
   //loop to calculate the average simple formula sum div nbr of calculated times
    return average;
}

void setup() {
    Serial.begin(9600);

}
void loop() {
 //I donùt wanna calculate the average inside a loop but instead inside a function 
  int value = calculateSoundValue();
  Serial.println(value);

  delay(600);
}

UPDATE

Bedoel je dit ?

unsigned long previousMillis = 0;
const long interval = 6000;  
int totalSamples = 0; 
int count = 0

    int calculateSoundValue(){
        int sound = analogRead(0);
        totalSamples+= sound;
        count += 1;
        return totalSamples/count;
    }

void setup() {
 //set the digital pin as output:
  pinMode(ledPin, OUTPUT);
}

void loop() {

  unsigned long currentMillis = millis();
int totalSamples = 0; 
int count = 0
  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;

  }
      int value = calculateSoundValue();
      Serial.println(value);
}
0
@ user3378649: het lijkt erop dat je niet weet wat geluid is ... Het is niet het gemiddelde van het signaal dat je analoog Lees() , het zijn de fluctuaties van dat signaal hierboven en hieronder het gemiddelde. Het dichtst bij "gemiddeld geluid" dat je kunt krijgen, is de RMS van de AC deel van het signaal. U kunt dat berekenen als low_pass (square (high_pass (signal))).
toegevoegd de auteur Sprogz, de bron
Weet jij hoe het gemiddelde wordt berekend?
toegevoegd de auteur user67244, de bron
Weet jij wat geluid is?
toegevoegd de auteur Majenko, de bron
@RSM Het is het klassieke XY-probleem - het OP denkt dat ze weten wat ze willen en hoe ze dit kunnen bereiken, maar kunnen het ' Niet uitzoeken hoe deze methode moet worden geïmplementeerd - de onderliggende methode en hun basisbegrip van dit alles is echter volledig verkeerd, dus zelfs als ze erin slagen het te implementeren zoals ze denken dat het zou moeten werken, zal het nog steeds niet werken. Ze stellen eigenlijk de verkeerde vraag.
toegevoegd de auteur Majenko, de bron
@RSM Dat is misschien verkeerd geadresseerd;) Het moest naar het OP worden gestuurd ...
toegevoegd de auteur Majenko, de bron
@RSM Dan is het gemiddelde niet wat je wilt - wat je wilt doen is continu luisteren en van moment tot moment beslissen of er geluid boven je triggerdrempel zit of niet en onthoud dat feit - kijk dan eens per minuut naar wat je hebt onthouden en handel ernaar.
toegevoegd de auteur Majenko, de bron
Je hebt geen dure software nodig om je te vertellen wat het gemiddelde geluid over een minuut zal zijn ... Het antwoord is nul - of zo dichtbij als geen kans maakt.
toegevoegd de auteur Majenko, de bron
@Majenko Ik luister niet naar muziek, maar ik ben het erover eens dat het gemiddeld tijdverspilling is, ik dacht alleen maar aan de implementatiemethoden. De OP kan net zo goed een piekdetector gebruiken.
toegevoegd de auteur RSM, de bron
@ user3378649 om niet-blokkerende code te maken die u kunt gebruiken met de functie mill is (), de meeste suggereren een blik op het knipperende voorbeeld zonder een vertraging. Vertraging blokkeert uw code, ik weet dat timeronderbrekingen nog steeds optreden wanneer een vertraging actief is, dus timeronderbrekingen zijn wat u kunt bekijken. Ook 60 * 1000mS = 1 minuut.
toegevoegd de auteur RSM, de bron
@Majenko zijn gekoelde :), op welke manier dan ook, denk ik verder dan het voor de hand liggende, en de OP zal nu een behoorlijk drukke inbox hebben :)
toegevoegd de auteur RSM, de bron
@ user3378649 je hebt niet heel duidelijk gemaakt dat je gebruik wilde maken van niet-blokkerende code, dus tot op zekere hoogte was het niet hard, alleen praktisch en ongecompliceerd.
toegevoegd de auteur RSM, de bron
slaap (600) ziet er niet uit als een minuut, bedoel je delay() ? Om dingen met andere sensoren te doen, zou je niet-blokkerende code moeten hebben wanneer je de middeling op de meting doet.
toegevoegd de auteur RSM, de bron
@RSM Kunt u alstublieft de UPDATE controleren, ik heb geprobeerd om te implementeren wat u voorstelde; controleer het en licht ons op met uw suggesties.
toegevoegd de auteur Peter - Designer Drains, de bron
@Majenko Ik probeer te zien of er een beweging was in de laatste minuut of niet; door geluidssensor te gebruiken
toegevoegd de auteur Peter - Designer Drains, de bron
@Avamander Hard Antwoord !; Hoe dan ook; in het geval dat u bekend bent met Arduino, weet u dat ik bedoelde hoe ik het gemiddelde op een niet-blokkerende manier kon berekenen.
toegevoegd de auteur Peter - Designer Drains, de bron
@RSM Ja! dat is het punt achter mijn vraag; hoe kan ik het tegelijkertijd niet blokkeren, ik doe een vertraging
toegevoegd de auteur Peter - Designer Drains, de bron

3 antwoord

U wilt het gemiddelde van het doen van een analRead over een minuut, is dat het?

Wat denk je hiervan?

unsigned long total;
unsigned int count;

unsigned long whenStarted;

const unsigned long INTERVAL = 60000; //one minute

void setup ()
{
  Serial.begin (115200);
  Serial.println (F("Starting ..."));
  whenStarted = millis ();
} //end of setup

void loop ()
{
 //one more sample
  total += analogRead (0);
  count++;

  if (millis() - whenStarted >= INTERVAL)//is a minute up?
    {
    Serial.print (F("Average = "));
    Serial.println (total/count);
    total = 0;
    count = 0;
    whenStarted = millis ();
    }
} //end of loop
1
toegevoegd
... maar zoals al is opgemerkt, zal het middelen van de metingen niets nuttigs bereiken
toegevoegd de auteur rossp, de bron
Bedankt! kan ik total + = analogRead (0) plaatsen; tel ++; op q-functie en vervang deze zoals ik deed - ik weet niet wat je daarmee bedoelt.
toegevoegd de auteur Nick Gammon, de bron
Bedankt! kan ik total + = analogRead (0) plaatsen; tel ++; op q-functie en vervang deze zoals ik deed
toegevoegd de auteur Peter - Designer Drains, de bron

The short answer is use millis() to keep track of time. You can also put all the time related stuff inside a class to have a nicely organized code. You can get more info about time management on the Arduino here. https://learn.adafruit.com/multi-tasking-the-arduino-part-1/ditch-the-delay

0
toegevoegd
U bedoelt waarschijnlijk micros() , niet millis() : als u de ADC wilt samplen bij snelheden die relevant zijn voor audiosignalen, millis() zal niet voldoende resolutie bieden.
toegevoegd de auteur Sprogz, de bron

Ik neem aan dat wat je eigenlijk wilt, de geluidsintensiteit is. Dit is aanzienlijk meer betrokken dan alleen het middelen van de monsters die u leest. ik heb een paar weken geleden een programma geschreven dat precies dat doet: het meet de geluidsintensiteit en verzendt die metingen via de seriële poort. Het is een vrij kort programma (43 regels code) dat je misschien bent in staat om aan je behoeften aan te passen, dus deel ik het nu als een GitHub-essentie: sound-meter.ino .

Om ervoor te zorgen dat dit geen link-alleen antwoord is, zal ik proberen het de innerlijke werking van het programma, en doorloop de theorie van het meten van geluid intensiteit op een Arduino. Maar laat me hier eerst een disclaimer plaatsen: a "Echte" geluidsniveaumeter moet een frequentierespons hebben die voldoet met sommige normen, en het moet worden gekalibreerd tot absolute niveaus. Dit programma biedt alleen niet-gekalibreerde meetwaarden met welke frequentie dan ook antwoord dat de analoge hardware heeft.

Signaal conditionering

Four measuring sound on an Arduino, you obviously need a microphone, but you also need some kind of interface circuit between the microphone and the Arduino. The purpose of the interface is to “condition the signal”, i.e. to make sure the Arduino gets a voltage in the proper range for it's analog-to-digital converter (ADC). It's typically an op-amp based circuit that provides some amplification and also adds a DC bias to avoid clipping the negative side of each oscillation. Ideally, the DC bias should be around Vcc/2, i.e. 2.5 V on an Arduino Uno.

Bekijk deze SparkFun-microfoon breakout voor een voorbeeld over hoe zo'n circuit kan worden gebouwd (klik op "Schematisch").

ADC-bemonstering

Once you have a properly conditioned analog signal, you have to sample it fast enough to catch all its spectral content. The Nyquist–Shannon sampling theorem tells us the sampling rate should be at least twice the highest frequency in the signal. For audio signals, sampling rates of the order of 8 kS/s (kilosamples per second) are typical of low quality, telephone-like applications, whereas high quality audio would run at 44.1 to 48 kS/s.

The ADC of the Arduino Uno, in its default configuration, takes 104 µs to convert one sample. If you just call analogRead() in a tight loop, this gives a sampling rate of about 9.6 kS/s, which is fine for this kind of application, unless we have to measure noise above 4.8 kHz. The problem with this approach is that analogRead() is a blocking function. Calling it in a tight loop means the program will spend most of its time just waiting for the ADC. If you do anything else in the loop, not only will the sampling rate be lowered, it will also become unsteady, which is generally not desirable.

In order to avoid blocking the CPU, we have to forgo analogRead(), and instead get our hands dirty with low-level configuration of the ADC. The ADC of the Arduino Uno offers a so-called “free running mode”, which is well suited for this kind of application. In this mode, the ADC starts a new conversion as soon as the previous one is done, ensuring a very consistent sampling rate of 9.6 kS/s. It can also trigger an interrupt after each conversion, in order for the interrupt service routine to retrieve and process the sample. See the datasheet of the ATmega328P for details on configuring the ADC.

Verwijdering van de DC-bias

Zodra we de gedigitaliseerde voorbeelden hebben, moet je eerst verwijderen de DC-bias die is toegevoegd door de interfaceschakeling. Als de bias is stabiel en bekend (misschien bepaald door experiment), dit gaat alleen om aftrekken van een constante. Als het niet bekend is, kan het worden geschat op de samples door een digitaal laagdoorlaatfilter met een cutoff laten lopen frequentie onder het interessegebied. Het aftrekken van de uitvoer van een laagdoorlaatfilter bouwt in wezen een hoogdoorlaatfilter. Als een alternatief, een numeriek derivaat (verschil tussen opeenvolgende monsters) kunnen worden gebruikt als een ruw hoogdoorlaatfilter. Dit zal echter verteken de gevoeligheid van de detectie naar het hoge einde van de spectrum. Afhankelijk van de ruis die u wilt detecteren en van de achtergrondgeluid, dit kan acceptabel zijn voor uw toepassing.

In het programma dat ik deel, neem ik aan dat de DC bias bekend is: het is de dc_offset constant aan het begin van het programma.

Onmiddellijke intensiteit

Met de DC bias verwijderd, is het signaal dat we hebben een digitaal beeld van de geluid gekozen door de microfoon. Het zou verleidelijk kunnen zijn om het gewoon te gemiddelde zoals het is. Dit zou echter alleen nul opleveren, als de positieve fluctuaties van het signaal zou de negatieve annuleren.

Er zijn verschillende opties om dit probleem op te lossen. We zouden een piek kunnen maken detectie in plaats van een gemiddelde, of we kunnen de absolute waarde nemen voor middeling. De meest populaire optie is waarschijnlijk om de vierkanten van de monsters. Omdat het vierkant van een reëel getal altijd is positief, dit vermijdt het probleem van de gemiddelde oplossing. Maar het plein heeft ook een diepere fysieke betekenis: het is evenredig met het geluid intensiteit , d.w.z. de energie gedragen door de geluidsgolf.

Laagdoorlaatfilter

The intensity computed above is a very fast varying quantity. If the signal is a simple tone of constant frequency and volume, the Onmiddellijke intensiteit fluctuates between zero and some maximum at twice the tone frequency. In order to recover the “constant volume” property of the sound, we need to perform some sort of averaging or, in other words, we need a Laagdoorlaatfilter.

There are many ways to implement a digital Laagdoorlaatfilter. The most intuitive may be to group the samples into batches, and then compute the average of each batch. However, this is neither the best nor the most efficient to implement. When I need a quick and simple low pass filter, I generally use an exponential moving average. This is the discrete-time equivalent of an analog RC filter, and it can be implemented very efficiently by remembering the previous output and updating it as

output += input - output/N;

where, for efficiency reasons, N should be a power of two. The filter's time constant is N/fs, where fs is the sampling frequency. In the program I use N = 256, which makes the division virtually free. This gives a time constant of 26.6 ms. You can tune the time constant to your needs simply by changing N, but make sure it is still a power of two.

slachting

If you only want to trigger an event when the sound intensity exceeds a defined level, you may not need this. But if you have other processing to do with those measurements, it is probably not useful to process more than one intensity reading per time constant of the previous filter. That's why the program has a slachting step. This is simply the ISR periodically signaling the main program that an intensity reading is available. Notice that, since the sample count is an 8-bit variable, it automatically counts modulo 256. If you want to increase the slachting factor, you should make sample_count wider and mask out the bits you do not need.

0
toegevoegd