Advertisement
Guest User

Mom's Soil Moisture Sensor

a guest
Nov 9th, 2024
157
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 11.83 KB | None | 0 0
  1. #include <GxEPD2_BW.h>
  2. #include<Wire.h>
  3.  
  4. #include <WiFi.h>
  5. #include "driver/periph_ctrl.h"
  6.  
  7. #include "bitmaps/Bitmaps200x200.h"
  8.  
  9. // base class GxEPD2_GFX can be used to pass references or pointers to the display instance as parameter, uses ~1.2k more code
  10. // enable GxEPD2_GFX base class
  11. #define ENABLE_GxEPD2_GFX 1
  12.  
  13. #define sleeptimeSecs 3600
  14. #define maxArray 750
  15. #define controlpin 10
  16. #define DRY 3562 // dry = 3750, wet = 1550
  17. #define WET 2000
  18. #define switch1pin 8
  19. #define switch2pin 2
  20.  
  21. int GxEPD_BLACK1   = 0;
  22. int GxEPD_WHITE1   = 65535;
  23. int newVal;
  24.  
  25.   float t, h;
  26. RTC_DATA_ATTR float soil0[maxArray];
  27. RTC_DATA_ATTR float volts0[maxArray];
  28.  RTC_DATA_ATTR   int firstrun = 0;
  29.  
  30. RTC_DATA_ATTR int readingCount = 0; // Counter for the number of readings
  31.  
  32. #include "bitmaps/Bitmaps128x250.h"
  33. #include <Fonts/FreeSans12pt7b.h>
  34. #include <Fonts/Roboto_Condensed_12.h>
  35.  
  36. // ESP32-C3 CS(SS)=7,SCL(SCK)=4,SDA(MOSI)=6,BUSY=3,RES(RST)=2,DC=1
  37. //GxEPD2_BW<GxEPD2_213_BN, GxEPD2_213_BN::HEIGHT> display(GxEPD2_213_BN(/*CS=5*/ SS, /*DC=*/ 1, /*RES=*/ 2, /*BUSY=*/ 3)); // DEPG0213BN 122x250, SSD1680
  38. GxEPD2_BW<GxEPD2_154_D67, GxEPD2_154_D67::HEIGHT> display(GxEPD2_154_D67(/*CS=5*/ SS, /*DC=*/ 20, /*RES=*/ 21, /*BUSY=*/ 3)); // GDEH0154D67 200x200, SSD1681
  39.  
  40. #define every(interval) \
  41.     static uint32_t __every__##interval = millis(); \
  42.     if (millis() - __every__##interval >= interval && (__every__##interval = millis()))
  43.  
  44. void killwifi() {
  45.             WiFi.disconnect();
  46. }
  47.  
  48.  
  49.  
  50.  
  51. float temp, volts, batwidth, soilPct;
  52. bool switch1 = false;
  53. bool switch2 = false;
  54.  
  55.  
  56.  
  57.  
  58.  
  59.  
  60. void gotosleep(int secondsToSleep) {
  61.       //WiFi.disconnect();
  62.       display.hibernate();
  63.       SPI.end();
  64.       //Wire.end();
  65.       pinMode(SS, INPUT_PULLUP );
  66.       pinMode(6, INPUT_PULLUP );
  67.       pinMode(4, INPUT_PULLUP );
  68.       pinMode(8, INPUT_PULLUP );
  69.       pinMode(9, INPUT_PULLUP );
  70.       pinMode(1, INPUT_PULLUP );
  71.       pinMode(2, INPUT_PULLUP );
  72.       pinMode(3, INPUT_PULLUP );
  73.       pinMode(controlpin, INPUT);
  74.  
  75.       //delay(10000);
  76.       //rtc_gpio_isolate(gpio_num_t(SDA));
  77.       //rtc_gpio_isolate(gpio_num_t(SCL));
  78.       //periph_module_disable(PERIPH_I2C0_MODULE);  
  79.       //digitalWrite(SDA, 0);
  80.       //digitalWrite(SCL, 0);
  81.       esp_deep_sleep_enable_gpio_wakeup(1 << 5, ESP_GPIO_WAKEUP_GPIO_LOW);
  82.       esp_sleep_enable_timer_wakeup(secondsToSleep * 1000000ULL);
  83.       delay(1);
  84.       esp_deep_sleep_start();
  85.       //esp_light_sleep_start();
  86.       delay(1000);
  87. }
  88.  
  89.  
  90.  
  91. void doDisplay() {
  92.      //newVal = ads.computeVolts(ads.readADC_SingleEnded(0)) * 2.0;
  93.    
  94.     display.setPartialWindow(0, 0, display.width(), display.height());
  95.  
  96.     display.firstPage();
  97.     do {
  98.       display.fillRect(0,0,display.width(),display.height(),GxEPD_WHITE);
  99.     } while (display.nextPage());
  100.     delay(10);
  101.     display.firstPage();
  102.     do {
  103.       display.fillRect(0,0,display.width(),display.height(),GxEPD_WHITE);
  104.     } while (display.nextPage());
  105.    
  106.    
  107.     display.firstPage();
  108.     do {
  109.         display.fillRect(0,0,display.width(),display.height(),GxEPD_WHITE1);
  110.  
  111.  
  112.     // Draw the needle, with radius shrunk by 10% and twice as thick
  113.   int centerX = 100;
  114.   int centerY = 105;
  115.   int radius = 63; // Shrunk radius by 10%
  116.   int circleRadius = 9; // Radius of the circle in the middle
  117.   int thickness = 3; // Thickness of the needle
  118.  
  119.   // Calculate the angle for the needle
  120.   float needleAngle = mapf(soilPct, 0, 10, 240, -60);
  121.   float needleRad = radians(needleAngle);
  122.  
  123.   // Calculate the end point of the needle
  124.   float needleX = centerX + cos(needleRad) * radius;
  125.   float needleY = centerY - sin(needleRad) * radius;
  126.  
  127.   // Calculate the start points on either side of the circle
  128.   float startX1 = centerX + cos(needleRad + PI / 2) * circleRadius;
  129.   float startY1 = centerY - sin(needleRad + PI / 2) * circleRadius;
  130.   float startX2 = centerX + cos(needleRad - PI / 2) * circleRadius;
  131.   float startY2 = centerY - sin(needleRad - PI / 2) * circleRadius;
  132.  
  133.   // Draw the thick needle using multiple parallel lines
  134.   for (int i = -thickness; i <= thickness; i++) {
  135.     int offsetX1 = i * cos(needleRad + PI / 2);
  136.     int offsetY1 = i * sin(needleRad + PI / 2);
  137.     int offsetX2 = i * cos(needleRad - PI / 2);
  138.     int offsetY2 = i * sin(needleRad - PI / 2);
  139.     display.drawLine(startX1 + offsetX1, startY1 + offsetY1, needleX + offsetX1, needleY + offsetY1, GxEPD_BLACK1);
  140.     display.drawLine(startX2 + offsetX2, startY2 + offsetY2, needleX + offsetX2, needleY + offsetY2, GxEPD_BLACK1);
  141.   }
  142.  
  143.  
  144.  
  145.   //display.setCursor(70, 170); // Adjusted for smaller size
  146.   //display.print(newVal);
  147.   //display.setCursor(70, 185); // Adjusted for smaller size
  148.   //display.print(soilPct, 2);
  149.  
  150.   display.drawInvertedBitmap(0, 0, momsbackdropmom, display.epd2.WIDTH, display.epd2.HEIGHT, GxEPD_BLACK1);  
  151.   display.fillCircle(100, 104, 7, GxEPD_BLACK1);      
  152.   display.fillRect(90, 190, batwidth, 7, GxEPD_BLACK1);
  153.        
  154.     } while (display.nextPage());
  155.  
  156.     display.setFullWindow();
  157. }
  158.  
  159. void doChart() {
  160.        //newVal = ads.computeVolts(ads.readADC_SingleEnded(0)) * 2.0;
  161.    
  162.     // Shift the previous data points
  163.  
  164.  
  165.     // Recalculate min and max values
  166.     float minVal = soil0[maxArray - readingCount];
  167.     float maxVal = soil0[maxArray - readingCount];
  168.  
  169.     for (int i = maxArray - readingCount + 1; i < maxArray; i++) {
  170.         if ((soil0[i] < minVal) && (soil0[i] > 0)) {
  171.             minVal = soil0[i];
  172.         }
  173.         if (soil0[i] > maxVal) {
  174.             maxVal = soil0[i];
  175.         }
  176.     }
  177.  
  178.     // Calculate scaling factors
  179.     float yScale = 199.0 / (maxVal - minVal);
  180.     float xStep = 199.0 / (readingCount - 1);
  181.  
  182.     // Draw the line chart
  183.    // display.firstPage();
  184.   //  do {
  185.    // display.fillScreen(GxEPD_WHITE);
  186.   //  } while (display.nextPage());
  187.     display.setPartialWindow(0, 0, display.width(), display.height());
  188.  
  189.     display.firstPage();
  190.     do {
  191.       display.fillRect(0,0,display.width(),display.height(),GxEPD_BLACK);
  192.     } while (display.nextPage());
  193.     delay(10);
  194.     display.firstPage();
  195.     do {
  196.       display.fillRect(0,0,display.width(),display.height(),GxEPD_WHITE);
  197.     } while (display.nextPage());
  198.  
  199.     int startIndex = 0;
  200.     for (int i = 0; i < maxArray; i++) {
  201.         if (soil0[i] != 0) {
  202.             startIndex = i;
  203.             break;
  204.         }
  205.     }
  206.    
  207.    
  208.     display.firstPage();
  209.     do {
  210.         display.fillRect(0,0,display.width(),display.height(),GxEPD_WHITE1);
  211.         display.setCursor(0, 9);
  212.         display.print(maxVal, 3);
  213.         display.setCursor(0, 190);
  214.         display.print(minVal, 3);
  215.         display.setCursor(100, 190);
  216.         display.print(">");
  217.         display.print(soilPct, 2);
  218.         display.print("<");
  219.         display.setCursor(100, 9);
  220.         display.print("#");
  221.         display.print(readingCount);
  222.         display.print(",");
  223.         display.print(newVal);
  224.        
  225.         for (int i = maxArray - (readingCount); i < (maxArray - 1); i++) {
  226.             int x0 = (i - (maxArray - readingCount)) * xStep;
  227.             int y0 = 199 - ((soil0[i] - minVal) * yScale);
  228.             int x1 = (i + 1 - (maxArray - readingCount)) * xStep;
  229.             int y1 = 199 - ((soil0[i + 1] - minVal) * yScale);
  230.             //if (soil0[i] > 0) {
  231.                 display.drawLine(x0, y0, x1, y1, GxEPD_BLACK1);
  232.             //}
  233.         }
  234.     } while (display.nextPage());
  235.  
  236.     display.setFullWindow();
  237. }
  238.  
  239. void doBatChart() {
  240.        //newVal = ads.computeVolts(ads.readADC_SingleEnded(0)) * 2.0;
  241.    
  242.     // Shift the previous data points
  243.  
  244.  
  245.     // Recalculate min and max values
  246.     float minVal = volts0[maxArray - readingCount];
  247.     float maxVal = volts0[maxArray - readingCount];
  248.  
  249.     for (int i = maxArray - readingCount + 1; i < maxArray; i++) {
  250.         if ((volts0[i] < minVal) && (volts0[i] > 0)) {
  251.             minVal = volts0[i];
  252.         }
  253.         if (volts0[i] > maxVal) {
  254.             maxVal = volts0[i];
  255.         }
  256.     }
  257.  
  258.     // Calculate scaling factors
  259.     float yScale = 199.0 / (maxVal - minVal);
  260.     float xStep = 199.0 / (readingCount - 1);
  261.  
  262.     // Draw the line chart
  263.    // display.firstPage();
  264.   //  do {
  265.    // display.fillScreen(GxEPD_WHITE);
  266.   //  } while (display.nextPage());
  267.     display.setPartialWindow(0, 0, display.width(), display.height());
  268.  
  269.     display.firstPage();
  270.     do {
  271.       display.fillRect(0,0,display.width(),display.height(),GxEPD_BLACK);
  272.     } while (display.nextPage());
  273.     delay(10);
  274.     display.firstPage();
  275.     do {
  276.       display.fillRect(0,0,display.width(),display.height(),GxEPD_WHITE);
  277.     } while (display.nextPage());
  278.    
  279.    
  280.     display.firstPage();
  281.     do {
  282.         display.fillRect(0,0,display.width(),display.height(),GxEPD_WHITE1);
  283.         display.setCursor(0, 9);
  284.         display.print(maxVal, 3);
  285.         display.setCursor(0, 190);
  286.         display.print(minVal, 3);
  287.         display.setCursor(100, 190);
  288.         display.print(">");
  289.         display.print(volts, 2);
  290.         display.print("v");
  291.         display.setCursor(100, 9);
  292.         display.print("#");
  293.         display.print(readingCount);
  294.        
  295.         for (int i = maxArray - (readingCount); i < (maxArray - 1); i++) {
  296.             int x0 = (i - (maxArray - readingCount)) * xStep;
  297.             int y0 = 199 - ((volts0[i] - minVal) * yScale);
  298.             int x1 = (i + 1 - (maxArray - readingCount)) * xStep;
  299.             int y1 = 199 - ((volts0[i + 1] - minVal) * yScale);
  300.             //if (soil0[i] > 0) {
  301.                 display.drawLine(x0, y0, x1, y1, GxEPD_BLACK1);
  302.             //}
  303.         }
  304.     } while (display.nextPage());
  305.  
  306.     display.setFullWindow();
  307. }
  308.  
  309.  
  310. double mapf(float x, float in_min, float in_max, float out_min, float out_max)
  311. {
  312.   return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
  313. }
  314.  
  315. void setup()
  316. {
  317.   temp = temperatureRead();
  318.   volts = analogReadMilliVolts(1) / 500.0;
  319.  
  320.  
  321.   pinMode(switch1pin, INPUT_PULLUP);
  322.   pinMode(5, INPUT_PULLUP);
  323.   pinMode(switch2pin, INPUT_PULLUP);
  324.   /*if (digitalRead(switch2pin) == LOW){switch1 = true;}
  325.   if (digitalRead(switch1pin) == LOW){
  326.     switch2 = true;
  327.     GxEPD_BLACK1  =   65535;
  328.     GxEPD_WHITE1  =   0000;
  329.   }*/
  330.  
  331.   batwidth = mapf(volts,3.6,4.0,1,18);
  332.   if (batwidth > 18) {batwidth = 18;}
  333.   if (batwidth < 0) {batwidth = 0;}
  334.   pinMode(controlpin, OUTPUT);
  335.   digitalWrite(controlpin, HIGH);
  336.   delay(100);
  337.   newVal = analogRead(0);
  338.   //Wire.begin();  
  339.    // dry = 3750, wet = 1550
  340.   soilPct = mapf(newVal, DRY, WET, 0, 10);
  341.   if (soilPct < 0) {soilPct = 0;}
  342.   if (soilPct > 10) {soilPct = 10;}
  343.  
  344.    if (firstrun > 1) {
  345.     for (int i = 0; i < (maxArray - 1); i++) { //add to array for chart drawing
  346.         soil0[i] = soil0[i + 1];
  347.         volts0[i] = volts0[i + 1];
  348.     }
  349.     volts0[(maxArray - 1)] = (volts);
  350.     soil0[(maxArray - 1)] = (soilPct);
  351.     // Increase the reading count up to maxArray
  352.     if (readingCount < maxArray) {
  353.         readingCount++;
  354.     }
  355.  
  356.    }
  357.  
  358.  
  359.  
  360.  
  361.   delay(10);
  362.   display.init(115200, false, 10, false); // void init(uint32_t serial_diag_bitrate, bool initial, uint16_t reset_duration = 10, bool pulldown_rst_mode = false)
  363.   display.setRotation(0);
  364.   display.setFont(&Roboto_Condensed_12);
  365.   display.setTextColor(GxEPD_BLACK1);
  366.   if (esp_sleep_get_wakeup_cause() == ESP_SLEEP_WAKEUP_GPIO) {
  367.     display.clearScreen();
  368.     doChart();
  369.     esp_sleep_enable_timer_wakeup(10000000); //10 seconds
  370.     esp_sleep_enable_gpio_wakeup();
  371.     esp_light_sleep_start();
  372.     doBatChart();
  373.     gotosleep(10);
  374.   }
  375.            
  376.   if (firstrun == 2) {
  377.     display.clearScreen();
  378.   }
  379.   firstrun++;
  380.   if (firstrun > 99) {firstrun = 2;}
  381.   doDisplay();
  382.   gotosleep(sleeptimeSecs);
  383.  
  384. }
  385.  
  386. void loop()
  387. {
  388.     //newVal = analogRead(0);
  389.  
  390.     doDisplay();
  391.     gotosleep(sleeptimeSecs);
  392.     // Add a delay to sample data at intervals (e.g., every minute)
  393.     //delay(1000); // 1 minute delay, adjust as needed
  394. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement