Досветка в теплице.

zsm@nxt.ru
Offline
Зарегистрирован: 27.05.2013

Здравствуйте уважаемые форумчане)



Решил для знакомого собрать устройство для досветки в теплице.

Задача максимально проста и банальна - включать натриевые лампы когда становится пасмурно.

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

Видится многократная проверка условия y+x>100 , но не понимаю как это сделать :(

да и в правильном ли направлении я двигаюсь тоже не понятно..



Буду рад любым советам и предложениям)

Так же интересны рекомендации по удешевлению устройства, думаю использовать более дешевый 

микроконтроллер. Подойдёт ли для этих целей attiny13 например? просто 328atmega слишком расточительно для таких целей использовать.

#define SENSOR_PIN A5//фоторезистор
    #define VAR_REZ A0// чувствительность
    int led = 13;
    int ledState = LOW; 
   
    void setup()
    {
    Serial.begin(9600);
    pinMode(led, OUTPUT);
    }
   
    void loop()
   
     
    {
     
      delay (1000) ;
     
      int lightLevel = analogRead(SENSOR_PIN);
      int sensitivity = analogRead(VAR_REZ);
      int y = map(lightLevel,0,1023,1,100) ;
      int x = map(sensitivity,31,955,1,100) ;
      Serial.println(y);
      Serial.println(x);
      Serial.println(lightLevel);
      Serial.println(sensitivity);
   
     
    if  (y+x>100 && ledState == HIGH )
   
    {
      ledState = LOW;
      digitalWrite(led, ledState);
    }
     
     
     
      if  (y+x<100 && ledState == LOW )
     
     
    {
      ledState = HIGH;
      digitalWrite(led, ledState);
    }
     
   
     
    }

 

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

1. тиньки вполне хватит, или atmega8 тоже недорого

2. можно поставить 2-3 фоторезистора в разных точках

а в сериал обязательно отправлять?

можно еще удешевить. поставьте компаратор и регулируйте уроверь сколько хотите. функции кроме отправки в сериал теже. хотя и тинька дешевая

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

zsm@nxt.ru пишет:

Видится многократная проверка условия y+x>100 , но не понимаю как это сделать :(

Надо вводить понятие "время" и по первому срабатыванию условия - взводить какую-нибудь переменную X. После чего отсчитываем время и если переменная не изменилась - то считаем, что "стемнело", если изменилась - обнуляем переменную X.

zsm@nxt.ru
Offline
Зарегистрирован: 27.05.2013

Спасибо всем за ответы. Накидал код , делает всё что надо но как то по дилетански получилось и расточительно к ресурсам....

думаю как бы красиво сделать :)

 

 #define SENSOR_PIN A5
    #define VAR_REZ A0
    int latency=1000;
    int led = 13;
    int ledState = LOW;
    int average = 0;
    int a=0;
    int b=0;
    int c=0;
    int d=0;
    int e=0;
    int f=0;
    int g=0;
    int h=0;
    int i=0;
    int j=0;   
    
    void setup()
    {
     Serial.begin(9600);
     pinMode(led, OUTPUT);
    }
     
    void loop()
    
      
     {
      
      delay (latency) ;
      
      int lightLevel = analogRead(SENSOR_PIN);
      int sensitivity = analogRead(VAR_REZ);
      int y = map(lightLevel,0,1023,1,100) ;
      int x = map(sensitivity,31,955,1,100) ;
      int a=(x+y);
      Serial.println("a");
      Serial.println(a);
      
      delay (latency) ;
      
      lightLevel = analogRead(SENSOR_PIN);
      sensitivity = analogRead(VAR_REZ);
      y = map(lightLevel,0,1023,1,100) ;
      x = map(sensitivity,31,955,1,100) ;
      int b=(x+y);
      Serial.println("b");
      Serial.println(b);
      
      delay (latency) ;
      
      lightLevel = analogRead(SENSOR_PIN);
      sensitivity = analogRead(VAR_REZ);
      y = map(lightLevel,0,1023,1,100) ;
      x = map(sensitivity,31,955,1,100) ;
      int c=(x+y);
      Serial.println("c");
      Serial.println(c);
      
      delay (latency) ;
      
      lightLevel = analogRead(SENSOR_PIN);
      sensitivity = analogRead(VAR_REZ);
      y = map(lightLevel,0,1023,1,100) ;
      x = map(sensitivity,31,955,1,100) ;
      int d=(x+y);
      Serial.println("d");
      Serial.println(d);
      
      delay (latency) ;
      
      lightLevel = analogRead(SENSOR_PIN);
      sensitivity = analogRead(VAR_REZ);
      y = map(lightLevel,0,1023,1,100) ;
      x = map(sensitivity,31,955,1,100) ;
      int e=(x+y);
      Serial.println("e");
      Serial.println(e);
      
      delay (latency) ;
      
      lightLevel = analogRead(SENSOR_PIN);
      sensitivity = analogRead(VAR_REZ);
      y = map(lightLevel,0,1023,1,100) ;
      x = map(sensitivity,31,955,1,100) ;
      int f=(x+y);
      Serial.println("f");
      Serial.println(f);
      
      delay (latency) ;
      
      lightLevel = analogRead(SENSOR_PIN);
      sensitivity = analogRead(VAR_REZ);
      y = map(lightLevel,0,1023,1,100) ;
      x = map(sensitivity,31,955,1,100) ;
      int g=(x+y);
      Serial.println("g");
      Serial.println(g);
      
      delay (latency) ;
      
      lightLevel = analogRead(SENSOR_PIN);
      sensitivity = analogRead(VAR_REZ);
      y = map(lightLevel,0,1023,1,100) ;
      x = map(sensitivity,31,955,1,100) ;
      int h=(x+y);
      Serial.println("h");
      Serial.println(h);
      
      delay (latency) ;
      
      lightLevel = analogRead(SENSOR_PIN);
      sensitivity = analogRead(VAR_REZ);
      y = map(lightLevel,0,1023,1,100) ;
      x = map(sensitivity,31,955,1,100) ;
      int i=(x+y);
      Serial.println("i");
      Serial.println(i);
      
      delay (latency) ;
      
      lightLevel = analogRead(SENSOR_PIN);
      sensitivity = analogRead(VAR_REZ);
      y = map(lightLevel,0,1023,1,100) ;
      x = map(sensitivity,31,955,1,100) ;
      int j=(x+y);
      Serial.println("j");
      Serial.println(j);
      
      delay (latency) ;
      
      
      
      
      
      Serial.println("*********");
      
      average = (a+b+c+d+e+f+g+h+i+j)/10;
      
      Serial.print("average-");
      Serial.println(average);
      
      Serial.println("*********");
      
      
      
    if  (average>100 && ledState == HIGH )  
      
    {
    ledState = LOW; 
    digitalWrite(led, ledState);
    } 
      
  
    if  (y+x<100 && ledState == LOW ) 
    {
    ledState = HIGH;
    digitalWrite(led, ledState);
    }
  
  
  
 
 
 
   }

 

zsm@nxt.ru
Offline
Зарегистрирован: 27.05.2013

в сериал не обязательно , это для настройки только..

для тиньки код жырный очень получается, пока только в atmega8 поместится)

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Такие вещи можно делать с помощью расчета среднего (плавающим окном) и с отсеиванием изменений значений больше какой то величины (т.е. если встретится значение, которое больше или меньше текущего среднего, допустим, на 50, то пропускаем такой отсчет и не берем в учет), тогда всё будет включаться/выключаться плавно и с гистерезисом. Такой вариант и в тиньку возможно войдет, там немного.

 

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

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

#define photo A1                      //вывод для фоторезистора
#define led 13                        //вывод для светодиода
#define numb 20                       //количество значений для вычисления среднего, не более 32!
#define porog 700                     //порог срабатывания
#define zaderzka 60000                //задержка между измерениями

int mass[numb];                       //массив для значений

void setup(){
  pinMode(photo, INPUT);
  pinMode(led, OUTPUT);
  int n = analogRead(photo);
  for(int i=0;i<numb;i++){           //заполним все элементы массива текущим значением
    mass[i] = n;
  }
}
void loop(){
  for(int i=0;i<numb-1;i++){         //смещаем элементы. 0 заменяется первым
    mass[i] = mass[i+1];
  }
  mass[numb-1] = analogRead(photo);  //последний элемент считываем с порта
  
  int sredn = 0;                     //среднее значение
  for(int i=0;i<numb;i++){           //суммируем все значения
    sredn = sredn + mass[i];
  }
  sredn = sredn/numb;
  
  if (sredn <= porog){               //проверяем темно или светло
    digitalWrite(led, HIGH);
  }
  else{
    digitalWrite(led, LOW);
  }
  
  delay(zaderzka);                   //ждем заданное время
}

на тиньке еще много места

zsm@nxt.ru
Offline
Зарегистрирован: 27.05.2013

Большое спасибо что уделили время, хорошее решение, а главное компактное)

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

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

void setup(){
  pinMode(photo, INPUT);
  pinMode(led, OUTPUT);
  delay(10000);                      //задержка 10с для момента установки и включения устройства
  int n = analogRead(photo);
  for(int i=0;i<numb;i++){           //заполним все элементы массива текущим значением
    mass[i] = n;
  }
}

 

toc
Offline
Зарегистрирован: 09.02.2013

Коллеги, давайте, по возможности, и добровольно экономить электричество. Например, тут, наверняка, можно на минуту перейти в спящий режим:

>> 36: delay(zaderzka);

раньше на компах был логотип об этом "energy star epa" 

 

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

давайте. я честно сказать еще не знаю как это делается. можно и вырубить на минуту

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

Клапауций
Offline
Зарегистрирован: 10.02.2013

toc пишет:

Коллеги, давайте, по возможности, и добровольно экономить электричество. Например, тут, наверняка, можно на минуту перейти в спящий режим:

>> 36: delay(zaderzka);

раньше на компах был логотип об этом "energy star epa" 

блок питания поддерживает модную функцию? - если "нет", то смысл?

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

тоже верно. тинька есть так мало что даже если загнать в спящий блок питания почти столько же потреблять будет

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

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

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

Неправильно вы дядя Фёдор среднее считаете....

averageWaterTemp= (averageWaterTemp*9 + waterTemp)/10;

Причём числа 9 и 10 могут быть  1 и 2 или 745 и 746

И никаких массивов в принципе, только помнить  о возможности переполнения...

Или использовать float

А если захочется поиграться с плавностью- резкостью изменений:

http://playground.arduino.cc/Main/RunningAverage

 

 

 

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

измерение раз в минуту. общее 20 минут. среднее за 20 минут будет достаточное для игнорирования случайного затемнения. количество можно увеличить. мне кажется этого достаточно

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

jeka_tm пишет:

измерение раз в минуту. общее 20 минут. среднее за 20 минут будет достаточное для игнорирования случайного затемнения. количество можно увеличить. мне кажется этого достаточно

http://playground.arduino.cc/Code/SimpleTimer

#include <SimpleTimer.h>

// the timer object
SimpleTimer timer;

// a function to be executed periodically
void repeatMe() {
   
}

void setup() {
    Serial.begin(9600);
    timer.setInterval(1000, repeatMe);
}

void loop() {
    timer.run();
}

 

Клапауций
Offline
Зарегистрирован: 10.02.2013

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

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

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

com
Offline
Зарегистрирован: 06.09.2013

jeka_tm пишет:

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

сами подумайте - зачем хранить массив из 20 значений, если использовать только среднее? логичнее (и правильнее, и оптимальнее) и хранить только среднее.

из старого среднего новое среднее получить просто:

<новое среднее> = (<старое среднее>*19 + <текущее значение>) / 20

без всяких циклов, сдвигов и пр.....

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

в принципе как вариант. интересная мысль

com
Offline
Зарегистрирован: 06.09.2013

это не моя мысль. это trembo вам три дня назад написал, я просто расжевал.

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

:)

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

com пишет:

это не моя мысль. это trembo вам три дня назад написал, я просто расжевал.

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

:)

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

извините, не прочитал когда отправил, да и потом не обратил внимание

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