I'm relatively new to arduino, but am working with a microSD card and an accelerometer. When I test my sensors individually, they work fine, but when I combine them, the code seems to stop detecting my accelerometer. Here's my code, and for reference it stops during the Adafruit sensor test section of setup.
#include <SPI.h>
#include <SD.h>
#include <Adafruit_ICM20649.h>
#include <Adafruit_Sensor.h>
Adafruit_ICM20649 icm;
const int chipSelect = 5;
uint16_t measurement_delay_us = 65535;
#define ICM_CS 6
#define ICM_SCK 7
#define ICM_MISO 8
#define ICM_MOSI 9
void setup() {
// Open serial communications and wait for port to open:
Serial.begin(115200);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
Serial.print("Initializing SD card...");
// see if the card is present and can be initialized:
if (!SD.begin(chipSelect)) {
Serial.println("Card failed, or not present");
// don't do anything more:
while (1);
}
Serial.println("card initialized.");
Serial.println("Adafruit ICM20649 test!");
// Try to initialize!
// if (!icm.begin_I2C()) {
if (!icm.begin_SPI(ICM_CS)) {
if (!icm.begin_SPI(ICM_CS, ICM_SCK, ICM_MISO, ICM_MOSI)) {
Serial.println("Failed to find ICM20649 chip");
while (1) {
delay(10);
}
}
}
Serial.println("ICM20649 Found!");
// icm.setAccelRange(ICM20649_ACCEL_RANGE_4_G);
Serial.print("Accelerometer range set to: ");
switch (icm.getAccelRange()) {
case ICM20649_ACCEL_RANGE_4_G:
Serial.println("+-4G");
break;
case ICM20649_ACCEL_RANGE_8_G:
Serial.println("+-8G");
break;
case ICM20649_ACCEL_RANGE_16_G:
Serial.println("+-16G");
break;
case ICM20649_ACCEL_RANGE_30_G:
Serial.println("+-30G");
break;
}
// icm.setGyroRange(ICM20649_GYRO_RANGE_500_DPS);
Serial.print("Gyro range set to: ");
switch (icm.getGyroRange()) {
case ICM20649_GYRO_RANGE_500_DPS:
Serial.println("500 degrees/s");
break;
case ICM20649_GYRO_RANGE_1000_DPS:
Serial.println("1000 degrees/s");
break;
case ICM20649_GYRO_RANGE_2000_DPS:
Serial.println("2000 degrees/s");
break;
case ICM20649_GYRO_RANGE_4000_DPS:
Serial.println("4000 degrees/s");
break;
}
// icm.setAccelRateDivisor(4095);
uint16_t accel_divisor = icm.getAccelRateDivisor();
float accel_rate = 1125 / (1.0 + accel_divisor);
Serial.print("Accelerometer data rate divisor set to: ");
Serial.println(accel_divisor);
Serial.print("Accelerometer data rate (Hz) is approximately: ");
Serial.println(accel_rate);
// icm.setGyroRateDivisor(255);
uint8_t gyro_divisor = icm.getGyroRateDivisor();
float gyro_rate = 1100 / (1.0 + gyro_divisor);
Serial.print("Gyro data rate divisor set to: ");
Serial.println(gyro_divisor);
Serial.print("Gyro data rate (Hz) is approximately: ");
Serial.println(gyro_rate);
Serial.println();
}
void loop() {
// make a string for assembling the data to log:
sensors_event_t accel;
sensors_event_t gyro;
sensors_event_t temp;
icm.getEvent(&accel, &gyro, &temp);
Serial.print("\t\tTemperature ");
Serial.print(temp.temperature);
Serial.println(" deg C");
/* Display the results (acceleration is measured in m/s^2) */
Serial.print("\t\tAccel X: ");
Serial.print(accel.acceleration.x);
Serial.print(" \tY: ");
Serial.print(accel.acceleration.y);
Serial.print(" \tZ: ");
Serial.print(accel.acceleration.z);
Serial.println(" m/s^2 ");
/* Display the results (acceleration is measured in m/s^2) */
Serial.print("\t\tGyro X: ");
Serial.print(gyro.gyro.x);
Serial.print(" \tY: ");
Serial.print(gyro.gyro.y);
Serial.print(" \tZ: ");
Serial.print(gyro.gyro.z);
Serial.println(" radians/s ");
Serial.println();
delay(100);
String dataString = "";
String temperature = "";
String gyroscopeX = "";
String gyroscopeY = "";
String gyroscopeZ = "";
String accelerometerX = "";
String accelerometerY = "";
String accelerometerZ = "";
temperature += "\t\tTemperature ", temp.temperature," deg C";
gyroscopeX += "\t\tGyro X: ", gyro.gyro.x;
gyroscopeY += " \tGyro Y: ", gyro.gyro.y;
gyroscopeZ += " \tGyro Z: ", gyro.gyro.z;
accelerometerX += "\t\tAccel X: ", accel.acceleration.x;
accelerometerY += " \tAccel Y: ", accel.acceleration.y;
accelerometerZ += " \tAccel Z: ", accel.acceleration.z;
// open the file. note that only one file can be open at a time,
// so you have to close this one before opening another.
File dataFile = SD.open("datalog.txt", FILE_WRITE);
// if the file is available, write to it:
if (dataFile) {
dataFile.println(temperature);
dataFile.println(gyroscopeX);
dataFile.println(gyroscopeY);
dataFile.println(gyroscopeZ);
dataFile.println(accelerometerX);
dataFile.println(accelerometerY);
dataFile.println(accelerometerZ);
dataFile.close();
// print to the serial port too:
}
// if the file isn't open, pop up an error:
else {
Serial.println("error opening datalog.txt");
}
}
oh, okay. It looks like you uncommented both SPI begin lines. You should only uncomment 1 of them, depending on if you are using software SPI (you are) or hardware SPI (you are not)
Since the first if() statement is the hardware SPI, it fails and never gets to the second if() which is the software SPI. Your code should look like this
// Try to initialize!
// if (!icm.begin_I2C()) {
// if (!icm.begin_SPI(ICM_CS)) {
if (!icm.begin_SPI(ICM_CS, ICM_SCK, ICM_MISO, ICM_MOSI)) {
Serial.println("Failed to find ICM20649 chip");
while (1) {
delay(10);
}
}
}
...
Thanks for the feedback. I implemented it but it still gets stuck on that step...where it doesn't print "failed to find ICM20649 Chip" or that it found the ICM 20649 chip. Are there any other bugs in my code that I could fix?
Post an annotated schematic showing exactly how you have wired it. Be sure to include all power, ground, power sources and indicate any wire over 10"/25cm in length.
I'm not sure how to upload a schematic onto this forum, but I can list the pinouts. I'm using an Arduino Nano which is linked to the ICM 20649 and a MicroSD card adapter
Pinouts for ICM 20649:
5V --> Vin
GND --> GND
D6 --> ChipSelect
D7 --> SCL
D8 --> AD0
D9 --> SDA
Pinouts for MicroSD Adapter
D5 --> ChipSelect
D11 --> MOSI
D12 --> MISO
D13 --> SCK
5V --> VIN
GND --> GND
And I connected by battery pack to the arduino nano via VIN and GND. Let me know if that works in place of a schematic
If your battery pack is connected to Vin and both your sensor and SD module are also connected to Vin, then depending on the battery pack voltage, you could have damaged both modules.
As suggested, a schematic - hand drawn and photographed/scanned is fine - would help more than words.
One suggestion would be to use D10 for one of your device CS signals. It's important that this pin is an output as it will cause the SPI hardware to switch to slave mode if it is left as an unused input.
If you are going to use the accelerometer in SPI mode, then it would seem sensible to use the hardware SPI interface.
Or, did you choose a software SPI interface because the SD card module didn't control the MISO line properly?
Just wanted to follow up after I updated to D10 --> I'm still getting the same issues, and for reference here's what's appearing on my serial monitor: ��8������؎�Initializing SD card...card initialized. Ada+� � !��a�aInitializing SD card...card initialized. Ada+� � !��a�aInitializing SD card...card initialized. Ada+� � !�0a�a.
For reference, when I run this code, the accelerometer outputs data to the serial monitor normally, it's only upon adding the code to include the SD card that it doesn't work properly: `// Basic demo for accelerometer readings from Adafruit ICM20649
#include <Adafruit_ICM20649.h>
#include <Adafruit_Sensor.h>
#include <Wire.h>
Adafruit_ICM20649 icm;
// For SPI mode, we need a CS pin
#define ICM_CS 6
// For software-SPI mode we need SCK/MOSI/MISO pins
#define ICM_SCK 7
#define ICM_MISO 8
#define ICM_MOSI 9
void setup(void) {
Serial.begin(115200);
while (!Serial)
delay(10); // will pause Zero, Leonardo, etc until serial console opens
Serial.println("Adafruit ICM20649 test!");
// Try to initialize!
if (!icm.begin_SPI(ICM_CS, ICM_SCK, ICM_MISO, ICM_MOSI)) {
Serial.println("Failed to find ICM20649 chip");
while (1) {
delay(10);
}
}
Serial.println("ICM20649 Found!");
// icm.setAccelRange(ICM20649_ACCEL_RANGE_4_G);
Serial.print("Accelerometer range set to: ");
switch (icm.getAccelRange()) {
case ICM20649_ACCEL_RANGE_4_G:
Serial.println("+-4G");
break;
case ICM20649_ACCEL_RANGE_8_G:
Serial.println("+-8G");
break;
case ICM20649_ACCEL_RANGE_16_G:
Serial.println("+-16G");
break;
case ICM20649_ACCEL_RANGE_30_G:
Serial.println("+-30G");
break;
}
// icm.setGyroRange(ICM20649_GYRO_RANGE_500_DPS);
Serial.print("Gyro range set to: ");
switch (icm.getGyroRange()) {
case ICM20649_GYRO_RANGE_500_DPS:
Serial.println("500 degrees/s");
break;
case ICM20649_GYRO_RANGE_1000_DPS:
Serial.println("1000 degrees/s");
break;
case ICM20649_GYRO_RANGE_2000_DPS:
Serial.println("2000 degrees/s");
break;
case ICM20649_GYRO_RANGE_4000_DPS:
Serial.println("4000 degrees/s");
break;
}
// icm.setAccelRateDivisor(4095);
uint16_t accel_divisor = icm.getAccelRateDivisor();
float accel_rate = 1125 / (1.0 + accel_divisor);
Serial.print("Accelerometer data rate divisor set to: ");
Serial.println(accel_divisor);
Serial.print("Accelerometer data rate (Hz) is approximately: ");
Serial.println(accel_rate);
// icm.setGyroRateDivisor(255);
uint8_t gyro_divisor = icm.getGyroRateDivisor();
float gyro_rate = 1100 / (1.0 + gyro_divisor);
Serial.print("Gyro data rate divisor set to: ");
Serial.println(gyro_divisor);
Serial.print("Gyro data rate (Hz) is approximately: ");
Serial.println(gyro_rate);
Serial.println();
}
void loop() {
// /* Get a new normalized sensor event */
sensors_event_t accel;
sensors_event_t gyro;
sensors_event_t temp;
icm.getEvent(&accel, &gyro, &temp);
Serial.print("\t\tTemperature ");
Serial.print(temp.temperature);
Serial.println(" deg C");
/* Display the results (acceleration is measured in m/s^2) */
Serial.print("\t\tAccel X: ");
Serial.print(accel.acceleration.x);
Serial.print(" \tY: ");
Serial.print(accel.acceleration.y);
Serial.print(" \tZ: ");
Serial.print(accel.acceleration.z);
Serial.println(" m/s^2 ");
/* Display the results (acceleration is measured in m/s^2) */
Serial.print("\t\tGyro X: ");
Serial.print(gyro.gyro.x);
Serial.print(" \tY: ");
Serial.print(gyro.gyro.y);
Serial.print(" \tZ: ");
Serial.print(gyro.gyro.z);
Serial.println(" radians/s ");
Serial.println();
delay(100);
// Serial.print(temp.temperature);
//
// Serial.print(",");
//
// Serial.print(accel.acceleration.x);
// Serial.print(","); Serial.print(accel.acceleration.y);
// Serial.print(","); Serial.print(accel.acceleration.z);
//
// Serial.print(",");
// Serial.print(gyro.gyro.x);
// Serial.print(","); Serial.print(gyro.gyro.y);
// Serial.print(","); Serial.print(gyro.gyro.z);
// Serial.println();
//
// delayMicroseconds(measurement_delay_us);
}`
I'm using less than 6V to power. Right now I'm using 5V DC from my PC and eventually plan to shift to 4.5V. What would you recommend I do if I can't connect to VIN?
Everything is powered through 5V, and they both work when individually tested. However, the issues only arise when I combine them in the code, which makes me believe it's a coding issue. Is there anything in the code that could lead to the garbage character outputs?