SHIFTIN SHIFTOUT timing problem
Does anyone know how to lengthen (slow down) the LOW period of the SHIFT clock?
The statement
Code:
DEFINE SHIFT_PAUSEUS 2
extends the HIGH period of the shift clock to about 10 uS but the LOW period remains fixed at about 2 uS. I need to retain something close to a 50:50 duty cycle but at a lower speed with about 10 uS HIGH and 10 uS LOW.
Cheers
Brian
bit banging for less than 8 bits
Thanks for that Steve.
I had considered the bit bang approach and had found the BS2 routines on the Melabs site. I am using the Intersema pressure transducer which needs the SHIFTOUT value\bits option to clock out some 2 and 3 bit values as well as regular 8 bit bytes. I guess I'll just have to bite the bullet and dive into the assembler. The lazy option is not going to cut it.
Cheers
Brian
bit banging the Intersema sensor
I could not make the PBP ShiftIn or ShiftOut routines work reliably with the latest Intersema MS5541C although the same code had worked a treat for several years. Intersema must have made some internal changes, one at least to reduce power consumption when MClk stops, or maybe meLabs has tweaked some code.
Intersema show DIn must be stable before SClk goes high. ShiftOut in PBP shows this as Mode 0. In the direction from Intersema to PIC, ShiftIn mode 2 should get the sense and timing right according to the PBP and Intersema waveform sketches. The problem seems to be that neither Intersema nor PBP specifies the setup time between data change and clock strobe. On an oscilloscope the clock follows data by a few hundred of nanoseconds which ought to be enough but I get many bad reads with the potted ShiftIn and ShiftOut routines.
I hand coded the 7 commands from PIC to Intersema and the single reply code from Intersema to PIC. The code is none too elegant but it now works 100% every time. Previously I was getting about 75% mis-reads of pressure data and some DA5541C chips would not work at all.
Code:
OutShift:
for fa = 1 to clockbits 'OutShift adds an extra bit at the end
din = (1 & iword) 'select lowest bit &
pauseus 1 'will actually be 4 uS or so
sclk = 1 : pauseus 1 : sclk = 0
iword = iword >> 1 'get next LSB, clock out zeros after 16 bits
next fa
sclk = 1 : pauseus 1 : sclk = 0 'extra clock per DA5541B_00513 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
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 1 '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
ReadTank: ' D1 is Pressure - D2 is Temperature. Same code for all 3.
'MUST know Tank# before calling this routine.
'D1
gosub resetintersema
' shiftout din, sclk, 0, [47, 0\5] ' Select D1 pattern
clockbits = 11 : iword = %00000101111
gosub outshift
gosub convertdelay
gosub fetchword
d1.byte0 = ii
d1.byte1 = ij
if (d1 = 0) or (d1 = 65535) then
debug "D1 error", 13, 10
goto readtank
endif
'D2
gosub resetintersema
'shiftout din, sclk, 0, [79, 0\5] ' Select D2 pattern
clockbits = 11 : iword = %00001001111
gosub outshift
gosub convertdelay
gosub fetchword
D2.byte0 = ii
D2.byte1 = ij
if (d2 = 0) or (d2 = 65535) then
debug "Tank ", #tank, ", D2 error", 13, 10
goto readtank
endif
CalcTempPress:
read (108 + tank*20), c1.byte0
read (109 + tank*20), c1.byte1
read (110 + tank*20), c2.byte0
read (111 + tank*20), c2.byte1
read (112 + tank*20), c3.byte0
read (113 + tank*20), c3.byte1
read (114 + tank*20), c4.byte0
read (115 + tank*20), c4.byte1
read (116 + tank*20), c5.byte0
read (117 + tank*20), c5.byte1
read (118 + tank*20), c6
ut1 = 8*c5 + 10000
dt = d2 - ut1
if dt < 0 then
dt2 = dt - (dt*dt)/(128*64)
else
dt2 = dt - (dt*dt)/(128*16)
endif
' tanktemp = 200 + (dt*(c6+100))/2048 'simpler form, less accurate??
tanktemp = 200 + dt2*(c6 + 100)/2048
offset = c2 + ((c4 - 250)*dt)/4096 + 10000
senstvty = c1/2 + ((c3 + 200)*dt)/8192 + 3000
tankpress = (senstvty*(d1 - offset))/4096 + 1000
BoundsCheck:
if (tankpress > 8000) or (tankpress < 700) then
debug 13, 10, "Bounds error. Tank = ",#tank, ", TankPress = ", _
#tankpress," mB", 13, 10
goto readtank 'retry until value is within bounds
endif
if tank = 0 then
t0pressure = tankpress
t0celsius = tanktemp
' debug "T0 D1, D2 = ", dec d1,", ", dec d2, ", T0 Pressure = ", dec t0pressure, ", Temp ", dec t0celsius, 13, 10
endif
if tank = 1 then
t1pressure = tankpress
t1celsius = tanktemp
' debug "T1 D1, D2 = ", dec d1,", ", dec d2, ", T1 Pressure = ", dec t1pressure, ", Temp ", dec t1celsius, 13, 10
endif
if tank = 2 then
t2pressure = tankpress
t2celsius = tanktemp
' debug "T2 D1, D2 = ", dec d1,", ", dec d2, ", T2 Pressure = ", dec t2pressure, ", Temp ", dec t2celsius, 13, 10
endif
return
The minimum pauseus is 4 uS so there is now plenty of time for the data to stabilise before the clock strobe.
The Intersema pressure sensors are spectacular little temperature and pressure sensors and up until some recent changes have served me very well. With this new code, the conversion takes about 1 mS longer and the code is slightly bigger but I am now in control of the read & write process.
I hope someone finds this useful.
Cheers
BrianT
Intersema pressure sensors
Hi Steve,
I use the MS5540 1 bar sansor for reading atmospheric pressure in a sample chamber where I must know the oxygen partial pressure very accurately. I also use this sensor for altitude in bird migration studies.
I use several MS5541 14 bar sensors in a gas mixer where I can mix O2, CO2 and N2 to 0.1 mB precision. I also use these in archival dataloggers which are surgically implanted in salmon, tuna, kingfish and penguins for physiological studies of aquaculture species.
Cheers
Brian
Re: SHIFTIN SHIFTOUT timing problem
Hi All!
I am very new to all of this and trying to learn and study what and how those of you who know this very well are doing. Is there any chance I could see the whole program/code for the MS5541 for a single unit? It would be very much appreciated.
Thanks, Ed
Re: SHIFTIN SHIFTOUT timing problem
Thanks Brian! :)
Yes I noticed that depending upon the PIC there is only one pin marked as CCP2. My guess is that by using HPWM the PIC knows to use this pin and it still must have a hardware definition? MCLK is shown as a comment so it has been confusing to know what to do for the hardware defines. Another thing I did not understand is why use CCP2 and not CCP1?
For 3.3 v to 5.0 v conversion (bi-directional) a device that does this known as the ADG3304 if this is of value. The device can also be used for other voltage level changes.
Variations in atmospheric pressure causes the zero reference point (the surface of the water) to change so to maintain accuracy a simple water detector (two transistors) could be used to set the zero reference (surface) point.
Thanks for answering and hope I have made some small contribution to you and others.
Ed
A little help with understand the code in this post Please
A little help please.
high presspwr ' there is no pin defined as presspwr
temp2 = 1000 - celsius ' there is no variable named temp2
d[17] = temp2.byte0
d[18] = temp2.byte1 ' There is no array named d.
high pgc ' there is no pin defined as pgc
gosub shutdownmemory ' there is no sub-routine with this name
gosub lowestpower ' there is no sub-routine with this name either end '
I do not wish it to stop or end just continue to get int information.
Thanks, Ed
Re: SHIFTIN SHIFTOUT timing problem
Quote:
high presspwr ' there is no pin defined as presspwr
If that is so, then pick one and make it so, some thing like
Code:
presspwr var PortA.0
Quote:
temp2 = 1000 - celsius ' there is no variable named temp2
Code:
temp2 var word 'a byte only holds 0-255
Quote:
d[17] = temp2.byte0
d[18] = temp2.byte1 ' There is no array named d.
assigns value to 2 bytes in array, set up array,
Quote:
high pgc ' there is no pin defined as pgc
again make a pin do this by assigning it to that duty
Code:
pgc var PortA.1 ' or some other unused pin
Quote:
gosub shutdownmemory ' there is no sub-routine with this name
Make a sub directory or remove the call to it and send the code elsewhere using
goto or gosub as appropriate.
gosub lowestpower ' there is no sub-routine with this name either end '
Quote:
I do not wish it to stop or end just continue to get int information.
same answer as above. this is the disadvantage to using code you did not write, you are forced into the position of clairvoyant as you try to imaging what the programmer envisioned.
Probably the best argument for chewing through someone else's code is to learn from it, the cost is the frustration of trying to understand it.
I hope you found something useful in my rant,
JS