Forum: Mikrocontroller und Digitale Elektronik Feuchtigkeitsmessung am Attiny - Übertragung mittels 433MHZ


von Daniel G. (dgrone)


Angehängte Dateien:

Lesenswert?

Guten Tag,
ich habe in letzter Zeit ein paar Experimente an einem Attiny85 gemacht.

Mein Plan ist, dass ich Feuchtigkeitswerte von meinen Pflanzen übertrage 
mittels einen RF433 MHZ Sender.

Zudem soll noch der Akkuwert und der Temperaturwert (jeweils 10 Bit 
Werte) übertragen werden.

So, das ganze funktioniert auch schon mit den übertragen und empfangen 
der Werte. Nur ich bin mir nicht sicher, ob mein Schaltplan "ausgereift" 
ist.

Zudem soll es auch Stromgünstig laufen (Knopfzelle im Blumentopf von 3V 
nur ~1x im Jahr wechseln).


Ich bräuchte ein paar Experten, die über meinen Schaltplan gucken.

Kurze Erklärung:
- PC0 ist ein Ausgang, der alle ca. 10 Min aktiv ist. Gibt 3V aus, 
wartet ca 200ms und sendet die Werte über das 433MHZ Modul.
- PB1 ist der digitale Ausgang für das 433MHZ Modul
- PB2 ist mein "roher" 10Bit Temperaturwert. Wird beim Empfangen des 
Wertes umgerechnet.
- PB3 ist mein Feuchtigketiswert (10 Bit). Ein Wiederstand geht auf GND 
und zwei Drähte werden in der Erde einen bestimmten Widerstand haben.
- PB4 ist mein Akkuwert - da bin ich mir unschlüssig, ob das so gemacht 
wird.

Code usw. werde ich später auf mein Blog dafür auch veröffentlichen. Ich 
bin nämlich kein Elektrioniker sondern Informatiker. Daher weiß ich, 
dass der Code richtig sein sollte ;-)

Danke und viele Grüße!

von Jojo S. (Gast)


Lesenswert?

funktioniert das Messen der Akkuspannung so wirklich? Ich denke da fehlt 
ein Widerstand für einen Spannungsteiler. Wenn du den ADC so einstellst 
das Vref=VCC ist dann misst du immer 100 %. Die Referenz sollte also auf 
2,56 V oder sogar 1,1 V eingestellt werden und der Spannungsteiler so 
berechnet werden das die max. Eingangsspannung unter der Ref liegt.
Dann findest du hier im Forum noch einen alternativen Feuchtesensor der 
kapazitiv arbeitet, halt also den Vorteil das da keine Kontakte 
korrodieren können.
In deinem Schaltplan fehlt sonst nur noch ein 100 nF Keramikkondensator 
zwischen VCC und GND.

von Daniel G. (dgrone)


Lesenswert?

Hallo,
beim Akkuwert habe ich auch noch Probleme. Wie kann ich die 
Referenzspannung denn für den IC einstellen? Bekommt er seine 
Referenzspannung von NRES? Oder vom 3V (von PB0) ein Widerstand nach 
PB4?

Den Kondensator könnte ich noch einbauen. Danke.
Werde mir noch den kapazitiven Sensor hier im Forum angucken.


Am Strom kann man nicht sparen, wenn man beim Attiny85 auf "internal 
1MHZ Clock" programmiert und dann ca. alle 10min oder mehr, oder?

Oder wäre ein Zeitgeber IC, wie der NE555 noch Stromgünstiger?

Gruß

: Bearbeitet durch User
von spess53 (Gast)


Lesenswert?

Hi

Da der Sensor mit Gleichspannung läuft ist (auf Dauer) mit Elektrolyse 
zu rechnen.

MfG Spess

von Daniel G. (dgrone)


Lesenswert?

jup, darum auch den Tip von Jojo.. Kapazitiven Sensor

von dansam (Gast)


Lesenswert?

Hallo,
wäre es vielleicht möglich mal in den Code reinzuschauen?
Schlagen uns seit Wochen damit rum einen Funkschalter zu bauen mit 
jeweils einem Attiny85 an jedem Ende. Das Ganze soll einen Code senden 
und am anderen Ende empfangen. Wenn der Code mit dem einprogrammierten 
übereinstimmt soll der Schalter ausgelöst werden. Sowas gibts auch schon 
massig, aber alles für Arduino. Hatten bisher keinen Erfolg was 
umzuschreiben und unsere eigenen mühsamen Versuche hatten nur eine 
geringe Erfolgsrate von 10% oder so.
Wäre wirklich hilfreich da mal was funktionierendes zu sehen. :)
MFG D.S.

von Uwe B. (boerge) Benutzerseite


Lesenswert?

MoinMoin,

Daniel Gronewold schrieb:
> beim Akkuwert habe ich auch noch Probleme.
>
...zum Thema messen der Akku-Spannung schaue dir mal das Manual der MCU 
an. Auch bei einem Attiny85 sollte es funktionieren, dass man die Höhe 
der Versorgungsspannung indirekt über die Bandgap-Spannung ermitteln 
kann.

Ich habe dieses Verfahren auch für eine meiner Funkbrücken verwendet:

http://bralug.de/wiki/RFM12-Funkbr%C3%BCcke#Versorgungsspannung_Sender_ermitteln

Grüße Uwe

von Daniel G. (dgrone)


Lesenswert?

Hallo,
ich habe die Arduino-Software genommen. Du brauchst das Board dazu 
nicht!
Die Software lässt sich leicht installieren (bei mir Win7 x86). Spielt 
aber keine Rolle, da es für fast alle Betriebssysteme ein Treiber gibt.
Das AMTEL Studio war mir zu aufgeblasen. Ich wollte ja nur den Attiny 
programmieren.

Schritte:
- Software herunterladen (momentan 1.0.6): 
http://arduino.cc/en/Main/Software
- Treiber (Jungo-USB) installieren für das Programmierboard (Bei mir 
Diamex All-AVR Programmer / ERFOS-ISP-2): 
http://sourceforge.net/projects/libusb-win32/
- Nun nur noch den verwendeten Microkontroller raussuchen (bei Arduino 
unter Tools -> Board) auswählbar: http://highlowtech.org/?p=1695 
(Anleitung befolgen)

fertig!

Hier mein Code:
1
#include <avr/sleep.h>
2
3
//clear bit macro
4
#ifndef cbi
5
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
6
#endif
7
8
//set bit macro
9
#ifndef sbi
10
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
11
#endif
12
13
int groni_code = 817;     // Buchstaben 'HAG'
14
int nPulseLength = 101;    // Definiert von DG
15
unsigned long m_w = 1;
16
unsigned long m_z = 2; 
17
18
int watchdog_counter = 10; // hauptsache hoch, damit beim ersten mal ausgeführt wird 
19
int first_wait = 0;
20
21
#define PIN_STROM 0
22
#define PIN_SEND 1
23
24
25
#define PIN_FEUCHT 3
26
#define ANALOG_FEUCHT 3
27
28
#define PIN_TEMP 2
29
#define ANALOG_TEMP 1
30
31
#define PIN_AKKU 4
32
#define ANALOG_AKKU 2
33
34
35
#define IC_CODE 255         // 0-FF -> 255 ICs möglich!
36
#define WAIT_TO_SEND 600    // in Sekunden
37
#define WAIT_DELAY_FIRST 50 // in ms
38
#define WAIT_DELAY_END 20   // in ms
39
40
41
void transmit(int nHighPulses, int nLowPulses) {
42
  digitalWrite(PIN_SEND, HIGH);
43
  delayMicroseconds(nPulseLength * nHighPulses);
44
  digitalWrite(PIN_SEND, LOW);
45
  delayMicroseconds(nPulseLength * nLowPulses);
46
}
47
48
49
unsigned long getRandom()
50
{
51
    m_z = 36969L * (m_z & 65535L) + (m_z >> 16);
52
    m_w = 18000L * (m_w & 65535L) + (m_w >> 16);
53
    return (m_z << 16) + m_w;  /* 32-bit result */
54
} 
55
56
void setup() {
57
    // Set up FAST PWM 
58
  TCCR0A = 2<<COM0A0 | 2<<COM0B0 | 3<<WGM00;  // Set control register A for Timer 0
59
  TCCR0B = 0<<WGM02 | 1<<CS00;  // Set control register B for Timer 0
60
  TCCR1 = 0<<PWM1A | 0<<COM1A0 | 1<<CS10;  // Set control register for Timer 1
61
  GTCCR = 1<<PWM1B | 2<<COM1B0;  // General control register for Timer 1
62
  
63
  pinMode(PIN_STROM, OUTPUT);
64
  pinMode(PIN_AKKU, INPUT);
65
  pinMode(PIN_TEMP, INPUT);
66
  pinMode(PIN_FEUCHT, INPUT);
67
  pinMode(PIN_SEND, OUTPUT);
68
  
69
  setup_watchdog(6);        // approximately 1 seconds sleep
70
}
71
72
void system_sleep() {
73
  cbi(ADCSRA,ADEN);                    // switch Analog to Digitalconverter OFF
74
  set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode is set here
75
  sleep_enable();
76
  sleep_mode();                        // System actually sleeps here
77
  sleep_disable();                     // System continues execution here when watchdog timed out   
78
  sbi(ADCSRA,ADEN);                    // switch Analog to Digitalconverter ON
79
  
80
81
}
82
83
void loop() {
84
  int wait_send;
85
  int fs_in = 0;
86
  int temp_in = 0;
87
  int paritaet = 0;
88
  int akku_in = 0;
89
  int i = 0;
90
    
91
  // wenn man den Akku reinsteckt, soll der Attiny für 1min in 10 Sekunden schritten senden
92
  // danach normal
93
  if(first_wait < 7) {
94
    wait_send = 10; // alle 10 sekunden;
95
  } else {
96
    wait_send = WAIT_TO_SEND;
97
  }
98
  
99
  if(watchdog_counter >= wait_send) {
100
  
101
    digitalWrite(PIN_STROM, HIGH);   // Spannung an 
102
    delay(WAIT_DELAY_FIRST); // - danach ein Delay zum einpendeln
103
    
104
    akku_in = analogRead(ANALOG_AKKU);
105
    temp_in = analogRead(ANALOG_TEMP);
106
    fs_in = analogRead(ANALOG_FEUCHT);
107
    
108
    transmit(1, 0); // Start
109
    
110
    transmit(1, 3); // Damit der Receiver weiß, wie lang eine '0' ist
111
    transmit(3, 1); // Damit der Receiver weiß, wie lang eine '1' ist
112
    
113
    for(i = 9; i >= 0; i--) { // 9 Bits takes the 'groni_code'
114
      if(((groni_code >> i) & 1)) {
115
        transmit(3, 1);
116
        paritaet = (paritaet+1) % 2; // Parität ausrechnen.. Im Anschluss mitsenden
117
      } else {
118
        transmit(1, 3);
119
      }
120
    }
121
    
122
    if(paritaet) {
123
        transmit(3, 1);
124
    } else {
125
        transmit(1, 3);
126
    }
127
    paritaet = 0;
128
    
129
    for(i = 7; i >= 0; i--) { // 8 Bits takes the 'ic-code'
130
      if(((IC_CODE >> i) & 1)) {
131
        transmit(3, 1);
132
        paritaet = (paritaet+1) % 2;
133
      } else {
134
        transmit(1, 3);
135
      }
136
      
137
    }
138
    
139
    if(paritaet) {
140
        transmit(3, 1);
141
    } else {
142
        transmit(1, 3);
143
    }
144
    paritaet = 0; 
145
    
146
    for(i = 9; i >= 0; i--) { // 10 Bits takes the 'feucht_sensor'
147
      if(((fs_in >> i) & 1)) {
148
        transmit(3, 1);
149
        paritaet = (paritaet+1) % 2;
150
      } else {
151
        transmit(1, 3);
152
      }
153
    } 
154
    
155
    if(paritaet) {
156
        transmit(3, 1);
157
    } else {
158
        transmit(1, 3);
159
    }
160
    paritaet = 0;
161
    
162
    for(i = 9; i >= 0; i--) { // 10 Bits takes the 'tempeartatur_sensor'
163
      if(((temp_in >> i) & 1)) {
164
        transmit(3, 1);
165
        paritaet = (paritaet+1) % 2;
166
      } else {
167
        transmit(1, 3);
168
      }
169
    }
170
    
171
    if(paritaet) {
172
        transmit(3, 1);
173
    } else {
174
        transmit(1, 3);
175
    }
176
    paritaet = 0;
177
    
178
    
179
    for(i = 9; i >= 0; i--) { // 10 Bits takes the 'akku_sensor'
180
      if(((akku_in >> i) & 1)) {
181
        transmit(3, 1);
182
        paritaet = (paritaet+1) % 2;
183
      } else {
184
        transmit(1, 3);
185
      }
186
    } 
187
    
188
    if(paritaet) {
189
        transmit(3, 1);
190
    } else {
191
        transmit(1, 3);
192
    }
193
    paritaet = 0;
194
    //transmit(0,99); // sendSync muss ungerade sein!
195
    
196
    
197
    delay(WAIT_DELAY_END);            // - danach ein Delay, falls er nochwas macht
198
    digitalWrite(PIN_STROM, LOW);     // Spannung aus
199
    
200
    watchdog_counter = 0;
201
    first_wait++;
202
    
203
  }
204
  //delay(WAIT_TO_SEND+((int)getRandom()%100)); // falls 2 ICs gleichzeitig senden.. Das muss nicht sein
205
  system_sleep(); 
206
  
207
}
208
209
// 0=16ms, 1=32ms,2=64ms,3=128ms,4=250ms,5=500ms
210
// 6=1 sec,7=2 sec, 8=4 sec, 9= 8sec
211
void setup_watchdog(int ii) {
212
213
  byte bb;
214
  int ww;
215
  if (ii > 9 ) ii=9;
216
  bb=ii & 7;
217
  if (ii > 7) bb|= (1<<5);
218
  bb|= (1<<WDCE);
219
  ww=bb;
220
221
  MCUSR &= ~(1<<WDRF);
222
  // start timed sequence
223
  WDTCR |= (1<<WDCE) | (1<<WDE);
224
  // set new watchdog timeout value
225
  WDTCR = bb;
226
  WDTCR |= _BV(WDIE);
227
}
228
229
ISR(WDT_vect) {
230
  watchdog_counter++;
231
}

Ich werde aber eventuell die Ansteuerung mit VirtuelWire.h machen, da es 
anscheinend zuverlässiger funktioniert.

Gruß!

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.