Smartening Plantation Shutters

had a big redesign to better fit when the shutter doors are closed, these motors are just a tad too long


Version 2 had an issue with flex, the really high friction between the Pin and Cam causing the rack to bend in and out depending on the direction. I had a ramp and level section thinking the ramp would be required to get the blind open the first 5mm then a level section should suffice after that and allow the blind to open further without the risk of binding up. Unfortunately the force is just too high and twists the pin off.

To resolve the issues version 3 has a large flat section above the rack, and I’ve also put another slot and put a retaining rail out the front, I don’t like it because it increases the twisting forces due to adding another 2.5mm , in future versions I may move this to the back side below the teeth and move the whole motor assembly up by 5mm, also changing where the force is being applied to aid in reducing bend too.

I also changed to a simple arc for the cam. this has an issue where once we are past 50% open the pin starts to travel inward towards the frame and at the same time working against the cam, there is a point at about 75% open where the shutters can lock up and it will require someone to close them a bit to get it going again. while it isn’t ideal I can’t see any alternative with this type of mechanism.

This version also has another issue, its not back drive-able the gear ratio is simply too high, ill try a lower ratio motor on the next print but I think the result will be the same.

This is version 3, currently printing


Notice the orange clips and the tactile switches for the limit switches. My plan is to put a resistor across each switch, and have 8 switches in series, the resistor values will be 1k, 2k, 4k, 8k, 16k, 32k, 64k and 128k with an analog input I should be able to determine which switch is pressed. hopefully something like the dirt cheap ads1115 4ch adc should have enough resolution?? my thoughts are there should be 256 possible voltages, essentially 8 bit resolution, so 16bit should work?. Has anyone done this before? is there a library to do such a thing? hopefully noise wont trouble it (although highly likely with the motors). The reason for 8 switches will be 2 limit switches for each motor - 3 per panel, one for a panel open reed switch, and a reed switch for the window or door behind the panel. then there is 4 panels so the 4 channel adc should be perfect.

3 Likes

This looks nice. I’ve been playing around with my own similar idea as well. Utilizing the switchbot blind tilt motor to control the blinds. I’m on version 3 now but not happy with any of them yet.

Do you have your models posted anywhere? I was going to work on a clip to the louvre to attach when I came across yours.

RE your switches - as you’re doing i2c anyway, just use an i2c expander board - PCF8575 are well cheap on Aliexpress and i’m sure there’s others that can be addressed differently!

Ive just been messing around in onshape for the design. Im still learning and this is by no means a finished model!
This is my latest attempt - completely unprinted and untested. its to try and overcome the issue of backdriving the motor. instead of the relatively easy to print module 1 gears I reduced them to module 0.5. Im not sure if they will be very durable and almost certainly not printable with FDM and will need to be resin printed (or purchased in nylon on aliexpress if it works). there is 3 gears in a carrier that rotates about 50 degrees each way in the body. in the body is an internal gear that will rotate the gear carrier and engage the gears to the rack and push it one way or the other. my plan is to drive the blinds to the desired position then disengage the motor by turning in the opposite direction briefly. there is a very high likelyhood this mechanism will lock up occasionally, especially after manual operation of the blinds, my thoughts are to introduce enough backlash and monitor the current to detect stalls and briefly drive in the opposite direction.
Onshape model

Section view


And the latest model in all its glory

While it looks big in these renders, its less than 20mm wide and less than 200mm long.

I’m also now considering moving the motor driver to each actuator.
currently im using this firmware on the motor boards github link
I want to modify the code to use the address pads for inputs for the limit switches. and just hard code each actuator with an address. this will give a nice 4 wire interface for each one

Thanks for the idea!

there are loads of smaller cheaper motor drivers that i dismissed earlier because they require more IO, something like the DRV8833 is AUD$0.85 per piece on Aliexpress, and measures about 16mm x 18mm. and the PCF8575 is AUD$1.37 and is 21mm x 23mm

I could use a PCF8575 and the DRV8833 on each actuator. this should give me the motor control (with fault detection and sleep mode) and a few extra IO for the limit switches. since there is 8 addresses available for the 8575 it will be able to cover half the blinds, then on a second i2c bus i could get the remaining. It also means that i can use smaller wire to link them all together, before i was going to use cat5 cable, now i plan on using USB cable as i should only need 4 wires.

with some minor tweaks to the current design i have squeezed them in under the cover

I had to make the base 2mm wider to fit both in, still only 22mm wide… so will fit inside the frame OK. I decided to use the motor clamp to support the top of the PCB’s, the bottom has slots. the motor card behind will be installed and screwed in with the motor clamp, and the PCF8575 will clip in after

As there may be some long runs of about 4m between the ESP and the far motor i may need to run a i2c repeater, there is a cavity in the base of 15mm x 24mm x 6mm where one could easily fit.

The only downside i can see is the lack of PWM, i would have really liked to have a soft start on the motors, to reduce power spikes

1 Like

This is awesome. Way beyond what I was working on but giving me some ideas. Its fun trying to solve this “problem”.

So some more progress, got to print a few things today. Even though my printer was having issues with bed adhesion I still managed to get a good enough print to check a few things.

This drive mechanism works OK, I have some tolerance issues - too much slop between the rack and the body so the gears don’t engage unless I push the rack in a little bit and this also effects the meshing and rotating back in. easy fix I hope just by moving the gears out by 0.25mm… its literally that close!

Adding a shadow line to the cover makes it look a lot neater too (even though the print warped because of poor adhesion to the bed), and the slot for the motor drive board seems to space the PCB perfectly from the motor. I had a last minute change to make a variation that holds an D1 Mini V4.0.0 and has a USB port opening in the top, but because of the uart IC on the board I’m half a port off… nothing major.

those gears are only 7mm dia, a little gunked up with the PTFE spray

Internal teeth printed nicely too

Ill make a few updates tonight and get it in the printer first thing tomorrow. hopefully a release version soon!

2 Likes

So last print went well, the mechanism works as expected and does a good job re-meshing itself. Just 3 more tweaks required, a little more clearance on the gear carrier as it takes a bit of work to clean it up for smooth operation, the tactile pockets need a better lead in for installing with leads attached, and the screw hole in the clip was a bit big for the screw through the bearing… all super minor adjustments and purely just to save time during assembly.

Software is next on the list. I’ve reconfigured the code above for the feedback cover, I cant figure out the direction change wait time for obstacle rollback though. The new mechanism requires a reverse after the movement, the obstacle rollback would be perfect… Feel free to give me some ideas!

This is where I’m currently at, there is an issue with the time taken calculation, it doesn’t seem to reset properly. it also doesn’t let me set by position, it doesnt actually report position like the current based cover, even when explicitly set to update interval 1s. its doing my head in so i’m going to bed!

    
i2c:
  sda: D2
  scl: D1
  scan: true
  id: bus_a

sensor:
  - platform: ina219
    address: 0x40
    shunt_resistance: 0.1 ohm
    current:
      internal: true
      id: current_sensor
    max_voltage: 7.2V
    max_current: 3.2A
    update_interval: 0.1s

binary_sensor:
  - platform: analog_threshold
    id: open_binary_sensor
    sensor_id: current_sensor
    threshold: 0.008
    filters:
      - delayed_off: 0.8s
      - lambda: |-
          if (id(blinds_cover).current_operation == CoverOperation::COVER_OPERATION_OPENING) {
            return x;
          } else {
            return {};
          }
  - platform: analog_threshold
    id: open_obstacle_binary_sensor
    sensor_id: current_sensor
    threshold: 0.1
    filters:
      - lambda: |-
          if (id(blinds_cover).current_operation == CoverOperation::COVER_OPERATION_OPENING) {
            return x;
          } else {
            return {};
          }
  - platform: analog_threshold
    id: close_binary_sensor
    sensor_id: current_sensor
    threshold: 0.008
    filters:
      - delayed_off: 0.8s
      - lambda: |-
          if (id(blinds_cover).current_operation == CoverOperation::COVER_OPERATION_CLOSING) {
            return x;
          } else {
            return {};
          }
  - platform: analog_threshold
    id: close_obstacle_binary_sensor
    sensor_id: current_sensor
    threshold: 0.1
    filters:
      - lambda: |-
          if (id(blinds_cover).current_operation == CoverOperation::COVER_OPERATION_CLOSING) {
            return x;
          } else {
            return {};
          }

  - platform: gpio
    pin:
      number: D7 
      mode:
        input: true
        pullup: true
      inverted: true
    id: open_endstop
    name: "Open Endstop"
    filters:
      - delayed_on: 10ms
      - delayed_off: 10ms
  - platform: gpio
    pin:
      number: D6 
      mode:
        input: true
        pullup: true
      inverted: true
    id: close_endstop
    name: "Close Endstop"
    filters:
      - delayed_on: 10ms
      - delayed_off: 10ms

cover:
  - platform: feedback
    name: "Blinds Cover"
    id: blinds_cover
    has_built_in_endstop: false
    infer_endstop_from_movement: false

    open_sensor: open_binary_sensor
    open_obstacle_sensor: open_obstacle_binary_sensor
    open_endstop: open_endstop
    open_duration: 14s
    open_action:
      - lambda: |-
          Wire.beginTransmission(0x30);
          Wire.write(0x00 | (byte)0x10);
          Wire.write(0x01);
          uint16_t _pwm_val=uint16_t(10000);
          if(_pwm_val>10000)
            _pwm_val=10000;
          Wire.write((byte)(_pwm_val >> 8));
          Wire.write((byte)_pwm_val);
          Wire.endTransmission();

    close_sensor: close_binary_sensor
    close_obstacle_sensor: close_obstacle_binary_sensor
    close_endstop: close_endstop
    close_duration: 14s
    close_action:
      - lambda: |-
          Wire.beginTransmission(0x30);
          Wire.write(0x00 | (byte)0x10);
          Wire.write(0x02);
          uint16_t _pwm_val=uint16_t(10000);
          if(_pwm_val>10000)
            _pwm_val=10000;
          Wire.write((byte)(_pwm_val >> 8));
          Wire.write((byte)_pwm_val);
          Wire.endTransmission();

    stop_action:
      - lambda: |-
          Wire.beginTransmission(0x30);
          Wire.write(0x00 | (byte)0x10);
          Wire.write(0x04);
          uint16_t _pwm_val=uint16_t(1);
          if(_pwm_val>10000)
            _pwm_val=10000;
          Wire.write((byte)(_pwm_val >> 8));
          Wire.write((byte)_pwm_val);
          Wire.endTransmission();

    acceleration_wait_time: 1s
    direction_change_wait_time: 1s
    obstacle_rollback: 5%

edit 2:
Coudn’t sleep… so I found a slightly different hacky method to get something working. this is using the tactile buttons as endstops, when activated they just reduce the current to 0.0A and the current based cover calls the stop routine.

i2c:
  sda: D2
  scl: D1
  scan: true
  id: bus_a

sensor:
  - platform: ina219
    address: 0x40
    shunt_resistance: 0.1 ohm
    current:
      internal: true
      id: current_sensor
    max_voltage: 7.2V
    max_current: 3.2A
    update_interval: 0.1s
  - platform: copy
    source_id: current_sensor
    id: current_filtered
    filters:
      - lambda: |-
          if (id(open_endstop).state or id(close_endstop).state) {
            return 0.0;
          } else {
            return x;
          }

binary_sensor:
  - platform: gpio
    pin:
      number: D7 
      mode:
        input: true
        pullup: true
      inverted: true
    id: open_endstop
    name: "Open Endstop"
    filters:
      - delayed_on: 10ms
      - delayed_off: 10ms
  - platform: gpio
    pin:
      number: D6 
      mode:
        input: true
        pullup: true
      inverted: true
    id: close_endstop
    name: "Close Endstop"
    filters:
      - delayed_on: 10ms
      - delayed_off: 10ms

cover:
  - platform: current_based
    name: "Blinds Cover"
    id: blinds_cover
    malfunction_detection: false
    open_sensor: current_filtered
    open_moving_current_threshold: 0.008
    open_obstacle_current_threshold: 0.1
    open_duration: 11s
    open_action:
      - lambda: |-
          Wire.beginTransmission(0x30);
          Wire.write(0x00 | (byte)0x10);
          Wire.write(0x01);
          uint16_t _pwm_val=uint16_t(10000);
          if(_pwm_val>10000)
            _pwm_val=10000;
          Wire.write((byte)(_pwm_val >> 8));
          Wire.write((byte)_pwm_val);
          Wire.endTransmission();
    close_sensor: current_filtered
    close_moving_current_threshold: 0.008
    close_obstacle_current_threshold: 0.1
    close_duration: 11s
    close_action:
      - lambda: |-
          Wire.beginTransmission(0x30);
          Wire.write(0x00 | (byte)0x10);
          Wire.write(0x02);
          uint16_t _pwm_val=uint16_t(10000);
          if(_pwm_val>10000)
            _pwm_val=10000;
          Wire.write((byte)(_pwm_val >> 8));
          Wire.write((byte)_pwm_val);
          Wire.endTransmission();
    stop_action:
      - lambda: |-
          Wire.beginTransmission(0x30);
          Wire.write(0x00 | (byte)0x10);
          Wire.write(0x04);
          uint16_t _pwm_val=uint16_t(1);
          if(_pwm_val>10000)
            _pwm_val=10000;
          Wire.write((byte)(_pwm_val >> 8));
          Wire.write((byte)_pwm_val);
          Wire.endTransmission();
          delay(100);
          Wire.beginTransmission(0x30);
          uint32_t freq= 10000;
          Wire.write(((byte)(freq >> 16)) & (byte)0x0f);
          Wire.write((byte)(freq >> 16));
          Wire.write((byte)(freq >> 8));
          Wire.write((byte)freq);
          Wire.endTransmission();     // stop transmitting
          delay(100);

    obstacle_rollback: 0%
    start_sensing_delay: 0.5s

now I just need to put in the slight reverse back, and then account for the time difference in the position.

1 Like

Still waiting for the new DRV8833 boards to arrive, the drivers I have at the moment are the D1 shield version so they don’t fit inside the cover… but just pretend its just a 3mm white cable going into the base from the solar panel/battery/charger unit

https://youtube.com/shorts/6qIA6DwgcF4

While it does work really well I’m not totally sold on the mechanism. I’m considering changing the rack to be 2 pieces with a couple of magnets to allow for the manual override. the disadvantage is the moving part will need to be three times as long and may flex too much as it will need to be printed in multiple pieces

Just checking if there is an update. The video was looking great. Love how manual control still worked.

Couldn’t do 3 posts in a row… was waiting for someone else to post!

This is another attempt with a different mechanism. The mechanism in post 24 above is awesome but the gears are really quite small and weak, there is also a good change they will jam up.

This one has a magnet between the rack and the bit that drives the blinds making it easily adjustable manually, and a quick sweep through the full range should pick it up again for remote control.

Unfortunately it was a bit of a quick and dirty design and I swapped resin so my tolerances for the sliding parts are way off and the parts have bowed. The actuator needed to be almost twice as long for this design, so had to be split in two but kept them at 130mm, and I was able to get the print time down to 4hrs compared to the 9hrs for previous version. I also added extra tactile switches so its possible to identify blind end stops and rack and pinion end stops.

I’ve made a few changes to this one to try and reduce friction and eliminate some screws, and try to beef up the join a bit.

Will be a few weeks before I’ll be able to print the next one because of work commitments, hopefully by then the rest of the parts will be here too. I can still mess around with Onshape in the evenings and get a new design together.

If anyone can think of a mechanism do us up a sketch and ill draw something up to test.

1 Like

3 posts would have been fine. I’ve been following along.

I’ve been working on something similar. Its been a learning experience and I get to play with tinkercad in the process.

My idea is to use the switchbot blind controller (battery powered with solar charger addon) to slide it up and down. I’ve been printing, testing, printing, testing and getting closer. I used ideas from you and a few other projects to design this. I had to adjust my arc similar to yours but designed a clip on the shutter because the rail had no room to fit anything. I may revisit this in the future. I got the switchbot adapter off of printables and ran with it too. I’m also playing with the herringbone gear for now (apparently its stronger) but may switch it out to a regular one later if I’m not happy with it. The shaft goes into the switchbot that sits in the clip on mount (that clips onto the centre beam in the shutter) I built for it for now. Just so I can dry fit everything until I get something I like. Eventually I plan to move it to the bottom where its more hidden.

Its still ruff as its my first attempt at this and I’ll clean it up later when I get something I’m comfortable with but this is where I’m at.

Do you add any lube or anything to it to help it slide better in the gears?

The 3 post in a row thing is a forum limit… i’ve actually had that post sitting as a draft a couple of days

For lubricant i chose DEOX R30 Non-Stick Dry PTFE Lubricant, it was at my local electronics store and has worked really well. I use it on all the gears and where ever things rub, it more than halved the current draw. I also had to lube up the blinds themselves - the pin on each side and where the bar is screwed on, they were just too tight before. just make sure you put some rags down and watch the overspray, it is clear for about a minute before you see the white spots all over the walls and floor… it cleans up easily but can be a little slippery to walk on. (and wife gets very angry when you try and do a nice thing like lubricating the carousel in the corner kitchen cupboard and get all the Tupperware containers covered in it, don’t ask me how i know) its also why the pictures above look blotchy, is not the resin… just ptfe overspray.

I like the herringbone gear, i did consider them but went the simple straight gear for the initial designs because of how easy they are to clean up after printing.

One of the things I noticed on my second design (very similar to yours above) was the amount of bending of the rack when fully extended, the third revision i put a thin wall to stop the bending and made it lock into the base. this will be most noticeable when closing, its tricky to determine which way the forces are acting, because of the friction between the pin and the cam it bends the cam outwards when closing, you also need to set a open limit as once you hit a certain point it will go the wrong way and jam up to the point where you need to manually close the blinds. the bending of the rack changes this point quite a bit, and the closer you get to the point the worse the bending gets. you can see i beefed up part of the cam slot as there is a fair amount of force on it, went from 3mm to 5mm.

I think if you change the slot to the clip (similar to the commercial version in post 17) it will overcome this limitation however it will not work on the side where the bar is because of where the pin needs to travel.

My next version I’m going to include a mouse encoder with a small gear that runs on the rack, and eliminate one of the end stops, just keeping the close one to re-zero when needed. they are super cheap ~$0.15 each… and will help with re-aligning the magnet and knowing where the blind is after manual adjustment. i think the hardest part will be the software - finding a low power way to monitor the encoder without missing steps. it will need to be interrupt driven to wake the device from the i2c expander, so may have to use 5 wires instead of 4… but then how to know which of the 12 i2c expanders triggered the wakeup. it may be best to get a small micro at each actuator, and take load off the esp.

Ohhh… I didn’t know. I’ll be more active just in case… lol

Thank you. I’ll definitely check out adding lube to help with some of the resistance.

I also plan to try a regular gear too later on. Just to see the difference. The herringbone feels like it can get ruff at times. But its pretty strong.

That is a good idea. I noticed that too but was planning to add a clip to help. But reinforcing with a thin wall would be better to strengthen it. I know what you are saying about the forces. I’ve been noticing it as well. I’m mainly focusing on just closed and open. I try to avoid going any higher to avoid the forces.

One of my original designs was like that (I’m not at version 7) but it was early in my CAD learning and I was having a tuff time with the curves. But I got that figured out now and may revisit that method down the road.

Oh that sounds nice. By using the Switchbot it handles a lot of that automatically. But I found manual control was a bit hard but I think I just need to fix some alignment and a bit of lube and it should help it out.

Thanks again for the tips.

As somebody who has a house full of planation shutters I am watching this post with fascination.

Thanks for sharing your journey with us so far @chris.huitema

2 Likes

Very interesting work! Was the reason you went to a linear actuator simply due to the need to be back-driveable?

I did a non-linear design a while back and have a few in my home (more similar to your version 1) but I solved the backdrive problem by creating a clutch gear that I can disengage by reversing the motor. This allows free movement (by hand) of the shutters. I also put a potentiometer on the output shaft that I can monitor to know the shutter’s position. That enabled what I consider to be the ‘killer feature’ for my wife – she can move one of the shutters by hand and the others will automatically match the position :slight_smile:

Interesting. Do you have any pictures of the clutch gear design? I’m still learning about gears but that has been my one issue. I wanted to keep the manual control somewhat smooth. Right now it works just not how I like it.

I’ll see if I can find some of my old drawings.

1 Like

Sorry for the radio silence, work has been busy, school holidays and all the other life stuff that happens!

A few small design changes from the one in post #31, i decided to use a mouse wheel encoder for position feedback, and make the actuator in one piece
I had a friend print the Actuator in one piece on a FDM machine for me, as it was too long for the SLA printer


there will be a magnet or two between the rack and actuator like the previous version
All the new electronics components are sitting at home so i should be able to assemble one with everything under the cover within days of getting home (still a few weeks away)

I’m also keen to try out some new resin, I hear the Siraya Tech Fast Mecha White is perfect for this sort of application so i’ve ordered a bottle… hopefully it performs like the Siraya Build resin in terms of dimensional accuracy and strength.

1 Like

I’ve found my people!

I’ve been working on this same problem for about 6+ months off and on but I’ve had it in my mind for even longer. I had similar requirements to yours @chris.huitema – namely:

(1) local control
(2) no tuya/3rd party crap
(3) solar powered or able to last a month without recharging
(4) quiet (or silent)
(5) open/close to certain %
(6) (optional) back drive able without breaking
(7) (optional) open/close on demand (right now, no waiting)

I started playing with the Tuya AM20 style from Alibaba, and the idea is nice (satisfies requirements 1/3 via RF), but the whining motors drove me crazy as in some locations in my house I’d need 12+ all turning at the same time in the same room. There were also some other oddities I didn’t like, for example, you can control % open/close via bluetooth and unreliable, but you could open/close to only 0/100% via RF. There are some other Chinese models that I tested that are similar in style but with different insides.

For fun I ended up desoldering the Bluetooth chip on the AM20 board and running IO wires from it to an ESP8266 which played really nicely with HomeAssistant to give me all the control I want, but battery only lasted about 10 hours as expected since WiFi is power hungry. I looked into low power sleep modes and waking up at intervals but realized requirement #7 for me was more important than I realized, WiFi takes time to negotiate, and that it didn’t buy me much in terms of battery life. (https://www.youtube.com/shorts/CJkv0Tge2S4)

While I was playing with the Frankenstein board I realized that when the AM20 receives an RF signal it wakes up the microcontroller from deep sleep mode so I had an idea to create a “gateway” board which would kick off an RF signal to wake up the Frankenstein board. The bluetooth board on one of the other Chinese models is a detachable hat board, so I created another one to similar spec, but unfortunately after fabrication I realized the power requirements from the ESP were just a smidge too much to pull from the existing board which made it unreliable so I had to abandon it.

(Original)

(Frankenstein hat board, I printed a dickbutt on the board because reasons)

So then I started to build a creation of my own based on lessons learned and essentially copying the AM20 physics design but with a stepper motor instead of a geared motor. I prototyped a LoRa/ESP32 solution with TMC2209 stepper motor driver where Home Assistant would talk to a gateway board that’s plugged in and stays on WiFi all the time which acts as a controller to send a “wake-up” LoRa packet to the window nodes waking them up from deep sleep and then once they were synced would send the open/close commands via LoRa. This worked really well and the operation was silent/near silent, effectively ticking off all of my requirements except the hand-operated open/close of the shutters themselves.

Here’s some prototype operations looping through LoRa-activated wakeup, motor moving in one direction, then sleep, then waking up again, moving in opposite direction, then sleep: https://www.youtube.com/shorts/MP3HbssO0VY

Obviously there are some cons to this design, namely that you can’t operate the shutters by hand and stepper motors aren’t cheap. Also I need to make more than 40 of these, so I probably would need to fabricate a custom board which also isn’t cheap. Reviewing this thread now I’m also thinking about pivoting the physics design to something similar to allow manual backdriving.