Change Variables Automatically

Project description
I want to make a plant irrigation system using an ESP32S3 MCU.
One controller should water 4 plants, uising overall 4 inputs (moisture sensors) and 4 outputs (water pumps).
Each plant has a function

void Plant1() {
(meausre moisture, calculate different things, start the motor, stop the motor...)
}

and also a display that shows many current and past values for each plant

#Plant 1
    u8g2Fonts.setCursor(plant1xlastwatering, plant1ylastwatering+8);
    u8g2Fonts.print(LatestM1);
Wateringduration, time of day, past 5 soil moisture measurments...

The code is groing very big and every time I make a change, I have to change like 50 things for each plant and be very carefuly that the general code stays the same for each function.

Question
If I define fixed variables for each plant, for instance

 int moistureRaw11 = 0;     // initialize Moisture Variable
int moistureRaw12 = 0;     // initialize Moisture Variable
int moistureRaw13 = 0;     // initialize Moisture Variable
int moistureRaw14 = 0;     // initialize Moisture Variable

(4 masurments for plant 1)
Can I somehow automate the changing of variables?

Something like:

NumberOfPlants=4
ActualPlant[1];
void Plant[1]() {
  moistureRaw[1]1 = analogRead(moisturePin1);  // read analog value of moisture sensor
  delay(500);
  moistureRaw[1]2 = analogRead(moisturePin1);  // read analog value of moisture sensor
  delay(500);
  moistureRaw[1]3 = analogRead(moisturePin1);  // read analog value of moisture sensor
  delay(500);
  moistureRaw[1]4 = analogRead(moisturePin1);  // read analog value of moisture sensor
  delay(500);
  moistureRawmean[1] = (moistureRaw[1]1 + moistureRaw[1]2 + moistureRaw[1]3 + moistureRaw[1]4) / 4;
}

then it saves all the values to the variables (instead of moistureraw[1]1 to moistureraw11)
goes back to the beginning and does the same with [2]
and then moves to the display section and does the same thing with changing the variable names?

So I have the code only once but it does the full independent routine for all 4 plants before going to the display function

You can have a two-dimensional array, if that is what you want.

Read about arrays, then structs, and finally put them together as an array of structs.

Put down the delay() calls, use millis() timing, and a simple state-machine to make this shorter, easier to read and maintain, and probably faster to execute.

It’s all part of the learning curve from newbie - to competent - to skilled developer.

It wouldn’t hurt to read a bit more about functions and how they can be used to reduce repeated code blocks.

1 Like

I have done the following:

int moistureRaw[4][4] = {
{0,0,0,0},
{0,0,0,0},
{0,0,0,0},
{0,0,0,0}
};

instead of this for each plant,

int moistureRaw11 = 0;     // initialize Moisture Variable
int moistureRaw12 = 0;     // initialize Moisture Variable
int moistureRaw13 = 0;     // initialize Moisture Variable
int moistureRaw14 = 0;     // initialize Moisture Variable

which works amazingly good!

Then I used it in the loop like this:

  CurrentPlant = 0;
  Pflanzen();
  CurrentPlant = 1;
  Pflanzen();
  CurrentPlant = 2;
  Pflanzen();
  CurrentPlant = 3;
  Pflanzen();

and the function looks something like this now:

void Pflanzen() {                            //Power MOSFET needs to be turned on first!
  pinMode(motorPin[CurrentPlant], OUTPUT);                // set to output
  moistureRaw[CurrentPlant][0] = analogRead(moisturePin[CurrentPlant]);  // read analog value of moisture sensor
  delay(500);
  moistureRaw[CurrentPlant][1] = analogRead(moisturePin[CurrentPlant]);  // read analog value of moisture sensor
  delay(500);
  moistureRaw[CurrentPlant][2] = analogRead(moisturePin[CurrentPlant]);  // read analog value of moisture sensor
  delay(500);
  moistureRaw[CurrentPlant][3] = analogRead(moisturePin[CurrentPlant]);  // read analog value of moisture sensor
  delay(500);
  moistureRawmean[CurrentPlant] = (moistureRaw[CurrentPlant][0] + moistureRaw[CurrentPlant][1] + moistureRaw[CurrentPlant][2] + moistureRaw[CurrentPlant][3]) / 4;

Which does exactly what I wanted! :slight_smile:

However I still dont know how I could solve this for the display section, which currently looks like this:

void displayRefr() {  //Power MOSFET needs to be turned on first!
  //Display Settings
  display.setRotation(3);
  waittimeinstd = waittime / 3600;
  //display.setFont(&FreeMonoBold9pt7b);
  //display.setTextColor(GxEPD_BLACK);
  uint16_t bg = GxEPD_WHITE;
  uint16_t fg = GxEPD_BLACK;
  u8g2Fonts.setFontMode(1);          // use u8g2 transparent mode (this is default)
  u8g2Fonts.setFontDirection(0);     // left to right (this is default)
  u8g2Fonts.setForegroundColor(fg);  // apply Adafruit GFX color
  u8g2Fonts.setBackgroundColor(bg);  // apply Adafruit GFX color
  u8g2Fonts.setFont(u8g2_font_5x7_tf);
  display.firstPage();
  do {
    display.fillScreen(GxEPD_WHITE);
    //Lines
    display.drawLine(0, 16, 296, 16, GxEPD_BLACK);  //drawLine(x1, y1, x2, y2, color)
    display.drawLine(display.width() / 2, 20, display.width() / 2, 128, GxEPD_BLACK);
    display.drawLine(display.width() / 4, 20, display.width() / 4, 128, GxEPD_BLACK);
    display.drawLine(222, 20, 222, 128, GxEPD_BLACK);
    //Bitmaps
    display.drawInvertedBitmap(25, 30, pflanze, 22, 35, GxEPD_BLACK);  // (0,0) where on the screen, (64,64) size of image, (conix_64x64) image name
    display.drawInvertedBitmap(100, 30, pflanze, 22, 35, GxEPD_BLACK);
    display.drawInvertedBitmap(175, 30, pflanze, 22, 35, GxEPD_BLACK);
    display.drawInvertedBitmap(250, 30, pflanze, 22, 35, GxEPD_BLACK);
    //Topbar
    u8g2Fonts.setCursor(10, 12);
    u8g2Fonts.print("" + LastUpdate);
    u8g2Fonts.print(" W: ");
    u8g2Fonts.print(waittimeinstd);
    u8g2Fonts.print("h");
    u8g2Fonts.print(" R: ");
    u8g2Fonts.print(Reboots);
    u8g2Fonts.setCursor(205, 12);
    u8g2Fonts.print(WiFi.RSSI());
    u8g2Fonts.print("dBm ");
    u8g2Fonts.print(in_voltage);
    u8g2Fonts.print("V ");
    u8g2Fonts.print(perc);
    u8g2Fonts.print("%");

    
    //Pflanze1
    //Aktueller Rohwert und Schwelle
    u8g2Fonts.setCursor(5, 30);
    u8g2Fonts.print("Roh");
    u8g2Fonts.setCursor(5, 37);
    u8g2Fonts.print(moistureRawmean[0]);
    u8g2Fonts.setCursor(5, 47);
    u8g2Fonts.print("Wet");
    u8g2Fonts.setCursor(5, 55);
    u8g2Fonts.print(wet[0]);
    //Bewässerungszeit
    u8g2Fonts.setCursor(5, 65);
    u8g2Fonts.print(watertimeM[0]);
    u8g2Fonts.print("S");
    //Moisture in Percent
    //u8g2Fonts.setCursor(55, 65);
    //u8g2Fonts.print(moisture1);
    //u8g2Fonts.print("%");
    //Last Waterings
    int plant1xlastwatering = 5;
    int plant1ylastwatering = 85;
    u8g2Fonts.setCursor(plant1xlastwatering, plant1ylastwatering);
    u8g2Fonts.print("Waterings");
    u8g2Fonts.setCursor(plant1xlastwatering, plant1ylastwatering+8);
    u8g2Fonts.print(LatestM[0]);
    u8g2Fonts.setCursor(plant1xlastwatering, plant1ylastwatering+16);
    u8g2Fonts.print(SLatestM[0]);
    u8g2Fonts.setCursor(plant1xlastwatering, plant1ylastwatering+24);
    u8g2Fonts.print(TLatestM[0]);
    u8g2Fonts.setCursor(plant1xlastwatering, plant1ylastwatering+32);
    u8g2Fonts.print(FLatestM[0]);
    u8g2Fonts.setCursor(plant1xlastwatering, plant1ylastwatering+40);
    u8g2Fonts.print(VLatestM[0]);
    //Humidity
    int plant1xlasthum = 55;
    int plant1ylasthum = 30;
    u8g2Fonts.setCursor(plant1xlasthum, plant1ylasthum);
    u8g2Fonts.print("Hum");
   // u8g2Fonts.setCursor(plant1xlasthum, plant1ylasthum+7);
   // u8g2Fonts.print(LatestHumM1act);
    u8g2Fonts.setCursor(plant1xlasthum, plant1ylasthum+7);
    u8g2Fonts.print(LatestHumM[0]);
    u8g2Fonts.setCursor(plant1xlasthum, plant1ylasthum+14);
    u8g2Fonts.print(SLatestHumM[0]);
    u8g2Fonts.setCursor(plant1xlasthum, plant1ylasthum+21);
    u8g2Fonts.print(TLatestHumM[0]);
    u8g2Fonts.setCursor(plant1xlasthum, plant1ylasthum+28);
    u8g2Fonts.print(FLatestHumM[0]);
    u8g2Fonts.setCursor(plant1xlasthum, plant1ylasthum+35);
    u8g2Fonts.print(VLatestHumM[0]);

I know how I can access the array now, but I am not sure how I can automate the process so that I just have to change the x/y positions on the display for the values, but not copy the code as many times as I have plants?

Okay. I think you need to learn about for loops, so that you don't need to write code that is so repetitive (you can let the machine do the repeating for you instead).

Read this:

And also read this:
https://www.programmingelectronics.com/iterate-array/

1 Like

I switched it to this and it is working perfectly fine, thank you!! :slight_smile:

    //Plants positioning  
    int PlantXLastWatering[4] = {5,80,160,230}; 
    int PlantYLastWateringTop = 30;
    int PlantYLastWateringMid = 85;
    int PlantXLastHumidity[4] = {55,130,200,280}; 
    int PlantYLastHumidity = 30;

 for (int CurrentPlantDisplay = 0; CurrentPlantDisplay < 4; CurrentPlantDisplay++){


    //Plant 1   
   // CurrentPlantDisplay = 0;
    //Raw values and threshold
    u8g2Fonts.setCursor(PlantXLastWatering[CurrentPlantDisplay], PlantYLastWateringTop);
    u8g2Fonts.print("Raw");
    u8g2Fonts.setCursor(PlantXLastWatering[CurrentPlantDisplay], PlantYLastWateringTop+7);
    u8g2Fonts.print(moistureRawmean[CurrentPlantDisplay]);
    u8g2Fonts.setCursor(PlantXLastWatering[CurrentPlantDisplay], PlantYLastWateringTop+17);
    u8g2Fonts.print("Wet");
    u8g2Fonts.setCursor(PlantXLastWatering[CurrentPlantDisplay], PlantYLastWateringTop+25);
    u8g2Fonts.print(wet[CurrentPlantDisplay]);
    //Watering Time
    u8g2Fonts.setCursor(PlantXLastWatering[CurrentPlantDisplay], PlantYLastWateringTop+35);
    u8g2Fonts.print(watertimeM[CurrentPlantDisplay]);
    u8g2Fonts.print("S");
    //Last Waterings
    u8g2Fonts.setCursor(PlantXLastWatering[CurrentPlantDisplay], PlantYLastWateringMid);
    u8g2Fonts.print("Waterings");
    u8g2Fonts.setCursor(PlantXLastWatering[CurrentPlantDisplay], PlantYLastWateringMid+8);
    u8g2Fonts.print(LatestM[CurrentPlantDisplay]);
    u8g2Fonts.setCursor(PlantXLastWatering[CurrentPlantDisplay], PlantYLastWateringMid+16);
    u8g2Fonts.print(SLatestM[CurrentPlantDisplay]);
    u8g2Fonts.setCursor(PlantXLastWatering[CurrentPlantDisplay], PlantYLastWateringMid+24);
    u8g2Fonts.print(TLatestM[CurrentPlantDisplay]);
    u8g2Fonts.setCursor(PlantXLastWatering[CurrentPlantDisplay], PlantYLastWateringMid+32);
    u8g2Fonts.print(FLatestM[CurrentPlantDisplay]);
    u8g2Fonts.setCursor(PlantXLastWatering[CurrentPlantDisplay], PlantYLastWateringMid+40);
    u8g2Fonts.print(VLatestM[CurrentPlantDisplay]);
    //Humidity
    u8g2Fonts.setCursor(PlantXLastHumidity[CurrentPlantDisplay], PlantYLastHumidity);
    u8g2Fonts.print("Hum");
   // u8g2Fonts.setCursor(plant1xlasthum, plant1ylasthum+7);
   // u8g2Fonts.print(LatestHumM1act);
    u8g2Fonts.setCursor(PlantXLastHumidity[CurrentPlantDisplay], PlantYLastHumidity+7);
    u8g2Fonts.print(LatestHumM[CurrentPlantDisplay]);
    u8g2Fonts.setCursor(PlantXLastHumidity[CurrentPlantDisplay], PlantYLastHumidity+14);
    u8g2Fonts.print(SLatestHumM[CurrentPlantDisplay]);
    u8g2Fonts.setCursor(PlantXLastHumidity[CurrentPlantDisplay], PlantYLastHumidity+21);
    u8g2Fonts.print(TLatestHumM[CurrentPlantDisplay]);
    u8g2Fonts.setCursor(PlantXLastHumidity[CurrentPlantDisplay], PlantYLastHumidity+28);
    u8g2Fonts.print(FLatestHumM[CurrentPlantDisplay]);
    u8g2Fonts.setCursor(PlantXLastHumidity[CurrentPlantDisplay], PlantYLastHumidity+35);
    u8g2Fonts.print(VLatestHumM[CurrentPlantDisplay]);
 }
1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.