Problem with adjusting code from I2C to SPI communication interface

Hello,

I was using I2C to communicate with 3d accelerometer (LIS35DE), but as it will be part of my bachelor thesis communication over SPI is required instead, and I need some help adjusting my code for that, I post my I2C code first and than SPI code which is not working maybe you could help me find errors in there so it could work with similar functionality as the I2C code. (right now I receive just zeros).

The accelerometer needs to be powered by 3,6 V at most so I power it through "voltage dividers", datasheets says that it needs 0,45 mA at the most so I hope there is no problem there, it also states that
"SPI clock frequency 10 MHz" I don't know what parameters are also relevant there so I include datasheet to this post if anyone would like to know. I include also wiring scheme so you could also say if there is problem there.

Please if possible post answer like you can't use this function like xxx type xyz instead, maybe not like read this 10 books and than you could read and understand this article where you could find an answer.

Code for I2C:

       //Hex bufferA for registers: X-0x29 ; Y-0x2B ; Z-0x2D
       // Ctrl_Reg1 - 0x20

        #define accel_module (0x1D)
        
        int readRegister =0x29;        
        char bufferA;
        
        
        
        #include <Wire.h>
        
        void setup()
        {
          Wire.begin();        // join i2c bus (address optional for master)
          Serial.begin(9600);  // start serial for output
          Wire.beginTransmission(accel_module);
          Wire.write(0x20);  // adres CTRL_REG1 25 str. datasheet
          Wire.write(64);     // turn on accelerometer (active mode)
          Wire.write(32);
          Wire.endTransmission();
        }
          

      void loop()
      {
          
          int x,y,z;
          
          dataRead();
          readRegister=0x29;       
          dataRead();
          x = bufferA;
          Serial.print(x);
          Serial.print("    "); 

          dataRead();
          readRegister=0x2B;
          dataRead();
          y = bufferA;
          Serial.print(y);
          Serial.print("    "); 
          
          dataRead();
          readRegister=0x2D;
          dataRead();
          z = bufferA;          
          Serial.print(z);
          Serial.print("    "); 
          
          Serial.write(10);                        
          
                     
          delay(500); 
      }
      

void dataRead(){
          
         
          bufferA=0;          
                 
          Wire.beginTransmission(accel_module);
          Wire.write(readRegister);
          Wire.endTransmission();
          
          Wire.beginTransmission(accel_module);
          Wire.requestFrom(accel_module, 1);
          
          
          while(Wire.available()){
          bufferA= Wire.read();
          
          }
          Wire.endTransmission();
          
  
}

Code for SPI:

       //Hex bufferA for registers: X-0x29 ; Y-0x2B ; Z-0x2D
       // Ctrl_Reg1 - 0x20

        #define accel_module (0x1D)
        
        int readRegister =0;        
        char bufferA;
        const int slaveSelectPin = 10;
        
        
        #include <SPI.h>
        
        void setup()
        {
      
          pinMode (slaveSelectPin, OUTPUT);
          SPI.begin();
          SPI.beginTransaction(SPISettings(10000000, MSBFIRST, SPI_MODE0));
          Serial.begin(9600);  // start serial for output

         
          
          SPI.transfer(0x20);  // address CTRL_REG1 datasheet
          SPI.transfer(64);    // turn on accelerometer (active mode)
         

        }
          

      void loop()
      {
          
          int x,y,z;
          
          dataRead();
          readRegister=0x29;       
          dataRead();
          x = bufferA;
          Serial.print(x);
          Serial.print("    "); 

          dataRead();
          readRegister=0x2B;
          dataRead();
          y = bufferA;
          Serial.print(y);
          Serial.print("    "); 
          
          dataRead();
          readRegister=0x2D;
          dataRead();
          z = bufferA;          
          Serial.print(z);
          Serial.print("    "); 
          
          Serial.write(10);                        
          
                     
          delay(500); 
      }
      

void dataRead(){
          
         
          bufferA=0;                                                       
          SPI.transfer(readRegister);
          bufferA=SPI.transfer(0);
        
          }

LIS35DE.pdf (646 KB)

          SPI.beginTransaction(SPISettings(10000000, MSBFIRST, SPI_MODE0));

          SPI.begin();

I do believe the begin() needs to be first.

Okay thanks, I corrected that but it still isn't working

The first step would have been to post a link to the device that you are trying to talk to. It's not too late...

here is the link: KAmodMEMS2 - moduł z układem LIS35 (3-osiowy akcelerometr z wyjściem cyfrowym) - sklep Kamami

but I also included circuit drawing and datasheet of LIS35DE to the first post

The accelerometer needs to be powered by 3,6 V at most so I power it through "voltage dividers"

Not at all a good idea. The voltage divider output depends on the current draw of the accelerometer, so it is not what you expect and the accelerometer may therefore not be working correctly. You MUST use a 3.3V voltage regulator.

Also, the MISO line is for data transfer from the device to the Arduino, so using a voltage divider on that line won't work as you intend, if at all. Voltage dividers are level shifters in one direction only. To be safe, use a bidirectional level shifter, like this one: https://www.sparkfun.com/products/12009.

Okay than I'll look for the bidirectional level shifter for this circuit replacement thanks, but in the meantime could somebody say whatever my SPI code does pretty much the same as the I2C does, or there are some mistakes and I'm using some functions incorrectly?

You need to control SS, before every transaction set SS low to select the device and set high afterwards. You also need to end transactions. SPI - Arduino Reference

So, I bought this bidirectional level shifter and connected it like on this picture:

My code right now looks like this (I added this end transactions functions and I switch slave select pin on and off and I'm just getting "-1's" printed.

Code:

       //Hex bufferA for registers: X-0x29 ; Y-0x2B ; Z-0x2D
       // Ctrl_Reg1 - 0x20
        #include <SPI.h>
        #define accel_module (0x1D)
        
        int readRegister =0;        
        char bufferA;
        const int slaveSelectPin = 10;
        

        
        void setup()
        {
      
          pinMode (slaveSelectPin, OUTPUT);
          SPI.begin();
          SPI.beginTransaction(SPISettings(10000000, MSBFIRST, SPI_MODE0));
          
          Serial.begin(9600);  // start serial for output

         
          digitalWrite(slaveSelectPin,LOW);
          SPI.transfer(0x20);  // addreslaveSelectPin CTRL_REG1 datasheet
          SPI.transfer(64);    // turn on accelerometer (active mode)
          digitalWrite(slaveSelectPin,HIGH);
          SPI.endTransaction();

        }
          

      void loop()
      {
    
          int x,y,z;
          
          dataRead();
          readRegister=0x29;       
          dataRead();
          x = bufferA;
          Serial.print(x);
          Serial.print("    "); 

          dataRead();
          readRegister=0x2B;
          dataRead();
          y = bufferA;
          Serial.print(y);
          Serial.print("    "); 
          
          dataRead();
          readRegister=0x2D;
          dataRead();
          z = bufferA;          
          Serial.print(z);
          Serial.print("    "); 
          
          Serial.write(10);                        
  
                     
          delay(500); 
      }
      

void dataRead(){
          
          digitalWrite(slaveSelectPin,LOW);
          bufferA=0;                                                       
          SPI.transfer(readRegister);
          bufferA=SPI.transfer(0);
          digitalWrite(slaveSelectPin,HIGH);
          SPI.endTransaction();
          }

Please help, I can not understand how to use SPI functions of arduino more without any working example, I'm reading about it on and on and still I don't have any idea what to do to make it work...

This might come as a surprise, but beginTransaction() and endTransaction() are used in pairs.

Okay I changed it so should it be like this:

       //Hex bufferA for registers: X-0x29 ; Y-0x2B ; Z-0x2D
       // Ctrl_Reg1 - 0x20
        #include <SPI.h>
        #define accel_module (0x1D)
        
        int readRegister =0;        
        char bufferA;
        const int slaveSelectPin = 10;
        

        
        void setup()
        {
      
          pinMode (slaveSelectPin, OUTPUT);
          SPI.begin();
          
          
          Serial.begin(9600);  // start serial for output

         
          digitalWrite(slaveSelectPin,LOW);
          SPI.beginTransaction(SPISettings(10000000, MSBFIRST, SPI_MODE0));
          SPI.transfer(0x20);  // addreslaveSelectPin CTRL_REG1 datasheet
          SPI.transfer(64);    // turn on accelerometer (active mode)
          SPI.endTransaction();
          digitalWrite(slaveSelectPin,HIGH);
          

        }
          

      void loop()
      {
    
          int x,y,z;
          
          dataRead();
          readRegister=0x29;       
          dataRead();
          x = bufferA;
          Serial.print(x);
          Serial.print("    "); 

          dataRead();
          readRegister=0x2B;
          dataRead();
          y = bufferA;
          Serial.print(y);
          Serial.print("    "); 
          
          dataRead();
          readRegister=0x2D;
          dataRead();
          z = bufferA;          
          Serial.print(z);
          Serial.print("    "); 
          
          Serial.write(10);                        
  
                     
          delay(500); 
      }
      

void dataRead(){
          
          digitalWrite(slaveSelectPin,LOW);
          SPI.beginTransaction(SPISettings(10000000, MSBFIRST, SPI_MODE0));  //added here
          bufferA=0;                                                       
          SPI.transfer(readRegister);
          bufferA=SPI.transfer(0);
          SPI.endTransaction();
          digitalWrite(slaveSelectPin,HIGH);
        
          }

results are the same ;(

Do you have a common ground between the Arduino, the level shifter and the device? If so, it is not shown in the diagram.

Please post an accurate schematic diagram of your setup. Hand drawn is fine (post a photo).

Fritzing diagrams are confusing, misleading and only for complete beginners with the simplest possible circuits.

I hope this will be readable:

I think problem is I don't quite understand how to use transfer functions and I think I made some mistakes with those... If you could spot where are errors and how it should be writen I would appreciate it very much.

The new diagram is not very helpful, because it suggests that you are using a unidirectional level shifter, with the directionality wired incorrectly. MOSI is data transfer from the Arduino to the device, MISO is the other way.

If you want help, the very least you could do is provide the required basic information on what you are doing. A second step would be to read the data sheets for the devices and take some time to think about and understand the material.

It was the same as on the picture, I can't find accual name, but it this one also on pictures on those sites:

https://learn.sparkfun.com/tutorials/using-the-logic-level-converter

http://www.aliexpress.com/store/product/Freeshipping-Logic-Level-Converter-converts-3-3V-5V-TTL-logic-level-conversion/925845_932132709.html

Okay so I modified circuit:

now I'm receiving just three zeros ("0 0 0")

What I'm trying to do at this point is just to read the values of acceleration from 3 axis, I read datasheet for accelerometer and I know what registers I want to set and read, you can see my code in I2C and that I'm saying it is working, I just need to adjust that code to SPI interface, but I'm failing to do so... ;(

Please tell me what other information do you need?

edit. I'm so sorry I posted same picture again...

right picture there:

The diagram suggests that the MISO/MOSI connections are wrong.

still? after I changed it after your previous reply?

edit. posted right picture to previous post

The most recently posted circuit should work, however there are about four different "modes" for SPI data transfer, and with that unusual device it is anyone's guess if the Arduino SPI library is using the correct one.

You should take a look at the example software on the web page you linked, as it has simple routines for SPI data transfer that presumably work for the sellers. They can replace the calls to the SPI library that you are currently using.

The key would be in the initialization of the SPCR register of the SPI peripheral. Here is what they do:

void SPI_Init(void)
{
	DDR_SPI |= (1<<DD_MOSI)|(1<<DD_SCK)|(1<<DD_SS);
	DDR_SPI &= ~(1 << DD_MISO);
	SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR1)|(1<<SPR0)|(1<<CPOL)|(1<<CPHA)/* | (1<<DORD)*/;
}

Okay thank you for your help till now, I will try to read into it but it does not look understandable for me as for now, could you maybe just for last time look and assure me if the code I posted is looking okay? And what about using different modes in this line: "SPI.beginTransaction(SPISettings(10000000, MSBFIRST, SPI_MODE1));"

could it make any difference?

and what about this section of the code:

  digitalWrite(slaveSelectPin,LOW);
          SPI.beginTransaction(SPISettings(10000000, MSBFIRST, SPI_MODE0));  //added here
          bufferA=0;                                                       
          SPI.transfer(readRegister);
          bufferA=SPI.transfer(0);
          SPI.endTransaction();
          digitalWrite(slaveSelectPin,HIGH);

is it suppose to work as intended? I mean first somehow initialise the register with address in brackets, and then simutaneously send 0 and receive value from register with this address?

And could you maybe explain a little bit how to use this function you posted do I have to do something with libraries or can I use it additional to my program and how to adjust it for it?

edit.
I tried same code with modes from 0 to 3 and there was no difference exept in mode2 there was 31's instead of zeros in other cases just zero's.

edit2.

I tried to decode those functions in this example software folder but I have no idea how those work and how to use them, when I tried to put this initialising function in my code it said I didn't declared some variables which are in this function.

it said I didn't declared some variables which are in this function.

When asking questions about code, doesn't it make sense to post the code in question?

For a beginner, working with an uncommon device, you are traveling a lonely road.

Why do you have to use SPI, if I2C works?
What does SPI have to do with your "bachelor thesis"?
If you have to use SPI, why not use an accelerometer for which debugged Arduino SPI code is available?
Or, contact the sellers. Perhaps they have functioning Arduino code available.

Regarding SPI.beginTransaction(SPISettings(10000000, MSBFIRST, SPI_MODE0));  //added here
Note: the CPOL and CPHA bits in the SPCR specify the mode and both are set to 1 in the example provided by the seller. Compare those with what is set in the Arduino library corresponding to the SPI_MODE call parameter, to determine the correct mode. Also, the speed of 10 MBit/sec could be too high. Check the device data sheet.