CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

SCL3300

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
beaker404



Joined: 24 Jul 2012
Posts: 163

View user's profile Send private message

SCL3300
PostPosted: Wed Aug 11, 2021 2:48 pm     Reply with quote

Working with the Murata SCL3300 tilt sensor.
Anyone seen any example code or instructions on getting going with this chip?
The SPI bus is working and working with 32b. I am just not getting the addressing or SPI framing scheme. I go through the motions and get wrong data and addresses.
Not a CCS question or kick this off if not appropriate. I did find some Arduino code on the web but it was not much help.

I can post more if you all want to see the code I have but first thought I would ask for a point to on the web for some better examples the data sheet is a bit lacking.
temtronic



Joined: 01 Jul 2010
Posts: 9232
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Wed Aug 11, 2021 2:54 pm     Reply with quote

Basic questions
1) Which PIC ?
2) VDD is 3 or 5 volts ??
3) Which SPI MODE ?

4) Post a small, compilable program that shows what you're doing.
Ttelmah



Joined: 11 Mar 2010
Posts: 19529

View user's profile Send private message

PostPosted: Thu Aug 12, 2021 2:25 am     Reply with quote

As Jay is alluding to, this is a 3.3v chip, so needs a 3.3v PIC, or hardware
level translation between the PIC and the chip. Beware that units sold
for things like the Arduino, have translation on the clock and the output
pin, but do not generally have translation on the MISO pin (since the
Arduino, will accept a 3.3v signal as 'high', when a 5v PIC will not on the
SPI signal). These therefore will need extra translation on this line.

The SPI should be setup for mode0.
You should not program the SPI to use an 'enable', but operate the CS line
yourself.
Recommended SPI clock is 2MHz to 4MHz.
Note also the need for a 10uSec delay between CS going high and being
dropped for the next command. Otherwise commands will be invalid.
Then there needs to be a long delay (up to 100mSec), for the reading to
be completed.
The data you get back is always the response to the previous command.
The first reply is therefore invalid.
Your writes to the chip need to have a correct CRC, or will be ignored.

Are you configuring for angle, or acceleration output?.

The returned data need to be loaded into a signed int16, which will then
allow you to handle maths correctly.
The returned data is the second and third bytes of the packet. The status
is the first byte returned, then the checksum is the last byte returned.
temtronic



Joined: 01 Jul 2010
Posts: 9232
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Thu Aug 12, 2021 5:21 am     Reply with quote

Got the datasheet, had a quick read...
They say to read the 'WHOAMI' register as a check to see IF you're 'connected and coded' properly. It'll return a specific value.
once you get that right, I'd read the temperature registers, convert (as per datasheet..) and work on that until it's correct.
While temperature will probably be higher than room temperature (self heating..), it should be a stable value and easy to code !

The Arduino code, while not runable on a PIC, may save a lot of time typing, especially for tables of defaults or 'settings'....CRC calculation...
Jay
beaker404



Joined: 24 Jul 2012
Posts: 163

View user's profile Send private message

PostPosted: Thu Aug 12, 2021 7:05 am     Reply with quote

Thanks for the tips. I have been employing a lot of what was suggested here. I am working with the WHOAMI command for verification as well as working with the initialization steps outlined on page 21 of the data sheet. I have code to post and will do so in another post after this one. I will use this post to outline answers to previously asked questions about my setup/efforts.

Whole circuit is 3.3V so no level shift needed for communication.
PIC is PIC18F25K22 running a 16MHz crystal and a clock of 64MHz.
CCS 5.094
MPLAB 8.92 (sorry should have posted this the first time)
Exact sensor I am using: SCL3300-D01-10
The data portion of the SPI frame is 16b, however, as you will see in the code snippets to follow, I am working with and returning INT32 data types so the entire 32b SPI message can be processed for CRC, Return Status etc information.
I have worked with the WHOAMI command and the Temperature command. For now will post code and behavior for the WHOAMI as I believe the statement is true that getting it to work and being able to understand it will make the rest fall in line.
Using the sensor in angle mode not doing accelerometer mode.
Using MODE 1 on the sensor and MODE 0 on SPI per the data sheet.
SPI speed is 2MHz.
SPI signals look nice and crisp on the scope.
I do understand the FRAME OFF method the sensor is using hopefully I am incorporating commands properly.
I will work on a post with some code snippets and behaviors to follow this post.
Ttelmah



Joined: 11 Mar 2010
Posts: 19529

View user's profile Send private message

PostPosted: Thu Aug 12, 2021 7:53 am     Reply with quote

The big thing always is that the sensor replies to the last command each time,
and you need to think about how the data is converted (since it can be
fractional, FP maths needs to be used). Layout to extract the actual 'data'
from the packet is quite complex.

I've just typed a first experiment, to show some thinking of the approach
needed.

Code:

#include <18LF45K22.h>
//basic chip supporting 3.3v operation
#device ADC=10

#FUSES NOWDT                    //No Watch Dog Timer

#use delay(internal=64MHz)
#use rs232(baud=19200,parity=N,UART1,bits=8,stream=PORT1)
#use spi (MASTER, SPI1, MODE=0, BITS=32, BAUD=2000000, STREAM=SCL3300)
//limit to 2MBaud. Using UART1 & SPI1

#define CS PIN_C0 //set to a suitable pin

#include <stdio.h>
#include <stdint.h>

struct SCLdata {
   //beware bitfield are allocated LSB first
   uint8_t RS:2; //RS reply
   uint8_t ADDR:5; //address
   uint8_t RW:1; //RW flag
   int16_t Data;
   uint8_t CRC;
};

union {
   struct SCLdata Rdata;
   uint32_t raw;
} SPIdata;

uint32_t send_commandSCL(uint32_t command)
{
   uint32_t reply;
   output_low(CS);
   delay_us(1); //required tPer/2 delay
   reply=spi_xfer(SCL3300, command);
   //32bit transfer
   output_high(CS);
   dely_us(10); //to ensure commands cannot happen closer than 10uSec
   return reply;
}

#define ANG_FACTOR (182.0444) //angle conversion fator in float

#define READ_ACC_X 0x040000F7
#define READ_ACC_Y 0x080000FD
#define READ_ACC_Z 0x0c0000FB
#define READ_STO 0x100000E9
#define ANG_CTRL 0xB0001F6F
#define READ_ANG_X 0x240000C7
#define READ_ANG_Y 0x280000CD
#define READ_ANG_Z 0x2C0000CB
#define READ_TEMP 0x140000EF
#define READ_STAT 0x180000E5
#define READ_ERR1 0x1C0000E3
#define READ_ERR2 0x200000C1
#define READ_CMD 0x340000DF
#define MODE1 0xB4000102
#define MODE2 0xB4000102
#define MODE3 0xB4000224
#define MODE4 0xB400046B
#define PWR_DOWN 0xB400046B
#define WAKE 0xB400001F
#define SW_RESET 0xB4002098
#define RD_WHOAMI 0x40000091
#define RD_SERIAL1 0x640000A7
#define RD_SERIAL2 0x680000AD
#define RD_BANK 0x7C0000B3
#define SEL_BANK0 0xFC000073
#define SEL_BANK1 0xFC00016E

#inline
uint8_t CRC8(uint8_t BitValue, uint8_t CRC)
{
   uint8_t Temp;
   Temp = (uint8_t)(CRC & 0x80);
   if (BitValue == 0x01)
   {
      Temp ^= 0x80;
   }
   CRC <<= 1;
   if (Temp > 0)
   {
      CRC ^= 0x1D;
   }
   return CRC;
}

uint8_t CalculateCRC(uint32_t Data)
{
   uint8_t BitIndex;
   uint8_t CRC;
   CRC = 0xFF;
   for (BitIndex = 31; BitIndex > 7; BitIndex--)
   {
      CRC = CRC8(bit_test(Data,BitIndex), CRC);
   }
   CRC = CRC ^ 0xFF;
   return CRC;
}

float to_angle(int16_t data)
{
   //angle arrives as signed int16, maths must be float
   return data/ANG_FACTOR; //using float angle conversion
}

float to_temp(int16_t data)
{
   //return the temperature
   return -273+(data/18.9); //again use float conversion
}

float to_g(int16_t data)
{
   //return the acceleration - Mode 1
   return data/6000.0;
}
//all of the above, since they can return fractional values, must use
//fp arithmetic. I force this by using float conversion factors.

void main()
{
   output_high(CS); //ensure CS starts high
   while (TRUE)
   {
      delay_ms(10); //unsure device has had time to start
      SPIdata.raw=send_commad(SW_RESET);
      delay_ms(1);
      SPIdata.raw=send_command(MODE_1); //default but set anyway

      SPIdata.raw=send_command(ANG_CTRL); //enable angle output ode
 
      delay_ms(25);
      //Now need to read th estatus register twice to clear it
      SPIdata.raw=send_command(READ_STAT);
      SPIdata.raw=send_command(READ_STAT);
      SPIdata.raw=send_command(READ_STAT); 
      if (SPIdata.Rdata.RS!=0b01)
      {
         //problem - have not receives RS='01' - read the status and retry
         printf(PORT1,"%04x/n", SPIdata.rData.data); //display the status register value         
         printf(PORT1,"A/n"); //message to show this has happened
         continue; //loop back
      } 
      SPIdata.raw=send_command(Read_ANG_X); //Now on each loop send this as the last
      //command so the value is returned at the start of the loop
     
      //Now need to read the registers every 0.5mSec or noise performance will degrade
      while (TRUE)
      {
         SPIdata.raw=send_command(READ_ANG_Y); //This will return ANG_X
         printf(PORT1,"%05.1f X\n", to_angle(SPIdata.rData.data));
         SPIdata.raw=send_command(READ_ANG_Z); //This will return ANG_Y
         printf(PORT1,"%05.1f Y\n", to_angle(SPIdata.rData.data));     
         SPIdata.raw=send_command(READ_ANG_X); //This will return ANG_Z
         printf(PORT1,"%05.1f z\n", to_angle(SPIdata.rData.data)); 
         //Now at 19200bps, the massages will take 1.25mSec
         //so can delay no more than 3.75mSec to meet the sampling spec.
         delay_ms(3);
      }
   }   
   while(TRUE)
   {
      delay_cycles(1);
   }
}


No guarantees, it is 'as typed'....
beaker404



Joined: 24 Jul 2012
Posts: 163

View user's profile Send private message

PostPosted: Thu Aug 12, 2021 8:25 am     Reply with quote

Here are some code snippets of my setup followed by a discussion of the data I get back. I am using a CS line that I control with output_high() output_low() commands.

Code:

#device PIC18f25k22

#fuses HSH, NOWDT, PUT, NOBROWNOUT, NOMCLR
#use delay(crystal=16M, clock=64M)                      // 18F23K22 running at 64MHz


#INCLUDE <18F25K22.H>

#use spi(master, SPI2, mode=0, baud=2000000, stream=SPI2_TILT, bits=32, MSB_FIRST) // SPI Call for Tilt Sensor

#DEFINE   CS_TILT    PIN_C1    //chip select for tilt sensor

// DEFINES for SCL3300 communication. 
// All communication is 32b

#DEFINE READ_ACC_X               0x040000F7
#DEFINE READ_ACC_Y               0x080000FD
#DEFINE READ_ACC_Z               0x0C0000FB
#DEFINE READ_STO               0x100000E9   // SELF TEST OUTPUT
#DEFINE ENABLE_ANGLE_OUTPUTS      0xB0001F6F
#DEFINE READ_ANG_X               0x240000C7
#DEFINE READ_ANG_Y               0x280000CD
#DEFINE READ_ANG_Z               0x2C0000CB
#DEFINE READ_TEMPERATURE         0x140000EF
#DEFINE READ_STATUS               0x180000E5
#DEFINE READ_ERR_FLAG1            0x1C0000E3
#DEFINE READ_ERR_FLAG2            0x200000C1
#DEFINE READ_CMD               0x340000DF
#DEFINE MODE_1                  0xB400001F
#DEFINE MODE_2                  0xB4000102
#DEFINE MODE_3                  0xB4000225
#DEFINE MODE_4                  0xB4000338
#DEFINE POWER_DOWN_MODE            0xB400046B
#DEFINE   WAKE_UP                  0xB400001F
#DEFINE SW_RESET               0xB4002098
#DEFINE READ_WHOAMI               0x40000091
#DEFINE READ_SERIAL1            0x640000A7
#DEFINE   READ_SERIAL2            0x680000AD
#DEFINE READ_CURRENT_BANK         0x7C0000B3
#DEFINE SWITCH_TO_BANK0            0xFC000073
#DEFINE SWITCH_TO_BANK1            0xFC00016E



Below is the function for the WHOAMI command call

Code:

unsigned int32 WHOAMI_SCL3300() {
   
    unsigned int32 dummy_32 = 0;
   unsigned int32 whoami_register = 0;

   output_low(CS_TILT);
   delay_ms(1);

   dummy_32 = SPI_XFER(SPI2_TILT, READ_WHOAMI);           // Ask who am I
   delay_ms(10);

   whoami_register = SPI_XFER(SPI2_TILT, READ_WHOAMI);    // Ask again
   delay_ms(10);

   output_high(CS_TILT);

   return whoami_register;


}  // end WHOAMI_SCL3300


Below is the initialization function doing the start up on page 21 of the datasheet.

Code:

unsigned int32 init_SCL3300() {
// starts up and configures the SCL3300 for use.

unsigned int32 dummy_32 = 0;                  // used for dummy reads

output_low(CS_TILT);
delay_ms(1);

dummy_32 = SPI_XFER(SPI2_TILT, SWITCH_TO_BANK0);
delay_ms(1);
dummy_32 = SPI_XFER(SPI2_TILT, SW_RESET);            // Software reset SCL3300
delay_ms(1);

dummy_32 = SPI_XFER(SPI2_TILT, MODE_1);              // Set SCL3300 to Mode 1
delay_ms(100);

dummy_32 = SPI_XFER(SPI2_TILT, ENABLE_ANGLE_OUTPUTS);           // enable angle output mode
                            // required for mode setup
delay_ms(1);
dummy_32 = SPI_XFER(SPI2_TILT, READ_STATUS);     // dummy read #1

delay_ms(1);
dummy_32 = SPI_XFER(SPI2_TILT, 0x00);     // dummy read #2

delay_ms(1);
dummy_32 = SPI_XFER(SPI2_TILT, 0x00);     // actual status read checking for proper SCL3300 setup
delay_ms(1);


delay_ms(1);
output_high(CS_TILT);

return dummy_32;

}  // end init_SCL3300()


below is a simple main used for checking the SC3300 operation.

Code:


main() {

SCL3300_register = init_SCL3300();                    // setup Tilt sensor
delay_ms(200);

while(1) {
        SCL3300_register = whoami_SCL3300();           
        delay_ms(10);
             
     fprintf(OOK_SERIAL, "$CA\t%08lX#\n\r",SCL3300_register); 

}

}
     
 


For the WHOAMI command, I get a message back of 0x2180609D
that is reported back via the fprintf() statement.
That is not right, the OP CODE + RS value does not jive with what the data sheet says. also, I think the CRC is wrong too.
I am not convinced I am doing the set up correctly and not convinced my data type for the message is the correct choice.
beaker404



Joined: 24 Jul 2012
Posts: 163

View user's profile Send private message

PostPosted: Thu Aug 12, 2021 9:59 am     Reply with quote

Ttelmah, can you expand on your following code and comment.

Quote:


struct SCLdata {
//beware bitfield are allocated LSB first
uint8_t RS:2; //RS reply
uint8_t ADDR:5; //address
uint8_t RW:1; //RW flag
int16_t Data;
uint8_t CRC;
};


are you saying the data coming in is LSB first? I thought the datasheet states MSB first.

As stated before, my WHOAMI call returns 0x2180609D

That would mean the data portion is 0x8060
CRC would be 0x9D
OP CODE + RS is 0x21 (0010 0001b)
so R/W is '0' correct, for the read command
ADDR would be 01000b if I read the datasheet correctly, that would be 0x08 for the address of the register. ---not right as WHOAMI register is 0x10
or am I doing the conversion wrong? Looks like RS is '01' that indicates a good sensor status.
This is the method I am using for decoding the message, is it flawed?

The data portion of the message is 0x8060. If I cast this to an int8, I get a value of 0x60 not the 0xC1 that WHOAMI should return.

Is my parsing of the SPI frame message incorrect?
Ttelmah



Joined: 11 Mar 2010
Posts: 19529

View user's profile Send private message

PostPosted: Thu Aug 12, 2021 10:52 am     Reply with quote

No, the bit organisation using bit fields in the structure is always LSB
first, so I have to reverse the order of the bits here relative to what comes
from the chip. This is just for the structure layout.

Your delay_ms(1) at boot is rather short. There is a classic problem, that
PIC's wake up faster when power is applied, than most other chips. Hence
you should allow a little longer before talking to the devices.

You need to send READ_STATUS again for the second read on boot,
otherwise the third reply will not be the status. So your return on the boot
won't be what is expected.

The CRC functions I put in do calculate the CRC correctly, so you can test
the CRC by comparing the fourth byte with what this returns.

You need to raise the CS after each four byte transfer. It is the act of
raising this and then lowering it that specifies this is a new command.
Also you are pushing several of the times beyond their maximum. Note
that it bases it's internal timing on how long the first clock edge comes
after the CS drops. It needs only a tiny delay after the CS before the
clocks start.
Code:

unsigned int32 WHOAMI_SCL3300() {
   
    unsigned int32 dummy_32 = 0;
   unsigned int32 whoami_register = 0;

   output_low(CS_TILT);
   delay_cycles(8);
   //or delay_us(1); //maximum

   dummy_32 = SPI_XFER(SPI2_TILT, READ_WHOAMI);           // Ask who am I
   output_highCS_TILT); //must go high
   delay_us(10);
   output_low(CS_TILT);
   delay_cycles(8);
   whoami_register = SPI_XFER(SPI2_TILT, READ_WHOAMI);    // Ask again

   output_high(CS_TILT);
   delay_us(10);

   return whoami_register;


}  // end WHOAMI_SCL3300

It is one of those chips, where you can't use longer delays and get the right
answer. It has maximum times on things.
beaker404



Joined: 24 Jul 2012
Posts: 163

View user's profile Send private message

PostPosted: Thu Aug 12, 2021 12:15 pm     Reply with quote

Quote:

You need to raise the CS after each four byte transfer. It is the act of
raising this and then lowering it that specifies this is a new command.


So every four byte transfer, meaning every time a call is made with spi_xfer() correct?
There needs to be 10uS between when the CS is taken high and the next time it is take low as well.

One topic is that I have the two UARTs running on the PIC18F25K22. One is at 9600 baud and one is at 38400 baud. They are both using the hardware TX/RX pins.
So for 9600 one 8b char (10b really, 1 start 8 data 1 stop) takes ~1mS, for 38400, the time is ~0.26mS
So the tilt sensor is picky on timing, should I disable these UART interrupts while I am working with the chip to keep timing tight on talking with the tilt sensor?
By the way, made the mods you pointed out in the WHOAMI function, getting correct data stream for that now. Moving to implement initialization and temperature reading next to build communication confidence.
Ttelmah



Joined: 11 Mar 2010
Posts: 19529

View user's profile Send private message

PostPosted: Fri Aug 13, 2021 6:08 am     Reply with quote

The UART will be sending the data while you are waiting for the SPI
transactions to complete. Shouldn't cause any problems.

It is not that fussy about timing. The internal state machine is clocked
off a PLL synchronised from the SPI. It uses the gap at the start when CS
drops to trigger this to reset. There should not be less than the SPI clock
period/2 from CS to the first data bit, and should not be more than 10uS at
the same point. The machine then needs 10uSec after a command completes
before it can accept another.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group