i2c в режиме SLEEP_MODE_PWR_DOWN

zegsoft
Offline
Зарегистрирован: 23.06.2016

Всем доброго времени суток!

Пытаюсь сделать метеостанцию и столкнулся с проблемой спящего режима. У станции будет 2 датчика:датчик температуры dht22 и датчик освещенности BH1750. Станция должна посылать показания по радиоканалу один раз в 5 минут и засыпать. Станция работает от батареек, поэтому вопрос энергопотребления критичен. Почитал про режимы сна и выяснил, что для снижения энергопотребления нужно все пины переводить в режим output low. И действительно, в этом случае мне удалось довести энергопотребление до 0,001 мА (1 мкА) в режиме сна. Но возникла следующая проблема: датчик BH1750 работаем по шине i2c. Когда я перевожу пин A5 в режим output low, микроконтроллер первый раз обрабатывает это нормально, а на второй итерации зависает. Код программы привожу. Еще раз хочу отметить, что одну итерацию микроконтроллер отрабатывает нормально. Знающие люди, подскажите, как правильно перевести пин A5 в режим low, чтобы потом продолжала работать шина i2c? Если его не переводить в режим low энергопотребление составляет около 0,1 мА, что довольно много для питания от батареек.

#include "DHT.h"
#include <VirtualWire.h>
#include "Wire.h"
#include "BH1750.h"
#include <meteo_packet.h>
#include <Adafruit_SleepyDog.h>
#include <avr/sleep.h>

#define DHTPIN 7          // номер пина, к которому подсоединен датчик температуры

void setup() {
}

void loop() {

   ADCSRA = 0; // disable ADC

 for (byte i = 0; i <= A4; i++)
    {
    pinMode (i, OUTPUT);    // changed as per below
    digitalWrite (i, LOW);  //     ditto
    }
   
  for(int sleep=0;sleep<1;)
  {
    sleep+=Watchdog.sleep(3000)/1000;
  }

 DHT dht(DHTPIN, DHT22);   // Датчик температуры и влажности
 BH1750 lightMeter;        // Датчик освещенности
    
pinMode(2,OUTPUT);
digitalWrite(2,LOW);
vw_setup(2000);
vw_set_tx_pin(3); 


  digitalWrite(2,HIGH);
  Watchdog.sleep(500);
  lightMeter.begin();
  dht.begin();
  meteo_data m_data;
  m_data.H = dht.readHumidity();//Считываем влажность
  m_data.T = dht.readTemperature();// Считываем температуру
  m_data.L = lightMeter.readLightLevel();

  vw_send((uint8_t*)&m_data,sizeof(m_data));
  vw_wait_tx();
}

 

strarbit
Offline
Зарегистрирован: 12.06.2016

zegsoft пишет:
 как правильно перевести пин A5 в режим low, чтобы потом продолжала работать шина i2c? 

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

zegsoft
Offline
Зарегистрирован: 23.06.2016

Микроконтроллер в спящий режим естественно перевожу! Но такой нюанс: если просто перевести в режим сна, потребялет 0,1 мА, если перед этим перевести пин в low, то потребление 0,001 мА.

Anton991
Offline
Зарегистрирован: 09.10.2017

Столкнулся с такой же проблемой. Не нашли решения?

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

где то на просторах интернета находил информацию чтоVirtualWire.h

что то ломает при инициализации и ее не рекомендуют при использовании в МК с WDT

сам планирую использовать Manchester.h - пишут что более стабильно

 

zegsoft
Offline
Зарегистрирован: 23.06.2016

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

#include "DHT.h"
#define PB7_out DDRB |=1<<7;
#define PB7_high PORTB|=1<<7;
#define PB7_low PORTB&=~(1<<7);

#include <VirtualWire.h>
#include "Wire.h"
#include "BH1750.h"
#include <meteo_packet.h>
#include <Adafruit_SleepyDog.h>

#define DHTPIN 5          // номер пина, к которому подсоединен датчик температуры
DHT dht(DHTPIN, DHT22);   // Датчик температуры и влажности
BH1750 lightMeter;        // Датчик освещенности

void setup() 
{
  pinMode (3, OUTPUT); 
PB7_out
//  Serial.begin(9600);
//  Serial.println("test");
}

void loop() 
{
  digitalWrite(3,HIGH);
//  digitalWrite(7,HIGH);
  PB7_high
 
  Watchdog.sleep(500);
  lightMeter.begin();
  dht.begin();
  vw_setup(2000);
  vw_set_tx_pin(2); 
  
  Watchdog.sleep(150);
  
  meteo_data m_data;
  m_data.L = lightMeter.readLightLevel();
  m_data.H = dht.readHumidity();  
  m_data.T = dht.readTemperature();
  
   pinMode(A2, INPUT);// Датчик дождя
   digitalWrite(A2,HIGH);
  m_data.R=analogRead(A2);
  vw_send((uint8_t*)&m_data,sizeof(m_data));
  vw_wait_tx();

  PB7_low
  for (byte i = 0; i <= A5; i++)
  {
    pinMode (i, OUTPUT);
    digitalWrite (i, LOW);
  }

 byte adcsra_save = ADCSRA;
  ADCSRA = 0; // disable ADC 
  for(int sleep=0;sleep<6;)
    sleep+=Watchdog.sleep()/1000;

ADCSRA=adcsra_save;
  
//  m_data.print();
 
}

 

Anton991
Offline
Зарегистрирован: 09.10.2017

У меня на I2C висят часы DS3231. устройство уходит в сон на час и по будильнику от DS3231 (нога SQW) контролер должен просыпаться делать замеры и отправлять измерения по радио, после чего переставлять будильник на час вперед и снова засыпать, а  ноги I2C  жрут во сне 0,2 мА., что много для спящего.   я пока попробую их принудительно в OUTPUT LOW режим перед сном отправлять, а после сна снова в INPUT, может сработает.