Skip to content

Commit 4877663

Browse files
committed
first commit
0 parents  commit 4877663

File tree

4 files changed

+205
-0
lines changed

4 files changed

+205
-0
lines changed

README.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Flipper servotester application
2+
3+
Application uses A7 pin for servo PWM output. Has different modes: Manual, Center, Auto.
4+
5+
## Installation instructions
6+
7+
Go to the [releases](https://github.com/spin7ion/flipper-servotester/releases), download apps.zip and extract it in your SD card.
8+
9+
## Build instructions
10+
11+
- Clone the [official flipper zero firmware](https://github.com/flipperdevices/flipperzero-firmware)
12+
- Add the content of this repo to the `applications_user` folder
13+
- Follow [official instructions](https://github.com/flipperdevices/flipperzero-firmware/blob/dev/documentation/AppsOnSDCard.md)

servotester/application.fam

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
App(
2+
appid="servotester",
3+
name="Servotester",
4+
apptype=FlipperAppType.EXTERNAL,
5+
entry_point="servotester_app",
6+
cdefines=["APP_SERVOTESTER"],
7+
requires=[
8+
"gui",
9+
],
10+
stack_size=1 * 1024,
11+
order=90,
12+
fap_icon="servotester.png",
13+
fap_category="GPIO",
14+
fap_author="Alexander Semion"
15+
)

servotester/servotester.c

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
#include <furi.h>
2+
#include <furi_hal.h>
3+
#include <furi_hal_clock.h>
4+
#include <furi_hal_pwm.h>
5+
#include <gui/gui.h>
6+
#include <input/input.h>
7+
#include <notification/notification_messages.h>
8+
#include <stdio.h>
9+
10+
#define DEFAULT_FREQ 50
11+
#define DEFAULT_DUTY 1
12+
13+
uint16_t pWidth = 1500;
14+
int8_t dir = 1;
15+
16+
enum Modes {
17+
Manual,
18+
Center,
19+
Auto,
20+
};
21+
22+
const char* const modes_text[Auto + 1] = {
23+
"Manual",
24+
"Center",
25+
"Auto",
26+
};
27+
28+
uint8_t mode = Manual;
29+
30+
typedef enum {
31+
EventTypeTick,
32+
EventTypeInput,
33+
} EventType;
34+
35+
typedef struct {
36+
EventType type;
37+
InputEvent input;
38+
} ServoTesterEvent;
39+
40+
static void draw_callback(Canvas* canvas, void* ctx) {
41+
UNUSED(ctx);
42+
43+
char temp_str[36];
44+
45+
canvas_clear(canvas);
46+
canvas_set_font(canvas, FontPrimary);
47+
48+
canvas_draw_frame(canvas, 0, 0, 128, 64);
49+
canvas_draw_str(canvas, 35, 10, "Servo tester");
50+
canvas_draw_line(canvas, 14, 30, 114, 30);
51+
canvas_draw_line(canvas, 14, 30, 14, 20);
52+
canvas_draw_line(canvas, 114, 30, 114, 20);
53+
54+
/*
55+
14-1000
56+
104-2000
57+
58+
59+
60+
(pWidth-1000)/10+10 === 0-1
61+
62+
63+
*/
64+
canvas_draw_frame(canvas, (pWidth - 1000) / 10.2 + 14, 20, 3, 10);
65+
66+
snprintf(temp_str, sizeof(temp_str), "%i us", pWidth);
67+
68+
canvas_draw_str(canvas, 50, 40, temp_str);
69+
70+
canvas_draw_str(canvas, 50, 50, modes_text[mode]);
71+
}
72+
73+
static void input_callback(InputEvent* input_event, void* ctx) {
74+
furi_assert(ctx);
75+
FuriMessageQueue* event_queue = ctx;
76+
ServoTesterEvent event = {.type = EventTypeInput, .input = *input_event};
77+
furi_message_queue_put(event_queue, &event, FuriWaitForever);
78+
}
79+
80+
static void timer_callback(FuriMessageQueue* event_queue) {
81+
furi_assert(event_queue);
82+
83+
ServoTesterEvent event = {.type = EventTypeTick};
84+
furi_message_queue_put(event_queue, &event, 0);
85+
}
86+
87+
void setServoPWM(uint32_t freq, uint32_t compare) {
88+
uint32_t freq_div = 64000000LU / freq;
89+
uint32_t prescaler = freq_div / 0x10000LU;
90+
uint32_t period = freq_div / (prescaler + 1);
91+
92+
LL_TIM_SetPrescaler(TIM1, prescaler);
93+
LL_TIM_SetAutoReload(TIM1, period - 1);
94+
LL_TIM_OC_SetCompareCH1(TIM1, compare);
95+
}
96+
97+
void updatePwm() {
98+
setServoPWM(DEFAULT_FREQ, pWidth * 3.2);
99+
}
100+
101+
int32_t servotester_app(void* p) {
102+
UNUSED(p);
103+
104+
ServoTesterEvent event;
105+
106+
FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(ServoTesterEvent));
107+
108+
ViewPort* view_port = view_port_alloc();
109+
110+
// callbacks init
111+
view_port_draw_callback_set(view_port, draw_callback, NULL);
112+
view_port_input_callback_set(view_port, input_callback, event_queue);
113+
114+
Gui* gui = furi_record_open(RECORD_GUI);
115+
gui_add_view_port(gui, view_port, GuiLayerFullscreen);
116+
117+
FuriTimer* timer = furi_timer_alloc(timer_callback, FuriTimerTypePeriodic, event_queue);
118+
furi_timer_start(timer, 5);
119+
120+
//GPIO init
121+
furi_hal_power_enable_otg();
122+
furi_hal_pwm_start(FuriHalPwmOutputIdTim1PA7, 50, 4);
123+
setServoPWM(DEFAULT_FREQ, pWidth * 3.2);
124+
125+
while(1) {
126+
furi_check(furi_message_queue_get(event_queue, &event, FuriWaitForever) == FuriStatusOk);
127+
if(event.type == EventTypeInput) {
128+
if(event.input.key == InputKeyBack) {
129+
furi_hal_power_disable_otg();
130+
furi_hal_pwm_stop(FuriHalPwmOutputIdTim1PA7);
131+
break;
132+
} else if(event.input.key == InputKeyOk) {
133+
if(event.input.type == InputTypeRelease) {
134+
if(mode == Auto) {
135+
mode = Manual;
136+
} else {
137+
mode++;
138+
}
139+
140+
if(mode == Center) {
141+
pWidth = 1500;
142+
updatePwm();
143+
}
144+
}
145+
} else if(event.input.key == InputKeyLeft) {
146+
if(pWidth > 1000) pWidth--;
147+
updatePwm();
148+
} else if(event.input.key == InputKeyRight) {
149+
if(pWidth < 2000) pWidth++;
150+
updatePwm();
151+
} else if(event.input.key == InputKeyDown) {
152+
if(pWidth >= 1010) pWidth -= 10;
153+
updatePwm();
154+
} else if(event.input.key == InputKeyUp) {
155+
if(pWidth <= 1990) pWidth += 10;
156+
updatePwm();
157+
}
158+
} else if(event.type == EventTypeTick) {
159+
if(mode == Auto) {
160+
pWidth += dir;
161+
if(pWidth > 1990 || pWidth < 1010) {
162+
dir = dir * -1;
163+
}
164+
updatePwm();
165+
}
166+
}
167+
}
168+
169+
furi_timer_free(timer);
170+
furi_message_queue_free(event_queue);
171+
172+
gui_remove_view_port(gui, view_port);
173+
view_port_free(view_port);
174+
furi_record_close(RECORD_GUI);
175+
176+
return 0;
177+
}

servotester/servotester.png

6.76 KB
Loading

0 commit comments

Comments
 (0)