Sparkfun has more of their BMP085 boards in stock now, if anyone is interested. Makes it nice to breadboard with. With the board, the cost is about the same as the Intersema. Still waiting on mine.
![]()
Sparkfun has more of their BMP085 boards in stock now, if anyone is interested. Makes it nice to breadboard with. With the board, the cost is about the same as the Intersema. Still waiting on mine.
![]()
Last edited by ScaleRobotics; - 24th April 2010 at 02:33.
I've got my BMP085 now, and I'm using a serial LCD and a PIC12F683 to try converse with the sensor initially. I have a problem with i2c comms, and reading the datasheet it mentions 'Restart condition' between starting a conversion (temperature in this case for simplicity to see it changing) and reading the result.
Now I've not come across the 'restart condition' before with i2c chips (just EEPROMS thus far).
Is it done in the PBP i2c statements or does it need to be bit-banged ? Or am I up the whole wrong tree here altogether ?
Cheers all,
MArtin
PBP gives you four choices for ShiftIn and ShiftOut to set the clock idle high/low and whether the shift is MSB or LSB first. This should cover your needs with the exception that PBP does NOT give you much control over the timing of the clock and data lines. There is a DEFINE SHIFT_PAUSEUS nn command but this only delays the clock/data transition at the start of the bit and there is no control over timing at the end of the bit.
Cable length, cloick & data slew speed and any ringing on the clock and data lines can give bulk grief that takes days to find. Been there done that.
I found with the intersems sensors that the potted PBP ShiftIn/Out routines would only drive about 300 mm of ribbon cable but my hand written bit bang method let me run over a metre of cable.
Intersema is not the same as the Bosch interface. DIn, DOut and SClk vs SDA and SCL but otherwise the chips are very similar so the same sort of code structure ought to work.
Here is how I do it.
HTHCode:OutShift: for fa = 1 to clockbits 'Don't forget OutShift adds an extra clock bit at the end. din = (1 & iword) 'select lowest bit via AND mask pauseus 4 'want minimum - about 4 uS or so sclk = 4 : pauseus 4 : sclk = 0 iword = iword >> 1 'get next LSB, clock out zeros after 16 bits next fa sclk = 1 : pauseus 4 : sclk = 0 'this is the extra clock per DA5541B_00513 datasheet page 13 return ResetIntersema: ' resets ALL pressure sensors ' shiftout din, sclk, 0, [85, 85, 0\5] ' Sense of Din is IN to 5541 output din : output sclk clockbits = 20 : iword = %0101010101010101 '16 bit data word gosub outshift return ConvertDelay: ' specific to each sensor if tank = 0 then While dout0 = 1 wend endif if tank = 1 then While dout1 = 1 wend endif if tank = 2 then While dout2 = 1 wend endif return FetchWord: ' read specific channel reply. Different pins for DOut0,1,2 input dout0 : input dout1 : input dout2 : output sclk : iword = 0 if tank = 0 then for fa = 15 to 0 step -1 'need 17 clock bits so add one at end sclk = 1 : pauseus 4 'wait for Intersema to present next bit iword.0[fa] = dout0 'read the bit on selected channel sclk = 0 'drop clock next fa 'do it 16 times endif if tank = 1 then for fa = 15 to 0 step -1 'need 17 clock bits so add one at end sclk = 1 : pauseus 1 'wait for Intersema to present next bit iword.0[fa] = dout1 'read the bit sclk = 0 'drop clock next fa 'do it 16 times endif if tank = 2 then for fa = 15 to 0 step -1 'need 17 clock bits so add one at end sclk = 1 : pauseus 1 'wait for Intersema to present next bit iword.0[fa] = dout2 'read the bit sclk = 0 'drop clock next fa 'do it 16 times endif sclk = 1 : pauseus 1 : sclk = 0 ' 17th clock bit ii = iword.byte0 : ij = iword.byte1 return ReadFactoryCal: ' This unpacks the factory calibration coefficients from the just ' read W1 ~ W4. ' These bitmaps are unpacked into the 6 working coefficients ' C1 to C6 which are then stored in EEROM for later use. 'W1 gosub resetintersema ' shiftout din, sclk, 0, [87, 1\5] ' Send W1 pattern to all sensors clockbits = 12 : iword = %000101010111 'request W1 pattern gosub outshift gosub fetchword ' recall selected Tank reply W1.byte0 = ii W1.byte1 = ij if (w1 = 0) or (w1 = 65535) then debug "W1 error", 13, 10 goto readfactorycal endif 'W2 gosub resetintersema ' shiftout din, sclk, 0, [215, 0\5] ' Send W2 pattern clockbits = 12 : iword = %000011010111 gosub outshift gosub fetchword W2.byte0 = ii W2.byte1 = ij if (w2 = 0) or (w2 = 65535) then debug "W2 error", 13, 10 goto readfactorycal endif 'W3 gosub resetintersema ' shiftout din, sclk, 0, [55, 1\5] ' Send W3 pattern clockbits = 12 : iword = %000100110111 gosub outshift gosub fetchword W3.byte0 = ii W3.byte1 = ij if (w3 = 0) or (w3 = 65535) then debug "W3 error", 13, 10 goto readfactorycal endif 'W4 gosub resetintersema ' shiftout din, sclk, 0, [183, 0\5] ' Send W4 pattern clockbits = 12 : iword = %000010110111 gosub outshift gosub fetchword W4.byte0 = ii W4.byte1 = ij if (w4 = 0) or (w4 = 65535) then debug "W4 error", 13, 10 goto readfactorycal endif CalcCoefficients: ' this serves all three sensors. 'C1 C1 = W1 >> 3 'unpack coefficient read (108 + tank*20), z.byte0 'store read (109 + tank*20), z.byte1 if z<>c1 then write (108 + tank*20), c1.byte0 'store write (109 + tank*20), c1.byte1 endif 'C2 C2 = ((W1 & %0000000000000111) << 10) + (W2 >> 6) read (110 + tank*20), z.byte0 read (111 + tank*20), z.byte1 if z<>c2 then write (110 + tank*20), c2.byte0 write (111 + tank*20), c2.byte1 endif 'C3 C3 = W3 >> 6 read (112 + tank*20), z.byte0 read (113 + tank*20), z.byte1 if z<>c3 then write (112 + tank*20), c3.byte0 write (113 + tank*20), c3.byte1 endif 'C4 C4 = W4 >> 7 read (114 + tank*20), z.byte0 read (115 + tank*20), z.byte1 if z<>c4 then write (114 + tank*20), c4.byte0 write (115 + tank*20), c4.byte1 endif 'C5 C5 = ((W2 & %0000000000111111) << 6) + (W3 & %0000000000111111) read (116 + tank*20), z.byte0 read (116 + tank*20), z.byte0 if z<>c5 then write (117 + tank*20), c5.byte1 write (117 + tank*20), c5.byte1 endif 'C6 C6 = W4 & %0000000001111111 read (118 + tank*20), z if z<>c6 then write (118 + tank*20), c6 endif Show5541Coefficients: 'only used during diagnostics ' high txd : pause 1 ' debug 13, 10, "Tank #", #tank, ", W1 = ", #w1, ", W2 = ",_ ' #w2, ", W3 = ", #w3, ", W4 = ", #w4, 13, 10 ' debug "Derived coeffs C1 = ", #C1, ", C2 = ", #C2, ", C3 = ",_ ' #C3, ", C4 = ", #c4, ", C5 = ", #C5, ", C6 = ", #C6, 13, 10 return
BrianT
Thanks Brian,
I'm not sure quite what to say though. I'm sure the tip I need is in the reply, but most of the answer went over my head.
I've not used shiftin/shiftout of anything in PBP so I'd rather get the i2c commands to work for me (if it's possible).
The sensor is 20mm from the PIC, so I'm hoping distance related issues should not be a problem. I'll just have a quiet little play with the i2c commands and see if I can get some sense out of it with that for now :-)
Thanks,
Martin
OK, got comms up. I can read the temperature sensor fine now. The issue was HW not SW this time.
Martin
Well I've spent a few hours working on this over the weekend, and I've made good progress (for me) with communicating with the sensor. I have a PIC Serial LCD (20x4) attached to a PIC12F683, which has the BMP085 attached to GPIO.0 (clock) and GPIO.1(data).
So far I can see the inbuilt temperature sensor value changing when I put a warm finger on the sensor, and also read out the eleven 16bit calibration parameters and display them (I think).
I'm worried about two things.
One is if I have the MSB and LSB of the calibration data in the right order when I'm storing them and then again using them. I not convinced the numbers look right on the LCD. The PBP manual I find confuses me somewhat when they talk about storing the LSB first in a word sized array of the i2c device (i2cread command description).
The second is converting this math to PBP, given that the values of some seem to be signed and results of some operations are going to be 32bit size (unless I don't understand it at all, which is possible).
To convert the raw temperature result UT to Deg C (T) is
X1 = (UT - AC6) * AC5 / 2^15
X2 = MC * 2^11 / (X1 + MD)
B5 = X1 + X2
T = (B5 + 8) / 2^4
I'd love some help with some code to show how this can be done in PBP.
Anybody ?
Cheers,
Martin
Code:'PIC 12F683 port/pin allocations '------------------------------- 'GPIO.0/Pin 7 = I2C SCL clock 'GPIO.1/Pin 6 = I2C SDA data 'GPIO.2/Pin 5 = spare 'GPIO.3/Pin 4 = spare 'GPIO.4/Pin 3 = LED 'GPIO.5/Pin 2 = Serial TX '----------------------- ' PIC Defines ' =========== 'Config bits set to INTERNAL OSC, Watch dog ON, Power up timer ON, Master Clear NOT used, BrownOut protection ON, @ Device pic12f683, intrc_osc, wdt_on, pwrt_on, mclr_off, bod_on ;Config switches, different from PBP default '@ __Config _INTRC_OSC_NOCLKOUT & _WDT_OFF & _PWRTE_ON & _MCLRE_OFF ;USING MPASM ONLY Define Osc 4 '4Mhz clock used. Note - Set PIC config fuses on programmer to use Internal RC OSC Include "modedefs.bas" ' Include serial modes ' Define some constants if needed ' Software Defines Cal_table var word[11] '11 word array to store calibration data Temp_Var var byte 'temp variable Temp_Var2 var Word 'temp variable i2c_Reg var Byte 'variable for target i2c register address CPIN var GPIO.0 ' I2C clock pin DPIN var GPIO.1 ' I2C data pin SO Var GPIO.5 'Serial out pin LED var GPIO.4 'Indicator LED, via 500ohm to +3.3V 'Alias's for calibration data in the sensor to match the Bosch paramater list names AC1 var Cal_table[0] ' AC2 var Cal_table[1] 'BMP085 has 11 16bit values stored in EEPROM AC3 var Cal_table[2] 'First byte is at $AA last at $BF AC4 var Cal_table[3] 'Lowbyte is MSB, Highbyte is LSB AC5 var Cal_table[4] 'some values are signed (not AC4, AC5, AC6) AC6 var Cal_table[5] B1 var Cal_table[6] B2 var Cal_table[7] MB var Cal_table[8] MC var Cal_table[9] MD var Cal_table[10] ' Initialise Processor - check for each PIC type either 12F629 or 12F675 ' -------------------- VRCON.7 = %0 'Comparator voltage reference OFF CMCON0 = %111 'Comparator inputs to OFF, all pins normal I/O ANSEL = 0 'Turn off al AD's rem out for PIC12F629, use for PIC12F675 ' Set initial state of GPIO port pins as Input or Output TRISIO.0 = 0 'Input(0 = output, 1 = Input) TRISIO.1 = 0 ' TRISIO.2 = 1 ' TRISIO.3 = 0 ' TRISIO.4 = 0 ' TRISIO.5 = 1 ' ' PIC initialization code Low LED 'LED on pause 500 High LED 'LED off Serout SO,N2400,[$FE,$01] ' Clear LCD & home LCD cursor. pause 10 ' wait for LCD to catch up Serout SO,N2400,[" FrSky Vario "] ' Serial print Serout SO,N2400,[$FE,$C0] ' Shift cursor to line2 Serout SO,N2400,[" development jig "] ' Serial print Pause 3000 i2c_Reg =$AA 'Start address of calibration data I2CREAD DPIN,CPIN,$EF,I2C_REG,[STR Cal_table\11],read_error1 'Read 11 words out of sensor Serout SO,N2400,[$FE,$01] ' Clear LCD & home LCD cursor. Pause 10 ' wait for LCD to catch up Main: Serout SO,N2400,[$FE,$02] 'home LCD cursor. i2c_Reg = $F4 '$F4 is the control register address I2CWRITE DPIN,CPIN,$EE,I2C_REG,[$2E] ' Write $2E to set temperature conversion Pause 10 ' Delay 10ms after each write i2c_Reg = $F6 '$F6 is the result register MSB I2CREAD DPIN,CPIN,$EF,I2C_REG,[Temp_Var2],read_error 'Read temperature MSB, LSB. Serout SO,N2400,[#Temp_Var2," "] 'Send Word size number to LCD 'lets see whats in the cal data array for a checking math Serout SO,N2400,[$FE,$C0] ' Shift cursor to line2 Serout SO,N2400,[#AC1," ",#AC2," ",#AC3] Serout SO,N2400,[$FE,$94] ' Shift cursor to line3 Serout SO,N2400,[#AC4," ",#AC5," ",#AC6] Serout SO,N2400,[$FE,$D4] Serout SO,N2400,[#B1," ",#B2," ",#MB] ' ," ",#MC," ",#MD] ' pause 1000 Toggle LED Goto main Read_error: Serout SO,N2400,[$FE,$01] ' Clear LCD & home LCD cursor. Pause 10 ' wait for LCD to catch up Serout SO,N2400,["i2c bus read error"] ' pause 250 Toggle LED Goto main Read_error1: Serout SO,N2400,[$FE,$01] ' Clear LCD & home LCD cursor. Pause 10 Serout SO,N2400,["i2c cal read error "] ' End
Real values.
If there happens to be a mathematician amongst us that likes puzzles like the one above, I have the raw values (as decimal) read out of my sensor to plug into the temperature equations as a test. The result should be around 21C.
UT = 30814
AC5 = 22882
AC6 = 1368
MC = 48596
MD = 32777
Bookmarks