Explorar el Código

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 hace 5 años
padre
commit
347211065c

+ 2
- 0
weather-sensor/firmware/.gitignore Ver fichero

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

+ 2
- 0
weather-sensor/firmware/compile.sh Ver fichero

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

+ 91
- 0
weather-sensor/firmware/main.c Ver fichero

@@ -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 Ver fichero

@@ -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 Ver fichero

@@ -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 Ver fichero

@@ -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 Ver fichero

@@ -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 Ver fichero

@@ -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…
Cancelar
Guardar