{"id":10,"date":"2010-07-26T09:04:55","date_gmt":"2010-07-26T09:04:55","guid":{"rendered":"http:\/\/ulrichard.is-a-geek.net\/?p=10"},"modified":"2010-07-26T09:04:55","modified_gmt":"2010-07-26T09:04:55","slug":"arduino-code-for-the-intersema-pressure-sensor","status":"publish","type":"post","link":"https:\/\/ulrichard.ch\/blog\/?p=10","title":{"rendered":"Arduino Code for the MS5534C Intersema pressure sensor"},"content":{"rendered":"<p>After receiving personal messages on the arduino forum asking for the code for the Intersema pressure sensor, I paste my code here. It is based on the code from Hari Nair for the <a title=\"solar vario\" href=\"http:\/\/pixelproc.net\/msp430solarvario.html\">open source solar vario<\/a> that I bought from him.<\/p>\n<p><!--more--><\/p>\n<p>I use it in my <a title=\"ChopperControl\" href=\"http:\/\/ulrichard.is-a-geek.net\/gallery2\/main.php?g2_itemId=3802\">ChopperControl<\/a> project which is not quite ready for releasing right now. It&#8217;s about controlling an RC helicopter from the openmoko freerunner smartphone over a bluetooth link.<\/p>\n<p>I ported the code to the Arduino. Later, I learned about SPI, and asked Hari, if it was possible to interface it with SPI. He told me that it&#8217;s not really thought that way, but possible. He sent me a note from Intersema describing that.<\/p>\n<p>In the meantime, Intersema released a sensor with I2C interface which I&#8217;m going to order some soon.<\/p>\n<p>Uploading the packed file didn&#8217;t work at the moment, so I pasted them below. I will upload the files as soon as I figure out how&#8230;<\/p>\n<p><!--more--><\/p>\n<p>*******************\u00c2\u00a0\u00c2\u00a0 IntersemaBaro.h :\u00c2\u00a0 **********************<\/p>\n<p>\/*<br \/>\n* Interface to Intersema Barometric pressure sensor.<br \/>\n* For the moment, only the MS5534C is supported.<br \/>\n* Others might be added in the future, especially the one with I2C.<br \/>\n*<br \/>\n* Created 14 Jan 2010<br \/>\n* By Richard Ulrich<br \/>\n* Inspired by the work of Hari Nair<br \/>\n*\/<br \/>\n#ifndef INTERSEMA_BARO_H<br \/>\n#define INTERSEMA_BARO_H<\/p>\n<p>#include &lt;WProgram.h&gt;<\/p>\n<p>class\u00c2\u00a0 BaroPressure_MS5534C<br \/>\n{<br \/>\npublic:<br \/>\nBaroPressure_MS5534C(uint8_t pinMCLK, uint8_t pinSCLK, uint8_t pinDIN, uint8_t pinDOUT);<\/p>\n<p>void begin();<\/p>\n<p>long getHeightCentiMeters(void)<br \/>\n{<br \/>\nreturn AcquireAveragedSampleCm(NUM_SAMP_FOR_AVG);<br \/>\n}<\/p>\n<p>long getHeightMeters(void)<br \/>\n{<br \/>\nlong AltCm = getHeightCentiMeters();<br \/>\nlong AltAvgM\u00c2\u00a0 = (AltCm &gt;= 0 ? (AltCm + 50L) \/ 100L : (AltCm &#8211; 50L) \/ 100L);<br \/>\nreturn AltAvgM;<br \/>\n}<\/p>\n<p>private:<br \/>\nvoid ResetSensor();<br \/>\nvoid ReadCoefficients(void);<br \/>\nsize_t ReadCoefficient(unsigned char addr);<br \/>\nvoid SendCommand(unsigned long cmd, size_t nbits);<br \/>\nunsigned int ReadWord(void);<br \/>\nlong AcquireAveragedSampleCm(const size_t nSamples);<br \/>\nlong ConvertPressureTemperature(unsigned int pressure, unsigned int temperature);<br \/>\nvoid TriggerTemperatureSample(void);<br \/>\nvoid TriggerPressureSample(void);<br \/>\nlong PascalToCentimeter(long pressurePa);<\/p>\n<p>enum SensorStates<br \/>\n{<br \/>\nSENSOR_READ_TEMPERATURE<br \/>\n};<\/p>\n<p>static const size_t NUM_SAMP_FOR_AVG = 4;<\/p>\n<p>const uint8_t pinMCLK_; \/\/ master clock 32.5 kHz<br \/>\nconst uint8_t pinSCLK_; \/\/ serial clock<br \/>\nconst uint8_t pinDIN_;\u00c2\u00a0 \/\/ data in\u00c2\u00a0 (out on the arduino)<br \/>\nconst uint8_t pinDOUT_; \/\/ data out (in\u00c2\u00a0 on the arduino)<\/p>\n<p>unsigned int coefficients_[6];<br \/>\nSensorStates SensorState_;<br \/>\nsize_t\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0 SmpCnt_;<br \/>\n};<\/p>\n<p>#endif<\/p>\n<p>*******************\u00c2\u00a0\u00c2\u00a0 IntersemaBaro.cpp :\u00c2\u00a0 **********************<\/p>\n<p>\/*<br \/>\n* Interface to Intersema Barometric pressure sensor.<br \/>\n* For the moment, only the MS5534C is supported.<br \/>\n* Others might be added in the future, especially the one with I2C.<br \/>\n*<br \/>\n* Created 14 Jan 2010<br \/>\n* By Richard Ulrich<br \/>\n* Inspired by the work of Hari Nair<br \/>\n*\/<\/p>\n<p>#include &#8220;IntersemaBaro.h&#8221;<br \/>\n\/\/#include &#8220;cppfix.h&#8221;<\/p>\n<p>\/\/using namespace Intersema;<\/p>\n<p>\/** @brief Constructur initializes the pins, reads the coefficients and reads a first altutude measurement. *\/<br \/>\nBaroPressure_MS5534C::BaroPressure_MS5534C(uint8_t pinMCLK, uint8_t pinSCLK, uint8_t pinDIN, uint8_t pinDOUT)<br \/>\n: pinMCLK_(pinMCLK), pinSCLK_(pinSCLK), pinDIN_(pinDIN), pinDOUT_(pinDOUT)<br \/>\n{<\/p>\n<p>}<\/p>\n<p>\/** @brief initialization function that has to be called in the setup() function. *\/<br \/>\nvoid BaroPressure_MS5534C::begin()<br \/>\n{<br \/>\n\/\/ set the pin directions<br \/>\npinMode(pinMCLK_, OUTPUT);<br \/>\npinMode(pinSCLK_, OUTPUT);<br \/>\npinMode(pinDIN_,\u00c2\u00a0 OUTPUT);<br \/>\npinMode(pinDOUT_, INPUT);<\/p>\n<p>\/\/ generate approx 34kHz square for pinMCLK_<br \/>\ntone(pinMCLK_, 31250);<\/p>\n<p>\/\/ configure the sensor<br \/>\nResetSensor();<br \/>\nReadCoefficients();<\/p>\n<p>\/\/ initialize<br \/>\nlong alt = AcquireAveragedSampleCm(NUM_SAMP_FOR_AVG);<br \/>\nTriggerTemperatureSample();<br \/>\nSensorState_ = SENSOR_READ_TEMPERATURE;<br \/>\n}<\/p>\n<p>void BaroPressure_MS5534C::ResetSensor()<br \/>\n{<br \/>\nSendCommand(0x155540, 21); \/\/ 1010101010101010 + 00000<br \/>\n}<\/p>\n<p>void BaroPressure_MS5534C::ReadCoefficients(void)<br \/>\n{<br \/>\nunsigned int wa = ReadCoefficient(0x15);<br \/>\nunsigned int wb = ReadCoefficient(0x16);<br \/>\ncoefficients_[0] = (unsigned int)((wa &gt;&gt; 1) &amp; (unsigned int)0x7FFF);<br \/>\ncoefficients_[4] = (unsigned int)(((wa &amp; 0x1) &lt;&lt; 10) | ((wb &gt;&gt; 6) &amp; (unsigned int)0x3FF));<br \/>\ncoefficients_[5] = (unsigned int)(wb &amp; 0x3F);<\/p>\n<p>wa = ReadCoefficient(0x19);<br \/>\nwb = ReadCoefficient(0x1A);<br \/>\ncoefficients_[3] = (unsigned int)((wa &gt;&gt; 6) &amp; 0x3FF);<br \/>\ncoefficients_[1] = (unsigned int)(((wa &amp; 0x3F) &lt;&lt; 6) | (wb &amp; 0x3F));<br \/>\ncoefficients_[2] = (unsigned int)((wb &gt;&gt; 6) &amp; 0x3FF);<\/p>\n<p>#ifdef DEBUG<br \/>\n\/\/\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0 for(size_t i=0; i&lt;6; ++i)<br \/>\n\/\/\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0 {<br \/>\n\/\/\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0 Serial.print(&#8220;Coefficient &#8220;);<br \/>\n\/\/\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0 Serial.print(i + 1, DEC);<br \/>\n\/\/\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0 Serial.print(&#8221; : &#8220;);<br \/>\n\/\/\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0 \u00c2\u00a0\u00c2\u00a0\u00c2\u00a0 \u00c2\u00a0\u00c2\u00a0\u00c2\u00a0 Serial.println(coefficients_[i], DEC);<br \/>\n\/\/\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0 }<br \/>\n#endif<br \/>\n}<\/p>\n<p>size_t BaroPressure_MS5534C::ReadCoefficient(unsigned char addr)<br \/>\n{<br \/>\n\/\/ 111 + 6bit coeff addr + 000 + 1clk(send0)<br \/>\nunsigned long cmd = (unsigned long)0x1C00 | (((unsigned long)addr) &lt;&lt; 4);<br \/>\nSendCommand(cmd,13);<br \/>\nreturn ReadWord();<br \/>\n}<\/p>\n<p>\/\/ send command MS bit first<br \/>\nvoid BaroPressure_MS5534C::SendCommand(unsigned long cmd, size_t nbits)<br \/>\n{<br \/>\nwhile(nbits&#8211;)<br \/>\n{<br \/>\nif(cmd &amp; (unsigned long)(1 &lt;&lt; nbits))<br \/>\ndigitalWrite(pinDIN_, HIGH);<br \/>\nelse<br \/>\ndigitalWrite(pinDIN_, LOW);<\/p>\n<p>digitalWrite(pinSCLK_, HIGH);<br \/>\ndigitalWrite(pinSCLK_, LOW);<br \/>\n}<br \/>\n}<\/p>\n<p>unsigned int BaroPressure_MS5534C::ReadWord(void)<br \/>\n{<br \/>\nunsigned int w;<br \/>\nunsigned int clk = 16;<br \/>\nw = 0;<br \/>\nwhile(clk&#8211;)<br \/>\n{<br \/>\ndigitalWrite(pinSCLK_, HIGH);<br \/>\ndigitalWrite(pinSCLK_, LOW);<br \/>\nw |=\u00c2\u00a0 (digitalRead(pinDOUT_) &lt;&lt; clk);<br \/>\n}<br \/>\ndigitalWrite(pinSCLK_, HIGH);<br \/>\ndigitalWrite(pinSCLK_, LOW);<\/p>\n<p>return w;<br \/>\n}<\/p>\n<p>long BaroPressure_MS5534C::AcquireAveragedSampleCm(const size_t nSamples)<br \/>\n{<br \/>\nlong pressAccum = 0;<\/p>\n<p>for(size_t n = nSamples; n; n&#8211;)<br \/>\n{<br \/>\nTriggerTemperatureSample();<br \/>\nwhile(digitalRead(pinDOUT_))<br \/>\n;<br \/>\nconst unsigned int temperature = ReadWord();<br \/>\nTriggerPressureSample();<br \/>\nwhile(digitalRead(pinDOUT_))<br \/>\n;<br \/>\nconst unsigned int pressure = ReadWord(); \/\/ read pressure<br \/>\npressAccum += ConvertPressureTemperature(pressure, temperature);<br \/>\n}<br \/>\nlong pressAvg = pressAccum \/ nSamples;<br \/>\nlong AltCm\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0 = PascalToCentimeter(pressAvg * 10);<\/p>\n<p>return AltCm;<br \/>\n}<\/p>\n<p>long BaroPressure_MS5534C::ConvertPressureTemperature(unsigned int pressure, unsigned int temperature)<br \/>\n{<br \/>\nconst long UT1\u00c2\u00a0 = (coefficients_[4] &lt;&lt; 3) + 20224;<br \/>\nconst long dT\u00c2\u00a0\u00c2\u00a0 = (long)temperature\u00c2\u00a0 &#8211; UT1;<br \/>\nconst long TEMP = 200 + ((dT * (coefficients_[5] + 50)) &gt;&gt; 10);<br \/>\nconst long OFF\u00c2\u00a0 = (coefficients_[1] &lt;&lt;2) + (((coefficients_[3] -512) * dT) &gt;&gt; 12);<br \/>\nconst long SENS = coefficients_[0]\u00c2\u00a0 + ((coefficients_[2] * dT) &gt;&gt; 10)\u00c2\u00a0 + 24576;<br \/>\nconst long X\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0 = ((SENS* ((long)pressure\u00c2\u00a0 &#8211; 7168)) &gt;&gt; 14) &#8211; OFF;<br \/>\npressure\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0 = ((X * 10) &gt;&gt; 5) + 2500;<br \/>\ntemperature = TEMP;<\/p>\n<p>long T2 = 0, P2 = 0;<br \/>\nif(TEMP &lt; 200)<br \/>\n{<br \/>\nT2 = (11 * (coefficients_[5] + 24) * (200 &#8211; TEMP) * (200 &#8211; TEMP)) &gt;&gt; 20;<br \/>\nP2 = (3 * T2 * (pressure &#8211; 3500)) &gt;&gt; 14;<br \/>\npressure\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0 = pressure &#8211; P2;<br \/>\ntemperature = temperature &#8211; T2;<br \/>\n}<\/p>\n<p>return pressure;<br \/>\n}<\/p>\n<p>void BaroPressure_MS5534C::TriggerTemperatureSample(void)<br \/>\n{<br \/>\n\/\/ 111 + 1001 + 000 + 2clks(send 0)<br \/>\nResetSensor();<br \/>\nSendCommand(0xF20, 12);<br \/>\n}<\/p>\n<p>void BaroPressure_MS5534C::TriggerPressureSample(void)<br \/>\n{<br \/>\n\/\/ 111 + 1010 + 000 + 2clks(send 0)<br \/>\nResetSensor();<br \/>\nSendCommand(0xF40, 12);<br \/>\n}<\/p>\n<p>long BaroPressure_MS5534C::PascalToCentimeter(long pressurePa)<br \/>\n{<br \/>\n\/\/ Lookup table converting pressure in Pa to altitude in cm.<br \/>\n\/\/ Each LUT entry is the altitude in cm corresponding to an implicit<br \/>\n\/\/ pressure value, calculated as [PA_INIT &#8211; 1024*index] in Pa.<br \/>\n\/\/ The table is calculated for a nominal sea-level pressure\u00c2\u00a0 = 101325 Pa.<br \/>\nstatic const size_t PZLUT_ENTRIES = 77;<br \/>\nstatic const size_t PA_INIT\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0 = 104908;<br \/>\nstatic const size_t PA_DELTA\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0 = 1024;<\/p>\n<p>static const long lookupTable[PZLUT_ENTRIES] = {<br \/>\n-29408, -21087, -12700,\u00c2\u00a0 -4244,\u00c2\u00a0\u00c2\u00a0 4279,<br \/>\n12874,\u00c2\u00a0 21541,\u00c2\u00a0 30281,\u00c2\u00a0 39095,\u00c2\u00a0 47986,<br \/>\n56953,\u00c2\u00a0 66000,\u00c2\u00a0 75126,\u00c2\u00a0 84335,\u00c2\u00a0 93628,<br \/>\n103006, 112472, 122026, 131672, 141410,<br \/>\n151244, 161174, 171204, 181335, 191570,<br \/>\n201911, 212361, 222922, 233597, 244388,<br \/>\n255300, 266334, 277494, 288782, 300204,<br \/>\n311761, 323457, 335297, 347285, 359424,<br \/>\n371719, 384174, 396795, 409586, 422552,<br \/>\n435700, 449033, 462560, 476285, 490216,<br \/>\n504360, 518724, 533316, 548144, 563216,<br \/>\n578543, 594134, 609999, 626149, 642595,<br \/>\n659352, 676431, 693847, 711615, 729752,<br \/>\n748275, 767202, 786555, 806356, 826627,<br \/>\n847395, 868688, 890537, 912974, 936037,<br \/>\n959766, 984206};<\/p>\n<p>if(pressurePa &gt; PA_INIT)<br \/>\nreturn lookupTable[0];<br \/>\nelse<br \/>\n{<br \/>\nconst long inx = (PA_INIT &#8211; pressurePa) &gt;&gt; 10;<br \/>\nif(inx &gt;= PZLUT_ENTRIES &#8211; 1)<br \/>\nreturn lookupTable[PZLUT_ENTRIES &#8211; 1];<br \/>\nelse<br \/>\n{<br \/>\nconst long pa1 = PA_INIT &#8211; (inx &lt;&lt; 10);<br \/>\nconst long z1 = lookupTable[inx];<br \/>\nconst long z2 = lookupTable[inx+1];<br \/>\nreturn (z1 + (((pa1 &#8211; pressurePa) * (z2 &#8211; z1)) &gt;&gt; 10));<br \/>\n}<br \/>\n}<br \/>\n}<\/p>\n","protected":false},"excerpt":{"rendered":"<p>After receiving personal messages on the arduino forum asking for the code for the Intersema pressure sensor, I paste my code here. It is based on the code from Hari Nair for the open source solar vario that I bought from him.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[6,1],"tags":[19,168],"class_list":["post-10","post","type-post","status-publish","format-standard","hentry","category-projects","category-uncategorized","tag-arduino","tag-paragliding"],"_links":{"self":[{"href":"https:\/\/ulrichard.ch\/blog\/index.php?rest_route=\/wp\/v2\/posts\/10","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ulrichard.ch\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/ulrichard.ch\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/ulrichard.ch\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/ulrichard.ch\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=10"}],"version-history":[{"count":0,"href":"https:\/\/ulrichard.ch\/blog\/index.php?rest_route=\/wp\/v2\/posts\/10\/revisions"}],"wp:attachment":[{"href":"https:\/\/ulrichard.ch\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=10"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/ulrichard.ch\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=10"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/ulrichard.ch\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=10"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}