-
Notifications
You must be signed in to change notification settings - Fork 18
Expand file tree
/
Copy pathuiservo.lsp
More file actions
182 lines (158 loc) · 4.33 KB
/
uiservo.lsp
File metadata and controls
182 lines (158 loc) · 4.33 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
<!DOCTYPE html>
<?lsp
--[[
Change 'gpioPin' in the code if you want to use a GPIO other than 14
Make sure to read the information in servo.lsp prior to testing this
example.
This example shows how to control the servo using a web based user
interface. The example uses the following slider:
https://roundsliderui.com/
The slider value is sent in real time from the browser to the device
using WebSockets or more specifically by using SMQ over WebSockets:
https://realtimelogic.com/ba/doc/?url=SMQ.html
The design pattern follows what is outlined in the following tutorial:
https://realtimelogic.com/articles/Modern-Approach-to-Embedding-a-Web-Server-in-a-Device
Open two browser windows to this page, and note that both sliders are
updated in real time.
--]]
local gpioPin=14
local bits=13 -- pwm resolution = 13 bits
local maxPwm=2^bits - 1 -- any value between 0 and maxPwm
local minPulseWidth = 1000 -- 1 ms
local cycleTime = 20000 -- 20 ms
local function calculatePwmDutyCycle(angle)
return (maxPwm / cycleTime) * (angle * 5.55 + minPulseWidth)
end
if page.smq then
if require"smq.hub".isSMQ(request) then
-- Upgrade HTTP(S) request to SMQ connection
page.smq:connect(request)
return
end
else
collectgarbage()
local ok,err=esp32.pwmtimer{
mode="LOW", -- speed_mode
bits=bits, -- duty_resolution (bits)
timer=0, -- timer_num
freq=50,
}
trace(ok,err)
if ok then
local duty = 2000 / 20000 * 100
local pwm,err=esp32.pwmchannel{
mode="LOW",
channel=1,
timer=0, -- timer_sel
gpio=14,
duty = calculatePwmDutyCycle(180),
hpoint=0,
}
trace(ok,err)
if ok then
local angle
local function newClient(tid)
trace"New browser window"
smq:publish({angle=angle},tid,"servo")
end
smq = require"smq.hub".create{onconnect=newClient}
local function servo(d)
angle=d.angle
trace("Angle", angle)
pwm:duty(calculatePwmDutyCycle(angle))
end
smq:subscribe("servo",{json=true,onmsg=servo})
page.smq=smq
trace"Starting servo example."
end
end
end
?>
<html>
<head>
<link href="https://cdn.jsdelivr.net/npm/round-slider@1.6.1/dist/roundslider.min.css" rel="stylesheet" />
<script src="/rtl/jquery.js"></script>
<script src="/rtl/smq.js"></script>
<script src="https://cdn.jsdelivr.net/npm/round-slider@1.6.1/dist/roundslider.min.js"></script>
<style>
html,body{
position: relative;
height:100%;
width:100%;
padding:0;
margin:0;
}
#ServoSlider {
width: 260px;
height: 130px;
padding: 20px;
position: absolute;
top: 50%;
left: 50%;
margin: -85px 0 0 -130px;
}
#ServoSlider .rs-handle {
background-color: transparent;
border: 8px solid transparent;
border-right-color: black;
margin: -8px 0 0 14px !important;
}
#ServoSlider .rs-handle:before {
display: block;
content: " ";
position: absolute;
height: 12px;
width: 12px;
background: black;
right: -6px;
bottom: -6px;
border-radius: 100%;
}
#ServoSlider .rs-handle:after {
display: block;
content: " ";
width: 106px;
position: absolute;
top: -1px;
right: 0px;
border-top: 2px solid black;
}
</style>
<script>
$(function() {
var smq = SMQ.Client(); // No args: connect back to 'origin'.
let active=true;
function onSmqMsg(d,ptid) {
if(ptid != smq.gettid()) { //Ignore messages from 'self'
active=true;
$("#ServoSlider").roundSlider("option", "value", Math.floor(d.angle * 100 / 180));
active=false;
}
}
smq.subscribe("self",{datatype:"json",onmsg:onSmqMsg});
smq.subscribe("servo",{datatype:"json",onmsg:onSmqMsg});
function onChange (e) {
if(!active)
smq.pubjson({angle:Math.floor(e.value * 180 / 100)}, "servo");
}
$("#ServoSlider").roundSlider({
animation:false,
sliderType: "min-range",
radius: 130,
showTooltip: false,
width: 16,
value: 0,
handleSize: 0,
handleShape: "square",
circleShape: "half-top",
change: onChange,
tooltipFormat: onChange
});
active=false;
});
</script>
</head>
<body>
<div id="ServoSlider">
</div>
</body></html>