Atmega 328p (без кварца) + nrf24 + dht22
- Войдите на сайт для отправки комментариев
Пт, 05/02/2016 - 20:26
Здравствуйте!
Хочу сделать свою метиостанцию.
Есть елементы:
Atmega 328p
nrf24
DHT22
Atmega 328p - я перепрошил по уроку "Arduino ATmega328 Без кварца without crystal quartz bootloader" от автора Dmitry OSIPOV ( https://www.youtube.com/watch?v=wuEzIKybvXw ).
Подключил на макетной плате:
Скетч:
#include <SPI.h>
#include "RF24.h"
#include "DHT.h"
#include <avr/sleep.h>
#include <avr/wdt.h>
#define DHTPIN 4 //Пин подключения DHT
#define DHTTYPE DHT22 //Прописываем тип датчика температуры
DHT dht(DHTPIN, DHTTYPE);
int dhtVcc = 5;
int ledVcc = 7;
int ledC = 0;
RF24 radio(9, 10);
const uint64_t pipes[2] = {0xF0F0F0F000LL, 0xF0F0F0F0FFLL};// адреса каналов приема и передачи
volatile boolean wdt_tripped = 1;
int count =0;
int isact=1;
void setup(){
pinMode(dhtVcc, OUTPUT);
pinMode(ledVcc, OUTPUT);
wdt_disable();
wdt_reset();
wdt_enable(WDTO_8S); //пробуждение каждые 8 сек
initRF();
dht.begin();
}
void loop() {
wdt_interrupt_mode();
if (wdt_tripped) {
wdt_tripped = 0;
count++;
ledC++;
if(ledC == 15 || isact==1){
ledC = 0;
ledOn();
}
if (count == 150 || isact==1) {
isact = 0;
digitalWrite(dhtVcc, HIGH);
delay(500);
int temp_new;
int humi_new;
temp_new=dht.readTemperature();//Читаем показания датчиков
humi_new=dht.readHumidity();
digitalWrite(dhtVcc, LOW);
delay(500);
String stringVar = String(temp_new)+":"+String(humi_new);
sendRF(stringVar);
}
}
system_sleep(); //МК засыпает
}
// мигание светодиодом
void ledOn(){
digitalWrite(ledVcc, HIGH);
delay(100);
digitalWrite(ledVcc, LOW);
}
void initRF(){
radio.begin();
radio.setDataRate(RF24_250KBPS); // Скорость передачи
//radio.setPALevel(RF24_PA_MAX);
radio.setChannel(100); // Номер канала от 0 до 127
radio.setRetries(15,15); // Кол-во попыток и время между попытками
radio.openWritingPipe(pipes[1]); // Открываем канал передачи
//radio.openReadingPipe(1, pipes[0]); // Открываем один из 6-ти каналов приема
//radio.startListening(); // Начинаем слушать эфир
radio.powerDown();
}
void sendRF(String str){
char data[50];
str.toCharArray(data, 50);
radio.powerUp(); //подаём питание на NRF24
delay(10);
radio.write(&data, 32);
delay(10);
radio.powerDown(); //отключаем питание RF24 штатно
}
//режим сна для МК
void system_sleep() {
delay(2); // Wait for serial traffic
_SFR_BYTE(ADCSRA) &= ~_BV(ADEN); // Switch ADC off
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_enable();
sleep_mode(); // System sleeps here
sleep_disable();
_SFR_BYTE(ADCSRA) |= _BV(ADEN); // Switch ADC on
}
void wdt_interrupt_mode() {
wdt_reset();
WDTCSR |= _BV(WDIE); // Restore WDT interrupt mode
}
ISR(WDT_vect) {
wdt_tripped = 1; // set global volatile variable
}
Все вроде бы работает, температуру получает, данные отправляет.
Пробую оставить на длительное время. И тут начинает ардуинка не стабильно работать, то не отправит ничего, то отправит, потом
такое ощущение что arduino залипает и не уходит в сон, не отправляет ничего, и все, как будто зависло, отключаю батарейки, включаю заново, опять все пошло, жду некоторое время опять зависло.
подскажите что можно сделать?
jondiv, вы бы для начала разобрались в какой фазе подвисает ардуина. Начать можно с того, что при бодрствовании зажигать светодиод, перед сном гасить. А вообще чаще подвисоны имеет аппаратные корни, я бы питание поменял в профилактических целях.
Светодиод я подключал, по скечу int ledVcc = 7; он мигает, все хорошо. На протяжении 2х-3х часов все норм. Данные передаются каждые 20 мин, светодиод мигает каждые 2 минуты. Работает от 3х пальчиковых батареек. Может при пробуждении каждые 20мин, сажать батарейки? пробовал еще подключать аккум на 3.7В (520mAh), тоже самое, потом пробовал аккум на 4,8В (700mAh) тоже через некоторое время зависон, и да зависон выражается еще на светодиоде который подключен к 7 пин, он как-бы мерцает(мигает)
А вы еще четвертым парамером напряжение батареи посылайте.
/** * Функция определения напряжения питания устройства */ 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; }Обязательно выдерживайте наймауты после пробуждения. Для начало побольше, потом уменьшайте.
А если оставить питание от USB и заюзать Serial.println() для отладки? Глядишь - найдете после чего виснет.
Всем привет!
Ребят на этом форуме с неделю так, что плохо тут ориентирусь.
Из последних тем по DHT 22 нашел эту. Есть вопрос по DHT. Я с Arduin-кой играюсь всего неделю, а с DHT 22 тоже раньше не имел дел.
За пару дней накидал Скетч с использованием DHT. Стал прогонять в Proteus-е и нашел временной провал в программе который мне сильно мешает.
boolean DHT::read(bool force) { // Check if sensor was read less than two seconds ago and return early // to use last reading. uint32_t currenttime = millis(); if (!force && ((currenttime - _lastreadtime) < 2000)) { return _lastresult; // return last correct measurement } _lastreadtime = currenttime; // Reset 40 bits of received data to zero. data[0] = data[1] = data[2] = data[3] = data[4] = 0; // Send start signal. See DHT datasheet for full signal diagram: http://www.adafruit.com/datasheets/Digital%20humidity%20and%20temperature%20sensor%20AM2302.pdf // Go into high impedence state to let pull-up raise data line level and // start the reading process. digitalWrite(_pin, HIGH); // return; delay(250);Alexey-kipia, завели бы свою тему. Неприлично как то.(((.
А на DHT сия проблема есть. И используя библиотеку ее похоже не решить.
Единственное, что нашел:
01 // Mega 02 uint8_t data[5]; 03 const byte DHT1_pin = 22; 04 const byte DHT2_pin = 24; 05 const unsigned int interval = 1000; 06 07 void setup(){ 08 Serial.begin(9600); 09 } 10 11 void loop(){ 12 int hum1 = 0, temp1 = 0; 13 int hum2 = 0, temp2 = 0; 14 static unsigned long prevMillis = 0; 15 if(millis() - prevMillis > interval){ 16 prevMillis += 1000; 17 if(readingDHT(DHT1_pin)){ //если контрольная сумма верна 18 hum1 = (data[0] << 8) | data[1];//считаем Н и Т первого датчика 19 temp1 = ((data[2] & 0x7F) << 8) | data[3]; 20 if(data[2] & 0x80) temp1 *= -1; 21 }else{ 22 //ошибка DHT1 23 } 24 if(readingDHT(DHT2_pin)){ 25 hum2 = (data[0] << 8) | data[1]; 26 temp2 = ((data[2] & 0x7F) << 8) | data[3]; 27 if(data[2] & 0x80) temp2 *= -1; 28 }else{ 29 //ошибка DHT2 30 } 31 Serial.print("hum1 = "); Serial.print(hum1 /10); 32 Serial.print('.'); Serial.println(hum1 %10); 33 Serial.print("tem1 = ");Serial.print(temp1 /10); 34 Serial.print('.'); Serial.println(temp1 %10); 35 Serial.print("hum2 = ");Serial.print(hum2 /10); 36 Serial.print('.'); Serial.println(hum2 %10); 37 Serial.print("tem2 = ");Serial.print(temp2 /10); 38 Serial.print('.'); Serial.println(temp2 %10); 39 Serial.println(); 40 } 41 } 42 //=============================================== 43 boolean readingDHT(byte pin) { 44 boolean state = HIGH; //состояние линии 45 byte counter = 0, j = 0; 46 const byte count = 5; 47 for(byte i=0; i<5; i++){ 48 data[i] = 0; 49 } 50 pinMode(pin, OUTPUT); 51 digitalWrite(pin, LOW); 52 delay(1); //более 800mks нужно чтобы рабудить датчик DHT21-22 53 //delay(18); //для DHT11 54 //cli(); //отключить прерывания если нужно 55 pinMode(pin, INPUT); //начинаем слушать датчик 56 for(byte i = 0; i < 83; i++){//читаем 83 сост линии 57 counter = 0; 58 while (digitalRead(pin) == state) {//state==1 первый проход 59 counter++; 60 delayMicroseconds(4);//if 4 mkc count==3-7 61 if (counter > 20) break; 62 }//end while 63 state = !state;//digitalRead(_pin); 64 if (counter > 20) break; 65 if ((i > 3) && !(i & 1)) {//i%2 записать каждый бит в байты хранения 66 data[j >> 3] <<= 1; //читаем с 5(i=4) состояния(1,0,1,0,?,0,?,0,...?) 67 if (counter > count) data[j>>3] |= 1;//counter>3-10 дальше ошибки 68 j++; 69 } 70 }//end for 71 //sei(); //включить прерывания 72 uint8_t sum = data[0] + data[1] + data[2] + data[3]; 73 if(sum == data[4]) return 1; 74 else return 0; 75 }Сам не пробовал, руки не дошли. Номера строк тереть надо, они в оригинале уже были.
Не совсем понял, сори.
Мне не нужен код. Библиотека, что я привел работает нормально. Мне не понятно зачем автор влупил задержку 250 милисекунд в том месте, что я указал. Такое ощущение, что он перепутал милисекунды с микро секундами. Я уже надумал вариант обхода этой проблемы. Применим подсчет времени работы программы. Зайдем, сохраним считвнное время. При следующем входе будем проверять прошедшее время. Если истекло, пойдем дальше. Функция millis(); . Просто странно. Автор применил эту функцию на входе в подпрограмму и тупо влепил остановку программы через несколько действий. Я решу эту проблему, но хочется знать для чего эта выдержка у Автора?
В Proteus-е нормально работает даже если вообще убираю эту задержку :-)
Alexey-kipia, завели бы свою тему. Неприлично как то.(((.
А на DHT сия проблема есть. И используя библиотеку ее похоже не решить.
Единственное, что нашел:
01 // Mega 02 uint8_t data[5]; 03 const byte DHT1_pin = 22; 04 const byte DHT2_pin = 24; 05 const unsigned int interval = 1000; 06 07 void setup(){ 08 Serial.begin(9600); 09 } 10 11 void loop(){ 12 int hum1 = 0, temp1 = 0; 13 int hum2 = 0, temp2 = 0; 14 static unsigned long prevMillis = 0; 15 if(millis() - prevMillis > interval){ 16 prevMillis += 1000; 17 if(readingDHT(DHT1_pin)){ //если контрольная сумма верна 18 hum1 = (data[0] << 8) | data[1];//считаем Н и Т первого датчика 19 temp1 = ((data[2] & 0x7F) << 8) | data[3]; 20 if(data[2] & 0x80) temp1 *= -1; 21 }else{ 22 //ошибка DHT1 23 } 24 if(readingDHT(DHT2_pin)){ 25 hum2 = (data[0] << 8) | data[1]; 26 temp2 = ((data[2] & 0x7F) << 8) | data[3]; 27 if(data[2] & 0x80) temp2 *= -1; 28 }else{ 29 //ошибка DHT2 30 } 31 Serial.print("hum1 = "); Serial.print(hum1 /10); 32 Serial.print('.'); Serial.println(hum1 %10); 33 Serial.print("tem1 = ");Serial.print(temp1 /10); 34 Serial.print('.'); Serial.println(temp1 %10); 35 Serial.print("hum2 = ");Serial.print(hum2 /10); 36 Serial.print('.'); Serial.println(hum2 %10); 37 Serial.print("tem2 = ");Serial.print(temp2 /10); 38 Serial.print('.'); Serial.println(temp2 %10); 39 Serial.println(); 40 } 41 } 42 //=============================================== 43 boolean readingDHT(byte pin) { 44 boolean state = HIGH; //состояние линии 45 byte counter = 0, j = 0; 46 const byte count = 5; 47 for(byte i=0; i<5; i++){ 48 data[i] = 0; 49 } 50 pinMode(pin, OUTPUT); 51 digitalWrite(pin, LOW); 52 delay(1); //более 800mks нужно чтобы рабудить датчик DHT21-22 53 //delay(18); //для DHT11 54 //cli(); //отключить прерывания если нужно 55 pinMode(pin, INPUT); //начинаем слушать датчик 56 for(byte i = 0; i < 83; i++){//читаем 83 сост линии 57 counter = 0; 58 while (digitalRead(pin) == state) {//state==1 первый проход 59 counter++; 60 delayMicroseconds(4);//if 4 mkc count==3-7 61 if (counter > 20) break; 62 }//end while 63 state = !state;//digitalRead(_pin); 64 if (counter > 20) break; 65 if ((i > 3) && !(i & 1)) {//i%2 записать каждый бит в байты хранения 66 data[j >> 3] <<= 1; //читаем с 5(i=4) состояния(1,0,1,0,?,0,?,0,...?) 67 if (counter > count) data[j>>3] |= 1;//counter>3-10 дальше ошибки 68 j++; 69 } 70 }//end for 71 //sei(); //включить прерывания 72 uint8_t sum = data[0] + data[1] + data[2] + data[3]; 73 if(sum == data[4]) return 1; 74 else return 0; 75 }Сам не пробовал, руки не дошли. Номера строк тереть надо, они в оригинале уже были.
А чего темы плодить? Просто тематически.
Забиваешь DHT22 и не получаешь ничего путнего. Просто каждый заводит свою тему: DHT22, 22DHT, DH22T.
А суть одна - решение проблем с датчиком или Библиотекой :-)
Ну в общем на данный момент просмотрел весь класс DHT и не увидел привязки к этой выдержке. Перед вызовом подпрограммы - объекта boolean DHT::read(bool force) нет ни одной манипуляции с входом - выходом типа старта опроса и тем самым нет нужды в выдержке. Просто коментируем и получаем 250 милисекунд свободного времени в собственной программе. Тем более, что есть переферия требующая обработки максимум в 10 милисекунд. :-)
Вот другой автор и соответственно другая реализация библиотеки https://github.com/RobTillaart/Arduino/tree/master/libraries/DHTlib