• Willeum leeper @willeum.61509 ·

    Do you think it would be possible to do this on a Arduino

  • TunyFPV @piratetunagames ·

    @william.61509 It’s very possible that it is, but this was done specifically for ESPHome, which is a Home Assistant integration for ESP32 devices. I don’t actually own any arduino devices, so I’m not entirely sure. That being said, the ESP32 devices are great and super cheap. I think you can get a 3 pack for like $15-$20 online! They are super useful, especially in this configuration with the stepper motors. I use this to power my automated blinds controllers in my house. I can use Google or HA to trigger my blinds to open and close on a time or with voice commands. It’s really neat!

  • Thanks for the work @piratetunagames. I found the script will miss several minutes per day, so I updated the script for compensating. At the same time I added an entity to calibrate the clock - by setting the displayed time and calculate the steps accordingly, so no need to manually tick hours and minutes.

    esphome:
      name: flip-clock
      friendly_name: Flip Clock
    
    esp32:
      board: esp32dev
      framework:
        type: arduino
    
    # Enable logging
    logger:
    
    ota:
      - platform: esphome
        password: "<REDACTED>"
    
    wifi:
      ssid: !secret wifi_ssid
      password: !secret wifi_password
    
      # Enable fallback hotspot (captive portal) in case wifi connection fails
      ap:
        ssid: "flip-clock Fallback Hotspot"
        password: "<REDACTED>"
    
    captive_portal:
    
    # Enable Home Assistant API
    api:
      encryption:
        key: "<REDACTED>"
    
    script:
      - id: flip
        then:
          - if:
              condition:
                lambda: return !id(flipping);
              then:
              - globals.set:
                  id: flipping
                  value: 'true'
              - lambda: |
                  auto now = id(sntp_time).now();
    
                  // Skip movement on the first run
                  if (id(last_reported_time) == 0) {
                    id(last_reported_time) = now.timestamp;
                    return;
                  }
                  
                  int time_diff = 0;
    
                  // Normal operation after initial run
                  if (now.timestamp < id(last_reported_time)) {
                    // Handle rollover if time is earlier than last reported time
                    int seconds_in_a_day = 86400;
                    time_diff = round(((now.timestamp + seconds_in_a_day) - id(last_reported_time)) / 60.0);
                  } else {
                    // Normal time difference calculation
                    time_diff = round((now.timestamp - id(last_reported_time)) / 60.0);
                  }
    
                  int total_steps = time_diff * 136;
                  if (id(accumulated_error) > 0.5){
                    total_steps += 1;
                    id(accumulated_error) -= 1;
                  }
                  id(accumulated_error) += 4096.0/30.0 - 136;
    
                  // Move the stepper motor for the required steps
                  id(clock_stepper).report_position(0);
                  id(clock_stepper).set_target(total_steps);
    
                  // Save the current time as the last reported time
                  id(last_reported_time) = now.timestamp;
                  id(flipping) = false;
              - globals.set:
                  id: flipping
                  value: 'false'
    
    time:
      - platform: sntp
        id: sntp_time
        timezone: ${timezone}
        on_time:
          - cron: '0 * * * * *'
            then:
              - script.execute:
                  id: flip
    
    datetime:
      - platform: template
        type: time
        name: Calibration
        id: calibration
        lambda: "return ESPTime::from_epoch_local(id(last_reported_time));"
        set_action:
          - lambda: |
              auto now = id(sntp_time).now();
              int now_time = now.hour*3600+now.minute*60+now.second;
              int now_date = now.timestamp - now_time;
              int cali_time = x.hour*3600 + x.minute*60;
              if(cali_time > now_time)
                cali_time -= 86400;
              id(last_reported_time) = now_date + cali_time;
          - script.execute:
              id: flip
    
    stepper:
      - platform: uln2003
        id: clock_stepper
        pin_a: 16
        pin_b: 17
        pin_c: 5
        pin_d: 18
        max_speed: $spin_speed steps/s
        step_mode: HALF_STEP
        sleep_when_done: True
        acceleration: 400 steps/s^2
    
    # Variables to track last reported time and steps
    globals:
      - id: last_reported_time
        type: int
        restore_value: yes
        initial_value: '0'
      - id: flipping
        type: bool
        restore_value: no
        initial_value: 'false'
      - id: accumulated_error
        type: float
        restore_value: no
        initial_value: "0"
    
    substitutions:
      spin_speed: "900"
      timezone: "America/Los_Angeles"
    
    Edited by Gavin Ni
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment