From a95b0c9d466f2de5e18cbd51c1d70f090440f8bb Mon Sep 17 00:00:00 2001 From: harald42 Date: Tue, 17 May 2016 16:43:11 +0200 Subject: [PATCH] add BH1750 sensor example --- .../BH1750FVI-master/.gitattributes | 22 ++ .../BH1750FVI-master/.gitignore | 36 +++ .../BH1750FVI-master/BH1750FVI.cpp | 209 ++++++++++++++++++ .../BH1750FVI-master/BH1750FVI.h | 115 ++++++++++ .../BH1750FVI-master/BasicDemo/BasicDemo.ino | 23 ++ .../BH1750FVI-master/LogGraph/LogGraph.ino | 36 +++ .../arduino-bh1750/BH1750FVI-master/README | 2 + .../BH1750FVI-master/keywords.txt | 47 ++++ examples/osd/arduino-bh1750/BH1750FVI.cpp | 209 ++++++++++++++++++ examples/osd/arduino-bh1750/BH1750FVI.h | 115 ++++++++++ examples/osd/arduino-bh1750/Makefile | 71 ++++++ examples/osd/arduino-bh1750/README.md | 11 + examples/osd/arduino-bh1750/arduino-example.c | 2 + examples/osd/arduino-bh1750/flash.sh | 2 + examples/osd/arduino-bh1750/project-conf.h | 106 +++++++++ .../osd/arduino-bh1750/resources/res-bh1750.c | 80 +++++++ examples/osd/arduino-bh1750/run.sh | 5 + examples/osd/arduino-bh1750/sketch.pde | 49 ++++ 18 files changed, 1140 insertions(+) create mode 100644 examples/osd/arduino-bh1750/BH1750FVI-master/.gitattributes create mode 100644 examples/osd/arduino-bh1750/BH1750FVI-master/.gitignore create mode 100644 examples/osd/arduino-bh1750/BH1750FVI-master/BH1750FVI.cpp create mode 100644 examples/osd/arduino-bh1750/BH1750FVI-master/BH1750FVI.h create mode 100644 examples/osd/arduino-bh1750/BH1750FVI-master/BasicDemo/BasicDemo.ino create mode 100644 examples/osd/arduino-bh1750/BH1750FVI-master/LogGraph/LogGraph.ino create mode 100644 examples/osd/arduino-bh1750/BH1750FVI-master/README create mode 100644 examples/osd/arduino-bh1750/BH1750FVI-master/keywords.txt create mode 100644 examples/osd/arduino-bh1750/BH1750FVI.cpp create mode 100644 examples/osd/arduino-bh1750/BH1750FVI.h create mode 100644 examples/osd/arduino-bh1750/Makefile create mode 100644 examples/osd/arduino-bh1750/README.md create mode 100644 examples/osd/arduino-bh1750/arduino-example.c create mode 100755 examples/osd/arduino-bh1750/flash.sh create mode 100644 examples/osd/arduino-bh1750/project-conf.h create mode 100644 examples/osd/arduino-bh1750/resources/res-bh1750.c create mode 100755 examples/osd/arduino-bh1750/run.sh create mode 100644 examples/osd/arduino-bh1750/sketch.pde diff --git a/examples/osd/arduino-bh1750/BH1750FVI-master/.gitattributes b/examples/osd/arduino-bh1750/BH1750FVI-master/.gitattributes new file mode 100644 index 000000000..412eeda78 --- /dev/null +++ b/examples/osd/arduino-bh1750/BH1750FVI-master/.gitattributes @@ -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 diff --git a/examples/osd/arduino-bh1750/BH1750FVI-master/.gitignore b/examples/osd/arduino-bh1750/BH1750FVI-master/.gitignore new file mode 100644 index 000000000..6dae74742 --- /dev/null +++ b/examples/osd/arduino-bh1750/BH1750FVI-master/.gitignore @@ -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 diff --git a/examples/osd/arduino-bh1750/BH1750FVI-master/BH1750FVI.cpp b/examples/osd/arduino-bh1750/BH1750FVI-master/BH1750FVI.cpp new file mode 100644 index 000000000..600905394 --- /dev/null +++ b/examples/osd/arduino-bh1750/BH1750FVI-master/BH1750FVI.cpp @@ -0,0 +1,209 @@ +#include "BH1750FVI.h" +#if ARDUINO >= 100 + #include "Arduino.h" +#else + #include "WProgram.h" +#endif + +#include + +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> 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; +} \ No newline at end of file diff --git a/examples/osd/arduino-bh1750/BH1750FVI-master/BH1750FVI.h b/examples/osd/arduino-bh1750/BH1750FVI-master/BH1750FVI.h new file mode 100644 index 000000000..4a7dc9866 --- /dev/null +++ b/examples/osd/arduino-bh1750/BH1750FVI-master/BH1750FVI.h @@ -0,0 +1,115 @@ +#ifndef BH1750FVI_h +#define BH1750FVI_h + +#if ARDUINO >= 100 + #include "Arduino.h" +#else + #include "WProgram.h" +#endif + +#include + +//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 \ No newline at end of file diff --git a/examples/osd/arduino-bh1750/BH1750FVI-master/BasicDemo/BasicDemo.ino b/examples/osd/arduino-bh1750/BH1750FVI-master/BasicDemo/BasicDemo.ino new file mode 100644 index 000000000..3625f5202 --- /dev/null +++ b/examples/osd/arduino-bh1750/BH1750FVI-master/BasicDemo/BasicDemo.ino @@ -0,0 +1,23 @@ +#include +#include + +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 +#include + +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<= 100 + #include "Arduino.h" +//#else +// #include "WProgram.h" +//#endif + +#include + +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> 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; +} diff --git a/examples/osd/arduino-bh1750/BH1750FVI.h b/examples/osd/arduino-bh1750/BH1750FVI.h new file mode 100644 index 000000000..acdf62102 --- /dev/null +++ b/examples/osd/arduino-bh1750/BH1750FVI.h @@ -0,0 +1,115 @@ +#ifndef BH1750FVI_h +#define BH1750FVI_h + +//#if ARDUINO >= 100 + #include "Arduino.h" +//#else +// #include "WProgram.h" +//#endif + +#include + +//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 diff --git a/examples/osd/arduino-bh1750/Makefile b/examples/osd/arduino-bh1750/Makefile new file mode 100644 index 000000000..201eeac72 --- /dev/null +++ b/examples/osd/arduino-bh1750/Makefile @@ -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 diff --git a/examples/osd/arduino-bh1750/README.md b/examples/osd/arduino-bh1750/README.md new file mode 100644 index 000000000..e1490ed05 --- /dev/null +++ b/examples/osd/arduino-bh1750/README.md @@ -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 diff --git a/examples/osd/arduino-bh1750/arduino-example.c b/examples/osd/arduino-bh1750/arduino-example.c new file mode 100644 index 000000000..ea74dd8b8 --- /dev/null +++ b/examples/osd/arduino-bh1750/arduino-example.c @@ -0,0 +1,2 @@ +#include +AUTOSTART_PROCESSES(&arduino_sketch); diff --git a/examples/osd/arduino-bh1750/flash.sh b/examples/osd/arduino-bh1750/flash.sh new file mode 100755 index 000000000..e82962073 --- /dev/null +++ b/examples/osd/arduino-bh1750/flash.sh @@ -0,0 +1,2 @@ +#!/bin/bash +make TARGET=osd-merkur-128 flash diff --git a/examples/osd/arduino-bh1750/project-conf.h b/examples/osd/arduino-bh1750/project-conf.h new file mode 100644 index 000000000..e25aed53c --- /dev/null +++ b/examples/osd/arduino-bh1750/project-conf.h @@ -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_ */ diff --git a/examples/osd/arduino-bh1750/resources/res-bh1750.c b/examples/osd/arduino-bh1750/resources/res-bh1750.c new file mode 100644 index 000000000..ae47f07a5 --- /dev/null +++ b/examples/osd/arduino-bh1750/resources/res-bh1750.c @@ -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 + */ + +#include "contiki.h" + +#include +#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)); + } +} diff --git a/examples/osd/arduino-bh1750/run.sh b/examples/osd/arduino-bh1750/run.sh new file mode 100755 index 000000000..5d5cbbbb4 --- /dev/null +++ b/examples/osd/arduino-bh1750/run.sh @@ -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 diff --git a/examples/osd/arduino-bh1750/sketch.pde b/examples/osd/arduino-bh1750/sketch.pde new file mode 100644 index 000000000..30b259b02 --- /dev/null +++ b/examples/osd/arduino-bh1750/sketch.pde @@ -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 +#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); +}