Forum: Mikrocontroller und Digitale Elektronik Auslesen eines Feuchtigkeitssensors (catnip moisture sensor)


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Julius (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Hallo,



mein erstes Experiment mit I2C will nicht so ganz durchstarten....
Der Sensor blinkt einmal kurz wenn die Spannung angeht gibt aber 
ansonsten keine Werte aus soweit ich das beurteilen kann.

Der Sensor [1] gibt den Feutchtigkeitswert in 2 byte zurück, den Code 
habe ich von hier [2] umgewandelt.

Als I2C Library kommt [3] zum Einsatz und der I2C Code ist dem Beispiel 
auf der Seite nach gebaut.



Als Debug Lösung um zu sehen ob überhaupt etwas vom Sensor blinkt eine 
LED von 0 ... moist[0] welches das erste byte das der Sensor ausspuckt 
anzeigt und das gleiche noch einmal für das andere byte moist[1] - Die 
Zahl ist hier natürlich auseinandergerissen, aber für den Anfang wäre 
ich dankbar wenn überhaupt mal etwas blinken würde.


Verkabelung:

Sensor -> Schaltung
VCC -> VCC
GND -> GND
SDA -> SDA
SCL -> SCL


Was funktioniert:
Bluetooth in Verbindung mit einem Android Handy und "Bluetooth Terminal"
Die LED ist richtig angeschlossen....sehr selten blinkt Sie einmal.


Was nicht funktioniert:
Auslesen des Sensors


Zum testen steht der Sensor zur Hälfte in einem Wasserglas.
Bin mir aber nicht sicher welcher Wert hier angezeigt werden sollte.


[1] https://www.tindie.com/products/miceuz/i2c-soil-moisture-sensor/
[2] https://github.com/Miceuz/i2c-moisture-sensor   (Beispiel 3)
[3] 
http://homepage.hispeed.ch/peterfleury/doxygen/avr-gcc-libraries/group__pfleury__ic2master.html

1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include <util/delay.h>
4
#include <string.h>
5
6
7
// i2c
8
#include <i2cmaster.h>
9
#define moisture  0x20      // device the address for the moisture sensor
10
11
12
// you always read online that the modules are preset to 9600 bauds, i just found one source who said otherwies.
13
// but that source could have been confused by the fact that the AT command mode works with 38400
14
#define BAUD 9600
15
/*
16
* dont forget to define F_CPU in the Makefile.
17
* something like:
18
* F_OSC = 16000000
19
* F_CPU = $(F_OSC)
20
* CFLAGS = -mmcu=$(DEVICE) -DF_CPU=$(F_CPU)
21
* 
22
* sometimes F_OSC is used, probably just another name for F_CPU
23
*/
24
25
#define MYUBRR ((uint16_t) ((F_CPU / ((BAUD) * 16.0)) + .5) - 1)
26
#define LED1 PD6
27
#define LED2 PD7
28
29
30
// contains what the bluetooth module received
31
uint8_t data;
32
33
void USART_Init(unsigned int ubrr) {
34
    // set baud rate
35
    UBRRH = (unsigned char)(ubrr>>8);
36
    UBRRL = (unsigned char)(ubrr);
37
    // enable receiver, transmitter and interrupts for rx/tx
38
    UCSRB = (1<<RXEN) | (1<<TXEN) | (1<<RXCIE) | (1<< TXCIE);
39
    // frame format: 8 bits data, 1 stop bit, no parity - these are the default settings for atmega168.
40
    // no change needed
41
    // could be changed here: //(0<<UPM00) not tested
42
    // UCSR0C = (1<<UCSZ00) | (1<<UCSZ01) | (0<<UPM00) | (0<<UPM01);
43
}
44
45
46
47
void USART_transmit(char c) {
48
    // the commented out test if we are ready to send should work too
49
    // while ((UCSR0A & (1 << UDRE0)) == 0) {};
50
    while ( !(UCSRA & (1<<UDRE)) ) {}
51
    UDR = c;
52
}
53
54
55
56
57
58
/*
59
* turn on led1 and led2, wait 200ms, turn them off - do this three times
60
* looks like a flashing led
61
*/
62
void flash_leds(void) {
63
    for (int n=0; n<3; n++) {
64
        PORTD |= (1 << LED1); // Turn on LED1
65
        PORTD |= (1 << LED2); // Turn on LED2
66
        _delay_ms(200);
67
        PORTD &= ~(1 << LED1); // Turn off LED1
68
        PORTD &= ~(1 << LED2); // Turn off LED2
69
        _delay_ms(200);
70
    }
71
}
72
73
74
// holds the moisture value
75
uint8_t moist[2];
76
77
78
79
void getMoisture(void) {
80
    i2c_init();                             // initialize I2C library
81
    i2c_start_wait(moisture+I2C_WRITE);       // set device address and read mode
82
    
83
    // the register we want to access, 0x00 is moisture. sensor also provides temperature and other things 
84
    i2c_write(0x00);
85
86
    i2c_rep_start(moisture+I2C_READ);    
87
    moist[0] = ((uint8_t)i2c_readAck())<<8; // read 2 bytes
88
    moist[0]|= i2c_readAck();
89
    moist[1] = ((uint8_t)i2c_readAck())<<8;
90
    moist[1]|= i2c_readAck();
91
    i2c_stop();                             // end communication
92
}
93
94
95
96
int main(void) {
97
98
    DDRD |= (1 << LED1);
99
   
100
    
101
    sei();
102
103
    
104
    //USART_Init(MYUBRR);
105
    _delay_ms(10);
106
      
107
    while(1) {
108
        
109
        // get a new moisture value
110
        getMoisture();
111
112
        for (uint8_t n=0; n<=moist[0]; n++) {
113
            PORTD |= (1 << LED1); // Turn on LED1
114
            _delay_ms(200);
115
            PORTD &= ~(1 << LED1); // Turn off LED1
116
            _delay_ms(200);
117
        }
118
119
        _delay_ms(2000);
120
121
        for (uint8_t n=0; n<=moist[1]; n++) {
122
            PORTD |= (1 << LED1); // Turn on LED1
123
            _delay_ms(200);
124
            PORTD &= ~(1 << LED1); // Turn off LED1
125
            _delay_ms(200);
126
        }
127
        _delay_ms(2000);
128
        
129
130
        // this is for testing the for loop, if the led blinks as expected. 
131
        // WORKS
132
        /*
133
        moist[0] = 5;
134
        moist[1] = 10;        
135
        for (uint8_t n=0; n<=moist[0]; n++) {
136
            PORTD |= (1 << LED1); // Turn on LED1
137
            _delay_ms(200);
138
            PORTD &= ~(1 << LED1); // Turn off LED1
139
            _delay_ms(200);
140
        }
141
        _delay_ms(3000);
142
143
        for (uint8_t n=0; n<=moist[1]; n++) {
144
            PORTD |= (1 << LED1); // Turn on LED1
145
            _delay_ms(200);
146
            PORTD &= ~(1 << LED1); // Turn off LED1
147
            _delay_ms(200);
148
        }
149
        _delay_ms(3000);
150
        */
151
152
       
153
        // send the data via bluetooth, see above...data invalid?
154
        /* 
155
        // for now only send half of the data
156
        // sending 2 bytes, set bluetooth terminal to hex encoding
157
        USART_transmit(moist[0]);
158
        USART_transmit(moist[1]);
159
        //USART_transmit('\r');   
160
        //USART_transmit('\n');    
161
        */
162
        
163
            
164
        // for testing the bluetooth code
165
        // WORKS
166
        // this transmits 'a' every 2 seconds -> bluetooth is working
167
        /*
168
        USART_transmit('a');        
169
        USART_transmit('\r');   
170
        USART_transmit('\n');    
171
        _delay_ms(2000);
172
        */
173
174
    }
175
}
176
177
178
179
180
// this is the interrupt service routine for receiving (its named differently on atmega32 for example)
181
ISR(USART_RXC_vect)
182
{
183
    data = UDR;
184
    if (data == 'h') {
185
        PORTD |= (1 << LED1); // Turn on LED1
186
        PORTD &= ~(1 << LED2); // Turn off LED2
187
    }
188
    else if (data == 'z') { 
189
        PORTD &= ~(1 << LED1); // Turn off LED1
190
        PORTD |= (1 << LED2); // Turn on LED2
191
    }
192
    // the terminal app terminates each string with '\r\n' - the windows way of a newline
193
    // (linux only uses '\n')
194
    // so, if we dont skip '\n' and '\r' here and send z led1 will go on for some microseconds? or shorter
195
    // - you wont see led 1 going on.
196
    // because after the code read the z it will immediately receive the next character, which is a '\r'
197
    // and the leds will blink. same for '\n'
198
    else if (data == '\n') {
199
        // do nothing
200
    }
201
    else if (data == '\r') {
202
        // do nothing
203
    }
204
    else {
205
        //send_string(data);
206
        flash_leds();
207
    }
208
}
209
210
211
// same as above for transfer
212
ISR(USART_TXC_vect)
213
{
214
    //data = 0;
215
    //PORTD &= ~(1 << LED1); // Turn off LED1
216
    //PORTD |= (1 << LED2); // Turn on LED2
217
}

von Dennis K. (scarfaceno1)


Bewertung
0 lesenswert
nicht lesenswert
Julius schrieb:
> Zum testen steht der Sensor zur Hälfte in einem Wasserglas.

Bin mir nicht sicher ob er das aushält...


The sensor comes coated with PRF202 - a moisture resistant varnish for 
electronics. It's ok for play around in a flower pot but not enough for 
outdoor use. You must add an additional protection to the whole sensor 
after soldering cable to it!

von Julius (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Oh, guter Hinweis. Dachte die Elektronik am oberen Ende ist nur 
offen...der untere Teil sah vergossen aus.

von Jim M. (turboj)


Bewertung
0 lesenswert
nicht lesenswert
Julius schrieb:
> Sensor -> Schaltung
> VCC -> VCC
> GND -> GND
> SDA -> SDA
> SCL -> SCL

Pullups am I²C Bus vorhanden? Sonst tut der nix.

von Mario M. (thelonging)


Bewertung
0 lesenswert
nicht lesenswert
Probiere mal "#define moisture 0x40". Könnte sich um das typische 
I²C-Adressierungs-Problem zu handeln.

von Julius (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Ja, Pullups sind vorhanden. Hatte ich ganz vergessen.

SDA -> 5.1K -> VCC
SLC -> 5.1K -> VCC

von Julius (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Mario M. schrieb:
> Probiere mal "#define moisture 0x40". Könnte sich um das typische
> I²C-Adressierungs-Problem zu handeln.

Warum 0x40?

Leider keine Abhilfe.

von Julius (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Der Sensor hat vielleicht schon einen Weg, mit Pullup ist SDA und SLC 
dauerhaft auf 5V laut Oszilloskop, ohne aber auch.

von Georg (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Julius schrieb:
> Der Sensor hat vielleicht schon einen Weg

Dieser Weg wird kein leichter sein. Oder ist das der Weg, der das Ziel 
ist?

Georg

von Wolfgang (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Julius schrieb:
> Warum 0x40?

Weil der Sensor die 7-Bit I2C Adresse 0x20 hat und du eine Funktion 
verwendest, die als Argument das erste Byte der Übertragung benötigt.

Eine Sensor, der die Adresse 0x21 hat könntest du mit deiner Methode gar 
nicht ansprechen, weil sich das unterste Bit der Adresse mit dem R/W-Bit 
überlagert.

Julius schrieb:
> i2c_start_wait(moisture+I2C_WRITE);       // set device address and

Aber das Problem hatten wir gerade: 
Beitrag "I2C SHT31 i2cmaster.h"

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.