Advertisement
hrfrazier

Aerogarden ESPHome Replacement Controller

Mar 21st, 2023 (edited)
96
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
YAML 10.03 KB | Source Code | 0 0
  1. substitutions:
  2. # Change the disp_name to something you want  
  3.   disp_name: AeroGarden Xtreme
  4.  
  5. esphome:
  6.   name: aerogarden-xtreme
  7.  
  8.   includes:
  9.    - aeroGradenPumpPwm/pumpwm.h
  10.  
  11. esp32:
  12.   board: esp32dev
  13.   framework:
  14.     type: arduino
  15.  
  16. # Enable logging
  17. logger:
  18. # Enable Home Assistant API
  19. api:
  20.   encryption:
  21.     key: ""
  22.  
  23. ota:
  24.   password: ""
  25.   on_begin:
  26.     then:
  27.       - output.turn_off: light_inverter_output
  28.  
  29. wifi:
  30.   ssid: !secret wifi_ssid
  31.   password: !secret wifi_password
  32.  
  33. status_led:
  34.   pin: GPIO2
  35.  
  36. web_server:
  37.   port: 80
  38.   auth:
  39.     username: !secret esphome_websrvr_user
  40.     password: !secret esphome_websrvr_pass
  41.  
  42. globals:
  43.   - id: plants_planted_timestamp
  44.     type: uint32_t
  45.     restore_value: yes
  46.   - id: nutrients_added_timestamp
  47.     type: uint32_t
  48.     restore_value: yes
  49.   - id: pump_run_timer
  50.     type: int
  51.     initial_value: "1"
  52.     restore_value: no
  53.  
  54. i2c:
  55.   sda: GPIO21
  56.   scl: GPIO22
  57.  
  58. display:
  59.   - platform: lcd_pcf8574
  60.     id: lcd_display
  61.     update_interval: 2s
  62.     dimensions: 20x2
  63.     address: 0x27
  64.     lambda: |-
  65.       int plant_age_in_days = (id(hass_time).now().timestamp - id(plants_planted_timestamp))/86400;
  66.       int days_ago_fed = (id(hass_time).now().timestamp - id(nutrients_added_timestamp))/86400;
  67.       int feed_in_days = 14 - days_ago_fed;
  68.       static uint8_t pageNum = 1;
  69.       static uint8_t redrawCounter = 0;
  70.       char tempStr[32];
  71.       switch(pageNum){
  72.         case 1:
  73.          it.print(3, 0, "AeroGarden");
  74.           it.print(5, 1, "Xtreme");
  75.           pageNum = 0; //default page.
  76.           break;
  77.         case 2:
  78.          // Custom page here
  79.           //Then bounce back to default page
  80.           pageNum = 0;
  81.           break;
  82.         default:
  83.          sprintf(tempStr, "%d", plant_age_in_days);
  84.           it.print(0, 1, tempStr);
  85.           sprintf(tempStr, "%d", feed_in_days);
  86.           it.print(14, 1, tempStr);
  87.  
  88.           if(redrawCounter % 2 == 0 && feed_in_days <= 1){
  89.               it.print(2, 0, "Feed Plants!");
  90.           }else{
  91.               id(hass_time).now().strftime(tempStr, sizeof(tempStr), "%I:%M %p");
  92.               it.print(4, 0, tempStr);
  93.           }
  94.  
  95.           id(hass_time).now().strftime(tempStr, sizeof(tempStr), "%D");
  96.           it.print(4, 1, tempStr);
  97.           break;
  98.       }
  99.       redrawCounter++;
  100.  
  101. sun:
  102.   latitude: 30.301131°
  103.   longitude: -81.700244°
  104.   id: hass_sun
  105.  
  106. #There are:
  107. #1036800 seconds in 12 days
  108. #1209600 seconds in 14 days
  109. #
  110. #Timer for pump & feeding schedule
  111. time:
  112.   - platform: homeassistant
  113.     id: hass_time
  114.     on_time:
  115.      # Every 1 minutes
  116.       - minutes: /1
  117.         seconds: 0
  118.         then:
  119.           - lambda: |-
  120.               char timeStr[32];
  121.               static bool pump_desired_state = false;
  122.               int days_ago_fed = (id(hass_time).now().timestamp - id(nutrients_added_timestamp))/86400;
  123.               int feed_in_days = 14 - days_ago_fed;
  124.               if(feed_in_days<0){feed_in_days=0;}
  125.               id(hass_time).now().strftime(timeStr, sizeof(timeStr), "%Y-%m-%d %H:%M");
  126.               ESP_LOGD("TIME", "Time is now %s", timeStr);
  127.               ESP_LOGD("TIME", "(Timestamp = %lu)", id(hass_time).now().timestamp);
  128.               //
  129.               //Plant feeding schedule check
  130.               //
  131.               ESP_LOGI("FEED_TIMER", "Plants were fed %d days ago and will need to be fed in %d days.", days_ago_fed, feed_in_days);
  132.               auto call = id(status_light).turn_on();
  133.               call.set_transition_length(0);
  134.               if(feed_in_days < 1){
  135.                 //light plant light red
  136.                 call.set_rgb(1.0, 0.0, 0.0);
  137.               }else if(feed_in_days <= 2){
  138.                 //light plant light yellow
  139.                 call.set_rgb(1.0, 1.0, 0.0);
  140.               }else{
  141.                 //light plany light green
  142.                 call.set_rgb(0.0, 1.0, 0.0);
  143.               }
  144.               call.set_brightness(0.8); //75%
  145.               call.perform();
  146.  
  147.               //
  148.               //Pump run timer
  149.               //
  150.               id(pump_run_timer)--;
  151.               if(id(pump_run_timer)<=0){
  152.                 if(pump_desired_state){
  153.                   ESP_LOGD("WATER_PUMP", "Turned off.");
  154.                   pump_desired_state = false;
  155.                   id(pump_run_timer) = 58;
  156.                 }else{
  157.                   ESP_LOGD("WATER_PUMP", "Turned on.");
  158.                   pump_desired_state = true;
  159.                   id(pump_run_timer) = 2;
  160.                 }
  161.               }
  162.  
  163.  
  164.               //
  165.               //Light Control
  166.               //
  167.               //Call the inverter output before
  168.  
  169.               auto hourNow = id(hass_time).now().hour;
  170.               ESP_LOGD("SUN", "Eleveation is %f", id(hass_sun).elevation());
  171.               if(pump_desired_state){
  172.                 id(grow_light_switch).turn_off();
  173.               }else if(id(hass_sun).elevation() > 0.0 ){
  174.                 id(grow_light_switch).turn_on();
  175.               }else if(hourNow>15 && hourNow<19){
  176.                 auto glc = id(grow_light).turn_on();
  177.                 glc.set_brightness(0.3);
  178.                 glc.perform();
  179.               }else{
  180.                 id(grow_light_switch).turn_off();
  181.               }
  182.  
  183.               //
  184.               //Pump run control - Lights to turn off if pump needs to run. Something to do with the PWM Channels. Need to Fix
  185.               //
  186.               if(pump_desired_state){
  187.                 id(pump_output).turn_on();
  188.               }else{
  189.                 id(pump_output).turn_off();
  190.               }
  191.               ESP_LOGI("WATER_PUMP", "Cycle change in %d minutes.", id(pump_run_timer));
  192.  
  193.               //
  194.               //Plant Age Indicator
  195.               //
  196.               int plant_age_in_days = (id(hass_time).now().timestamp - id(plants_planted_timestamp))/86400;
  197.               time_t plantEpoch = id(plants_planted_timestamp);
  198.               auto plantDate = ESPTime::from_epoch_local(plantEpoch);
  199.               plantDate.strftime(timeStr, sizeof(timeStr), "%Y-%m-%d %H:%M");
  200.               ESP_LOGI("PLANT_AGE", "Plants were planted on %s", timeStr);
  201.               ESP_LOGI("PLANT_AGE", "Plants are %d days old.", plant_age_in_days);
  202.  
  203.               printf("___________________________________________________________________________");
  204.  
  205.  
  206. #Virtual Buttons
  207. button:
  208.   - platform: template
  209.     id: record_nutrients_added
  210.     name: "Nutrients Added"
  211.     on_press:
  212.       then:
  213.         lambda: id(nutrients_added_timestamp) = id(hass_time).now().timestamp;
  214.   - platform: template
  215.     id: record_plants_planted
  216.     name: "Plants Planted"
  217.     on_press:
  218.       then:
  219.         lambda: id(plants_planted_timestamp) = id(hass_time).now().timestamp; //First planting was 1676775420
  220.  
  221.   - platform: restart
  222.     name: ${disp_name} Restart
  223.  
  224. # Touch Buttons
  225. esp32_touch:
  226.   setup_mode: false
  227.  
  228. binary_sensor:
  229.   - platform: gpio
  230.     pin:
  231.       number: GPIO25
  232.       mode:
  233.         input: true
  234.         pullup: true
  235.     name: "Water Level"
  236.  
  237. # Light Entity
  238. light:
  239.   - platform: monochromatic
  240.     id: grow_light
  241.     # internal: true
  242.     name: "Grow Light"
  243.     output: grow_light_pwm
  244.     default_transition_length: 5s
  245.     restore_mode: ALWAYS_OFF      #Keep this so that it doesn't turn on at boot in case there is an issue.
  246.   - platform: neopixelbus
  247.     type: GRB
  248.     id: status_light
  249.     variant: 800KBPS
  250.     pin: GPIO23
  251.     num_leds: 1
  252.     name: "Status Light"
  253.  
  254. #pin 17 is to the MOS PWM switch, I don't think it's needed.
  255. #pin 16 is to the inverter.
  256. #I swapped these outputs in the code below.
  257. output:
  258.  #Light Inverter Power
  259.   - id: light_inverter_output
  260.     platform: gpio
  261.     pin: GPIO17
  262.   # PWM Control for Lights
  263.   - platform: ledc
  264.     id: grow_light_pwm
  265.     pin: GPIO16
  266.     frequency: "120Hz"
  267.  
  268.   # Pump PWM Control (60hz 50% Opposing)  
  269.   - platform: custom
  270.     type: binary
  271.     lambda: |-
  272.       auto pump_pwm = new AeroGardenPumpOutput();
  273.       App.register_component(pump_pwm);
  274.       return {pump_pwm};
  275.     outputs:
  276.       id: pump_pwm
  277.  
  278. # custom_component:
  279. #   - lambda: |-
  280. #       auto pump_pwm = new AeroGardenPumpOutput();
  281. #       return {pump_pwm};
  282. #     components:
  283. #     - id: pump_pwm
  284.  
  285.        
  286. #See this https://github.com/Dlloydev/ESP32-ESP32S2-AnalogWrite
  287.   #60hz pump signal
  288. #   - platform: ledc
  289. #     id: motor_pwm_hplus
  290. #     frequency: "60Hz"
  291. #     channel: 2
  292. #     pin: GPIO32
  293. #   - platform: ledc
  294. #     id: motor_pwm_hneg
  295. #     frequency: "60Hz"
  296. #     channel: 3
  297. #     pin:
  298. #       number: GPIO33
  299. #       inverted: true
  300.  
  301. switch:
  302.   - platform: output
  303.     id: pump_output
  304.     restore_mode: DISABLED
  305.     name: "Water Pump"
  306.     output: pump_pwm
  307.   - platform: output
  308.     id: grow_light_switch
  309.     output: light_inverter_output
  310.     restore_mode: ALWAYS_OFF      #Keep this so that it doesn't turn on at boot in case there is an issue.
  311.     name: "Grow Light"
  312.     on_turn_on:
  313.       then:
  314.         - delay: 1s
  315.         - light.turn_on:
  316.             brightness: 65%
  317.             id: grow_light
  318.     on_turn_off:
  319.         - output.turn_off: light_inverter_output
  320.         - light.turn_off: grow_light
  321.  
  322. sensor:
  323.   - platform: uptime
  324.     id: uptime_sensor
  325.     internal: true
  326.     name: ${disp_name} Uptime
  327.     update_interval: 30s
  328.     on_raw_value:
  329.       then:
  330.         - text_sensor.template.publish:
  331.             id: uptime_human
  332.             state: !lambda |-
  333.               int seconds = round(id(uptime_sensor).raw_state);
  334.               int days = seconds / (24 * 3600);
  335.               seconds = seconds % (24 * 3600);
  336.               int hours = seconds / 3600;
  337.               seconds = seconds % 3600;
  338.               int minutes = seconds /  60;
  339.               seconds = seconds % 60;
  340.               return (
  341.                 (days ? to_string(days) + "d " : "") +
  342.                 (hours ? to_string(hours) + "h " : "") +
  343.                 (minutes ? to_string(minutes) + "m " : "") //+
  344.                 //(to_string(seconds) + "s")
  345.               ).c_str();
  346.  
  347. text_sensor:
  348.   - platform: template
  349.     name: ${disp_name} Uptime Human Readable
  350.     id: uptime_human
  351.     icon: mdi:clock-start
  352.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement