Siphon Regulator 1.0
Nanosattelite attitude determination and control system.
Loading...
Searching...
No Matches
loop_fcn.c
Go to the documentation of this file.
1/*
2 * Loop functions library
3 * (c) Antonin_Putala 2026
4 *
5 * Developed using STM32CubeIDE
6 * Tested on BluePill board and STM32F103C8T6, 32 MHz.
7 */
8
9/* Includes -----------------------------------------------*/
10#include "loop_fcn.h"
11#include "loop_fcn_def.h"
12#include "main.h"
13#include "sensor_fcn.h"
14#include <math.h>
15#include <stdio.h>
16
17/* Global functions ---------------------------------------*/
18/*
19 * Function: uart_byte_available
20 * Purpose: It handles the periodic transmission of
21 * the sensor data message.
22 * Input(s): reg - command register, involves
23 * information about system state and
24 * switching time of valves
25 * Returns: none
26 */
27void autoread_fcn(uint32_t reg)
28{
29 if (_read_BV(reg, AUTOREAD_BIT))
30 {
31 /* Previous event time */
32 static uint32_t ticks = 0;
33
34 if (HAL_GetTick() > (ticks + set_data.time_a * 100))
35 {
36 ticks = HAL_GetTick();
37
38 if (_read_BV(reg, AUTOREAD_ACC_BIT))
39 {
40 printf("A: X=%d, Y=%d, Z=%d\n", _float2int(measured_data.acc[0]),
42 }
43
44 if (_read_BV(reg, AUTOREAD_GYR_BIT))
45 {
46 printf("G: X=%d, Y=%d, Z=%d\n", _float2int(measured_data.gyr[0]),
48 }
49
50 if (_read_BV(reg, AUTOREAD_POS_BIT))
51 {
52 printf("P: X=%ld, Y=%ld, Z=%ld\n", (int32_t)(measured_data.pos[0]),
53 (int32_t)(measured_data.pos[1]), (int32_t)(measured_data.pos[2]));
54 }
55 }
56 }
57}
58
59/*
60 * Function: valve_fcn
61 * Purpose: It handles the execution of motion commands.
62 * Input(s): p_reg - command register, involves
63 * information about system state and
64 * switching time of valves
65 * p_set_pos - the orientation is maintained by
66 * the regulation loop.
67 * Returns: none
68 */
69void valve_fcn(uint32_t * p_reg, float * p_set_pos)
70{
71 static uint32_t ticks = 0;
72
73 /* Default measured_data.pos is 0 0 0 */
74 static float stable_pos = 0;
75 static float required_pos = 0;
76
77 if (_read_BV(*p_reg, RUN_BIT))
78 {
79 if (_read_BV(*p_reg, PULSE_BIT) || _read_BV(*p_reg, TURN_BIT) || _read_BV(*p_reg, HOME_BIT))
80 {
81 /* Run is handled */
82 _clr_BV(*p_reg, RUN_BIT);
83
84 /* Duration of pulse */
85 ticks = HAL_GetTick();
86 /* Time is interpreted as tens of milliseconds */
87 ticks += (_read_BV(*p_reg, DIR_BIT)) ? ((_read_time_r(*p_reg)) * PULSE_REPRE) : ((_read_time_l(*p_reg)) * PULSE_REPRE);
88
89 /* 1 - right direction, 0 - left direction */
90 HAL_GPIO_WritePin(VALVE_R_GPIO_Port, VALVE_R_Pin, _read_BV(*p_reg, DIR_BIT));
91 HAL_GPIO_WritePin(VALVE_L_GPIO_Port, VALVE_L_Pin, !(_read_BV(*p_reg, DIR_BIT)));
92
93 /* Update stable position */
94 stable_pos = measured_data.pos[2];
95 /* For regulator */
96 *p_set_pos = stable_pos;
97
98 // printf("stable_pos: %d\n", (int16_t)(stable_pos));
99 }
100 else
101 {
102 /* Satellite is moving, waiting for required position */
103 if ((fabsf(required_pos - measured_data.pos[2]) < ANGLE_TOL))
104 {
105 /* Create opposite pulse */
106 _tog_BV(*p_reg, DIR_BIT);
107 _set_BV(*p_reg, PULSE_BIT);
108
109 /* Redefine time according to angle speed */
110 _clr_time(*p_reg);
111 uint8_t time[2];
112
113 /* Positive velocity => right rotation => left valve for stop */
114 time[0] = !(_read_BV(*p_reg, DIR_BIT)) ? (uint8_t)(STOP_CONST_LEFT * (fabsf(measured_data.gyr[2]) - STOP_CONST_OFF_LEFT)) : set_data.time_l;
115 time[1] = (_read_BV(*p_reg, DIR_BIT)) ? (uint8_t)(STOP_CONST_RIGHT * (measured_data.gyr[2] - STOP_CONST_OFF_RIGHT)) : set_data.time_r;
116 _set_time(*p_reg, time[0], time[1]);
117
118 // printf("gyroscope: %d\n", _float2int(measured_data.gyr[2]));
119 // printf("break time: %d %d\n", time[0], time[1]);
120 }
121 }
122 }
123 else if ((HAL_GetTick() > ticks))
124 {
125 if (_read_BV(*p_reg, PULSE_BIT))
126 {
127 _clr_BV(*p_reg, PULSE_BIT);
128
129 valve_close();
130 }
131 else if (_read_BV(*p_reg, TURN_BIT))
132 {
133 _clr_BV(*p_reg, TURN_BIT);
134 /* When run is set, and pulse and turn bit clear, satellite is moving. */
135 /* Waiting for stopping pulse */
136 _set_BV(*p_reg, RUN_BIT);
137
138 valve_close();
139
140 /* Set duration of fly */
141 required_pos = stable_pos;
142 required_pos += (_read_BV(*p_reg, DIR_BIT)) ? (-set_data.angle) : set_data.angle;
143 sensor_deg_limit(&required_pos);
144
145 // printf("required_pos: %d\n", (int16_t)(required_pos));
146
147 }
148 else if (_read_BV(*p_reg, HOME_BIT))
149 {
150 _clr_BV(*p_reg, HOME_BIT);
151 _set_BV(*p_reg, RUN_BIT);
152
153 valve_close();
154
155 required_pos = (float)set_data.home;
156
157 // printf("required_pos: %d\n", (int16_t)(required_pos));
158 }
159 /* For regulation, it helps transfer regulation to home setting */
160 else if (_read_BV(*p_reg, RETURN_BIT))
161 {
162 /* Now I am flying */
163 _clr_BV(*p_reg, RETURN_BIT);
164 _set_BV(*p_reg, RUN_BIT);
165
166 required_pos = *p_set_pos;
167
168 // printf("required_pos: %d\n", (int16_t)(required_pos));
169 }
170 }
171}
172
173/*
174 * Function: regul_fcn
175 * Purpose: It handles the regulation of the orientation.
176 * Input(s): p_reg - command register, involves
177 * information about system state and
178 * switching time of valves
179 * set_pos - the orientation is maintained by
180 * the regulation loop.
181 * Returns: none
182 */
183void regul_fcn(uint32_t * p_reg, float set_pos)
184{
185 static uint32_t ticks = 0;
186
187 /* No motion is processed */
188 if (!(_read_valve(*p_reg)))
189 {
190 /* Condition of running */
191 if ((_read_BV(*p_reg, CMD0_BIT)))
192 {
193 if (fabsf(measured_data.gyr[2]) > GYR_TOL)
194 {
195 regul_stop(p_reg, &ticks);
196 }
197 /* Cube is stable but position is different from required */
198 else if (fabsf(measured_data.pos[2] - set_pos) > ANGLE_TOL)
199 {
200 regul_return(p_reg, &ticks, set_pos);
201 }
202 }
203 }
204 else if (_read_BV(*p_reg, REG_BIT))
205 {
206 /* Condition of stopping */
207 if (HAL_GetTick() > ticks)
208 {
209 _clr_BV(*p_reg, REG_BIT);
210 valve_close();
211 // printf("Valve was closed\n");
212 }
213 }
214}
215
216/* Local function */
217/*
218 * Function: valve_close
219 * Purpose: Closes all valves.
220 * Input(s): none
221 * Returns: none
222 */
223static void valve_close(void)
224{
225 HAL_GPIO_WritePin(VALVE_R_GPIO_Port, VALVE_R_Pin, 0);
226 HAL_GPIO_WritePin(VALVE_L_GPIO_Port, VALVE_L_Pin, 0);
227}
228
229/*
230 * Function: regul_stop
231 * Purpose: It provides the stopping pulse.
232 * Input(s): p_reg - command register, involves
233 * information about system state and
234 * switching time of valves
235 * p_ticks - number of ticks until the pulse
236 * is stopped
237 * Returns: none
238 */
239static void regul_stop(uint32_t * p_reg, uint32_t * p_ticks)
240{
241 /* Create stop pulse when position is forced to change */
242 _set_BV(*p_reg, REG_BIT);
243
244 if (measured_data.gyr[2] > 0)
245 {
246 HAL_GPIO_WritePin(VALVE_R_GPIO_Port, VALVE_R_Pin, 1);
247 *p_ticks = (uint32_t)(STOP_CONST_RIGHT * (measured_data.gyr[2] - STOP_CONST_OFF_RIGHT));
248 }
249 else
250 {
251 HAL_GPIO_WritePin(VALVE_L_GPIO_Port, VALVE_L_Pin, 1);
252 /* Gyroscope data are negative!!! */
253 *p_ticks = (uint32_t)(STOP_CONST_LEFT * ((-1 * measured_data.gyr[2]) - STOP_CONST_OFF_LEFT));
254 }
255
256 /* Ignore too short pulses */
257 if (*p_ticks > PULSE_IGNORE)
258 {
259 *p_ticks += HAL_GetTick();
260 }
261 else
262 {
263 /* Too short */
264 _clr_BV(*p_reg, REG_BIT);
265 }
266}
267
268/*
269 * Function: regul_return
270 * Purpose: It initiates the return to the stable orientation.
271 * Input(s): p_reg - command register, involves
272 * information about system state and
273 * switching time of valves
274 * p_ticks - number of ticks until the pulse
275 * is stopped
276 * set_pos - the orientation is maintained by
277 * the regulation loop.
278 * Returns: none
279 */
280static void regul_return(uint32_t * p_reg, uint32_t * p_ticks, float set_pos)
281{
282 /* First pulse which start return to original position */
283 /* Helps to regulate required destination */
284 _set_BV(*p_reg, REG_BIT);
285 _set_BV(*p_reg, RETURN_BIT);
286
287 *p_ticks = HAL_GetTick();
288
289 /* Choose direction */
290 if ((((measured_data.pos[2] - set_pos) > 0) && ((measured_data.pos[2] - set_pos) < 180)) || ((measured_data.pos[2] - set_pos) < -180))
291 {
292 _set_BV(*p_reg, DIR_BIT);
293
294 /* Interpreted as tens of milliseconds */
295 *p_ticks += set_data.time_r * PULSE_REPRE; //
296 HAL_GPIO_WritePin(VALVE_R_GPIO_Port, VALVE_R_Pin, 1);
297 // printf("Right valve was open\n");
298 }
299 else
300 {
301 _clr_BV(*p_reg, DIR_BIT);
302
303 /* Interpreted as tens of milliseconds */
304 *p_ticks += set_data.time_l * PULSE_REPRE;
305 HAL_GPIO_WritePin(VALVE_L_GPIO_Port, VALVE_L_Pin, 1);
306 // printf("Left valve was open\n");
307 }
308}
309
settings_t set_data
Main system settings.
Definition main.c:61
sensor_data_t measured_data
Current sensor measured data.
Definition main.c:60
void valve_fcn(uint32_t *p_reg, float *p_set_pos)
It handles the execution of motion commands.
Definition loop_fcn.c:69
void autoread_fcn(uint32_t reg)
It handles the periodic transmission of the sensor data message.
Definition loop_fcn.c:27
#define STOP_CONST_LEFT
#define STOP_CONST_RIGHT
#define PULSE_IGNORE
#define STOP_CONST_OFF_LEFT
#define GYR_TOL
#define ANGLE_TOL
void regul_fcn(uint32_t *p_reg, float set_pos)
It handles the regulation of the orientation.
Definition loop_fcn.c:183
#define STOP_CONST_OFF_RIGHT
void sensor_deg_limit(float *p_deg)
It normalizes the orientation value to the –180° to +180° range.
Definition sensor_fcn.c:88
static void valve_close(void)
Definition loop_fcn.c:223
static void regul_stop(uint32_t *p_reg, uint32_t *p_ticks)
Definition loop_fcn.c:239
static void regul_return(uint32_t *p_reg, uint32_t *p_ticks, float set_pos)
Definition loop_fcn.c:280
: Header for main.c file. This file contains the common defines of the application.
#define _read_valve(reg)
Definition main.h:200
#define AUTOREAD_BIT
Definition main.h:183
#define VALVE_L_Pin
Definition main.h:149
#define _clr_time(reg)
Definition main.h:118
#define _read_BV(reg, bit)
Definition main.h:103
#define DIR_BIT
Definition main.h:165
#define CMD0_BIT
Definition main.h:208
#define RETURN_BIT
Definition main.h:177
#define _read_time_l(reg)
Definition main.h:128
#define VALVE_R_Pin
Definition main.h:147
#define _float2int(data_fl)
Definition main.h:133
#define _read_time_r(reg)
Definition main.h:125
#define VALVE_R_GPIO_Port
Definition main.h:148
#define RUN_BIT
Definition main.h:162
#define _tog_BV(reg, bit)
Definition main.h:112
#define TURN_BIT
Definition main.h:171
#define _clr_BV(reg, bit)
Definition main.h:109
#define _set_time(reg, time_l, time_r)
Definition main.h:122
#define AUTOREAD_ACC_BIT
Definition main.h:186
#define HOME_BIT
Definition main.h:180
#define PULSE_BIT
Definition main.h:168
#define VALVE_L_GPIO_Port
Definition main.h:150
#define AUTOREAD_POS_BIT
Definition main.h:192
#define _set_BV(reg, bit)
Definition main.h:106
#define REG_BIT
Definition main.h:174
#define PULSE_REPRE
Definition main.h:195
#define AUTOREAD_GYR_BIT
Definition main.h:189
float pos[3]
Orientation X, Y, Z [deg]; related to initial position.
Definition main.h:82
float gyr[3]
Gyroscope X, Y, Z [dps].
Definition main.h:80
float acc[3]
Accelerometer X, Y, Z [g].
Definition main.h:79
uint8_t time_r
Time [10*ms], right valve is open.
Definition main.h:88
uint8_t angle
Angle [deg], cube rotate after turn cmd.
Definition main.h:87
int16_t home
Angle [deg], default orientation.
Definition main.h:91
uint8_t time_l
Time [10*ms], left valve is open.
Definition main.h:89
uint8_t time_a
Period [100*ms], sensor report will be sended.
Definition main.h:90