Bed Occupancy Sensor

I got frustrated with off the self bed occupancy sensors that would trigger false positives when I laid out cloths on my bed, or false negatives when I rolled over in the night.

I made my own solution using cheap load cells that essentially turns my bed into a giant scale. The goal was accurate boolean presence but the accuracy ended up around +/- 1kg.

This was fairly inexpensive to build, around $100 in development and $100 for the final product. This could be done for around half the cost with an ESP8266 or RFM69, but I like the reliability and low latency of Ethernet.

Home Assistant Card

Hardware picture

Github project

34 Likes

Fantastic project, how did you mount the sensors on to the bed leg, can you post some pictures. How many persons on the bed can it detect? I see that the sensor detects up to 50 kg/leg?.
I have cobbled together something from 2 plates separated by an insulator and springs which sort of works but is fiddly. This seems to be much better solution and I am definitely going to build some. Are you offering the board for sale?
Thank you for posting.

1 Like

It can detect any number of people in theory, as long as the load cells can support the mass of the bed + persons. My setup can comfortably determine 1 person vs 2 persons, even if they both roll around in the night.

I had plans to mount the load cells on the legs of my bed, and do a much more elaborate setup. When I bread boarded this I just tested it out by sliding them under the legs of my bed with the 3D printed holder, and it worked out much better than I expected. Even though there is nothing holding them on the floor, or to the bed they don’t slide around, the weight of the bed frame keeps them in place.
I was going to buy more expensive load cells that can hold more weight, but these cheap ones work surprisingly well, and if they break from overloading it’s only a $2 part.

As for the boards, I made a mistake on the boards I have fabricated, I misread the TRS jack datasheet, and had to put in a couple jumpers. The design published on github does not have this mistake.

If you don’t mind cutting a couple traces and putting in a couple jumpers I can send you one of the boards for the cost of shipping from Canada.

Are this PCB comes as fully populated? I do not have the facility or skills to solder the small components.
If it is fully populated I am happy to get one of the board. I have already ordered the load cells from Aliexpress.

Sorry, no. Populating these boards takes quite a while for me since I am soldering each joint manually with a fine point iron.

No worries, I am planning to implement this with a Wemos D1 Mini, now the wait for load cell from China begins!!

found this which might help using a wemos

2 Likes

I could not get the scale code working on a Wemos, It kept on resetting.
Worked ok with a mysensors sketch.
I did not realize the load cell needs a base to sit on and was getting inconsistent readings. This printed part solved that issue.
Anyway thank you for sharing your project.
Here is the mysensors sketch if anyone is interested

/**
 * Documentation: http://www.mysensors.org
 * Support Forum: http://forum.mysensors.org
 *
 * http://www.mysensors.org/build/light
 * copied and adapted from HA Mysensors documentation
 */

#define MY_DEBUG
#define MY_RADIO_NRF24
#include <HX711.h>
#include <MySensors.h>

#define SN "BedScale"
#define SV "1.0"
#define CHILD_ID 1
unsigned long SLEEP_TIME = 3000; // Sleep time between reads (in milliseconds)

// Scale Settings
const int SCALE_DOUT_PIN = 3;
const int SCALE_SCK_PIN = 2;
HX711 scale(SCALE_DOUT_PIN, SCALE_SCK_PIN);

MyMessage msg(CHILD_ID, V_WEIGHT);

float lastWeight = 0;
bool initialValueSent = false;

void setup()
{
  sendSketchInfo(SN, SV);
  present(CHILD_ID, S_WEIGHT);
  scale.set_scale(-1830341/80);// <- set here calibration factor- read value with known weight(80Kg)/ Known weight
  scale.tare();
}

void loop()
{
  if (!initialValueSent) {
    Serial.println("Sending initial value");
    send(msg.set(String(lastWeight)));
    Serial.println("Requesting initial value from controller");
    request(CHILD_ID, V_WEIGHT);
    wait(2000, C_SET, V_WEIGHT);
  }
  float weight = scale.get_units(1);
    //Serial.print("Weight is:");
    //    Serial.println(String(weight, 2));
  if (weight != lastWeight) {
      send(msg.set(weight, 2));
      lastWeight = weight;
  }

  sleep(SLEEP_TIME);
}

void receive(const MyMessage &message) {
  if (message.type == S_WEIGHT) {
    if (!initialValueSent) {
      Serial.println("Receiving initial value from controller");
      initialValueSent = true;
    }
  }
}```
5 Likes

Hi,
Just wanted to say thanks for this project. I got this working great using an nodemcu, hx711, and the 50kg load cells. I couldn’t be happier with the results. Thanks for the great idea!

Hi, can you please share your code?

Here is my code for the nodemcu. I’m certainly not a seasoned programming, this is mostly just bits and pieces stolen from others.

#include "HX711.h" //This is for the Load Cell Amp
#include <ESP8266WiFi.h> //This is for the WiFi
#include <PubSubClient.h> //This is for the MQTT Connection

#define topic "home/bedroom/bed/load"

HX711 scale(D1, D2);  //Sets the HX711 Pins

//Wifi Info
const char* ssid     = "WIFI SSID";
const char* password = "WIFIPASSWORD";

//MQTT Servo Info
const char* mqtt_server = "192.168.1.2";
WiFiClient espClient;
PubSubClient client(espClient);

//Variables
float load;
float oldload=0;
float loadchange;

//Connect to WIFI
void reconnect() 
{
  // Loop until we're reconnected
  while (!client.connected()) 
  {
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect
    if (client.connect("ESP8266Client")) 
    {
      Serial.println("connected");
      // Once connected, publish an announcement...
      //client.publish("outTopic", "hello world");
      // ... and resubscribe
      client.subscribe("inTopic");
    } 
    else 
    {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

    
void setup() 
{

  //MQTT Setup 
  client.setServer(mqtt_server, 1883);
 
  /* Explicitly set the ESP8266 to be a WiFi-client, otherwise, it by default,
     would try to act as both a client and an access-point and could cause
     network-issues with your other WiFi-devices on your WiFi-network. */
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  
  while (WiFi.status() != WL_CONNECTED) 
  {
   delay(500);
  }
 
  //Set scale calibaration and zero scale
  scale.set_scale(-8825.f);   // this value is obtained by calibrating the scale with known weights; see the README for details
  scale.tare();				        // reset the scale to 0
}


void loop() 
{
  
  if (!client.connected())
  {
    reconnect();
  }
  client.loop();
  
  load=scale.get_units(10), 1;

  loadchange=oldload-load;
  
  if(loadchange >= 10 || loadchange <= -10)
  {
    client.publish(topic, String(load).c_str(), true);
  }
  
  oldload=load;
  delay(1000);
}
3 Likes

Very interested in this and can you give more detail? such as components、Wiring diagram.etc
thank you

i made a bed occupancy sensor with two load cells mounted on a latch under my mattress. i thought this might be much easier than using four sensors, which it actualy is. it’s invisible, too. to control the sensor, i used the newest ESPeasy test-version, which contains experimental HX711 support. makes it really easy on the esp8266 side.

the sensor has been working reliably for a couple of weeks now and i documented it in german here:

8 Likes

two load cells ? detects up to 50 kg? that’s ok for 2 person?

1 Like

I’m also interested in this?

the weight is not applied directly to the load cells, as the weight is distributed across the mattress and then across each latch of the slatted bed frame. so the actual measured weight, even when there are two persons on the mattress, is around 20-35 kg. the only way to apply more weight ist point loading — standing on one foot on the matress, right where measuring latch is located. but even then, the weight will get distributed by the mattress — and who wants to stand on a bed, anyways?

1 Like

Yes, I made one based on your article but I want to know how to get the correct value, it is always unstable

it is unstable as long as you move, but if you round it in homeassistant to full kilograms, it’s more or less stable.

sensor:
  - platform: mqtt
    state_topic: "bett/weight/Weight"
    name: "bett gewicht"
    value_template: "{{ (value | float /1000) | round(0) }}"
    qos: 0
    unit_of_measurement: "kg"
    availability_topic: "bett/status/LWT"
    payload_available: "Connected"
    payload_not_available: "Connection Lost"

to keep mqtt traffic low, you could also try to round it on the esp or write a rule, that only transmits significant changes.

Great idea, I’ll try making it for cheap as possible, just ordered ESP8266, USB Programmer, HX711 and 4 Load cells, everything just for 6.6$

Does the end result show accurate weight? can it be trusted as weight tracker or it’s more used like binary sensor?

@g0g0 can you put tjhe link of load cells?