add BH1750 sensor example

This commit is contained in:
harald42 2016-05-17 16:43:11 +02:00
parent 944f1b06d6
commit a95b0c9d46
18 changed files with 1140 additions and 0 deletions

View file

@ -0,0 +1,22 @@
# Auto detect text files and perform LF normalization
* text=auto
# Custom for Visual Studio
*.cs diff=csharp
*.sln merge=union
*.csproj merge=union
*.vbproj merge=union
*.fsproj merge=union
*.dbproj merge=union
# Standard to msysgit
*.doc diff=astextplain
*.DOC diff=astextplain
*.docx diff=astextplain
*.DOCX diff=astextplain
*.dot diff=astextplain
*.DOT diff=astextplain
*.pdf diff=astextplain
*.PDF diff=astextplain
*.rtf diff=astextplain
*.RTF diff=astextplain

View file

@ -0,0 +1,36 @@
# Windows image file caches
Thumbs.db
ehthumbs.db
# Folder config file
Desktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msm
*.msp
# =========================
# Operating System Files
# =========================
# OSX
# =========================
.DS_Store
.AppleDouble
.LSOverride
# Icon must ends with two \r.
Icon
# Thumbnails
._*
# Files that might appear on external disk
.Spotlight-V100
.Trashes

View file

@ -0,0 +1,209 @@
#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;
}

View file

@ -0,0 +1,115 @@
#ifndef BH1750FVI_h
#define BH1750FVI_h
#if ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
#include <Wire.h>
//device address options
#define BH_AddrL 0x23 // Device address when addr pin is LOW
#define BH_AddrH 0x5C // Device address when addr pin is HIGH
//power codes
#define BH_PowOf 0x00 // power-off code
#define BH_PowOn 0x01 // power-on code
#define BH_Reset 0x07 // code to reset the light reading register to zero
//mode codes
#define BH_NoMod 0x02 // No mode specified. Keeps mode the same as before.
#define BH_EasyH 0x03 // 'easy' mode. basically the same as ContH
#define BH_ContH 0x10 // continuous full-scale, high-resolution sampling
#define BH_Conth 0x11 // continuous with twice the resolution but half the max value
#define BH_ContL 0x13 // continuous full-scale, low-resolution sampling. faster.
#define BH_SingH 0x20 // take one high-resolution, full-scale sample then turn off
#define BH_Singh 0x21 // take one high-resolution, half-scale sample then turn off
#define BH_SingL 0x23 // take one low-resolution, full-scale sample then turn off
// (happens to be the same as the low address value)
//sensitivity codes
#define BH_MTrHb 0x40 // last 3 bits must be masked to 3 MSB of desired value
#define BH_MTrLb 0x60 // last 5 bits must be masked to 5 LSB of desired value
#define BH_MinSv 31 // minimum sensitivity register value, yields Lux * 0.45
#define BH_MaxSv 254 // maximum sensitivity register value, yields Lux * 3.68
#define BH_DefSv 69 // default sensitivity register value, yields Lux * 1.00
//timing delays. they're actually longer than the datasheet says.
#define BH_FastD 18 // basic delay in microseconds for a fast sample
#define BH_SlowD 125 // basic delay in microseconds for a slow sample
class BH1750FVI {
public:
/*BEGIN
this is intended to be as error-tolerant as possible. if you don't supply
a mode, the default mode will be 'easy'. the sensitivity obviously defaults
to 1.0 (byte value of 69). Default address selection is LOW, which is how
the BH1750FVI should default if you don't connect anything to its ADDR pin.
*/void begin(byte mode=BH_EasyH, byte addr=BH_AddrL, double sens=BH_DefSv, int addrPin=-1);
/*FRESH SAMPLE POLLING
Check whether you have already looked at the current sample.
*/bool sampleIsFresh();
/*ACTUALLY GET A READING FROM THE SENSOR
This is probably all you wanted from this library. Return value is an
unsigned 16 bit integer with units of Lux. There are three possible modes:
'r' raw numerical reading, no units, you get what you get
'c' convert units to Lux or half-Lux, depending on the mode, but don't
compensate for the sensitivity setting. This allows sensitivity to
be used as enclosure optics calibration/compensation.
't' true Lux (or half-Lux) reading, regardless of sensitivity settings.
*/word getLightLevel(char adjustments='c');
word retrieveSample();
/*CONTINUOUS SAMPLING
Return value of this start function is the delay time between refreshes of
the ambient light reading. After you call this function, you can use getLightLevel()
to read the most recent ambient light level. If you try to run this ongoing start
function with a one-time mode argument, it will do nothing and return 0.
*/word startOngoingSamples(char mode=BH_NoMod);
/*ONE-TIME SAMPLE START
Return value of this start function is the delay time before the new ambient
light reading will be available. You can check whether the new sample is ready
yet using sampleIsFresh(). Retrieve that single sample with getLightLevel().
If you give this one-time start function a continuous mode argument, it will
do nothing and return 0.
*/word startSingleSample(char mode=BH_NoMod);
/*SENSITIVITY SETTINGS
This function lets you change the 'sensitivity' of the BH1750FVI by changing
its sampling time up or down. The sensitivity is stored as a number between
31 and 254, with a default value of 69. This is intended to compensate for
having the chip installed in an enclosure that blocks some ambient light.
The floating point versions of the function allow the sensitivity to be
given as a ratio between ~0.45 and ~3.68. The return value is the number of
milliseconds that the chip will take to create a new light level reading.
*/word setSensitivity(double sens);
word setSensitivity(float sens);
word setSensitivity(int sens);
word setSensitivity(byte sens=BH_DefSv);
/*POWERDOWN FUNCTION
In case you want to turn off the BH1750FVI to save power. Other commands will wake
the chip back up. Single sample modes automatically turn off the chip after sampling,
but you can still read the value from it without waking it up.
*/void powerDown();
private:
void init(byte mode, byte addr, byte sens);
void i2cWrite(byte dataToSend);
word i2cRead();
byte address;
byte currentMode;
byte currentSensitivity;
bool sampleUnseen;
byte MTreg_hiByte;
byte MTreg_loByte;
unsigned long int lastSampleStart;
word currentSamplingTime;
};
#endif

View file

@ -0,0 +1,23 @@
#include <Wire.h>
#include <BH1750FVI.h>
BH1750FVI eye;
word maxLux = 0;
void setup() {
Wire.begin();
Serial.begin(115200);
//most basic setup with all default options
eye.begin();
}
void loop() {
//take a sensor reading, with units of Lux
word value = eye.getLightLevel();
byte spaces;
if(value>maxLux) maxLux=value;
spaces=map(value, 0, maxLux, 0, 32);
for(int i=0; i<spaces; i++) Serial.print(' ');
Serial.println(value);
delay(100);
}

View file

@ -0,0 +1,36 @@
#include <Wire.h>
#include <BH1750FVI.h>
BH1750FVI eye;
void setup() {
Wire.begin();
Serial.begin(115200);
//setup with continuous sampling, using the low address and double sensitivity
eye.begin(BH_ContH, BH_AddrL, 2.0);
}
void loop() {
//test if the sensor has had time to produce a new reading
if(eye.sampleIsFresh()){
//read the calibration-adjusted value, according to the sensitivity setting
word value = eye.getLightLevel('c');
logarithmicGraphing(value);
Serial.println(value);
}
}
void logarithmicGraphing(word value){
int i=0;
while(value>>i){
i++;
Serial.print(" ");
}
if(i>=2){
i=i-2;
if(value&(1<<i))Serial.print(' ');
}
}

View file

@ -0,0 +1,2 @@
This library interfaces with the BH1750FVI ambient light sensor.
Written by Drew Morgan in September 2014 while I stayed at home with my first baby.

View file

@ -0,0 +1,47 @@
#######################################
# Syntax Coloring Map For BH1750FVI
#######################################
#######################################
# Datatypes (KEYWORD1)
#######################################
BH1750FVI KEYWORD1
#######################################
# Methods and Functions (KEYWORD2)
#######################################
sampleIsFresh KEYWORD2
getLightLevel KEYWORD2
retrieveSample KEYWORD2
startOngoingSamples KEYWORD2
startSingleSample KEYWORD2
setSensitivity KEYWORD2
startSingleSample KEYWORD2
printDebug KEYWORD2
#######################################
# Constants (LITERAL1)
#######################################
BH_AddrL LITERAL1
BH_AddrH LITERAL1
BH_PowOf LITERAL1
BH_PowOn LITERAL1
BH_Reset LITERAL1
BH_NoMod LITERAL1
BH_EasyH LITERAL1
BH_ContH LITERAL1
BH_Conth LITERAL1
BH_ContL LITERAL1
BH_SingH LITERAL1
BH_Singh LITERAL1
BH_SingL LITERAL1
BH_MTrHb LITERAL1
BH_MTrLb LITERAL1
BH_MinSv LITERAL1
BH_MaxSv LITERAL1
BH_DefSv LITERAL1
BH_FastD LITERAL1
BH_SlowD LITERAL1

View file

@ -0,0 +1,209 @@
#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;
}

View file

@ -0,0 +1,115 @@
#ifndef BH1750FVI_h
#define BH1750FVI_h
//#if ARDUINO >= 100
#include "Arduino.h"
//#else
// #include "WProgram.h"
//#endif
#include <Wire.h>
//device address options
#define BH_AddrL 0x23 // Device address when addr pin is LOW
#define BH_AddrH 0x5C // Device address when addr pin is HIGH
//power codes
#define BH_PowOf 0x00 // power-off code
#define BH_PowOn 0x01 // power-on code
#define BH_Reset 0x07 // code to reset the light reading register to zero
//mode codes
#define BH_NoMod 0x02 // No mode specified. Keeps mode the same as before.
#define BH_EasyH 0x03 // 'easy' mode. basically the same as ContH
#define BH_ContH 0x10 // continuous full-scale, high-resolution sampling
#define BH_Conth 0x11 // continuous with twice the resolution but half the max value
#define BH_ContL 0x13 // continuous full-scale, low-resolution sampling. faster.
#define BH_SingH 0x20 // take one high-resolution, full-scale sample then turn off
#define BH_Singh 0x21 // take one high-resolution, half-scale sample then turn off
#define BH_SingL 0x23 // take one low-resolution, full-scale sample then turn off
// (happens to be the same as the low address value)
//sensitivity codes
#define BH_MTrHb 0x40 // last 3 bits must be masked to 3 MSB of desired value
#define BH_MTrLb 0x60 // last 5 bits must be masked to 5 LSB of desired value
#define BH_MinSv 31 // minimum sensitivity register value, yields Lux * 0.45
#define BH_MaxSv 254 // maximum sensitivity register value, yields Lux * 3.68
#define BH_DefSv 69 // default sensitivity register value, yields Lux * 1.00
//timing delays. they're actually longer than the datasheet says.
#define BH_FastD 18 // basic delay in microseconds for a fast sample
#define BH_SlowD 125 // basic delay in microseconds for a slow sample
class BH1750FVI {
public:
/*BEGIN
this is intended to be as error-tolerant as possible. if you don't supply
a mode, the default mode will be 'easy'. the sensitivity obviously defaults
to 1.0 (byte value of 69). Default address selection is LOW, which is how
the BH1750FVI should default if you don't connect anything to its ADDR pin.
*/void begin(byte mode=BH_EasyH, byte addr=BH_AddrL, double sens=BH_DefSv, int addrPin=-1);
/*FRESH SAMPLE POLLING
Check whether you have already looked at the current sample.
*/bool sampleIsFresh();
/*ACTUALLY GET A READING FROM THE SENSOR
This is probably all you wanted from this library. Return value is an
unsigned 16 bit integer with units of Lux. There are three possible modes:
'r' raw numerical reading, no units, you get what you get
'c' convert units to Lux or half-Lux, depending on the mode, but don't
compensate for the sensitivity setting. This allows sensitivity to
be used as enclosure optics calibration/compensation.
't' true Lux (or half-Lux) reading, regardless of sensitivity settings.
*/word getLightLevel(char adjustments='c');
word retrieveSample();
/*CONTINUOUS SAMPLING
Return value of this start function is the delay time between refreshes of
the ambient light reading. After you call this function, you can use getLightLevel()
to read the most recent ambient light level. If you try to run this ongoing start
function with a one-time mode argument, it will do nothing and return 0.
*/word startOngoingSamples(char mode=BH_NoMod);
/*ONE-TIME SAMPLE START
Return value of this start function is the delay time before the new ambient
light reading will be available. You can check whether the new sample is ready
yet using sampleIsFresh(). Retrieve that single sample with getLightLevel().
If you give this one-time start function a continuous mode argument, it will
do nothing and return 0.
*/word startSingleSample(char mode=BH_NoMod);
/*SENSITIVITY SETTINGS
This function lets you change the 'sensitivity' of the BH1750FVI by changing
its sampling time up or down. The sensitivity is stored as a number between
31 and 254, with a default value of 69. This is intended to compensate for
having the chip installed in an enclosure that blocks some ambient light.
The floating point versions of the function allow the sensitivity to be
given as a ratio between ~0.45 and ~3.68. The return value is the number of
milliseconds that the chip will take to create a new light level reading.
*/word setSensitivity(double sens);
word setSensitivity(float sens);
word setSensitivity(int sens);
word setSensitivity(byte sens=BH_DefSv);
/*POWERDOWN FUNCTION
In case you want to turn off the BH1750FVI to save power. Other commands will wake
the chip back up. Single sample modes automatically turn off the chip after sampling,
but you can still read the value from it without waking it up.
*/void powerDown();
private:
void init(byte mode, byte addr, byte sens);
void i2cWrite(byte dataToSend);
word i2cRead();
byte address;
byte currentMode;
byte currentSensitivity;
bool sampleUnseen;
byte MTreg_hiByte;
byte MTreg_loByte;
unsigned long int lastSampleStart;
word currentSamplingTime;
};
#endif

View file

@ -0,0 +1,71 @@
# Set this to the name of your sketch (without extension .pde)
SKETCH=sketch
EXE=arduino-example
all: $(EXE)
CONTIKI=../../..
# Contiki IPv6 configuration
CONTIKI_WITH_IPV6 = 1
CFLAGS += -DPROJECT_CONF_H=\"project-conf.h\"
LFLAGS += -lm
PROJECT_SOURCEFILES += ${SKETCH}.cpp BH1750FVI.cpp
# automatically build RESTful resources
REST_RESOURCES_DIR = ./resources
REST_RESOURCES_DIR_COMMON = ../resources-common
REST_RESOURCES_FILES= $(notdir \
$(shell find $(REST_RESOURCES_DIR) -name '*.c') \
$(shell find $(REST_RESOURCES_DIR_COMMON) -name '*.c') \
)
PROJECTDIRS += $(REST_RESOURCES_DIR) $(REST_RESOURCES_DIR_COMMON)
PROJECT_SOURCEFILES += $(REST_RESOURCES_FILES)
# variable for Makefile.include
ifneq ($(TARGET), minimal-net)
CFLAGS += -DUIP_CONF_IPV6_RPL=1
else
# minimal-net does not support RPL under Linux and is mostly used to test CoAP only
${info INFO: compiling without RPL}
CFLAGS += -DUIP_CONF_IPV6_RPL=0
CFLAGS += -DHARD_CODED_ADDRESS=\"fdfd::10\"
${info INFO: compiling with large buffers}
CFLAGS += -DUIP_CONF_BUFFER_SIZE=2048
CFLAGS += -DREST_MAX_CHUNK_SIZE=1024
CFLAGS += -DCOAP_MAX_HEADER_SIZE=640
endif
# linker optimizations
SMALL=1
# REST Engine shall use Erbium CoAP implementation
APPS += er-coap
APPS += rest-engine
APPS += arduino
include $(CONTIKI)/Makefile.include
include $(CONTIKI)/apps/arduino/Makefile.include
$(CONTIKI)/tools/tunslip6: $(CONTIKI)/tools/tunslip6.c
(cd $(CONTIKI)/tools && $(MAKE) tunslip6)
connect-router: $(CONTIKI)/tools/tunslip6
sudo $(CONTIKI)/tools/tunslip6 aaaa::1/64
connect-router-cooja: $(CONTIKI)/tools/tunslip6
sudo $(CONTIKI)/tools/tunslip6 -a 127.0.0.1 aaaa::1/64
connect-minimal:
sudo ip address add fdfd::1/64 dev tap0
avr-size: $(EXE).$(TARGET).sz
flash: $(EXE).$(TARGET).u $(EXE).$(TARGET).eu
.PHONY: flash avr-size
.PRECIOUS: $(EXE).$(TARGET).hex $(EXE).$(TARGET).eep

View file

@ -0,0 +1,11 @@
Arduino compatibility example
=============================
This example shows that it is now possible to re-use arduino sketches in
Contiki. This example documents the necessary magic. Arduino specifies
two routines, `setup` and `loop`. Before `setup` is called, the
framework initializes hardware. In original Arduino, all this is done in
a `main` function (in C). For contiki we define a process that does the
same.
See the documentation file in apps/contiki-compat/README.md

View file

@ -0,0 +1,2 @@
#include <arduino-process.h>
AUTOSTART_PROCESSES(&arduino_sketch);

View file

@ -0,0 +1,2 @@
#!/bin/bash
make TARGET=osd-merkur-128 flash

View file

@ -0,0 +1,106 @@
/*
* Copyright (c) 2010, Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*
*/
#ifndef PROJECT_RPL_WEB_CONF_H_
#define PROJECT_RPL_WEB_CONF_H_
#define PLATFORM_HAS_LEDS 1
//#define PLATFORM_HAS_BUTTON 1
#define PLATFORM_HAS_BATTERY 1
#define SICSLOWPAN_CONF_FRAG 1
#define LOOP_INTERVAL (10 * CLOCK_SECOND)
/* Save energy */
//#define RDC_CONF_PT_YIELD_OFF
/* For Debug: Dont allow MCU sleeping between channel checks */
//#undef RDC_CONF_MCU_SLEEP
//#define RDC_CONF_MCU_SLEEP 0
/* Disabling RDC for demo purposes. Core updates often require more memory. */
/* For projects, optimize memory and enable RDC again. */
// #undef NETSTACK_CONF_RDC
//#define NETSTACK_CONF_RDC nullrdc_driver
/* Increase rpl-border-router IP-buffer when using more than 64. */
#undef REST_MAX_CHUNK_SIZE
#define REST_MAX_CHUNK_SIZE 64
/* Estimate your header size, especially when using Proxy-Uri. */
/*
#undef COAP_MAX_HEADER_SIZE
#define COAP_MAX_HEADER_SIZE 70
*/
/* The IP buffer size must fit all other hops, in particular the border router. */
#undef UIP_CONF_BUFFER_SIZE
#define UIP_CONF_BUFFER_SIZE 256
/* Multiplies with chunk size, be aware of memory constraints. */
#undef COAP_MAX_OPEN_TRANSACTIONS
#define COAP_MAX_OPEN_TRANSACTIONS 4
/* Must be <= open transaction number, default is COAP_MAX_OPEN_TRANSACTIONS-1. */
/*
#undef COAP_MAX_OBSERVERS
#define COAP_MAX_OBSERVERS 2
*/
/* Filtering .well-known/core per query can be disabled to save space. */
/*
#undef COAP_LINK_FORMAT_FILTERING
#define COAP_LINK_FORMAT_FILTERING 0
*/
/* Save some memory for the sky platform. */
/*
#undef NBR_TABLE_CONF_MAX_NEIGHBORS
#define NBR_TABLE_CONF_MAX_NEIGHBORS 10
#undef UIP_CONF_MAX_ROUTES
#define UIP_CONF_MAX_ROUTES 10
*/
/* Reduce 802.15.4 frame queue to save RAM. */
/*
#undef QUEUEBUF_CONF_NUM
#define QUEUEBUF_CONF_NUM 4
*/
/*
#undef SICSLOWPAN_CONF_FRAG
#define SICSLOWPAN_CONF_FRAG 1
*/
#endif /* PROJECT_RPL_WEB_CONF_H_ */

View file

@ -0,0 +1,80 @@
/*
* Copyright (c) 2013, Institute for Pervasive Computing, ETH Zurich
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This file is part of the Contiki operating system.
*/
/**
* \file
* Moisture resource
* \author
* Harald Pichler <harald@the-develop.net>
*/
#include "contiki.h"
#include <string.h>
#include "rest-engine.h"
#include "Arduino.h"
static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
/* A simple getter example. Returns the reading from the sensor with a simple etag */
RESOURCE(res_bh1750,
"title=\"Lux status\";rt=\"Lux\"",
res_get_handler,
NULL,
NULL,
NULL);
extern uint16_t lux;
static void
res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
unsigned int accept = -1;
REST.get_header_accept(request, &accept);
if(accept == -1 || accept == REST.type.TEXT_PLAIN) {
REST.set_header_content_type(response, REST.type.TEXT_PLAIN);
snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "%d", lux);
REST.set_response_payload(response, buffer, strlen((char *)buffer));
} else if(accept == REST.type.APPLICATION_JSON) {
REST.set_header_content_type(response, REST.type.APPLICATION_JSON);
snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{'lux':%d}", lux);
REST.set_response_payload(response, buffer, strlen((char *)buffer));
} else {
REST.set_response_status(response, REST.status.NOT_ACCEPTABLE);
const char *msg = "Supporting content-types text/plain and application/json";
REST.set_response_payload(response, msg, strlen(msg));
}
}

View file

@ -0,0 +1,5 @@
#!/bin/bash
# For the ages-old bootloader (before 2014) you want to use
# BOOTLOADER_GET_MAC=0x0001f3a0 as parameter to make below.
make clean TARGET=osd-merkur-128
make TARGET=osd-merkur-128

View file

@ -0,0 +1,49 @@
/*
* Sample arduino sketch using contiki features.
* We turn the LED off
* We allow read the moisture sensor
* Unfortunately sleeping for long times in loop() isn't currently
* possible, something turns off the CPU (including PWM outputs) if a
* Proto-Thread is taking too long. We need to find out how to sleep in
* a Contiki-compatible way.
* Note that for a normal arduino sketch you won't have to include any
* of the contiki-specific files here, the sketch should just work.
*/
#include <Wire.h>
#include "BH1750FVI.h"
extern "C" {
#include "arduino-process.h"
#include "rest-engine.h"
BH1750FVI lightMeter;
extern resource_t res_bh1750, res_battery;
uint16_t lux;
#define LED_PIN 4
}
void setup (void)
{
// switch off the led
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, HIGH);
// BH1750 sensor
lightMeter.begin();
// init coap resourcen
rest_init_engine ();
rest_activate_resource (&res_bh1750, "s/lux");
rest_activate_resource (&res_battery, "s/battery");
}
// at project-conf.h
// LOOP_INTERVAL (10 * CLOCK_SECOND)
void loop (void)
{
mcu_sleep_off();
lux = lightMeter.getLightLevel();
mcu_sleep_on();
printf("Lux: %d",lux);
}