Stacje meteo i nietylko
Stacje meteo i nietylko
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.
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.
Ostatnio zmieniony środa 14 maja 2014, 19:25 przez fredek, łącznie zmieniany 1 raz.
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.
Ja chcę swoją zmontować na balkonie i połączyć skrętką do "centrum dowodzenia", więc podglądam projekty innych.
"In the brave new world of the year 2000, a kiss can still break your heart." - Program from Cirque du Soleil's Alegría
Nad tymi gwiazdami jest wszechświat szybujących potworów! Wiedziałaś?
Nad tymi gwiazdami jest wszechświat szybujących potworów! Wiedziałaś?
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).
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).
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.
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.
"In the brave new world of the year 2000, a kiss can still break your heart." - Program from Cirque du Soleil's Alegría
Nad tymi gwiazdami jest wszechświat szybujących potworów! Wiedziałaś?
Nad tymi gwiazdami jest wszechświat szybujących potworów! Wiedziałaś?
To takie 2 uwagi w ramach OT: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.
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!
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ą
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ą
"In the brave new world of the year 2000, a kiss can still break your heart." - Program from Cirque du Soleil's Alegría
Nad tymi gwiazdami jest wszechświat szybujących potworów! Wiedziałaś?
Nad tymi gwiazdami jest wszechświat szybujących potworów! Wiedziałaś?
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:
Brakuje jednak pomiaru wilgotności, ilości opadu, wiatru i najlepiej automatyzacji. Może kiedyś
Tak to wygląda:
Po lewej stronie procka zegar RTC oraz czujnik ciśnienia BMP085. Na połowie prawej strony od procka buzzer, układ dekodera klawiatury matrycowej oraz dekoder cyfry IW18. Na samym prawym brzegu część wysokonapięciowa do IW18.
Jak widać wykonanie "na pająka" Napięcie do IW18 to ~42V (max dla przetwornicy).
Wydaje mi się, że ciekawie rozwiązałem kwestie multipleksowania:
Segmenty do IW18 to cały PORTA bezpośrednio na bufor TD62783AP. Cyfry idą najpierw na MH7442, potem są negowane na 7400 i dopiero teraz idą na drugi bufor TD62783AP. Ten sam sygnał do MH7442 dla IW18 jest wykorzystywany do multipleksowania klawiatury matrycowej (za pomocą drugiego MH7442), według mojego pomysłu: http://forum.atnel.pl/topic3584.html. Pozwoliło to obskoczyć IW18 oraz klawiaturę wykorzystując jedynie 12 pinów uC (8segmenty + 3BCD + 1 do detekcji klawisza).
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.
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.
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
bBMP085.c
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
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_ */
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);
}