Panda 2 - MPL115A1 Pressure Sensor and SPI

Hi all,

Does anyone have idea on getting me started with this?

I dont really know where to start. I have SPI pins, a serial clock,miso and mosi pins but I have no idea what connects to what and then let alone read it.

I have read the datasheet, looked at some arduino code and I think I understand less than when I started :).

I have tried the SPI pressure sensor code on TinyCLR but I dont really understand what that is about either.

[url]http://www.sparkfun.com/products/9721[/url] This is the board at sparkfun.

I read somewhere that this datasheet is useful but I am still at a loss. [url]NXP® Semiconductors Official Site | NXP Semiconductors

TIA

Would this help? GHI Electronics – Where Hardware Meets Software

I think it would possibly help with the bulk of the wiring and getting info back in. Although I wish I knew what all the spi parms were and had a clue how to read the datasheet.

Thanks Gus I did come across that before but it makes more sense now that I have looked at it all more.

I thought about it a bit more but I thought I had it but i dont.

 new SPI.Configuration(Cpu.Pin.GPIO_Pin1,
             false, 0, 0, false, true, 1000, SPI.SPI_module.SPI1);

I don’t understand which pins on the panda 2 to connect when this is how the SPI is setup in code. Some times just a digital pin is used in the examples. As in here:

SPI.Configuration MyConfig =
new SPI.Configuration((Cpu.Pin)FEZmini.Pin.Di2x,
false,0,0,false,true,1000,SPI.SPI_module.SPI1);

The examples look so simple but there are quite a few connections that need setting up before you can even look at the register setting etc…

Dredwerker,

So there’s two components to SPI - the SPI core connections (MOSI, MISO, SCLK) and the device chip select (CS) line.

If you go into Visual Studio, create a new Fez Panda II project, and in program.cs just after the BOOL LedState line is defined, and start typing:

new SPI.Configuration(

you’ll see the auto-complete start telling you information about SPI.Configuration. This tells you what all those parameters are for.

So from this, GPIO_Pin1 is the Chip Select pin, and SPI1 is the SPI module used. If you look at the Panda II user manual you can see the pin mappings, and SPI1 equates to Di11, Di12, Di13 (as MOSI,MISO, SCLK respectively).

The two SPI.Configuration lines you show are functionally exactly the same. If you use the GHI naming of an IO pin, you need to cast it back to a (Cpu.Pin) as the second code snippet does.

So this should tell you enough about SPI and an indication of the wiring needed. But the good news is that you don’t need to use those pins, you have options !

On the Panda II you can optionally use SPI2, which is D38, D36, D35 on the 40-pin connector.

For the Chip Select (CS) pin you can choose to use any IO port you like - select one that won’t cause you a conflict with anything else that you’re likely to do in this project, but you can also move it if you need to at any time simply by changing the first parameter in the configuration.

I haven’t checked the pressure sensor’s wiring diagram, but you need to connect those 4 pins, plus VCC and GND at a minimum.

hope that helps… if you have any more specific questions, ask away :slight_smile:

Decided I’d give you a quick update after looking at the SparkFun data sheet of how I think you need to connect it up.

Sensor ==> Fez

VDD = VCC 3v3
GND = GND
SCK = SCLK
SDI = MOSI
SDO = MISO
CSN = your chosen CS pin
SDN = optional digital pin, that you should set TRUE when you want the sensor to run or FALSE to disable it. Otherwise just wire to VCC 3v3.

Thanks Brett. Help most appreciated.

Still floundering and constantly realising that I know very little about c# dev :slight_smile:

What you have said makes sense and I am giving it a go from the wiring perspective.

I may come back about the register bit but you never know I may just work it all out.

Thanks again :slight_smile:

Right - I have wired it up. I have pin di21 as my Chip select pin.

 bool ledState = false;

            OutputPort led = new OutputPort((Cpu.Pin)FEZ_Pin.Digital.LED, ledState);
            led.Write(ledState);

            SPI.Configuration MyConfig = new SPI.Configuration((Cpu.Pin)FEZ_Pin.Digital.Di21, false, 0, 0, false, true, 1000, SPI.SPI_module.SPI1);

            SPI MySPI = new SPI(MyConfig);
            byte[] tx_data = new byte[8];
            byte[] rx_data = new byte[8];

                     
            MySPI.WriteRead(tx_data, rx_data);
            Thread.Sleep(100);

I am not sure what to do next.

I have was looking at the arduino code from the sparkfun page [url]http://www.sparkfun.com/products/9721[/url] but I am still none the wiser.

// Pin definitions
 #define MPL115A1_ENABLE_PIN 9
 #define MPL115A1_SELECT_PIN 10

// Masks for MPL115A1 SPI i/o
 #define MPL115A1_READ_MASK  0x80
 #define MPL115A1_WRITE_MASK 0x7F 

// MPL115A1 register address map
 #define PRESH   0x00    // 80
 #define PRESL   0x02    // 82
 #define TEMPH   0x04    // 84
 #define TEMPL   0x06    // 86

 #define A0MSB   0x08    // 88
 #define A0LSB   0x0A    // 8A
 #define B1MSB   0x0C    // 8C
 #define B1LSB   0x0E    // 8E
 #define B2MSB   0x10    // 90
 #define B2LSB   0x12    // 92
 #define C12MSB  0x14    // 94
 #define C12LSB  0x16    // 96
 #define C11MSB  0x18    // 98
 #define C11LSB  0x1A    // 9A
 #define C22MSB  0x1C    // 9C
 #define C22LSB  0x1E    // 9E

I think this is the bit which reads it and sets up the register but I just cannot seem to relate that back to the c# code.

  writeRegister(0x24, 0x00);      // Start Both Conversions
    //writeRegister(0x20, 0x00);    // Start Pressure Conversion
    //writeRegister(0x22, 0x00);    // Start temperature conversion
    delay(2);                       // Max wait time is 1ms, typ 0.8ms
    
    // Read pressure
    uiPH = readRegister(PRESH);
    uiPL = readRegister(PRESL);
    uiTH = readRegister(TEMPH);
    uiTL = readRegister(TEMPL);

What is the code inside readRegister? This is what you need to implement. The rest will be almost identical

To me it seems simple enough, you write the register address you need followed by writing or reading the data. I just looked at the code sample from the sparkfun site - main.c in the read() and write() functions.

This is the code in the read and write register.

unsigned int readRegister(byte thisRegister) {
    
    byte result = 0;
    
    // select the MPL115A1
    digitalWrite(MPL115A1_SELECT_PIN, LOW);
    
    // send the request
    SPI.transfer(thisRegister | MPL115A1_READ_MASK);
    result = SPI.transfer(0x00);
    
    // deselect the MPL115A1
    digitalWrite(MPL115A1_SELECT_PIN, HIGH);
    
    return result;  
}


void writeRegister(byte thisRegister, byte thisValue) {
    
    // select the MPL115A1
    digitalWrite(MPL115A1_SELECT_PIN, LOW);
    
    // send the request
    SPI.transfer(thisRegister & MPL115A1_WRITE_MASK);
    SPI.transfer(thisValue);
    
    // deselect the MPL115A1
    digitalWrite(MPL115A1_SELECT_PIN, HIGH);
}

I am still a bit lost. What is all the mask stuff about?

Is it like a label/value pair or something?

Does the value come back on pin 21?

Why is there an array of bytes in the example?

Its possible that I am over complicating this but thanks again guys for your help.

ok good. All code sample will be about identical but the only changes you need are inside these functions and htey are VERY easy :slight_smile:

Here is an example on how it should be done but should look at SPI on wiki Support – GHI Electronics


static int readRegister(byte thisRegister)
{
 
    byte[] result = new byte[1];
    byte[] send = new byte[1];
 
    // select the MPL115A1
//    digitalWrite(MPL115A1_SELECT_PIN, LOW);//this is not needed as it is done automatically, just add this correct SSEL pin to SPI constructor
 
    // send the request
    //SPI.transfer(thisRegister | MPL115A1_READ_MASK);
    //result = SPI.transfer(0x00);
   send[0] = thisRegister | MPL115A1_READ_MASK;
    MySPI.WriteRead(send, result);

    // deselect the MPL115A1
//    digitalWrite(MPL115A1_SELECT_PIN, HIGH);//again, not needed
 
    return result[0];  
}

arggghhh easy :slight_smile: I have lost days of my life trying to get a value back. I could have bought a barometer :slight_smile:

What does the “|” do in

send[0] = thisRegister | MPL115A1_READ_MASK;

Is it some sort of concatenate? It doesnt work in c# - I can’t seem to google it either.

I have read the article on SPI but it doesn’t really explain it. Its a bit like explaining what a database is with the only barest bit of SQL but a lot of info on how databases work - useful later on.

Binary OR.

:o What do you mean it doesn’t work in C#.

I suggest you read this document:

http://cache.freescale.com/files/sensors/doc/app_note/AN3785.pdf?fpsp=1

You will see that when you READ from the module you need to send one byte with register address and you get one byte with its value in return. When you WRITE you send one byte with register address and second byte with value.

You need to send 1 byte to the module that identifies which register you are interested in. The MSB (most significant bit) of that byte needs to be ‘1’ if you want to read that register, ‘0’ if you want to write value to that register. So:

thisRegister | MPL115A1_READ_MASK

results in the register number with MSB set to 1. The MPL115A1_READ_MASK is equal to (1 << 8).

Because the data needs to be a byte array, no matter if you send only one byte.

Here is a link that explains what binary operators do:

http://blog.typps.com/2007/10/bitwise-operators-in-c-or-xor-and-not.html

Try this:


int MPL115A1_READ_MASK = 1 << 8;
int MPL115A1_WRITE_MASK = 0 << 8;

send[0] = (byte)(thisRegister | MPL115A1_READ_MASK);
 

I only meant the line of code didn’t work not the “|” operator and it was annoying to google as it seemed to be ignored.

@ Architect thanks I shall have a read as I am obviously deficient(in this area anyway) :slight_smile:

@ Gralin the byte and then bracket combo compiles wonderfully. understanding it is next on the agenda.
I did read the an3785 pdf and it makes more sense now.

So write starts the process as in “read Pressure” and read gets the value.

 // Masks for MPL115A1 SPI i/o
            byte MPL115A1_READ_MASK     =  0x80;
            byte MPL115A1_WRITE_MASK    =  0x7F;

            // MPL115A1 register address map
            byte PRESH  =   0x00;    // 80
            byte PRESL  =   0x02;    // 82
            byte TEMPH  =   0x04;    // 84
            byte TEMPL  =   0x06;    // 86

            //Bytes to be sent via SPI read and Write
            byte[] result     = new byte[1];
            byte[] send       = new byte[1];
            byte[] sendWrite1 = new byte[1];
            byte[] sendWrite2 = new byte[1];
            byte[] sendWrite3 = new byte[1];
            byte thisRegister;

            // Turn off Blink
            bool ledState = false;

            OutputPort led = new OutputPort((Cpu.Pin)FEZ_Pin.Digital.LED, ledState);
            led.Write(ledState);

            //setup the SPI connnection - Pin 21 - what does it do ????

            SPI.Configuration MyConfig = new SPI.Configuration((Cpu.Pin)FEZ_Pin.Digital.Di21, false, 0, 0, false, true, 1000, SPI.SPI_module.SPI1);

            Debug.Print("Start");
            

            SPI MySPI = new SPI(MyConfig);
            
            //write to start pressure sensor
            //writeRegister(0x24, 0x00);
            sendWrite1[0] = (byte)(0x00 | MPL115A1_WRITE_MASK);
            sendWrite2[0] = (0x24);
            
            
            MySPI.Write(sendWrite1);

            MySPI.Write(sendWrite2);

            //read the information 
            thisRegister = PRESH;

            send[0] = (byte)(thisRegister | MPL115A1_READ_MASK);

            MySPI.WriteRead(send, result);


            Debug.Print(result.ToString());
            Debug.Print("End of Main");
            Thread.Sleep(100);

I have tried to make this similar to the Arduino code:

unsigned int readRegister(byte thisRegister) {
    
    byte result = 0;
    
    // select the MPL115A1
    digitalWrite(MPL115A1_SELECT_PIN, LOW);
    
    // send the request
    SPI.transfer(thisRegister | MPL115A1_READ_MASK);
    result = SPI.transfer(0x00);
    
    // deselect the MPL115A1
    digitalWrite(MPL115A1_SELECT_PIN, HIGH);
    
    return result;  
}


void writeRegister(byte thisRegister, byte thisValue) {
    
    // select the MPL115A1
    digitalWrite(MPL115A1_SELECT_PIN, LOW);
    
    // send the request
    SPI.transfer(thisRegister & MPL115A1_WRITE_MASK);
    SPI.transfer(thisValue);
    
    // deselect the MPL115A1
    digitalWrite(MPL115A1_SELECT_PIN, HIGH);
}

Still to no avail. Any obvious errors here? The write looks similar in structure.

It should be something like this:


// Masks for MPL115A1 SPI i/o
byte MPL115A1_READ_MASK = 0x80;
byte MPL115A1_WRITE_MASK = 0x7F;

// MPL115A1 register address map
byte PRESH = 0x00;    // 80
byte PRESL = 0x02;    // 82
byte TEMPH = 0x04;    // 84
byte TEMPL = 0x06;    // 86

//Bytes to be sent via SPI read and Write
byte[] write = new byte[2];
byte[] result = new byte[1];
byte[] send = new byte[1];
byte thisRegister;

// Turn off Blink
bool ledState = false;

OutputPort led = new OutputPort((Cpu.Pin)FEZ_Pin.Digital.LED, ledState);
led.Write(ledState);

//setup the SPI connnection - Pin 21 - what does it do ?
//This is the pin that you will connect  to CSN on your MPL115A1 breakout board
SPI.Configuration MyConfig = new SPI.Configuration((Cpu.Pin)FEZ_Pin.Digital.Di21, false, 0, 0, false, true, 1000, SPI.SPI_module.SPI1);

Debug.Print("Start");


SPI MySPI = new SPI(MyConfig);

//write to start pressure sensor
//writeRegister(0x24, 0x00);
write[0] = (byte)(0x24 & MPL115A1_WRITE_MASK);
write[1] = (0x00);


MySPI.Write(write);

//read the information 
thisRegister = PRESH;
send[0] = (byte)(thisRegister | MPL115A1_READ_MASK);
MySPI.WriteRead(send, result);


Debug.Print(result.ToString());
Debug.Print("End of Main");
Thread.Sleep(100);

MPL115A1_WRITE_MASK needs binary AND operator. I’ve modified the code.