osd-contiki/examples/osd/arduino-weather/BH1750FVI.cpp
2016-05-20 11:18:19 +02:00

210 lines
5.2 KiB
C++

#include "BH1750FVI.h"
//#if ARDUINO >= 100
#include "Arduino.h"
//#else
// #include "WProgram.h"
//#endif
#include <Wire.h>
void BH1750FVI::begin(byte mode, byte addr, double sens, int pin){
if(pin>=0 && pin<55){
pinMode(pin, OUTPUT);
if(addr==BH_AddrL) digitalWrite(pin, LOW);
if(addr==BH_AddrH) digitalWrite(pin, HIGH);
}
byte sensitivity;
if(sens<BH_MinSv){
sens = constrain(sens, ((double)BH_MinSv/(double)BH_DefSv), ((double)BH_MaxSv/(double)BH_DefSv));
sensitivity = (byte)round(sens*(double)BH_DefSv);
}
else{
sensitivity = constrain((byte)sens, BH_MinSv, BH_MaxSv);
}
address = addr;
currentSensitivity = sensitivity;
MTreg_hiByte = BH_MTrHb | (sensitivity >> 5);
MTreg_loByte = BH_MTrLb | (sensitivity & 0b00011111);
switch(mode){
case BH_ContL:
case BH_ContH:
case BH_Conth:
startOngoingSamples(mode);
break;
case BH_SingH:
case BH_Singh:
case BH_SingL:
startSingleSample(mode);
break;
default:
mode = BH_EasyH;
startOngoingSamples(mode);
break;
}
sampleUnseen = false;
lastSampleStart = 0;
}
word BH1750FVI::startOngoingSamples(char mode){
if(mode==BH_NoMod) mode=currentMode;
byte lowLevelMode = mode;
if(lowLevelMode==BH_EasyH) lowLevelMode=BH_ContH;
switch(mode){
case BH_EasyH:
case BH_ContH:
case BH_Conth:
case BH_ContL:
i2cWrite(BH_PowOn);
i2cWrite(MTreg_hiByte);
i2cWrite(MTreg_loByte);
i2cWrite(lowLevelMode);
lastSampleStart = millis();
currentMode = mode;
return setSensitivity(currentSensitivity);
break;
default:
return 0;
}
}
word BH1750FVI::startSingleSample(char mode){
if(mode==BH_NoMod){
mode=currentMode;
}
switch(mode){
case BH_SingH:
case BH_Singh:
case BH_SingL:
i2cWrite(BH_PowOn);
i2cWrite(MTreg_hiByte);
i2cWrite(MTreg_loByte);
i2cWrite(mode);
lastSampleStart = millis();
currentMode = mode;
return setSensitivity(currentSensitivity);
break;
default:
return 0;
}
}
bool BH1750FVI::sampleIsFresh(){
if(sampleUnseen) return true;
else if((millis() > (lastSampleStart+currentSamplingTime))){
sampleUnseen = true;
return true;
}
else return false;
}
word BH1750FVI::getLightLevel(char mode){
unsigned long int Intensity_value;
sampleUnseen = false;
Intensity_value = i2cRead();
if(mode!='r'){
Intensity_value = (Intensity_value*5)/6;
if(mode!='c'){
Intensity_value = (Intensity_value*69)/currentSensitivity;
}
/*this next adjustment is not useful in practice. if you're using
a half-scale mode, you want the extra sensitivity. I'm leaving it
here for reference.
switch(currentMode){
case BH_Singh:
case BH_Conth:
Intensity_value /= 2;
}*/
Intensity_value = constrain(Intensity_value, 0, 65535);
}
switch(currentMode){
case BH_ContH:
case BH_Conth:
case BH_ContL:
case BH_EasyH:
//this is a fake previous sample time that will keep pace with
//the actual BH1750FVI's sampling rate, but isn't necessarily
//synchronized to the earliest time each new sample is available.
//if you want true synchronized timing, use a single-sample mode.
lastSampleStart = millis();
}
return (word)Intensity_value;
}
word BH1750FVI::setSensitivity(double sens){
if(sens<((double)(BH_MinSv/2))){
sens = constrain(sens,
((double)BH_MinSv/(double)BH_DefSv),
((double)BH_MaxSv/(double)BH_DefSv)
);
sens = sens*(double)BH_DefSv;
}
else{
sens = constrain(sens, (double)BH_MinSv, (double)BH_MaxSv);
}
return setSensitivity((byte)round(sens));
}
word BH1750FVI::setSensitivity(float sens){
return setSensitivity((double)sens);
}
word BH1750FVI::setSensitivity(int sens){
sens = constrain(sens, 1, BH_MaxSv);
return setSensitivity((byte)sens);
}
word BH1750FVI::setSensitivity(byte sens){
if(sens<(BH_MinSv/2)){
sens = BH_DefSv*(constrain(sens, (byte)1, (byte)3));
}
else{
sens = constrain(sens, BH_MinSv, BH_MaxSv);
}
switch(currentMode){
case BH_ContL:
case BH_SingL:
currentSamplingTime = (word)((BH_FastD*(unsigned long int)sens)/BH_DefSv);
break;
default:
currentSamplingTime = (word)((((unsigned long int)BH_SlowD)*((unsigned long int)sens))/BH_DefSv);
break;
}
MTreg_hiByte = BH_MTrHb | (sens >> 5);
MTreg_loByte = BH_MTrLb | (sens & 0b00011111);
currentSensitivity = sens;
sampleUnseen = false;
return currentSamplingTime;
}
void BH1750FVI::powerDown(){
i2cWrite(BH_PowOf);
}
/*I2C INTERFACE
These two functions were originally based on code written by
https://github.com/claws/ and
https://github.com/Genotronex/
*/
void BH1750FVI::i2cWrite(byte dataToSend){
Wire.beginTransmission(address);
Wire.write(dataToSend);
Wire.endTransmission();
}
word BH1750FVI::i2cRead(){
word value;
Wire.beginTransmission(address);
Wire.requestFrom(address, (byte)2);
if(Wire.available()){
value = Wire.read();
if(Wire.available()){
value <<= 8;
value |= Wire.read();
}
else value=0;
}
else value=0;
Wire.endTransmission();
return value;
}