SPI communication with RM3100 magnetometer testing board

Hi Everyone,

I am a complete novice with Arduino, so apologies for any ignorance on my behalf. Basically, I need to create an SPI communication protocol with an RM 3100 magnetometer testing board (3-axis magnetometer). I have attached the user manual, and I'll try to be as detailed/specific as I can. I have followed the example SPI code given on pages 27-30 of that manual, which sets a cycle count, and then does a continuous or a single measurement. I am using an Arduino Nano, which is hooked to the RM 3100 SPI pins. I have double checked to make sure I haven't put the wires in the wrong place! The code I have is:

#include <SPI.h>
const int DRDY = 8;
const int CS = 10;
uint8_t data;
void setup() {
  
  Serial.begin(115200);
  // put your setup code here, to run once:
  pinMode(DRDY, INPUT);
  pinMode(CS, OUTPUT); 
  SPI.begin();
  SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0));
}

void loop() {
  digitalWrite(CS,HIGH); //set cycle count register
  digitalWrite(CS,LOW);
  SPI.transfer(0x04);
  SPI.transfer(0x00);
  SPI.transfer(0x64);
  SPI.transfer(0x00);
  SPI.transfer(0x64);
  SPI.transfer(0x00);
  SPI.transfer(0x64);
  digitalWrite(CS,HIGH); //end of set cycle counter

  delay(100);
 
//  digitalWrite(CS,LOW); //CMM MODE start
//  SPI.transfer(0x01);
//  SPI.transfer(0x79);
//  digitalWrite(CS,HIGH);

  digitalWrite(CS,LOW); //Single measurement MODE start
  SPI.transfer(0x00);
  SPI.transfer(0x70);
  digitalWrite(CS,HIGH);


 

while(1)
{
measure();
}
}
  void measure() {
    digitalWrite(CS,LOW);
   data=SPI.transfer(0xA4);
   
   Serial.println(data);
  
   digitalWrite(CS,HIGH);
    delay(1000);
    
  }

When I run this code, on either continuous or single measurement, I get a 3-bit value (usually 192, it occasionally drops below that) that prints out every 1000 ms (the delay I have set). What I expect to get here, according to the manual, is 3-bytes of data for X, followed by 3-bytes for Y and 3-bytes for Z, but that isn't what I get and I can't work out how to go about debugging this. This exact question was asked a few years ago (SPI COMMUNICATION ON ARDUINO PLEASE HELP - Networking, Protocols, and Devices - Arduino Forum) but I can't use the advice given there to change what numbers are being read.

Any help would be appreciated, and please let me know if there's any more information that might be helpful.

RM3100 Testing Boards User Manual r04.pdf (658 KB)

The RM3100 is a 3.3V sensor and your Arduino Nano is a 5V board with 5V signals. You might have damaged the sensor.

The Arduino Nano can output 20mA (40mA shortcut current) with its SS and MOSI pins. They can push 5V into the pins of the sensor.

Can you get a 3.3V Arduino board ?
With a 3.3V Arduino board, you could start with the I2C mode and run a I2C Scanner sketch. Then read the REVID byte from the sensor. If that works, then you can try to read the REVID with the SPI interface.

You are aiming at the end result and you are trying to fix that. But an experienced Arduino user does not do that. Make small steps and verify that each step is working.

If you are going to read the REVID from a sensor that might already have been damaged and using a 5V Arduino board, then we can not help you.

You can also get a level translator for less then an arduino. Sparkfun has them for about 3 bucks, there are many other sources for them. google "Arduino Level Translator" you will find manyl.

Koepel:
The RM3100 is a 3.3V sensor and your Arduino Nano is a 5V board with 5V signals. You might have damaged the sensor.

The Arduino Nano can output 20mA (40mA shortcut current) with its SS and MOSI pins. They can push 5V into the pins of the sensor.

Can you get a 3.3V Arduino board ?
With a 3.3V Arduino board, you could start with the I2C mode and run a I2C Scanner sketch. Then read the REVID byte from the sensor. If that works, then you can try to read the REVID with the SPI interface.

You are aiming at the end result and you are trying to fix that. But an experienced Arduino user does not do that. Make small steps and verify that each step is working.

If you are going to read the REVID from a sensor that might already have been damaged and using a 5V Arduino board, then we can not help you.

Thank you very much for your reply. That may well be a problem. I will have to use a 3.3V Arduino or use a level translator, as suggested by a separate poster. You are completely right in that my approach is the wrong way. The issue is I have a deadline with work to hit, and unfortunately I need to try and bypass a lot of the learning steps to get something working (might not be realistic, but it's the hand I've been dealt). Ideally I would start with baby steps, and work my way up!
I will take your advice and try an I2C scanner.

If you were to speculate, would you assume that the reason I'm not getting useful information is due to the 5V/3.3V problem, and if I had an undamaged sensor, with the correct voltages, I would be able to read something sensible?

Thanks a lot!

christ93:
If you were to speculate, would you assume that the reason I'm not getting useful information is due to the 5V/3.3V problem, and if I had an undamaged sensor, with the correct voltages, I would be able to read something sensible?

I don't know :confused:

According to the datasheet, the maximum voltage of the chip is 3.7V and a input pin may not get higher. In theory the sensor is broken with 3.7001 Volt. In real life it might still work.

The Arduino Nano has a diode from the USB 5V to the microcontroller. Therefor, the microcontroller might run at 4.5V (measure the 5V pin). Maybe there is a 0.2V voltage drop in the USB cable. It is not so bad after all, but the sensor could be damaged.

You want to make the end result work.
That is not how we do a project. Make small steps and check every step. There is a I2C Scanner sketch, so that makes the I2C bus a good start. The first thing to do after that is to read the REVID byte (with I2C or SPI). Only then you know that you can read registers from the sensor.

That byte is called the "WHO_AM_I" byte or "CHIP_ID" byte in other sensors. It is a good way to begin the communication with the sensor.

Koepel:
You want to make the end result work.
That is not how we do a project. Make small steps and check every step. There is a I2C Scanner sketch, so that makes the I2C bus a good start. The first thing to do after that is to read the REVID byte (with I2C or SPI). Only then you know that you can read registers from the sensor.

That byte is called the "WHO_AM_I" byte or "CHIP_ID" byte in other sensors. It is a good way to begin the communication with the sensor.

Yeah, you're completely right. It's been a tricky one for me because I've been quite randomly asked to do this, and I have never used Arduino or SPI (or I2C) for anything ever before, and I have a couple of weeks. I will follow your advice and try and test each step. First step will be to make sure the sensor isn't damaged.
Further question: Do you know if Arduino Nano accepts 3.3V logic (MOSI)? I can't find anything about this in the documentation. I ask this because the electronics we have make using a potential divider for the SS and MISO lines easy, but not converting the logic if necessary.
Once again, thanks a lot. You've been very helpful!

Go to the manufacturer's page of the ATmega328P: https://www.microchip.com/wwwproducts/en/ATmega328P.
Open the datasheet and go to page 322.
The VIH for normal pins for VCC of 2.4V and higher is 0.6VCC.

If your ATmega328P runs at 5.0V, then the input should be at least 3.0V to see it as a high level.
If your Nano runs at 4.5V, then it only needs to be 2.7V.

Thank you very much again!

Fingers crossed I can make some progress.

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