Strona 1 z 1
Stacje meteo i nietylko
: niedziela 08 wrz 2013, 10:36
autor: fredek
Udało mi się w końcu dokończyć projekt mini stacji meteo
Tak się prezentuje:
A tak wygląda
interface www
Wszystkim steruje ATMega32A, obsługuje 2 wyświetlacze (tekstowy 2x16 i graficzny nokiowski), czujnik temperatury DS18B20, wilgotności DHT-22, ciśnienia BMP-085, klawiaturę matrycową, buzzerek, RTC na DS1307, pamięć 24C32 i kartę sieciową ENC28J60.
: niedziela 08 wrz 2013, 12:23
autor: Marooned
fredek, masz gdzieś większe info o bebechach? (forum Elektrody?)
Ja chcę swoją zmontować na balkonie i połączyć skrętką do "centrum dowodzenia", więc podglądam projekty innych.
: niedziela 08 wrz 2013, 13:03
autor: fredek
Marooned: pełnego schematu w eagle nie mam... robiłem to z modułów kupowanych na e-bay jak miałem trochę wolnego czasu.
Moja płytka jest tylko jedna ze sterowaniem podświetleniem wyświetlaczy i buzzerka, konwerterem napięcia dla karty sieciowej i rozprowadzenie sygnałów I2C, SPI oraz 1wire do modułów. Oprogramowanie w C też pisałem na raty,
Barney też pomógł (napisał libs-a do wyświetlacza
nokii i BMP-085, robił też optymalizacje kodu dla eth i statystyk).
: niedziela 08 wrz 2013, 13:20
autor: Marooned
Schematu nie oczekiwałem (każdy projekt jest nieco inny) tylko takich ogólnych (choć konkretnych) info.
Dzięki
Ja w swoim domu zaszywam 10 DS18B20, na zewnątrz też DS18B20 + właśnie jakieś (jeszcze nie sprecyzowane) czujniki ciśnienia, wilgotności i zobaczymy, co jeszcze wydumam.
: niedziela 08 wrz 2013, 13:54
autor: fredek
Marooned pisze:Ja w swoim domu zaszywam 10 DS18B20, na zewnątrz też DS18B20 + właśnie jakieś (jeszcze nie sprecyzowane) czujniki ciśnienia, wilgotności i zobaczymy, co jeszcze wydumam.
To takie 2 uwagi w ramach OT:
1. W pewnym momencie miałem 7 czujników 1wire na testach i bez tablicowania ID z rom-code to ciężko było się w tym połapać, pamiętaj o tym. Przy tych czujnikach to pisz funkcje nieblokujące - zapomnij o _delay_ms, tylko timery na przerwaniach i liczniki. Rezystor podciągający do VCC też możesz dać mniejszy dla trybu normal np. 3k a dla parasite nawet 1,5kOhma zwłaszcza jak masz dużo kabla.
2. Czujniki ciśnienia i temperatury też mają czujniki temperatury (dla kompensacji) także możesz je wykorzystać, są całkiem dokładne i szybciej działają. Tylko musisz je wystawić poza obudowę urządzenia jak mają pokazywać dokładną temperaturę.
Powodzenia!
: niedziela 08 wrz 2013, 14:11
autor: Marooned
Sieć 1-wire będzie obsługiwana przez Raspberry Pi i jej bibliotekę. Tylko zewnętrzna stacja w planach jest po skrętce [jeszcze nie wybrałem typu komunikacji] (plus pewnie jakiś AVR), bo każdy z 3 czujników jest na inną magistralę. DS na 1-wire, wilgoć jakiś niekompatybilny "1-wire", ciśnienie I2C. Nie znalazłem 2 ostatnich na 1-wire.
A co do połapania się, to w planach oczywiście najpierw odczytanie ID dla każdego czujnika przed wpięciem do magistrali by potem wiedzieć który gdzie. A w ostateczności można też jeden ogrzać i zobaczyć który ID pokazuje skok temperatury
Ok, nie będziemy już ciągnąć off-topicu bo mnie pogonią
: niedziela 08 wrz 2013, 20:37
autor: DNF
Panowie, jeśli chcecie sobie pogawożyć nt stacji meteo, to mogę Wam wydzielić temat. Chcecie?
: niedziela 08 wrz 2013, 21:30
autor: fredek
DNF, przenoś, może Barney się swoją też pochwali... pewnie więcej ludzi majstruje takie dziwactwa
: niedziela 08 wrz 2013, 21:53
autor: belushi
Nie majstruje, bo za głupi na to, ale chętnie poczyta, może coś wykmini.
B
co zawsze chciał mieć stacje, różne stacje
: niedziela 08 wrz 2013, 22:48
autor: bulwa11
Od dawna mi się marzy taka stacja bo mam małego hopla na punkcie pogody. Nie chwaląc się prowadzę od prawie 3 lat zapiski dzień po dniu z danymi (subiektywnymi) pogodowymi (temp max, min, zachmurzenie max, min, rodzaj opadu, skala opadu, w zimie pokrywa śnieżna, zmiana pokrywy, inne zjawiska (burza, grad, susza itp) i takie tam. Nie wiem po co mi to, ale fajne
Brakuje jednak pomiaru wilgotności, ilości opadu, wiatru i najlepiej automatyzacji. Może kiedyś
Tak to wygląda:
: niedziela 15 wrz 2013, 23:41
autor: barney
: poniedziałek 16 wrz 2013, 09:27
autor: kisi
barney, czy nie miałeś problemów z BMP085? Mój egzemplarz troszkę fiksuje, tzn. pokazuje jakieś z sufitu ciśnienie. Owszem mogę wprowadzić korektę, ale obawiam się czy aby błąd nie jest nieliniowy i odstępstwo od nomy będzie większe.
: poniedziałek 16 wrz 2013, 16:15
autor: fredek
kisi, sprawdzałeś na innym egzemplarzu czy też jest problem?
Może algorytm obliczeń ma jakieś błędy, łatwo to sprawdzić bo na 13 stronie pdf od czujnika są przykładowe dane i obliczenia, warto zweryfikować.
Błędy mogą też wynikać z niewłaściwej inicjacji lub za szybkiego odczytu - bez zachowania czasu potrzebnego na konwersję danych i odpowiedź przez czujnik.
: poniedziałek 16 wrz 2013, 16:55
autor: barney
Miałem trochę problemów na etapie pisania libsa, a potem już bez problemów. Algorytm podany w specyfikacji nie lubi się z rzutowaniem do int przez kompilator, trzeba zrobić trochę jawnych rzutowań.
bBPM085.h
Kod: Zaznacz cały
/*
* BMP085 library
* Autor: barney
*/
#include <avr/io.h>
#ifndef BBMP085_H_
#define BBMP085_H_
uint8_t bmp085_init (uint8_t oversampling_setting); // if return !=0 then data communication problem
void bmp085_temp_start (void);
int16_t bmp085_temp_read (void);
void bmp085_press_start (void);
int32_t bmp085_press_read (void);
// Modes of pressure measurement (oversampling_setting)
// Number of internal samples is 2^define
#define BMP085_PRESS_ULP 0 // wait 4.5 ms
#define BMP085_PRESS_STD 1 // wait 7.5 ms
#define BMP085_PRESS_HR 2 // wait 13.5 ms
#define BMP085_PRESS_UHR 3 // wait 25.5 ms
/*
* FIRST RUN
* ||
* ||
* \ /
* \/
* bmp085_init <===========\\
* || YES
* || ||
* |/ <===== NO = change number of
* || pressure samples?
* || ||
* \ / ||
* \/ ||
* bmp085_temp_start ||
* || ||
* || ||
* \ / ||
* \/ ||
* wait >4.5ms ||
* || ||
* || ||
* \ / ||
* \/ ||
* bmp085_temp_read ||
* || ||
* pressure? = NO ======>/|
* || ||
* YES ||
* || ||
* \ / ||
* \/ ||
* bmp085_press_start ||
* || ||
* || ||
* \ / ||
* \/ ||
* wait >define ||
* || ||
* || ||
* \ / ||
* \/ ||
* bmp085_press_read =====>//
*/
#include "../I2C_TWI/i2c_twi.h" // Connecting this library with i2c lib
inline void bmp085_start (void)
{
TWI_start ();
}
inline void bmp085_write (uint8_t command)
{
TWI_write (command);
}
inline uint8_t bmp085_read (uint8_t command)
{
return TWI_read (command);
}
inline void bmp085_stop (void)
{
TWI_stop ();
}
#define BMP085_NAME_READ 0b11101111
#define BMP085_NAME_WRITE 0b11101110
#define BMP085_ACK 1
#define BMP085_NACK 0
#endif /* BBMP085_H_ */
bBMP085.c
Kod: Zaznacz cały
/*
* BMP085 library
* Autor: barney
*/
#include "bBMP085.h"
static struct
{
uint8_t oss;
int32_t b5;
struct
{
int16_t ac1;
int16_t ac2;
int16_t ac3;
uint16_t ac4;
uint16_t ac5;
uint16_t ac6;
int16_t b1;
int16_t b2;
int16_t mb;
int16_t mc;
int16_t md;
} memory;
} bmp085;
static uint16_t bmp085_read_eeprom (uint8_t adress)
{
register uint16_t data;
bmp085_start ();
bmp085_write (BMP085_NAME_WRITE);
bmp085_write (adress);
bmp085_start ();
bmp085_write (BMP085_NAME_READ);
data = bmp085_read (BMP085_ACK);
data = (data<<8) + bmp085_read(BMP085_NACK);
bmp085_stop ();
if ((!data) || (data==0xFFFF)) bmp085.oss=0xFF;
return data;
}
uint8_t bmp085_init (uint8_t oversampling_setting)
{
bmp085.oss=0; // Using oss as error value.
bmp085.memory.ac1=bmp085_read_eeprom (0xAA);
bmp085.memory.ac2=bmp085_read_eeprom (0xAC);
bmp085.memory.ac3=bmp085_read_eeprom (0xAE);
bmp085.memory.ac4=bmp085_read_eeprom (0xB0);
bmp085.memory.ac5=bmp085_read_eeprom (0xB2);
bmp085.memory.ac6=bmp085_read_eeprom (0xB4);
bmp085.memory.b1= bmp085_read_eeprom (0xB6);
bmp085.memory.b2= bmp085_read_eeprom (0xB8);
bmp085.memory.mb= bmp085_read_eeprom (0xBA);
bmp085.memory.mc= bmp085_read_eeprom (0xBC);
bmp085.memory.md= bmp085_read_eeprom (0xBE);
if (bmp085.oss) return bmp085.oss;
bmp085.oss=oversampling_setting;
return 0;
}
void bmp085_temp_start (void)
{
bmp085_start ();
bmp085_write (BMP085_NAME_WRITE);
bmp085_write (0xF4);
bmp085_write (0x2E);
bmp085_stop ();
}
int16_t bmp085_temp_read (void)
{
bmp085_start ();
bmp085_write (BMP085_NAME_WRITE);
bmp085_write (0xF6);
bmp085_start ();
bmp085_write (BMP085_NAME_READ);
int32_t ut= bmp085_read (BMP085_ACK);
ut= (ut<<8) + bmp085_read (BMP085_NACK);
bmp085_stop ();
int32_t x1 = (((int32_t) ut - bmp085.memory.ac6) * bmp085.memory.ac5)>>15 ;
int32_t x2 = ((int32_t) bmp085.memory.mc<<11) / (x1 + bmp085.memory.md);
bmp085.b5 = x1 + x2;
// bmp085.b5 = 3912;
return (bmp085.b5 + 8)>>4;
}
void bmp085_press_start (void)
{
bmp085_start ();
bmp085_write (BMP085_NAME_WRITE);
bmp085_write (0xF4);
bmp085_write (0x34+(bmp085.oss<<6));
bmp085_stop ();
}
int32_t bmp085_press_read (void)
{
bmp085_start ();
bmp085_write (BMP085_NAME_WRITE);
bmp085_write (0xF6);
bmp085_start ();
bmp085_write (BMP085_NAME_READ);
int32_t up= bmp085_read (BMP085_ACK);
up= (up<<8) + bmp085_read (BMP085_ACK);
up= ((up<<8) + bmp085_read (BMP085_NACK)) >> (8-bmp085.oss);
bmp085_stop ();
int32_t b6=bmp085.b5-4000;
int32_t x1=(bmp085.memory.b2*((b6*b6)>>12))>>11;
int32_t x2=(bmp085.memory.ac2*b6)>>11;
int32_t x3=x1+x2;
int32_t b3=(((((int32_t)bmp085.memory.ac1<<2)+x3)<<bmp085.oss)+2)>>2;
x1=(bmp085.memory.ac3*b6)>>13;
x2=(bmp085.memory.b1*((b6*b6)>>12))>>16;
x3=((x1+x2)+2)>>2;
uint32_t b4=(bmp085.memory.ac4*(uint32_t)(x3+32768))>>15;
uint32_t b7=((uint32_t)up-b3)*(50000>>bmp085.oss);
int32_t p;
if (b7<0x80000000)
p=(b7<<1)/b4;
else
p=(b7/b4)<<1;
x1=(p>>8)*(p>>8);
x1=(x1*3038)>>16;
x2=(-7357*p)>>16;
return p+((x1+x2+3791)>>4);
}
Taki kod działa u mnie bez najmniejszych problemów już z pół roku. Pamiętaj, że to ty musisz zapewnić odstęp czasowy między funkcjami żądania, a odczytu
: wtorek 17 wrz 2013, 06:54
autor: kisi
OK, dzięki za listing, będę analizował. Gdzieś na forach wyczytałem że czujnik (scalak) ten jest wrażliwy na przegrzanie w czasie procesu produkcyjnego...
Sam go nie lutowałem, kupiłem gotowy moduł i chciałem wykorzystać w swojej stacji używając do tego arduino.