Skip to content

Commit ed89a70

Browse files
authored
Merge pull request #12 from PaulThbt/main
Chirp doc v1.0 & error management for chirp functions
2 parents 58265c1 + 300152e commit ed89a70

File tree

17 files changed

+201
-222
lines changed

17 files changed

+201
-222
lines changed

docs/Library/DAC.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,14 +49,14 @@ typedef struct {
4949
#### Fields
5050
{: .no_toc}
5151
* `dac_channel`: Selects the DAC channel (channel 1 or channel 2)
52-
* `sampling_freq`: Specified DAC sampling frequency. Maximum value that can be set is 60 GHz.
52+
* `sampling_freq`: Specified DAC sampling frequency. Maximum value that can be set is 15 MHz.
5353
* `mem_address`: Address of the array's first element written to DAC
54-
* `mem_size`: Number of array elements
54+
* `mem_size`: Number of array elements.
5555
* `wave_mode`:
5656
* `SENSEDU_DAC_MODE_CONTINUOUS_WAVE`
5757
* `SENSEDU_DAC_MODE_SINGLE_WAVE`
5858
* `SENSEDU_DAC_MODE_BURST_WAVE`
59-
* `burst_num`: Number of instances of specified LUT.
59+
* `burst_num`: Number of instances of specified LUT.
6060

6161
#### Notes
6262
{: .no_toc}

docs/Projects/Chirp.md

Lines changed: 107 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,75 +1,145 @@
11
---
2-
title: Chirp
2+
title: Chirp Signal Generation
33
layout: default
44
math: mathjax
55
parent: Projects
66
nav_order: 2
77
---
88

9-
# PCB
10-
{: .fs-8 .fw-500}
9+
# Chirp Signal Generation
10+
{: .no_toc .fs-8 .fw-500}
1111
---
1212

13-
very cool pcb for sensedu shield for arduino giga r1... (short description)
13+
The **chirp signal generation project** aims at proviving basic code to generate **frequency modulated continuous waves (FMCW)** on the **SensEdu Shield** using the **Arduino Giga R1**. The projects provides two types of frequency modulation : **sawtooth** and **triangular**.
14+
15+
Chirp signals are encountered in numerous fields like radar & sonar systems, telecommunications, signal processing and more. You will find more information on the potential applications from our upcoming FMCW radar project.
16+
17+
<img src="{{site.baseurl}}/assets/images/Chirp_signal.png" alt="drawing" width="500"/>
18+
{: .text-center}
19+
20+
Chirp signal sweeping from 100 Hz to 10 kHz
21+
{: .text-center}
22+
23+
<img src="{{site.baseurl}}/assets/images/Chirp_spectro.png" alt="drawing" width="499"/>
24+
{: .text-center}
25+
26+
Spectrogram of chirp sweeping from 100 Hz to 10 kHz
27+
{: .text-center}
28+
29+
1430
{: .fw-500}
1531

16-
- TOC
32+
## Table of contents
33+
{: .no_toc .text-delta }
34+
1. TOC
1735
{:toc}
1836

19-
## Chapter 1
37+
## Chirp Generation Function
38+
Arduino does not provide any built-in chirp signal function. There are workarounds using MATLAB's built-in chirp function but our idea was to create this signal directly in Arduino with the SensEdu library.
2039

21-
TODO: exaplanations about component specifics, voltages, range
40+
The `generateSawtoothChirp` and `generateTriangularChirp` functions both calculate the values to generate a sawtooth chirp and triangular chirp respectively and copy these values to the DAC's buffer.
2241

23-
TODO: voltage for DC jack
42+
```c
43+
void generateSawtoothChirp(uint16_t* array)
44+
void generateTriangularChirp(uint16_t* array)
45+
```
2446
25-
TODO: aplifiers gain
47+
### Parameters
48+
* `uint16_t* array` : A pointer to an array where the generated chirp signal will be stored.
2649
27-
TODO: screenshots of specific parts of schematics for better understanding
2850
29-
TODO: eveything needed for board modifications, pitfalls and problems
3051
31-
TODO: guide, how to order the board
52+
### Description
53+
The generate chirp functions use two arrays `lut_sine` and `vChirp` to calculate the chirp values :
3254
55+
* `lut_sine` is a LUT containing the values of a quarter sine wave. The `x` variable defines the resolution of `lut_sine`. A larger `x` will result in a more detailed LUT with more values which in turn increases the precision of the chirp values which will be calculated.
56+
* `vChirp` is the array in which the chirp values are calculated.
3357
34-
styling examples:
35-
* check library documentation code
36-
* [link1]
37-
* [link2]
3858
39-
---
59+
The following steps describe how the function was implemented :
4060
41-
example text
61+
**Step 1**{: .text-blue-000} : Generate the quarter-wave LUT
4262
43-
[example link]
63+
```c
64+
// Generate the quarter-wave sine LUT
65+
for (int i = 0; i < 90 * x; i++) {
66+
float phase_deg = (float)i * 90.0 / (90 * x); // Phase angle in degrees
67+
float phase_rad = phase_deg * Pi / 180.0; // Phase angle to radians
68+
lut_sine[i] = sin(phase_rad-Pi/2); // Store sine value in the LUT
69+
}
70+
```
71+
72+
**Step 2**{: .text-blue-000} : Calculate the instantaneous phase of the chirp signal and wrap between 0-360 degrees
4473

45-
example list:
46-
* sdsd
47-
* sdsds
48-
* sdsds
74+
```c
75+
for (int i = 1; i < samples_int + 1; i++) {
76+
float phase_rad = 2.0 * Pi * (0.5 * sK * (i - 1) / fs + START_FREQUENCY) * (i - 1) / fs; // Phase angle in radians
77+
float phase_deg = phase_rad * 180.0 / Pi; // Phase angle to degrees
78+
float phase_deg_wrapped = fmod(phase_deg, 360.0); // Wrap phase angle to 0-360 degrees
79+
```
4980
50-
example list 2:
51-
1. sdsd
52-
2. sdsds
53-
3. sdsds
81+
**Step 3**{: .text-blue-000} : Calculate the value of the chirp using a quadrant-based approach. Scale and offset values to get 12 bit values.
5482
55-
`marked text`
83+
```c
84+
if (phase_deg_wrapped <= 90) {
85+
vChirp[i - 1] = lut_sine[(int)(phase_deg_wrapped / 90.0 * (90 * x - 1))] * 2047.5 + 2047.5;
86+
} else if (phase_deg_wrapped <= 180) {
87+
vChirp[i - 1] = -lut_sine[(int)((180.0 - phase_deg_wrapped) / 90.0 * (90 * x - 1))] * 2047.5 + 2047.5;
88+
} else if (phase_deg_wrapped <= 270) {
89+
vChirp[i - 1] = -lut_sine[(int)((phase_deg_wrapped - 180.0) / 90.0 * (90 * x - 1))] * 2047.5 + 2047.5;
90+
} else {
91+
vChirp[i - 1] = lut_sine[(int)((360.0 - phase_deg_wrapped) / 90.0 * (90 * x - 1))] * 2047.5 + 2047.5;
92+
}
93+
```
5694

57-
**Bold text**
95+
{: .warning }
96+
In this configuration, the first value of the chirp signal array is 0 (or 0 V in amplitude at DAC output). This initial value can be changed by modifying `sine_lut`.
5897

59-
*Italics*
98+
**Step 4**{: .text-blue-000} : Copy the chirp signal's values to the DAC buffer
6099

61-
### subchapter 1
62100
```c
63-
// cool code
101+
// Copy the chirp signal to the DAC buffer
102+
for (int i = 0; i < samples_int; i++) {
103+
array[i] = (uint16_t)vChirp[i];
104+
}
64105
```
65106
66-
## Chapter 2
107+
---
108+
109+
## Main code
110+
Check out the [DAC]({% link Library/DAC.md %}) section for more information on the DAC library and different DAC related functions.
111+
112+
The `Chirp_SawtoothMod.ino` and `Chirp_TriangularMod.ino` files contain the main code to generate the chirp signal, send the chirp signal to the DAC and enable the DAC.
113+
114+
The code contains the following user settings to adjust the chirp signal :
67115
68-
{. :warning}
69-
callout #1
116+
* `CHIRP_DURATION`{: .text-green-000} : The period of the chirp signal in seconds
117+
* `START_FREQUENCY`{: .text-green-000} : The start frequency of the chirp signal in Hz
118+
* `END_FREQUENCY`{: .text-green-000} : The end frequency of the chirp signal in Hz
119+
120+
A very important variable in the main code is the sampling frequency `fs`. Based on the Nyquist-Shannon sampling theorem, `fs` needs to be at least double the maximum frequency (or end frequency) of the chirp signal.
121+
Keep in mind this sampling frequency will also be the DAC's output frequency in the `SensEdu_DAC_Settings` function.
122+
123+
{: .warning }
124+
`fs` needs to be at least 2*END_FREQUENCY in order for the chirp signal to be generated properly.
125+
126+
The `samples_int` is an integer representing the amount of samples for one period of the chirp signal. This value also represents the memory size in the `SENSEDU_DAC_BUFFER` and `SensEdu_DAC_Settings` functions.
127+
128+
{: .warning }
129+
In this implementation, `samples_int` cannot exceed 7688.
130+
131+
The values of the chirp are printed in the serial monitor.
132+
```c
133+
// Print the chirp signal LUT
134+
Serial.println("start of the Chirp LUT");
135+
for (int i = 0 ; i < samples_int; i++) { // loop for the LUT size
136+
Serial.print("value ");
137+
Serial.print(i+1);
138+
Serial.print(" of the Chirp LUT: ");
139+
Serial.println(lut[i]);
140+
}
141+
```
70142

71-
{. :note}
72-
callout #1
73143

74144

75145
[example link]: https://github.com/ShiegeChan/SensEdu

docs/assets/images/Chirp_signal.png

46.1 KB
Loading

docs/assets/images/Chirp_spectro.png

969 KB
Loading

libraries/SensEdu/src/SensEdu.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,17 @@ SENSEDU_ERROR SensEdu_GetError(void) {
1818
return error;
1919
}
2020

21-
error |= DMA_GetError();
21+
error |= DAC_GetError();
2222
if (error) {
23-
error |= SENSEDU_ERROR_DMA;
23+
error |= SENSEDU_ERROR_DAC;
2424
return error;
2525
}
2626

27-
error |= DAC_GetError();
27+
error |= DMA_GetError();
2828
if (error) {
29-
error |= SENSEDU_ERROR_DAC;
29+
error |= SENSEDU_ERROR_DMA;
3030
return error;
3131
}
3232

3333
return error;
34-
}
34+
}

libraries/SensEdu/src/dac.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,10 @@ static DAC_ERROR check_settings(SensEdu_DAC_Settings* settings) {
171171
if (settings->dac_channel != DAC_CH1 && settings->dac_channel != DAC_CH2) {
172172
return DAC_ERROR_INIT_FAILED;
173173
}
174+
175+
if (settings->sampling_freq > 15000000) {
176+
return DAC_ERROR_SAMPLING_FREQ_TOO_HIGH;
177+
}
174178

175179
if (settings->mem_address == 0x0000) {
176180
return DAC_ERROR_INIT_FAILED;
@@ -179,7 +183,7 @@ static DAC_ERROR check_settings(SensEdu_DAC_Settings* settings) {
179183
if (settings->mem_address == 0) {
180184
return DAC_ERROR_INIT_FAILED;
181185
}
182-
186+
183187
if (settings->wave_mode == SENSEDU_DAC_MODE_BURST_WAVE && settings->burst_num < 1) {
184188
settings->burst_num = 1; // be careful not to stuck in interrupt
185189
return DAC_ERROR_INIT_FAILED;

libraries/SensEdu/src/dac.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ typedef enum {
1313
DAC_ERROR_WRONG_CHANNEL = 0x02,
1414
DAC_ERROR_DMA_UNDERRUN = 0x03,
1515
DAC_ERROR_ENABLED_BEFORE_INIT = 0x04,
16-
DAC_ERROR_WRONG_MODE = 0x05
16+
DAC_ERROR_WRONG_MODE = 0x05,
17+
DAC_ERROR_SAMPLING_FREQ_TOO_HIGH = 0x06
1718
} DAC_ERROR;
1819

1920
typedef enum {

projects/Chirp_SawtoothMod/Chirp_SawtoothMod.ino renamed to projects/Chirp/Chirp_SawtoothMod/Chirp_SawtoothMod.ino

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,26 @@
55
/* -------------------------------------------------------------------------- */
66

77
#define CHIRP_DURATION 0.001 // Duration of the chirp (in seconds)
8-
#define START_FREQUENCY 30300 // Start frequency (in Hz)
9-
#define END_FREQUENCY 35300 // Stop frequency (in Hz)
8+
#define START_FREQUENCY 1000 // Start frequency (in Hz)
9+
#define END_FREQUENCY 30000 // Stop frequency (in Hz)
1010

1111
/* -------------------------------------------------------------------------- */
1212
/* Global Variables */
1313
/* -------------------------------------------------------------------------- */
1414

1515
static uint32_t lib_error = 0;
1616
static uint8_t increment_flag = 1; // Run time modification flag
17-
const float fs = 42 * END_FREQUENCY; // Sampling frequency
17+
const float fs = 100 * END_FREQUENCY; // Sampling frequency
1818
const float samples = fs * CHIRP_DURATION; // Number of samples
1919
const uint32_t samples_int = (uint32_t)samples;
2020
static SENSEDU_DAC_BUFFER(lut, samples_int); // Buffer for the chirp signal
2121

22+
// Initialize DAC settings
23+
SensEdu_DAC_Settings dac1_settings = {
24+
DAC_CH2, fs, (uint16_t*)lut, samples_int,
25+
SENSEDU_DAC_MODE_CONTINUOUS_WAVE, 1
26+
};
27+
2228
/* -------------------------------------------------------------------------- */
2329
/* Setup */
2430
/* -------------------------------------------------------------------------- */
@@ -27,17 +33,17 @@ void setup() {
2733
Serial.begin(115200);
2834
while(!Serial);
2935

30-
// Initialize DAC settings
31-
SensEdu_DAC_Settings dac1_settings = {
32-
DAC1, fs, (uint16_t*)lut, samples_int,
33-
SENSEDU_DAC_MODE_CONTINUOUS_WAVE, 2
34-
};
36+
// Check if array size exceeds 7688 or fs exceeds 15 MHz
37+
if (samples_int > 7688 || fs > 15000000) {
38+
Serial.println("Error: samples_int exceeds 7688 or fs exceeds 15 MHz!");
39+
while (true);
40+
}
3541

3642
// Generate the chirp signal
37-
generateChirpSignal(lut);
43+
generateSawtoothChirp(lut);
3844

3945
SensEdu_DAC_Init(&dac1_settings);
40-
SensEdu_DAC_Enable(DAC1);
46+
SensEdu_DAC_Enable(DAC_CH2);
4147

4248
// Check for errors
4349
lib_error = SensEdu_GetError();
@@ -49,6 +55,7 @@ void setup() {
4955

5056
Serial.println("Setup is successful.");
5157

58+
// Print the chirp signal LUT
5259
Serial.println("start of the Chirp LUT");
5360
for (int i = 0 ; i < samples_int; i++) { // loop for the LUT size
5461
Serial.print("value ");
@@ -58,7 +65,6 @@ void setup() {
5865
}
5966
}
6067

61-
6268
/* -------------------------------------------------------------------------- */
6369
/* Loop */
6470
/* -------------------------------------------------------------------------- */
@@ -70,7 +76,4 @@ void loop() {
7076
Serial.print("Error: 0x");
7177
Serial.println(lib_error, HEX);
7278
}
73-
74-
/* delay(100);
75-
SensEdu_DAC_Enable(DAC1); */
7679
}
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
1-
const uint32_t x = 5; // cos LUT resolution
1+
const uint32_t x = 5; // sine LUT resolution
22
const float Pi = 3.14159; // pi
33

4-
// Generate the chirp signal
5-
void generateChirpSignal(uint16_t* array) {
4+
// Generate chirp signal with a sawtooth modulation
5+
void generateSawtoothChirp(uint16_t* array) {
66

7-
float lut_cos[90 * x]; // Quarter-wave LUT for cosine values
8-
float vChirp[samples_int]; // Chirp signal LUT
7+
float lut_sine[90 * x]; // Quarter-wave LUT for sine values
8+
float vChirp[samples_int]; // Chirp signal array
99

10-
// Generate the quarter-wave cosine LUT
10+
// Generate the quarter-wave sine LUT
1111
for (int i = 0; i < 90 * x; i++) {
1212
float phase_deg = (float)i * 90.0 / (90 * x); // Phase angle in degrees
1313
float phase_rad = phase_deg * Pi / 180.0; // Phase angle to radians
14-
lut_cos[i] = cos(phase_rad); // Store cosine value in the LUT
14+
lut_sine[i] = sin(phase_rad-Pi/2); // Store sine value in the LUT
1515
}
1616

1717
// Generate the chirp signal
@@ -24,18 +24,18 @@ void generateChirpSignal(uint16_t* array) {
2424
float phase_deg_wrapped = fmod(phase_deg, 360.0); // Wrap phase angle to 0-360 degrees
2525

2626
if (phase_deg_wrapped <= 90) {
27-
vChirp[i - 1] = lut_cos[(int)(phase_deg_wrapped / 90.0 * (90 * x - 1))] * 2047.5 + 2047.5;
27+
vChirp[i - 1] = lut_sine[(int)(phase_deg_wrapped / 90.0 * (90 * x - 1))] * 2047.5 + 2047.5;
2828
} else if (phase_deg_wrapped <= 180) {
29-
vChirp[i - 1] = -lut_cos[(int)((180.0 - phase_deg_wrapped) / 90.0 * (90 * x - 1))] * 2047.5 + 2047.5;
29+
vChirp[i - 1] = -lut_sine[(int)((180.0 - phase_deg_wrapped) / 90.0 * (90 * x - 1))] * 2047.5 + 2047.5;
3030
} else if (phase_deg_wrapped <= 270) {
31-
vChirp[i - 1] = -lut_cos[(int)((phase_deg_wrapped - 180.0) / 90.0 * (90 * x - 1))] * 2047.5 + 2047.5;
31+
vChirp[i - 1] = -lut_sine[(int)((phase_deg_wrapped - 180.0) / 90.0 * (90 * x - 1))] * 2047.5 + 2047.5;
3232
} else {
33-
vChirp[i - 1] = lut_cos[(int)((360.0 - phase_deg_wrapped) / 90.0 * (90 * x - 1))] * 2047.5 + 2047.5;
33+
vChirp[i - 1] = lut_sine[(int)((360.0 - phase_deg_wrapped) / 90.0 * (90 * x - 1))] * 2047.5 + 2047.5;
3434
}
3535
}
3636

3737
// Copy the chirp signal to the DAC buffer
3838
for (int i = 0; i < samples_int; i++) {
39-
array[i] = (uint16_t)vChirp[i];
39+
array[i] = (uint16_t)vChirp[i];
4040
}
4141
}

0 commit comments

Comments
 (0)