Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for dmaker.fan.p18 and dmaker.fan.p33 #19

Open
helgek opened this issue Apr 13, 2024 · 47 comments
Open

Support for dmaker.fan.p18 and dmaker.fan.p33 #19

helgek opened this issue Apr 13, 2024 · 47 comments

Comments

@helgek
Copy link

helgek commented Apr 13, 2024

Hi,

I have here a dmaker.fan.p18 and a dmaker.fan.p33 (Mi Smart Standing Fan 2 and Mi Smart Standing Fan 2 Pro). Difference between the two is that one has a battery, otherwise they should be the same. The specs differ slightly though:

https://home.miot-spec.com/s/dmaker.fan.p18
https://home.miot-spec.com/spec?type=urn:miot-spec-v2:device:fan:0000A005:dmaker-p18:1

https://home.miot-spec.com/s/dmaker.fan.p33
https://home.miot-spec.com/spec?type=urn:miot-spec-v2:device:fan:0000A005:dmaker-p33:1

Screenshots of the app show that there are differences regarding accessible controls through the app. The control name for speed adjustment differs:

(dmaker.fan.p18 / Mi Smart Standing Fan 2)
Screenshot_2024-04-13-02-48-56-74

(dmaker.fan.p33 / Mi Smart Standing Fan 2 Pro)
Screenshot_2024-04-13-02-50-21-79

These are pictures of the dmaker.fan.p33 / Mi Smart Standing Fan 2 Pro version (for the other one I haven't done the sull teardown yet but I could see inside that it's an ESP-WROOM-02D for both):

image

image

Unlike the Air Purifier devices that are already supported in this project these fans don't seem to have an easily accessible UART port so one probably has to flash directly on the pins of the ESP-WROOM-02D.

I checked plenty of contacts combinations for continuity but for the ESP-WROOM-02D I could only find test points for IO13 and IO15 on the backside of the PCB (marked in the pictures above) + 3.3V and GND. My hope is that IO13 and IO15 would work if I use them in the ESPHome config:

uart:
tx_pin: GPIO15
rx_pin: GPIO13
baud_rate: 115200

For Air Purifier 4 Lite the config looks like this:

uart:
tx_pin: GPIO17
rx_pin: GPIO16
baud_rate: 115200

and the docucmentation (ESP32-­WROOM­-32D - https://www.espressif.com/sites/default/files/documentation/esp32-wroom-32d_esp32-wroom-32u_datasheet_en.pdf) states this :

image

This is from the ESP-WROOM-02D documentation ( https://www.espressif.com/sites/default/files/documentation/esp-wroom-02u_esp-wroom-02d_datasheet_en.pdf ):

image

image

image

As a next step I will try backing up the original firmware and flashing the chip with ESPHome, starting with only a basic config and as a next step I would try if e.g. a switch added to the config would work. I'd be happy though if - in the meantime - maybe one of the pros here could share their opinion if these things I've summarized here make sense. Thank you!

@helgek
Copy link
Author

helgek commented Apr 13, 2024

Spend a night shift and I have good news: I was both able to do a backup of the original firmware, flash ESPHome and then I tried one test control in the config (power on/off) and the device does react to it 👍

This is the original firmware:

mi-smart-standing-fan-2-pro--dmaker.fan.p33-orignal-firmware.zip

The ESPHome log for this device shows many commands sent from the MCU to the ESP8266/ESP-WROOM-02D which should be additionally helpful to further complete the config with all possible controls.

This is the working ESPHome config with the first working controls (most essential controls already included):

external_components:
  source: github://dhewg/esphome-miot@main

esphome:
  name: mi-smart-standing-fan
  friendly_name: Xiaomi Mi Smart Standing Fan 2 Pro
  comment: Xiaomi Mi Smart Standing Fan 2 Pro (dmaker.fan.p33)
  project:
    name: "dhewg.esphome-miot"
    version: "dmaker.fan.p33"

esp8266:
  board: esp_wroom_02
  framework:
    version: recommended

logger:
  level: DEBUG

api:
  #encryption:
  #  key: !secret api_encryption_key
  reboot_timeout: 0s

ota:
  password: !secret ota_password

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  ap:
    password: !secret wifi_ap_password

captive_portal:


uart:
  tx_pin: GPIO15
  rx_pin: GPIO13
  baud_rate: 115200


miot:
  id: miot_main

button:
  - platform: "miot"
    miot_siid: 2
    miot_aiid: 1
    name: "Toggle Power"
    icon: mdi:power

switch:
  - platform: "miot"
    miot_siid: 2
    miot_piid: 1
    name: "Power"
    icon: mdi:power
  - platform: "miot"
    miot_siid: 4
    miot_piid: 1
    name: "Indicator Light"
    icon: mdi:power
  - platform: "miot"
    miot_siid: 5
    miot_piid: 1
    name: "Notification Sound"
    icon: mdi:power
  - platform: "miot"
    miot_siid: 7
    miot_piid: 1
    name: "Child Lock"
    icon: mdi:power

select:
  - platform: "miot"
    miot_siid: 6
    miot_piid: 1
    name: "Fan Blades turning direction"
    options:
      0: "Auto"
      1: "Left"
      2: "Right"
  - platform: "miot"
    miot_siid: 2
    miot_piid: 2
    name: "Fan Level"
    options:
      1: "Level 1"
      2: "Level 2"
      3: "Level 3"
      4: "Level 4"
  - platform: "miot"
    miot_siid: 2
    miot_piid: 3
    name: "Mode"
    options:
      0: "Straight Wind"
      1: "Natural Wind"

@scrampker
Copy link

I just bought the non-pro version based on this post and looking to flash the ESP. Did you end up soldering pig-tails to the chip to flash via USB-to-serial adapter?

If this works, this will be the only full-local smart tower fan that I'm aware of, and I have had nearly 7 of them. So far they all require cloud API integrations.

@scrampker
Copy link

Sure is a shame that these pins cannot be used :/

image

@scrampker
Copy link

I wired up to io13 and 15 on the back per your previous post, and I'm hoping that I can piggyback on the VDD5 and GND front the other controller in my above photo. I just need to dig out my serial to USB adapter and fiddle with it. Any tips? Would be so cool to build a full guide on this.

@scrampker
Copy link

I built up a little mount to hold pins/wires up against the ESP, and when I set my USB-to-Serial adapter to 3.3v and plug in, my port disappears immediately from my Windows PC, and the fan board just keeps chirping, about once every second.

My next test will be with the 12v plugged into the board. I was hoping to avoid this, just in case it could shoot it into my serial adapter.... somehow

image

@helgek
Copy link
Author

helgek commented May 13, 2024

@scrampker you should try it only using UART USB device connection, incl power coming from UART. This worked well for me. I used FTDI Chip based UART like this one https://amzn.eu/d/2w40Qh4 . Experience with it was much more stable than other noname chip UART that I used before. I'm traveling until the end of the week, I thought I had already posted the instructions how I successfully put the ESP into bootloader mode but it doesn't seem to be the case. I'll post it later. I think I kept notes about it.

@scrampker
Copy link

Oh that would be really cool. I'm using https://www.amazon.com/dp/B09F3196FB?psc=1&ref=ppx_yo2ov_dt_b_product_details which looks to be using a proper FTDI chipset. I tested a loopback to make sure it's working properly.

When I connect everything WITH the 12v base attached, the serial adapter does not crash. I believe what is happening is that the 3.3v line is pulling too much power for my serial adapter -- due to all the extra components being powered off that rail.

That being said, I tried using the UART0 TXD/RXD pins, and also the IO13/15 pins you reference in the yaml, but nothing seems to stick. It's been 3+ years since I've programmed an ESP device from a serial header, so I could be screwing up any number of things.

Your notes would be amazing, exactly which pins you used for each step. I'm trying to ground IO0 like it says to flash firmware, but no dice. Could even be that I'm not making sufficient contact with the pads. Did you solder directly to the chip, or were the underside contacts enough for everything?

Thanks so much!

@scrampker
Copy link

I finally got it connected. Here's what seemed to work, but I'm not 100% sure if I had a bad connection for other attempts or not.

  • Hook up per-spec UART0 TXD/RXD, IO13/15 for RTS/CTS, 3.3v and GND.
  • Use ESPHome Web to flash the 'starter' -- which worked, but didn't have a Wi-Fi config afterwards... partial success. No serial output. This MAY have been due to forgetting to remove the flash-pin loop from IO0 to GND.
  • Re-flash, using Powershell (Admin) ESPTool, which was successful, but of course since your YAML didn't use the standard pins, I didn't see any serial output. (also I hadn't removed the flash pin yet.)
  • Pull power and flash pin-to-gnd.
  • Give power and watch it come up on the network, discovered by hass.

Looking good so far. Time to re-assemble.

@helgek
Copy link
Author

helgek commented May 13, 2024

Congrats! Glad you got it to work. My yaml is work in progress as you probably noted already, it's not on top of my priority list at the moment since there are some other projects I want to complete before, but I will definitely continue on it in the later course of this year. Of course I'm happy if others join the yaml configuration work.

@helgek
Copy link
Author

helgek commented May 13, 2024

Because you asked how I flashed the chip. I bought PCBite from Sensepeek some time ago. I'm not capable of soldering and using this amazing equipment I was able to flash more than 10 devices, some of them had ESP pins which were extremely difficult to reach due to the PCB design. PCBite saved me. It's such a well designed toolset.

@scrampker
Copy link

Dang, that's pretty cool. Never seen it before, which is why I 3D printed my own pin-holder. I also was not confident in soldering such small pads without damaging the connection to the traces.

Word of warning to anyone else doing this.. the nut that attaches the motor housing to the base which allows it to tilt, (the tensioner,) is made out of extremely soft metal and stripped instantly. I have to find a suitable replacement at the hardware store. My guess is it was made out of aluminum.

@scrampker
Copy link

I do have to say, this build quality and features of this fan are pretty weak when you look at the sale price of $159. It's actually horrendous, and unforgiveable.

I have several of these $139 Dreo Pedestal fans that oscillate left/right and up/down, with temperature, and better algorithms for natural-feeling airflow. The only reason I don't have 20 of them in my house is because I have to rely on the cloud to control them. https://www.amazon.com/dp/B0BSH7YKHT?psc=1&ref=ppx_yo2ov_dt_b_product_details

All that being said, I'm very pleased to have flashed this ESP and have 100% local control. Not relying on the internet, or some greedy company that wants to charge for their API access.

@scrampker
Copy link

@helgek by chance do you know if the miot module can define an actual fan component, versus 'select'? The reason being is that certain automations and especially my hubitat integration have a hard time controlling the speed. It's not seen as a legit fan. More of a jumble of various entities.

@cristianchelu
Copy link
Contributor

@scrampker I think I can answer that. esphome-miot doesn't (yet) have a fan component implemented, but since ESPHome 2024.3 there's a Template Fan you can use to hack something together.

It's as barebones as it can be and there's no state feedback support (i.e. register state change when pressing physical buttons) but may be workable via the On State trigger and friends.

fan:
  - platform: template
    name: "Virtual Fan"
    on_state:
      - lambda: |-
          // id(my_miot_speed_select).set_index(x->speed) or something?
    on_speed_set: # etc

I've ordered a non-pro standing fan 2 too and it seems fun to try my hand at a miot fan component, but don't hold your breath.

I'd love to hear it if you manage something workable with the above 😃

@scrampker
Copy link

Thanks! I was tinkering with something along these lines, but I'm not too familiar with the way this all pieces together. I assume I'd need to add some code to the miot base for fan. My quick attempts to build outputs and whatever haven't worked yet. Hopefully I'll figure out something.

@w-marco
Copy link

w-marco commented Jul 18, 2024

@scrampker would you mind sharing the 3D Print STL files for the Dupont holder?
I want to flash mine too (successfully converted my Air Purifier 4 Lite today as a first trial, now onto the fan), and would love to use the Dupont holder you designed for it.

@cristianchelu
Copy link
Contributor

cristianchelu commented Jul 19, 2024

@w-marco You can search the Thingiverse and other sharing platforms for "ESP8266 programming jig", I see there are several options.

I've also received my dmaker.fan.p18 yesterday and managed to get a good config working, hopefully this will cut some of your work :)

#28

(change the external-components: - source to a branch that has the fix for the OTA platform until it's merged to main.)

Edit:
What's also important for ESP8266 devices from what I've seen, is to disable the esphome serial debug output on UART1. It helps greatly with stability in the comms with the MCU.

logger:
  level: DEBUG
  # Important: Disable UART1 logging to avoid hardware errors on main UART0
  baud_rate: 0

@scrampker
Copy link

I can send you mine a bit later if you really want. I did search a bit but I must suck at it and didn't find an easy print. Otherwise I wouldn't have made mine. If you know of a good one please let us know.

@scrampker
Copy link

Mine definitely isn't perfect. It could hold the pins in tension better if the holes were angled some.

@w-marco
Copy link

w-marco commented Jul 20, 2024

Yeah, I also couldn’t find one where I am certain it will fit, so adding yours here is probably a good idea!

@cristianchelu
Copy link
Contributor

@scrampker I managed to get the fan component working via Template Fan and, as expected, it's an ugly mess, but it works.

The fan component can control the device, and device updates by button press / entity changes are updated in the fan too.

Also, I've shoehorned the "Natural / Direct" breeze modes as presets. To make this work, I've had to keep updating the template_fan preset_mode state, as the normal esphome fan behavior is to clear the preset whenever a manual speed/oscillation change is made :/

You can check out the full working yaml here for dmaker.fan.p18: cristianchelu@1801e60 , I'm sure it can be adapted to other fan types without much change.

Hopefully, in the future the Template Fan component will get new powers so we can maybe say which number/select/switch entities control which part of the fan instead of this spaghetti, like:

# My daydream
fan:
  - platform: template
    entities:
      power: my_miot_power_switch
      speed: my_miot_power_number
      preset: my_miot_mode_select
      oscillation: my_miot_oscillation_switch

Seeing how often devices break the xiaomi specifications (integer 0/1 instead of booleans, one write-only property for left/right instead of two actions, etc) I'm not sure how a miot fan platform would even look in order to be flexible.

If you have any ideas or successes I'd be happy to hear them!

And, last but not least, some eye candy:

Screenshot from 2024-07-20 17-57-20
Screenshot from 2024-07-20 17-57-03

@w-marco
Copy link

w-marco commented Jul 21, 2024

@w-marco You can search the Thingiverse and other sharing platforms for "ESP8266 programming jig", I see there are several options.

I've also received my dmaker.fan.p18 yesterday and managed to get a good config working, hopefully this will cut some of your work :)

Unfortunately none of the prints from Thingiverse seem to fit the orientation this ESP Chip is placed in the p18, but once I have the 3D Print files from @scrampker I will happily try out your config for the fan and report back!

@scrampker
Copy link

Here's the latest version I had.
programming guide v7.zip

@scrampker
Copy link

@scrampker I managed to get the fan component working via Template Fan and, as expected, it's an ugly mess, but it works.

Pretty cool man, I was just able to test this yaml and pretty smooth sailing. Does anyone know if we can use the original repo yet?

@scrampker
Copy link

scrampker commented Jul 21, 2024 via email

@cristianchelu
Copy link
Contributor

I'll have to be keep playing with that yaml because it seems to turn the fan right back on every time I power it off

On that branch I have another commit simplifying things a bit after I've discovered you can just id(fan).make_call() instead of turn_off() / turn_on().

If after you power off the fan it tries to set the speed anyway, the automation there starts with auto call = id(template_fan).turn_on(). Try this patch and see if it works:

  - platform: "miot"
    id: "speed_level"
    miot_siid: 2
    miot_piid: 10
    name: "Fan Speed"
    icon: "mdi:speedometer"
    min_value: 1
    max_value: 100
    step: 1
    unit_of_measurement: "%"
    on_value:
      - lambda: |-
-         auto call = id(template_fan).turn_on();
+         auto call = id(template_fan).make_call();
          call.set_speed(x);
          call.set_preset_mode(id(mode).state.c_str());
          call.perform();

@scrampker
Copy link

I'm a dummy -- totally glossed over the fact that you were using the d18 and I have the d33 'pro' version and in testing I copied your yaml entirely. After throwing back some of the code I had previously, AND making the patch you pasted, it seems to work great.

Doesn't appear to be turning back on right away. Awesome! I really need to dig deeper into these yaml configurations, and the baseline code. Just getting started with truly customizing HA or ESPHome stuffs. I also have a bunch of 8266 units I was using some hacked code to operate linear actuators to open windows, and should get those over on ESPHome as well.

@scrampker
Copy link

Yay, the notification sound disabling actually sticks now. That's been obnoxious. Seems to work exactly as I'd expect. The added bonus of the left/right control is actually interesting. I wasn't aware that it was even capable of that. I knew it had a little servo from the tear-down, but that's really cool.

Wild thought... is the servo index/left-right position known or controllable? Would be so cool to use occupancy data to tell the fan where to position itself and then set the oscillation angle range.

@cristianchelu
Copy link
Contributor

Awesome, glad to hear it! When you're happy with the config for the p33 you could add a PR for it so we can close this issue :)

Last I heard from the maintainer, he was swamped with other things, but he'll take a look when he has time, and in the meantime people can still benefit from the config in the PR.

As for the left-right position, I can only speak for the p18, but the MCU knows and doesn't expose that in the miot-spec, bummer. I've tried wild poking of a few random SIID/PIIDs (Calling esphome.standing_fan_mcu_command with get_properties [random-int] [random-int] from HA) but had no success; there's 65k possibilities at the end of the day, if there's an undocumented property the engineers used to debug it.

Off-topic

When first plugged in, the fan goes full-tilt to the right for a couple of seconds to zero the angle (e.g. even if it started full left it should be back in a known position) and then back to center.

To hack it, you could delete the oscillation switch from the config, tape over the button, and emulate the same behavior in the ESP. Make a note of how many steps you have for a full swing, then at startup spam enough button.press: pan_left to get yourself in a known position, and Bob's your uncle.

(You could even do the same thing for the "natural breeze" algorithm. Add a template number input for the speed control for the intensity, and each 1-5s calculate a speed based on a pseudo-random math function of your choosing.)

@scrampker
Copy link

Steps are probably better than timing, but that's likely something I'd play with using another tool. Was just thinking it would be cool if somehow we could get that angle.

@w-marco
Copy link

w-marco commented Jul 24, 2024

Hi @scrampker and @cristianchelu, just reporting in:

I got it flashed using the 3D printed flashing jig and the YAML code you provided. It was a bit fiddly with the Dupont Pins but it worked out! Thanks for the help.

@w-marco
Copy link

w-marco commented Jul 24, 2024

+         auto call = id(template_fan).make_call();

Btw. for my p18 I also had to apply that match to make it work and not restart directly after shutting off.

@scrampker
Copy link

What's cool is now we have the only totally-local fans other than ceiling fans that use zwave/zigbee. I'm not aware of any smart fans other than that.

@cristianchelu
Copy link
Contributor

+         auto call = id(template_fan).make_call();

Btw. for my p18 I also had to apply that match to make it work and not restart directly after shutting off.

Yeah. Mine as well, but in this heat I never stopped mine to catch the bug... 😄

I'll have it fixed when I add the fan component to the PR branch a bit later, thanks for the feedback & trying it out!

@scrampker
Copy link

Has been working great for me on my p-33. And also due to the proper fan component I can actually control it with hubitat.

@helgek
Copy link
Author

helgek commented Jul 26, 2024

Just read through all the latest updates, great to see the progress! Thank you for continuing to work on this. I'm still heavily consumed with other things, so I still won't find time and a peaceful moment to look into this in the next months. But please feel free to close the issue if you're happy with the configuration you figured out.

@scrampker
Copy link

The question is, in my eyes, which github project should these changes be merged into? Seems that dhewg stopped work. The main branch still fails to compile.

@cristianchelu
Copy link
Contributor

The question is, in my eyes, which github project should these changes be merged into? Seems that dhewg stopped work. The main branch still fails to compile.

I would still create a PR here.

For an open source, voluntary project, I wouldn't consider it abandoned until let's say a year or more of inactivity, but especially not after just 3 months -- life happens to all of us, see helgek's reply just above yours :)

In parallel, I'm also merging my open PRs to my fork's main branch, just because of the logistics of keeping my different devices up-to-date. You're welcome to use my fork if you trust strangers on the internet and have a need for any of my PRs.

For a safer alternative, you can merge 9R's fix PR into your own fork's main to have your devices compile, as others have already done. Here's a stackoverflow post describing the steps.

Cheers!

@syssi
Copy link

syssi commented Aug 14, 2024

Could somebody provide some guidance how to disassemble the fan? Where is the ESP32 board located?

@helgek
Copy link
Author

helgek commented Aug 14, 2024

@syssi I didn't take many photos with the board inside the fan housing. This one will maybe give a little bit of a better idea. To disassemble you need to first remove the fan blade and its housing as also described in the manual. Then you can open the pcb housing itself. I can't recall the steps anymore but I remember that it wasn't too difficult to reach the pcb. I hope this helps a little bit.

IMG_6816

mmo_89660723_1633327873_4601_37430.pdf

@scrampker
Copy link

Maybe some of these photos will help?
image

image

@scrampker
Copy link

It took me about 15 minutes to get the board out, a few hours of work to really understand what pins are used for what, and then another chunk of hours building my crappy little 3d-printed jig. Then a few more hours fiddling with the upload process until it just magically worked. Probably I had issues due to loose tolerances on my print.

@syssi
Copy link

syssi commented Aug 15, 2024

Thanks for sharing! This helps a lot. I will give it a try! :-)

@dhewg
Copy link
Owner

dhewg commented Sep 20, 2024

Nice work everybody, this looks nice!
Did anyone look into implementing a fan component?
FYI: the p18 config is merged now

@scrampker
Copy link

Nice work everybody, this looks nice! Did anyone look into implementing a fan component? FYI: the p18 config is merged now

Yes @cristianchelu code has it and it works perfectly.

@dhewg
Copy link
Owner

dhewg commented Sep 25, 2024

I meant adding a miot::Fan C++ component derived from the esphome fan::Fan component, so the yaml template code can be reduced ;)

@cristianchelu
Copy link
Contributor

Given how much variation and quirky implementations we have seen so far across devices, how would a miot.fan component have to look in order to keep some flexibility?

fan:
 - platform: miot
   oscillation: # implicit switch?
     miot_siid: x 
     miot_piid: y
     miot_false: '0' # hypothetical quirk
     miot_true: '1'
     # what if the on/off is implemented as a miot action
     # and the piid is not directly controllable?
   preset:
    # select here?
    # filter map values?

I may be overthinking it, but I suspect this component has the potential to become a maintenance burden if we don't do it right.

In parallel, I asked on Discord if we could have the template fan instead mix-and-match from other sensors/numbers like I wished for in a comment above

fan:
  - platform: template
    entities:
      power: my_miot_power_switch_id
      speed: my_miot_power_number_id
      preset: my_miot_mode_select_id
      oscillation: my_miot_oscillation_switch_id

and the code-owner replied along the lines of 'no, the platform must implement it; not what template fan was made for.'

Maybe we can implement the miot version like this to keep maximum flexibility?

Unfortunately, I don't have too much time right now to explore this further, just saying some thoughts out loud.

Should we open a separate issue to continue this discussion?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants