McKesson Bed Sensor Pad Wiring

I picked up one of these bed sensor pads to see if I can get it to work with HA. The pad has a 4-conductor wire, red, black, green, and yellow.

Red and black always have continuity between them as do green and yellow. Pressure on the pad doesn’t seem to affect this.

Anyone out there used one of these before and/or able to shed some light on what readings I should be looking for with the multimeter?

I have a pressure mat that has 4 cables (all black) but I only use 2 of the 4 and they are just attached to an aqara leak sensor set in occupancy mode which works pretty much flawless since setting it up.

You just need to see what 2 of the 4 will allow a closed circuit when pressure is applied.

One of those wire loops is there exclusively to detect if the device has been cut (for alarms).

Still struggling with this one. I’ve got the four wires each hooked up to a GPIO on an ESP32 and the voltage readings don’t really give me any indication when someone’s in bed (see graph below).

Green/Yellow have continuity as do Black/Red. I’ve tried connecting G/B, G/R, Y/B, and Y/R and don’t get any significant readings across them with a multimeter when there’s someone in bed.

Anyone have a suggestion for a next step that’s not “Return the thing to Amazon”? :rofl:

You’re not supposed to be connecting those wires directly to GPIO. What you’re supposed to be making is a resistor network that allows you to sense voltage differences in the range of 0–3.3V and therefore measure the change in resistance.

Hang on…

  1. Find the two leads that have some sort of resistance that varies with weight using your multimeter (it should be high normally and drop down when squeezed hard).
  2. Then use those two leads as part of our resistor network, with a decent amount of resistance added in the network (in my case I used 460k ohm IIRC). I will share below my own sensor’s schematic.

Then you will have a sensor that will get you a variable resistance or variable voltage. When the resistance goes below a certain setpoint, that means detection.

On top of that you can add debouncing using the delay on and delay off ESPhome constructs.

Here is the schematic of my bed sensor:

Note the bed pressure sensors are VR1 and VR2.

Here is the YAML

substitutions:
  name: "master-bedroom-bed"
  friendly_name: Master bedroom bed

esphome:
  name: ${name}
  friendly_name: ${friendly_name}
  name_add_mac_suffix: false

esp32:
  # XTVTX ESP32 (wroom)
  board: nodemcu-32s
  framework:
    type: esp-idf

logger:
  level: debug
  logs:
    esp32_ble: debug
    sensor: info
    mdns: debug
    adc: info
    resistance: info
    internal_temperature: info

# Enable Home Assistant API
api:
  encryption:
    key: "<SUITABLE ENCRYPTION KEY>"

ota:
  - platform: esphome
    password: "<SUITABLE OTA PASSWORD>"

wifi:
  reboot_timeout: 120min
  networks:
  - ssid: !secret wifi_ssid
    password: !secret wifi_password

esp32_ble_tracker:
  scan_parameters:
    active: true

bluetooth_proxy:
  active: true

number:
  - platform: template
    optimistic: true
    id: resistance_threshold_for_occupant_1
    name: Resistance threshold for occupant 1
    min_value: 0
    max_value: 212184185438208
    step: 1000
    icon: mdi:omega
    entity_category: config
    unit_of_measurement: Ω
    restore_value: True
  - platform: template
    id: resistance_threshold_for_occupant_2
    optimistic: true
    name: Resistance threshold for occupant 2
    min_value: 0
    max_value: 212184185438208
    step: 1000
    icon: mdi:omega
    entity_category: config
    unit_of_measurement: Ω
    restore_value: True

binary_sensor:
  - platform: template
    id: occupant_1
    name: Occupant 1
    device_class: occupancy
    icon: mdi:bed
    lambda: |
      if (id(variable_resistance_1).state < id(resistance_threshold_for_occupant_1).state) {
        return true;
      }
      return false;
    filters:
      delayed_off: 5s
#    on_state:
#      - if:
#          condition:
#            lambda: "return id(occupant_1).state;"
#          then:
#            - lambda: >
#                id(occupant_1).set_icon("mdi:bed");
#          else:
#            - lambda: >
#                id(occupant_1).set_icon("mdi:bed-empty");
  - platform: template
    id: occupant_2
    name: Occupant 2
    device_class: occupancy
    icon: mdi:bed
    lambda: |
      if (id(variable_resistance_2).state < id(resistance_threshold_for_occupant_2).state) {
        return true;
      }
      return false;
    filters:
      delayed_off: 5s
#    on_state:
#      - if:
#          condition:
#            lambda: "return id(occupant_2).state;"
#          then:
#            - lambda: >
#                id(occupant_2).set_icon("mdi:bed");
#          else:
#            - lambda: >
#                id(occupant_2).set_icon("mdi:bed-empty");

button:
  - platform: restart
    name: Restart
    entity_category: diagnostic
    icon: mdi:restart
  - platform: safe_mode
    name: Safe mode restart
    entity_category: diagnostic
    icon: mdi:restart-alert

sensor:
- platform: uptime
  name: Uptime
  entity_category: diagnostic

- platform: wifi_signal
  name: "Wi-Fi signal strength"
  update_interval: 10s
  entity_category: "diagnostic"
- platform: internal_temperature
  name: "Device temperature"
  update_interval: 10s
  entity_category: "diagnostic"

- platform: adc
  id: resistance_voltage_1
  name: Resistance voltage 1
  pin: GPIO35
  attenuation: 11dB
  accuracy_decimals: 5
  update_interval: 0.2s
  filters:
    - median:
        window_size: 25
        send_every: 5
        send_first_at: 1
    - calibrate_linear:
      - 0.142 -> 0.0
      - 3.171 -> 3.33
  entity_category: "diagnostic"
  disabled_by_default: True
- platform: resistance
  id: variable_resistance_1
  name: Variable resistance 1
  sensor: resistance_voltage_1
  configuration: UPSTREAM
  resistor: 462kOhm
  reference_voltage: 3.33V
  icon: mdi:resistor
  entity_category: "diagnostic"
  disabled_by_default: True

- platform: adc
  id: resistance_voltage_2
  name: Resistance voltage 2
  pin: GPIO32
  attenuation: 11dB
  accuracy_decimals: 5
  update_interval: 0.2s
  filters:
    - median:
        window_size: 25
        send_every: 5
        send_first_at: 1
    - calibrate_linear:
      - 0.142 -> 0.0
      - 3.171 -> 3.33
  entity_category: "diagnostic"
  disabled_by_default: True
- platform: resistance
  id: variable_resistance_2
  name: Variable resistance 2
  sensor: resistance_voltage_2
  configuration: UPSTREAM
  resistor: 470kOhm
  reference_voltage: 3.33V
  icon: mdi:resistor
  entity_category: "diagnostic"
  disabled_by_default: True

Thank you so much for that detailed reply. I finally had time to dig in to this and replicate your circuit (I think) and I’m not getting the results you describe.

I’ve tried with every permutation of the orange and brown wires with the R/B/G/Y wires from the sensor pad, but I think the yellow and green are the correct pair.

Regardless, the logs show the same values over and over, even with pressure on the sensor:

[12:10:04][D][sensor:093]: 'GPIO5': Sending state 3.10700 V with 5 decimals of accuracy
[12:10:04][D][resistance:039]: 'Variable resistance 1' - Resistance 33733.5Ω
[12:10:04][D][sensor:093]: 'Variable resistance 1': Sending state 33733.47656 Ω with 1 decimals of accuracy
[12:10:06][D][sensor:093]: 'GPIO5': Sending state 3.10700 V with 5 decimals of accuracy
[12:10:06][D][resistance:039]: 'Variable resistance 1' - Resistance 33733.5Ω
[12:10:07][D][sensor:093]: 'Variable resistance 1': Sending state 33733.47656 Ω with 1 decimals of accuracy
[12:10:09][D][sensor:093]: 'GPIO5': Sending state 3.10700 V with 5 decimals of accuracy
[12:10:09][D][resistance:039]: 'Variable resistance 1' - Resistance 33733.5Ω
[12:10:09][D][sensor:093]: 'Variable resistance 1': Sending state 33733.47656 Ω with 1 decimals of accuracy
[12:10:11][D][sensor:093]: 'GPIO5': Sending state 3.10700 V with 5 decimals of accuracy
[12:10:11][D][resistance:039]: 'Variable resistance 1' - Resistance 33733.5Ω
[12:10:11][D][sensor:093]: 'Variable resistance 1': Sending state 33733.47656 Ω with 1 decimals of accuracy

Here’s my sensor config:

sensor:
  - platform: adc
    pin: GPIO5
    attenuation: 12dB
    name: "GPIO5"
    id: resistance_voltage_1
    icon: mdi:bed
    accuracy_decimals: 5
    update_interval: 0.5s
    filters:
      - median:
          window_size: 25
          send_every: 5
          send_first_at: 1
    entity_category: "diagnostic"
  - platform: resistance
    id: variable_resistance_1
    name: Variable resistance 1
    sensor: resistance_voltage_1
    configuration: UPSTREAM
    resistor: 470kOhm
    reference_voltage: 3.33V
    icon: mdi:resistor
    entity_category: "diagnostic"

Any suggestions? Is my circuit even correct?

Did you first determine which pair of wires actually changes resistance with a multimeter?

You shouldn’t swim before you can walk.

Yes, the green and yellow pair changes resistance when I attach a multimeter and apply pressure to the pad.

Simplify.

  • Green lead to 3.3v.
  • Yellow lead to:
      • GPIO35 (or equivalent pin chosen in the ADC sensor of your YAML)
      • 460K resistance
  • Other side of 460K resistance to GND.

Skip the capacitors for now.

You should see the ADC value change up or down when you compress the resistance. It’ll be noisy because of no capacitors, but at least you can confirm it’s happening and you can add the caps later.

Also, what is the range of resistances your thing goes over? You may have to select a different resistance to get a good ADC measurement.