NRF24L01 Sensor Communication
Created on: November 21, 2024
Answered using OpenAI 01 Preview by OpenAI01
Created on: November 21, 2024
Answered using OpenAI 01 Preview by OpenAI01
Piecing together the connection
I’m working through integrating nRF24L01 communication into the code to receive fixed values from another Arduino, using a specific library for this functionality.
Setting up the modules
I'm working through the setup process, starting with the nRF24L01 module, configuring it as a receiver, and adjusting the showSensorScreen function to display received values.
Preparing for communication
You're setting up the RF24 module by including its library, initializing the object with specific pins, and defining addresses for communication.
Receiving and sending data
First, gather data into a global variable. Then, tweak showSensorScreen() to integrate this data and finally, transmit the fixed values.
Setting up the sensor network
I’m configuring the RF24 network and preparing the sensor data structure. Next, I’ll initialize the radio in setup() and progressively read sensor data in loop().
Crafting transmitter code
I’m mapping out the transmitter code, which involves importing libraries, initializing RF24, setting up pipe addresses, defining SensorData structures, and sending fixed values in a loop.
Setting up data transmission
I initialized the nRF24L01 module, defined a fixed data structure for sensor readings, and configured the radio for reliable data transmission every second.
Ensuring smooth communication
I'm confirming that the receiver code is compatible with the nRF24L01 module, noting no conflicts between the LiquidCrystal_I2C and RF24 libraries. Serial initialization does not affect the process.
Certainly! Below is the modified code for both the receiver and the transmitter using the nRF24L01 modules. The receiver code has been adjusted to receive fixed sensor values from the transmitter, and the transmitter code sends these fixed values.
#include <Arduino.h> #include <Wire.h> #include <LiquidCrystal_I2C.h> #include <RF24.h> // Initialize the LCD: address 0x27, 16 characters, 2 lines LiquidCrystal_I2C lcd(0x27, 16, 2); // Adjust the I2C address if needed // Initialize the nRF24L01 module RF24 radio(9, 10); // CE, CSN pins // Address for communication const byte address[6] = "00001"; // 5-byte address // Define pins for joystick module const int vryPin = A0; // Y-axis const int vrxPin = A1; // X-axis const int buttonPin = 2; // Button // Device list const uint8_t listSize = 1; const char* const devices[listSize] = { "DEVICE 1", }; // Enumeration for screen states enum ScreenState { LIST_SCREEN, CONNECTING_SCREEN, TEMPERATURE_SCREEN, HUMIDITY_SCREEN, LIGHT_INTENSITY_SCREEN, GAS_CONCENTRATION_SCREEN, SOIL_MOISTURE_SCREEN, PRECIPITATION_LEVELS_SCREEN }; // Enumeration for joystick directions enum Direction { CENTER, UP, DOWN, LEFT, RIGHT }; // Current screen state ScreenState currentScreen = LIST_SCREEN; // Array of sensor screens for easy navigation const ScreenState sensorScreens[] = { TEMPERATURE_SCREEN, HUMIDITY_SCREEN, LIGHT_INTENSITY_SCREEN, GAS_CONCENTRATION_SCREEN, SOIL_MOISTURE_SCREEN, PRECIPITATION_LEVELS_SCREEN }; const uint8_t totalSensorScreens = sizeof(sensorScreens) / sizeof(sensorScreens[0]); uint8_t currentSensorIndex = 0; // Start with the first sensor screen // Current index for list display uint8_t currentIndex = 0; // Variables for joystick state Direction mainDirection = CENTER; bool isCentered = true; // Timing variables for holding in a single direction unsigned long holdStartTime = 0; const unsigned long holdIncrementInterval = 500; // 500 milliseconds // Variables for button handling bool lastButtonState = HIGH; // Assume button is not pressed initially bool buttonPressed = false; unsigned long lastDebounceTime = 0; const unsigned long debounceDelay = 50; // 50 milliseconds debounce // Variable to store selected device const char* selectedDevice = nullptr; // Variables for screen transitions unsigned long connectingStartTime = 0; const unsigned long connectingDuration = 2000; // 2 seconds // Data structure for sensor data struct SensorData { float temperature; uint8_t humidity; uint16_t lightIntensity; float gasConcentration; uint8_t soilMoisture; float precipitationLevel; }; // Variable to hold received sensor data SensorData sensorData; void displayInitialMessages(); void displayList(); void showConnectingScreen(); void showSensorScreen(ScreenState screen); void handleJoystick(); void debounceButton(); void clearScreen(); void displayInitialMessages() { // ECOROOTS Message lcd.clear(); lcd.setCursor((16 - 8) / 2, 0); // Center "ECOROOTS" on first line lcd.print("ECOROOTS"); const char message[] = "ROOTING SUSTAINABILITY INTO THE FUTURE"; uint8_t msgLen = strlen(message); if (msgLen <= 16) { lcd.setCursor((16 - msgLen) / 2, 1); lcd.print(message); delay(5000); } else { for (uint8_t pos = 0; pos <= msgLen - 16; pos++) { lcd.setCursor(0, 1); lcd.print(&message[pos]); delay(100); // Adjust scrolling speed as needed } delay(500); // Pause after scrolling } // Searching Message lcd.clear(); const char searchMsg[] = "SEARCHING ENVIRONMENT FOR DEVICES"; msgLen = strlen(searchMsg); if (msgLen <= 16) { lcd.setCursor((16 - msgLen) / 2, 0); lcd.print(searchMsg); delay(5000); } else { for (uint8_t pos = 0; pos <= msgLen - 16; pos++) { lcd.setCursor(0, 0); lcd.print(&searchMsg[pos]); delay(100); } delay(500); } // Device Found Message lcd.clear(); const char deviceFoundMsg[] = "1 DEVICE FOUND"; lcd.setCursor(0, 0); lcd.print(deviceFoundMsg); delay(1000); } void displayList() { lcd.clear(); // Display first device const char* firstItem = devices[currentIndex]; lcd.setCursor(0, 0); lcd.print(firstItem); // Display second device if exists if (currentIndex + 1 < listSize) { const char* secondItem = devices[currentIndex + 1]; lcd.setCursor(0, 1); lcd.print(secondItem); } else { lcd.setCursor(0, 1); lcd.print(" "); // Clear second line } } void showConnectingScreen() { lcd.clear(); static const char connectingPrefix[] = "CONNECTING TO "; char fullMessage[32]; snprintf(fullMessage, sizeof(fullMessage), "%s%s", connectingPrefix, selectedDevice); uint8_t msgLen = strlen(fullMessage); if (msgLen <= 16) { lcd.setCursor(0, 0); lcd.print(fullMessage); } else { for (uint8_t pos = 0; pos <= msgLen - 16; pos++) { lcd.setCursor(0, 0); lcd.print(&fullMessage[pos]); delay(100); // Adjust scrolling speed as needed } } connectingStartTime = millis(); // Start timer for transition } void showSensorScreen(ScreenState screen) { lcd.clear(); // Sensor names and received values switch (screen) { case TEMPERATURE_SCREEN: lcd.setCursor(0, 0); lcd.print("TEMPERATURE"); // Display temperature { char tempStr[16]; snprintf(tempStr, sizeof(tempStr), "%.1f oC", sensorData.temperature); lcd.setCursor(0, 1); lcd.print(tempStr); } break; case HUMIDITY_SCREEN: lcd.setCursor(0, 0); lcd.print("HUMIDITY"); // Display humidity { char humStr[16]; snprintf(humStr, sizeof(humStr), "%d %%", sensorData.humidity); lcd.setCursor(0, 1); lcd.print(humStr); } break; case LIGHT_INTENSITY_SCREEN: lcd.setCursor(0, 0); lcd.print("LIGHT INTENSITY"); // Display light intensity { char luxStr[16]; snprintf(luxStr, sizeof(luxStr), "%d Lux", sensorData.lightIntensity); lcd.setCursor(0, 1); lcd.print(luxStr); } break; case GAS_CONCENTRATION_SCREEN: lcd.setCursor(0, 0); lcd.print("GAS CONCENTRATION"); // Display gas concentration { char gasStr[16]; snprintf(gasStr, sizeof(gasStr), "%.1f ppm", sensorData.gasConcentration); lcd.setCursor(0, 1); lcd.print(gasStr); } break; case SOIL_MOISTURE_SCREEN: lcd.setCursor(0, 0); lcd.print("SOIL MOISTURE"); // Display soil moisture { char moistStr[16]; snprintf(moistStr, sizeof(moistStr), "%d %%", sensorData.soilMoisture); lcd.setCursor(0, 1); lcd.print(moistStr); } break; case PRECIPITATION_LEVELS_SCREEN: lcd.setCursor(0, 0); lcd.print("PRECIPITATION"); // Display precipitation levels { char precStr[16]; snprintf(precStr, sizeof(precStr), "%.1f mm", sensorData.precipitationLevel); lcd.setCursor(0, 1); lcd.print(precStr); } break; default: // Default to Temperature Screen showSensorScreen(TEMPERATURE_SCREEN); break; } } void handleJoystick() { // Read joystick analog values uint16_t yValueCurrent = analogRead(vryPin); uint16_t xValueCurrent = analogRead(vrxPin); // Determine joystick direction Direction direction = CENTER; if (yValueCurrent > 800) { direction = UP; } else if (yValueCurrent < 200) { direction = DOWN; } else if (xValueCurrent > 800) { direction = RIGHT; // Currently unused } else if (xValueCurrent < 200) { direction = LEFT; } // Handle based on current screen switch (currentScreen) { case LIST_SCREEN: if (direction == CENTER) { isCentered = true; } else if (isCentered) { mainDirection = direction; isCentered = false; holdStartTime = millis(); if (mainDirection == UP) { if (currentIndex > 0) { currentIndex--; displayList(); } } else if (mainDirection == DOWN) { if (currentIndex < listSize - 2) { // Display two devices at a time currentIndex++; displayList(); } } } else { if (mainDirection == direction && (millis() - holdStartTime >= holdIncrementInterval)) { holdStartTime = millis(); if (mainDirection == UP) { if (currentIndex > 0) { currentIndex--; displayList(); } } else if (mainDirection == DOWN) { if (currentIndex < listSize - 2) { currentIndex++; displayList(); } } } } break; case CONNECTING_SCREEN: // No joystick handling during connecting break; case TEMPERATURE_SCREEN: case HUMIDITY_SCREEN: case LIGHT_INTENSITY_SCREEN: case GAS_CONCENTRATION_SCREEN: case SOIL_MOISTURE_SCREEN: case PRECIPITATION_LEVELS_SCREEN: if (direction == DOWN) { // Scroll down to the next sensor screen currentSensorIndex++; if (currentSensorIndex >= totalSensorScreens) { currentSensorIndex = 0; // Loop back to the first sensor screen } currentScreen = sensorScreens[currentSensorIndex]; showSensorScreen(currentScreen); delay(200); // Simple debounce } else if (direction == UP) { // Scroll up to the previous sensor screen if (currentSensorIndex > 0) { currentSensorIndex--; } else { currentSensorIndex = totalSensorScreens - 1; } currentScreen = sensorScreens[currentSensorIndex]; showSensorScreen(currentScreen); delay(200); // Simple debounce } else if (direction == LEFT) { // Return to Device List currentScreen = LIST_SCREEN; displayList(); delay(200); // Simple debounce } break; } } void debounceButton() { int reading = digitalRead(buttonPin); if (reading != lastButtonState) { lastDebounceTime = millis(); } if ((millis() - lastDebounceTime) > debounceDelay) { if (reading != buttonPressed) { buttonPressed = reading; if (buttonPressed == LOW) { // Button pressed if (currentScreen == LIST_SCREEN) { selectedDevice = devices[currentIndex]; currentScreen = CONNECTING_SCREEN; showConnectingScreen(); } } } } lastButtonState = reading; } void setup() { // Initialize Serial for debugging (optional) Serial.begin(9600); // Initialize the LCD lcd.init(); lcd.backlight(); // Set button pin as input with pull-up resistor pinMode(buttonPin, INPUT_PULLUP); // Initialize the radio radio.begin(); radio.openReadingPipe(0, address); radio.setPALevel(RF24_PA_LOW); radio.startListening(); // Display initial messages displayInitialMessages(); // Display "ECOROOTS" and scrolling message displayList(); // Display the device list } void loop() { // Receive data if (radio.available()) { radio.read(&sensorData, sizeof(SensorData)); // Optionally, print received data to Serial for debugging Serial.println("Data received:"); Serial.print("Temperature: "); Serial.println(sensorData.temperature); Serial.print("Humidity: "); Serial.println(sensorData.humidity); Serial.print("Light Intensity: "); Serial.println(sensorData.lightIntensity); Serial.print("Gas Concentration: "); Serial.println(sensorData.gasConcentration); Serial.print("Soil Moisture: "); Serial.println(sensorData.soilMoisture); Serial.print("Precipitation Level: "); Serial.println(sensorData.precipitationLevel); } // Debounce and handle button press debounceButton(); // Handle joystick navigation handleJoystick(); // Handle screen transitions if (currentScreen == CONNECTING_SCREEN) { if (millis() - connectingStartTime >= connectingDuration) { // Transition to first sensor screen currentSensorIndex = 0; currentScreen = sensorScreens[currentSensorIndex]; showSensorScreen(currentScreen); } } // Small delay to prevent excessive CPU usage delay(10); }
#include <Arduino.h> #include <RF24.h> // Initialize the nRF24L01 module RF24 radio(9, 10); // CE, CSN pins // Address for communication const byte address[6] = "00001"; // 5-byte address // Data structure for sensor data struct SensorData { float temperature; uint8_t humidity; uint16_t lightIntensity; float gasConcentration; uint8_t soilMoisture; float precipitationLevel; }; // Fixed sensor values SensorData sensorData = { 25.5, // temperature in °C 65, // humidity in % 750, // light intensity in Lux 12.3, // gas concentration in ppm 40, // soil moisture in % 5.5 // precipitation level in mm }; void setup() { Serial.begin(9600); // Optional for debugging // Initialize the radio radio.begin(); radio.openWritingPipe(address); radio.setPALevel(RF24_PA_LOW); radio.stopListening(); // Set as transmitter } void loop() { // Send the data bool success = radio.write(&sensorData, sizeof(SensorData)); // Optionally print to Serial for debugging if (success) { Serial.println("Data sent successfully:"); } else { Serial.println("Data sending failed."); } Serial.print("Temperature: "); Serial.println(sensorData.temperature); Serial.print("Humidity: "); Serial.println(sensorData.humidity); Serial.print("Light Intensity: "); Serial.println(sensorData.lightIntensity); Serial.print("Gas Concentration: "); Serial.println(sensorData.gasConcentration); Serial.print("Soil Moisture: "); Serial.println(sensorData.soilMoisture); Serial.print("Precipitation Level: "); Serial.println(sensorData.precipitationLevel); Serial.println("------------------------"); delay(1000); // Send data every second }
Explanation:
Receiver Code Modifications:
RF24
library and initialized the radio module with RF24 radio(9, 10);
.SensorData
struct to hold the sensor values.setup()
function, initialized the radio as a receiver and started listening.loop()
function, checked if data is available and read it into sensorData
.showSensorScreen()
function to display the received sensor data instead of simulated values.Transmitter Code:
RF24
library and initialized the radio module.SensorData
struct and populated it with fixed values.setup()
function, initialized the radio as a transmitter.loop()
function, continuously sent the sensorData
every second.Notes:
address[6] = "00001";
).RF24 radio(9, 10);
) are correctly connected on both Arduinos.Wiring for nRF24L01 Modules:
Final Steps: