PTSolns
Published © MIT

Off-Grid Greenhouse Automation on Blynk IOT

Based on sensor data open/close window via actuator and turn on/off fans. App via Blynk platform. Entirely solar powered.

IntermediateShowcase (no instructions)20 hours499
Off-Grid Greenhouse Automation on Blynk IOT

Things used in this project

Hardware components

Arduino Nano R3
Arduino Nano R3
×1
Espressif ESP32 Development Board - Developer Edition
Espressif ESP32 Development Board - Developer Edition
×1
PTSolns Proto-N2RF
×2
NRF24L01+PA+LNA
×2
Hall sensor
×1
Temperature sensor
×1
Linear Actuator
This was an off-the-shelf unit that came with a controller. The linear actuator opens up to 30cm, which is just enough for the greenhouse window. The controller allows the user to open the window either by onboard buttons or a remote. Most importantly for our project was that in the back of the controller are the exposed pins to externally control the actuator. We used these pins connected to our relay module to control the actuator.
×1
4-Channel Relay 5V
Or anything similar. We only need three of the four relays. Must be 5V controlled so that we can directly control relays from Nano. Relays need to be rated for main voltage.
×1
1602 LCD
To reduce wiring we used the LCD that already contained the I2C backpack on it.
×1
Wire kit
Any wire kit will do. Preformed wires are used on the boards. You will need larger diameter wire for higher current/voltage such as connected to the relay side.
×1
Resistor kit
Any resistor kit will do. We need this here only for the hall sensor. Used a 1k Ohm resistor to limit current consumption while the window is open.
×1
Screw terminals 5.08mm (11 pins used)
Any screw terminal will do. We used 11 pins in total. For the low current connections you can use 2.54mm/0.1inch pitch screw terminal. For the higher current we decided to go with the 5.08mm/0.2inch as the wires gauge is thicker.
×1
Enclosure and Connectors
At minimum, we put the relay module in an enclosure and used IP68 connectors to connect the devices controlled by the relays. This is to ensure user safety as no live terminals are exposed.
×1

Software apps and online services

Blynk
Blynk
Arduino IDE
Arduino IDE

Hand tools and fabrication machines

Many
Drill, wire strippers, tape, screw driver set, multimeter, soldering iron, etc

Story

Read more

Schematics

Follower Node

Basic schematic for the follower node

Code

Code for Leader Node

C/C++
Sorry about the mess of this code. The logic for window and fan control could greatly be improved. We added more logic loops as there were required and eventually ended up with this mess.. It works, but it is not pretty.
// Master Node
// Last Update: March 4, 2023
// Note: Change settings under SETTINGS below.
// 
// RELAY CONNECTION (on Slave Node 1 in Hot Greenhouse)
// Relay 1 (Pin 5) -> Window Open Button
// Relay 2 (Pin 6) -> Window Close Button
// Relay 3 (Pin 7) -> Fan On/Off Button
//
// OPERATIONAL LOGIC
// Data
// - Master node sends data to Slave Node 1 in Hot Greenhouse. This data is as follows:
//   - window_open   = dataFromMaster[0];
//   - window_close  = dataFromMaster[1];
//   - fan_status    = dataFromMaster[2];
// - This data is sent at regular intervals (rate_transmission) from Master to Slave
// - Upon receiving data, the Slave sends back an acknowledgment payload. This payload contains data from sensors as follows:
//   - temp          = ackData[0]/10.0;
//   - window_status = ackData[1];
//
// Window
// - Window opening and closing has a hysteresis to prevent unstable logic (rapid opening and closing of window).
// - Window opens when temp >= temp_open_window
// - Window closes when temp <= temp_close_window
// - Window takes a min. amount of time to open/close. Measured this to be around 45sec.
// - Therefore, when opening or closing, a timer (timer_onoff_window_actuator) controls for how long the actuator gets power before turning OFF relays
// - A manual window overwrite can open/close window regardless of temp (e.g. if user wants to open window while temp < temp_open_window)
// - This manual window overwrite is on a timer (timer_overwrite_window) so that if the user forgets to turn OFF overwrite, the code does it automatically after the timer has expired.
// - If manual window overwrite is not active, user cannot open/close window via buttons on app.
//
// Fans
// - (NOT IMPLEMENTED) Fans On/Off has a hystereiss to prevent unstable logic (rapidly turning On/Off fans)
// - A hall sensor detects when the window is open or closed (window_status).
// - Fans turn ON only if A) window is open, and B) temp >= temp_on_fan. If either of these is false, fans turn OFF
// - A manual fans overwrite can turn On/Off fans regardless of above conditions.
// - This manual fans overwrite is on a timer (timer_overwrite_fan)  so that if the user forgets to turn OFF overwrite, the code does it automatically after the timer has expired.
// - If manual fans overwrite is not active, user cannot turn on/Off fans via buttons on app.


#define BLYNK_TEMPLATE_ID "XXX"
#define BLYNK_DEVICE_NAME "XXX"
#define BLYNK_FIRMWARE_VERSION "XXX"
#define BLYNK_PRINT Serial
#define APP_DEBUG
#define CE_PIN  22
#define CSN_PIN 21
#include "BlynkEdgent.h" 
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

BlynkTimer timer; // Announcing the timer


// **************************************************
// *** SETTINGS *************************************
// **************************************************
float temp_on_fan       = 25.0; // Temp [C] at which fan turns ON (only if window is open)
//float temp_off_fan      = 24.0; // Temp [C] at which fan turns OFF - NOT USED. USE ONLY IF HYSTERESIS IS REQUIRED
float temp_open_window  = 30.0; // Temp [C] at which to open window
float temp_close_window = 15.0; // Temp [C] at which to close window

int timer_on_fan                = 60 * 10; // (10 mins) // Time [seconds] the fans are ON (only during automated cycle. only if window is open and temp>temp_on_fan)
int timer_off_fan               = 60 * 20; // (20 mins) // Time [seconds] the fans are OFF (only during automated cycle)
int timer_overwrite_fan         = 60 * 60; // (1 hour)  // Time [seconds] the manual fan overwrite remains active once pressed.
int timer_onoff_window_actuator = 50;      // (50 sec)  // Time [seconds] the window linear actuator is the be given power once either open or close button is pressed. Takes approx 45sec.
int timer_overwrite_window      = 60 * 60; // (1 hour)  // Time [seconds] the manual window overwrite remains active once pressed.

unsigned long rate_transmission = 1000L; // Rate [milli seconds] at which Master sends data to Slave
// **************************************************
// *** End of SETTINGS ******************************
// **************************************************



const byte slaveAddress[5] = {'R','x','A','A','A'};

RF24 radio(CE_PIN, CSN_PIN); // Create a Radio

// Data to and from
int ackData[2] = {-666, -666}; // to hold the two values coming from the slave
uint32_t dataFromMaster[3] = {0, 0, 0};
int window_open   = dataFromMaster[0];
int window_close  = dataFromMaster[1];
int fan_status    = dataFromMaster[2];


unsigned long trigger_timer;
unsigned long trigger_window_press = 1000 * timer_onoff_window_actuator; 
int trigger_pin = 0;
unsigned long trigger_timer2;
unsigned long trigger_timer4a;
unsigned long trigger_timer4b;
unsigned long trigger_man_win_overwrite = 1000 * timer_overwrite_window; 
int trigger_pin2 = 0;
int trigger_pin4a = 0; // Used in window manual overwrite
int trigger_pin4b = 0; // Used in window manual overwrite
unsigned long trigger_timer3;
unsigned long trigger_man_fan_overwrite = 1000 * timer_overwrite_fan;
unsigned long trigger_timer_fan_ON  = 1000 * timer_on_fan;
unsigned long trigger_timer_fan_OFF = 1000 * timer_off_fan;
int trigger_pin3 = 0;
bool fan_flag = true;

// Window
int window_status = 0;
int window_open_previous;
int window_close_previous;
int man_win_overwrite;
int man_fan_overwrite;

// Others
bool newData = false;
float temp;
float temp_previous;
int flag_timezero = 0;


BLYNK_WRITE(V2) {
  window_open = param.asInt();

  // If other button is ON, then turn it OFF.
  if ((window_open_previous == 0) && (window_open == 1) && (window_close_previous == 1)){
    window_close = 0;
    Blynk.virtualWrite(V3, window_close);
  }
}

BLYNK_WRITE(V3) {
  window_close = param.asInt();

  // If other button is ON, then turn it OFF.
  if ((window_close_previous == 0) && (window_close == 1) && (window_open_previous == 1)){
    window_open = 0;
    Blynk.virtualWrite(V2, window_open);
  }
}

BLYNK_WRITE(V4) {
  man_win_overwrite = param.asInt();
  if (man_win_overwrite == 1) {
    trigger_pin2 = 1;
    trigger_pin4a = 0;
    trigger_pin4b = 0;
  }
}

BLYNK_WRITE(V5) {
  fan_status = param.asInt();
  //dataFromMaster[2] = fan_status;
}

BLYNK_WRITE(V6) {
  man_fan_overwrite = param.asInt();
  if (man_fan_overwrite == 1) {
    trigger_pin3 = 1;
  } 
}

void setup() {
  Serial.begin(9600);

  BlynkEdgent.begin();

  // Radio
  radio.begin();
  radio.setDataRate( RF24_250KBPS );
  radio.enableAckPayload();
  radio.setRetries(5,5); // delay, count
  radio.setPALevel(RF24_PA_MAX);  
  radio.setChannel(124); 
  radio.openWritingPipe(slaveAddress);

  Blynk.virtualWrite(V2, 0); // Set window open initially to off
  Blynk.virtualWrite(V3, 0); // Set window close initially to off
  Blynk.virtualWrite(V5, 0); // Set fans initially to off
  Blynk.virtualWrite(V6, 0); // Set fans initially to off

  timer.setInterval(rate_transmission, data_transfer);

  flag_timezero = 0;
}

void loop() {
  BlynkEdgent.run();
  timer.run();

  // Sanity check - turn all off if both are ON
  if ((window_open == 1) && (window_close == 1)){
    window_open = 0;
    window_close = 0;
    Blynk.virtualWrite(V2, 0); 
    Blynk.virtualWrite(V3, 0);     
  }

  BlynkEdgent.run();

  // Open window based on Temp reading
  // trigger_pin = 1  -> Window open
  // trigger_pin = 2  -> Timer started for Window open
  // trigger_pin = -1 -> Window close
  // trigger_pin = -2 -> Timer started for Window close
  if (man_win_overwrite == 0){
    if ((temp >= temp_open_window) && (trigger_pin == 0) && (temp_previous < temp_open_window) && (window_status == 0)) {
      trigger_pin = 1;
      window_open = 1;
      dataFromMaster[0] = window_open; // Tell the relay to OPEN
      Blynk.virtualWrite(V2, window_open); // Tell the App it is OPEN
    } else if ((temp <= temp_close_window) && (trigger_pin == 0) && (temp_previous > temp_close_window) && (window_status == 1)) {
      trigger_pin = -1;
      window_close = 1;
      dataFromMaster[1] = window_close;
      Blynk.virtualWrite(V3, window_close); 
    } else if (trigger_pin == 0) { // In this case ignore the buttons
      window_open = 0;
      dataFromMaster[0] = window_open; // Tell the relay to CLOSE
      Blynk.virtualWrite(V2, window_open); // Tell the App it is CLOSE
      window_close = 0;
      dataFromMaster[1] = window_close;
      Blynk.virtualWrite(V3, window_close);
    } else if (trigger_pin == 1) { // In this case ignore the buttons
      window_open = 1;
      dataFromMaster[0] = window_open; // Tell the relay to CLOSE
      Blynk.virtualWrite(V2, window_open); // Tell the App it is CLOSE
      window_close = 0;
      dataFromMaster[1] = window_close;
      Blynk.virtualWrite(V3, window_close);
    } else if (trigger_pin == -1) { // In this case ignore the buttons
      window_open = 0;
      dataFromMaster[0] = window_open; // Tell the relay to CLOSE
      Blynk.virtualWrite(V2, window_open); // Tell the App it is CLOSE
      window_close = 1;
      dataFromMaster[1] = window_close;
      Blynk.virtualWrite(V3, window_close);
    }
  } else if (man_win_overwrite == 1){
    trigger_pin = 0;

    

  }

  BlynkEdgent.run();

  // Start timer to turn off button after duration
  if (trigger_pin == 1){
    trigger_pin = 2;
    trigger_timer = millis();
  } else if (trigger_pin == -1){
    trigger_pin = -2;
    trigger_timer = millis();
  }

  BlynkEdgent.run();

  // If duration has passed, turn off buttons
  if (((millis() - trigger_timer) >= trigger_window_press) && (trigger_pin == 2)) {
    trigger_pin = 0;
    window_open = 0;
    window_close = 0;
    Blynk.virtualWrite(V2, 0); 
    Blynk.virtualWrite(V3, 0); 
    dataFromMaster[0] = window_open;
    dataFromMaster[1] = window_close;
  } else if (((millis() - trigger_timer) >= trigger_window_press) && (trigger_pin == -2)) {
    trigger_pin = 0;
    window_open = 0;
    window_close = 0;
    Blynk.virtualWrite(V2, 0); 
    Blynk.virtualWrite(V3, 0); 
    dataFromMaster[0] = window_open;
    dataFromMaster[1] = window_close;
  }


  BlynkEdgent.run();

 // Start timer to turn manually overwrite temp controls automation
  if (trigger_pin2 == 1){
    trigger_pin2 = 2;
    trigger_timer2 = millis();
  }

  BlynkEdgent.run();

  // If duration has passed, disable manual window overwrite
  if (((millis() - trigger_timer2) >= trigger_man_win_overwrite) && (trigger_pin2 == 2)) {
    trigger_pin2 = 0;
    trigger_pin4a = 0;
    trigger_pin4b = 0;
    man_win_overwrite = 0;
    Blynk.virtualWrite(V4, 0); 
  }

  if (trigger_pin2 == 2) {
    dataFromMaster[0] = window_open;
    dataFromMaster[1] = window_close;

    // Reset pin any time buttons are turned off by user
    if (window_open == 0) {
      trigger_pin4a = 0;
    }

    // Reset pin any time buttons are turned off by user
    if (window_close == 0) {
      trigger_pin4b = 0;
    }


    if ((window_open == 1) && (trigger_pin4a == 0)) {
      trigger_pin4a = 1;
      trigger_timer4a = millis();
    }

    if ((window_close == 1) && (trigger_pin4b == 0)) {
      trigger_pin4b = 1;
      trigger_timer4b = millis();
    }

    if (((millis() - trigger_timer4a) >= trigger_window_press) && (trigger_pin4a == 1)) {
      trigger_pin4a = 0;
      window_open = 0;
      Blynk.virtualWrite(V2, 0); 
      dataFromMaster[0] = window_open;
    }

    if (((millis() - trigger_timer4b) >= trigger_window_press) && (trigger_pin4b == 1)) {
      trigger_pin4b = 0;
      window_close = 0;
      Blynk.virtualWrite(V3, 0); 
      dataFromMaster[1] = window_close;
    }

  }

  BlynkEdgent.run();

  // Fan control
  // For manual overwrite
  if ((man_fan_overwrite == 1) && (trigger_pin3 == 1)) { // If overwrite is ON, do whatever the button say, and start a timer
    trigger_pin3      = 2;
    trigger_timer3    = millis();
    Serial.println("here1");
  } 

  if (((millis() - trigger_timer3) >= trigger_man_fan_overwrite) && (trigger_pin3 == 2)) {
    Serial.println("here2");
    man_fan_overwrite = 0;
    trigger_pin3 = 0;
    fan_status = 0;
    dataFromMaster[2] = fan_status;
    Blynk.virtualWrite(V5, 0); // Reset fans button
    Serial.println("here7"); 
    Blynk.virtualWrite(V6, 0); // Turn OFF manual overwrite and reset trigger pin
  }

  if (trigger_pin3 == 2) {
    Serial.println("here3");
    dataFromMaster[2] = fan_status;
  }

  // For Automation
  if ((window_status == 1) && (man_fan_overwrite == 0) && (temp >= temp_on_fan)) { // Only do regular timer if window is OPEN
    if (trigger_pin3 == 0) {
      trigger_pin3 = 3; // Value 3 is ON timer
      trigger_timer3 = millis();
    }

    if (((millis() - trigger_timer3) >= trigger_timer_fan_ON) && (trigger_pin3 == 3)) {
      trigger_pin3 = 4;
      trigger_timer3 = millis();
    }

    if (((millis() - trigger_timer3) >= trigger_timer_fan_OFF) && (trigger_pin3 == 4)) {
      trigger_pin3 = 0;
    }


    if (trigger_pin3 == 3) {
      Serial.println("what!");
      fan_status = 1;
      Blynk.virtualWrite(V5, 1);
    } else if (trigger_pin3 == 4) {
      Serial.println("No way!");
      fan_status = 0;
      Blynk.virtualWrite(V5, 0);
    }

    dataFromMaster[2] = fan_status;

  } else if (man_fan_overwrite == 0){
      if ((window_status == 0) || (temp < temp_on_fan)){
        fan_status = 0;
        dataFromMaster[2] = fan_status;
        Blynk.virtualWrite(V5, 0); // Always return this button back to off while window is closed
        Serial.println("here4");
      }
  } else if (man_fan_overwrite == 1) { // Just do whatever the button says if in manual fans overwrite
    dataFromMaster[2] = fan_status;
   // Blynk.virtualWrite(V5, fan_status);   
    Serial.println("here6"); 
  }


  BlynkEdgent.run();
  Serial.println("");
  Serial.print("trigger_pin3: ");
  Serial.println(trigger_pin3);
  Serial.print("fan_status: ");
  Serial.println(fan_status);
  Serial.print("man_fan_overwrite: ");
  Serial.println(man_fan_overwrite);
  Serial.print("window_status: ");
  Serial.println(window_status);


  // Store states
  window_open_previous = window_open;
  window_close_previous = window_close;
  if (man_win_overwrite == 0){
    temp_previous = temp;
  }

  // Initialization
  flag_timezero = timezero(flag_timezero);
}

void data_transfer() {
  bool rslt;

  rslt = radio.write( &dataFromMaster, sizeof(dataFromMaster) );

  BlynkEdgent.run();

  if (rslt) {
    if ( radio.isAckPayloadAvailable() ) {
      BlynkEdgent.run();
      radio.read(&ackData, sizeof(ackData));
      temp          = ackData[0]/10.0;
      window_status = ackData[1];
      Blynk.virtualWrite(V0, temp); 
      Blynk.virtualWrite(V1, window_status); 

      newData = true;
    }
    else {
      BlynkEdgent.run();
      Serial.println("  Acknowledge but no data ");
    }
  }
  else {
    BlynkEdgent.run();
    Serial.println("  Tx failed");
  }

  if (newData == true) {
    newData = false;
  }
}

// 
int timezero(int flag_timezero){
  if (flag_timezero == 0){
    flag_timezero = 1; // Only initialize at the first pass

    window_open           = 0;
    window_close          = 0;
    window_open_previous  = 0;
    window_close_previous = 0;
    man_win_overwrite     = 0;
    man_fan_overwrite     = 0;
    fan_status            = 0;

    trigger_pin   = 0;
    trigger_pin2  = 0;
    trigger_pin3  = 0;     
    trigger_pin4a = 0;
    trigger_pin4b = 0; 

    Blynk.virtualWrite(V2, window_open); // Set window open initially to off
    Blynk.virtualWrite(V3, window_close); // Set window close initially to off
    Blynk.virtualWrite(V4, man_win_overwrite); // Set man window overwrite initially to off
    Blynk.virtualWrite(V5, fan_status); // Set fans initially to off
    Blynk.virtualWrite(V6, man_fan_overwrite); // Set man fans overwrite initially to off
  }

  return flag_timezero;  
}

Code for Follower Node

C/C++
Code for the Follower Node on the Arduino Nano.
// Follower Node 1 - Greenhouse
// Last Update: March 6, 2023
//
// NOTES: 
// - Using watchdog timer to reset Arduino if code gets stuck. Reset at max time of 8s
//   Watchdog timer does not work properly with OLD bootloader, which is required to program the Arduino Clones! MUST USE GENUINE ARDUINO


#include <OneWire.h>
#include <DallasTemperature.h>
#include <LiquidCrystal_I2C.h>
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <avr/wdt.h> // Watchdog timer

#define CE_PIN   9
#define CSN_PIN 10

#define ONE_WIRE_BUS 4

const byte thisSlaveAddress[5] = {'R','x','A','A','A'};

// Radio 
RF24 radio(CE_PIN, CSN_PIN);

// Set the LCD I2C address
LiquidCrystal_I2C lcd(0x27, 16, 2); 

// Setup a oneWire instance to communicate with any OneWire devices
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);

// Addresses o DS18B20
uint8_t sensor1[8] = { 0x28, 0x04, 0xC6, 0x07, 0xD6, 0x01, 0x3C, 0xEB };

// Data to and from
static uint32_t ackData[2] = {-666, -666}; // the two values to be sent to the master
uint32_t dataFromMaster[3] = {0, 0, 0};
int window_open   = dataFromMaster[0];
int window_close  = dataFromMaster[1];
int fan_status    = dataFromMaster[2];


// Hall Sensor
//int hall_sensor_pin       = A5;   // Hardcoded - should be set here instead...
int hall_sensor           = 0;    // Analog reading of pin hall_sensor_pin (0-1023)
int hall_sensor_threshold = 1000; // Threshold. Anything below is considered in OPEN state
                                  // This threshold needs to be tuned. After installation, longer wire=more resistance=different close threshold
int window_status         = 0; // 0=closed, 1=open

// Relay Pins
int window_open_pin = 5;  // Relay 1
int window_close_pin = 6; // Relay 2
int fan_relay_pin = 7;    // Relay 3

// Others
bool newData = false;
float temp;


void setup() {
  Serial.begin(9600);

  // LCD
  lcd.init();
  lcd.backlight(); 

  // Radio
  radio.begin();
  radio.setDataRate( RF24_250KBPS );
  radio.openReadingPipe(1, thisSlaveAddress);
  radio.enableAckPayload();
  radio.setPALevel(RF24_PA_MAX);  
  radio.setChannel(124); 
  radio.startListening();
  radio.writeAckPayload(1, &ackData, sizeof(ackData)); 

  // Define relay pins
  pinMode(window_open_pin, OUTPUT);
  pinMode(window_close_pin, OUTPUT);
  pinMode(fan_relay_pin, OUTPUT);
  digitalWrite(window_open_pin, LOW);
  digitalWrite(window_close_pin, LOW);
  digitalWrite(fan_relay_pin, LOW);

  // Watchdog timer
  wdt_disable(); 
  delay(3000);
  wdt_enable(WDTO_8S); //Enable WDT with a timeout of 8 seconds
}


void loop() {
  if ( radio.available() ) {
    radio.read( &dataFromMaster, sizeof(dataFromMaster) );

    window_open = dataFromMaster[0];
    window_close = dataFromMaster[1];
    fan_status = dataFromMaster[2];

    if (window_open == 0){
      digitalWrite(window_open_pin, LOW);
    } 

    if (window_close == 0){
      digitalWrite(window_close_pin, LOW);
    } 
  
    // This loop is written like this to avoid both relays being ON at the same time.
    if (window_open == 1){
      digitalWrite(window_open_pin, HIGH);
    } else if (window_close == 1) {
      digitalWrite(window_close_pin, HIGH);
    }

    // Fans
    if (fan_status == 0){
      digitalWrite(fan_relay_pin, LOW);
    } else if (fan_status == 1){
      digitalWrite(fan_relay_pin, HIGH);
    } 

    // Serial.print("window Open: ");
    // Serial.println(window_open);
    // Serial.print("window Close: ");
    // Serial.println(window_close);
    // Serial.print("Fan Status: ");
    // Serial.println(fan_status);
    // Serial.println("");

    updateReplyData();
    newData = true;
  }

  // Toggle Bool
  if (newData == true) {
    newData = false;
  }


  wdt_reset(); // Need to reset watchdog timer otherwise it trips
}



void updateReplyData() {
  // Window status - Reading Hall Sensor value for Window
  hall_sensor = analogRead(A3);
  if (hall_sensor < hall_sensor_threshold){
    window_status = 0;
  } else {
    window_status = 1;
  }

  // Temp
  sensors.requestTemperatures();
  temp = sensors.getTempC(sensor1);
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Temp: ");
  lcd.setCursor(6,0);
  lcd.print(temp,1);
  lcd.setCursor(10,0);
  lcd.print(" C");
  lcd.setCursor(0,1);
  lcd.print("Thres: ");
  lcd.setCursor(7,1);
  lcd.print(hall_sensor);

  ackData[0] = 10*temp; // Times 10 here to get 1 decimal accuracy as this is converted to Int. In Master divide by 10
  ackData[1] = window_status;

  radio.writeAckPayload(1, &ackData, sizeof(ackData)); // load the payload for the next time
}

Credits

PTSolns

PTSolns

1 project • 0 followers
We are engineers and professionals passionate about technology.

Comments