Hey guys,
I would like to share my new project. I’ve seen many videos regarding how to mount a platform and how to avoid annoying your neighbors while playing in an apartment. So, I followed those recommendations, and for almost a year I didn’t have any issues.
However, two weeks ago, a neighbor complained that someone was playing some kind of drums on Sunday (a no go in Switzerland). I thought it was me, so my engineer mind made me check whether I was annoying people. Meanwhile, I found out it was some kids playing for a carnival group, not me. Too late, I had already bought all the components.
The idea is to measure the vibration on the Thomann platform and how much of it transfers to the floor. Ideally, I would have needed a 3rd sensor close to the pedals, on top of the noise eater, to get a real reference, but for now it’s fine; I used a phone to measure this reference.
You can see the results so far. Using the reference I got from my phone, the absorption is around 99% of the real vibration created by the pedals.
Dashboard:
How does it work?
The idea is to measure the source of vibration and compare it with the floor, to understand the attenuation and whether the vibration is reaching your neighbor. In my case, I am using 2 sensors, but ideally I need a 3rd one.
I need to measure the vibration side by side with the pedal. The pedals are on top of a Roland Noise Eater, and the stand is using a Noise Eater too, and the drum rack is using this washing machine rubber for vibration.
All of those things are on top of the Thomann platform. Then I need another sensor to measure the vibration on the Thomann platform and understand whether the Noise Eaters are attenuating the vibration.
Finally, a third sensor goes on the floor, close to or under the platform; then you can see the source of vibration, the attenuation on the platform, and how much is reaching the floor.
So far, I’ve measured the source using my phone as a reference, and I can see the performance of the system is 99%.
=====
List of components:
- ESP32 NodeMCU Development Board
- Accelerometer ADXL345 GY-291
- Single Dupont cableFemale
Inside the configuration.yaml (You need to use app like Studio Code server to get access to it)
Add it after the last line in your configuration.yaml
template:
- sensor:
- name: "Vibration Platform Percent"
unique_id: vib_platform_pct
unit_of_measurement: "%"
state: >
{% set max_g = 0.05 %}
{% set v = states('sensor.office_adsxl_vib01_vibra_rms_g')|float(0) %}
{{ [100, (v / max_g * 100)] | min | round(1) }}
- name: "Vibration Floor Percent"
unique_id: vib_floor_pct
unit_of_measurement: "%"
state: >
{% set max_g = 0.05 %}
{% set v = states('sensor.office_adsxl_vib02_vibra_rms_g')|float(0) %}
{{ [100, (v / max_g * 100)] | min | round(1) }}
- name: "Vibration Difference Percent"
unique_id: vib_diff_pct
unit_of_measurement: "%"
state: >
{% set p = states('sensor.vibration_platform_percent')|float(0) %}
{% set f = states('sensor.vibration_floor_percent')|float(0) %}
{{ (p - f) | round(1) }}
Electrical connection:
You need to use the same 3V3 for the VCC and CS.
Create a new device in the ESPHOME device Builder
Device configuration inside the ESPHome device Builder:
You need to flash each device with differente name, don’t forget it.
# Board: NodeMCU-32S (NodeMCU)
# Definition: definitions/boards/nodemcu-32s/manifest.yaml
esphome:
name: Sensor Name
friendly_name: Sensor Name
esp32:
variant: esp32
flash_size: 4MB
framework:
type: esp-idf
logger:
api:
encryption:
key: API ENCRYPTION KEY IN THE CONFIGURATION
ota:
- platform: esphome
wifi:
ssid: YOUR_WIFI_NETWORK
password: YOUR_WIFI_PASSWORD
ap:
ssid: Sensor Name Fallback Hotspot
password: AUTOMATIC GENERATED IN THE CONFIGURATION
captive_portal:
external_components:
- source:
type: git
url: https://github.com/jdillenburg/esphome
ref: main
components: [ adxl345 ]
i2c:
sda: GPIO21
scl: GPIO22
frequency: 400kHz
adxl345:
- id: my_adxl345
address: 0x53
update_interval: 100ms
range: 4G # options: 2G, 4G, 8G, 16G
accel_x:
name: "Vibra X"
accel_y:
name: "Vibra Y"
accel_z:
name: "Vibra Z"
Dashboard:
You need to change the entity and heading here:
views:
- type: sections
sections:
- type: grid
cards:
- type: heading
heading: Neighbor Mood
- type: custom:button-card
entity: sensor.vibration_floor_percent
show_name: false
show_state: false
show_icon: false
show_label: true
label: |
[[[
var pct = parseFloat(entity.state);
if (pct < 10) return '😊';
else if (pct < 40) return '😐';
else return '😢';
]]]
styles:
card:
- background-color: |
[[[
var pct = parseFloat(entity.state);
if (pct < 10) return '#2e7d32';
else if (pct < 40) return '#f9a825';
else return '#c62828';
]]]
- border-radius: 12px
- padding: 30px 0
- transition: background-color 0.3s ease
label:
- font-size: 110px
- line-height: 1
- justify-content: center
- width: 100%
- type: custom:button-card
entity: sensor.vibration_floor_percent
show_name: false
show_state: false
show_icon: false
show_label: true
label: |
[[[
var pct = parseFloat(entity.state);
if (pct < 10) return 'Happy Neighbor';
else if (pct < 40) return 'Neutral Neighbor';
else return 'Annoyed Neighbor';
]]]
styles:
label:
- font-size: 32px
- font-weight: bold
- justify-content: center
- width: 100%
- color: |
[[[
var pct = parseFloat(entity.state);
if (pct < 10) return '#4caf50';
else if (pct < 40) return '#f9a825';
else return '#e53935';
]]]
- type: heading
heading: Isolation Analysis
- type: markdown
content: >
{% set v01 =
states('sensor.office_adsxl_vib01_vibra_rms_g')|float(0) %} {% set
v02 = states('sensor.office_adsxl_vib02_vibra_rms_g')|float(0) %}
{% set db01 =
states('sensor.office_adsxl_vib01_vibra_db_re_1g')|float(0) %} {%
set db02 =
states('sensor.office_adsxl_vib02_vibra_db_re_1g')|float(0) %} {%
set activity_threshold = 0.01 %}
{% if v01 < activity_threshold %} ⚪ **At rest** — not enough
excitation for a reliable transmission reading
*(Platform: {{ v01 }} g | Floor: {{ v02 }} g — background noise)*
{% else %} {% set diff_g = (v01 - v02) | round(5) %} {% set
isolation_db = (db01 - db02) | round(1) %} {% set transmitted =
((v02 / v01) * 100) | round(1) %} {% set absorbed = (100 -
transmitted) | round(1) %}
**Difference (g):** {{ diff_g }} g
**Isolation:** {{ isolation_db }} dB
**Transmitted to floor:** {{ transmitted }}%
**Absorbed by platform:** {{ absorbed }}%
{% if v02 > 0.02 %} 🔴 **Vibration HIGH on floor** — risk of
disturbing the neighbor {% elif v02 > 0.005 %} 🟡 **Vibration
MEDIUM on floor** — pay attention {% else %} 🟢 **Vibration LOW on
floor** — all quiet {% endif %} {% endif %}
- type: grid
cards:
- type: heading
heading: adsxl-vib01
- type: tile
entity: sensor.office_adsxl_vib01_vibra_db_re_1g
icon: mdi:sine-wave
- type: tile
entity: sensor.office_adsxl_vib01_vibra_db_re_1um_s2
icon: mdi:volume-vibrate
- type: tile
entity: sensor.office_adsxl_vib01_vibra_rms_g
icon: mdi:vibrate
- type: tile
entity: sensor.office_adsxl_vib01_vibra_rms_m_s2
icon: mdi:vibrate
- type: heading
heading: Comparison
- type: history-graph
title: Vibration Difference Over Time (%)
entities:
- entity: sensor.vibration_platform_percent
name: Platform
- entity: sensor.vibration_floor_percent
name: Floor
- entity: sensor.vibration_difference_percent
name: Difference
hours_to_show: 1
- type: grid
cards:
- type: heading
heading: adsxl-vib02
- type: tile
entity: sensor.office_adsxl_vib02_vibra_db_re_1g
icon: mdi:sine-wave
- type: tile
entity: sensor.office_adsxl_vib02_vibra_db_re_1um_s2
icon: mdi:volume-vibrate
- type: tile
entity: sensor.office_adsxl_vib02_vibra_rms_g
icon: mdi:vibrate
- type: tile
entity: sensor.office_adsxl_vib02_vibra_rms_m_s2
icon: mdi:vibrate
- type: grid
cards:
- type: heading
heading: Vibration Level
- type: gauge
entity: sensor.vibration_platform_percent
name: Platform Vibration
min: 0
max: 100
severity:
green: 0
yellow: 20
red: 60
- type: gauge
entity: sensor.vibration_floor_percent
name: Floor Vibration
min: 0
max: 100
severity:
green: 0
yellow: 10
red: 40
Sensor temporary installed:
I hope you like it.
Cheers
Fab from Brazil in Switzerland




