Arduino + сенсор DHT11 + шаговый двигатель (биполярный)
- Войдите на сайт для отправки комментариев
Сб, 14/04/2012 - 22:34
- Доброго времени суток! Есть Arduino + сенсор DHT11 (температура и влажность) + шаговый двигатель (биполярный). Хочу сделать конролируемое по температуре открытие/закрытие форточки в доме. Например, при достижении t > 24 C, форточка открылась и не закрывалась. При t < 24 C форточка закрылась. При работе моего кода ШД, если t>24 или t<24, постоянно срабатывает. Знаю, чо где-то что-то делаю не правильно при цеплянии ШД. Помогите пожалуйста...
- P.S. да, ламер и чайник
#include <Stepper.h>
#define DHT11_PIN 0 // цепляю сенсор
#define STEPS 200
Stepper stepper(STEPS, 8, 9, 10, 11);
byte read_dht11_dat()
{
byte i = 0;
byte result=0;
for(i=0; i< 8; i++){
while(!(PINC & _BV(DHT11_PIN)));
delayMicroseconds(30);
if(PINC & _BV(DHT11_PIN))
result |=(1<<(7-i));
while((PINC & _BV(DHT11_PIN)));
}
return result;
}
void setup()
{
DDRC |= _BV(DHT11_PIN);
PORTC |= _BV(DHT11_PIN);
Serial.begin(9600);
stepper.setSpeed(10);
Serial.println("Ready");
}
void loop()
{
byte dht11_dat[5];
byte dht11_in;
byte i;
PORTC &= ~_BV(DHT11_PIN);
delay(18);
PORTC |= _BV(DHT11_PIN);
delayMicroseconds(40);
DDRC &= ~_BV(DHT11_PIN);
delayMicroseconds(40);
dht11_in = PINC & _BV(DHT11_PIN);
if(dht11_in){
Serial.println("dht11 start condition 1 not met");
return;
}
delayMicroseconds(80);
dht11_in = PINC & _BV(DHT11_PIN);
if(!dht11_in){
Serial.println("dht11 start condition 2 not met");
return;
}
delayMicroseconds(80);
for (i=0; i<5; i++)
dht11_dat[i] = read_dht11_dat();
DDRC |= _BV(DHT11_PIN);
PORTC |= _BV(DHT11_PIN);
byte dht11_check_sum = dht11_dat[0]+dht11_dat[1]+dht11_dat[2]+dht11_dat[3];
if(dht11_dat[4]!= dht11_check_sum)
{
Serial.println("DHT11 checksum error");
}
Serial.print("Current humdity = ");
Serial.print(dht11_dat[0], DEC);
Serial.print(".");
Serial.print(dht11_dat[1], DEC);
Serial.print("% ");
Serial.print("temperature = ");
Serial.print(dht11_dat[2], DEC);
Serial.print(".");
Serial.print(dht11_dat[3], DEC);
Serial.println("C ");
delay(2000);
if (dht11_dat[2] > 24) // начало работы ШД
{
stepper.step(100);
}
if (dht11_dat[2] < 22)
{
stepper.step(-100);
}
}
спасибо
Решение называется RTFM - Read The Fucking Manual.
Если открыть даташит и посмотреть раздел тех. характеристик, то можно выяснить, что
"Temperature Accuracy ±2℃"
то есть, при одном считывании вы можете получить 20 градусов Цельсиуса, а при следующем за ним - 24. Или лучше так - при одном 25 (и срочно откроете свою форточку), а при следующем - 21 (и "побежите" задраивать все щели).
Пути решения? Их есть у меня:
либо расширяйте гистерезис, скажем с ">24 откр, <22 закр" перейдите на ">25 откр, <21 закр"
либо находите среднее арифметическое по последни 5-6-10-100 замерам.
ЗЫ: И еще: вот вы чексум проверяете и даже истошное сообщение в случае чего выводите.
Оч. хор.
Только, выполнив эту проверку, почему-то успокаиваитесь и бесстрашно используете полученные неправильные данные в своем алгоритме. Правильнее было бы заключить все инструкции, стоящие ниже проверки контрольной суммы, в конструкцию "else {...}" и выполнять их ТОЛЬКО в том случае, если проверка успешна.
Спасибо step962. значения температуры поменял.. однако остается следующая проблема - при t>25 двигатель срабатывает постоянно (т.е форточка открывается, затем еще и еще). <21 происходит закрытие, +закрытие, + закрытие и т.д.
Как сделать так, чтоб открытие/закрытие осуществлялось однократно (т.е. 24, 25, 26(открытие),27 (форточка продолжает оставаться открытой, а не "открывается еще разок")?
P.S. как посчитать "среднее арифметическое по последни 5-6-10-100 замерам"
Как сделать так, чтоб открытие/закрытие осуществлялось однократно (т.е. 24, 25, 26(открытие),27 (форточка продолжает оставаться открытой, а не "открывается еще разок")?
Ну, это можно реализовать разными способами.
Например, ввести константы
и переменную состояния (обозвав ее, например, State)
В setup():
В loop():
if (dht11_dat[2]>25 && State != OPENED) { stepper.step(100); // открываем форточку State = OPENED; // запоминаем текущее состояние }Проверка на закрывание - в том же духе.
P.S. как посчитать "среднее арифметическое по последни 5-6-10-100 замерам"
Это уже разбиралось в одной из тем, посвященных борьбе с дребезгом кнопок или чему-то там еще:
При расчете среднего не следует забывать об особенностях целочисленной математики, иначе очень легко накопить непереносимо большую погрешность. (например, в выражении, в котором участвуют исключительно целочисленные переменные результат действия 4/5 и даже 99/100 равен нулю)
Step962 спасибо вам ОГРОМНОЕ! Все работает! Думаю, тема закрыта)