Saturday, June 10, 2023

Local Automation for a Window Air Conditioner

 

I recently added a window air conditioner to keep the bedroom cool at night.  This air conditioner was a "smart" unit, with built-in wifi.  But like most commercial smart devices, it required installation of a (poorly reviewed) mobile app, creation of a cloud account and Internet connectivity (with reports that the unit routinely dropped off of wifi).  While I did want to use automation for control of this AC unit, I wanted that control to be local like most of my other devices.  So that's what I set out to do. 

Background Information and Goals


If you prefer, you can watch a YouTube video that covers many parts of this project and the refer back to this article for full details and step-by-step instructions.

Since this air conditioner was just meant to add auxiliary cooling to the bedroom at night for sleeping, it would ideally turn on automatically an hour or so before bedtime and turn off again at whatever time I get out of bed in the morning, since this can vary based on the day of the week.

Now there is some work being done on creating Home Assistant integrations for Midea air conditioners.  But at the time of this writing, they either rely on the cloud app (which defeats the purpose of local control) or they do not support my particular model.  So, for now, I was on my own.

The initial quick and easy solution was to flash Tasmota to a Sonoff S31 smart plug.


Since the Sonoff S31 is rated for up to 15 amps, it should have no problem handling the load of the A/C (which peaks at around 5A).  With this option, I'd have local integration into Home Assistant and could at least turn the unit off and on based on time and the current temperature in the room (this room already had temperature and humidity sensor integrated into Home Assistant).  So, a very simple automation in Home Assistant was:

At 10:00pm each night, if the temperature is 70°F or above, turn on the unit.  Luckily the unit did remember the prior setting even after power was cut, so it would start up at with the last settings.

But this method had a few major drawbacks.  First, to shut the unit off in the morning required me to manually turn off the power via the Sonoff, which could easily be forgotten and the AC unit would run unnecessarily all day.  Next, this particular unit has automatic louvers that would open and close when the unit was powered off and on. 


This helps to keep out the warmer outside air when the unit is not running.  But killing the power via the Sonoff S31 left these louvers opened all the time.

Finally, I'm not sure whether continuously killing the power to the unit in this manner could damage or shorten the life of the unit.  So a different approach was needed.

The Dual Approach


I decided to approach the automation of the air conditioner with two different DIY devices.  Fortunately, the A/C unit did come with a remote control, meaning it had a built-in IR receiver.


If I could build an IR transmitter using an ESP8266 or ESP32 and determine the proper codes, I could use something like ESPHome and have local control over nearly all the features, including the ability to turn the unit off and on appropriately.

This still left the issue of how to turn the unit off after rising in the morning, since this isn't always at the same time for me.  To handle that automation, I'm going add something I've wanted for quite a while... a bed occupancy sensor.  And this bed occupancy sensor can be used for many other automations as well.

Note: I'm opting to create two separate controllers due to the layout of my particular bedroom.  However, you could use a single ESP controller for both the IR transmitter and the bed sensor (and even add an optional room temperature sensor).  See a potential 'one controller' wiring option near the end of this article.

Parts List


Since I'm really approaching this as two separate projects, I'll list the parts by project along with a list of common items .  Note that these are the particular parts I used, but alternates could be used.  For example, even though I'm using a Wemos D1 Mini ESP8266 for the bed sensor and an ESP32 mini for the IR transmitter/receiver, you could use an ESP8266 or ESP32 for either one.  Some other parts are optional, but the lists below are the actual parts I used to build the projects as shown.

IR Transmitter/Receiver

QTY

Item Description

Notes

1

Mini ESP32

ESP8266 can be used

 

 

 

 

Only one of the following needed

 

1

IR Transmitter

Best tested range

or

IR Transmitter/Receiver Pair

Comes in transmit/receive pairs

or

IR Transmit/Receive with ESP8265

Did not test: should work w/ESPHome

 

 

 

1

Logic Level Shifter

Optional – may increase IR range

1

ElectroCookie ½ Size Protoboard

 

1

USB Slim Wall Charger

 

1

MicroUSB Cable

 

1

Dupont Connector & Crimper Set

 Optional

 

 

 

 

 

 


Bed Occupancy Sensor

QTY

Item Description

Notes

1

Force Sensitive Resistor Strip

 

1

Wemos D1 Mini (ESP8266)

ESP32 can be used

1

Resistor Kit

Value needed based on your install

1

ElectroCookie ½ Size Protoboard

 

1

USB Slim Wall Charger

 

1

MicroUSB Cable

 

4

Spade Connectors

 

2

Normally-open Push Buttons

Optional add-on

1

Logic Level Shifter

Optional (for future LED add-on)

 

 

 

 

 

 


Common Parts (used in both projects, most are optional)

QTY

Item Description

Notes

1

¼” Braided Sleeve – 25 ft.

 

1

Heat Shrink Tubing Assortment

 

1

½ Size Breadboard

 

1

Breadboard Jumper Kit

 

1

Alligator Test Lead Kit

 

-

Project Boxes (for no 3D printer)

Various sizes – check your board size

-

Misc. Wire: 20-24 gauge

 

 

 

 

 

 

 


Some of these links may be Amazon affiliate links.  Use of these links will not affect your pricing, but this channel may earn a small commission if you make a purchase.

Creating the IR Transmitter


This proved to be the more challenging of the two parts of this project... mostly due to issues with sourcing an appropriate IR transmitter.

Selecting an IR Transmitter



I decided that I would test two different IR transmitters to see if one option offered better range, as I wanted some flexibility in terms of where I could place the transmitter in relation to the A/C unit in the bedroom.  After some initial issues where neither board appeared to function (this was resolved by changing the GPIO pin used for the data line), testing both on a breadboard showed that the IR transmitter on the left in the above photo had a range of 2-4 feet, while the one one the right still worked reliably from around 6-8 feet.  The distance of both was improved somewhat by running the data signal through a level shifter (more on this below), but the transmitter on the right was the clear winner for range.

As a side note, while you cannot see the IR transmitted signal with the naked eye, you can use your cell phone camera.  You will be able to see the LED light up via the camera when transmitting.  

Cell phone camera can detect when the transmitter sends IR signals

This helped me to resolve the initial issue I had when the boards were not transmitting.  I'll just mention my experience here in case you run into the same problem.

I initially had the transmitter data pin connected to GPIO32 on my ESP32.  I chose this pin because it was the pin used in the ESPHome documentation example for an IR transmitter: 

# Example configuration entry
remote_transmitter:
  pin: GPIO32
  carrier_duty_percent: 50%

I'm unsure why this pin did not want to work (unless it also had something to do with the fact that GPIO32 is also one of the ADC2 pins that does have a conflict with wifi... even though I was not using analog input for this pin).  When I changed the data line to use GPIO22, the transmitters began working normally.

Note that I did order an additional option as a transmitter, but did not test it since I was able to get the other versions to work:

All-in-one option with ESP8265

This is an interesting option as not only does it have both an IR transmitter and receiver on the same board, it also has a built-in ESP8265.  This means it could be used "standalone" without a separate ESP32/ESP8266 board.  The ESP8265 uses the same code set as the ESP8266 and is theoretically supported by ESPHome.  It is a little more difficult to flash as there is no onboard USB port, so a USB-to-Serial adapter is needed.  I did not try this option, so I cannot speak to how well it might (or might not) work.  But I included it here as another option and this would also create the smallest possible controller.

Selecting an ESP Board


As mentioned above, I did opt to use a mini ESP32 for the controller.  While the IR transmitter can also be used with a D1 Mini/ESP8266, there were numerous reports about better performance with the ESP32 when using the ESPHome IR transmitter platform.  Again, I did not test this, but just opted to use the ESP32.

Wiring Diagrams


The basic IR transmitter is a really simple device, and can theoretically be done without any soldering and just three Dupont jumpers.  I'll show this diagram, then some additional wiring diagrams with optional add-ons.

Note: I'm using the mini ESP32 for my controller and that is what I will show in all my diagrams.  I will only be using the "D1 Mini" equivalent pins (those highlighted in white on the board).  But you could easily substitute a full size ESP32 or a D1 Mini/ESP8266.  All will work.  Just substitute the pins based on your selected board and update the ESPHome code below as appropriate.

Basic Controller

Click to enlarge

At the most basic, you can create a non-soldered version (if your board already has the pins installed) by using three female Dupont jumpers and connect 5V, GND and your selected GPIO pin (I opted for GPIO22 and as noted above, I had issues when attempting to use GPIO32).  This is all you really need for a basic IR transmitter.

Click to enlarge

You could also recreate this same version on an ElectroCookie or other prototype board.  The actual IR transmitter could also be mounted on the board if desired, but I'm opting to keep the IR transmitter connected by wire leads as it gives me some additional mounting options for the transmitter in the final project.

You will likely need to mount the ESP board on to some sort of ElectroCookie type board for the next few options, since multiple 5V and ground connections are needed.

Adding an IR Receiver

Certain brands/protocols of air conditioner units also support the inclusion of an IR receiver.  You can check the current list of which protocols are included here.  Adding a receiver gives you the option of keeping the data in Home Assistant "in sync" should you make a change to the AC unit via the original remote.  For example, without the IR receiver, if you use the original remote to change modes or temperature settings, Home Assistant will have no way to know about those changes, so it will show a different setting or value than the unit itself.  With the IR receiver, you can capture those changes and Home Assistant will update accordingly.

Click to enlarge

Adding a receiver is almost identical to the IR transmitter.  Connect the receiver to either 3.3V or 5V (check the receiver specs) and the data line to an appropriate GPIO pin.  Then add the code to ESPHome (covered below).

In my case, during the breadboard testing, I found the receiver to be of little use and positioning both the transmitter and receiver in an optimal position for both to function reliably was a challenge in my particular room layout.  And honestly, if I have the AC unit automated in Home Assistant, I will rarely, if ever, use the remote.  So, I opted to omit the receiver in my final install.  But I'm covering it here in case the inclusion of the receiver makes more sense in your project.

You can also use an IR receiver to capture codes from any IR remote in the event your IR device is not listed as a known platform.  You can then transmit these codes via ESPHome to control your device.  The method to do this is covered in the ESPHome documentation.

Note that while I'm focusing on automation of my AC unit, you can use the combination of an IR receiver and transmitter in many different ways with Home Assistant.  For example, you could place a receiver/controller in one room of your house and a transmitter/controller in another.  When Home Assistant receives a code on the receiver, automation could be used to send a code via the transmitter, basically creating an IR extender... where you could use a standard IR remote in one room of your house to control an IR device in a completely different room.

Adding a Level Shifter

During my very unscientific testing of the range of the various IR transmitters, I found that by adding a level shifter to boost the data signal from the 3.3V output by the ESP to 5V for the transmitter (assuming the transmitter has a working voltage of 5V as mine did) at least appeared to help with the range.  This may have been a fluke or inaccurate testing, but I decided to include the level shifter, as it won't hurt and could possibly help the final range.

Click to enlarge

If you've ever done an LED project, then you may already be familiar with the level shifter and it is used exactly the same here.  You take the outgoing 3.3V signal line from the ESP GPIO pin and run it into one of the channels on the low voltage side (LVx) of the shifter, which is also connected to 3.3V and GND via the LV and GND pins on the same side.  On the other side, you connect 5V and GND to the HV and GND of the shifter.  The outbound data line that connects to the IR transmitter using the same high voltage channel (HVx) as the source.

Again, use of the shifter is completely optional... and may not make a major difference, but I did opt to include it in my install, so I'm showing the wiring diagram that I used.

ESPHome Code

I'm only including the key components of the ESPHome code I used here.  You can find my complete ESPHome listing in this Gist file.  But do note that mine is specific to my Midea brand of AC unit.  You will need to adjust for your particular platform, so you should refer to the official ESPHome IR Climate documentation for more details.

remote_transmitter:
  pin: GPIO22
  carrier_duty_percent: 50%

remote_receiver:
  id: br2acrcvr
  pin:
    number: GPIO19
    inverted: true
    mode:
      input: true
      pullup: true
  # high 55% tolerance is recommended for some remote control units
  tolerance: 55%

climate:
  - platform: midea_ir
    name: "Bedroom2 AC"
    use_fahrenheit: true
    sensor: br2_room_temp
    supports_heat: false
    visual:
      min_temperature: 60
      max_temperature: 75
      temperature_step: 
        target_temperature: 1.0
        current_temperature: 0.1

sensor:
  - platform: homeassistant
    id: br2_room_temp
    entity_id: sensor.bedroom2_temperature

Again, refer to the official ESPHome documentation for details for your particular system, but the code defines the IR transmitter, optional IR receiver and the Home Assistant climate entity.

I will make a note here about the climate entity and its use in Home Assistant. 


The climate card shows both the current temperature and the set point of the device (AC unit in this case).  However, there wasn't a way for me to get the current room temperature from the thermostat in the AC unit.  

DHT22 Temperature/Humidity Sensor

Luckily, I already had a temperature sensor in that room (using a D1 Mini and a DHT22 temp/humidity sensor).  The climate definition allows you to specify a sensor to use for the current room temperature.  If you don't have a room temperature sensor, you could easily add the DHT22 or another sensor to either this controller or the bed sensor controller below.  I do cover these sensors in other videos/articles... and there is plenty of information online about building a temperature sensor using an ESP and ESPHome, so I won't cover the details of that here, but I do provide a potential 'one controller' wiring diagram near the end of this article that includes a DHT22 sensor.

Since I already had this sensor, I simply imported the existing Home Assistant temperature entity into ESPHome and then could reference that sensor via its ID (br2_room_temp) in the sensor setting for the climate entity.

If you do not currently have a temperature sensor in the room, you could either build a simple sensor with a D1 Mini and DHT22 or use one of the many room sensors that are now available that use bluetooth.  And if using the ESP32 for this project, you can add Bluetooth proxy to your ESPHome code.  These options are beyond the scope of this article, but you can find lots of information online about building a temperature sensor for Home Assistant.

Bench Testing


Like most of my projects, after installing the ESPHome code, I started with a test on a breadboard.


I could then either use the Developer-States page in Home Assistant or the climate card on a dashboard to try sending signals to the AC unit from different positions around the room.



This was to test that the codes were correct, that the AC unit responded appropriately and to test the range and positioning in the room.  It was during this testing (with different brands of IR transmitters) that I opted to add the level shifter.


Note that the original breadboard version also had the IR receiver... but it was from this testing that I decided to omit the receiver from my installation.

Once I was happy with the range and potential positioning, I was ready to transfer to a final soldered version. 

Final Version



The final build is wired just like the breadboard version, but uses soldered components on an ElectroCookie prototype board.  The actual IR transmitter could have been mounted on the same board with the ESP32, but I opted to have the transmitter connected by cable so it will allow me to mount it separately for better placement and to keep the larger controller enclosure hidden.


I opted to use my own Dupont connectors should I need to create a longer version and/or replace the sensor or controller down the road.  I enclosed the wiring in some braided sleeve sealed with some heat shrink just to give it a neater appearance.


For the IR transmitter itself, I 3D printed a small 'wedge' that allows the transmitter to slide in and out and gives me a solid mounting surface, while also providing an approximate 45° angle which will help with alignment towards the AC unit for my mounting location.


The IR transmitter is pointed directly at the AC unit in this manner, and is approximately 6 feet (1.8 m) from the front of the AC.  This configuration also allowed me to tuck the larger controller box and power cord back into the corner of the TV stand, completely out of sight.

While the IR transmitter and controller are placed in 3D printed parts, a 3D printer is not required for the project.  You can find small project boxes of various sizes on Amazon and elsewhere that can easily be adapted for your own controller.

See the section after the bed occupancy sensor for more information on Home Assistant integrations and automations

Drawbacks and Caveats


One major issue with this type of integration is that if the air conditioner is manually adjusted through the local controls on the unit itself, those changes are not communicated back to Home Assistant.  This means that the two systems could fall out of sync.  For example, if the A/C mode or temperature set point is changed through the unit's control panel, then Home Assistant and the actual unit will be in disagreement.  For me, I plan on only controlling the unit via Home Assistant automation, so it should not be an issue... but it is worth noting.

Alternate Methods

   
Depending on your particular air conditioner (and willingness to potentially disassemble parts of the A/C), other options do exist.  For example, on some Midea units, a USB/UART port is available on the control board.  Using a special dongle, it is possible to not only control, but receive data back from the AC unit in Home Assistant... which alleviates the caveat listed above.  If you are interested in this, or other alternative methods, I recommended you do some searching online as other resources are available.  Of course, you could also just install the manufacturer's cloud app and Home Assistant integration (if any) and likely recreate some of the automations I'm using.  Naturally, if you lose Internet connectivity, your remote control and automations will no longer function.

Creating the Bed Occupancy Sensor


As I mentioned, I had wanted to add a bed occupancy sensor to my home automation for quite some time.  But the most common approach I had seen used a load cell under each leg of the bed and creating a Wheatstone bridge.  This required running wiring to each corner of the bed... more or less turning the bed into a giant scale and using pressure/weight to determine occupancy.  But I have a Sleep Number bed that just wasn't conducive to this sort of setup... and would have more or less required complete disassembly of the bed to install.  This did not have a high WAF!  There are also other methods that use pressure mats, contact switches, etc.

But I then ran across a Home Assistant forum posting by tom_l (linked below) that used a force sensitive resistor to create an occupancy sensor.


This force sensitive resistor changes resistivity from very high (in the megaohm range) with no pressure applied, down to single ohm resistance when force is applied.  By connecting this to an ESP8266 and a resistor, the voltage can be measured and used to determine whether the bed was occupied or empty.  And the best part, it will be installed under the mattress and only require two wires leading to the controller!  Now, this won't be as accurate as the load cells, but we only need to determine whether the bed is occupied or not... the actual value or force applied really doesn't matter.

Testing the Force Sensitive Resistor



To test the FSR strip, you can simply connect the two leads to a multimeter set to resistance (Ω) measurement.  Now, note that when no pressure is applied to the strip, the resistance is > 10 MΩ so it may be out of range of your meter.  But simply press down and apply a little pressure to the strip and the resistance should quickly drop down into the kΩ or even 100Ω range.  

Attaching Lead Wires



Lead wires need to be attached to the two prongs or pins from the force sensitive resistor.  Soldering is the best option.  

Use the absolute minimum heat needed and work quickly!

Applying too much heat will likely melt the FSR plastic and may damage or even destroy the sensor.  The best method it to tin both the leads and your wire with some solder and then quickly attach the wires.  There are special clips made for attaching wires to the FSR, but I have not tried them and cannot speak to how well they may or may not work.


After soldering, add some heat shrink tubing around each lead and a larger piece around those two.  This will help support the connection... but again, use the minimum heat needed for the heat shrink.

I highly recommend you test the strip again for varying resistance with pressure after attaching the leads to assure the strip wasn't damaged by heat during soldering.  You should also support that connection when moving the strip around during testing so as not to stress the very thin leads from the FSR.  Once installed under the bed mattress, this connection will lay flat and can be taped down for extra support.

Determining Resistor Value - Part 1


A resistor will need to be added to the controller to create a voltage divider so that we can measure voltage to determine when the bed is occupied vs. unoccupied.  The value of this resistor will be highly dependent upon your particular situation.  Differences in mattress weigh, placement of the FSR, body weight and other factors will influence the final selection of resistor that provides the best range of voltages.  But you can get an initial starting value now... and then fine tune that after the controller is built.

This is my final install on a Sleep Number bed

Temporarily install the FSR strip under the mattress on a solid surface.  For a conventional bed with box springs, place the FSR under the box springs and on a supporting slat.  You can try different locations for the strip, but I found the most consistent results with the strip located about in the same location as my waist when in bed.  But you can try up around your shoulder area as well.  Add a little masking tape to hold the strip in place if necessary.

Note that since the FSR strip is only about 24" wide, this is only going to work for one side of anything larger than a twin bed.  If you wish to measure occupancy on both sides of a bigger bed, you will need to use two FSR strips.  More on options for that below.  For now, focus on just one side of the bed and center the strip under the normal sleeping position for that side.

Connect the leads from FSR to your multimeter, again set to measure resistance.  With the bed 'unoccupied', but as it would otherwise normally be with sheets, blankets, etc. measure the resistance.  You may need to set your meter in the megaohm (MΩ) range to get a reading at this point.  Note the approximate value.

Now get into bed into your normal position and note the resistance reading.  It is likely that you will need to adjust the range of your meter down to the low kΩ range.  Note the approximate value again.

Repeat the unoccupied and occupied readings a dozen times or so, altering your position in bed for the occupied readings to reflect your potential normal sleeping positions.  Calculate an average for both the unoccupied and occupied reading.

Now, drop those average values into the following calculations, converting both to the same ohm units:


In my case, I had an average of 3 MΩ when unoccupied and 500 Ω when occupied.  Converting both values to kiloohms (kΩ):


This will provide a general starting value for resistors to test, but we will fine tune this using a breadboard version of the actual controller.  Don't be concerned if your calculation results in a value significantly different from mine.  Again, this is influenced by numerous factors, including mattress weight.  As I mentioned, I have a Sleep Number bed which does not have box springs, so my mattress likely weighs significantly less than a standard bed.

Building the controller


Click to enlarge

Before creating the final soldered version shown above, you'll want to duplicate this on a breadboard.  This will allow you to easily swap out different resistor values during final testing.  But the wiring is the same on both:

I'm using a Wemos D1 Mini (ESP8266) as I only need one analog input.  If you need to use two FSR strips to determine occupancy on both sides of a larger bed, then you can either use an ESP32 or dual D1 Minis on a single controller board (see below).  The wiring is the same whether using the ESP8266 or ESP32... pins are just located in different positions and the ESP32 has multiple pins for the analog connection (just be sure to use on of the ADC1 pins and not ADC2 as these conflict with wifi).

The ESP board will be powered by USB.  Any USB source of at least 2 amps will be adequate... so an old phone charger would be just fine.

Connect the 5V and GND pins to the (+) and (-) on one power rail and the 3V3 pin to the (+) power rail on the opposite side.  Since the D1 Mini only has one ground pin, connect the ground rails together as shown above.

Connect 3.3V from the power rail to one side of a resistor (begin with a resistor near the range you calculated above).  To the other side of the resistor, connect one of the leads from the FSR and a line to the ADC of the ESP board.  On the D1 Mini, this is the A0 pin.  Finally connect the other lead from the FSR to one of the ground rails.  When done on a breadboard, note that it should look nearly identical to the soldered version above:

Click to enlarge

Just use a couple alligator clips to connect the FSR leads for the breadboard.  Before we can test and fine tune the resistor used, we need to install the ESPHome code onto the controller.

Installing the ESPHome Code


I'm not going to cover installation of ESPHome into Home Assistant, or the process of creating a new ESPHome node, as this is covered in many other places (including some of my other projects), but the new web installer makes the process very easy.   Simply select the type of ESP board you are using and all the necessary base information, such as wifi, API key, etc. will be created for you.  I'll just list the information you need to add to that base file here.  You can find a complete copy of my ESPHome code and the related Home Assistant automations in this Gist file.

binary_sensor:
  - platform: template
    name: "Bedroom2 Bed Occupied"
    id: br2_o
    lambda: |-
      if (id(br2_bed_sensor).state < id(trigger_level).state) {
        return true;
      } else {
        return false;
      }

sensor:
  - platform: adc
    pin: A0
    name: "Bedroom2 Bed Sensor"
    id: "br2_bed_sensor"
    icon: mdi:bed
    update_interval: 0.5s
    filters:
      - multiply: 3.3
      - sliding_window_moving_average:
          window_size: 10
          send_every: 1
      - or:
          - throttle: 180s
          - delta: 0.02

  - platform: homeassistant
    name: "Trigger Level"
    id: "trigger_level"
    entity_id: input_number.bedroom2_bed_trigger_level

Note that this ESPHome code uses an input number from Home Assistant as a trigger level for the binary sensor.  This will allow you to adjust the trigger level of the system by changing the input number in Home Assistant.  However, this also means that you must manually create the input_number in Home Assistant before this code will compile and work.  You can create the input number via YAML or by using the UI Helper function.  Here is the YAML version of that input number:

input_number:
  bedroom2_bed_trigger_level:
    name: Bed2 Trigger Level
    min: 0
    max: 3.5
    step: 0.05
    unit_of_measurement: V
    icon: mdi:arrow-collapse-down

Naturally, you can change the name of the input boolean, icon, etc.  Just make sure the name you use is also the same name you use in the ESPHome code above.

The ESPHome code is going to expose two entities to Home Assistant (my names shown, but you can use your own entity names):

sensor.bedroom2_bed_sensor: This will return a measured voltage between 0 and 3.3V and varies based on the resistance created by the FSR strip.

binary_sensor.bedroom2_bed_occupied: This will return true ('on') when the bed is occupied and false ('off') when unoccupied based on the measured voltage being lower or higher then the threshold number from the input_number value.

Once you've installed the ESPHome code to the controller and integrated the new ESPHome node into Home Assistant, we can now test the system to determine the final best resistor value to use.

Determining Resistor Value - Part 2


For the final part of determining the ideal resistor value, you will once again place the FSR under the mattress in approximately the planned final location.  But this time, connect the FSR to the breadboard controller.  You'll also need to have a way to see the Home Assistant states page (laptop, tablet, etc.).

Start with a resistor around the range you calculated in Part 1.  First, see what the reported voltage is in Home Assistant when the bed is unoccupied:


Ideally, this should be above 3.0V.  When this voltage is above the input number trigger level, the binary sensor should be 'off' or false for the bed occupancy.

Then lay down in the bed in your normal sleeping position and again note the voltage.  


Again, ideally this value should be around 1.0V or less.  When this values is below the input_number trigger level, the binary occupancy sensor should be "on" or true.  

You may need to try different resistor values to get the ideal range.  And the ideal value could vary greatly from install to install.  As tom_l stated in his post, one install used a 300Ω for one install and 3 kΩ for another identical install.  Consider trying much higher and much lower values until you find the resistor that gives you the broadest voltage range between occupied and unoccupied.  Also try different positions in the bed to see that you can set an input_number trigger value that gives you a consistent binary_sensor on/off reading.  In my case, the ideal resistor was 33 kΩ, which was pretty close to my original calculated value of 37.8 kΩ.

Once you've determined the best resistor value, you can transfer the breadboard version to the ElectroCookie prototype, a PCB or other more permanent version.  This is technically all you need for the bed sensor, but before creating the final version, you may want to consider adding some optional features.

Adding optional components


Since only one pin is being used on the ESP8266 (or ESP32), I opted to add a few additional components to my install that could be used to expand the system now or at a later time.  These are completely optional and are not needed for basic functionality of the bed sensor.

Push Buttons

I decided to add two normally-open pushbuttons to my controller, connecting one leg of each button to a GPIO pin and the other leg to ground (see diagram below).  This will give me buttons by the bed that I can use to launch automations, disable the air conditioning automations or other future needs.

Logic Level shifter for LEDs 

I also decided to go ahead and install a logic level shifter for the $1 it costs and wire it up for future use to add LEDs to the controller.  If I want to potentially add LEDs under the bed at a later time that can be automated with the bed sensor, I'll already have a controller available to use and won't need to add a second controller just for the LEDs.

Click to enlarge

If I opt to add LEDs at a later time, then I'd just have to add the wiring shown with dashed lines to the existing controller.  Of course the addition of push buttons and/or the LEDs will require updates to the ESPHome code as well.  I won't cover that here, but you can look up how to add push buttons and LED lights to ESPHome on the official ESPHome web site or see a complete copy of my code in this Gist file.  I will define the buttons as GPIO binary sensors and, if added later, the LEDs as a NeoPixelBus light. 

Final version

Two sensors for larger beds


As mentioned above, the FSR strip is only about 24" long.  This means it is probably only good for one side of a standard or larger size bed.  If you want to determine occupancy on both sides of the bed, you will likely need two FSR strips.  While you could create two completely separate controllers, here are a couple of alternative options that still result in one "controller" and one power supply.

Note: I have not built or tested either of the following options, but they should work as long as you follow the notes listed under each type.

Dual ESP8266 Controllers

Click to enlarge

This option places two separate Wemos D1 Minis (ESP8266) on a single board, powered by a single 5V power supply.  Here are some additional notes about this configuration:
  • Be sure to join the ground rails on the end of the board before mounting the second D1 Mini.
  • Each controller/FSR strip may need a different resistor value just due to variances in the strips, position on the bed, weight distribution, etc.  Each controller/resistor combination should be tested for the best value using the methods listed above.
  • Each D1 Mini will have its own separate ESPHome code installed, meaning you will have two independent ESPHome nodes in Home Assistant.  The ESPHome code will be nearly identical, but each of the entities should have unique identifying names, such as sensor.bed_sensor_left and sensor.bed_sensor_right.  The same goes for the binary sensors and input number helpers.  In essence, you are creating two separate devices but they are sharing the ElectroCookie board and the power supply.
Single ESP32 Controller with Dual FSR Strips

Click to enlarge

Since the ESP32 has multiple pins that can act as analog/ADC pins, it is possible to connect two FSR strips to one controller.  There are a few additional notes if using the ESP32 as well:

  • The ESP32 boards are generally one row too wide to allow a row of open through-holes on each side of the board.  For this reason, either the connection to 3V3 and ground (recommended) or the blue analog lines shown in the above diagram will need to be wired on the under side of the board.
  • Like the dual ESP8266, it is very possible that different resistor values will be needed for the different FSR strips.  Again, test and determine the best value for each resistor.
  • The ESPHome code for the sensor when using an ESP32 is slightly different than the ESP8266:
sensor:
  - platform: adc
    pin: GPIO34  #Use a different pin for each FRS strip
    attenuation: 11db
    name: "Bed Sensor Left"
    id: "bed_sensor left"
    icon: mdi:bed
    update_interval: 0.5s
    filters:
      - sliding_window_moving_average:
          window_size: 10
          send_every: 1
      - or:
          - throttle: 180s
          - delta: 0.02

The primary difference here is the addition of the 'attenuation' line and the removal of the 3.3 multiplier filter.  The other entities are the same, but remember that you will need two sensors, two binary sensors and two input_number helpers (triggers) in the ESPHome code... one for each FSR strip.  Be sure you update the ID tags appropriately in the entity definitions.

Note that you can use any of the ESP32 pins marked as ADC1.  Do not try to use any of the ADC2 pins as these conflict with wifi on the ESP32. On most ESP32 boards, you can use GPIO32 thru GPIO36 plus GPIO39 for ADC input.

One Controller Option


As I mentioned earlier, I already had a room temperature sensor and opted to create separate controllers for the IR transmitter and bed sensor just due to the layout of my bedroom, which made a single controller option impractical.  However, it is possible to put many of these options together using a single controller for everything: 

Click to enlarge

This is just an example of how a single ESP32 NodeMCU controller could be used for both the IR transmitter, dual bed sensors, two optional push buttons and a DHT22 room temperature and humidity sensor.  It combines all of the options above except the logic level shifter and LED wiring.  And you could also squeeze in the shifter.  Since the shifter has 4 channels, it could be used both for the IR transmitter and a potential LED data line.  Mix and match as you see fit.  Naturally, you will need to modify the ESPHome code to match whatever you build, including adding sensors for the DHT22.

Final Installation  


I opted to add some braided sleeve and spade connectors to the wiring from the controller to the FSR strip, primarily just to make for a little neater and easier final installation.

Optional braided sleeve and spade connectors

You will need to remove your mattress and box springs for this next step (if you have box springs - for my Sleep Number bed, I just had to remove the mattress).  You want to install the FSR strip on a solid surface and where it won't be disturbed by things like changing the sheets or rotating the mattress.

For my Sleep Number bed, this is a solid surface

I found the best location for the strip was near where my hips/rear end would be located when I was in the bed.  I used a little masking tape on the ends of the strip and along some of the wiring just to be sure everything stayed in place.  


I then connected the leads from the FSR strip to the controller (using the optional spade connectors) and the USB cable connected to 5V supply plugged into a power strip under the bed.  Since I have those two optional push buttons, I mounted the controller box near the head of the bed where it was easily accessible but generally not noticeable.  If you don't have the push buttons, the controller could be mounted or placed under the bed.

Initial Results


After running the system for a few days, the results have been very good.  

First three nights

From the graph, you can clearly see when the bed was occupied each night, including the first night when I briefly arose for a quick bathroom trip!

The AC unit automatically turns on and cools the room prior to bedtime and then the unit shuts off automatically a few minutes after I get out of bed in the morning.  See the Home Assistant automations below for details on how I created these automations.  It will remain to be seen how well the force sensitive resistor strip maintains its range and whether a new resistor will need to be installed (since I lost range due to the extra weight of the blankets, comforter, etc. that I did not include in the initial testing of the resistor/range (oops!).

I'll update this section of the blog if or when I change needs to be made.

Home Assistant Integrations and Entities


One big advantage of using ESPHome is that once you integrate the new node, all the entities are imported and created for you.

IR Transmitter:
The ESPHome code will create a 'climate' entity that can be used to control the AC unit via the remote IR transmitter.

Click to enlarge

The Home Assistant climate entity allows you to control many features of the AC unit, including state (off/on/mode), fan speed, temperature set point, etc.  The exact features will depend on the type of unit you have and what commands are supported via the IR remote.

Bed Sensor:
The bed sensor gives us a number of entities for use in automations, dashboards, etc.

Click to enlarge

Of course two of these entities are the optional push buttons that I added.  If I were to eventually go back and add the LED strip, I'd also have a light entity available in Home Assistant.

Manually Created Entities/Helpers:
There are two other entities/helpers that were manually created for use in the automations.  These can be created in YAML or via the UI Helper interface in Home Assistant.

Click to enlarge

Of course one of these is the input number trigger level for the bed sensor.  The other is an input boolean (toggle helper) for easily enabling/disabling the auto AC automations.

Home Assistant Automations


My automations may be significantly different from yours... not only due to different types of AC units, but how I wish to automated the on/off cooling for my bedroom.  I'll only provide an overview here, and while I create my automations and entities in YAML, these can easily be done in the same manner via the Home Assistant automation and helper UIs.  See the linked Gist file at the end of this article for full copies of my ESPHome files, helper entities and automations.

Helper Entities

As mentioned above, I have a couple of helper entities that I use in my automations.  These are not created by ESPHome or any other integrations, so they have be manually added to Home Assistant.  While I am showing the YAML, these can also be created via the Helper UI (the input_boolean is called a 'toggle' in the UI):

# =========================
#  INPUT BOOLEANS / Toggle
# =========================
input_boolean:
  bedroom2_ac_auto_run:
    name: Auto Run Bedroom2 AC
    
# =========================
#  INPUT NUMBERS
# =========================
input_number:
  bedroom2_bed_trigger_level:
    name: Bed2 Trigger Level
    min: 0
    max: 3.5
    step: 0.05
    unit_of_measurement: V
    icon: mdi:arrow-collapse-down

Automations

Turn on the AC before bedtime

automation:
  - alias: Bedroom2 AC Turn On
    trigger:
      - platform: time
        at: "22:00:00"
    condition:
      condition: and
      conditions:
        - condition: state
          entity_id: input_boolean.bedroom2_ac_auto_run
          state: "on"
        - condition: numeric_state
          entity_id: sensor.bedroom2_temperature
          above: 69
    action:
       - service: climate.set_hvac_mode
         target:
           entity_id: climate.bedroom2_ac
         data:
           hvac_mode: cool

This is a pretty simple automation. At 10pm each night, it checks to see if the auto-run enabled and if the room temperature is above 69°F.  If so, it turns on the AC unit to cooling mode.  I'm not setting a temperature set point here since the AC unit remembers the last setpoint.  But I could also set the temperature if it had been changed by some other process.

Turn off the AC when leaving bed (after 6 am)

  - alias: Bedroom2 AC Turn Off with Bed Sensor
    # Turn off AC based on bed occupancy change if after 6 am
    trigger:
      - platform: state
        entity_id: binary_sensor.bedroom2_bed_occupied
        from: 'on'
        to: 'off'
        for: '00:05:00'  #allow time to return to bed (e.g. bathroom)
    condition:
      condition: and
      conditions:
        # Check that auto AC is enabled
        - condition: state
          entity_id: input_boolean.bedroom2_ac_auto_run
          state: "on"
        # Only turn off if after 6 am
        - condition: time
          after: "06:00:00"
    action:
      - service: climate.turn_off
        target:
          entity_id: climate.bedroom2_ac

This automation uses the bed occupancy sensor to determine if or when to automatically turn off the AC unit.  First, the bed occupancy sensor needs to go from 'on' (occupied) to 'off' (unoccupied).  I add that it needs to stay in this state for at least 5 minutes... in case I'm just getting up for a quick bathroom visit!

It then checks that the auto AC process is enable and that it is after 6:00 am.  The 6:00 am check is just a personal preference.  It could probably be omitted, but if I do get up for more than 5 minutes prior to 6 am (maybe a snack?), it won't shut off the AC.  But what if I get up for the day before 6 am?  That's where this second automation kicks in.

Check each hour for an empty bed and turn off AC

In the example above, if I arise before 6:00 am and do not return to bed, the AC unit would continue to run.  This automation is a "fallback" should either that occur or the bed sensor doesn't properly reflect my transition out of the bed.

  - alias: Bedroom2 AC Turn Off with Time
    # Check each hour and turn AC off if bed unoccupied
    trigger:
      # Check once per hour from 7-10am
      - platform: time
        at:
          - "07:00:00"
          - "08:00:00"
          - "09:00:00"
          - "10:00:00"
    condition:
      condition: and
      conditions:
        - condition: state
          entity_id: input_boolean.bedroom2_ac_auto_run
          state: "on"
        # Check that AC is not currently off
        - condition: not
          conditions: 
            condition: state
            entity_id: climate.bedroom2_ac
            state: 'off'
       # Check that bed is unoccupied
        - condition: state
          entity_id: binary_sensor.bedroom2_bed_occupied
          state: "off"
    action:
      - service: climate.turn_off
        target:
          entity_id: climate.bedroom2_ac

This automation is going to do a check at the top of each hour between 7am and 10am.  If the auto AC process is enabled, running (not off)  and the bed is unoccupied, it simply turns off the AC.  Again, this normally will not will not be needed except in the rare situation mentioned above.

Final thoughts and future additions


While I've only been using the system for a couple of weeks as of the time of this original post of this article, it has been functioning perfectly for my needs.

I haven't automated anything yet with the two push buttons I added to the bed sensor controller.  I'll probably use them to manually enable/disable the automatic AC processes, maybe manually turn the AC off or on... or some other goodnight or good morning routines.

I may also eventually add some LED lighting for those late night bathroom visits.  Currently I want to be sure that the bed sensor remains stable.  I don't want LEDs to inadvertently turn on while I'm still in bed and trying to sleep!  I'll also consider updating this section if I add LEDs or do anything interesting with the two push buttons.

Links and additional information



If you'd like to support future content on this blog and the related YouTube channel, or just say thanks for something that helped you out, you can say thanks by buying me a one-off cup of coffee at:



10 comments:

  1. Hi, I am doing my best to follow this guide(amazing work) thank you! trying to calculate the resistor I need. I believe I calculated 34 Kilo ohm resistor that I need. on hand I have some 10k ohm resistors and 330 ohm resistors. Is there anyway I could make this work? I am still trying to learn all this stuff. Thank you again!

    ReplyDelete
    Replies
    1. Well, your resistance doesn't have to be exact, just something that gives you an acceptable voltage difference between occupied and unoccupied once the force resistor has been installed. But you can always wire your resistors in series and this gives you the total resistance when the individual resistors are added together: R(total) = R1 + R2 + R3... etc. So, in your case of needing 34K, you could connect three of the 10K resistors in series and that would get you to 30K... probably close enough. But you could add additional 330 ohm resistors as well... but you'll end up with a pretty long string of resistors connected one to another. I'd test three 10K resistors and maybe four 10K resistors for a total of 30K and 40K and see if either one of those options work well enough. Otherwise, the best bet is to probably buy a small assorted resistor kit that might have something like a 33K or 36K resistor included... or you could even buy individual resistors of those values... but I did find I had to tweak my resistor a bit after using it for a night or two, so having an assortment of resistors makes that much easier than trying to daisy-chain a bunch of resistors together. Just let me know if you have any other questions. I've been using mine successfully for almost three months now. I've had to tweak the trigger level a couple of times as the system "settled" in, but otherwise it has been working great!

      Delete
    2. Thank you for the quick reply! I did put the 3 10k together to make 30k. Just for a breadboard test. I was very nervous that I didn't calculate the value correctly but I did! I was able to test it and it worked correctly. my r1 value was between 27k-34k ohm. So I am going to buy a resistor kit and another FSR Strip for the other side of the bed. going to put it all on a proto-type board which again is my first time doing that. Is there a better way to reach out? Do you have a discord community? I really love your videos and you explain things so well! Thank you again for all your work.

      Delete
    3. on my breadboard test it keeps going unavailable to available. I am guessing it is due to some loose wiring on my breadboard. I soldered some 24gauge solid core wire to the leads on the FSR and I made it long. Guessing the breadboard finds that loose?

      Delete
    4. Sounds like you are on the right track! I think that ordering a resistor kit is probably the way to go. I did find that I had to slightly change the resistor value between the breadboard and soldered/prototype version, so having a variety on hand is good... and you'll have them available for other projects later on!

      I do have a Resinchem Tech Discord server. Currently it is private, by invite only, but I'd be happy to send you an invite. If you can share your Discord handle, I'll first send a private DM (for verification) and then I can invite you into the server. Right now it is a small group of like-minded, friendly folks and a mix of beginners and a couple of pretty advanced folks. If you don't want to post your Discord here in the comments, then you can email me at the address you can find on the 'About' page of my YouTube channel. This says for business inquiries only, but I don't mind if someone contacts me at that address if I have invited them to do so. I don't post it publicly because the ol' spam bots will pick it up.
      Troubleshooting will definitely be easier via Discord than here in the blog comments!

      Delete
    5. This comment has been removed by the author.

      Delete
    6. Hi. Thanks for this great tutorial. I plan to work on this project in the week or so. All of my parts should arrive today. You mentioned a Discord server. I would greatly appreciate an invite to the server as well in case I need help troubleshooting. I'll send my Discord handle your way.

      Delete
    7. I'm glad you found it helpful. Let me know if you run into any questions and if it isn't something that can easily be answered here in the comments, I can certainly shoot you over a Discord invite if needed. Just FYI, ssjucrono above did get his system up and running and mine is still working great after about 4 months of use.

      Delete
    8. When I put the FSR under my mattress, my tester is showing "0.L" when no one is on the bed. When someone gets on the bed, I do get a reading. I tried all of the different ohm settings on my tester (2M, 200k, 20k, 2k, 200) to make sure I wasn't missing something. I have a memory foam mattress, so maybe that is what is causing there to be no reading when no one is on the bed? Can I still use the FSR if "unoccupied" means no value, but "occupied" does have a value? Thanks in advance.

      Delete
    9. Are you using a resistor yet? Normally the mattress adds enough weight to get a bit of resistance that can be measured. But it's possible that your particular mattress isn't adding enough appreciable pressure on the FSR. This is why you get a reading when occupied, but it is "out of range" (or basically the resistance is extremely high). You might need to try temporarily just picking a random resistor value (maybe try something like 100 - 200 kOhm to start) and see if you get a resistance reading when unoccupied. From there, you'll need to fine tune that resistance to get the best voltage range when connected to the ESP. The good news is that if you are getting a resistance reading when the bed is occupied, the sensor is working properly. You just need to get it adjusted to get a reading when unoccupied.

      Delete

To help eliminate spam and to keep all conversations civil, submitted comments are moderated. Therefore your post may not show up immediately. Please be patient as most reviews are completed within a few hours.