Capteur d'éclairage sans fil CR2450

Faire une sorte de capteur sans fil contenant un baromètre, un thermomètre, un hygromètre ou tout dans une bouteille, alimenté par 220V n'est pas un problème. Mais alimenter un tel appareil à partir de piles ou d'accumulateurs est déjà plus intéressant. Eh bien, s'il s'agit d'une batterie au lithium à disque (tablette) - c'est généralement cool, car l'appareil se révélera très compact.
Le seul obstacle à l'utilisation de la «pilule» est sa petite capacité. Mais même parmi les "comprimés", il existe des échantillons tout à fait appropriés, par exemple CR2450, avec la capacité revendiquée de 550-610 mAh.
Comme au moment de la fabrication de l'appareil, je disposais déjà de capteurs de température et d'humidité intérieurs et extérieurs prêts à l'emploi, j'ai décidé de fabriquer un capteur d'éclairage basé sur le BH1750 et de le placer sur le balcon, en l'équipant en outre d'un capteur de température DS18B20.
Étant donné que toutes les fenêtres sont orientées au sud, le capteur de température et d'humidité extérieure est considérablement affecté par la lumière du soleil, cet effet doit être compensé par les données météorologiques reçues d'Internet.À l'avenir, je prévois d'utiliser des informations sur le niveau d'éclairage pour calculer la compensation.
Pour minimiser l'énergie consommée par le capteur, il a été décidé:
1. Refusez d'utiliser l'Arduinki fini et utilisez directement le microcontrôleur ATmega 328P-PU avec quartz 8 MHz. J'ai refusé d'utiliser le générateur RC interne, car en raison de changements importants de la température extérieure, la fréquence de fonctionnement n'est pas stable.
2. Utilisez la bibliothèque LowPower et activez le mode d'économie d'énergie LowPower.powerDown (SLEEP_8S, ADC_OFF, BOD_OFF) pour le contrôleur
3. Alimentez le capteur DS18B20 à partir de la sortie numérique du microcontrôleur et allumez-le immédiatement avant la mesure.
4. Alimentez directement le module radio et le BH1750 en utilisant respectivement les modes d'économie d'énergie radio.powerDown () et Light.configure (BH1750_ONE_TIME_HIGH_RES_MODE).
Armé du programmateur USBasp,

J'ai demandé un fusible dans le contrôleur et, bien sûr, dans le chargeur de démarrage. J'ai assemblé un prototype, esquissé un croquis de test et mesuré les courants consommés: en mode veille, il s'est avéré 14 μA, en mode de lecture de capteurs - 3-4 mA, en mode de transmission de données via nRF24 à une station météo - 16-18 mA. Étant donné que j'ai décidé de prendre des lectures des capteurs une fois toutes les 3 minutes et de les transmettre toutes les 10 minutes - le capteur est très économique.
Pour la fabrication du dispositif final utilisé un morceau de planche à pain et de fil MGTF. Le résultat est ce qui s'est passé:

pour surveiller l'état de la batterie, nous utilisons les fonctionnalités intégrées d'ATmega, qui sont bien décrites dans cet article .
Le processus de flashage du chargeur de démarrage et des fusibles est traité en détail ici et ici .
L'idée générale de créer un capteur autonome a été empruntée sur le site de maniacbug .

Le capteur est déjà couché (et fonctionne) depuis le deuxième mois sur le balcon sur le rebord de la fenêtre, envoie correctement les données. Le contrôle de l'alimentation signale que pendant ce temps, la tension de la source est passée de 3,05 V à la mise sous tension à 2,98 V. Cependant, pendant la journée, lorsque le soleil réchauffe le balcon, la tension peut monter jusqu'à 3,00V. J'attends avec impatience le froid, voyons comment la batterie sélectionnée se montrera à basse température.
Avec la durée sélectionnée du mode veille, il s'avère que le capteur n'est éveillé que de 492 à 495 secondes en 24 heures.

L'appareil est complet, mais malheureusement jusqu'à présent sans étui, je ne trouve pas de



ajout du 20/03/2016.
6 , . -24, 2,5280V.
( ) 4 + .


La source
#include <LowPower.h>
#include <SPI.h>
#include <RF24Network.h>   
#include <RF24.h>          
#include <OneWire.h>
#include <DallasTemperature.h>
#include <Wire.h>
#include <BH1750.h>
/////// lass AVG //////////////////////////////////////////////////////////
class AVG {
  #define DEPTH_AVG 10
  private :
     int depth;
     long *mas;
     int cur;
     boolean first;
  public :
     boolean fDebug;  

  AVG(int d)
  {
    if( d == 0 || d > DEPTH_AVG)depth = DEPTH_AVG;
    else depth = d;
    mas = (long *)malloc(sizeof(long)*depth);
    first = true;
    cur   = 0;
    fDebug = false;
  }
  void Set(long x)
  {
    if( first )
    {
       for( int i=0; i<depth; i++ )mas[i] = x;
       cur = 0;
    }
    else
    {
    mas[cur++] = x;
    if( cur >= depth ) cur = 0; 
    }
    first = false;  
  }
  long Get()
  {
    long x=0;
    for( int i=0; i<depth; i++ )
          {
            x+=mas[i];
          }
    x/=depth;
    return(x);
  }
};
/////////////////////////////////////////////////////////////////////
#define pinPowerSensor 4    //    Pin 4
#define ONE_WIRE_BUS 3
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
BH1750 Light;
RF24 radio(/*ce*/ 9, /*cs*/ 10);
RF24Network network(radio);
//   
uint16_t this_node = 02;
// ,     
uint16_t main_node = 0;
//  
const int Chanel = 11;
int ReadCount;
int iSend     = 3;    //    
int WaitCount = 24;   //     8 .
bool allowSend = false; //   
AVG vAVG(3);
AVG tAVG(3);
AVG lAVG(3);
struct StreetMeteoSensor
{
  char    ID[5];     // 
  unsigned long UpTime;
  int   T;           //
  long  L;           //  (Lx) 
  int   V;           //   (mV)
};
struct StreetMeteoSensor sensor;
RF24NetworkHeader header(main_node, 'I');
////////////////////////////////////////////
#define DEBUG_MODE     0
////////////////////////////////////////////
void setup(void)
{
    if (DEBUG_MODE) 
  {
    Serial.begin(115200);
    //tAVG.fDebug = true;  
    //lAVG.fDebug = true;      
    Serial.println("-- START --");  
    WaitCount = 5;
  }
  for (int i = 1; i < 15; i++)  
  {
    pinMode(i, OUTPUT);
    digitalWrite(i,LOW);
  }
  digitalWrite(pinPowerSensor,HIGH);
  char ID[5] = "LTS1";
  memcpy(sensor.ID, ID, 5);  
  ReadCount = iSend;
  SPI.begin();
  delay(500);
  radio.begin();
  network.begin( Chanel, this_node );  
  sensors.begin();  
  Light.begin(BH1750_ONE_TIME_HIGH_RES_MODE);
  delay(500);
  radio.powerDown();    
  digitalWrite(pinPowerSensor,LOW);  
  Light.configure(BH1750_POWER_DOWN);
  if (DEBUG_MODE)  Serial.println("-- End SETUP --"); 
}

void loop(void)
{
  //  
 if (DEBUG_MODE) Serial.println("data read...");
  //  BH1750    , 
  Light.configure(BH1750_POWER_ON);                    //  
  Light.configure(BH1750_ONE_TIME_HIGH_RES_MODE);     //   
  digitalWrite(pinPowerSensor,HIGH);                  //    DS18B20
  sensors.setResolution(TEMP_9_BIT);   
  delay(250); 
  sensors.requestTemperatures();
  int T = sensors.getTempCByIndex(0);
  digitalWrite(pinPowerSensor,LOW);  //   DS18B20
  long L = Light.readLightLevel();  // ONE_TIME   
  int V = readVcc();  
  /////////////////////////////////////////////////////////////
  int tt = tAVG.Get();
  int vv = vAVG.Get();
  long ll = lAVG.Get();
  if (L > 0 || ll > 0 || T < tt-2 || T > tt+2 || V < vv-100/*0.1V*/) 
  { //  -    
    tAVG.Set(T);
    lAVG.Set(L);
    vAVG.Set(V); 
    allowSend = true;     //   -  
    //     0 ()
    if (ll == 0 &&  L > 0)
      lAVG.Set(L);  
  }
  ReadCount++;        
  /////////////////////////////////////////////////////////////
  if (DEBUG_MODE)
  {
    Serial.print("T= ");
    Serial.print(tAVG.Get());
    Serial.print(": ");
    Serial.print(T);    
    Serial.print("; L= ");
    Serial.print(lAVG.Get());
    Serial.print(": ");    
    Serial.print(L);    
    Serial.print("; V= ");
    Serial.print(vAVG.Get());
    Serial.print(": ");    
    Serial.print(V);        
    Serial.print("; ReadCount= ");    
    Serial.println(ReadCount);
  }  
  /////////////////////////////////////////////////////////////
  //    
  if ( ReadCount >= iSend && allowSend )
  {
    //     
    ReadCount = 0;
    allowSend = false;   
    radio.powerUp();
    delay(50);
    sensor.T = tAVG.Get();  
    sensor.L = lAVG.Get();
    sensor.V = vAVG.Get();    
    sensor.UpTime = millis()/1000;     
    network.write(header,&sensor,sizeof(sensor));
    radio.powerDown();  
  }    
  sleep();
}
//      
void sleep()
{
  if (DEBUG_MODE) {Serial.println("----- SLEEP -----");Serial.flush();}
  for (int i = 0; i < WaitCount; i++)  //   
  {
    LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF); 
  }
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//   
int readVcc() 
{
  int result;
  // Read 1.1V reference against AVcc
  // set the reference to Vcc and the measurement to the internal 1.1V reference
  ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
  delay(75); // Wait for Vref to settle
  ADCSRA |= _BV(ADSC); // Start conversion
  while (bit_is_set(ADCSRA,ADSC)); // measuring
  result = ADCL;
  result |= ADCH<<8;
  if (DEBUG_MODE) {Serial.print("result=");Serial.println(result);}
  result =  1125300L / result; // (Kvcc * 1023.0 * 1000) (in mV);
  return result; 
}

Source: https://habr.com/ru/post/fr385129/


All Articles