03 January 2015

Mini Meteo Station with Arduino Nano

I finished a complex project, a mini Meteo Station based on Arduino Nano.

On a 4x20 I2C LCD I can see the date, time, inside and outside temperature, relative humidity and air pressure (in hPa).


Main features are:
    -Low footprint
    -Precise Date and Time with a DS1307 RTC circuit
    -Humidity with a DHT-11 sensor
    -Baro pressure and interior temperature with a BMP-085
    -External temperature with a DS-18B20
    -Low power (40 mA from one Li-Ion cell with a DC-DC converter with LCD Backlight on, 30 mA).
    -LCD Backlight on demand by push button

Took me about 2 days but I made it!

I intend to make some averages and to compare the pressure over an variable inteval tohave a weather prediction.





Here is the code:


 /*

   Meteo station with Arduino Nano
   by Adrian, YO3HJV
   http://yo3hjv.blogspot.com
  
  
  
  -- LCD on I2C
  -- Barometer and temperature sensor BMP-085 on I2C
  -- Humidity sensor DHT-11 on pin D3
  -- Dallas DS-18B20 temperature sensor on OneWire, pin D2
  -- Backlight Push button on pin A3
 
  */


   #include <Wire.h>
   #include <LCD.h>
   #include <LiquidCrystal_I2C.h>
   #include <Time.h>
   #include <DS1307RTC.h>
   #include <Barometer.h>
   #include <OneWire.h>
   #include <DallasTemperature.h>
   #include <dht11.h>
  
                                          // Data wire is plugged into port 2 on the Arduino
    #define ONE_WIRE_BUS 2                                         
    OneWire oneWire(ONE_WIRE_BUS);                                       
    DallasTemperature sensors(&oneWire);
   
    #define DHT11PIN 3
   
    dht11 DHT11;

  
     
// I2C LCD DISPLAY
   #define I2C_ADDR    0x27
   #define BACKLIGHT_PIN     3
   #define En_pin  2
   #define Rw_pin  1
   #define Rs_pin  0
   #define D4_pin  4
   #define D5_pin  5
   #define D6_pin  6
   #define D7_pin  7

// ******************
 
 
       LiquidCrystal_I2C    lcd(I2C_ADDR, En_pin, Rw_pin, Rs_pin, D4_pin, D5_pin, D6_pin, D7_pin);

    // Variabilele pentru Barometru
       float temperature;  // FLOAT or INT
       float tempext;      // FLOAT or INT
       float pressure;
       float atm;
       float altitude;
   
       Barometer myBarometer;
      
      int BLpin = A3;   // choose the input pin (for a pushbutton)
      int val = 0;      // variable for reading the pin status


  void setup()
    {    
     myBarometer.init();    
     sensors.begin();   // External Temp sensor         
     lcd.begin (20,4);  // initialize the lcd
     lcd.setBacklightPin(BACKLIGHT_PIN, POSITIVE); 
     pinMode(BLpin, INPUT);    // declare pushbutton as input
    }

              void loop()
 {
            
              val = digitalRead(BLpin);  // test BLpin
             
                  if (val == LOW)
                  {        
                  lcd.backlight();  // Backlight ON and...
                  sens();  // ... execute "sens"
                  }
                 
                  else  // if not ...,
                  {
                  lcd.noBacklight();  // Backlight OFF and...
                  sens();  // ...execute "sens"
                  }
}

    void sens()   // Main function
    {
     
       tmElements_t tm;                        //DS1307 RTC
       sensors.requestTemperatures();          // Send the command to get ext temperature
       tempext = sensors.getTempCByIndex(0);  
      

   //BARO + TEMP PE I2C
   // we read all the values from barometric sensor but use only temperature and pressure
   // we might calculate Dew point!
       temperature = myBarometer.bmp085GetTemperature(myBarometer.bmp085ReadUT()); //Get the temperature, bmp085ReadUT MUST be called first
       pressure = myBarometer.bmp085GetPressure(myBarometer.bmp085ReadUP());       //Get the temperature
       altitude = myBarometer.calcAltitude(pressure);                              //Uncompensated caculation - in Meters
       atm = pressure / 101325;
 
 
   //Hygro sensor DHT-11
       int chk = DHT11.read(DHT11PIN);
      
              if (RTC.read(tm))
              {

                 // Hours, minutes, seconds
               
                     lcd.setCursor(12, 0);                                                 
                                lcd2digits(tm.Hour);
                            lcd.print(":");
                                lcd2digits(tm.Minute);
                            lcd.print(":");
                                lcd2digits(tm.Second);
                
                
                 // Only hours and minutes. Uncomment this and comment above
                               
                 /*    lcd.setCursor(14, 0);                                                 
                                lcd2digits(tm.Hour);
                            lcd.print(":");
                                lcd2digits(tm.Minute);
        
                 */
                     lcd.setCursor(0, 0);
                                 lcd.print(tm.Day);
                             lcd.print('/');
                                 lcd.print(tm.Month);
                             lcd.print('/');
                                 lcd.print(tmYearToCalendar(tm.Year));
                            
                     lcd.setCursor(0, 2);
                             lcd.print("In: ");
                                 lcd.print(temperature);  // we can use [lcd.print(int(temperature))] for value without decimals;
                             lcd.print(" *C ");           // otherwise, temp is with two decimals
            
                     lcd.setCursor(0, 3);
                             lcd.print("Ex: ");
                                 lcd.print(tempext);      // the same as above ...
                             lcd.print(" *C ");                          
                     
                     lcd.setCursor(0, 1);
                              lcd.print("P:");
                                 lcd.print(int((pressure) / 100)); // No decimals pressure
                              lcd.print(" hPa");
                             // lcd.print("  ");
   
                     lcd.setCursor(12, 1);
                              lcd.print("Hum. ");
                                 lcd.print((int)DHT11.humidity);
                              lcd.print("%");
   
   
                } else
                    
                  {
                    lcd.clear();
                    lcd.print("RTC HW ERROR!!!"); // This is for RTC comm error
                    delay(10000);
                  }
             
            delay(200);
 
    }  // END  "sens" function


//LCD nice time function

    void lcd2digits(int number)   {
     
        if (number >= 0 && number < 10) {
            lcd.print('0');             }
            lcd.print(number);                   
                                  }




 73 de Adrian, YO3HJV


01 January 2015

Arduino Energy-meter

A few days ago I was contemplating a little device from a hobby store. It was a smart power gauge meter for tracking the charge and discharge of a battery.
I was wondering if I cannot do it by myself with a Arduino Uno board and some current sensor.
As I'm not a code-freak dude, I did a little research and found a nice start for my project, right here.
I do have a ACS-712 for 5 Amps and also for 30 Amps.

I decided to start with the little one as my project is designated for my portable HF backpack based on ICOM IC-703.

As the Arduino ADC input cannot accept more than 5V, a voltage divider has to be used.
Is the classic one, in wich I used a 10 kOhm from A4 to ground and a 100 kOhm from A4 to the probe. I used SMD resistors but after I measured the ratio I found that the real ratio is not 10 to 1 but somewhere around 10.93:1.
It is important as this ratio will be used to calculate the voltage into the Arduino code.
I modified the code from Instructables because it had some major measurement errors inside as it was written for ACS715 and I do have some problems here with the libraries since I tried to do some tests with I2C LCDs... Also, I found a lot of discussions about how that code is not working properly.

So, below  is my version of the code of the Energy meter with ACS-712-05T.



The code is heavily commented so, I believe is easy to understand what is about.






#include <Arduino.h>
#include <Wire.h>
#include <LCD.h>
#include <LiquidCrystal.h>

/* This sketch describes how to connect a ACS712 - Bidirectional Current Sense Carrier
to the Arduino, and read current flowing through the sensor.

*/

LiquidCrystal lcd(8, 9, 4, 5, 6, 7); // Easy to connect the LCD Shield

/*

Vcc on carrier board to Arduino +5v
GND on carrier board to Arduino GND
OUT on carrier board to Arduino A0

Insert the power lugs into the loads positive lead circuit,
arrow on carrier board points to load, other lug connects to
power supply positive

*/

  int batMonPin = A4;           // input pin for the voltage divider
  int batVal = 0;                     // variable for the A/D value
  float pinVoltage = 0;           // variable to hold the calculated voltage
  float batteryVoltage = 0;

  int analogInPin = A0;          // Analog input pin that the carrier board OUT is connected to
  int sensorValue = 0;            // value read from the carrier board
  int outputValue = 0;            // output in milliamps
  unsigned long msec = 0;
  float time = 0.0;
  int sample = 0;
  float totalCharge = 0.0;
  float averageAmps = 0.0;
  float ampSeconds = 0.0;
  float ampHours = 0.0;
  float wattHours = 0.0;
  float amps = 0.0;


void setup()
{
                                               // initialize serial communications at 9600 bps:
  Serial.begin(9600);
  lcd.begin(20, 4);
}



void loop()

{
 
  int sampleBVal = 0;
  int avgBVal = 0; 
  int sampleAmpVal = 0;
  int avgSAV = 0;
 
      for (int x = 0; x < 20; x++)                 // run through loop 20x


                 {
                                                                                        // read the analog in value:
        sensorValue = analogRead(analogInPin);  
        sampleAmpVal = sampleAmpVal + sensorValue;       // add samples together

        batVal = analogRead(batMonPin);                           // read the voltage on the divider
        sampleBVal = sampleBVal + batVal;                        // add samples together
 
      delay (10);                                                                // let ADC settle before next sample

                   }

   avgSAV = sampleAmpVal / 20;

                                                                                      // convert to milli amps
   outputValue = (((long)avgSAV * 4980 / 1024) - 2485 ) * 1000 / 130;  
 
/*
Modified by Adrian YO3HJV for real life ACS712-05A

Sensor outputs about 2.485 V at rest.
Analog read produces a value of 0-1023, equating to 0v to 5v.
"((long)sensorValue * 5000 / 1024)" is the voltage on the sensor's output in millivolts.
"5000"mV is ideal value, my board has 4.985 V measured with a precision Voltmeter
Therefore, we have a 2485mv offset to subtract.
The unit produces 185 mv per amp of current, so divide by 0.185 to convert mV to mA.
The documentation said that the ACS has 185mV/Amp but I measured 130 mV/ Amp.
         

*/


  avgBVal = sampleBVal / 20;                       //divide by 20 (number of samples) to get a steady reading

  pinVoltage = (avgBVal * 5.0) / 1024;      
 
                                //  Calculate the voltage on the A/D pin
                                /*  A reading of 1 for the A/D = 0.0048mV
                                    if we multiply the A/D reading by 0.00488 then
                                    we get the voltage on the pin.                                 
                                   It is a good practice to measure the Vcc with a good voltmeter and
                                   to adjust the 5.0 V to the measured value.                                  
                                    Also, depending on wiring and where voltage is being read, under
                                    heavy loads voltage displayed can be  well under voltage at supply. monitor
                                    at load or supply and decide.
*/


  batteryVoltage = pinVoltage * 10.93;    /* 10.93 is the voltage divider ratio
                                          measured with a voltmeter.
                                          First, measure the input voltage (ex. 12V)
                                          Then, measure the voltage at pin A4 (V input).
                                          Then make the ratio between and write it here.
                                          */
                                         
                                           
  amps = (float) outputValue / 1000;
  float watts = amps * batteryVoltage;
   
                                          //Here we print the data output to serial port.
                                          //Usefull for some data logging onto PC
  Serial.print("Volts = " );                      
  Serial.print(batteryVoltage);     
  Serial.print("\t Current (amps) = ");     
  Serial.print(amps); 
  Serial.print("\t Power (Watts) = ");  
  Serial.print(watts);  
 
   
  sample = sample + 1; 
  msec = millis();
 
 
 
   time = (float) msec / 1000.0;
   totalCharge = totalCharge + amps; 
   averageAmps = totalCharge / sample; 
   ampSeconds = averageAmps*time;
   ampHours = ampSeconds/3600; 
   wattHours = batteryVoltage * ampHours;
 

  Serial.print("\t Time (hours) = ");
  Serial.print(time/3600);
 
  Serial.print("\t Amp Hours (ah) = ");
  Serial.print(ampHours);
  Serial.print("\t Watt Hours (wh) = ");
  Serial.println(wattHours);
 

  lcd.setCursor(0, 0);
    lcd.print(batteryVoltage, 2);
    lcd.print(" V ");
  lcd.setCursor(11, 0);
    lcd.print(amps, 2);
  lcd.setCursor(16, 0);
    lcd.print(" A ");
 
  lcd.setCursor(0, 1);
    lcd.print(watts, 2 );
  lcd.setCursor(7, 1);
     lcd.print(" W ");
  lcd.setCursor(11, 1);
    lcd.print(time/3600);
  lcd.setCursor(16, 1);
    lcd.print(" H ");
 
  lcd.setCursor(0, 2);
    lcd.print(ampHours, 2);
    lcd.print(" Ah ");
  lcd.setCursor(11, 2);
    lcd.print(wattHours, 2);
    lcd.print(" Wh ");
 

  lcd.setCursor(0, 3);
  lcd.print("Ch/Dsc: ");
  lcd.print(totalCharge, 0);
  lcd.print("mA");
 // lcd.print(avgBVal);
 


  // wait 10 milliseconds before the next loop
  // for the analog-to-digital converter to settle
  // after the last reading:
 
  delay(10);                    
}
//END of void loop ()





 I have some plans to develop even further this project... I think is suitable for a smart monitor for my holiday house...

73 de Adrian

26 December 2014

Hytera PD-785G, scurta prezentare

In ultima saptamana am avut ocazia de a testa o statie portabila Hytera PD-785G, varf de lance in gama de statii portabile a firmei chineze.
Sunt destul de reticent cand vine vorba de statiile produse de chinezi insa Hytera se dovedeste a fi o firma cu planuri ambitioase ce a cumparat divizia de radiocomunicatii profesionale de la celebra Rhode & Schwartz, demonstrand ca doreste sa devina un jucator serios in piata DMR si TETRA.

 Ca aspect, PD-785G are un design modern, apropiat de terminalele portabile Tetra; carcasa este realizata din policarbonat, in doua nuante de gri.

Ecranul este generos, color, afisand informatiile necesare utilizatorului, inclusiv nivelul de semnal si starea bateriei precum si sincronizarea cu satelitii GPS - pentru versiunea "G".

Incarcatorul este de tip "drop in", operarea fiind simpla si intuitiva.

Spre deosebire de Motorola, a carei gama "Intellicharge" furnizeaza informatii extinse despre acumulator, acesta este simplu, indicatia incarcarii realizandu-se cu un LED bicolor.



Antena este amplasata in mijlocul partii superioare, intre butonul de volum si comutatorul de canale.

Din acest motiv, aspectul este usor diferit de cel cu care suntem obisnuiti sa il intalnim la statiile portabile, accentuand aspectul particular al PD-785G.
Antena se conecteaza la statie printr-un conector tip SMA-Reverse, ceea ce inseamna ca vom avea nevoie de un adaptor SMA-mama <> SMA-mama pentru a conecta o antena externa.
Tot in partea de sus se gaseste si un buton orange, de regula utilizat pentru anuntarea unei urgente si punerea statiei in mod automat de funtionare.
Spre deosebire de competitorul direct, Motorola, selectorul de canale are doar 16 pozitii. Desi poate parea vetust, numerotarea canalelor poate fi de ajutor atunci cand dorim sa verificam canalul pe care este statia fara sa o mai scoatem de la centura. O singura privire la selector ne informeaza pe deplin.
Tot in partea superioara se afla un LED care ofera indicatii cu privire la traficul radio in frecventa selectata.


Chiar deasupra ecranului este o mica perforatie pentru microfon; prima reactie a unui amic radioamator a fost sa intrebe daca acolo este difuzorul si daca statia poate fi utilizata ca un telefon mobil ori ca o statie Tetra.

Difuzorul se afla in spatele tastaturii numerice, chiar sub tastele de meniu si, desi deschizatura pare insuficienta, cutia de rezonanta astfel realizata asigura claritate si volum suficient chiar si pentru utilizarea in medii zgomotoase cum este, de exemplu, utilizarea in mobil.

 Tastele sunt din cauciuc si nu din plastic cauciucat cum intalnim la majoritatea statiilor chinezesti, si furnizeaza un feedback tactil clar dar discret.

Tastatura este retroiluminata insa, pentru conservarea energiei, retroiluminarea este activa in mod curent doar la ecran; numai la accesarea meniului se aprind si LED-urile de sub tastatura numerica.

In laterala stanga se afla tasta PTT si doua taste programabile. Prin intermediul soft-ului de programare se pot aloca diverse functii acestor doua taste, cum ar fi: modificarea puterii de emisie, scanare, modificarea treptelor de squelch samd.

Tasta PTT este inconjurata de o garnitura orange si este amplasata intr-o protuberanta de protectie.

Tot pe latura stanga, in partea inferioara se afla o eticheta cu modelul statiei.



Pe latura din dreapta se gaseste conectorul de accesorii. Acesta este acoperit de un capac de protectie, realizat din cauciuc. Spre deosebire de alte statii profesionale, la Hytera PD-785, capacul este fixat de corpul statiei printr-o balama.

Personal, consider ca aceasta solutie este mult mai buna comparativ cu fixarea printr-o "codita" cauciucata care, mai devreme sau mai tarziu se va rupe si va duce la pierderea protectiei.

Pentru siguranta, capacul de protectie se imobilizeaza in pozitia "inchis" cu ajutorul unui surub cu profil redus.



 Hytera PD-785 poate fi echipata cu un suport de fixare la curea, care se monteaza direct pe corpul statiei, pe o decupare de aluminiu. Gasesc foarte inspirata alegerea, spre deosebire de solutia Motorola, care a decis sa amplaseze clips-ul de curea pe spatele bateriei!
Un plus, neesential pentru functionarea statiei dar pentru precizia prelucrarii, este faptul ca nu exista niciun joc mecanic intre statiei si baterie!
Bateria cu care vine echipata statia este LiIon, 7,4V / 2000mAh, existand posibilitatea echiparii cu o baterie extinsa, de 2500mAh.
Durata de exploatare a bateriei este superioara statiei Motorola DP4801 cu care am facut unele comparatii in utilizare. Spre deosebire de Motorola, Hytera PD-785 poate fi utilizata doua zile pe bateria standard si circa 3 zile cu cea extinsa, in utilizare moderata, mixt analogic si digital.

Desi statia este, in principiu, programabila cu ajutorul calculatorului, exista posibilitatea de a programa o serie de parametri utili direct din tastatura, cu conditia activarii acestei optiuni in softul de programare. Putem programa frecventa canalului radio, ID-uri ale corespondentilor dar nu si CTCSS.

In "lumea reala", statia se prezinta bine, fiind suficient de sensibila si avand o buna procesare a semnalului inclusiv pe calea analogica.
Desi sunt unele voci care critica antena cu care statia vine echipata, personal nu am nimic de reprosat acesteia. E foarte posibil ca utilizatorii nemultumiti sa nu fi selectat gama de frecvente corecta.
Cum spuneam si mai sus, prezenta unui conector de antena este un plus pentru cei care doresc sa utilizeze statia si in mobil. Pentru ei, exista un suport auto care permite incarcarea bateriei pe durata utilizarii statiei.
Rapoartele de receptie sunt incurajatoare si nu releva nimic suspect; neanuntati, corespondentii nu au remarcat diferente intre Motorola si Hytera PD-785G.

Per ansamblu, statia este o alternativa pertinenta la rivala mult mai scumpa de la Motorola, DP-4801. Este o statie robusta, de calitate, receptia si emisia rivalizand cu orice alt competitor din gama de varf; politica de vanzare cu pret preferential catre radioamatori a dus la proliferarea Hytera PD-785G in randul utilizatorilor retelei MARC-DMR.
Pentru cei care au restrictii la bugetul destinat echipamentelor HAM, statia se prezinta si in versiunea fara GPS (PD-785), pretul ajungand astfel la aproximativ 60% din cel al unei statii Motorola DP-4801.

Chiar daca nu este "Statia", Hytera PD-785G este o alternativa serioasa, in opinia mea fiind varful in clasa de statii DMR de buget redus.

73 de Adrian, YO3HJV

Completare (26 august 2015)

Prin update FW, s-au rezolvat o serie de probleme, in special legate de FPP. Acum se poate programa si CTCSS, distinct pe Rx fata de Tx!
De asemeni, o facilitate pe care nu am gasit-o la Motorola este "Pseudo Trunk", care poate fi activata via FPP si care permite ascultarea simultana a TG-urilor active pe AMBELE TIMESLOT in frecventa respectiva! E ca si cum statia ar scana canale cu TS diferit, facilitate extrem de utila pentru monitorizarea TG internationale si a celor locale.






Most viewed posts in last 30 days