Detekce pohybu čidlem MPU-6050. Čidlo MPU-6050 obsahuje měřič zrychlení (accelerometer), gyroskop a teploměr. Komunikace s RPi Pico je sběrnicí I2C. V následujícím příkladu použijeme měřič zrychlení, protože potřebujeme chránit předmět před odnesením. Jakmile dojde k pohybu práněného předmětu (měřič zrychlení zaznamená změnu zrychlení) vyvoláme poplach (rozsvítíme LED).

Čidlo MPU-6050 svrchu

MPU6050 vrsek

Čidlo MPU-6050 zespodu

MPU6050 spodek

Popis funkce registrů: MPU-6000-Register-Map1.pdf

Použitá knihovna: RPi Pico MPU6050 C library

Zapojení

Napájení čidla je 3.3V, čidlo nesnese napájecí napětí 5V.

MPU-6050 pin RPi pin

VCC

3V3

GND

GND

SDA

GPIO4 (default I2C SDA)

SCL

GPIO5 (default I2C SCL)

AD0

3V3

Na pin AD0 je přivedeno napětí 3.3V, což znamená, že čidlo bude mít I2C adresu 0x69. Pokud bude pin AD0 uzemněn (0V), potom má čidlo I2C adresu 0x68. Je potřeba, aby pin čidla AD0 byl buď na napětí 3.3V nebo přizemněn. Jinak to nebude fungovat.

Program

#include "stdio.h"
#include <math.h>
#include "pico/stdlib.h"
#include "haw/MPU6050.h"

// pokud se čísla h1 a h2 neliší od sebe o toleranci, vrací false, pokud se liší vrací true
bool porovnej_s_toleranci( int h1, int h2, int tolerance )
{
    if( h1 == h2) return false;
    if( h1+tolerance >= h2 && h1-tolerance <= h2 ) return false;
    return true;
}

int main()
{
bool pohyb = false;
int x,y,z, ox,oy,oz;

    stdio_init_all();

    gpio_init(22);
    gpio_set_dir(22,GPIO_OUT);
    gpio_put(22,1);
    sleep_ms(200);
    gpio_put(22,0);

    // Setup I2C properly
    gpio_init(PICO_DEFAULT_I2C_SDA_PIN);
    gpio_init(PICO_DEFAULT_I2C_SCL_PIN);
    gpio_set_function(PICO_DEFAULT_I2C_SDA_PIN, GPIO_FUNC_I2C);
    gpio_set_function(PICO_DEFAULT_I2C_SCL_PIN, GPIO_FUNC_I2C);
    // Don't forget the pull ups! | Or use external ones
    gpio_pull_up(PICO_DEFAULT_I2C_SDA_PIN);
    gpio_pull_up(PICO_DEFAULT_I2C_SCL_PIN);

    // Pass in the I2C driver (Important for dual-core operations). The second parameter is the address,
    // which can change if you connect pin A0 to GND or to VCC.
    mpu6050_t mpu6050 = mpu6050_init(i2c_default, MPU6050_ADDRESS_A0_VCC);

    // Check if the MPU6050 can initialize
    if (mpu6050_begin(&mpu6050))
    {
        // Set scale of gyroscope
        mpu6050_set_scale(&mpu6050, MPU6050_SCALE_250DPS);
        // Set range of accelerometer
        mpu6050_set_range(&mpu6050, MPU6050_RANGE_2G); (1)

        // digital highpass filter
        mpu6050_set_dlpf_mode(&mpu6050, MPU6050_DHPF_0_63HZ);

        // Enable temperature, gyroscope and accelerometer readings
        mpu6050_set_temperature_measuring(&mpu6050, false);
        mpu6050_set_gyroscope_measuring(&mpu6050, false);
        mpu6050_set_accelerometer_measuring(&mpu6050, true);

        // Enable free fall, motion and zero motion interrupt flags
        mpu6050_set_int_free_fall(&mpu6050, true);
        mpu6050_set_int_motion(&mpu6050, true);
        mpu6050_set_int_zero_motion(&mpu6050, true);

        // Set motion detection threshold and duration
        mpu6050_set_motion_detection_threshold(&mpu6050, 1);
        mpu6050_set_motion_detection_duration(&mpu6050, 20);

        // Set zero motion detection threshold and duration
        mpu6050_set_zero_motion_detection_threshold(&mpu6050, 4);
        mpu6050_set_zero_motion_detection_duration(&mpu6050, 2);
    }
    else
    {
        while (1)
        {
            // Endless loop
            printf("Error! MPU6050 could not be initialized. Make sure you've entered the correct address. And double check your connections.\n");
            sleep_ms(1000);
        }
    }

    uint i = 0;
    uint j = 0;
    while (1)
    {
        // Fetch all data from the sensor | I2C is only used here
        mpu6050_event(&mpu6050);

        // Pointers to float vectors with all the results
        mpu6050_vectorf_t *accel = mpu6050_get_accelerometer(&mpu6050);
        mpu6050_vectorf_t *gyro = mpu6050_get_gyroscope(&mpu6050);

        // Activity struct holding all interrupt flags
        mpu6050_activity_t *activities = mpu6050_read_activities(&mpu6050);

        // Rough temperatures as float -- Keep in mind, this is not a temperature sensor!!!
        float tempC = mpu6050_get_temperature_c(&mpu6050);
        float tempF = mpu6050_get_temperature_f(&mpu6050);

        x = round(accel->x*10);
        y = round(accel->y*10);
        z = round(accel->z*10);
        // Print all the measurements
//        printf("Accelerometer: %f, %f, %f - Gyroscope: %f, %f, %f - Temperature: %f°C - Temperature: %f°F\n", accel->x, accel->y, accel->z, gyro->x, gyro->y, gyro->z, tempC, tempF);
        printf("Accelerometer: %d, %d, %d Overflow: %d - Freefall: %d - Inactivity: %d, Activity: %d, DataReady: %d PosX: %d - NegX: %d -- PosY: %d - NegY: %d -- PosZ: %d - NegZ: %d 22=%d , i=%d\r", x, y, z,
               activities->isOverflow,
               activities->isFreefall,
               activities->isInactivity,
               activities->isActivity,
               activities->isDataReady,
               activities->isPosActivityOnX,
               activities->isNegActivityOnX,
               activities->isPosActivityOnY,
               activities->isNegActivityOnY,
               activities->isPosActivityOnZ,
               activities->isNegActivityOnZ,
               pohyb,
               i);
        // I když je čidlo v klidu, tak se hodnoty naměřené akcelerometrem malinko od sebe liší
        // Toto malinko je tolerance.
        // Porovnáváme předchozí hodnotu akcelerometru se současnou hodnotou
        // i > 20 dělá prodlevu při zapnutí
        if(i>20 && ( porovnej_s_toleranci(x, ox, 2) || porovnej_s_toleranci(y, oy, 2) || porovnej_s_toleranci(z, oz, 2)) ) { (2)
            pohyb = true;  // zaznamenali jsme pohyb předmětu
            j = i;
        } else {
            pohyb = false; // předmět je v klidu
        }
        gpio_put(22,pohyb);
        mpu6050_set_sleep_enabled(&mpu6050, false);
        sleep_ms(180);
        mpu6050_set_sleep_enabled(&mpu6050, true);
        sleep_ms(20);
        ox = x; oy = y; oz = z;
        i++;
    }

    return 0;
}
1 Nastavení citlivosti je záležitost experimentu. MPU6050_RANGE_2G je nejvyšší citlivost, pak jsou k dispozici ještě nižší citlivosti (vyšší rozsahy zrychlení) MPU6050_RANGE_4G, MPU6050_RANGE_8G a MPU6050_RANGE_16G
2 Tolerance 2 je možná příliš citlivá, stačí aby se stůl lehounce zachvěl a čidlo to zaznamená. Při této citlivosti se zaznamená chůze člověka vedle stolu.

Konstrukce

Je detekován pohyb

IMG 20260116 012043

Není detekován pohyb

IMG 20260116 012035

Testování (čidlo je příliš lenivé)
Testování

Zdroje a odkazy