Pages: 1 [2] 3   Go Down
Author Topic: MS5541 depth sensor communication  (Read 12536 times)
0 Members and 1 Guest are viewing this topic.
Erlangen, Germany
Offline Offline
Jr. Member
**
Karma: 0
Posts: 60
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

.... and just because it was to much to put it in one post:


MS5541_demo.pde
Code:
/*
 MS5541 Pressure Sensor demonstration sketch
 To obtain the calibration factors run the read-calwords-sketch before.
 
 Circuit:
 MS5541 sensor attached to pins 10 - 13:
 MOSI: pin 11
 MISO: pin 12
 SCK: pin 13
 MCLK: pin 9
CS is not in use, but might be pin 10
  
 created August 2011
 by SMStrauch based on application note AN510 from www.intersema.ch (http://www.meas-spec.com/downloads/Using_SPI_Protocol_with_Pressure_Sensor_Modules.pdf),
 and with help of robtillaart and ulrichard. Thanks!
 */

// include librariy:
#include <SPI.h>

// generate a MCKL signal
const int clock = 9;

//include the calibration factors according to your individual sensor; they MUST be long for internal calculation of the compensated values
//intersema.ch provides a file with expected values
const long c1 = 2723;
const long c2 = 4648;
const long c3 = 388;
const long c4 = 224;
const long c5 = 2309;
const long c6 = 54;

void resetsensor() //this function keeps the sketch a little shorter
{
  SPI.setDataMode(SPI_MODE0);
  SPI.transfer(0x15);
  SPI.transfer(0x55);
  SPI.transfer(0x40);
}

void setup() {
  Serial.begin(9600);
  SPI.begin();
  SPI.setBitOrder(MSBFIRST);
  SPI.setClockDivider(SPI_CLOCK_DIV32); //divide 16 MHz to communicate on 500 kHz
  pinMode(clock, OUTPUT); //sets clockpin on output
}

void loop()
{
  TCCR1B = (TCCR1B & 0xF8) | 1 ; //generates the MCKL signal
  analogWrite (clock, 128) ;

  void resetsensor(); //resets the sensor, be aware SPI remains in Mode 0 afterwards!

  //Temperature:
  unsigned int tempMSB = 0; //first byte of value
  unsigned int tempLSB = 0; //last byte of value
  unsigned int D2 = 0;
  SPI.transfer(0x0F); //send first byte of command to get temperature value
  SPI.transfer(0x20); //send second byte of command to get temperature value
  delay(35); //wait for conversion end
  SPI.setDataMode(SPI_MODE1); //change mode in order to listen
  tempMSB = SPI.transfer(0x00); //send dummy byte to read first byte of value
  tempMSB = tempMSB << 8; //shift first byte
  tempLSB = SPI.transfer(0x00); //send dummy byte to read second byte of value
  D2 = tempMSB | tempLSB; //combine first and second byte of value
  Serial.print("Temperature raw =");
  Serial.println(D2); //voilá!

  void resetsensor();//resets the sensor

  //Pressure:
  unsigned int presMSB = 0; //first byte of value
  unsigned int presLSB =0; //last byte of value
  unsigned int D1 = 0;
  SPI.transfer(0x0F); //send first byte of command to get pressure value
  SPI.transfer(0x40); //send second byte of command to get pressure value
  delay(35); //wait for conversion end
  SPI.setDataMode(SPI_MODE1); //change mode in order to listen
  presMSB = SPI.transfer(0x00); //send dummy byte to read first byte of value
  presMSB = presMSB << 8; //shift first byte
  presLSB = SPI.transfer(0x00); //send dummy byte to read second byte of value
  D1 = presMSB | presLSB; //combine first and second byte of value
  Serial.print("Pressure raw =");
  Serial.println(D1);

  //calculation of the real values by means of the calibration factors and the maths
  //in the datasheet
  const long UT1 = (c5 << 3) + 10000;
  const long dT = D2 - UT1;
  const long TEMP = 200 + ((dT * (c6 + 100)) >> 11);
  const long OFF  = c2 + (((c4 - 250) * dT) >> 12) + 10000;
  const long SENS = (c1/2) + (((c3 + 200) * dT) >> 13) + 3000;
  long PCOMP = (SENS * (D1 - OFF) >> 12) + 1000;
  float TEMPREAL = TEMP/10;
  //2nd order compensation only for T > 0°C
  const long dT2 = dT - ((dT >> 7 * dT >> 7) >> 3);
  const float TEMPCOMP = (200 + (dT2*(c6+100) >>11))/10;

  Serial.print("Real Temperature [°C]=");
  Serial.println(TEMPREAL);

  Serial.print("Compensated pressure [mbar] =");
  Serial.println(PCOMP);

  Serial.print("2nd order compensated temperature [°C] =");
  Serial.println(TEMPCOMP);  

  delay(5000);
}


Any comments are welcome, and please tell me about your applications with the sensor.
« Last Edit: August 25, 2011, 01:45:28 pm by godo » Logged

Δεν ελπίζω τίποτα. Δε φοβούμαι τίποτα. Είμαι λέφτερος.

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 170
Posts: 12465
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

¡Bien hecho smiley-wink

Might include the link to the datasheet in the code
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Erlangen, Germany
Offline Offline
Jr. Member
**
Karma: 0
Posts: 60
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

¡Muchas gracias!
Links are in.
Logged

Δεν ελπίζω τίποτα. Δε φοβούμαι τίποτα. Είμαι λέφτερος.

Erlangen, Germany
Offline Offline
Jr. Member
**
Karma: 0
Posts: 60
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi folks,
and on it goes: I have a new riddle to solve!
Since my project requires quite some memory I decided to upgrade and made myself a neat little Sanguino clone board. It works nicely, I downloaded and installed awesome stuff from here http://avr-developers.com/corefiles/index.html and some Sanguino board data I do not remember from where. It runs both with the Ardu-Duino 644P and Sanguino board settings (but that's probably obvious).
Then I tested sketches I already used on my 2009 as this one... no wait, it is far to long. It is the AnalogLogger example from the SdFat-library which I adapted and added a DS18B20. Unfortunately I only figured out the code formally and adapted it without deep understanding. But it runs like a charm logging 4 analog inputs and digital temperature via SPI onto a µSD-Card. So far so good.
Now comes the riddle: I also adapted the code I displayed in this post but it won't work. There aren't even osci-spikes on the SCK line which I clearly saw running the SdFat-based code. So to me it looks like the sketch doesn't access the SPI-Bus at all, even though I adjusted the PINs to the right ones on the 644 (SS 4, MOSI 5, MISO 6, SCK 7). So - more of a general understanding question - where exactly does the SdFat library access the information about the PIN configuration? And where do I have to give the SPI library that information (I copied and included ArduinoPins.h from the SdFat diractory, but it didn't help)?
Can anybody tell me more about the compiling process, I mean, by selecting a specific board, do I already direct the compiler to a specific file in which the PIN configuration is given or do the respective libraries do that independently of the board I chose; it seems to me a valuable general info and a good point to look for the problem.
Thanks in advance, any comment is apreciated, greetings from Patagonia
Seb

PS: Problem solved with help from Nick. If you modify a .h-file NEVER copy-paste the code but type it. If copy-pasted the changes are visible, appear totally normal but the compiler does not read it properly.
« Last Edit: January 26, 2012, 09:03:55 am by godo » Logged

Δεν ελπίζω τίποτα. Δε φοβούμαι τίποτα. Είμαι λέφτερος.

Offline Offline
Jr. Member
**
Karma: 0
Posts: 69
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hey this is great I just bought the sensor and it is pretty small, how did you manage to solder it, any recommendations?

What did you use for the 32.768. khz clock? I bought t a DS32khz/ 14-dip .. http://www.maxim-ic.com/datasheet/index.mvp/id/2940
I will be using an arduino pro mini for the 3.3 volts that the sensor requires.

I will be use this a diving depth logger..

So I will keep you inform.

Thanks for the code I will try it, any more tips?
Logged


Erlangen, Germany
Offline Offline
Jr. Member
**
Karma: 0
Posts: 60
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi there,
soldering that little one is a royal pain in the ... soldering hand, I can tell you. End of this week I will try it with a reflow oven, but up to now I managed with no clean flux and a lot of patience. Good luck anyway; if you use SPI for datalogging you will have to put a 74HC125 or so into the DOUT line to avoid interfering of the sensor with the sd-card. And THAT one is a demanding little bugger to solder!
This codeline
Code:
  TCCR1B = (TCCR1B & 0xF8) | 1 ; //generates the MCKL signal
  analogWrite (clock, 128) ;
takes care of the signal on pin 9. It is not possible to use any pin but the timer pin, so do not simply switch it. It will allow you to skip the extra chip, so it might be an elegant possibility to keep it all small.
Good luck and share your progress and chalenges, by all means!
Logged

Δεν ελπίζω τίποτα. Δε φοβούμαι τίποτα. Είμαι λέφτερος.

Offline Offline
Jr. Member
**
Karma: 0
Posts: 69
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks for the info..

did you ever tried to do it without using the SPI? i don really want to add the 74HC125...but i will have to try it.. or maybe storing values in an external memory and then export it through serial port will be another idea..

i will keep you posted..
Logged


Offline Offline
Jr. Member
**
Karma: 0
Posts: 69
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

it was quite a challenge to solder this but and i do not if i broke the sensor for over-heating smiley-lol

this is what i go on the serial port when reading the calibration words...


Calibration word 1 =18820
Calibration word 2 =35237
Calibration word 3 =22501
Calibration word 4 =27826
2352
4646
351
217
2405
50
Temperature raw =65535
Pressure raw =65535
Real Temperature in °C=285.00
Compensated pressure in mbar =-209082
2nd order compensated temperature in °C =285.00


some of the values are pretty similar to yours...

but the temperature somehow is not working.. another interesting think is that i am using a 8 MHZ  arduino not the 16....

so i wonder if the divider is set correctly for the frequency...

thanks
Logged


Offline Offline
Jr. Member
**
Karma: 0
Posts: 69
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

second try i hooked the 32.768 khz clock i bought directly to the sensor and things got better

first reading is good, second reading is bad...


Temperature raw =30027
Pressure raw =2047
Real Temperature [°C]=31.00
Compensated pressure [mbar] =-12747
2nd order compensated temperature [°C] =31.00
Temperature raw =49151
Pressure raw =2047
Real Temperature [°C]=175.00
Compensated pressure [mbar] =-16794
2nd order compensated temperature [°C] =175.00

i reset and put my finger and temperature increases
Logged


Offline Offline
Jr. Member
**
Karma: 0
Posts: 69
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

second try i hooked the 32.768 khz clock i bought directly to the sensor and things got better

first reading is good, second reading is bad...


Temperature raw =30027
Pressure raw =2047
Real Temperature [°C]=31.00
Compensated pressure [mbar] =-12747
2nd order compensated temperature [°C] =31.00
Temperature raw =49151
Pressure raw =2047
Real Temperature [°C]=175.00
Compensated pressure [mbar] =-16794
2nd order compensated temperature [°C] =175.00

i reset and put my finger and temperature increases


I solder it again and it is working perfect

thank you man..

the diving community really appreciate your effort

Temperature raw =29659
Pressure raw =14623
Real Temperature [°C]=28.00
Compensated pressure [mbar] =981
2nd order compensated temperature [°C] =28.00
Logged


Erlangen, Germany
Offline Offline
Jr. Member
**
Karma: 0
Posts: 60
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Great, congratulations!
Let me know if you by chance modify the code, because for some reason it only gives X.00 (point zero) temperature values and I would like to have a better resolution.
It is great to contribute to the community after I received so much help and advice, I am very happy to share!
Logged

Δεν ελπίζω τίποτα. Δε φοβούμαι τίποτα. Είμαι λέφτερος.

Offline Offline
Jr. Member
**
Karma: 0
Posts: 69
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Great, congratulations!
Let me know if you by chance modify the code, because for some reason it only gives X.00 (point zero) temperature values and I would like to have a better resolution.
It is great to contribute to the community after I received so much help and advice, I am very happy to share!

i think that i got it

change the calculation of the temeperature to double

Code:
const double TEMP = 200 + ((dT * (c6 + 100)) >> 11);

double TEMPREAL = TEMP/10;

smiley

Logged


Erlangen, Germany
Offline Offline
Jr. Member
**
Karma: 0
Posts: 60
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Wow, great, that is a bit of a surprise though, because:
Quote
The double implementation on the Arduino is currently exactly the same as the float, with no gain in precision.
But, on the other hand:
Quote
Users who borrow code from other sources that includes double variables may wish to examine the code to see if the implied precision is different from that actually achieved on the Arduino.
I will try that asap, thanks!
Logged

Δεν ελπίζω τίποτα. Δε φοβούμαι τίποτα. Είμαι λέφτερος.

Offline Offline
Jr. Member
**
Karma: 0
Posts: 69
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I realized that having the microsd card and the sensor on the same buss will be too complicated due to the libray SDFAT.. and i dont want to add another IC

so i was thingking about doing some bit banging to get the data...

somehow i got it to work(i think)  the reset and pressure conversion sequence works because i am getting data

where i am having problems is on the reading, no reading the correct raw value...how ever if i manually press the sensor with my finger... i start getting numbers...also if i modify the delay on the clk while reading it also changes... smiley

godo please helpme out if you see something weird.. i almost follow the datasheet and some insights of you spi code..

Code:


word start=0b1111010000000000;//start sequence
 unsigned int p1,p2;
long reset=0b10101010101010100000000000000000;//reset sequence
byte counts;//for debug
int dout= 2;//pin for data out MOSI
int din=3;//pin for data in MISO
int clk=4;//data clock
boolean data=0;


void setup() {               
  // initialize the digital pin as an outputand input
 
  Serial.begin(9600);
  pinMode(dout, OUTPUT);     
    pinMode(din, INPUT); 
   pinMode(clk,OUTPUT);
 
}

void loop() {
  pressure();   //main function
  delay(3000);              // wait for a second
}

void pressure()
{
  Serial.println("start Reset");
  //---start REset sequence...
        for(int i=31;i>10;i--)
        {
         
          boolean x;
         
          x=bitRead(reset,i);
       
         
          digitalWrite(dout,x);
           digitalWrite(clk,HIGH);
            digitalWrite(clk,LOW);
        }
   
  //--------Start Conversion sequence
    for(int i=15; i>5;i--)   
    {
               
                       boolean x;
                       x=bitRead(start,i);
                       digitalWrite(dout,x);               
                       //--DRIVE CLOCK
                       digitalWrite(clk,HIGH);
                       digitalWrite(clk,LOW);   
                               
                                       
                               
                               
   }
               
         
         
   //wait unti conversion
    // i keep runing the clock and wait until the Din(miso) detects that it went to 0 and the data is ready
   
     data=  digitalRead(din);
    while(data==1)
   
    {
     
      digitalWrite(clk,HIGH);   
      digitalWrite(clk,LOW);
      data=digitalRead(din);
     
     
    }
   //------------
 
 
 //---start reading
    //Serial.println("Read raw pressure");
     
        for(int i=16; i>=0;i--)
            {
                 digitalWrite(clk,HIGH);    // drive the clock down     
                 delay(10);       
                 digitalWrite(clk,LOW);
                 delay(10);
                 data= digitalRead(din);// i read on low cycle de input(output of the sensor)
                  if(data==1)
                  {
                   
                    bitWrite(p1,i,1);// write the value and i index the int to the right..
             
                    }
                 else
                 {
                bitWrite(p1,i,0);
             
                   
                 }
                 
              counts++;
            }
     
     
     
     
   
   
    //testing to see if shifting will help also
  Serial.println(p1);
  p2=p1>>1;
 
  Serial.println(p2);
  Serial.println(counts);//test to se how many times went into for cycle
  counts=0;
 
}

Logged


Offline Offline
Jr. Member
**
Karma: 0
Posts: 69
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

well i added the 74hc125 and it is workign

take a look

http://www.youtube.com/watch?v=xZsiV52b0B0&feature=youtu.be
Logged


Pages: 1 [2] 3   Go Up
Jump to: