소스 검색

Add prototyping code for sending a dummy message with the nrf24l01

The firmware is developed using an aduino micro pro with an atmega32u4
as the hardware for the weather station is not ready yet.
Bernd Gottschlag 5 년 전
부모
커밋
347211065c

+ 2
- 0
weather-sensor/firmware/.gitignore 파일 보기

@@ -0,0 +1,2 @@
1
+main
2
+*.hex

+ 2
- 0
weather-sensor/firmware/compile.sh 파일 보기

@@ -0,0 +1,2 @@
1
+make main
2
+make main.hex

+ 91
- 0
weather-sensor/firmware/main.c 파일 보기

@@ -0,0 +1,91 @@
1
+//#define F_CPU 1000000UL  // Frequenz des Quarzes, ohne Quarz standardmäßig 1MHz
2
+
3
+#include <avr/io.h>
4
+#include <util/delay.h>
5
+#include <stdint.h>
6
+#include <stdio.h>
7
+#include <stdlib.h>
8
+#include <string.h>
9
+
10
+#include "nrf24l01.h"
11
+#include "uart_debug.h"
12
+
13
+//#define LED_DDR     DDRB        //DDRA, DDRB...
14
+//#define LED_PORT    PORTB       //PORTA, PORTB...
15
+//#define LED_PORTPIN PB0         //PA0, PA1..., PB0, PB1..., ...
16
+//#define time_off    8
17
+
18
+/* SPI: */
19
+#define SPI_DDR       DDRB
20
+#define SPI_SCK_PIN   PB1
21
+#define SPI_MOSI_PIN  PB2
22
+#define SPI_MISO_PIN  PB3
23
+
24
+/* NRF24L01 */
25
+
26
+
27
+
28
+/*
29
+ * CS: pin 9
30
+ * CE: pin 8
31
+ * IRQ: pin 7
32
+ */
33
+
34
+
35
+
36
+char bool_case = 0;
37
+int timer = 0;
38
+int timer_max = 0;
39
+
40
+
41
+void Initialize_SPI(void);
42
+
43
+int main (void)
44
+{
45
+	char debugString[50] = "";
46
+//	uint8_t testRegisterContent = 0x0A;
47
+//	uint8_t registerContent[5];
48
+//	char registerContentString[30];
49
+//	uint8_t lengthRead;
50
+
51
+	/* Set baud rate */
52
+	Initialize_UART(51);
53
+
54
+	sprintf(debugString, "%s\r\n", "Program start");
55
+	Print_Debug_String(debugString);
56
+
57
+	/* Initialize the SPI */
58
+	Initialize_SPI();
59
+
60
+	/* Initialize the nrf24l01 */
61
+	Initialize_NRF24L01();
62
+	// The NRF24L01 is now in the mode Standby-I.
63
+
64
+	/* Configure the transmission parameters (Enhanced ShockBurst)*/
65
+	Configure_Transmission();
66
+
67
+
68
+
69
+
70
+
71
+
72
+
73
+//	sprintf(debugString, "%s\r\n", "program end");
74
+//	Print_Debug_String(debugString);
75
+
76
+	while(1)
77
+	{
78
+		Send_Test_Message();
79
+		sprintf(debugString, "%s\r\n", "test message");
80
+		Print_Debug_String(debugString);
81
+		_delay_ms(1000);
82
+	}
83
+}
84
+
85
+void Initialize_SPI(void)
86
+{
87
+	/* Set MOSI and SCK output, all others input */
88
+	SPI_DDR = (1<<SPI_MOSI_PIN)|(1<<SPI_SCK_PIN);
89
+	/* Enable SPI, Master, set clock rate fck/16 */
90
+	SPCR = (1<<SPE)|(1<<MSTR);
91
+}

+ 14
- 0
weather-sensor/firmware/makefile 파일 보기

@@ -0,0 +1,14 @@
1
+all: main.hex
2
+
3
+clean:
4
+	rm -f main.hex
5
+	rm -f main
6
+
7
+flash: main.hex
8
+	sudo avrdude -c avr109 -b 57600 -P /dev/ttyACM0 -p m32u4 -v -U flash:w:main.hex
9
+
10
+main: main.c nrf24l01.c nrf24l01.h uart_debug.c uart_debug.h
11
+	avr-gcc main.c nrf24l01.c uart_debug.c  -o main -mmcu=atmega32u4 -Os -Wall -Wextra -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -DF_CPU=8000000UL
12
+
13
+main.hex: main
14
+	avr-objcopy -O ihex -R .eeprom main main.hex

+ 341
- 0
weather-sensor/firmware/nrf24l01.c 파일 보기

@@ -0,0 +1,341 @@
1
+#include <stdint.h>
2
+#include <avr/io.h>
3
+#include <util/delay.h>
4
+#include <stdio.h>
5
+#include <stdbool.h>
6
+
7
+#include "nrf24l01.h"
8
+#include "uart_debug.h"
9
+
10
+/* TODO
11
+ * - Build a state machine that tracks the mode the NRF is set to
12
+ * - Configuration of NRF24L01 and startup
13
+ * - Send and Receive functions
14
+ * - Interrupt handling for Send and Receive
15
+ */
16
+
17
+void Print_Register_Contents(uint8_t address);
18
+
19
+/* Startup and initial configuration of the NRF24L01 */
20
+void Initialize_NRF24L01(void)
21
+{
22
+	/* Configure the AVR pins for the nrf24l01 */
23
+	/* Set up the NRF24L01 */
24
+	NRF_CE_DDR |= (1 << NRF_CE_PIN);
25
+	NRF_CSN_DDR |= (1 << NRF_CSN_PIN);
26
+
27
+	NRF_CSN_PORT |= (1 << NRF_CSN_PIN);
28
+
29
+	/* Ensure that the CE pin is set to 0*/
30
+	NRF_CE_PORT &= ~(1 << NRF_CE_PIN);
31
+
32
+	/* Wait more than 10.3 ms to make sure the nrf24l01 is running */
33
+	_delay_ms(11);
34
+
35
+	/* Write the PWR_UP bit of the CONFIG register (EN_CRC is also set) */
36
+	Write_NRF_Register(0x0, 0xA);
37
+
38
+	/* Wait more than 1.5 ms for the change to take effect */
39
+	_delay_ms(2);
40
+
41
+	/* The NRF24L01 is now in the mode Standby-I */
42
+}
43
+
44
+void Configure_Transmission(void)
45
+{
46
+	/* 
47
+	 * - Length of CRC (CRCO in CONFIG)
48
+	 * - Enable auto acknowledgment (EN_AA)
49
+	 *   -> Register already set correctly after reset
50
+	 * - Enable data pipes (EN_RXADDR)?
51
+	 *   -> Two pipes are already enabled on reset
52
+	 * - Set up address width (SETUP_AW)
53
+	 *   -> 3 bytes
54
+	 * - Automatic Retransmission (SETUP_RETR)
55
+	 *   -> ARD = 0b0000
56
+	 *   -> 3 retransmits -> ARC = 0b0011
57
+	 *   -> Register already set correctly after reset
58
+	 * - RF Channel (RF_CH)
59
+	 *   -> RF_CH = 0b1010000
60
+	 * - RF Setup (RF_SETUP)
61
+	 *   -> first use reset values, can be fine tuned later
62
+	 * - Enable dynamic payload length (DYNPD) -> command activate + 0x73, then set bits in FEATURE?
63
+	 */
64
+
65
+	/* Set the address width to 3 bytes */
66
+	//Write_NRF_Register(0x03, 0x1);
67
+
68
+	/* Set the frequency to 1450 MHz */
69
+	Write_NRF_Register(0x05, 0x32);
70
+
71
+	/* Enable dynamic payload length */
72
+	Send_Activate_Command();
73
+	Write_NRF_Register(0x1D, 0x4); // enable dynamic payload length
74
+	Write_NRF_Register(0X1C, 0X3F); // set dynamic payload length for all data pipes
75
+
76
+	/* Set the TX address */
77
+	//Set_TX_Address(0x563412);
78
+	Set_TX_Address(0x123456);
79
+
80
+	Set_RX_P0_Address(0x123456);
81
+	
82
+
83
+	// TODO: set addresses for all data pipes
84
+}
85
+
86
+void Send_Test_Message(void)
87
+{
88
+	uint8_t buffer[4] = {0xDE, 0xAD, 0xBE, 0xEF};
89
+	bool transmissionFinished = false;
90
+	uint8_t statusContent = 0;
91
+
92
+	uint8_t registerContent[5];
93
+	uint8_t lengthRead;
94
+	char debugString[50] = "";
95
+	uint32_t timeout = 0;
96
+	/* TODO:
97
+	 * - if needed: PRIM_RX = 0
98
+	 * - Set CE = 1 for more than 10 us
99
+	 * - Wait until the transmission is finished
100
+	 * - Read number of retries for debug purposes
101
+	 * - Check if the FIFO is empty -> if not, flush it
102
+	 * - reset the interupts of the STATUS
103
+	 */
104
+	Write_Message_To_TX_FIFO(4, buffer);
105
+
106
+	/* Set CE = 1 for more than 10 us */
107
+	NRF_CE_PORT |= (1 << NRF_CE_PIN);
108
+	_delay_us(15);
109
+	NRF_CE_PORT &= ~(1 << NRF_CE_PIN);
110
+
111
+
112
+	do
113
+	{
114
+		_delay_ms(1);
115
+		lengthRead = Read_NRF_Register(0x07, registerContent);
116
+
117
+		if (lengthRead > 1)
118
+		{
119
+			sprintf(debugString, "%s\r\n", "read error");
120
+			Print_Debug_String(debugString);
121
+		}
122
+
123
+		if ((registerContent[0] & (1<<5)) != 0)
124
+		{
125
+			transmissionFinished = true;
126
+			sprintf(debugString, "%s\r\n", "TX fin");
127
+			Print_Debug_String(debugString);
128
+		}
129
+
130
+		if ((registerContent[0] & (1<<4)) != 0)
131
+		{
132
+			transmissionFinished = true;
133
+			sprintf(debugString, "%s\r\n", "max ret");
134
+			Print_Debug_String(debugString);
135
+		}
136
+		
137
+		timeout ++;
138
+	} while ((transmissionFinished == false) && (timeout < 0xFF));
139
+
140
+	if (timeout >= 0xFF)
141
+	{
142
+			sprintf(debugString, "%s\r\n", "timeout");
143
+			Print_Debug_String(debugString);
144
+	}
145
+
146
+	/* Reset the interrupts */
147
+	lengthRead = Read_NRF_Register(0x07, registerContent);
148
+	statusContent = registerContent[0] & 0x0F;
149
+	Write_NRF_Register(0x07, statusContent);
150
+
151
+	// TODO: flush FIFO if an error occured
152
+}
153
+
154
+void Print_Register_Contents(uint8_t address)
155
+{
156
+	uint8_t registerContent[5];
157
+	uint8_t lengthRead;
158
+	char debugString[50] = "";
159
+	char registerContentString[30];
160
+
161
+
162
+	lengthRead = Read_NRF_Register(address, registerContent);
163
+
164
+	registerContentString[0] = '\0';
165
+	for (uint8_t i = 0; i < lengthRead; i++)
166
+	{
167
+		sprintf(registerContentString, "%s0x%x ", registerContentString, registerContent[i]);
168
+	}
169
+	sprintf(debugString, "%s\r\n", registerContentString);
170
+	Print_Debug_String(debugString);
171
+}
172
+
173
+
174
+
175
+
176
+/* Send a message:
177
+ * - Set PRIM_RX = 0 and add one message to the TX-FIFO
178
+ * - Set CE=1 for more than 10 us
179
+ * - The NRF takes 130 us to enter the TX Mode
180
+ * - An Interrupt is generated once the 
181
+ * - 
182
+ */
183
+
184
+
185
+/* Set the NRF to RX Mode */
186
+
187
+/* Disable the RX Mode */
188
+
189
+
190
+
191
+
192
+uint8_t Read_NRF_Status_Register(void)
193
+{
194
+	NRF_CSN_PORT &= ~(1 << NRF_CSN_PIN); // Start the transmission
195
+	SPDR = 0XFF;
196
+
197
+	while(!(SPSR & (1<<SPIF))); // Wait for transmission complete
198
+
199
+	NRF_CSN_PORT |= (1 << NRF_CSN_PIN); // Stop the transmission
200
+
201
+	return SPDR;
202
+}
203
+
204
+uint8_t Read_NRF_Register(uint8_t address, uint8_t * registerContents)
205
+{
206
+	uint8_t numberOfBytes = 0;
207
+
208
+	if ((address == 0x0A) ||
209
+	    (address == 0x0B) ||
210
+	    (address == 0x10))
211
+	{
212
+		numberOfBytes = 5;
213
+	}
214
+	else
215
+	{
216
+		numberOfBytes = 1;
217
+	}
218
+
219
+	/* First write the address */
220
+	NRF_CSN_PORT &= ~(1 << NRF_CSN_PIN); // Start the transmission
221
+	SPDR = address;
222
+
223
+	while(!(SPSR & (1<<SPIF))); // Wait for transmission complete
224
+
225
+	/* Read the register bytes */
226
+	for (uint8_t i = 0; i < numberOfBytes; i++)
227
+	{
228
+		/* Write dummy data to shift in the register content */
229
+		SPDR = 0x0;
230
+		while(!(SPSR & (1<<SPIF))); // Wait for transmission complete
231
+		registerContents[i] = SPDR;
232
+	}
233
+
234
+	NRF_CSN_PORT |= (1 << NRF_CSN_PIN); // Stop the transmission
235
+
236
+	// TODO: registers with more than one byte
237
+	return numberOfBytes;
238
+}
239
+
240
+void Write_NRF_Register(uint8_t address, uint8_t registerContents)
241
+{
242
+	/* First write the write command with the address */
243
+	NRF_CSN_PORT &= ~(1 << NRF_CSN_PIN); // Start the transmission
244
+	SPDR = address | 0x20;
245
+	
246
+	while(!(SPSR & (1<<SPIF))); // Wait for transmission complete
247
+
248
+	/* Write the data byte */
249
+	SPDR = registerContents;
250
+
251
+	while(!(SPSR & (1<<SPIF))); // Wait for transmission complete
252
+
253
+	NRF_CSN_PORT |= (1 << NRF_CSN_PIN); // Stop the transmission
254
+}
255
+
256
+void Send_Activate_Command(void)
257
+{
258
+	/* First write the write command with the address */
259
+	NRF_CSN_PORT &= ~(1 << NRF_CSN_PIN); // Start the transmission
260
+	SPDR = 0x50;
261
+	
262
+	while(!(SPSR & (1<<SPIF))); // Wait for transmission complete
263
+
264
+	/* Write the data byte */
265
+	SPDR = 0x73;
266
+
267
+	while(!(SPSR & (1<<SPIF))); // Wait for transmission complete
268
+
269
+	NRF_CSN_PORT |= (1 << NRF_CSN_PIN); // Stop the transmission
270
+}
271
+
272
+
273
+
274
+void Write_Message_To_TX_FIFO(uint8_t length, uint8_t * buffer)
275
+{
276
+	NRF_CSN_PORT &= ~(1 << NRF_CSN_PIN); // Start the transmission
277
+
278
+	/* Issue the write command: */
279
+	SPDR = 0xA0;
280
+
281
+	while(!(SPSR & (1<<SPIF))); // Wait for transmission complete
282
+
283
+	/* Write the data bytes */
284
+	for (uint8_t i = 0; i < length; i++)
285
+	{
286
+		SPDR = buffer[i];
287
+		while(!(SPSR & (1<<SPIF))); // Wait for transmission complete
288
+	}
289
+
290
+	NRF_CSN_PORT |= (1 << NRF_CSN_PIN); // Stop the transmission
291
+}
292
+
293
+void Set_TX_Address(uint32_t txAddress)
294
+{
295
+	uint8_t * buffer = (uint8_t*) &txAddress;
296
+	/* First write the write command with the address */
297
+	NRF_CSN_PORT &= ~(1 << NRF_CSN_PIN); // Start the transmission
298
+	SPDR = 0x10 | 0x20;
299
+	
300
+	while(!(SPSR & (1<<SPIF))); // Wait for transmission complete
301
+
302
+	/* Write the data byte */
303
+	for (uint8_t i = 0; i < 4; i ++)
304
+	{
305
+		SPDR = buffer[i];
306
+
307
+		while(!(SPSR & (1<<SPIF))); // Wait for transmission complete
308
+	}
309
+
310
+	SPDR = 0x0;
311
+
312
+	while(!(SPSR & (1<<SPIF))); // Wait for transmission complete
313
+
314
+	NRF_CSN_PORT |= (1 << NRF_CSN_PIN); // Stop the transmission
315
+}
316
+
317
+void Set_RX_P0_Address(uint32_t rxAddress)
318
+{
319
+	uint8_t * buffer = (uint8_t*) &rxAddress;
320
+	/* First write the write command with the address */
321
+	NRF_CSN_PORT &= ~(1 << NRF_CSN_PIN); // Start the transmission
322
+	SPDR = 0x0A | 0x20;
323
+	
324
+	while(!(SPSR & (1<<SPIF))); // Wait for transmission complete
325
+
326
+	/* Write the data byte */
327
+	for (uint8_t i = 0; i < 4; i ++)
328
+	{
329
+		SPDR = buffer[i];
330
+
331
+		while(!(SPSR & (1<<SPIF))); // Wait for transmission complete
332
+	}
333
+
334
+	SPDR = 0x0;
335
+
336
+	while(!(SPSR & (1<<SPIF))); // Wait for transmission complete
337
+
338
+	NRF_CSN_PORT |= (1 << NRF_CSN_PIN); // Stop the transmission
339
+}
340
+
341
+//TODO: only write the used bytes into the address registers

+ 25
- 0
weather-sensor/firmware/nrf24l01.h 파일 보기

@@ -0,0 +1,25 @@
1
+#ifndef NRF24L01_H
2
+#define NRF24L01_H
3
+
4
+/* AVR I/O pin definionts */
5
+#define NRF_CE_DDR   DDRB
6
+#define NRF_CE_PORT  PORTB
7
+#define NRF_CE_PIN   PB4
8
+
9
+#define NRF_CSN_DDR   DDRB
10
+#define NRF_CSN_PORT  PORTB
11
+#define NRF_CSN_PIN   PB5
12
+
13
+void Initialize_NRF24L01(void);
14
+void Configure_Transmission(void);
15
+uint8_t Read_NRF_Status_Register(void);
16
+uint8_t Read_NRF_Register(uint8_t address, uint8_t * registerContents);
17
+void Write_NRF_Register(uint8_t address, uint8_t registerContents);
18
+void Send_Activate_Command(void);
19
+
20
+void Send_Test_Message(void);
21
+void Write_Message_To_TX_FIFO(uint8_t length, uint8_t * buffer);
22
+void Set_TX_Address(uint32_t txAddress);
23
+void Set_RX_P0_Address(uint32_t rxAddress);
24
+
25
+#endif

+ 23
- 0
weather-sensor/firmware/uart_debug.c 파일 보기

@@ -0,0 +1,23 @@
1
+#include <avr/io.h>
2
+#include <string.h>
3
+
4
+#include "uart_debug.h"
5
+
6
+void Initialize_UART(uint16_t baudRate)
7
+{
8
+	UBRR1H = (unsigned char)(baudRate>>8);
9
+	UBRR1L = (unsigned char)baudRate;
10
+	/* Enable receiver and transmitter */
11
+	UCSR1B = (1<<RXEN1)|(1<<TXEN1);
12
+	/* Set frame format: 8data, 2stop bit */
13
+	UCSR1C = (1<<USBS1)|(3<<UCSZ10);
14
+}
15
+
16
+void Print_Debug_String(char * debugString)
17
+{
18
+	for (uint8_t i = 0; i < strlen(debugString); i++)
19
+	{
20
+		while ( !( UCSR1A & (1<<UDRE1)));
21
+		UDR1 = debugString[i];
22
+	}
23
+}

+ 7
- 0
weather-sensor/firmware/uart_debug.h 파일 보기

@@ -0,0 +1,7 @@
1
+#ifndef UART_DEBUG_C
2
+#define UART_DEBUG_C
3
+
4
+void Initialize_UART(uint16_t baudRate);
5
+void Print_Debug_String(char * debugString);
6
+
7
+#endif

Loading…
취소
저장