admin管理员组文章数量:1313786
I'm working on a NodeMCU project that uses an nRF24L01, SD card, MPU6050, and BMP280. Individually, both the SD card and nRF24 work fine, but when I plug in the SD card, the nRF24 stops working (doesn't send or receive data).
Hardware Setup: NodeMCU ESP8266 nRF24L01 (CE: D4 (GPIO2), CSN: D8 (DPIO15)) SD card module (CS: D0(GPIO16)) Works Perfectly - MPU6050 & BMP280 (I2C - SDA: D2, SCL: D1) Works Perfectly - Servo on D0 Code Snippet:
#include <Wire.h>
#include <Adafruit_MPU6050.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BMP280.h>
#include <SD.h>
#include <Servo.h> // Include Servo library
#include <RF24.h>
RF24 radio(2, 15); // CE, CSN pins on NodeMCU
#define BMP_SCK (13)
#define BMP_MISO (12)
#define BMP_MOSI (11)
#define BMP_CS (10)
#define APOGEE_THRESHOLD 1.5 // Adjust this threshold as needed
Servo parachuteServo; // Define servo object
// Constants for smoothing
const int numReadings = 10;
float accelXReadings[numReadings];
float accelYReadings[numReadings];
float accelZReadings[numReadings];
float pressureReadings[numReadings];
int readIndex = 0;
float sumAccelX = 0.0;
float sumAccelY = 0.0;
float sumAccelZ = 0.0;
float sumPressure = 0.0;
float averageAccelX = 0.0;
float averageAccelY = 0.0;
float averageAccelZ = 0.0;
float averagePressure = 0.0;
// Function prototypes
void initializeMPU();
void initializeBMP();
void initializeSDCard();
void saveDataToFile(const char *filename, String data);
Adafruit_BMP280 bmp;
Adafruit_MPU6050 mpu;
float initialAltitude = 0.0; // Initial altitude
float initialZAccel = 0.0; // Initial Z acceleration
unsigned long prevTime = 0; // Previous time for time difference calculation
bool shakeDetected = true; // Flag to indicate if shake is detected
bool loggingStarted = false; // Flag to indicate if data logging has started
bool chuteDeployed = false;
// Addresses for communication
const byte slaveAddress[5] = {'R','x','A','A','A'};
const byte masterAddress[5] = {'T','X','a','a','a'};
// Initialize the nRF24 radio
char dataToSend[32]; // Increased buffer size for sensor data
char receivedCommand[10] = {0}; // Buffer for received command
bool newData = false;
void setup() {
Serial.begin(115200);
while (!Serial) {
delay(10);
}
initializeMPU();
initializeBMP();
initializeSDCard();
radio.begin();
radio.setDataRate(RF24_250KBPS);
radio.openWritingPipe(slaveAddress);
radio.openReadingPipe(1, masterAddress);
radio.setRetries(3, 5);
radio.startListening();
Serial.println("Transmitter ready!");
// Wait for shake detection
while (!shakeDetected) {
sensors_event_t a, g, temp;
mpu.getEvent(&a, &g, &temp);
// Calculate total acceleration magnitude
float totalAccel = sqrt(pow(a.acceleration.x, 2) + pow(a.acceleration.y, 2) + pow(a.acceleration.z, 2));
// Check if total acceleration exceeds threshold for shake detection
if (totalAccel > 12.0) { // Adjust threshold as needed
shakeDetected = true;
}
delay(100); // Adjust delay as needed
}
Serial.println("Shake detected!");
parachuteServo.attach(0); // Attach servo to pin number
parachuteServo.write(0);
delay(300);
// Initialize smoothing arrays
for (int i = 0; i < numReadings; i++) {
accelXReadings[i] = 0.0;
accelYReadings[i] = 0.0;
accelZReadings[i] = 0.0;
pressureReadings[i] = 0.0;
}
}
void loop() {
sensors_event_t a, g, temp;
mpu.getEvent(&a, &g, &temp);
float accelX = a.acceleration.x;
float accelY = a.acceleration.y;
float accelZ = a.acceleration.z;
float gyroX = g.gyro.x;
float gyroY = g.gyro.y;
float gyroZ = g.gyro.z;
// Update smoothing arrays
sumAccelX -= accelXReadings[readIndex];
sumAccelY -= accelYReadings[readIndex];
sumAccelZ -= accelZReadings[readIndex];
sumPressure -= pressureReadings[readIndex];
accelXReadings[readIndex] = accelX;
accelYReadings[readIndex] = accelY;
accelZReadings[readIndex] = accelZ;
pressureReadings[readIndex] = bmp.readPressure(); // Read pressure here
sumAccelX += accelXReadings[readIndex];
sumAccelY += accelYReadings[readIndex];
sumAccelZ += accelZReadings[readIndex];
sumPressure += pressureReadings[readIndex];
averageAccelX = sumAccelX / numReadings;
averageAccelY = sumAccelY / numReadings;
averageAccelZ = sumAccelZ / numReadings;
averagePressure = sumPressure / numReadings;
readIndex = (readIndex + 1) % numReadings;
float temperature = bmp.readTemperature();
// Calculate altitude using provided BMP280 library code
float currentAltitude = bmp.readAltitude(1013.25); /* Adjusted to local forecast! */
float currentAltitudeFt = currentAltitude * 3.28084; // Convert altitude to feet
// Calculate relative altitude
int relativeAltitude = (int)(currentAltitudeFt - initialAltitude); // Convert to integer
// Calculate vertical speed (Z acceleration)
unsigned long currentTime = millis();
float deltaTime = (currentTime - prevTime) / 1000.0; // Convert to seconds
float currentZAccel = (averageAccelZ - initialZAccel) * 9.81; // Convert from g to m/s^2
float verticalSpeed = currentZAccel * deltaTime * 3.6; // Convert from m/s to km/h
float maxAltitude = 0.0; // Variable to store the maximum altitude
bool apogeeDetected = false;
// Update previous time for next iteration
prevTime = currentTime;
// Prepare data packet
char dataToSend[128]; // Buffer large enough to hold full data
snprintf(dataToSend, sizeof(dataToSend),
"AccelX:%.2f, AccelY:%.2f, AccelZ:%.2f, GyroX:%.2f, GyroY:%.2f, GyroZ:%.2f, "
"Altitude:%d, VSpeed:%.2f",
averageAccelX, averageAccelY, averageAccelZ,
gyroX, gyroY, gyroZ,
relativeAltitude,
verticalSpeed);
// Send data in chunks
sendDataInChunks(dataToSend);
getData();
if (newData) {
executeCommand();
newData = false;
}
checkSerialCommand();
Serial.println("Data sent: " + String(dataToSend));
// Print structured data to Serial monitor
Serial.print("AccelX:");
Serial.print(accelX);
Serial.print(", AccelY:");
Serial.print(accelY);
Serial.print(", AccelZ:");
Serial.print(accelZ);
Serial.print(", GyroX:");
Serial.print(gyroX);
Serial.print(", GyroY:");
Serial.print(gyroY);
Serial.print(", GyroZ:");
Serial.print(gyroZ);
Serial.print(", Altitude:");
Serial.print(relativeAltitude);
Serial.print(", VSpeed:");
Serial.print(verticalSpeed);
Serial.println("");
if (accelZ < 0) {
Serial.println("Negative AccelZ detected! Rotating servo...");
parachuteServo.write(180); // Rotate servo to 180 degrees
delay(600); // Allow time for servo to rotate
parachuteServo.write(0); // Return servo to initial position
delay(600); // Allow time for servo to rotate back
}
delay(100); // Adjust delay as needed
// Check for serial input and process it
if (Serial.available() > 0) {
String command = Serial.readStringUntil('\n'); // Read until newline
// Check if command is "deploy" or "eject"
if (command.equals("a") || command.equals("eject")) {
Serial.println("Chute Deployed!");
parachuteServo.write(180); // Rotate servo to 180 degrees
delay(600); // Allow time for servo to rotate
}
// Check if command is "deploy" or "eject"
if (command.equals("initial") || command.equals("b")) {
Serial.println("Chute Ready!");
parachuteServo.write(0); // Set to a neutral or initial position
delay(600); // Allow time for servo to rotate
}
// Check if command is "test" or "t"
if (command.equals("test") || command.equals("t")) {
Serial.println("Testing components...");
int pos;
for (pos = 0; pos <= 180; pos += 5) {
parachuteServo.write(pos);
delay(15);
}
for (pos = 190; pos >= 0; pos -= 1) {
parachuteServo.write(pos);
delay(15);
}
delay(2000);
// Test MPU
sensors_event_t a, g, temp;
mpu.getEvent(&a, &g, &temp);
Serial.println("MPU6050 Test:");
Serial.print("AccelX: "); Serial.print(a.acceleration.x); Serial.print(" ");
Serial.print("AccelY: "); Serial.print(a.acceleration.y); Serial.print(" ");
Serial.print("AccelZ: "); Serial.print(a.acceleration.z); Serial.println(" ");
Serial.print("GyroX: "); Serial.print(g.gyro.x); Serial.print(" ");
Serial.print("GyroY: "); Serial.print(g.gyro.y); Serial.print(" ");
Serial.print("GyroZ: "); Serial.print(g.gyro.z); Serial.println(" ");
Serial.println("MPU6050 Test Complete!");
delay(2000);
// Test BMP
float temperature = bmp.readTemperature();
float pressure = bmp.readPressure();
float altitude = bmp.readAltitude(1013.25);
Serial.println("BMP280 Test:");
Serial.print("Temperature: "); Serial.print(temperature); Serial.print(" C ");
Serial.print("Pressure: "); Serial.print(pressure); Serial.print(" Pa ");
Serial.print("Altitude: "); Serial.print(altitude); Serial.println(" m ");
Serial.println("BMP280 Test Complete!");
delay(2000);
// Test SD Card
if (SD.begin(16)) {
Serial.println("SD Card Test: SD card initialized successfully.");
File testFile = SD.open("testfile.txt", FILE_WRITE);
if (testFile) {
testFile.println("SD Card Test Successful!");
testFile.close();
Serial.println("SD Card Test: Test file written successfully.");
} else {
Serial.println("SD Card Test: Failed to open file for writing.");
}
} else {
Serial.println("SD Card Test: Failed to initialize SD card.");
}
delay(2000);
}
// Check if "start log" command received and logging not started yet
if (command.equals("start log") && !loggingStarted || command.equals("l") && !loggingStarted) {
loggingStarted = true;
Serial.println("Data logging started!");
}
// Check if "stop log" command received and logging currently active
if (command.equals("stop log") && loggingStarted || command.equals("s") && loggingStarted) {
loggingStarted = false;
Serial.println("Data logging stopped!");
}
}
// Save sensor data to SD card if logging started
if (loggingStarted) {
saveDataToFile("datalogg.csv", String(averageAccelX) + "," + String(averageAccelY) + "," + String(averageAccelZ) + "," +
String(gyroX) + "," + String(gyroY) + "," + String(gyroZ) + "," +
String(temperature) + "," + String(averagePressure) + "," + String(relativeAltitude) + "," + String(verticalSpeed));
}
// Check for apogee detection if logging started
if (loggingStarted && !apogeeDetected) {
if (relativeAltitude > maxAltitude) {
maxAltitude = relativeAltitude; // Update maximum altitude
} else if ((maxAltitude - relativeAltitude) > APOGEE_THRESHOLD) {
// Apogee detected
apogeeDetected = true;
// Save apogee data to SD card
saveApogeeData(maxAltitude, currentTime);
}
}
delay(100); // Adjust delay as needed
}
void initializeMPU() {
if (!mpu.begin()) {
Serial.println("Failed to initialize MPU6050!");
while (1);
}
Serial.println("MPU6050 initialized.");
}
void initializeBMP() {
if (!bmp.begin(BMP280_ADDRESS_ALT, BMP280_CHIPID)) {
Serial.println("Failed to initialize BMP280!");
while (1);
}
Serial.println("BMP280 initialized.");
initialAltitude = bmp.readAltitude(1013.25); // Set initial altitude
initialZAccel = 0.0;
}
void initializeSDCard() {
// Ensure BMP280 is not using the SPI bus
digitalWrite(BMP_CS, HIGH);
if (!SD.begin(16)) {
Serial.println("Failed to initialize SD card!");
// while (1);
}
Serial.println("SD card initialized.");
}
void sendDataInChunks(const char *data) {
int dataLength = strlen(data);
int chunkSize = 32;
int chunks = (dataLength / chunkSize) + ((dataLength % chunkSize) > 0 ? 1 : 0);
for (int i = 0; i < chunks; i++) {
radio.stopListening();
char chunk[32] = {0}; // Initialize buffer with null characters
strncpy(chunk, data + (i * chunkSize), chunkSize); // Copy 32 bytes or remaining bytes
radio.write(chunk, sizeof(chunk)); // Send chunk
radio.startListening(); // Start listening again
// delay(10); // Short delay to ensure proper transmission
}
}
void getData() {
if (radio.available()) {
radio.read(&receivedCommand, sizeof(receivedCommand));
newData = true;
}
}
void executeCommand() {
String command = String(receivedCommand);
command.trim(); // Remove any extra spaces or newlines
// Check if command is "deploy" or "eject"
if (command.equals("a") || command.equals("eject")) {
Serial.println("Chute Deployed!");
parachuteServo.write(180); // Rotate servo to 180 degrees
delay(600); // Allow time for servo to rotate
}
// Check if command is "initial" or "b"
else if (command.equals("initial") || command.equals("b")) {
Serial.println("Chute Ready!");
parachuteServo.write(0); // Set to a neutral or initial position
delay(600); // Allow time for servo to rotate
}
// Check if command is "test" or "t"
else if (command.equals("test") || command.equals("t")) {
Serial.println("Testing components...");
// Test parachute servo movement
int pos;
for (pos = 0; pos <= 180; pos += 5) {
parachuteServo.write(pos);
delay(15);
}
for (pos = 180; pos >= 0; pos -= 5) { // Adjusted range to start from 180 and decrement by 5
parachuteServo.write(pos);
delay(15);
}
delay(2000);
// Test MPU
sensors_event_t a, g, temp;
mpu.getEvent(&a, &g, &temp);
Serial.println("MPU6050 Test:");
Serial.print("AccelX: "); Serial.print(a.acceleration.x); Serial.print(" ");
Serial.print("AccelY: "); Serial.print(a.acceleration.y); Serial.print(" ");
Serial.print("AccelZ: "); Serial.print(a.acceleration.z); Serial.println(" ");
Serial.print("GyroX: "); Serial.print(g.gyro.x); Serial.print(" ");
Serial.print("GyroY: "); Serial.print(g.gyro.y); Serial.print(" ");
Serial.print("GyroZ: "); Serial.print(g.gyro.z); Serial.println(" ");
Serial.println("MPU6050 Test Complete!");
delay(2000);
// Test BMP
float temperature = bmp.readTemperature();
float pressure = bmp.readPressure();
float altitude = bmp.readAltitude(1013.25);
Serial.println("BMP280 Test:");
Serial.print("Temperature: "); Serial.print(temperature); Serial.print(" C ");
Serial.print("Pressure: "); Serial.print(pressure); Serial.print(" Pa ");
Serial.print("Altitude: "); Serial.print(altitude); Serial.println(" m ");
Serial.println("BMP280 Test Complete!");
delay(2000);
// Test SD Card
if (SD.begin(16)) {
Serial.println("SD Card Test: SD card initialized successfully.");
File testFile = SD.open("testfile.txt", FILE_WRITE);
if (testFile) {
testFile.println("SD Card Test Successful!");
testFile.close();
Serial.println("SD Card Test: Test file written successfully.");
} else {
Serial.println("SD Card Test: Failed to open file for writing.");
}
} else {
Serial.println("SD Card Test: Failed to initialize SD card.");
}
delay(2000);
}
// Check if "start log" command received and logging not started yet
else if ((command.equals("start log") || command.equals("l")) && !loggingStarted) {
loggingStarted = true;
Serial.println("Data logging started!");
}
// Check if "stop log" command received and logging currently active
else if ((command.equals("stop log") || command.equals("s")) && loggingStarted) {
loggingStarted = false;
Serial.println("Data logging stopped!");
}
else {
Serial.println("Unknown command!");
}
memset(receivedCommand, 0, sizeof(receivedCommand)); // Clear buffer
}
void checkSerialCommand() {
if (Serial.available() > 0) {
String command = Serial.readStringUntil('\n');
command.trim();
executeCommandFromSerial(command);
}
}
void executeCommandFromSerial(String command) {
// Check if command is "deploy" or "eject"
if (command.equals("a") || command.equals("eject")) {
Serial.println("Chute Deployed!");
parachuteServo.write(180); // Rotate servo to 180 degrees
delay(600); // Allow time for servo to rotate
}
// Check if command is "initial" or "b"
else if (command.equals("initial") || command.equals("b")) {
Serial.println("Chute Ready!");
parachuteServo.write(0); // Set to a neutral or initial position
delay(600); // Allow time for servo to rotate
}
// Check if command is "test" or "t"
else if (command.equals("test") || command.equals("t")) {
Serial.println("Testing components...");
// Test parachute servo movement
int pos;
for (pos = 0; pos <= 180; pos += 5) {
parachuteServo.write(pos);
delay(15);
}
for (pos = 180; pos >= 0; pos -= 5) { // Adjusted range to start from 180 and decrement by 5
parachuteServo.write(pos);
delay(15);
}
delay(2000);
// Test MPU
sensors_event_t a, g, temp;
mpu.getEvent(&a, &g, &temp);
Serial.println("MPU6050 Test:");
Serial.print("AccelX: "); Serial.print(a.acceleration.x); Serial.print(" ");
Serial.print("AccelY: "); Serial.print(a.acceleration.y); Serial.print(" ");
Serial.print("AccelZ: "); Serial.print(a.acceleration.z); Serial.println(" ");
Serial.print("GyroX: "); Serial.print(g.gyro.x); Serial.print(" ");
Serial.print("GyroY: "); Serial.print(g.gyro.y); Serial.print(" ");
Serial.print("GyroZ: "); Serial.print(g.gyro.z); Serial.println(" ");
Serial.println("MPU6050 Test Complete!");
delay(2000);
// Test BMP
float temperature = bmp.readTemperature();
float pressure = bmp.readPressure();
float altitude = bmp.readAltitude(1013.25);
Serial.println("BMP280 Test:");
Serial.print("Temperature: "); Serial.print(temperature); Serial.print(" C ");
Serial.print("Pressure: "); Serial.print(pressure); Serial.print(" Pa ");
Serial.print("Altitude: "); Serial.print(altitude); Serial.println(" m ");
Serial.println("BMP280 Test Complete!");
delay(2000);
// Test SD Card
if (SD.begin(16)) {
Serial.println("SD Card Test: SD card initialized successfully.");
File testFile = SD.open("testfile.txt", FILE_WRITE);
if (testFile) {
testFile.println("SD Card Test Successful!");
testFile.close();
Serial.println("SD Card Test: Test file written successfully.");
} else {
Serial.println("SD Card Test: Failed to open file for writing.");
}
} else {
Serial.println("SD Card Test: Failed to initialize SD card.");
}
delay(2000);
}
// Check if "start log" command received and logging not started yet
else if ((command.equals("start log") || command.equals("l")) && !loggingStarted) {
loggingStarted = true;
Serial.println("Data logging started!");
}
// Check if "stop log" command received and logging currently active
else if ((command.equals("stop log") || command.equals("s")) && loggingStarted) {
loggingStarted = false;
Serial.println("Data logging stopped!");
}
else {
Serial.println("Unknown command!");
}
}
void saveDataToFile(const char *filename, String data) {
Serial.print("Attempting to open file: ");
Serial.println(filename);
File file = SD.open(filename, FILE_WRITE);
if (file) {
file.println(data);
file.close();
Serial.println("Data saved to file.");
} else {
Serial.println("Failed to open file for writing.");
}
}
void saveApogeeData(float maxAltitude, unsigned long apogeeTime) {
Serial.println("Attempting to save apogee data...");
File file = SD.open("apogeee.csv", FILE_WRITE);
if (file) {
file.print("MaxAltitude: ");
file.print(maxAltitude);
file.print(" ft, Time: ");
file.println(apogeeTime);
file.close();
Serial.println("Apogee data saved.");
} else {
Serial.println("Failed to open file for writing apogee data.");
}
}
String getDataString() {
sensors_event_t a, g, temp;
mpu.getEvent(&a, &g, &temp);
float accelX = a.acceleration.x;
float accelY = a.acceleration.y;
float accelZ = a.acceleration.z;
float gyroX = g.gyro.x;
float gyroY = g.gyro.y;
float gyroZ = g.gyro.z;
float pressure = bmp.readPressure();
float temperature = bmp.readTemperature();
float currentAltitude = bmp.readAltitude(1013.25);
float currentAltitudeFt = currentAltitude * 3.28084;
int relativeAltitude = (int)(currentAltitudeFt - initialAltitude); // Convert to integer
unsigned long currentTime = millis();
float deltaTime = (currentTime - prevTime) / 1000.0;
float currentZAccel = (accelZ - initialZAccel) * 9.81;
float verticalSpeed = currentZAccel * deltaTime * 3.6;
// Prepare data packet
String dataPacket = String(accelX) + "," + String(accelY) + "," + String(accelZ) + "," +
String(gyroX) + "," + String(gyroY) + "," + String(gyroZ) + "," +
String(relativeAltitude) + "," + String(verticalSpeed);
return dataPacket;
}
Issue: SD card and nRF24 work fine separately. When SD is plugged in, nRF24 stops working (doesn't send or receive data). No errors, just no radio communication.
Using different CS pins → SD (D10), nRF (D15) Changing SPI speeds → SD.begin(10, SPI_HALF_SPEED); Checking power supply → SD and nRF24 get 3.3V from NodeMCU Adding decoupling capacitors (330µF) to nRF24
本文标签: cnRF24 Stops Working When SD Card is Plugged In (NodeMCURF24SDMPU6050BMP280)Stack Overflow
版权声明:本文标题:c++ - nRF24 Stops Working When SD Card is Plugged In (NodeMCU + RF24 + SD + MPU6050 + BMP280) - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741956012a2406991.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论