Note de ce sujet :
  • Moyenne : 0 (0 vote(s))
  • 1
  • 2
  • 3
  • 4
  • 5
Détecter fin de cycle machine à laver
#8
Ah, si tu veux reconnaître le son que fait le buzzer en fin de cycle, j'ai un truc pour toi !

Au hackerspace que je fréquente, j'avais justement lancé l'idée de pouvoir détecter l'alarme incendie de manière non intrusive. Du coup, un copain qui touche bien en traitement du signal a pondu un petit bout de code ultra simple qui tourne sur un Arduino, et qui fait une détection homodyne d'un signal sonore. Ça marche vraiment du feu de dieu.

Le code est ici :

https://gist.github.com/edgar-bonet/0b03...366bc05fc6

Compliqué, hein ? Wink

Attention, si tu veux faire tourner le code sur un Leonardo, il faut changer le numéro de canal ADC, car il ne les numérote pas de la même façon.

Pour revenir au KNX, tu peux sortir un contact qui active un relais qui pilotera un moduel d'entrée KNX.

Voici ma version du code, pour un Leonardo, justement (je compte utiliser celui-ci), qui active une sortie, et rentre dans une boucle infinie (il faut le reseter pour relancer le code ; tu peux adapter).

Code :
/*
* homodyne.ino: Homodyne detection of a 3.03 kHz signal.
*
* This program continuously samples analog input 0 and uses an homodyne
* detection scheme to identify a signal at 3.03 kHz (+/- 24 Hz @ -3dB).
*
* The analog-to-digital converter is set to "free running mode" and
* takes one sample every 104 us. The samples are multiplied by two
* generated signals at 1 kHz (the "local oscillator"), in quadrature to
* one another. The products are then low-pass filtered with a time
* constant of 64 sample periods (6.656 ms), which gives the (I, Q)
* signals with a 24 Hz bandwidth. Finally, the signal power is computed
* as I^2 + Q^2.
*
* The program is intended for an Arduino Leonardo, and is likely to work on
* any AVR-based Arduino having an ADC and clocked at 16 MHz.
*
* For a detailed explanation, see
* http://arduino.stackexchange.com/a/21175
*
* Copyright (c) 2016 Edgar Bonet Orozco.
* Released under the terms of the MIT license:
* https://opensource.org/licenses/MIT
*/

#include <util/atomic.h>

// The frequency we want to detect, in Hz.
const float SIGNAL_FREQ = 3030.0; // ADJUST!

// Power detection level
const uint16_t POWER_TRESHOLD = 32768; // ADJUST!

// Timing bits.
const float SAMPLING_FREQ = F_CPU / (128 * 13.0);  // 9.615 kHz
const long PHASE_INC = round(SIGNAL_FREQ / SAMPLING_FREQ * (1L << 16));
const int LOG_TAU = 6;  // tau = 64 / SAMPLING_FREQ = 6.656 ms

// Analog input to use.
const uint8_t ANALOG_PIN = 7;

// The number of the LED pin.
const uint8_t LED_PIN = 13;

// The number of the alarm pin.
const uint8_t ALARM_PIN = 9;

// Print every xxx ms
const uint16_t PRINT_PERIOD = 1000;

// Demodulated (I, Q) amplitudes.
volatile int16_t signal_I, signal_Q;

int8_t sample;


// Set the ADC to free running mode.
static void configure_adc()
{
    ADMUX  = _BV(REFS0)   // ref = AVCC
           | _BV(ADLAR)   // left adjust result
           | ANALOG_PIN;  // input channel
    ADCSRB = 0;           // free running mode
    ADCSRA = _BV(ADEN)    // enable
           | _BV(ADSC)    // start conversion
           | _BV(ADATE)   // auto trigger enable
           | _BV(ADIF)    // clear interrupt flag
           | _BV(ADIE)    // interrupt enable
           | 7;           // prescaler = 128
}


// Interrupt handler called each time an ADC reading is ready.
ISR(ADC_vect)
{
    // Read the ADC and convert to signed number.
    sample = ADCH - 128;

    // Update the phase of the local oscillator.
    static uint16_t phase;
    phase += PHASE_INC;

    // Multiply the sample by square waves in quadrature.
    int8_t x = sample;
    if (((phase>>8) + 0x00) & 0x80) x = -1 - x;
    int8_t y = sample;
    if (((phase>>8) + 0x40) & 0x80) y = -1 - y;

    // First order low-pass filter.
    signal_I += x - (signal_I >> LOG_TAU);
    signal_Q += y - (signal_Q >> LOG_TAU);
}


// Return a power reading.
static uint16_t get_power_reading()
{
    int16_t I, Q;
    ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
        I = signal_I;
        Q = signal_Q;
    }
    return sq((int8_t)(I >> LOG_TAU)) + sq((int8_t)(Q >> LOG_TAU));
}


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

    configure_adc();

    // Set the digital led pin as output:
    pinMode(LED_PIN, OUTPUT);

    // Set the digital alarm pin as output:
    pinMode(ALARM_PIN, OUTPUT);
}


void loop()
{
    static uint16_t last_print;

    uint16_t power = get_power_reading();

    // Print a power reading every PRINT_PERIOD ms.
    uint16_t now = millis();
    if (now - last_print >= PRINT_PERIOD) {
        Serial.println(sample);
        digitalWrite(LED_PIN, HIGH);
        last_print += PRINT_PERIOD;
    }
    if (now - last_print >= 10) {
        digitalWrite(LED_PIN, LOW);
    }
    
    // Check power level
    if (power > POWER_TRESHOLD) {
        digitalWrite(ALARM_PIN, HIGH);
        digitalWrite(LED_PIN, HIGH);

        // Wait forever
        while (true);
    }
}

Hope this helps!
Frédéric

https://pknyx.gbiloba.org (de nouveau en ligne !)
Répondre


Messages dans ce sujet
RE: Détecter fin de cycle machine à laver - par fma38 - 13/04/2016, 17:02:14

Atteindre :


Utilisateur(s) parcourant ce sujet : 3 visiteur(s)