|
Forum Index : Microcontroller and PC projects : Sensor MM code examples
| Author | Message | ||||
| lew247 Guru Joined: 23/12/2015 Location: United KingdomPosts: 1702 |
Following on from the thread about all the program examples for the cmm2 I thought why not have a thread with examples of code for various modules that are or can be used by any of the MM family? I'm looking for code for the following modules if anyone has any example codes Here's some codes to start off with, hopefully others will keep this going and it doesn't die as it will be handy to many newcomers and possibly older members also BME280 Temp & Humidity sensor '****************************************************** '* BME280 routine * '* Thanks to matherp * '****************************************************** option explicit option default none ' BME280 routines and test harness ' const BME280_ADDRESS = &H77 const BME280_REGISTER_T1 = &H88 const BME280_REGISTER_P1 = &H8E const BME280_REGISTER_H1 = &HA1 const BME280_REGISTER_H2 = &HE1 const BME280_REGISTER_CHIPID = &HD0 const BME280_REGISTER_CONTROLHUMID = &HF2 const BME280_REGISTER_CONTROL = &HF4 const BME280_REGISTER_PRESSUREDATA = &HF7 const BME280_REGISTER_TEMPDATA = &HFA const BME280_REGISTER_HUMIDDATA = &HFD ' dim integer s16=&HFFFFFFFFFFFF0000 , s16b=&H8000 dim integer s12=&HFFFFFFFFFFFFF000 , s12b=&H800 dim integer s8= &HFFFFFFFFFFFFFF00 , s8b=&H80 ' DIM INTEGER T1,T2,T3 'uint16_t, int16_t, int16_t DIM INTEGER P1,P2,P3,P4,P5,P6,P7,P8,P9 'uint16_t, 8 x int16_t DIM INTEGER H1,H2,H3,H4,H5,H6 'uint8_t, int16_t , uint8_t, int16_t, int16_t, int8_t ' dim INTEGER t_fine 'used to store accurate temp reading from temp conversion for use in pressure and humidity conversions ' ' Test program ' bme280_init do print bme280_read_temp()"C" bme280_read_pressure()"mB" bme280_read_humidity()"% Humidity" 'Temp must be run before pressure or humidity pause 500 print Altitude " " pause 3000 loop ' end ' '*************************************************************************************************** ' function bme280_read_temp() as float local integer var1,var2,adc_T local adc%(2) i2c write BME280_ADDRESS,1,1,BME280_REGISTER_TEMPDATA i2c read BME280_ADDRESS,0,3,adc%() adc_T=((adc%(0)<<16) OR (adc%(1)<<8) or adc%(2))>>4 var1 = ((((adc_T>>3) - (T1 <<1))) * T2) \ q(11) var2 = (((((adc_T>>4) - (T1)) * ((adc_T\ q(4)) - (T1))) \ q(12)) * (T3)) \ q(14) t_fine = var1 + var2 bme280_read_temp = ((t_fine * 5 + 128) \ q(8))/100.0 end function function bme280_read_pressure() as float local integer var1, var2, adc_P, p local adc%(2) i2c write BME280_ADDRESS,1,1,BME280_REGISTER_PRESSUREDATA i2c read BME280_ADDRESS,0,3,adc%() adc_P=((adc%(0)<<16) OR (adc%(1)<<8) or adc%(2))>>4 var1 = t_fine - 128000 var2 = var1 * var1 * P6 var2 = var2 + ((var1 * P5)<<17) var2 = var2 + (P4 << 35) var1 = ((var1 * var1 * P3)\ q(8)) + ((var1 * P2)<<12) var1 = ((1<<47)+var1)*P1\ q(33) if var1 = 0 THEN bme280_read_pressure = 0' avoid exception caused by division by zero exit function endif p = 1048576 - adc_P p = (((p<<31) - var2)*3125) \ var1 var1 = (P9 * (p\ q(13)) * (p\ q(13))) \ q(25) var2 = (P8 * p) \ q(19) p = ((p + var1 + var2) \ q(8)) + (P7<<4) bme280_read_pressure = p/25600.0 end function ' function bme280_read_humidity() as float local integer v_x1,adc_H local adc%(1) i2c write BME280_ADDRESS,1,1,BME280_REGISTER_HUMIDDATA i2c read BME280_ADDRESS,0,2,adc%() adc_H=(adc%(0)<<8) or adc%(1) v_x1 = t_fine - 76800 v_x1=(((((adc_H<<14)-((H4)<<20)-(H5*v_x1))+16384)\ q(15))*(((((((v_x1*H6)\ q(10))*(((v_x1*H3)\ q(11))+32768))\ q(10))+2097152)*H2+8192)\ q(14))) v_x1 = (v_x1 - (((((v_x1 \ q(15)) * (v_x1 \ q(15))) \ q(7)) * (H1)) \ q(4))) if v_x1< 0 then v_x1 = 0 if v_x1 > 419430400 then v_x1= 419430400 bme280_read_humidity = (v_x1\ q(12)) / 1024.0 end function sub bme280_init local i%,cal%(17) i2c open 400,1000 '400KHz bus speed i2c write BME280_ADDRESS,1,1,BME280_REGISTER_CHIPID i2c read BME280_ADDRESS,0,1,i% if i%<>&H60 then print "Error BME280 not found" ' i2c write BME280_ADDRESS,1,1,BME280_REGISTER_T1 i2c read BME280_ADDRESS,0,6,cal%() T1=cal%(0) OR (cal%(1)<< 8) T2=cal%(2) OR (cal%(3)<< 8): if T2 and s16b then T2=T2 OR s16 'sign extend if required T3=cal%(4) OR (cal%(5)<< 8): if T3 and s16b then T3=T3 OR s16 ' i2c write BME280_ADDRESS,1,1,BME280_REGISTER_P1 i2c read BME280_ADDRESS,0,18,cal%() P1=cal%(0) OR (cal%(1)<<8) P2=cal%(2) OR (cal%(3)<<8): if P2 and s16b then P2=P2 OR s16 'sign extend if required P3=cal%(4) OR (cal%(5)<<8): if P3 and s16b then P3=P3 OR s16 P4=cal%(6) OR (cal%(7)<<8): if P4 and s16b then P4=P4 OR s16 P5=cal%(8) OR (cal%(9)<<8): if P5 and s16b then P5=P5 OR s16 P6=cal%(10) OR (cal%(11)<<8): if P6 and s16b then P6=P6 OR s16 P7=cal%(12) OR (cal%(13)<<8): if P7 and s16b then P7=P7 OR s16 P8=cal%(14) OR (cal%(15)<<8): if P8 and s16b then P8=P8 OR s16 P9=cal%(16) OR (cal%(17)<<8): if P9 and s16b then P9=P9 OR s16 ' i2c write BME280_ADDRESS,1,1,BME280_REGISTER_H1 i2c read BME280_ADDRESS,0,1,H1 i2c write BME280_ADDRESS,1,1,BME280_REGISTER_H2 i2c read BME280_ADDRESS,0,7,cal%() H2=cal%(0) OR (cal%(1)<< 8): if H2 and s16b then H2=H2 OR s16 'sign extend if required H3=cal%(2) H6=cal%(6): if H6 and s8b then H6=H6 OR s8 'sign extend if required H4=(cal%(3)<<4) OR (cal%(4) and &H0F): if H4 and s12b then H4=H4 OR s12 'sign extend if required H5=(cal%(5)<<4) OR (cal%(4)>>4): if H5 and s12b then H5=H5 OR s12 ' i2c write BME280_ADDRESS,0,2,BME280_REGISTER_CONTROLHUMID,&H05 '16x oversampling humidity i2c write BME280_ADDRESS,0,2,BME280_REGISTER_CONTROL,&HB7 '16x oversampling pressure/temp, normal mode ' end sub ' function q(x as integer) as integer 'returns 2 raised to the power q=(1<<x) End Function Altitude = 44330*(1-(BME280_read_humidity()/101325)^(1/5.255)) TSL2561 Lux Code option explicit Sorry not sure who to give full credit to for that oneoption default none const intpin = 12 'connect to the INT pin on the TLS2561 const TLSaddr=&B0111001 'Floating, GND is &B0101001, VCC is &B1001001 const TLScontrol = &H00 const TLStiming = &H01 const TLSINTERRUPT = &H06 const TLSCRC = &H08 const TLSID = &H0A const TLSDATA0LOW = &H0C const TLSDATA0HIGH = &H0D const TLSDATA1LOW = &H0E const TLSDATA1HIGH = &H0F const TLSCMD = &H80 const TLSCLEAR = &H40 const TLSPOWER = &H03 const TLSLOWGAIN = &H00 const TLSHIGHGAIN = &H10 CONST TLSINTEG402 = &H02 dim integer C1datalow,C1datahigh,C0datalow,C0datahigh,useresult=1 dim float CH1,CH0,lux,gain=0.0625 i2c open 400,1000 'device will run at full speed i2c write TLSaddr,0,2,TLSCMD OR TLScontrol,TLSPOWER ' turn on the device i2c write TLSaddr,0,2,TLSCMD OR TLStiming,TLSINTEG402 OR TLSLOWGAIN 'set output every 402msec, gain = 1 setpin intpin,intl,TLS2561int,PULLUP i2c write TLSaddr,0,2,TLSCMD OR TLSCLEAR OR TLSINTERRUPT,&H10 ' enable interrupts every ADC conversion ' do pause 1000 loop ' sub TLS2561int i2c write TLSaddr,1,1,TLSCMD OR TLSDATA0LOW i2c read TLSaddr,0,1,C0datalow i2c write TLSaddr,1,1,TLSCMD OR TLSDATA0HIGH i2c read TLSaddr,0,1,C0datahigh CH0=(C0datahigh*256 + C0datalow)/gain i2c write TLSaddr,1,1,TLSCMD OR TLSDATA1LOW i2c read TLSaddr,0,1,C1datalow i2c write TLSaddr,1,1,TLSCMD OR TLSDATA1HIGH i2c read TLSaddr,0,1,C1datahigh CH1=(C1datahigh*256 + C1datalow)/gain i2c write TLSaddr,0,2,TLSCMD OR TLSCLEAR OR TLScontrol,TLSPOWER 'clear the interrupt if CH0*gain < 500 and gain = 0.0625 then 'switch to low light i2c write TLSaddr,0,2,TLSCMD OR TLStiming,TLSINTEG402 OR TLSHIGHGAIN 'switch to high gain useresult=0 gain=1.0 Print "Switching to high gain" elseif CH0*gain > 10000 and gain = 1.0 then 'switch to normal light i2c write TLSaddr,0,2,TLSCMD OR TLStiming,TLSINTEG402 OR TLSLOWGAIN 'switch to high gain useresult=0 gain=0.0625 Print "Switching to low gain" else select case CH1/CH0 'normal processing case IS > 0,<=0.5 lux = 0.0304 * CH0 - 0.062 * CH1 * ((CH1/CH0)^1.4) case IS >0.5,<=0.61 lux = 0.0224 * CH0 - 0.031 * CH1 case IS >0.61, <=0.8 lux = 0.0128 * CH0 - 0.0153 * CH1 case IS >0.8, <=1.3 lux = 0.00146 * CH0 - 0.00112 * CH1 case else lux = 0 end select if useresult then 'skip the first result after gain change print "ADC count visible + IR=",CH0; print " ADC count IR only=",CH1; print " converts to ",lux," Lux" else useresult=1 'enable for next time endif endif end sub SI1145 LUX Sensor '*** Thanks to Matherp*** option explicit option default NONE '/* COMMANDS */ const SI1145_PARAM_QUERY = &H80 const SI1145_PARAM_SET = &HA0 const SI1145_NOP = &H0 const SI1145_RESET = &H01 const SI1145_BUSADDR = &H02 const SI1145_PS_FORCE = &H05 const SI1145_ALS_FORCE = &H06 const SI1145_PSALS_FORCE = &H07 const SI1145_PS_PAUSE = &H09 const SI1145_ALS_PAUSE = &H0A const SI1145_PSALS_PAUSE = &HB const SI1145_PS_AUTO = &H0D const SI1145_ALS_AUTO = &H0E const SI1145_PSALS_AUTO = &H0F const SI1145_GET_CAL = &H12 '/* Parameters */ const SI1145_PARAM_I2CADDR = &H00 const SI1145_PARAM_CHLIST = &H01 const SI1145_PARAM_CHLIST_ENUV = &H80 const SI1145_PARAM_CHLIST_ENAUX = &H40 const SI1145_PARAM_CHLIST_ENALSIR = &H20 const SI1145_PARAM_CHLIST_ENALSVIS = &H10 const SI1145_PARAM_CHLIST_ENPS1 = &H01 const SI1145_PARAM_CHLIST_ENPS2 = &H02 const SI1145_PARAM_CHLIST_ENPS3 = &H04 const SI1145_PARAM_PSLED12SEL = &H02 const SI1145_PARAM_PSLED12SEL_PS2NONE = &H00 const SI1145_PARAM_PSLED12SEL_PS2LED1 = &H10 const SI1145_PARAM_PSLED12SEL_PS2LED2 = &H20 const SI1145_PARAM_PSLED12SEL_PS2LED3 = &H40 const SI1145_PARAM_PSLED12SEL_PS1NONE = &H00 const SI1145_PARAM_PSLED12SEL_PS1LED1 = &H01 const SI1145_PARAM_PSLED12SEL_PS1LED2 = &H02 const SI1145_PARAM_PSLED12SEL_PS1LED3 = &H04 const SI1145_PARAM_PSLED3SEL = &H03 const SI1145_PARAM_PSENCODE = &H05 const SI1145_PARAM_ALSENCODE = &H06 const SI1145_PARAM_PS1ADCMUX = &H07 const SI1145_PARAM_PS2ADCMUX = &H08 const SI1145_PARAM_PS3ADCMUX = &H09 const SI1145_PARAM_PSADCOUNTER = &H0A const SI1145_PARAM_PSADCGAIN = &H0B const SI1145_PARAM_PSADCMISC = &H0C const SI1145_PARAM_PSADCMISC_RANGE = &H20 const SI1145_PARAM_PSADCMISC_PSMODE = &H04 const SI1145_PARAM_ALSIRADCMUX = &H0E const SI1145_PARAM_AUXADCMUX = &H0F const SI1145_PARAM_ALSVISADCOUNTER = &H10 const SI1145_PARAM_ALSVISADCGAIN = &H11 const SI1145_PARAM_ALSVISADCMISC = &H12 const SI1145_PARAM_ALSVISADCMISC_VRNG = &H20 const SI1145_PARAM_ALSIRADCOUNTER = &H1D const SI1145_PARAM_ALSIRADCGAIN = &H1E const SI1145_PARAM_ALSIRADCMISC = &H1F const SI1145_PARAM_ALSIRADCMISC_RANGE = &H20 const SI1145_PARAM_ADCCOUNTER_511CLK = &H70 const SI1145_PARAM_ADCMUX_SMALLIR = &H00 const SI1145_PARAM_ADCMUX_LARGEIR = &H03 '/* REGISTERS */ const SI1145_REG_PARTID = &H00 const SI1145_REG_REVID = &H01 const SI1145_REG_SEQID = &H02 const SI1145_REG_INTCFG = &H03 const SI1145_REG_INTCFG_INTOE = &H01 const SI1145_REG_INTCFG_INTMODE = &H02 const SI1145_REG_IRQEN = &H04 const SI1145_REG_IRQEN_ALSEVERYSAMPLE = &H01 const SI1145_REG_IRQEN_PS1EVERYSAMPLE = &H04 const SI1145_REG_IRQEN_PS2EVERYSAMPLE = &H08 const SI1145_REG_IRQEN_PS3EVERYSAMPLE = &H10 const SI1145_REG_IRQMODE1 = &H05 const SI1145_REG_IRQMODE2 = &H06 const SI1145_REG_HWKEY = &H07 const SI1145_REG_MEASRATE0 = &H08 const SI1145_REG_MEASRATE1 = &H09 const SI1145_REG_PSRATE = &H0A const SI1145_REG_PSLED21 = &H0F const SI1145_REG_PSLED3 = &H10 const SI1145_REG_UCOEFF0 = &H13 const SI1145_REG_UCOEFF1 = &H14 const SI1145_REG_UCOEFF2 = &H15 const SI1145_REG_UCOEFF3 = &H16 const SI1145_REG_PARAMWR = &H17 const SI1145_REG_COMMAND = &H18 const SI1145_REG_RESPONSE = &H20 const SI1145_REG_IRQSTAT = &H21 const SI1145_REG_IRQSTAT_ALS = &H01 const SI1145_REG_ALSVISDATA0 = &H22 const SI1145_REG_ALSVISDATA1 = &H23 const SI1145_REG_ALSIRDATA0 = &H24 const SI1145_REG_ALSIRDATA1 = &H25 const SI1145_REG_PS1DATA0 = &H26 const SI1145_REG_PS1DATA1 = &H27 const SI1145_REG_PS2DATA0 = &H28 const SI1145_REG_PS2DATA1 = &H29 const SI1145_REG_PS3DATA0 = &H2A const SI1145_REG_PS3DATA1 = &H2B const SI1145_REG_UVINDEX0 = &H2C const SI1145_REG_UVINDEX1 = &H2D const SI1145_REG_PARAMRD = &H2E const SI1145_REG_CHIPSTAT = &H30 const SI1145_ADDR = &H60 ' ' Main Program ' dim float UVindex i2c open 400,1000 'device will run at full speed if(read8(SI1145_REG_PARTID)<>&H45) then print "SI1145 not found" else reset_SI1145() start_SI1145() do print "Vis: ",readVisible() Print "IR: ",readIR() UVindex = readUV() UVindex = UVindex /100.0 print "UV: ",UVindex print "" pause 1000 loop endif end ' '******************************************************************************************************* ' ' Subroutines ' sub start_SI1145() 'set up the sensor and start it reading local integer i ' *********************************** ' enable UVindex measurement coefficients! write8(SI1145_REG_UCOEFF0, &H29) write8(SI1145_REG_UCOEFF1, &H89) write8(SI1145_REG_UCOEFF2, &H02) write8(SI1145_REG_UCOEFF3, &H00) ' enable UV sensor i=writeParam(SI1145_PARAM_CHLIST, SI1145_PARAM_CHLIST_ENUV OR SI1145_PARAM_CHLIST_ENALSIR OR SI1145_PARAM_CHLIST_ENALSVIS OR SI1145_PARAM_CHLIST_ENPS1) ' enable interrupt on every sample write8(SI1145_REG_INTCFG, SI1145_REG_INTCFG_INTOE) write8(SI1145_REG_IRQEN, SI1145_REG_IRQEN_ALSEVERYSAMPLE) '****************************** Prox Sense 1 ' program LED current write8(SI1145_REG_PSLED21, &H03)' 20mA for LED 1 only i=writeParam(SI1145_PARAM_PS1ADCMUX, SI1145_PARAM_ADCMUX_LARGEIR) ' prox sensor #1 uses LED #1 i=writeParam(SI1145_PARAM_PSLED12SEL, SI1145_PARAM_PSLED12SEL_PS1LED1) ' fastest clocks, clock div 1 i=writeParam(SI1145_PARAM_PSADCGAIN, 0) ' take 511 clocks to measure i=writeParam(SI1145_PARAM_PSADCOUNTER, SI1145_PARAM_ADCCOUNTER_511CLK) ' in prox mode, high range i=writeParam(SI1145_PARAM_PSADCMISC, SI1145_PARAM_PSADCMISC_RANGE OR SI1145_PARAM_PSADCMISC_PSMODE) i=writeParam(SI1145_PARAM_ALSIRADCMUX, SI1145_PARAM_ADCMUX_SMALLIR) ' fastest clocks, clock div 1 i=writeParam(SI1145_PARAM_ALSIRADCGAIN, 0) ' take 511 clocks to measure i=writeParam(SI1145_PARAM_ALSIRADCOUNTER, SI1145_PARAM_ADCCOUNTER_511CLK) ' in high range mode i=writeParam(SI1145_PARAM_ALSIRADCMISC, SI1145_PARAM_ALSIRADCMISC_RANGE) ' fastest clocks, clock div 1 i=writeParam(SI1145_PARAM_ALSVISADCGAIN, 0) ' take 511 clocks to measure i=writeParam(SI1145_PARAM_ALSVISADCOUNTER, SI1145_PARAM_ADCCOUNTER_511CLK) ' in high range mode (not normal signal) i=writeParam(SI1145_PARAM_ALSVISADCMISC, SI1145_PARAM_ALSVISADCMISC_VRNG) '************************ ' measurement rate for auto write8(SI1145_REG_MEASRATE0, &HFF)' 255 * 31.25uS = 8ms ' auto run write8(SI1145_REG_COMMAND, SI1145_PSALS_AUTO) end sub sub reset_SI1145() 'Reset the sensor write8(SI1145_REG_MEASRATE0, 0) write8(SI1145_REG_MEASRATE1, 0) write8(SI1145_REG_IRQEN, 0) write8(SI1145_REG_IRQMODE1, 0) write8(SI1145_REG_IRQMODE2, 0) write8(SI1145_REG_INTCFG, 0) write8(SI1145_REG_IRQSTAT, &HFF) write8(SI1145_REG_COMMAND, SI1145_RESET) pause 10 write8(SI1145_REG_HWKEY, &H17) pause 10 end sub ' returns the UV index * 100 (divide by 100 to get the index) FUNCTION readUV() as integer readUV= read16(&H2C) end function ' returns visible+IR light levels FUNCTION readVisible() as integer readVisible = read16(&H22) end function ' returns IR light levels FUNCTION readIR() as integer readIR = read16(&H24) end function ' returns "Proximity" - assumes an IR LED is attached to LED FUNCTION readProx() as integer readProx = read16(&H26) end function function writeParam(p as integer, v as integer) as integer write8(SI1145_REG_PARAMWR, v) write8(SI1145_REG_COMMAND, p OR SI1145_PARAM_SET) writeParam = read8(SI1145_REG_PARAMRD) end function FUNCTION readParam(uint8_t p) as integer write8(SI1145_REG_COMMAND, p OR SI1145_PARAM_QUERY) readParam = read8(SI1145_REG_PARAMRD) end function sub write8(reg as integer, myval as integer) i2c write SI1145_ADDR,0,2,reg,myval end sub function read8(reg as integer) as integer local integer i i2c write SI1145_ADDR,1,1,reg i2c read SI1145_ADDR,0,1,i read8=i end function function read16(reg as integer) as integer local integer i(1) i2c write SI1145_ADDR,1,1,reg i2c read SI1145_ADDR,0,2,i() read16=i(0) OR (i(1)<<8) end function |
||||
| lizby Guru Joined: 17/05/2016 Location: United StatesPosts: 3477 |
This is a good idea, and I'm planning to do this for the 37-sensor and/or 45-sensor kits, as well as other sensors (and things not sensors, like servos), but I had planned to put it on http://fruitoftheshed.com, where it can perhaps be more organized. Thanks for the code. I plan to hook up a BM280 soon. PicoMite, Armmite F4, SensorKits, MMBasic Hardware, Games, etc. on fruitoftheshed |
||||
CircuitGizmos![]() Guru Joined: 08/09/2011 Location: United StatesPosts: 1427 |
Would be nice to copy it to 37 Sensors and 37 sensor documentation as a lot of people that find the 37sensors.com site have become fans of MMBasic. I need to make another grand pass at that site to include more sensors. I have only added a few things since taking over that effort. MMBasic code for new stuff would be great. Micromites and Maximites! - Beginning Maximite |
||||
| matherp Guru Joined: 11/12/2012 Location: United KingdomPosts: 10594 |
Guess |
||||
| Nimue Guru Joined: 06/08/2020 Location: United KingdomPosts: 425 |
Love 37sensors -- thank you for sharing. Entropy is not what it used to be |
||||
CircuitGizmos![]() Guru Joined: 08/09/2011 Location: United StatesPosts: 1427 |
Updating it is in my "spare time" that I don't have. If anyone here has contributions I would add. The 37-45 sensors there can be supplemented by many other inexpensive sensors. Micromites and Maximites! - Beginning Maximite |
||||
| The Back Shed's forum code is written, and hosted, in Australia. | © JAQ Software 2025 |