Struggling to make sense of sample code - Need help

Hi,

I’ve acquired an inclinometer sensor.

The sensor info can be found here : MURATA SCA100T Dual Axis Inclinometer Sensor | 14core.com

On that page there is sample code. I copied and pasted it into the arduino IDE but couldn’t anything meaningful out of it so now I’m going through trying to work out what I/the sample code has wrong.

BTW I’m using a nano, the same as what is shown in their wiring diagram on the webpage mentioned above.

The sample code is below.

#include <SPI.h>
 
const int DIN = 11; 
const int DOUT = 12;
const int CSPIN = 10
const int SCLCK = 13;
 
const byte MEAS = 0 //00000000 Measure Mode
const byte RWTR = 8 //00001000 Read Temperature Reg
const byte RDSR = 10; 
const byte RLOAD = 11; 
const byte SX = 14; //00001110 Enable self test for X Channel
const byte SY = 15; //00010000 Enable self test for Y Channel
const byte AX = 16; //00010000 Read X Channel Acceleration
const byte AY = 17; //00010001 Read Y Channel Acceleration
 
word readCommand(byte ofVal) {
    byte inByte = 0;
    word sense = 0;
    digitalWrite(CSPIN, 0);
    delay(20);
    SPI.transfer(ofVal);
    sense = SPI.transfer(MEAS);
    sense = sense << 8;
    inByte = SPI.transfer(MEAS);
    sense = sense | inByte;
    sense = sense >> 5;
    digitalWrite(CSPIN, 1);
    return(sense);
}
 
void setup(){
while(!Serial){
Serial.begin(9600);
}
 
  Serial.println("14CORE | SCA100T TEST CODE");
  Serial.println("Initializing............. ");
  delay(4000); 
  SPI.begin();
  SPI.setBitOrder(MSBFIRST)
  SPI.setDataMode(0);
  Serial.println("");
  pinMode(DIN, INPUT);
  pinMode(DOUT, OUTPUT);
  pinMode(CSPIN, OUTPUT);
  pinMode(SCLCK, OUTPUT);
  delay(1000);
}
 
void loop(){
 
    int senseX = readCommand(AX);
    int senseY = readCommand(AY);
    Serial.println("Read value of X > ");
    Serial.println(AX);
    Serial.println("Read value of Y > ");
    Serial.println(AY);
    delay(1000);
 
}

As I read through this I see a few mistakes.
Mistake 1: a few “;” missing.
Mistake 2: some commented binary values are incorrect

Mistake 3: I think they have swapped DIN and DOUT, can someone confirm this? i.e. should MISO be an output or input pin, I would have though input. And Should MOSI be and output or input pin? I would have through Output.

Now for the more confusing part, at least for me. The function they have written “readCommand”, go to line 6 of this function:

sense = SPI.transfer(MEAS);

Note that MEAS has value of 0 or binary 00000000

The next line of code is:

sense = sense << 8;

So we shift the MEAS binary value by 8 places to the left, i.e. changing the binary from 00000000 to 0000000 i.e. no change.
The following lines of code come next:

inByte = SPI.transfer(MEAS);
  sense = sense | inByte;
  sense = sense >> 5;

Don’t all of these have binary code 00000000? Why is there any manipulation required for this?

Is my understanding of their code, correct? Are they shifting 0 around a few times to get 0?

My confusion doesn’t stop there. The whole point of this code is the get readings of X and Y inclination. So in the loop function, they print values of AX and AY which are supposed to be the inclination values i.e. variables. However, they are defined as constant values, are they not?

All I get out on the serial monitor is the following :

“Read value of X > 16”
“Read value of Y > 17”

Can anyone confirm my thoughts above and or provide any corrections for this code? Or identify more incorrect parts of the code?

Thanks for your help,

There are certainly multiple issues with that code. Obviously it won’t compile and thus, as it stands at least, was never tested. Whether it’s worth working with that flawed sketch is a tricky thing to answer.

The issue in loop suggests that it should be this instead:

void loop() 
{
  int senseX = readCommand(AX);
  int senseY = readCommand(AY);
  Serial.println("Read value of X > ");
  Serial.println(senseX);
  Serial.println("Read value of Y > ");
  Serial.println(senseY);
  delay(1000);
}

The original code is a mess, but I guess it worked and was later “improved” by someone who did not test it afterwards.

Maybe I can clear up this issue of understanding:

sense = SPI.transfer(MEAS);

MEAS does indeed have the value of 0 but that is not necessarily what the method SPI.transfer() returns when it has the parameter 0. It could be any valid byte depending on what was read from the device etc. Certain is that it must return a single byte because that is how the method is defined.

Secondly, sense is defined as word ( that is two bytes, actually an unsigned int) so

sense = sense << 8;

puts the byte returned from SPI.transfer() in the ‘left’ byte of sense. So it carries on with the bit manipulation.

Thanks wildbill, that makes sense. I've updated the code to include that.

6v6gt, thank you. That does clear up some of my confusion.

The data sheet states: " Data output is an 11-bit digital word that is fed out MSB first and LSB last."

Since 11 bits is 1.4 bytes and we can only read in 1 byte at a time, we need to read two bytes in (16 bits). We then need to discard the last 5 bits of 'sense'. So that is why the code shifts 'sense' 5 places to the right in the following line:

sense = sense >> 5;

I am now getting value "2047" as the output, however when I remove the MISO cable connection between the sensor and the arduino I still get 2047 as the output. The value doesn't change when I tilt/shake the sensor. If I remove the MOSI line or voltage line the value goes to 0.

The data sheet also states the following:

"Measure mode (MEAS) is standard operation mode after power-up. During normal operation, the MEAS command is the exit command from Self test." & "the AD converted X-channel (Channel 1) acceleration signal stored in acceleration data register X. "

& "the AD converted Y-channel (Channel 2) acceleration signal stored in acceleration data register Y" & "If the SPI interface is not used SCK (pin1), MISO (pin3), MOSI (pin4) and CSB (pin7) must be left floating."

So I connected analog pins A1 and A2 to output 1 and output 2 with the following code:

void setup(){
Serial.begin(9600);
delay(1000);
}

void loop(){

    Serial.println("Analog Read");
    Serial.print("Channel 1 ");
    Serial.println(analogRead(A1));
    Serial.print("Channel 2 ");
    Serial.println(analogRead(A2));
    delay(1000);
}

Wiring as follows: Arduino 5v --> Sensor Vcc Arduino GND --> Sensor GND Arduino A1 --> Sensor OUT_1 Arduino A2 --> Sensor OUT_2

No other cables used other than the mini usb to power the arduino nano.

I still get nothing meaningful out. I seem to be getting floating values out? Out_1 and Out_2 readings are anywhere between 200 and 1023. The sensor is stationary sitting on a desk. I tried to tilt the sensor but did not notice any patterns emerge in the readings.

For completeness, I’ve attached the image of the sensor that I have and the wiring I used for the SPI connection.

I’ve assumed CSB1 is the chip select pin.
Not sure what CSB2 pin and OUT3 pin is for? My guess is that the PCB may be suitable for multiple chips?

Have you a schematic diagram of that break out board for the SCA100T ? You are almost certainly correct that the additional pins are for the chip space which has not be populated on the right hand side of the board.

The one thing I would suggest if you are using the chip in Analog mode is to try pulling the CSB1 towards a power rail with a 1K resistor. First ground, then Vcc. Despite the instruction to leave it floating, it could be that your break out board has a resistor which pulls it in the "wrong" direction.

You could also reduce the delay() in the loop() to say 100mS.

thanks, I’ll give those ideas a try.

I’ve stalked another person on these forums and found code that he/she has posted as working. They did not mention which board they have, merely the chip on the board (SCA100T-D02).

I’ve tried their code however I still get the same result, i.e. the result I get is a constant value of 2047 and not changing when I tilt the sensor.

After your question about the schematics, I went digging to try find one but didn’t expect anything. To my surprise I found something. The closest thing to a schematic that I could find is attached.

From the attached file and having the board in hand I have traced the CSB1 pin to nowhere on the chip. CSB2 connects directly to the CS pin on the chip, it doesn’t pass any resistor.
OUT1 on the board doesn’t connect anywhere on the chip.
OUT2 on the board connects to OUT1 on the chip
OUT3 on the board conencts to OUT2 on the chip
The SPI pins go to where they are supposed to go.

I am concerned that the ground pin is not making it to where it is supposed to go. See attached image, “Closeup of breakout board”.
Are the ‘holes’ that allow traces to go from one side to the other meant to be physical holes? I have had some PCBs printed before, when the trace is required to go between the top side and bottom side, there are visibly small holes which go from one side of the PCB to the other and the holes are lined with, I’m guessing some tin alloy?
To test my suspicion, I connected the SPI connections and power connections as I usually would. I then added a second ground cable which I then physically held the other end of the ground cable to the ground pin of the chip. The readings then changed from 2047 to 0. The result stayed constant at 0 regardless of how much I rotated the sensor. I took the extra ground cable off and the readings went back to 2047. I tried this twice. Once with CSB1 pin connected to D10 of the nano and a second time with CSB2 pin connected to D10 of the nano (D10 being the pin assigned as the chip select pin in the code).

This board was the cheapest possible that I could find on ebay $36 AUD. Other electronics companies in my area (Sydney, Australia) are selling just the chip for $100 AUD or more. Perhaps going cheap was the wrong choice.

Looking at pcb layout diagram, it is clear that CSB1 is for the "other" chip. CSB2 should be connected to pin 10 of the Nano.

Are the 'holes' that allow traces to go from one side to the other meant to be physical holes?

These are via(s) and should be plated through and can be hollow. I would be surprised if these have failed. Can you test with a multimeter ? Pin 6 of the IC should be connected to GND according to the datasheet you have linked.

The soldering on the chip looks rather untidy with some splatter which could be shorting adjacent tracks. Also, the basic chip is quite expensive. If you have not obtained it from a reputable supplier, it may be that you have got a reject (or a used one).

Ok, I’ve found some time to continue this further.

My multi meter doesn’t have a continuity option so I could not check if there were things shorted out with that.

6v6gt:
The one thing I would suggest if you are using the chip in Analog mode is to try pulling the CSB1 towards a power rail with a 1K resistor. First ground, then Vcc. Despite the instruction to leave it floating, it could be that your break out board has a resistor which pulls it in the “wrong” direction.
You could also reduce the delay() in the loop() to say 100mS.

I tried the following:

  • Pulling CSB2 to a 5v rail and then to a GND rail .The readings from the analog input didn’t seem to make sense, just largely varying numbers between 100 and 1023 - The sensor was stationary/horizontal so it should have been fairly constant.
  • Swapping to arduino leonardo - No help

I then decided stuff it! I cut the chip off the board with some edge cutters and soldered some cables onto it. See attached image.
So basically I connected the minimum number of cables that I thought should work based upon the datasheet description “Measure mode (MEAS) is standard operation mode after power-up”.

VCC → Arduino 5v
GND → Arduino GND
OUT1 → 5.1k resistor → Arduino Analog pin A1

I don’t have any capacitors so did not include any, I thought the capacitors were to make the readings less noisy and not necessary for basic function.

I uploaded the following code:

void setup(){
Serial.begin(9600);
delay(1000);
}
 
void loop(){

    Serial.println("Analog Read");
    Serial.print("Channel 1 ");
    Serial.println(analogRead(A1));
    delay(1000);
}

Finally! Some success.
As I tilt the sensor, the readings go from 500ish when near horizontal to 100ish when vertical and near 900 when rotated the other direction i.e. the readings are 100ish when rotated +90° from horizontal and 900ish when rotated -90° from horizontal - Hopefully my description isn’t too hard to understand

The readings are a bit noisy so I’ll try getting some capacitors over the weekend.
I’ll also try the SPI communication after I get the capacitors.

Thanks for the assistance 6v6gt.

Update:

I have obtained the capacitors and resistors as shown in the wiring diagram attached.
I connected pin Analog Out X and Analog Out Y to arduino pins A1 and A2, respectively.

I have modified the source code from the website: MURATA SCA100T Dual Axis Inclinometer Sensor | 14core.com

The code works for both SPI communication and analog read of the outputs.

This is the modified code:

#include <SPI.h>
const int CSPIN = 10;
const byte MEAS = 0; //00000000 Measure Mode
const byte RWTR = 8; //00001000 Read Temperature Reg
const byte RDSR = 10; 
const byte RLOAD = 11; 
const byte SX = 14; //00001110 Enable self test for X Channel
const byte SY = 15; //00001111 Enable self test for Y Channel
const byte AX = 16; //00010000 Read X Channel Acceleration
const byte AY = 17; //00010001 Read Y Channel Acceleration
 
word readCommand(byte ofVal) {
    byte inByte = 0;
    word sense = 0;
    digitalWrite(CSPIN, 0);
    delay(20);
    SPI.transfer(ofVal);
    sense = SPI.transfer(MEAS);
    sense = sense << 8;
    inByte = SPI.transfer(MEAS);
    sense = sense | inByte;
    sense = sense >> 5;
    digitalWrite(CSPIN, 1);
    return(sense);
}
 
void setup(){
Serial.begin(9600);
  delay(4000); 
  SPI.begin();
  SPI.setBitOrder(MSBFIRST);
  pinMode(CSPIN, OUTPUT);
  delay(1000);
}
 
void loop(){
    int senseX = readCommand(AX);
    int senseY = readCommand(AY);
    Serial.println("Read value of X > ");
    Serial.println(senseX);
    Serial.println("Read value of Y > ");
    Serial.println(senseY);
    Serial.print("Analog Read of X axis is: ");
    Serial.println(analogRead(A1));
    Serial.print("Analog Read of Y axis is: ");
    Serial.println(analogRead(A2));
    delay(1000);
 
}

Everything is working fine.
If anyone is using this code, remember that the output in this code is:
10 bit ADC values from the arduino analog read
11 bit values from the SPI communication.
If you want output to be in degrees of inclination, you would need to convert the output appropriately.
Cheers

My multi meter doesn't have a continuity option so I could not check if there were things shorted out with that."

Of course it has a continuity function. It's called ohms, ohmmeter. Zero Ohms means there is continuity.

Paul