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 | }
|