Люксметр

sav13
sav13 аватар
Онлайн
Зарегистрирован: 17.06.2013

Часто делаю что-нибудь светодиодное. Чтобы не таскать с работы люксметр, решил собрать свой.

Взял за основу готовый модуль BH1750, откалиброванный на заводе и выдающий сразу цифру по I2C

Схема получилась такой

Корпус купил на ТАОБАО, остальное на EBAY

Собрал все на макетной плате, аккумулятор от старого телефона

Даташит на BH1750
Библиотеки для дисплея 5110 Adafruit-PCD8544-Nokia-5110-LCD-library и Adafruit-GFX-Library
Скетч для Ардуино
Подробное описание изготовления

Тестирование показало расхождение со стандартным прибором DT-1300 не более 5% - в рамках погрешности

Характеристики

  • Диапазон измерения 1 — 65535 лк
  • Разрешение измерения 1 лк
  • Потребляемый ток в режиме измерения  60мА
  • Ток в режиме ожидания (PowerDowsn) 100мкА
  • Габариты 134 x 70 х 25 мм

Сильно разочаровал дешевый дисплей NOKIA 5110. Очень слепой хоть с подсветой хоть без.

Сейчас работаю над алгоритмом измерения пульсаций света. Может кто уже реализовывал?

Также планирую подключение к прибору разных датчиков по I2C - модулей измерения освещенности покрцче (лежит TSL2581), инфрокрасного термометра, измерителя УФ и т.д. с автоопределением типа датчика (подключил и получил измеритель чего то другого)

Ну и сервисное меню сделать, с настройкой контрастности и подсветки дисплея и др. характеристик

 

 

inspiritus
Offline
Зарегистрирован: 17.12.2012

Спасибо, впечатлило. Редко тут до функционирующего протипа доводит устройство кто.

В опубликованом скетче (Safari iPad iOS-8.1) комментарии крякозябрами.

a5021
Offline
Зарегистрирован: 07.07.2013

sav13 пишет:

Сильно разочаровал дешевый дисплей NOKIA 5110. Очень слепой хоть с подсветой хоть без.

По моему мнению, если не требуется отображать сложные картинки, всем остальным устройствам отображения стоит предпочесть светодиодные семисегментные индикаторы.

Цитата:

Сейчас работаю над алгоритмом измерения пульсаций света. Может кто уже реализовывал?

На радиокоте, призером конкурса года в разделе "Цифровые устройства" оказался как раз такой прибор .

 

sav13
sav13 аватар
Онлайн
Зарегистрирован: 17.06.2013

inspiritus пишет:

В опубликованом скетче (Safari iPad iOS-8.1) комментарии крякозябрами.

В среде Arduino русские буквы в UNICODE пишутся. Если есть такие настройки в сафари, то должны отобразиться нормально. Если нет, могу сюда запостить весь скетч

inspiritus
Offline
Зарегистрирован: 17.12.2012

Нет таких настроек, автоматом переключает, видимо с текстом не приходит идетификатор кодировки.

лучше запостить в тему раскрывающимся текстом или

Текстом

 

sav13
sav13 аватар
Онлайн
Зарегистрирован: 17.06.2013

a5021 пишет:

По моему мнению, если не требуется отображать сложные картинки, всем остальным устройствам отображения стоит предпочесть светодиодные семисегментные индикаторы.

Закупил таких вместе с MAX7219. Очень они нравятся

В этом проекте боялся, что слишком яркие, будут датчик засвечивать

 

a5021 пишет:

На радиокоте, призером конкурса года в разделе "Цифровые устройства" оказался как раз такой прибор .

Отличный проект. К этому и стремлюсь. Только очень не хочется аналоговый датчик ставить для измерения пульсаций.

inspiritus
Offline
Зарегистрирован: 17.12.2012

Как вариант - аналоговый датчик с выходом на компаратор и регулировка уровня сравнения, пока пульсации не проявятся...

trembo
trembo аватар
Offline
Зарегистрирован: 08.04.2011

sav13 пишет:

inspiritus пишет:

В опубликованом скетче (Safari iPad iOS-8.1) комментарии крякозябрами.

В среде Arduino русские буквы в UNICODE пишутся. Если есть такие настройки в сафари, то должны отобразиться нормально. Если нет, могу сюда запостить весь скетч

Там наверху кнопка есть: " Исправить кодировку и перезагрузить"   Всегда помогала с русскими буквами.....

sav13
sav13 аватар
Онлайн
Зарегистрирован: 17.06.2013
// Библиотеки отвечающие за режим сна
#include <avr/sleep.h>
#include <avr/power.h>
// Библиотеки для работы с дисплеем 5110
#include <Adafruit_GFX.h>
#include <Adafruit_PCD8544.h>
// Библиотека работы с устройствами по I2C
#include <Wire.h> 
 

// pin 7 - Serial clock out (SCLK)
// pin 6 - Serial data out (DIN)
// pin 5 - Data/Command select (D/C)
// pin 4 - LCD chip select (CS)
// pin 3 - LCD reset (RST)
Adafruit_PCD8544 display = Adafruit_PCD8544(3, 4, 5, 6, 7);

boolean DebugFlag = true;
int BH1750address = 0x23; //Адрес IIC BH1750
byte buff[2];


int key_count          = 0; 
unsigned long key_time = 0;
boolean key_press      = false;
boolean power_on       = false;


volatile boolean int_pwr_up  = false;
volatile boolean int_key     = false;

/**
* Функция определения напряжения питания устройства
*/
static int vccRead(byte us =250) {
  ADMUX = 1<<REFS0; // опорное напряжение - Vcc
  ADMUX |= 0x0E;    // объект измерения - внутренний источник
                    // стабилизированного напряжения 1.1В
  delayMicroseconds(us);
 
  ADCSRA |= 1<<ADSC;         // запуск АЦ-преобразования
  while(ADCSRA & (1<<ADSC)); // и ожидание его завершения
  word x = ADC;
  return x ? (1100L * 1023) / x : -1;
}


/**
* Функция инициализации при включении питания 
*/
void PowerOn(){
  digitalWrite(8,HIGH);   //  on
  digitalWrite(9,HIGH);   // on
  digitalWrite(13,HIGH);  // power LED on
  display.begin();
  Wire.begin();
  BH1750_Init();
  display.setContrast(37);
}

/**
* Функция выключение всех устройств при переходе в POWER_DOWN моде
*/
void PowerOff(){
// Отключаем все выходы 3-19
  for( int i=3; i<20; i++ ){
     pinMode(i,INPUT_PULLUP); 
     digitalWrite(i,LOW);  
  }
}

/**
* Функция обраюотчик прерывания на кнопку питания 
*/
void intKey()
{
  int_key = true;
  detachInterrupt(0); //Отключаем прерывания 
}

/**
* Функия перевода ARDUINO в POWER_DOWN режим
*/
void EnterSleep()
{
  PowerOff();
  DebugPrint("I am sleeping");
  attachInterrupt(0, intKey, LOW); //Если на 0-вом прерываниии - ноль, то просыпаемся.
  power_on = false;
  delay(100);
  set_sleep_mode(SLEEP_MODE_PWR_DOWN); //Определяем режим сна
  
  sleep_enable(); //Разрешаем спящий режим
  sleep_mode(); //Спим (Прерывания продолжают работать.) Программа останавливается.
  sleep_disable(); //Запрещаем спящий режим
}

/* 
Чтение значение освещенности
*/
int BH1750_Read() //
{
  int i=0;
  Wire.beginTransmission(BH1750address);
  Wire.requestFrom(BH1750address, 2);
  while(Wire.available()) //
  {
    buff[i] = Wire.read();  // Считываем 1байт данных
    i++;
  }
  Wire.endTransmission(); 
  return i;
}
 
/** 
* Инициализация датчика освещенности
*/
void BH1750_Init()
{
  Wire.beginTransmission(BH1750address);
  Wire.write(0x10);//1lx reolution 120ms
  Wire.endTransmission();
}


void DebugPrint( char *msg ){
   if( DebugFlag )Serial.println(msg);
} 


 
void setup()
{
   if( DebugFlag ){
      Serial.begin(9600);
      Serial.println("Hello World");
   }
   pinMode(13,OUTPUT);      // Светодиод питания
   pinMode(9,INPUT_PULLUP); // Выход на подсветку дисплея
   pinMode(8,INPUT_PULLUP); // Выход на питание дисплея

   analogRead(0);           // Порт для измерения напряжения питания по внутреннему источнику
   pinMode(2, INPUT_PULLUP);// Порт кнопки питания 
 //  digitalWrite(pin, HIGH);   
   attachInterrupt(0, intKey, LOW); //Если на 0-вом прерываниии - ноль, то просыпаемся.
   EnterSleep();            // Идем спать
 
}
 
unsigned long ms1 = 0; 
 
void loop()
{
   unsigned long ms = millis();
// Кнопка нажата
   if( key_press ){
// Кнопка наконец то отаущена     
      if( digitalRead(2) == HIGH ){
         unsigned int key_interval =0;
         if( DebugFlag ){
            Serial.print("Press key ");
            key_interval = abs(ms - key_time);
            Serial.print(key_count);
            Serial.print(" ");
            Serial.print(key_interval);
            Serial.println("");
         }
         key_count = 0;
         key_press = false;
         if( power_on && key_interval > 2000 ){
            DebugPrint("Power off");
            EnterSleep();
         }  
         else if( !power_on && key_interval < 2000 ){
            DebugPrint("Sleep again");
            EnterSleep();
         }
         else if( key_interval>2000 ){
           DebugPrint("Power on");
           power_on = true;
           PowerOn();
         }  
         else {
           DebugPrint("Press PWR key");
         }
      }  
   }
// Прерывание нажатия кнопки
   if( int_key ){
      delay(100);
      key_press = true;
// Первый тик времени нажатия кнопки
      if( key_count == 0 )key_time = ms;
      key_count++;
// Заряжаем обработку прерывния по новой
      int_key = false;
      attachInterrupt(0, intKey, LOW); //Если на 0-вом прерываниии - ноль, то просыпаемся.
   }
   
// Опрос датчиков каждую секунду
   if( (ms < ms1 || (ms - ms1) > 1000)&&power_on ){
      ms1 = ms;
      uint16_t l1=0,l2=0,u1=0,l_min=0,l_max=0;
      
      
      BH1750_Init();
      if(2==BH1750_Read()){
          l1=((buff[0]<<8)|buff[1])/1.2;
      }
      u1 = vccRead(100);
      if( DebugFlag ){
         Serial.print("Light (Lx)=");
         Serial.print(l1);
         Serial.print("Light2 (Lx)=");
         Serial.print(l2);
         Serial.print("LightMin (Lx)=");
         Serial.print(l_min);
         Serial.print("LightMax (Lx)=");
         Serial.print(l_max);
         Serial.print(",Vcc (mV)=");
         Serial.println(u1);
      }
      display.clearDisplay();
      display.setTextSize(2);
      display.setCursor(0,0);
      display.print(l1);
      display.setTextSize(1);
      display.println(" Lx");
      display.println("");
      display.println("");
      display.println("");
      display.print("Bat: ");
      display.print(u1/1000);
      display.print(".");
      display.print((u1/100)%10);
      display.println(" V");
      display.display(); 
 
   }
 
}

 

Araris
Araris аватар
Offline
Зарегистрирован: 09.11.2012

sav13, качественно исполнено, респект Вам и уважуха.

sav13
sav13 аватар
Онлайн
Зарегистрирован: 17.06.2013

Сейчас разбирал старое барахло. Нашел сенсор движения инфракрасный.

Интересно, можно линзу использовать для изготовления конструктива сенсора?

Например, такую

Или они только для инфракрасного света нормално прозрачные?

sav13
sav13 аватар
Онлайн
Зарегистрирован: 17.06.2013

Сегодня доработал свой люксметр

Подключил модуль TSL2561 с двумя встроенными фотодиодами.
Сенсор встроил прямо в прибор. 

Подключил библиотеку работы с TSL2561
Читаю в цикле 84 значения (по числу точек дисплея) освещенности в самом быстром режиме (13мс)
Нахожу минимум, максимум, среднее и К пульсаций = (макс-мин)/макс * 100%
Вывожу в текстовом режиме

Как раз баловался с таким драйвером 

Мультимитер на шкале переменного тока показывает пульсации около 1В. Если посадить на выход кондер 10000мкф, пульсации уменьшаются до 0.4В

Люксметр показал пульсации 12% и 5% соответственно
И форму пульсаций такую

sav13
sav13 аватар
Онлайн
Зарегистрирован: 17.06.2013

Скетч люксметра с измерением пульсаций на TSL2561

// Люксметр на TSL2561 с режимом измерения пульсаций
// Библиотеки отвечающие за режим сна
#include <avr/sleep.h>
#include <avr/power.h>
// Библиотеки для работы с дисплеем 5110
#include <Adafruit_GFX.h>
#include <Adafruit_PCD8544.h>
// Библиотека работы с устройствами по I2C
#include <Wire.h> 
// Библиотека работы с TSL2561
#include <Adafruit_Sensor.h>
#include <Adafruit_TSL2561_U.h>
 
#define MAX_UNITS  84 

// pin 7 - Serial clock out (SCLK)
// pin 6 - Serial data out (DIN)
// pin 5 - Data/Command select (D/C)
// pin 4 - LCD chip select (CS)
// pin 3 - LCD reset (RST)
Adafruit_PCD8544 display = Adafruit_PCD8544(3, 4, 5, 6, 7);
Adafruit_TSL2561_Unified tsl = Adafruit_TSL2561_Unified(TSL2561_ADDR_FLOAT, 12345);

boolean DebugFlag = true;


int key_count          = 0; 
unsigned long key_time = 0;
boolean key_press      = false;
boolean power_on       = false;

int key_count2          = 0; 
unsigned long key_time2 = 0;
boolean key_press2      = false;
int key_mode2           = 1;


volatile boolean int_pwr_up  = false;
volatile boolean int_key     = false;

/**
* Функция определения напряжения питания устройства
*/
static int vccRead(byte us =250) {
  ADMUX = 1<<REFS0; // опорное напряжение - Vcc
  ADMUX |= 0x0E;    // объект измерения - внутренний источник
                    // стабилизированного напряжения 1.1В
  delayMicroseconds(us);
 
  ADCSRA |= 1<<ADSC;         // запуск АЦ-преобразования
  while(ADCSRA & (1<<ADSC)); // и ожидание его завершения
  word x = ADC;
  return x ? (1100L * 1023) / x : -1;
}


/**
* Функция инициализации при включении питания 
*/
void PowerOn(){
  digitalWrite(8,HIGH);   //  on
  digitalWrite(9,HIGH);   // on
  digitalWrite(13,HIGH);  // power LED on
  display.begin();
  Wire.begin();
  tsl.begin();
  tsl.enableAutoGain(true);          /* Auto-gain ... switches automatically between 1x and 16x */
  tsl.setIntegrationTime(TSL2561_INTEGRATIONTIME_13MS);      /* fast but low resolution */
  display.setContrast(40);
}

/**
* Функция выключение всех устройств при переходе в POWER_DOWN моде
*/
void PowerOff(){
// Отключаем все выходы 3-19
  for( int i=3; i<20; i++ ){
     pinMode(i,INPUT_PULLUP); 
     digitalWrite(i,LOW);  
  }
}

/**
* Функция обраюотчик прерывания на кнопку питания 
*/
void intKey()
{
  int_key = true;
  detachInterrupt(0); //Отключаем прерывания 
}

/**
* Функия перевода ARDUINO в POWER_DOWN режим
*/
void EnterSleep()
{
  PowerOff();
  DebugPrint("I am sleeping");
  attachInterrupt(0, intKey, LOW); //Если на 0-вом прерываниии - ноль, то просыпаемся.
  power_on = false;
  delay(100);
  set_sleep_mode(SLEEP_MODE_PWR_DOWN); //Определяем режим сна
  
  sleep_enable(); //Разрешаем спящий режим
  sleep_mode(); //Спим (Прерывания продолжают работать.) Программа останавливается.
  sleep_disable(); //Запрещаем спящий режим
}

void DebugPrint( char *msg ){
   if( DebugFlag )Serial.println(msg);
} 

uint16_t l1=0,l2=0,l_min=0,l_max=0;
uint16_t u1 = 0;
double pulse = 0;
uint16_t l_mas[MAX_UNITS];


/**
* Текстовый экран
*/
void DisplayMode1(){ 
   display.clearDisplay();
   display.setTextSize(2);
   display.setCursor(0,0);
   display.print(l1);
   display.setTextSize(1);
   display.println(" Lx");
   display.println("");
   display.println("");
   display.print("Pulse: ");
   display.print(pulse,1);
   display.println("%");
   display.print("Bat: ");
   display.print(u1/1000);
   display.print(".");
   display.print((u1/100)%10);
   display.println(" V");
   display.display(); 
} 

/**
* Графический экран
*/
void DisplayMode2(){ 
   display.clearDisplay();
   display.setTextSize(1);
   display.setCursor(0,0);
   display.print(l1);
   display.print(" Lx. ");
   display.print(pulse,1);
   display.println("%");
 
   uint16_t dl = l_max - l_min;
   display.drawLine(0, 45, 84, 45 , BLACK);
   display.drawLine(78, 43, 84, 45 , BLACK);
   display.drawLine(78, 477, 84, 45 , BLACK);
   for( int i=0; i<MAX_UNITS; i++){
      uint16_t y = 44-(l_max-l_mas[i])*28/dl;
      display.drawLine(i, y, i, y-4, BLACK);
   }  
   
   display.display();
} 


 
void setup()
{
   if( DebugFlag ){
      Serial.begin(9600);
      Serial.println("Start luxmetr");
   }
   pinMode(13,OUTPUT);      // Светодиод питания
   pinMode(9,INPUT_PULLUP); // Выход на подсветку дисплея
   pinMode(8,INPUT_PULLUP); // Выход на питание дисплея

   analogRead(0);           // Порт для измерения напряжения питания по внутреннему источнику
   pinMode(2, INPUT_PULLUP);// Порт кнопки питания 
//




0=pinMode(10, INPUT_PULLUP);// Порт кнопки режима 
    attachInterrupt(0, intKey, LOW); //Если на 0-вом прерываниии - ноль, то просыпаемся.
   EnterSleep();            // Идем спать
 
}




 
unsigned long ms1 = 0; 
 
void loop()
{
   unsigned long ms = millis();
// Кнопка POWER нажата
   if( key_press ){
// Кнопка наконец то отаущена     
      if( digitalRead(2) == HIGH ){
         unsigned int key_interval = 0;
         if( DebugFlag ){
            Serial.print("Press key ");
            key_interval = abs(ms - key_time);
            Serial.print(key_count);
            Serial.print(" ");
            Serial.print(key_interval);
            Serial.println("");
         }
         key_count = 0;
         key_press = false;
         if( power_on && key_interval > 2000 ){
            DebugPrint("Power off");
            EnterSleep();
         }  
         else if( !power_on && key_interval < 2000 ){
            DebugPrint("Sleep again");
            EnterSleep();
         }
         else if( key_interval>2000 ){
           DebugPrint("Power on");
           power_on = true;
           PowerOn();
         }  
         else {
           DebugPrint("Press PWR key");
           if( key_mode2 == 1 ){key_mode2 = 2;DisplayMode2();}
           else {key_mode2 = 1;DisplayMode1();}
          }
      }  
   }
// Прерывание нажатия кнопки
   if( int_key ){
      delay(100);
      key_press = true;
// Первый тик времени нажатия кнопки
      if( key_count == 0 )key_time = ms;
      key_count++;
// Заряжаем обработку прерывния по новой
      int_key = false;
      attachInterrupt(0, intKey, LOW); //Если на 0-вом прерываниии - ноль, то просыпаемся.
   }

   
   
// Опрос датчиков каждую секунду
   if( (ms < ms1 || (ms - ms1) > 3000)&&power_on ){
      ms1 = ms;
      l1=0;l2=0;l_min=0;l_max=0;
      u1 = vccRead(100);
      uint32_t l_avg = 0;
      sensors_event_t event;
// Делаем MSX_UNITS измерений по 13мс      
      for( int i=0; i<MAX_UNITS; i++){
         tsl.getEvent(&event);
         l_avg += event.light;
         l_mas[i] = event.light;
         if( i == 0 ){
            l_min = event.light;
            l_max = event.light;
         }
         else {
            if( event.light < l_min )l_min = event.light;
            if( event.light > l_max )l_max = event.light;
         }
      } 
      l1 = l_avg / MAX_UNITS;
      if( l_max != 0 )pulse = (double)((l_max - l_min))*100/(double)l_max;
      else pulse = 0; 
      if( DebugFlag ){
         Serial.print("l_min(lx)=");
         Serial.print(l_min);
         Serial.print(",l_max(lx)=");
         Serial.print(l_max);
         Serial.print(",l1(lx)=");
         Serial.print(l1);
         Serial.print(",pulse(%)=");
         Serial.print(pulse,1);
         Serial.print(",Vcc (mV)=");
         Serial.println(u1);
     }

     if( key_mode2 == 1)DisplayMode1();
     else DisplayMode2();
   }
 
}

 

sav13
sav13 аватар
Онлайн
Зарегистрирован: 17.06.2013

Допилил люксметр.

Измерят освещенность и пульсации, переключает режимы и т.д.

Подробности здесь

 

 

Maverik
Offline
Зарегистрирован: 12.09.2012

у этих дисплеев 5110 вроде как логика 3.3вольтовая, а питание до 5 вольт держит спокойно и контрастность зависит от напряжения питания.

 

 

sav13
sav13 аватар
Онлайн
Зарегистрирован: 17.06.2013

Так и есть. Но высокая контрастность выражается в том что фон сливается с текстом

art100
Offline
Зарегистрирован: 09.03.2014

Мне как "ступеду" пните ногами. Может кто помнит "попугаи"?

1.Люмен это в точке?

2.Люкс это на метре квадратном?

3.или наоборот?

http://art1.by/0arduino/

Забирал на почте всякое разное  Хрень получил BH1750 . Тыкнул получил некую байду lx  сходу подправил бред на некий другой бред lux

//art100 to write test BH1750-lux ?
#include <Wire.h>
#include <BH1750.h>
//pins----------------------
// VCC-5v
// GND-GND
// SCL-SCL(analog pin 5)
// SDA-SDA(analog pin 4)
// ADD-NC or GND
//consts--------------------
BH1750 lightMeter;
//----------------------------------
void setup(){
  Serial.begin(9600);
  lightMeter.begin();
}
//====================================================
void loop() {
  uint16_t lux = lightMeter.readLightLevel();
  Serial.print("Light in lux: ");  Serial.println(lux);
  delay(1000);
}
//====================================================
Light in lux: 2204
Light in lux: 119
Light in lux: 99
Light in lux: 85
Light in lux: 94
Light in lux: 93
Light in lux: 472
Light in lux: 2205
Light in lux: 2204
Light in lux: 2203
Light in lux: 2202

4.А если серьезно. Из метрологии тут есть кто? Фильтры и стекла покрытые матом русским и не только не надо или нет? Кто нибудь с поверенными эти китайчики BH1750 поверял?

art100
Offline
Зарегистрирован: 09.03.2014

sav13 пишет:
... можно линзу...?

Или они только для инфракрасного света нормално прозрачные?

нужно

sav13
sav13 аватар
Онлайн
Зарегистрирован: 17.06.2013

Последний раз сравнивал с Эколайтом

На рассеяном свете показания в рамках погрешности 5%. На точечных исходниках Эколайт показывает больше благодаря сферической линзе над датчиком

Если честно, как то положил рядом три поверенных датчика. У всех показания расходились примерно на 10%

p.s. Люкс это освещенность в точке

Люмен - единица светового потока

Люкс равен освещённости поверхности площадью 1 м² при световом потоке падающего на неё излучения, равном 1 лм.

trembo
trembo аватар
Offline
Зарегистрирован: 08.04.2011

Я обычно в setup вместо бесполезного   Serial.println("Hello World"); вставляю вот это....

  Serial.begin(115200);
  Serial.print(__FILE__);
  Serial.print(F("    "));
  Serial.print(__DATE__);
  Serial.print(F("    "));
  Serial.println(__TIME__);

 

art100
Offline
Зарегистрирован: 09.03.2014

trembo пишет:
...Я...  в setup вместо ..
30nov2014 не кашерненько ;)

20141130;110707;;;;;;; ну под мой классический парс с разделителем посимвольный

а вариантец годмесяц число может без форматирования есть?

Nov 30 2014;11:07:07;BH1750test20141130101100.ino;

Light in lux: 1074
Light in lux: 1072
Light in lux: 1073
Light in lux: 54
Light in lux: 55
Light in lux: 1106
Light in lux: 1079
Light in lux: 1074
Light in lux: 1077
//art100 to write test BH1750-lux ?
#include <Wire.h>
#include <BH1750.h>
//pins----------------------
// VCC-5v
// GND-GND
// SCL-SCL(analog pin 5)
// SDA-SDA(analog pin 4)
// ADD-NC or GND
//consts--------------------
BH1750 lightMeter;
//----------------------------------
void setup(){
  Serial.begin(9600);
  lightMeter.begin();
  Serial.print(__DATE__);Serial.print(F(";"));Serial.print(__TIME__);Serial.print(F(";"));Serial.print(__FILE__);Serial.println(F(";"));//hello from trembo
}
//====================================================
void loop() {
  uint16_t lux = lightMeter.readLightLevel();
  Serial.print("Light in lux: ");  Serial.println(lux);
  delay(1000);
}
//====================================================

sav13 говоришь 5-10% :) 

Фоточка моей чудо линзованой покрытой белым матом с отсутствием наличия поверочек. Слово "поверка" тоже безграмотностью аж воняет но смотрю все метрологи этот термит в выражовывании (проффесианализмы) переводят. Гыг.

тискайте для увеличения фоточки не стесняйтесь :-)

sav13
sav13 аватар
Онлайн
Зарегистрирован: 17.06.2013

art100 пишет:

тискайте для увеличения фоточки не стесняйтесь :-)

Дурацкое расположение выводов в этом датчике
Сразу на Г-образные разъемы перепаивал

Два значения - явный косяк

Или датчик бракованный или библиотека глючит

Какая задержка становлена в датчике?

p.s. Слово "поверка" не воняет безграмотностью а просто отличется от слова "проверка"
 

 

art100
Offline
Зарегистрирован: 09.03.2014

sav13 пишет:

art100 пишет:

тискайте для увеличения фоточки не стесняйтесь :-)

...Два значения - явный косяк...
А у  меня вроде нормально снизу впаял и тыкаю.

Light in lux: 1074
Light in lux: 1072
Light in lux: 1073
Light in lux: 54
Light in lux: 55
Light in lux: 1106
Light in lux: 1079
Light in lux: 1074
Light in lux: 1077

Это не косяк :) это работает хорошо.  Рукой водишь чувствует тени. Там
http://art1.by/0arduino/ киношка во время этих "косяков" валялась. Повеселись http://art1.by/0arduino/video/BH1750.wmv

Andrey_Y_Ostanovsky
Offline
Зарегистрирован: 03.12.2012

Собрал схемку на BH1750 , засветил датчик налобным фонарем - после 20000 люкс пошли нули... :) Видимо где-то переполнение происходит...

sav13
sav13 аватар
Онлайн
Зарегистрирован: 17.06.2013

65535 лк

Нужно посмотреть, что переменная, куда пишется освеженность, uint16_t

Режим измерения 120мс 1лк разрешения

Andrey_Y_Ostanovsky
Offline
Зарегистрирован: 03.12.2012

sav13 пишет:

65535 лк Нужно посмотреть, что переменная, куда пишется освеженность, uint16_t Режим измерения 120мс 1лк разрешения

Скетч Ваш, по ссылке из 1-го поста с минимальными доработками. :) Размерность переменных - точно не трогал...

По даташиту, VCC должно быть 3.3V, а я шилд запитал от 5V, может какая защита срабатывает...

Kolchugin
Offline
Зарегистрирован: 15.12.2013

Здравствуйте sav13

Повторил Ваше устройство (пока на макетной плате), на BH1750. 

Работает отлично! Спасибо Вам.

TevatroN
Offline
Зарегистрирован: 17.11.2013

Вопрос к автору, у которого я понимаю есть поверенные приборы. Я данный датчик хочу подключить к метеостанции для народмон.ру

Сейчас подключил, на улице очень пасмурно, поднося к окну показал 123lx

А на кухне лампа LED, и когда датчик в пол, то показывает 0lx, вспышка на телефоне галакси с3 в упор показывает 54612lx, а на расстоянии около 10 см показывает ~4500 lx, это правильно ил нет?

Если кто спец, как в домашних условиях проверить достоверность, да и в двух словах ликбез если можно о люксах "бенелюксах"

Вот тут библиотека BH1750 которой я пользуюсь:
https://yadi.sk/d/q7SpS243eV8k4
 

sav13
sav13 аватар
Онлайн
Зарегистрирован: 17.06.2013

TevatroN пишет:

Вопрос к автору, у которого я понимаю есть поверенные приборы. Я данный датчик хочу подключить к метеостанции для народмон.ру

Сейчас подключил, на улице очень пасмурно, поднося к окну показал 123lx

А на кухне лампа LED, и когда датчик в пол, то показывает 0lx, вспышка на телефоне галакси с3 в упор показывает 54612lx, а на расстоянии около 10 см показывает ~4500 lx, это правильно ил нет?

Если кто спец, как в домашних условиях проверить достоверность, да и в двух словах ликбез если можно о люксах "бенелюксах"

Вот тут библиотека BH1750 которой я пользуюсь:
https://yadi.sk/d/q7SpS243eV8k4
 

Данные датчики выпускаются откалиброванные на заводе и освещенность их соответсвует тестовым приборам.

Хоть получить 100% совпадения на разных типах не удается. Это относится не только к этому датчику, но и если сравнивать показания двух разеых поверенных приборов.

На самом деле, точность выше 10% не особо нужна.

0лк датчик показывает, так как максимальное значение его 16Клюкс ли 32Клюкс (в разных режимах)

Проверки на переполнение у него нет

Некоторые коммерческие приборы использу.т для измерения такой освещенности специальные фильтры, ослабляющие свет в кратное количество раз x10, x100

Andrey_Y_Ostanovsky
Offline
Зарегистрирован: 03.12.2012

sav13 пишет:

Некоторые коммерческие приборы использу.т для измерения такой освещенности специальные фильтры, ослабляющие свет в кратное количество раз x10, x100

Кстати, хорошая мысль: можно же использовать нейтральные светофильтры (ND-фильтры/Graduated lens) с известным коэффициентом ослабления.

Цитата:

Нейтральные фильтры бывают разной плотности, и это указано в названии. Самый светлый – ND2. Цифра в названии означает долю света, которая через фильтр проходит (для ND2 доля равна 1/2, то есть, половина). Более тёмным будет ND4, затем ND8, например. Если вы поставите несколько фильтров подряд, то, чтобы понять, что у вас получилось, надо перемножить цифры всех установленных фильтров. То есть, ND2+ND4=ND8.

TevatroN
Offline
Зарегистрирован: 17.11.2013

sav13 Хочу уточнить, освещенный прямым светом датчик BH1750, ламопчкой 60Вт 230В на расстоянии 1м=100см от колбы, это сколько Люксов?

Ну не может быть отраженный от пола свет на датчике 0 люксов там несколько десятков должно быть.

Я грешу на библиотеку указанную выше в моем посте.

Прошу уменно данную ситуацию лампочка, под ней датчик BH1750 на расстоянии 1м, сколько Люксов?

Andrey_Y_Ostanovsky
Offline
Зарегистрирован: 03.12.2012

TevatroN пишет:

sav13 Хочу уточнить, освещенный прямым светом датчик BH1750, ламопчкой 60Вт 230В на расстоянии 1м=100см от колбы, это сколько Люксов?

Ну не может быть отраженный от пола свет на датчике 0 люксов там несколько десятков должно быть.

Я грешу на библиотеку указанную выше в моем посте.

Прошу уменно данную ситуацию лампочка, под ней датчик BH1750 на расстоянии 1м, сколько Люксов?

Примерно в метре от датчика:

- пыльная лампочка (галогенка в баллоне от обычной) мощностью ~50 Вт - 96 люкс.

- зеркальная лампочка "на прищепке" 60 Вт - 210 люкс

- лестничное освещение (60 Вт в плафонах) 36 люкс.

nick_kr
Offline
Зарегистрирован: 13.12.2014

всем доброго времени суток, а подскажите пожалуйста критичен ли к питанию датчик tsl2561, можно ли его питать от 5 вольт? как правильно его подключить к 5 ввольтовой  ардуино нано?

sav13
sav13 аватар
Онлайн
Зарегистрирован: 17.06.2013

По даиашиту TSL2561:
Питание: 2.7 - 3.6В
Логическая 1: 2.1 - 3.6В
Логическая 0: -0.5 - 0.8В

То есть работают от 3В логики, но некоторые модули, например такой имеют на борту встроенный преобразователь уровня логики и питания и могут нормально запитываться от 5В

Если модуль не имеет такого стабилизатора, то подключать его нужно через преобразователь логического уровня и питать от 3.3.В ноги Arduino.

 

nick_kr
Offline
Зарегистрирован: 13.12.2014

sav13 пишет:
По даиашиту ...

Благодарю, паралельно сам искал ответы на свои вопросы.

На адафруит нашёл информацию о том что новые партии модулей толерантны к логическому уровню в 5В, и могут так же питаться от 5В https://learn.adafruit.com/tsl2561/wiring 

При более внимательном рассмотрении модуля http://ru.aliexpress.com/store/product/5pcs-lot-GY-2561-TSL2561-Light-module/403088_32272911986.html был замечен регулятор питания http://www.mikrocontroller.net/attachment/193855/LM6206N3.pdf

Такой же регулятор стоит на барометре bmp180 который отлично работает с 5В.

Вечером буду пробовать подключить вышеупомянутый модуль и выводить информацию на 0,96 олед дисплейчик.

nick_kr
Offline
Зарегистрирован: 13.12.2014

подключил модуль и экранчик, но вот с кодом немного беда, не показывает уровень пульсации. за основу брался код от sav13 и стандартный от микродуино. может кто подскажет в чем проблема?

#include <Adafruit_GFX.h>
#include <Adafruit_PCD8544.h>

#include "U8glib.h"

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_TSL2561_U.h>

#define MAX_UNITS  84 

Adafruit_TSL2561_Unified tsl = Adafruit_TSL2561_Unified(TSL2561_ADDR_FLOAT, 12345);

float sensor_lux=0.00;

U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE);        // HW SPI Com: CS = 10, A0 = 9 (Hardware Pins are  SCK = 13 and MOSI = 11)
//U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_DEV_0|U8G_I2C_OPT_NO_ACK|U8G_I2C_OPT_FAST);
//show speed
void draw() {
  /*
  u8g.setFont(u8g_font_courB18);//font
  u8g.setPrintPos(0, 16);
  u8g.print("Light intensity");
  u8g.setPrintPos(0, 50);
  u8g.print(sensor_lux);
  u8g.print("LUX");
  */
 
boolean DebugFlag = true;


int key_count          = 0; 


int disp_interval      = 3000;

uint16_t l1=0,l2=0,l_min=0,l_max=0;
uint32_t l_avg = 0;
uint16_t u1    = 0;
double pulse   = 0;
uint16_t l_mas[MAX_UNITS];
uint16_t l_pos = 0;
  
  
  
   sensors_event_t event;
   tsl.getEvent(&event);
   l1 = event.light;
   if( l_pos == 0 ){
      l2 = l_avg / MAX_UNITS;
      if( l_max != 0 )pulse = (double)((l_max - l_min))*100/(double)l_max;
      else pulse = 0; 
      l_min = l1;
      l_max = l1;
      l_avg = 0;
   }
   l_mas[l_pos++] = l1;
   l_avg += l1;
   if( event.light < l_min )l_min = l1;
   if( event.light > l_max )l_max = l1;
   if( l_pos >= MAX_UNITS )l_pos = 0;
   
   
  
 u8g.setFont(u8g_font_courB12);
 u8g.setPrintPos(0, 10);
 u8g.print("l_min(lx)=");u8g.print(l_min);
 
  

u8g.setPrintPos(0, 25);
      u8g.print("l_max(lx)="); u8g.print(l_max);

                

      u8g.setPrintPos(0, 40);
      u8g.print("l1(lx)=");u8g.print(l1);
     u8g.setPrintPos(0, 55); 
     u8g.print("pulse(%)=");u8g.print(pulse,1);
  
}  

void setup()
{
  Serial.begin(9600);
  Serial.println(tsl.begin() ? "TSL2561 connection successful" : "TSL2561 connection failed");
tsl.setIntegrationTime(TSL2561_INTEGRATIONTIME_13MS);

}
 
 void loop()
{
    sensors_event_t event;
  tsl.getEvent(&event);
  
  
  
    /* Display the results (light is measured in lux) */
 if (event.light)
 sensor_lux=event.light;
      
    
  
  u8g.firstPage();  
  do {
    draw();
  } 
  while( u8g.nextPage() ); 
  delay(2);
}

 

sav13
sav13 аватар
Онлайн
Зарегистрирован: 17.06.2013

А что мешает сделать код как у автора?

Сперва мерим 84 раза освещенность

      for( int i=0; i<MAX_UNITS; i++){
         tsl.getEvent(&event);
         l_avg += event.light;
         l_mas[i] = event.light;
         if( i == 0 ){
            l_min = event.light;
            l_max = event.light;
         }
         else {
            if( event.light < l_min )l_min = event.light;
            if( event.light > l_max )l_max = event.light;
         }
      } 
      l1 = l_avg / MAX_UNITS;
      if( l_max != 0 )pulse = (double)((l_max - l_min))*100/(double)l_max;
      else pulse = 0; 

А потом выводим в виде показаний или графиком

 

nick_kr
Offline
Зарегистрирован: 13.12.2014

Благодарю, вроди бы как разобрался

sav13 пишет:
А что мешает сделать код как у автора?

мне не нужны графики, режимы сна и т.д. необходимо только знать значение освещенности и пульсации.

отдельного прибора как такового не будет, просто макетка с дуиной датчиком и экраном

 

Roman_Anatolievich
Offline
Зарегистрирован: 08.11.2015

подскажите возможно ли на вашем люксметре измерять освещенность равную 0,01 лк или даже ниже?

заранее спасибо

Roman_Anatolievich
Offline
Зарегистрирован: 08.11.2015

подскажите возможно ли на вашем люксметре измерять освещенность равную 0,01 лк или даже ниже?

заранее спасибо

sav13
sav13 аватар
Онлайн
Зарегистрирован: 17.06.2013

Нет, так как используемы датчики работают от 0.5лк

Нужно брать какой-нибудь фотодиод/фототранзистор, подключать его через усилитель к аналоговому входу и калибровать.

 

Roman_Anatolievich
Offline
Зарегистрирован: 08.11.2015

а как именно калибровать?

 

sav13
sav13 аватар
Онлайн
Зарегистрирован: 17.06.2013

Берете эталонный люксометр и по нему устанавливаете контрольные точки 

karl2233
karl2233 аватар
Offline
Зарегистрирован: 05.07.2015

вопрос - какие фузы выставлять? можно скрин для ПониПрог?  

satman123
Offline
Зарегистрирован: 11.02.2016

Добрый день

При компиляции luxsometr2 ругается на Adafruit_Sensor.h

Прошу не пинать чайника :) я только учусь

sav13
sav13 аватар
Онлайн
Зарегистрирован: 17.06.2013
karl2233
karl2233 аватар
Offline
Зарегистрирован: 05.07.2015

при компиляции вылетает:

luxometr_v1.1.ino: In function 'void PowerOn()':
luxometr_v1.1:75: error: 'class Adafruit_TSL2561_Unified' has no member named 'enableAutoGain'
'class Adafruit_TSL2561_Unified' has no member named 'enableAutoGain'
 
вроде все библиотеки поставил.
но как только удаляю строку 75 из авторского скетча
 tsl.enableAutoGain(true);          /* Auto-gain ... switches automatically between 1x and 16x */

компилируется о_О проверить пока не могу - нет сенсора ещё :/

с этим вроде разобрался(спасибо snag)  - надо заменить 75 строку на это

tsl.enableAutoRange

 

upd.

главныt вопросы:

1. как запустить? не работатет ни в какую :( экран девственно чист. правда подключаю без датчика.

2. как упростить скетч? оставив только функции измерения, убрав всё лишнее?

вот авторский скетч, изменил только tsl.enableAutoGain(true) и установил контраст в виде константы.

#include <avr/sleep.h>
#include <avr/power.h>
// Библиотеки для работы с дисплеем 5110
#include <Adafruit_GFX.h>
#include <Adafruit_PCD8544.h>
// Библиотека работы с устройствами по I2C
#include <Wire.h> 
// Библиотека работы с TSL2561
#include <Adafruit_Sensor.h>
#include <Adafruit_TSL2561_U.h>
 
#define MAX_UNITS  84 

// pin 4  - Serial clock out (SCLK)
// pin 5  - Serial data out (DIN)
// pin 6  - Data/Command select (D/C)
// pin 7  - LCD chip select (CS)
// pin 10 - LCD reset (RST)
Adafruit_PCD8544 display = Adafruit_PCD8544(4, 5, 6, 7, 10);
Adafruit_TSL2561_Unified tsl = Adafruit_TSL2561_Unified(TSL2561_ADDR_FLOAT, 12345);

boolean DebugFlag = true;

int key_count          = 0; 
boolean key_press      = false;

int disp_interval      = 1000;

uint16_t l1=0,l2=0,l_min=0,l_max=0;
uint32_t l_avg = 0;
uint16_t u1    = 0;
double pulse   = 0;
uint16_t l_mas[MAX_UNITS];
uint16_t l_pos = 0;

volatile unsigned long key_time  = 0;
volatile unsigned long key_time2 = 0;
boolean power_on            = false;
boolean light_on            = true;

volatile boolean int_key    = false;
volatile boolean int_key2   = false;
int key_mode2               = 1;



/**
* Функция определения напряжения питания устройства
*/
static int vccRead(byte us =250) {
  ADMUX = 1<<REFS0; // опорное напряжение - Vcc
  ADMUX |= 0x0E;    // объект измерения - внутренний источник
                    // стабилизированного напряжения 1.1В
  delayMicroseconds(us);
 
  ADCSRA |= 1<<ADSC;         // запуск АЦ-преобразования
  while(ADCSRA & (1<<ADSC)); // и ожидание его завершения
  word x = ADC;
  return x ? (1100L * 1023) / x : -1;
}

/**
* Функция инициализации при включении питания 
*/
void PowerOn(){
  power_on = true;
  digitalWrite(8,HIGH);       //  Питание периферии
  digitalWrite(9,light_on);   // Подсветка
  digitalWrite(13,HIGH);      // power LED on
  Wire.begin();
  tsl.begin();
  tsl.enableAutoRange(true);  // Auto-gain ... switches automatically between 1x and 16x было это tsl.enableAutoGain
  display.setContrast(65);

 // u1 = vccRead(100);
 // uint16_t c1=28;
 // if( u1 < 3500 )c1 = 44;
  //else if( u1 > 4700 )c1=25;
//  float contrast = 123.2308 - (float)u1*0.021538;
  //if( DebugFlag ){
  //   Serial.print("Contrast=");
  //   Serial.println(u1);
  //   Serial.println(",");
  //   Serial.println(c1);
  //}

  //display.begin();
  //display.setContrast(c1);
}

/**
* Функция выключение всех устройств при переходе в POWER_DOWN моде
*/
void PowerOff(){
// Отключаем все выходы 3-19
  power_on = false;
  for( int i=4; i<20; i++ ){
     pinMode(i,INPUT_PULLUP); 
     digitalWrite(i,LOW);  
  }
}

/**
* Функция обраюотчик прерывания на кнопку питания 
*/
void intKey()
{
  int_key   = true;
  key_time  = millis();
  detachInterrupt(0); //Отключаем прерывания 
}

/**
* Функция обраюотчик прерывания на кнопку mode 
*/
void intKey2()
{
  int_key2  = true;
  key_time2 = millis();
  detachInterrupt(1); //Отключаем прерывания 
}


/**
* Функия перевода ARDUINO в POWER_DOWN режим
*/
void EnterSleep()
{
  DebugPrint("I am sleeping");
  PowerOff();
  attachInterrupt(0, intKey, LOW); //Если на 0-вом прерываниии - ноль, то просыпаемся.
  power_on = false;
  delay(100);
  set_sleep_mode(SLEEP_MODE_PWR_DOWN); //Определяем режим сна
  
  sleep_enable(); //Разрешаем спящий режим
  sleep_mode(); //Спим (Прерывания продолжают работать.) Программа останавливается.
  sleep_disable(); //Запрещаем спящий режим
}

/**
* Выдача отладочной строки на экран
*/
void DebugPrint( char *msg ){
   if( DebugFlag )Serial.println(msg);
} 

/**
* Выдача на дисплей в режиме 1
*/
void DisplayMode1(){ 
   if( DebugFlag ){
      Serial.print("l_min(lx)=");
      Serial.print(l_min);
      Serial.print(",l_max(lx)=");
      Serial.print(l_max);
      Serial.print(",l1(lx)=");
      Serial.print(l1);
      Serial.print(",pulse(%)=");
      Serial.print(pulse,1);
      Serial.print(",Vcc (mV)=");
      Serial.println(u1);
  }
  
   display.clearDisplay();
   display.setTextSize(2);
   display.setCursor(0,0);
   display.print(l1);
   display.setTextSize(1);
   display.println(" Lx");
   display.println("");
   display.println("");
   display.print("Pulse: ");
   display.print(pulse,1);
   display.println("%");
   display.print("Bat: ");
   display.print(u1/1000);
   display.print(".");
   display.print((u1/100)%10);
   display.println(" V");
   display.display(); 
} 

/**
* Выдача на дисплей в режиме 2 (график)
*/
void DisplayMode2(){ 
   if( DebugFlag ){
      Serial.print("l_min(lx)=");
      Serial.print(l_min);
      Serial.print(",l_max(lx)=");
      Serial.print(l_max);
      Serial.print(",l1(lx)=");
      Serial.print(l1);
      Serial.print(",pulse(%)=");
      Serial.print(pulse,1);
      Serial.print(",Vcc (mV)=");
      Serial.println(u1);
  }
  
  
   display.clearDisplay();
   display.setTextSize(1);
   display.setCursor(0,0);
   display.print(l1);
   display.print(" Lx. ");
   display.print(pulse,1);
   display.println("%");
 
   uint16_t dl = l_max - l_min;
   display.drawLine(0, 45, 84, 45 , BLACK);
   display.drawLine(78, 43, 84, 45 , BLACK);
   display.drawLine(78, 47, 84, 45 , BLACK);
   for( int i=0; i<MAX_UNITS/3; i++){
      uint16_t y1 = 44-(l_max-l_mas[i])*28/dl;
      uint16_t y2 = 44-(l_max-l_mas[i+1])*28/dl;
      display.drawLine(i*3, y1, i*3+3, y2, BLACK);
   }  
   
   display.display();
} 

/**
* Выдача га экран в режиме 3 (максимальное качество)
*/
void DisplayMode3(){ 
   if( DebugFlag ){
      Serial.print(",Light (lx)=");
      Serial.print(l1);
      Serial.print(",Vcc (mV)=");
      Serial.println(u1);
   }
   display.clearDisplay();
   display.setTextSize(2);
   display.setCursor(0,0);
   display.print(l1);
   display.setTextSize(1);
   display.println(" Lx");
   display.println("");
   display.println("Max Quality");
   display.println("");
   display.print("Bat: ");
   display.print(u1/1000);
   display.print(".");
   display.print((u1/100)%10);
   display.println(" V");
   display.display(); 
} 


/**
* Переключение режимов люксометра
*/
void SwitchMode(){
   switch( key_mode2 ){
      case 1  :
         key_mode2     = 2;
         disp_interval = 3000;
         DisplayMode2();
         tsl.setIntegrationTime(TSL2561_INTEGRATIONTIME_13MS);
         break;
      case 2  :
         key_mode2     = 3;
         disp_interval = 1000;
         DisplayMode3();
         tsl.setIntegrationTime(TSL2561_INTEGRATIONTIME_402MS);      
         break;
      case 3  :
         key_mode2     = 1;
         disp_interval = 1000;
         DisplayMode1();
         tsl.setIntegrationTime(TSL2561_INTEGRATIONTIME_13MS);
         break;
      default :
         key_mode2 = 1;  
   }

}
 
/**
* Включение/выключение подсветки
*/
void SwitchLight(){
   light_on = !light_on;
   digitalWrite(9,light_on);   // Подсветка
}
 
 
 
void setup()
{
   if( DebugFlag ){
      Serial.begin(9600);
      Serial.println("Start luxmetr");
   }
   pinMode(13,OUTPUT);      // Светодиод питания
   pinMode(9,INPUT_PULLUP); // Выход на подсветку дисплея
   pinMode(8,INPUT_PULLUP); // Выход на питание дисплея

   analogRead(0);           // Порт для измерения напряжения питания по внутреннему источнику
   pinMode(2, INPUT_PULLUP);// Порт кнопки питания 
   pinMode(3, INPUT_PULLUP);// Порт кнопки питания 

   attachInterrupt(0, intKey,  LOW); //Если на 0-вом прерываниии - ноль, то просыпаемся.
   attachInterrupt(1, intKey2, LOW); //Если на 1-вом прерываниии - ноль, то просыпаемся.
   EnterSleep();            // Идем спать
 
}
 
unsigned long ms1 = 0; 
 
void loop()
{
   unsigned long ms = millis();
// Спаботало прерывание нажатия кнопки
   if( int_key ){
      delay(100);
// Кнопка отпущена
      unsigned int key_interval = 0;
      key_interval = abs(ms - key_time);
      if( digitalRead(2) == HIGH ){
         if( power_on && key_interval > 1500 ){
            DebugPrint("Power off");
            EnterSleep();
         }  
         else if( !power_on && key_interval < 1500 ){
            DebugPrint("Sleep again");
            EnterSleep();
         }
         else if( key_interval>1500 ){
           DebugPrint("Power on");
           PowerOn();
         }  
         else {
           SwitchLight();
          }

        if( DebugFlag ){
            Serial.print("Press PWR (");
            Serial.print(key_interval);
            Serial.print("ms), power=");
            Serial.print(power_on);
            Serial.print(", light=");
            Serial.println(light_on);
         }
// Заряжаем прерывание по новой
         int_key   = false;
         attachInterrupt(0, intKey, LOW); //Если на 0-вом прерываниии - ноль, то просыпаемся.
      }
   }

 
 // Сработало прерывание нажатия кнопки MODE
   if( int_key2 ){
      delay(100);
// Кнопка отпущена
      if( digitalRead(3) == HIGH ){
        SwitchMode();
        if( DebugFlag ){
            unsigned int key_interval2 = 0;
            key_interval2 = abs(ms - key_time2);
            Serial.print("Press MODE (");
            Serial.print(key_interval2);
            Serial.print("ms), mode=");
            Serial.println(key_mode2);
         }
// Заряжаем прерывание по новой
         int_key2   = false;
         attachInterrupt(1, intKey2, LOW); //Если на 1-вом прерываниии - ноль, то просыпаемся.
      }
   }
 
   
// Выдача картинки на дисплей в зависимости от режима
   if( (ms < ms1 || (ms - ms1) > disp_interval)&&power_on ){
      ms1 = ms;
      u1 = vccRead(100);
      if( key_mode2 == 1 )DisplayMode1();
      else if( key_mode2 == 2 )DisplayMode2();
      else if( key_mode2 == 3 )DisplayMode3();
   }
   
// Опрос датчика освещенности 
   sensors_event_t event;
   tsl.getEvent(&event);
   l1 = event.light;
   if( l_pos == 0 ){
      l2 = l_avg / MAX_UNITS;
      if( l_max != 0 )pulse = (double)((l_max - l_min))*100/(double)l_max;
      else pulse = 0; 
      l_min = l1;
      l_max = l1;
      l_avg = 0;
   }
   l_mas[l_pos++] = l1;
   l_avg += l1;
   if( event.light < l_min )l_min = l1;
   if( event.light > l_max )l_max = l1;
   if( l_pos >= MAX_UNITS )l_pos = 0;
 
}

 

karl2233
karl2233 аватар
Offline
Зарегистрирован: 05.07.2015

коллеги, помогите упростить авторский проект.

а то у меня ничего не получается ((( надо бы при включениии начинал измерять, а по нажатию одной кнопки что б Люксомер перебирал три варината вывода инф на экран, безо всяких спящих режимов.

ну или подскажите куда копать.

пока смог сделать так(выводит один экран(остальные закоментил пока) но в левлм углу откуда-то большая буква "Q" вылезла.


// Библиотеки для работы с дисплеем 5110
#include <Adafruit_GFX.h>
#include <Adafruit_PCD8544.h>
// Библиотека работы с устройствами по I2C
#include <Wire.h> 
// Библиотека работы с TSL2561
#include <Adafruit_Sensor.h>
#include <Adafruit_TSL2561_U.h>
#define MAX_UNITS  84 

// pin 7  - Serial clock out (SCLK)
// pin 6  - Serial data out (DIN)
// pin 5  - Data/Command select (D/C)
// pin 4  - LCD chip select (CS)
// pin 10 - LCD reset (RST)
Adafruit_PCD8544 display = Adafruit_PCD8544(2, 3, 4, 6, 7);
Adafruit_TSL2561_Unified tsl = Adafruit_TSL2561_Unified(TSL2561_ADDR_FLOAT, 12345);
byte cont = 65;
int buttonState = 0;
const int buttonPin = 5;     // номер входа, подключенный к кнопке
void setup() {
  Serial.begin(9600);
  display.begin();
  Wire.begin();
  tsl.begin();
  tsl.enableAutoRange(true);          /* Auto-gain ... switches automatically between 1x and 16x */
  display.setContrast(cont);
  
// инициализируем пин, подключенный к кнопке, как вход
  pinMode(buttonPin, INPUT); 
 
// переменные
  
  }
uint16_t l1=0,l2=0,l_min=0,l_max=0;
uint32_t l_avg = 0;
uint16_t u1    = 0;
double pulse   = 0;
uint16_t l_mas[MAX_UNITS];
uint16_t l_pos = 0;

/**
* Выдача на дисплей в режиме 1
*/
void loop()
{
   display.clearDisplay();
   buttonState = digitalRead(buttonPin);
   

   if(buttonState == HIGH){
    display.clearDisplay();
      display.print(",Light (lx)=");
      display.print(l1);
      display.print(",Vcc (mV)=");
      display.print(u1);
   
   display.clearDisplay();
   display.setTextSize(2);
   display.setCursor(0,0);
   display.print(l1);
   display.setTextSize(1);
   display.println(" Lx");
   display.println("");
   display.println("Max Quality");
   display.println("");
   display.print("Bat: ");
   display.print(u1/1000);
   display.print(".");
   display.print((u1/100)%10);
   display.println(" V");
   display.display(); 
   }
   if(buttonState == LOW){  
     display.clearDisplay();
      display.print("l_min(lx)=");
      display.print(l_min);
      display.print(",l_max(lx)=");
      display.print(l_max);
      display.print(",l1(lx)=");
      display.print(l1);
      display.print(",pulse(%)=");
      display.print(pulse,1);
      display.print(",Vcc (mV)=");
      display.println(u1);
  
  
   display.clearDisplay();
   display.setTextSize(2);
   display.setCursor(0,0);
   display.print(l1);
   display.setTextSize(1);
   display.print(" Lx");
   display.print("");
   display.print("");
   display.print("Pulse: ");
   display.print(pulse,1);
   display.println("%");
   display.print("Bat: ");
   display.print(u1/1000);
   display.print(".");
   display.print((u1/100)%10);
   display.println(" V");
   display.display(); 
  
 
}

/**
* Выдача на дисплей в режиме 2 (график)
*/
/*void DisplayMode2(){ 
   if( DebugFlag ){
      Serial.print("l_min(lx)=");
      Serial.print(l_min);
      Serial.print(",l_max(lx)=");
      Serial.print(l_max);
      Serial.print(",l1(lx)=");
      Serial.print(l1);
      Serial.print(",pulse(%)=");
      Serial.print(pulse,1);
      Serial.print(",Vcc (mV)=");
      Serial.println(u1);
  }
  
  
   display.clearDisplay();
   display.setTextSize(1);
   display.setCursor(0,0);
   display.print(l1);
   display.print(" Lx. ");
   display.print(pulse,1);
   display.println("%");
 
   uint16_t dl = l_max - l_min;
   display.drawLine(0, 45, 84, 45 , BLACK);
   display.drawLine(78, 43, 84, 45 , BLACK);
   display.drawLine(78, 47, 84, 45 , BLACK);
   for( int i=0; i<MAX_UNITS/3; i++){
      uint16_t y1 = 44-(l_max-l_mas[i])*28/dl;
      uint16_t y2 = 44-(l_max-l_mas[i+1])*28/dl;
      display.drawLine(i*3, y1, i*3+3, y2, BLACK);
   }  
   
   display.display();
}
*/

/**
* Выдача га экран в режиме 3 (максимальное качество)
*/
/*
void DisplayMode3(){ 
   if(buttonState == LOW){
      Serial.print(",Light (lx)=");
      Serial.print(l1);
      Serial.print(",Vcc (mV)=");
      Serial.println(u1);
   }
   display.clearDisplay();
   display.setTextSize(2);
   display.setCursor(0,0);
   display.print(l1);
   display.setTextSize(1);
   display.println(" Lx");
   display.println("");
   display.println("Max Quality");
   display.println("");
   display.print("Bat: ");
   display.print(u1/1000);
   display.print(".");
   display.print((u1/100)%10);
   display.println(" V");
   display.display(); 
} 
*/

/**
* Переключение режимов люксометра
*/
/*void SwitchMode(){
   switch( key_mode2 ){
      case 1  :
         key_mode2     = 2;
         disp_interval = 3000;
         DisplayMode2();
         tsl.setIntegrationTime(TSL2561_INTEGRATIONTIME_13MS);
         break;
      case 2  :
         key_mode2     = 3;
         disp_interval = 1000;
         DisplayMode3();
         tsl.setIntegrationTime(TSL2561_INTEGRATIONTIME_402MS);      
         break;
      case 3  :
         key_mode2     = 1;
         disp_interval = 1000;
         DisplayMode1();
         tsl.setIntegrationTime(TSL2561_INTEGRATIONTIME_13MS);
         break;
      default :
         key_mode2 = 1;  
   }

}
 */
 
 

   
  
// Опрос датчика освещенности 
   sensors_event_t event;
   tsl.getEvent(&event);
   l1 = event.light;
   if( l_pos == 0 ){
      l2 = l_avg / MAX_UNITS;
      if( l_max != 0 )pulse = (double)((l_max - l_min))*100/(double)l_max;
      else pulse = 0; 
      l_min = l1;
      l_max = l1;
      l_avg = 0;
   }
   l_mas[l_pos++] = l1;
   l_avg += l1;
   if( event.light < l_min )l_min = l1;
   if( event.light > l_max )l_max = l1;
   if( l_pos >= MAX_UNITS )l_pos = 0;
 
}
karl2233
karl2233 аватар
Offline
Зарегистрирован: 05.07.2015

пришел датчик, подключаю - не алё (((

уже пины дисплея менял по всякому.

питание на дисплей и датчик подаю напрямую, без транзисторов.

мож кто подскажет что не так? скетч из поста 46.

в мониторе последовательного порта чёт происходит - включается, пишет про режимы.

запустил скетч из поста 12(индикатор там не правильно указан, надо вот так:

.// pin 3 - Serial clock out (SCLK)

// pin 4- Serial data out (DIN)

// pin 5 - Data/Command select (D/C)
// pin 6 - LCD chip select (CS)
// pin 7 - LCD reset (RST)

появился текст на экране, но он налазит сам на себя %)

 

satman123
Offline
Зарегистрирован: 11.02.2016

Доброе время суток

получил моник решил проэкспериментировать

все сторонние тесты на ура

при заливке данно скетча при отключённом датчике эффект "0"

на какой версии программы ардуино вы сидите?

sav13 - где наша глобальная ошибка?

satman123
Offline
Зарегистрирован: 11.02.2016

кстати датчик отдельно работает на ура - в соседней ветке скетч

моник отдельно так же пашет

а вот в связке - есть засада