Content
:
Introduction: 41
Interpreter: 43
Branch labels.
44
Variables: 45
Arrays: 46
OPTION.BASE 1. 46
LBOUND(array() [, dimension]) :
Returns the lower bound of the specified array dimension.
47
UBOUND(array() [, dimension]) :
Returns the upper bound of the specified array dimension.
47
Scope of the variables: 48
Bases of the language.
48
OPERATORS AND PRECEDENCE..
49
Basic internal keywords: 51
IF command : 51
FOR loop.
52
WHILE WEND loop.
53
DO LOOP loop.
53
SELECT CASE..
54
GOTO..
56
GOSUB..
56
DATA..
56
END..
58
EXIT.
58
SUB..
58
Logical / boolean Operations.
60
ERRORS HANDLING..
61
ONERROR ABORT.
61
ONERROR IGNORE.
61
ONERROR SKIP [nn].
61
ONERROR CLEAR.
61
ONERROR GOTO [label |
OFF].
61
BAS.ERRLINE.
62
BAS.ERRNUM.
62
BAS.ERRMSG$.
62
HOW the interpreter works with the HTML
code and Objects : 62
HTML Objects.
67
TIMERS..
72
EVENTS..
72
Button Event 73
OnHtmlChange Event 73
OnHtmlReloadEvent 73
OnInfrared Event 74
OnSerial Event 74
OnSerial2 Event 74
OnTouch Event 75
OnUDP Event 75
OnWgetAsync Event 75
OnUrlMessage Event 76
OnEspNowMsg Event 79
OnEspNowError Event 80
OnMQTT Event 80
OnPlay Event 80
WiFI CONNECTIONS..
80
PROGRAM AUTORUN..
83
RECOVERY MODE..
83
SLEEP mode (low energy) and RTC
memory.
83
DATE - TIME timekeeper 84
Unix Time functions.
85
FAT32 File System..
85
FILE.COPY(filename$,
newfile$).
87
FILE.DELETE(filename$).
87
FILE.EXISTS(filename$).
87
FILE.RENAME(oldname$,
newname$).
87
FILE.SIZE(filename$).
87
FILE.MKDIR(dirname$).
87
FILE.RMDIR(dirname$).
87
FILE.DIR$(path$).
87
FILE.READ$(filename$, [line_num] | [start,
length]).
87
FILE.APPEND filename$,
content$.
87
FILE.SAVE filename$,
content$.
88
FILE.WRITE filename$,
content$.
88
FILE.FROMBASE64 source$,
dest$.
88
FILE.TOBASE64 source$,
dest$.
88
FILE.SAVE_IOBUFF.
88
FILE.WRITE_IOBUFF.
88
FILE.APPEND_IOBUFF.
88
FILE.READ_IOBUFF.
88
Download files from another module or WEB
server 89
Notes: 89
I/O BUFFERS..
90
Define the Size of an I/O Buffer
90
IOBUFF.DIM(buff_num,
size).
90
Fill a Buffer with Predefined
Data.
90
IOBUFF.DIM(buff_num, size) =
data_list.
90
Release a Buffer 91
IOBUFF.DESTROY(buff_num,
size).
91
Get the Size of a Buffer 91
IOBUFF.LEN(buff_num).
91
Read Data from a Buffer 92
IOBUFF.READ(buff_num,
position).
92
Write Data to a Buffer 92
IOBUFF.WRITE(buff_num, position,
value).
92
Read Operations.
93
Write Operations.
94
Special operations.
95
Advanced operations.
95
IOBUFF.FROMSTRING(buff_num, var$ [,
pos]).
95
IOBUFF.TOSTRING$(buff_num, [, start [,
size]]).
96
IOBUFF.FROMHEX(buff_num, var$ [,
pos]).
97
IOBUFF.TOHEX$(buff_num, [, start [,
size]]).
97
Base64 conversion.
98
IOBUFF.TOBASE64(buff_num).
98
IOBUFF.FROMBASE64(buff_num,
Base64String$).
99
Cryptography.
99
IOBUFF.ENCRYPT(buff_num,
key$).
99
IOBUFF.DECRYPT(buff_num,
key$).
100
CRC Function: 100
IOBUFF.CRC(buff_num, nb_bits, polynom,
initial_value, ref_in, ref_out, xor_out).
100
Bit Operations on Buffer Data.
104
IObuff.bit(buff_num, position,
bit).
104
IObuff.setbit(buff_num, position,
bit).
104
IObuff.clearbit(buff_num, position,
bit).
105
IObuff.togglebit(buff_num, position,
bit).
105
Buffer copy.
106
IObuff.copy(dest_buff_num [,pos]) ,
(source_buff_num, [, start [, size]]).
106
Code examples : 107
WIRING..
109
DIGITAL I/O..
110
PIN.STRENGTH 15, 2.
111
PIN SERIAL SHIFTING..
111
PIN.SHIFTOUT pin_data, pin_clk, data [,
bit_order] [, nb_bits] [, delay_us].
112
PIN.SHIFTIN( pin_data, pin_clk [, bit_order]
[, nb_bits] [, delay_us] ).
113
PIN INTERRUPTS..
114
Analog inputs.
115
TOUCH inputs.
115
Analog outputs.
116
Hardware interfaces: 116
PWM..
116
PWM.SETUP pin, channel, default_value,
[,frequency] [,resolution].
117
PWM.OUT channel,
value.
117
SERVO..
118
I2S BUS..
119
SPEAKER OUTPUT.
121
SPDIF OUTPUT.
122
I2C BUS..
122
PCF8574 Module.
123
ADS1115 Module.
125
MCP23017 Module.
127
SPI BUS..
128
74HC595 Module.
131
MCP23S17 Module.
132
CAN BUS..
134
CAN.SETUP..
135
CAN.INIT.
136
CAN.STOP..
136
CAN.WRITE..
136
CAN.WRITE_IOBUFF.
137
ONCANBUS..
137
CANBUS BUFFERS..
139
RMT Module.
141
Key Features.
141
Memory Management and Synchronisation
of RMT Channels.
142
Clock Divider.
142
RMT RAM Composition.
143
Memory Block Extension.
144
RMT Transmit
Synchronisation.
145
TX Transmitter Mode.
145
RX Reception Mode.
146
RX Reception Event 146
RMT Command Functions.
146
RMT.SETUP_TX channel, pin [, clk_div] [,
mem_block_num] [, idle_level] [, loop_en] [, carrier_en] [,
carrier_freq_hz] [, carrier_duty_percent] [,
carrier_level].
146
RMT.WRITE channel, num_items, name [,
wait].
147
RMT.ENCODE channel, num_items, array() [,
wait].
147
RMT.SETUP_RX channel, pin [, clk_div] [,
mem_block_num] [, invert] [, filter_en] [, filter_ticks_thresh] [,
idle_threshold] [, rm_carrier] [, carrier_freq_hz] [,
carrier_duty_percent] [, carrier_level].
147
RMT.READ array().
148
RMT.DECODE array().
148
RMT.ADD_GROUP channel.
148
RMT.DEL_GROUP channel.
148
RMT.END channel.
149
Synchronisation in
Groups.
149
Example 1: RMT Transmission of a Pulse
Sequence.
149
Example 2: RMT Transmission of a
Sinusoidal Pattern.
151
Example 3: Synchronized RMT
Transmission of Sinusoidal Patterns.
153
Example 4: Infrared Signal Reception
and Decoding with RMT on ESP32.
155
COUNTERS..
157
PID controllers.
158
SOUND PLAYER..
160
Metadata Decoding from Mp3 and
streaming.
162
SPEECH SYNTHESIS with vintage C64 SAM
speaker 163
SPEECH SYNTHESIS using google
translate.
164
SPEECH SYNTHESIS using voiceRSS free
service.
165
VS1053B Audio Decoder 166
VS1053.SETUP XCS_pin, XDCS_pin, DREQ_pin
[,info_enabled] [,SPIfreq] [SCI_CLOCKF].
168
VS1053.PLAY file$.
168
VS1053.STREAM
streaming_url$.
169
VS1053.VOICE "message",
"language".
169
VS1053.STOP.
169
VS1053.VOLUME vol.
169
VS1053.RESET.
169
VS1053.INIT patchFile$.
170
VS1053.INIT
"/patches/vs1053b-patches-flac.cmd".
170
VS1053.WRITE register,
value.
170
VS1053.READ register.
170
VS1053.MIDI_CMD cmd, data1,
data2.
170
VS1053.NOTE_ON channel, note,
velocity.
170
VS1053.NOTE_OFF channel, note,
velocity.
170
LCD DISPLAY USING I2C..
170
OLED DISPLAY..
175
ST7920 LCD DISPLAY..
177
RTC module.
179
PCA9685 (PWM / Servo) Module.
181
TM1637 display module.
182
TM1638 display module.
184
MAX7219 8-Digits 7-segment
display.
186
MAX7219 Dot Matrix Display.
187
NeoPixel WS2812B led strips.
189
NEO.SETUP pin,
[nb_led].
191
NEO.STRIP led_start_pos, led_end_pos, R, G,
B [, disable].
191
NEO.STRIP led_start_pos, led_end_pos, COLOR
[, disable].
191
NEO.PIXEL led_pos, R, G, B [,
disable].
191
NEO.PIXEL led_pos, COLOR [,
disable].
191
NEO.RGB(R, G, B).
191
NEO.GETPIXEL(led_pos).
191
NEO.ROTATELEFT num_steps, [led_end_pos,
led_end_pos, disable].
191
NEO.ROTATERIGHT num_steps, [led_end_pos,
led_end_pos, disable].
191
NEO.SHIFTLEFT num_steps, [led_end_pos,
led_end_pos, disable].
191
NEO.SHIFTRIGHT num_steps, [led_end_pos,
led_end_pos, disable].
192
NEO.REFRESH.
192
NEO.DIM(COLOR , Gain).
192
NEO.LIGHTEN(COLOR ,
Gain).
192
NEO.DARKEN(COLOR ,
Gain).
192
NEO.LINEARBLEND(COLOR1, COLOR2,
progress).
192
NEO.BILINEARBLEND(.
192
Upper_Left_COLOR, Upper_Right_COLOR,
Lower_Left_COLOR, Lower_Right_COLOR, x, y).
192
NeoPixel based WS2812b Dot Matrix
DIsplay.
193
NEOSCROLL.SETUP nb_devices, nb_lines, pin
[,layout] [,width, height, orientation].
197
NEOSCROLL.DELETE.
197
NEOSCROLL.FILL color, [x, y, width,
height].
197
NEOSCROLL.TEXT.POS x,
y.
197
NEOSCROLL.TEXT.FONT
font.
197
NEOSCROLL.SHOW x, y.
197
NEOSCROLL.TEXT.BRIGHTNESS
brightness.
197
NEOSCROLL.BRIGHTNESS
brightness.
197
NEOSCROLL.PRINT text$,
color$.
198
NEOSCROLL.SPRITESHEET
image$.
198
NEOSCROLL.SPRITE x, y, width, height,
x_in_bmp, y_in_bmp.
199
Copy a portion of the SPRITESHEET image into the canvas
using the parameters given.
199
NEOSCROLL.LIMITS [x1,] [x2], [y1],
[y2].
199
NEOSCROLL.SYNC.
199
NEOSCROLL.MODE mode.
199
NEOSCROLL.SCROLL.
199
NEOSCROLL.SCROLL.
199
Scroll the image using the current
MODE and within
the current LIMITS.c.
199
NEOSCROLL.OSCILLATE.
199
NEOSCROLL.OSCILLATE.
199
Oscillate the image using the current
MODE and within
the current LIMITS.c.
199
NEOSCROLL.X.
199
NEOSCROLL.Y.
199
HUB75 Matrix Displays -
DMAMATRIX..
203
DMAMATRIX.INIT R1, G1, B1, R2, G2, B2, A, B,
C, D, E, LAT, OE, CLK [,freq_DMA]
[,resolution].
204
DMAMATRIX.SETUP nb_devices, nb_lines
[,layout] [,width, height, orientation].
204
DMAMATRIX.DELETE.
204
DMAMATRIX.FILL color, [x, y, width,
height].
204
DMAMATRIX.TEXT.POS x,
y.
204
DMAMATRIX.TEXT.FONT
font.
205
DMAMATRIX.TEXT.COLOR
color.
205
DMAMATRIX.SHOW [x, y].
205
DMAMATRIX.TEXT.BRIGHTNESS
brightness.
205
DMAMATRIX.BRIGHTNESS
brightness.
205
DMAMATRIX.PRINT text$ [, color$ |
color].
206
DMAMATRIX.SPRITESHEET
image$.
206
DMAMATRIX.SPRITE x, y, width, height,
x_in_bmp, y_in_bmp.
207
Copy a portion of the SPRITESHEET image into the canvas
using the parameters given.
207
DMAMATRIX.LIMITS [x1,] [x2], [y1],
[y2].
207
DMAMATRIX.SYNC.
207
DMAMATRIX.MODE mode.
207
DMAMATRIX.SCROLL.
207
DMAMATRIX.SCROLL.
207
Scroll the image using the current
MODE and within
the current LIMITS.c.
207
DMAMATRIX.OSCILLATE.
207
DMAMATRIX.OSCILLATE.
207
Oscillate the image using the current
MODE and within
the current LIMITS.c.
207
DMAMATRIX.PIXEL x, y,
color.
207
DMAMATRIX.LINE x1, y1, x2, y1,
color.
207
DMAMATRIX.CIRCLE x, y, radius, color
[,fill].
207
DMAMATRIX.RECT x, y, w, h, color
[,fill].
207
DMAMATRIX.X.
207
DMAMATRIX.Y.
208
DMAMATRIX.POSX.
208
DMAMATRIX.POSY.
208
DMAMATRIX.PLAYGIF gif$ [,x ,
y].
208
DMAMATRIX.LOADGIF gif$ [,x ,
y].
208
DMAMATRIX.FRAMEGIF [do_not_show
[,loop]].
208
SD CARD ADAPTER..
208
TFT DISPLAY ILI9341.
210
TFT DISPLAY ILI9163.
214
TFT DISPLAY ILI9486.
215
TFT DISPLAY ILI9481.
218
TFT DISPLAY ILI9488.
219
TFT DISPLAY ST7735.
220
TFT DISPLAY ST7796.
221
TFT DISPLAY ST7789.
224
OLED DISPLAY SSD1351 RGB..
225
TFT DISPLAY GC9A01.
226
TouchScreen.
226
TouchScreen - Resistive.
226
TouchScreen - Capacitive.
227
TFT FONTS..
228
QR CODES..
232
GRAPHIC GUI for TFT.
232
GUI Objects.
233
gui.TextLine.
233
gui.Button.
234
gui.Image.
234
gui.ButtonImage.
235
gui.CheckBox.
235
gui.Slider.
236
gui.ProgressBar.
236
gui.Ramp.
237
gui.Gauge.
237
gui.Box.
237
gui.Circle.
238
gui.Rect 238
gui.Line.
239
GUI.TEXTAREA(x, y, width, height, "text",
[,font] [,alignment] [,color_text] [,color_back] [,color_frame]
[,margin] ).
240
GUI.GETTEXT obj, var$.
241
GUI.VISIBLE obj,
visible.
241
GUI Functions.
241
gui.GetValue.
241
gui.Target 241
GUI Commands.
241
gui.INIT..
241
gui.REDRAW...
241
gui.REFRESH..
241
gui.AUTOREFRESH..
241
gui.SETVALUE..
242
gui.SETTEXT..
242
gui.SETIMAGE..
242
gui.SETCOLOR..
242
gui.SETRANGE..
243
gui.SETEVENT..
243
gui.SETSTYLE..
243
LovyanGFX Graphics Library.
244
Key Features: 244
Implementation Notes.
245
Color Management 245
GFX Functions.
245
TFT.RGB(r, g, b).
245
TFT.COLOR colorName.
245
TFT.WIDTH.
246
TFT.SPRITE.WIDTH
spriteNum.
247
TFT.HEIGHT.
247
TFT.SPRITE.HEIGHT
spriteNum.
247
TFT.GETPIXEL x, y.
248
TFT.SPRITE.GETPIXEL spriteNum, x,
y.
248
TFT.SIZE filename$.
248
TFT.FRAMEGIF [loop =
0].
248
GFX Commands.
249
TFT.LOADFONT path$,
font_num.
249
TFT.INIT [rot].
249
TFT.SETFREQ freq [,
read_freq].
250
TFT.TEXT.POS x, y.
250
TFT.SPRITE.TEXT_POS spriteNum, x,
y.
250
TFT.TEXT.COLOR col [,
back].
250
TFT.SPRITE.TEXT.COLOR spriteNum, col [,
back].
251
TFT.TEXT.SIZE size [,
font].
251
TFT.SPRITE.TEXT.SIZE spriteNum, size [,
font].
251
TFT.PRINT str$ [, x] [, y] [,
fontnum].
252
TFT.SPRITE.PRINT spriteNum, str$ [, x] [, y]
[, fontnum].
252
TFT.BMP filename$ [, x] [, y] [,
scale].
252
TFT.JPG filename$ [, x] [, y] [,
scale].
253
TFT.IMAGE filename$ [, x] [, y] [, zoom] [,
x1] [, y1] [, w] [, h].
253
TFT.SPRITE.IMAGE spriteNum, filename$ [,x]
[,y] [,zoom] [,x1] [,y1] [,w] [,h].
254
TFT.BRIGHTNESS brt.
254
TFT.TEXT.FONT fontnum.
254
TFT.SPRITE.TEXT.FONT spriteNum,
fontnum.
255
TFT.TEXT.DRAW str$, x, y [,
fontnum].
255
TFT.SPRITE.TEXT.DRAW spriteNum, str$, x, y
[, fontnum].
255
TFT.TEXT.ALIGN datum.
256
TFT.SPRITE.TEXT.ALIGN spriteNum,
datum.
256
TFT.TEXT.PADDING
padding.
256
TFT.SPRITE.TEXT.PADDING spriteNum,
padding.
256
TFT.QRCODE str$, x, y, w [,
version].
257
TFT.CREATESPRITE spriteNum, w,
h.
257
TFT.DELETESPRITE
spriteNum.
257
TFT.SPRITE.FROMBMP spriteNum,
filename$.
258
TFT.SPRITE.FROMIMG spriteNum,
filename$.
258
TFT.LINE x1, y1, x2, y2, col [,
radius].
258
TFT.SPRITE.LINE spriteNum, x1, y1, x2, y2,
col [, radius].
259
TFT.WEDGELINE x1, y1, x2, y2, col, radius1,
radius2.
259
TFT.SPRITE.WEDGELINE spriteNum, x1, y1, x2,
y2, col, radius1, radius2.
260
TFT.RECT x, y, w, h, col [, fill] [,
radius].
260
TFT.SPRITE.RECT spriteNum, x, y, w, h, col
[, fill] [, radius].
260
TFT.CIRCLE x, y, radius, col [,
fill].
261
TFT.SPRITE.CIRCLE spriteNum, x, y, radius,
col [, fill].
261
TFT.ELLIPSE x, y, radius1, radius2, col [,
fill].
262
TFT.SPRITE.ELLIPSE spriteNum, x, y, radius1,
radius2, col [, fill].
262
TFT.ARC x, y, radius1, radius2, angle1,
angle2, col [, fill].
262
TFT.SPRITE.ARC spriteNum, x, y, radius1,
radius2, angle1, angle2, col [, fill].
263
TFT.TRIANGLE x1, y1, x2, y2, x3, y3, col [,
fill].
263
TFT.SPRITE.TRIANGLE spriteNum, x1, y1, x2,
y2, x3, y3, col [, fill].
264
TFT.PIXEL x, y, col.
264
TFT.SPRITE.PIXEL spriteNum, x, y,
col.
264
TFT.FILL col.
265
TFT.SPRITE.FILL spriteNum,
col.
265
TFT.AAC.
265
TFT.SAVE filename$ [,
spriteDest].
266
TFT.PIVOT xf, yf.
266
TFT.SPRITE.PIVOT spriteNum, xf,
yf.
266
TFT.SPRITE.COPY spriteNum, spriteDest, x, y,
w, h, x1, y1 [,col] [,angle] [,zoom].
267
TFT.PUSH spriteNum, xf, yf [, col] [, angle]
[, zoom].
267
TFT.SPRITE.PUSH spriteNum [, spriteDest] [,
xf] [, yf] [, col] [, angle] [, zoom].
267
TFT.SPRITE.PUSHAA spriteNum [, spriteDest]
[, xf] [, yf] [, col] [, angle] [, zoom].
268
TFT.LOADGIF path$ [, x] [,
y].
268
TFT.PLAYGIF path$ [, x] [,
y].
269
LVGL - Light and Versatile Graphics
Library.
269
Core Concepts in Annex32 LVGL.
269
Base Object 269
Parts.
269
States.
269
Flags.
270
Object Relationships, Attributes, Styles,
and Events Object 270
Hierarchy.
270
Attributes and Properties.
270
Styles.
270
Events in LVGL (Annex) 270
Colors in LVGL (Annex) 270
Opacity in LVGL (Annex) 271
Usage in Annex.
271
Widgets in LVGL (and Annex): The Building
Blocks of User Interfaces.
271
Basic Display Elements:
271
Buttons and Input: 272
Selectors and Indicators:
272
Checkboxes and Radio Buttons:
272
Indicators and Visualizations:
273
Data Display: 273
Groups: 273
Getting Started with Annex.
273
Initializing LVGL and Understanding
Memory Allocation.
273
LVGL.INIT: Configuring Memory and
Display.
273
Memory Allocation Breakdown: 273
Important Notes on Memory Management.
274
Understanding col_fg and col_bg in
LVGL.INIT.
274
Color Representation. 274
LVGL.SET_THEME : Setting the default
Theme.
276
Understanding lv_style_selector_t
277
Functions and Commands in LVGL
Implementation.
277
LVGL Functions.
278
LVGL.INIT col_fg, col_bg [, buff_size [,
buff_count = 1].
278
LVGL.SET_THEME col_primary, col_secondary,
fontnum, dark [, theme_type = 0].
279
LVGL.REFRESH.
279
LVGL.START [memory = 8192] [, priority = 0]
[, core = 0].
279
LVGL.STOP.
280
LVGL.RESET.
280
LVGL.CLEAN [obj].
280
LVGL.DELETE obj.
280
LVGL.SCREEN.
281
LVGL.CURSOR.
281
LVGL.DEF_FATHER obj.
281
LVGL.ARC [x [, y [, w [,
h]]]].
281
LVGL.ARC_ROTATE_OBJ_TO_ANGLE arc_obj,
obj_to_rotate, radius_offset.
282
LVGL.BASE [x [, y [, w [,
h]]]].
282
LVGL.BAR [x [, y [, w [,
h]]]].
282
LVGL.BUTTON text$ [, x [, y [, w [,
h]]]].
283
LVGL.BUTTONMATRIX but_map$ [, x [, y [, w [,
h]]]].
283
LVGL.CANVAS [x [, y [, w [, h [,
col_bg]]]]].
284
LVGL.CHECKBOX text$ [, x [, y [, w [,
h]]]].
284
LVGL.RADIO text$ [, x [, y [, w [,
h]]]].
284
LVGL.DROPDOWN options$ [, x [, y [, w [,
h]]]].
285
LVGL.GIF path$ [, x [, y [, w [,
h]]]].
285
LVGL.GIF_PLAY obj,
play_control.
286
LVGL.IMAGE path$.
286
LVGL.IMAGEBUTTON img1 [,
img2].
286
LVGL.IMAGETOGGLE img1 [,
img2].
287
LVGL.KEYBOARD mode.
287
LVGL.KBD_SET_TEXTAREA kbd_obj,
txt_obj.
287
LVGL.LABEL text$ [, x [, y [, w [,
h]]]].
288
LVGL.LED [color [, x [, y [, w [,
h]]]]].
288
LVGL.LIST [x [, y [, w [,
h]]]].
288
LVGL.ADD_BUTTON list_obj, icon,
text$.
289
LVGL.ADD_TEXT list_obj,
text$.
289
LVGL.MSGBOX title$,
msg$.
289
LVGL.MSGBOX_CLOSE
msgbox_obj.
290
LVGL.ROLLER options$ [, x [, y [, w [,
h]]]].
290
LVGL.SCALE [x [, y [, w [,
h]]]].
290
LVGL.SET_ANGLE_RANGE obj,
val.
291
LVGL.SET_TICKS obj, total,
interval.
291
LVGL.SET_LABEL_SHOW obj,
val.
291
LVGL.LINE.
292
LVGL.SET_LINE_NEEDLE_VALUE scale_obj,
line_obj, length, val.
292
LVGL.SET_IMAGE_NEEDLE_VALUE scale_obj,
image_obj, val.
292
LVGL.SLIDER [x [, y [, w [,
h]]]].
292
LVGL.SPINNER anim, angle [, x [, y [, w [,
h]]]].
293
LVGL.SWITCH [x [, y [, w [,
h]]]].
293
LVGL.TABVIEW [x [, y [, w [,
h]]]].
293
LVGL.ADD_TAB tab_view_obj,
tab_name$.
294
LVGL.SET_TAB_BAR_POS tab_view_obj,
tab_pos.
294
LVGL.SET_ACTIVE obj, idx,
[anim].
294
LVGL.TEXTAREA text$ [, x [, y [, w [,
h]]]].
295
LVGL.ADD_EVENT obj, event,
gotoline.
295
LVGL.REMOVE_EVENT obj,
event.
295
LVGL.ADD_FLAG obj,
flag.
296
LVGL.REMOVE_FLAG obj,
flag.
296
LVGL.UPDATE_FLAG obj, val, [flag =
1].
296
LVGL.GET_FLAG obj.
297
LVGL.ADD_STATE obj,
state.
297
LVGL.REMOVE_STATE obj,
state.
297
LVGL.SET_STATE obj, val, [state =
1].
298
LVGL.GET_STATE obj.
298
LVGL.ALIGN_TO obj, obj_base, align [, x [,
y]].
298
LVGL.GET_CHILD obj,
idx.
299
LVGL.GET_CHILD_COUNT
obj.
299
LVGL.GET_PARENT obj.
299
LVGL.SET_PARENT obj,
obj_parent.
300
LVGL.GET_CLASS_ID obj.
300
LVGL.GROUP.
300
LVGL.GROUP_ADD group,
obj.
300
LVGL.GROUP_REMOVE obj.
301
LVGL.GROUP_DELETE
group.
301
LVGL.GET_GROUP obj.
301
LVGL.GET_TARGET.
301
LVGL.GET_GESTURE.
302
LVGL.GET_VALUE obj.
302
LVGL.LOAD_FONT path$,
fontnum.
302
LVGL.SET_FONT obj, fontnum
[,style_selector].
303
LVGL.SET_BG_ANGLES obj, start,
end.
303
LVGL.SET_BG_COLOR obj, col_bg [,
style_selector].
304
LVGL.SET_BG_OPA obj, val [,
style_selector].
304
LVGL.SET_BORDER_COLOR obj, color [,
style_selector].
304
LVGL.SET_BORDER_SIDE obj, side [,
style_selector].
305
LVGL.SET_BORDER_WIDTH obj, width [,
style_selector].
305
LVGL.SET_CLIP_CORNER obj, val [,
style_selector].
305
LVGL.SET_ARC_COLOR obj, color [,
style_selector].
306
LVGL.SET_ARC_OPA obj, val [,
style_selector].
306
LVGL.SET_LINE_COLOR obj, color [,
style_selector].
306
LVGL.SET_LINE_OPA obj, val [,
style_selector].
307
LVGL.SET_FLEX_ALIGN obj, main, cross,
track_cross.
307
LVGL.SET_FLEX_FLOW obj,
flex_flow.
307
LVGL.SET_HEIGHT obj,
h.
307
LVGL.SET_IMAGE_RECOLOR obj, color [,
style_selector].
308
LVGL.SET_IMAGE_RECOLOR_OPA obj, val [,
style_selector].
308
LVGL.SET_LAYER obj,
layer.
308
LVGL.SET_LENGTH obj, val [,
style_selector].
309
LVGL.SET_LINE_ROUNDED obj, val [,
style_selector].
309
LVGL.SET_LINE_WIDTH obj, val [,
style_selector].
309
LVGL.SET_MARGIN obj, top, [,bottom [,left
[,right [,vert [,horiz [,
style_selector]]]]]].
310
LVGL.SET_MODE obj,
val.
310
LVGL.SET_PAD obj, top, [,bottom [,left
[,right [,vert [,horiz [,row [,column [,
style_selector]]]]]]]].
311
LVGL.SET_PAD_GAP obj, val [,
style_selector].
311
LVGL.SET_POS obj, x,
y.
312
LVGL.SET_RANGE obj, start,
end.
312
LVGL.SET_RADIUS obj, val [,
style_selector].
312
LVGL.SET_ROTATION obj,
angle.
313
LVGL.SET_SCROLL_DIR obj,
scroll_dir.
313
LVGL.SET_SIZE obj, w,
h.
313
LVGL.SET_SIZE_PCT obj, w_pct,
h_pct.
313
LVGL.SET_TEXT obj,
str$.
314
LVGL.SET_TEXT_ALIGN obj,
align.
314
LVGL.SET_TEXT_COLOR obj, color [,
style_selector].
314
LVGL.SET_TRANSFORM_PIVOT obj, x, y [,
style_selector].
315
LVGL.SET_TRANSFORM_PIVOT_PCT obj, x_pct,
y_pct [, style_selector].
315
LVGL.SET_IMAGE_PIVOT obj, x,
y.
315
LVGL.SET_IMAGE_PIVOT_PCT obj, x_pct, y_pct
[.
316
LVGL.SET_TRANSFORM_ROTATION obj, angle [,
style_selector].
316
LVGL.SET_TRANSFORM_SCALE obj, x, y [,
style_selector].
316
LVGL.SET_VALUE obj, val [, anim =
1].
317
LVGL.SET_WIDTH obj, w.
317
LVGL.SPRITE.PUSH canvas_obj, sprite_num [, x
[, y]].
318
LVGL.SWAP
obj, obj_base.
318
LVGL.VISIBLE obj, vis.
318
LVGL.RGB(red, green,
blue).
318
LVGL.MOUSE_ENABLE.
319
LVGL.MOUSEMOVE mouse_x, mouse_y,
mouse_z.
319
LVGL.MOUSE_CURSOR.
319
LVGL.KEYBOARD_ENABLE.
320
LVGL.SET_KEYBOARD_KEY
key.
320
LVGL.SET_KEYBOARD_GROUP
group.
320
LVGL.SET_IMAGE_SRC obj,
src$.
320
LVGL.GET_IMAGE_SRC
obj.
321
LVGL.GET_CLASS_NAME$
obj.
321
LVGL.GET_TEXT$ obj.
321
LVGL Tables.
322
Widget States (lv_state_t) 323
Widget Parts (lv_part_t) 324
Object Flags (lv_obj_flag_t) 324
Image Button States
(lv_imagebutton_state_t) 326
LVGL Alignment Enums (lv_align_t)
327
LVGL Text Alignment Enums
(lv_text_align_t) 328
LVGL Direction Enums (lv_dir_t)
328
LVGL Border Side Enums (lv_border_side_t)
329
Flexbox Layout Options and
Enumerations.
329
Flexbox Layout Options.
329
Flex Alignment Options (lv_flex_align_t)
330
Flex Flow Options (lv_flex_flow_t)
330
...............................................................................................................................................................................................
331
Scale modes (lv_scale_mode_t)
331
...........................................................................................................................................................................................
331
Label Long Mode Options
(lv_label_long_mode_t) 331
...............................................................................................................................................................................................
332
Keyboard Mode Enums (lv_keyboard_mode_t)
332
...............................................................................................................................................................................................
332
Keyboard Key Enums (lv_key_t)
332
...............................................................................................................................................................................................
333
Event Codes (lv_event_code_t)
333
Symbol Definitions (unicode from
FontAwesome) 336
USB HID INTERFACE (Mouse, Keyboard,
Gamepad) - ESP32-S3 only.
339
How use the USB devices.
341
USB.SETUP Command.
341
Mouse Input 341
Keyboard Input 341
Associated Events.
342
1.
onMouseMove :
Triggered when the mouse moves. 342
2.
onMouseClick:
Triggered when a mouse button is clicked. 342
3.
onKeyboard:
Triggered when a key is pressed on the keyboard. 342
4.
onGamePad:
Triggered when there is a change in the gamepad state. 342
Handling Events.
342
USB HID Mouse / Keyboard Emulation -
ESP32-S3 only.
342
Introduction.
342
Commands.
343
USB.START [keymap$].
343
USB.TYPETEXT text$.
343
USB.KEYPRESS keycode.
343
USB.KEYRELEASE keycode.
343
USB.KEYRELEASEALL.
344
USB.MOUSEMOVE width, height, [wheel [,
pan]].
344
USB.MOUSECLICK button.
344
USB.MOUSEPRESS button.
344
USB.MOUSERELEASE button.
344
Mouse Button Definitions.
345
Keycode Definitions.
346
Keymaps for regional
keyboards.
347
INFRARED INTERFACE..
348
ULTRASONIC DISTANCE SENSOR
HC-SR04.
352
DHT xx Temperature / Humidity
Sensors.
353
DS18B20 Temperature Sensors.
355
TEMPR$(pin_number, [ID],
[resolution]).
356
BNO055 Absolute Orientation Sensor
357
BME280 Combined humidity and pressure
sensor 359
BME680 Combined gas, pressure,
temperature & humidity sensor 361
FUNCTIONS / COMMANDS..
363
BME680.BEGIN(address).
364
BME680.SETUP(rate,
filename).
364
BME680.SAVE_STATE(filename).
364
BME680.LOAD_STATE(filename).
364
BME680.SET_OFFSET(offset).
364
BME680.RUN.
364
BME680.TEMP.
364
BME680.RAW_TEMP.
364
BME680.HUM.
364
BME680.RAW_HUM.
364
BME680.PRESS.
364
BME680.IAQ.
365
BME680.STATIC_IAQ.
365
BME680.IAQ_ACCURACY.
365
BME680.CO2.
365
BME680.BREATH_VOC.
365
BME680.GAS.
365
BME680.GAS_RES.
365
BME680.BME_STATUS.
365
BME680.BSEC_STATUS.
365
BME680.STAB_STATUS.
365
BME680.RUN_STATUS.
365
HDC1080 High Accuracy Digital Humidity
Sensor with Temperature Sensor 366
CCS811 Air Quality Sensor 367
APDS9960 Digital Proximity, Ambient
Light, RGB and Gesture Sensor 370
RFID MFRC522 RFID cards reader
373
Writing NUID for UID changeable card (4 byte UID version)
377
VL53L0X TOF (Time Of Flight) Distance
Sensor 377
VL53L0X.INIT function.
378
VL53L0X.SETRANGE
range.
378
VL53L0X.SETACCURACY
accuracy.
378
VL53L0X.DISTANCE.
378
VL53L0X.DISTANCE_N.
378
VL53L0X.CUSTOM signal_rate_limit,
VcselPeriodPreRange, VcselPeriodFinalRange,
MeasurementTimingBudget.
379
HX711 - Weight Measurement
Module.
379
SI5351 Clock Generator Module.
381
SI5351.INIT [capacitor
[,crystal]].
383
SI5351.CALIB
correction.
383
SI5351.SETFREQ out_nb,
frequency.
383
SI5351.SETFREQ_MAN out_nb, frequency,
pll.
383
SI5351.STRENGTH out_nb,
strength.
383
SI5351.PHASE out_nb,
phase.
383
SI5351.RESET_PLL
pll_nb.
383
SI5351.ENABLE out_nb,
enable.
383
SI5351.INVERT out_nb,
invert.
383
SI5351.LOAD filename$.
384
STEP MOTOR..
384
STEPPER.SETUP stepper_id, pin_step,
pin_dir.
386
STEPPER.SETPARAM stepper_id, speed,
acceleration.
386
STEPPER.SETPOSITION stepper_id,
position.
386
STEPPER.MOVE stepper_id,
position.
386
STEPPER.MOVETO stepper_id,
position.
386
STEPPER.STOP
stepper_id.
386
STEPPER.FORCESTOP
stepper_id.
386
STEPPER.RUNFWD
stepper_id.
386
STEPPER.RUNBKD
stepper_id.
386
STEPPER.GETPOSITION(stepper_id).
387
STEPPER.GETTARGET(stepper_id).
387
MPU9250.
387
MPU6500 / MPU6050.
389
MPU6886 (For M5 Atom) 391
IMU FUSION FUNCTIONS..
393
ETHERNET Module W5500.
395
FTP..
399
BAS.FTP$.
399
Server data requests (GET, POST and
PUT) 400
-
WGET$(server$, port,
[,rx_header] [,header$]).
401
-
WGET$(url$ [,rx_header]
[,header$]).
401
-
WPOST$(server$, body$, port
[,rx_header] [,header$] ).
401
-
WPOST$(url$, body$ [,rx_header]
[,header$]).
401
-
WPUT$(server$, body$, port
[,rx_header] [,header$] ).
401
-
WPUT$(url$, body$ [,rx_header]
[,header$]).
401
-
WGETASYNC[(] server$, port,
[,rx_header] [)].
401
-
WGETASYNC[(] url$,[,rx_header]
[)].
401
MQTT Client 403
MQTT.Setup(server$
[,debug]).
405
MQTT.Certif(cert_pem$ [,client_cert_pem$]
[,client_key_pem$]).
405
MQTT.PSK(psk_hint_key$).
405
MQTT.LWT(topic$, message$ [,Qos]
[,retain]).
405
MQTT.Connect(login$, pass$
[,id$]).
405
MQTT.Connect("", ""
[,id$]).
405
MQTT.Disconnect[()].
405
MQTT.Publish(topic$, message$ [,Qos]
[,retain]).
405
MQTT.Subscribe(topic$
[,Qos]).
405
MQTT.UnSubscribe(topic$).
405
MQTT.Connected[()].
405
MQTT.Status[()].
406
MQTT Broker 408
MqttBroker.Setup(port, login$, password$ [,
debug]).
409
MqttBroker.Start(ramsize).
409
MqttBroker.Stop.
410
MqttBroker.Restart.
410
MqttBroker.Publish(topic, payload[, qos[,
retain]]).
410
MqttBroker.Subscribe(topic$).
410
MqttBroker.UnSubscribe(topic$).
411
MqttBroker.ListTopics[(list$)].
411
MqttBroker.ClearTopics.
412
MqttBroker.ListClients[(list$)].
412
OnMQTT Event Handler 412
OnMQTT label.
412
Event Information Variables.
413
Special Event Topics.
413
Disabling ONMQTT.
413
ESP-NOW...
416
EspNow.Begin.
417
EspNow.Stop.
417
EspNow.Add_Peer(MAC_add$ [,interface]
[,channel]).
417
EspNow.Del_Peer.
417
EspNow.Write(msg$).
417
EspNow.Write(msg$,
MAC_add$).
417
EspNow.READ$.
417
ESPNow.REMOTE$.
417
ESPNow.ERROR$.
417
OnEspNowMsg label.
418
OnEspNowError label.
418
BLUETOOTH Low Energy (BLE) 426
Overview..
426
Operating Modes.
426
Server Mode.
427
Communication Details.
427
BLE Commands / Functions.
427
BLUETOOTH.SETUP "devicename" [,
code].
427
BLUETOOTH.CLEAR.
428
BLUETOOTH.DELETE.
428
BLUETOOTH.POWER pow.
428
BLUETOOTH.WRITE
"text".
428
BLUETOOTH.READ$.
428
BLUETOOTH.LEN.
428
BLUETOOTH.CONNECTED.
428
BLUETOOTH.STATUS.
428
BLUETOOTH.WRITE_IOBUFF(buff_num [, start [,
size]]).
428
BLUETOOTH.READ_IOBUFF(buff_num).
428
BLUETOOTH.SCAN time.
428
BLUETOOTH.SCANRESULT$.
428
Client Mode Functions.
429
BLUETOOTH.CLIENT mac, service_UUID,
characteristic_UUID.
429
BLUETOOTH.CLWRITE characteristic_UUID,
"text".
429
BLUETOOTH.CLWRITE_IOBUFF
characteristic_UUID, (buff_num [, start [,
size]]).
429
Event Handling.
429
ONBLUETOOTH label.
429
TELEGRAM (messenger) support 433
LORA..
435
LoRa.Setup ss, reset,
dio0.
438
LoRa.Begin(freq).
438
LoRa.End.
438
LoRa.BeginPacket.
438
LoRa.Print.
438
LoRa.EndPacket.
438
LoRa.Receive.
438
LoRa.RSSI.
438
LoRa.SNR.
438
LoRa.Idle.
438
LoRa.Sleep.
438
LoRa.TXpower pow.
438
LoRa.SyncWord word.
439
LoRa.EnableCRC enable.
439
OnLora.
439
LoRa.Message$.
439
Modbus.
441
MODBUS.CONNECT IP$, [port] [,timeout]
[,idleTimeout].
441
MODBUS.DISCONNECT.
442
MODBUS.REQUEST token, serverID, functionCode [,p1] [,p2]
[,p3].
442
Modbus RTU Support 445
MODBUS.SetupRTU RX_pin, TX_pin, RE_DE_pin,
["BBBB,P,D,S"].
445
MODBUS.requestRTU ….. (see the
details in the chapter above) 445
MODBUS RTU wiring.
447
Regular Expressions (RegEx) 448
Patterns.
449
Magic characters.
449
Repetition.
450
Anchor to start and/or end of
string.
451
Captures.
451
Frontier patterns.
452
Multiple matches.
452
M5 Tough.
453
M5Tough.BatLevel.
455
M5Tough.BatVoltage.
455
M5Tough.BatCurrent.
455
M5Tough.VinVoltage.
455
M5Tough.VinCurrent.
455
M5Tough.VBusVoltage.
455
M5Tough.VBusCurrent.
455
M5Tough.BatChgCurrent.
455
M5Tough.BatPower.
455
M5Tough.AxpTemp.
455
M5Tough.ApsVoltage.
455
M5Tough.AxpState.
455
M5Tough.TftPower
power.
455
M5Tough.SpeakerPower
power.
455
M5Tough.SetBusPowerMode
mode.
456
M5Tough.PowerOff sec.
456
M5Tough.LightSleep
sec.
456
M5Tough.DeepSleep sec.
456
ANNEXCAM..
456
Functionalities enabled in the ANNEXCAM
version.
459
Camera Functions / commands.
460
Using AnnexCam in output page.
463
Control of the camera using
URL.
464
Face Recognition.
465
Image / video reception from
Annex.
466
ANNEXEPAPER for LILYGO T5 4.7” E-paper
module.
468
.........................................................................................................................................
469
GRAPHIC GUI for E-PAPER..
471
Functionalities enabled in the E-PAPER
version.
478
PEEK and POKE FUNCTIONS..
480
BAS.PEEK(addr).
480
BAS.PEEK16(addr).
480
BAS.PEEK8(addr).
480
BAS.POKE addr, data.
480
BAS.POKE16 addr, data.
480
BAS.POKE8 addr, data.
480
CONVERSION FUNCTIONS..
481
CONVERT.DEGC_TO_F(degC).
482
CONVERT.F_TO_DEGC(degF).
482
CONVERT.TO_IEEE754(num).
482
CONVERT.FROM_IEEE754(iee754_bin).
482
CONVERT.MAP(number, fromLow, fromHigh,
toLow, toHigh).
482
CONVERT.TO_BCD(number).
482
CONVERT.FROM_BCD(number).
482
CONVERT.LIMITS(number, min,
max).
482
BAS CONSTANTS..
482
BAS.VER.
483
BAS.VER$.
483
BAS.ERRLINE.
483
BAS.ERRNUM.
483
BAS.ERRMSG$.
483
BAS.FILENAME$.
483
BAS.RTCMEM$.
483
BAS.SSID$.
483
BAS.PASSWORD$.
483
BAS.LOAD.
483
BAS.RESETREASON.
484
BAS.WAKEUPREASON.
485
BAS.DEVICE.
486
BAS.TFT.
487
OPTION COMMANDS..
487
OPTION.BASE 0 | 1.
488
OPTION.CPUFREQ
80|160|240.
488
OPTION.ES8388.
488
OPTION.MAC mac$.
488
OPTION.LOWRAM value.
488
OPTION.NTPSYNC.
488
OPTION.WDT time.
488
OPTION.WDTRESET.
488
OPTION.WLOG value.
488
OPTION.TOUCH value.
489
OPTION.I2S BCLK_pin, WSEL_pin,
DOUT_pin.
489
OPTION.PSRAM limit.
489
HALL Sensor (Internal): 489
BAS.HALL.
489
FUNCTIONS: 489
NUMERICAL FUNCTIONS..
489
ABS(number) 490
ACOS(number) 490
ADC(pin) 490
APDS9960.SETUP (mode) 490
APDS9960.READGESTURE..
490
APDS9960.AMBIENT.
490
APDS9960.RED..
490
APDS9960.GREEN..
490
APDS9960.BLUE..
491
APDS9960.PROXIMITY..
491
APDS9960.GESTUREGAIN (gain) 491
APDS9960.GESTURELED (intensity)
491
ASC(string$) 491
ASIN(number) 491
ATAN(number) 491
ATAN2(x, y) 491
BAS.VER..
491
BAS.ERRLINE..
492
BAS.ERRNUM..
492
BME280.SETUP(address) 492
BME280.ALT(qnh) 492
BME280.HUM..
492
BME280.QFE..
492
BME280.QNH(altitude) 492
BME280.TEMP..
492
BNO055.SETUP( address) 492
BNO055.HEADING..
492
BNO055.PITCH..
492
BNO055.ROLL.
492
BNO055.VECTOR ( param, axis) 493
BNO055.CALIB [(param)] 493
CINT(number) 494
CONVERT.DEGC_TO_F(degC) 494
CONVERT.F_TO_DEGC(degF) 494
CONVERT.TO_IEEE754(num) 494
CONVERT.FROM_IEEE754(ieee754_bin)
494
CONVERT.MAP(number, fromLow, fromHigh,
toLow, toHigh) 494
CONVERT.TO_BCD(number) 494
CONVERT.FROM_BCD(number) 494
COS(number) 494
COUNTER.COUNT (cnt) 494
COUNTER.PERIOD (cnt) 494
DATEUNIX(date$) 494
DHT.TEMP..
495
DHT.HUM..
495
DHT.HEATINDEX..
495
DISTANCE(pin_trig, pin_echo) 495
EMAIL from$, to$, subject$,
message$.
495
ESPNOW.ADD_PEER(MAC_add$ [,interface]
[,channel]) 495
ESPNOW.BEGIN..
495
ESPNOW.DEL_PEER(MAC_add$) 495
ESPNOW.STOP..
495
ESPNOW.WRITE( msg$) 495
ESPNOW.WRITE( msg$,MAC_add$) 495
EXP(number) 495
FIX(number) 496
FILE.DELETE(filename$) 496
FILE.EXISTS(filename$) 496
FILE.SIZE(filename$) 496
FLASHFREE..
496
FUSION.ANGLE(axis) 496
INSTR([start], string$, pattern$)
496
I2C.LEN..
496
I2C.READ..
496
I2C.READREGBYTE (i2c_address, register)
497
I2C.END..
497
INT(number) 497
LEN(string$) 497
LOG(number) 497
MILLIS..
497
MQTT.Setup(server$ [,debug]) 497
MQTT.Certif(cert_pem$ [,client_cert_pem$]
[,client_key_pem$]) 498
MQTT.PSK(psk_hint_key$) 498
MQTT.LWT(topic$, message$ [,Qos,
[,retain]) 498
MQTT.Connect(login$, pass$ [,id$])
498
MQTT.Connect("", "" [,id$]) 498
MQTT.Disconnect[()] 498
MQTT.Publish(topic$, message$ [,Qos]
[,retain]) 498
MQTT.Subscribe(topic$ [,Qos])
498
MQTT.UnSubscribe(topic$) 498
MQTT.Connected[()] 498
MQTT.Status[()] 498
NEO.GETPIXEL(pos) 499
NEO.RGB(R, G, B) 499
PI 499
PID1.COMPUTE( current_value,
target_value) 499
PIN(pin_number) 499
PIN.TOUCH(pin_number) 499
PING(host$) 499
POW(x, y) 499
RAMFREE..
499
RFID.SETUP(CS_pin, RST_pin) 500
RFID.SETGAIN(gain) 500
RFID.SETKEY(key$) 500
RFID.RESET.
500
RFID.AWAKE..
500
RFID.SETNUID(NUID$) 500
RFID.WRITE(block, data$) 501
RND(number) 501
SERIAL.LEN..
501
SERIAL2.LEN..
501
SGN(number) 501
SIN(number) 501
SPI.BYTE(byte) 501
SQR(number) 501
TAN(number) 501
TFT.RGB(r,g,b) 501
TIMEUNIX(time$) 502
TM1638.BUTTONS..
502
TOUCH.X..
502
TOUCH.Y..
502
VAL(string$) 502
WIFI.CHANNEL.
502
WIFI.MODE..
502
WIFI.NETWORKS ( network$ )
503
WIFI.RSSI 503
WIFI.STATUS..
503
WORD.COUNT( string$ [,delimiter$])
503
WORD.FIND( string$, find$ [,delimiter$])
504
STRING FUNCTIONS..
505
BAS.ERRMSG$.
506
BAS.FILENAME$.
506
BAS.FTP$( host$, login$, password$,
file$, folder$) 506
BAS.PASSWORD$.
506
BAS.RTCMEM$.
506
BAS.SSID$.
506
BAS.VER$.
506
BIN$(number) 506
BUTTON$(name$, label [, id] )
506
CHECKBOX$( variable [,id]) 506
CHR$(number) 507
CSSID$(object_id, object_style)
507
DATE$[(format)] 507
ESPNOW.ERROR$.
507
ESPNOW.READ$.
507
ESPNOW.REMOTE$.
507
FILE.DIR$[(path$)] 507
FILE.READ$(filename$,[line_num] | [start,
length]) 507
HEX$(number) 507
HtmlEventButton$.
507
HtmlEventVar$.
508
IMAGE$(path [,id]) 508
IMAGEBUTTON$(path, label [,id])
508
IP$.
508
IR.GET$[ (param) ] 508
JSON$(string$, field$) 508
LCASE$(string$) 508
LED$(variable [,id]) 509
LEFT$(string$, num) 509
LISTBOX$(variable$, "option1, option2,
option3, ..." [, height] [,id]) 509
MAC$[ (id) ] 509
METER$(variable, min, max [,id])
509
MID$(string$, start [,num]) 509
MQTT.Message$.
510
MQTT.Topic$.
510
OCT$(number) 510
PASSWORD$(variable [, id] ) 510
REPLACE$(expression$, find$,
replacewith$) 510
RFID.NUID$.
510
RFID.TYPE$.
511
RFID.READ$(block [,key_b]) 511
RIGHT$(string$, num) 511
RTC.DATE$[(format)] 511
RTC.TIME$.
512
SERIAL.CHR$.
512
SERIAL.INPUT$.
512
SERIAL2.CHR$.
512
SERIAL2.INPUT$.
512
SLIDER$(variable, min, max [,step] [,id])
512
SPACE$(number) 512
SPI.STRING$(data$, len) 512
SPI.HEX$(datahex$, len) 512
STR$ (number [,format$ [,toint]])
513
STRING$(num, char$) 515
TEMPR$(pin_number [,ID]) 515
TEXTAREA$(variable [, id] ) 516
TEXTBOX$(variable [, id] ) 516
TRIM$(string$) 516
TIME$.
516
UCASE$(string$) 516
UDP.READ$.
516
UDP.REMOTE$.
516
UNIXDATE$(value [,format]) 516
UNIXTIME$(value) 516
URLMSGGET$ ([arg$]) 517
WGET$( http_server$, port [,header] )
517
WGET$( url$, [,header] ) 517
WGETRESULT$.
517
WORD$(string$, position [,delimiter$])
517
WORD.DELETE$(string$, position
[delimiter$]) 517
WORD.EXTRACT$(string$, lead$, trail$)
518
WORD.GETPARAM$( setting$,
parameter$ [,separator$]) 518
WPOST$(server$, body$, port [,header])
518
WPOST$(url$, body$, [,header])
518
COMMANDS: 518
AUTOREFRESH interval 519
BAS.LOAD filename$.
519
BAS.RTCMEM$ = val$.
519
CLS..
519
CSS style_code$.
519
COMMAND cmd$.
519
COUNTER.RESET cnt 519
COUNTER.SETUP cnt, pin [,mode]
519
CSSEXTERNAL file$.
520
DATA const1 [,const2] ... 520
DHT.SETUP pin, model 521
EMAIL.SETUP server$, port, user_name$,
password$ [, debug] 521
EMAILASYNC from$, to$, subject$,
message$.
521
FILE.FROMBASE64 source$,
dest$.
521
FILE.SAVE filename$, content$.
521
FILE.TOBASE64 source$, dest$.
521
FUSION.INIT.
521
FUSION.MADGWICK ax, ay, az, gx, gy,
gz.
522
FUSION.MADGWICK ax, ay, az, gx, gy, gz,
mx, my, mz.
522
FUSION.MAHONY ax, ay, az, gx, gy, gz, mx,
my, mz.
523
FUSION.BETA =.
523
FUSION.ZETA =.
523
FUSION.KI =.
523
FUSION.KP =.
523
HTML code$.
523
I2C.SETUP sda_pin, scl_pin [,freq ]
523
I2C.BEGIN address.
523
I2C.END..
524
I2C.REQFROM address, length.
524
I2C.READREGARRAY i2c_address, register,
nb_of_bytes, Array() 524
I2C.WRITE value.
524
I2C.WRITEREGBYTE i2c_address,register,
value.
525
I2C.WRITEREGARRAY i2c_address, register,
nb_of_bytes, Array() 525
INCR var [, increment] 525
INPUT.TIMEOUT timeout 525
INPUT["prompt$";] variable.
525
INTERRUPT pin_no, {OFF | label} [, mode]
526
IR.INIT pin_rx | OFF [, pin_tx]
526
IR.SEND type, code$, bits.
526
JSCALL javaCode$.
526
JSCRIPT script$.
526
JSEXTERNAL file$.
526
LCD.INIT address, cols, rows.
527
LCD.CLS..
527
LCD.PRINT x, y, text$.
527
LOCAL var1 [,var2], ... 527
MAXDISPLAY.SETUP CS_pin.
527
MAXDISPLAY.PRINT msg$ [,‘brightness]
527
MAXSCROLL.SETUP nb_devices,
CS_pin.
527
MAXSCROLL.PRINT msg$.
527
MAXSCROLL.NEXT msg$.
528
MAXSCROLL.TEXT msg$.
528
MAXSCROLL.SHOW pos [, brightness]
528
MAXSCROLL.SCROLL [brightness]
528
MAXSCROLL.OSCILLATE [brightness]
528
NEO.PIXEL led_pos, R, G, B [, disable]
528
NEO.PIXEL led_pos, COLOR [, disable]
528
NEO.SETUP pin [,nb_led] 528
NEO.STRIP led_start_pos, led_end_pos, R,
G, B [, disable] 528
NEO.STRIP led_start_pos, led_end_pos,
COLOR [, disable] 529
NEOSCROLL.SETUP nb_devices, pin
[,serpentine] 529
NEOSCROLL.PRINT msg$.
529
NEOSCROLL.NEXT msg$.
529
NEOSCROLL.COLORS col$.
529
NEOSCROLL. NEXTCOLORS col$.
529
NEOSCROLL.SHOW pos [, brightness]
529
NEOSCROLL.TEXT msg$.
529
NEOSCROLL.SCROLL [‘brightness]
529
NEOSCROLL.OSCILLATE [‘brightness]
529
OLED.CLS..
530
OLED.INIT orientation [,model]
530
OLED.REFRESH fmt 530
OLED.COLOR color 530
OLED.PIXEL x, y.
530
OLED.LINE x1, y1, x2, y2.
530
OLED.RECT x,y, width, height [,fill]
530
OLED.CIRCLE x, y, radius [, fill]
530
OLED.FONT font_num..
531
OLED.PRINT x, y, text$ [background]
531
OLED.IMAGE x, y, image$.
531
OLED.BMP x, y, image$.
531
ONERROR ABORT or ONERROR IGNORE or
ONERROR SKIP [nn] or ONERROR CLEAR or ONERROR GOTO label
531
ONESPNOWERROR [label | OFF] 531
ONESPNOWMSG [label | OFF] 531
ONGESTURE [label | OFF] 531
ONHTMLCHANGE [label | OFF] 532
ONHTMLRELOAD [label | OFF] 532
ONINFRARED label 532
ONMQTT label 532
ONRFID label 532
ONSERIAL [label | OFF] 532
ONSERIAL2 [label | OFF] 532
ONTOUCH [label | OFF] 532
ONUDP [label | OFF] 532
ONURLMESSAGE [label | OFF] 532
ONWGETASYNC [label | OFF] 532
OPTION.CPUFREQ 80|160|240.
532
OPTION.LOWRAM value.
533
PAUSE delay.
533
PCA9685.SETUP addr 533
PCA9685.SETFREQ freq.
533
PCA9685.PWM pin, value.
533
PID1.INIT Kp, Ki, Kd.
533
PID1.LIMITS min, max.
533
PID1.PERIOD msec.
533
PID1.PARAMS Kp, Ki, Kd.
533
PID1.SETMODE mode.
533
PIN(pin_number) = val 533
PIN.DAC pin_number, value.
534
PIN.MODE pin_number, mode [,PULLUP |
PULLDOWN ] 534
PLAY.MP3 mp3$.
534
PLAY.STREAM stream$ [,buffer]
534
PLAY.SETUP dest [,buffer] [,mono]
534
PLAY.SPEAK message$ [, phonetic]
535
PLAY.STOP..
535
PLAY.VOICE "message", "language" [,
"filename"] [, action] 535
PLAY.VOLUME volume.
535
PLAY.WAV..
535
PRINT expression[[,; ]expression] ...
535
PRINT2 expression [[,; ]expression] ...
535
PWM.SETUP pin, chan, default,
[,freq] [,resol] 536
PWM.SETUP pin, OFF.
536
PWM.OUT chan, value.
536
READ var1 [,var2] ... 536
REBOOT.
536
REFRESH..
536
RESTORE [label] 536
RTC.SETTIME Year, Month, Day, Hours,
Minutes, Seconds.
536
SERIAL.BYTE ch1 [,ch2] . . . 536
SERIAL2.BYTE ch1 [,ch2] . . .
537
SERIAL.MODE baudrate [, bits, parity,
stop] 537
SERIAL2.MODE baudrate, pin_tx, pin
rx [, bits, parity, stop] [, TXbuffer, RXbuffer] 537
SETTIME Year, Month, Day, Hours, Minutes,
Seconds.
537
SLEEP value [,pin, level] 537
SOCKET client, msg$.
537
SPI.CSPIN pin [, polarity] 537
SPI.SETUP speed [,data_mode [,
bit_order]] 538
SPI.STOP..
538
ST7920.INIT CS_pin.
538
ST7920.CLS..
538
ST7920.REFRESH fmt 538
ST7920.COLOR color 538
ST7920.PIXEL x, y.
538
ST7920.LINE x1, y1, x2, y2.
538
ST7920.RECT x,y, width, height [,fill]
538
ST7920.CIRCLE x, y, radius [, fill]
538
ST7920.FONT font_num..
539
ST7920.PRINT x, y, text$ [background]
539
ST7920.IMAGE x, y, image$.
539
ST7920.BMP x, y, image$.
539
TM1637.PRINT msg$ [, brightness ]
539
TM1637.SETUP data_pin, clock_pin [,
bit_delay] [, display_type] 539
TM1638.PRINT msg$ [, brightness ]]
539
TM1638.SETUP data_pin, clock_pin,
strobe_pin.
539
TM1638.LEDS val 539
TFT.BMP filename$, [x, y [, back_color] ]
540
TFT.BRIGHTNESS val 540
TFT.CIRCLE x, y, radius,color [, fill]
540
TFT.FILL color 540
TFT.IMAGE filename$, [x, y [, back_color]
] 540
TFT.INIT orientation.
541
TFT.JPG filename$, [x, y [, scale] ]
541
TFT.LINE x1, y1, x2, y2, col 541
TFT.PIXEL x, y, col 541
TFT.PRINT expression [[,; ]expression]
... 542
TFT.RECT x, y, width, height, color [
[,fill] ,[round_radius] ] 542
TFT.SETFREQ freq.
542
TFT.TEXT.COLOR color [,backcolor]
542
TFT.TEXT.POS x, y.
542
TFT.TEXT.SIZE size.
542
TIMER0 interval, label 542
TIMER1 interval, label 542
TOUCH.CALIB..
543
UDP.BEGIN port 543
UDP.REPLY msg$ [,port] 543
UDP.STOP..
543
UDP.WRITE ip, port, msg$.
543
URLMSGRETURN msg$ [,content_type$]
543
WAIT.
543
WGETASYNC server$, port [,header]
543
WGETASYNC url$, port [,header]
544
WIFI.APMODE SSID$, password$ [, channel]
[, IP$ , MASK$] 544
WIFI.AWAKE..
544
WIFI.CONNECT SSID$, password$ [, BSSID$]
[, IP$ , MASK$ [, GATEWAY$]] 544
WIFI.POWER pow..
544
WIFI.SCAN..
544
WIFI.SLEEP..
544
WLOG [text$ | num] 545
WORD.DELPARAM setting$, parameter$,
[,separator$] 545
WORD.SETPARAM setting$, parameter$,
value$ [,separator$] 546
BASIC KEYWORDS..
546
CASE..
547
DIM array(size) [, …] 547
DO..
547
ELSE..
547
ELSEIF.
547
END [IF | SELECT | SUB] 547
ENDIF.
547
EXIT {DO | FOR | SUB} 547
FOR..
547
GOSUB [label | lab$] 547
GOTO [label | lab$] 547
IF.
547
LET var = expression.
547
LOOP..
547
NEXT.
547
OFF.
548
OUTPUT.
548
PULLUP..
548
PULLDOWN..
548
REM..
548
RETURN..
548
SELECT.
548
SPECIAL.
548
STEP..
548
SUB..
548
THEN..
548
TO..
548
UNTIL.
548
WEND..
548
WHILE..
548
Annex32 WI-Fi RDS (Rapid Development Suite) is
a version of the "BASIC" language developed to run on low cost
ESP-32 WIFI devices. Annex32 is specifically for the ESP32 range of
devices, whose implemented features can vary greatly.
To offer some standardisation, Annex32 caters
in particular to M5stack devices, which include a micro-SD card
slot, TFT display, speaker, 3 user buttons plus a reset button, and
a lipo battery, all self-contained in a plastic case offering
expansion pin access and designed to accept ‘stackable’ expansion
modules.
All drivers needed for the M5stack features
are already included in the Annex32 firmware, and pre-configured
for the M5stack so that features such as TFT display and SDcard
work by default.
Similar functionality could be built using
alternative TFT display and SD card reader etc, if preferred.
Please refer to the original
M5Stack schematics for more details.
However, M5stack and its hardware features
merely offer a convenient standardised feature set, they are not
mandatory - Annex32 works with any ESP32 devices, with or without
hardware expansion modules.
Obviously appropriate hardware is needed for
any required features - eg: an OLED display could be used, but
scripts written for TFT displays will need modifying for the
different display.
Annex32 can use the internal flash disk space,
or an external SD card.
The internal and the external (SDcard) space
are mutually exclusive and cannot be accessed at the same time.
By default Annex32 will use the SD, if
available, otherwise it will use the internal flash disk space
(FATFS).
Both use the same type file system (FAT32),
enabling the use of long file names and directories.
Depending on the module flash memory size (4,
8 or 16MB), the internal disk space can be from ~1MB to 13MB.
Using the ESP32 partition scheme it is
possible to freely define this space, but modifying it will wipe
out all existing files already stored.
Annex32 Wi-Fi RDS takes from the original
concept of Annex WI-FI RDS for ESP8266 from which it shares
essentially the IDE interface and the same command syntax as much
as possible.
It should be straightforward switching to
Annex32 if coming from Annex, and the same programs should run
without (or with minimum) modifications (eg: pin numbers).
Annex32 Wi-Fi RDS benefits from the powerful
H/W architecture of the ESP32 using both cores and the RAM memory
available. In addition, for modules equipped with PSRAM memory
extension, Annex32 can make available to the users this additional
RAM space (up to 4MBytes).
Functionalities:
-
Includes an internal IDE so can be programmed directly using your
web browser (even from your phone/tablet) without any additional
utility.
-
Syntax highlighting with context-sensitive Help
-
A programmable web server which includes a file server
-
Supports OTA (over the air) update.
-
Support async events (interrupts, timers, web access, UDP, ….)
-
Breakpoints, immediate execution of commands, display of variables,
single step.
-
A basic interpreter with floating point variables (double
precision) and string variables, multi-dimensional arrays (float
and string), user defined subroutines.
-
Access to any available I/O pin for input/output, PWM and
Servo.
-
Errors Handling .
-
Support TCP (HTTP) GET and POST for communications
-
Support for UDP for communications.
-
Support for sending Emails using SMTP SSL servers
-
Support for AJAX communications (GET, POST, PUT) Synchronous and
Asynchronous
-
Support for ESP-NOW communications
-
Support for MQTT communications
-
Support for MODBUS communications
-
Support for FTP communications
-
Support for Bluetooth Low Energy (BLE) communications
-
Support for Telegram communications
-
Support for RJ45 wired ethernet using W5500 module
-
Accompanying utility suite includes Flasher, File Manager, HTML
Converter, Backup/Restore to bin or zip, integrated Serial Port
Monitor, OTA (over the air) update server and UDP Console.
-
IMU / AHRS Fusion algorithms 6 DOF and 9 DOF (Madgwick and
Mahony)
-
Play MP3 or WAV sound files or streaming using a speaker or an
external I2S DAC
-
Text to Speech using a speaker or an external I2S DAC
-
Support for regular expressions (regex)
The following
devices are supported directly with dedicated commands / functions
:
-
DHT11, DHT21 or DHT22 Temperature / Humidity Sensors
-
DS18B20 Temperature sensor
-
LCD HD44780 with I2C interface module (1, 2 or 4 lines with 16 or
20 chars per line)
-
LCD Display based on chipset ST7920 with 128x64 pixels
monochrome
-
OLED Display based on chipset SSD1306 or SH1106 with 128x64 pixels
monochrome
-
TFT Display at 16 bits colors based on the following chipset:
-
ILI9341 with 320x240 pixels
-
ILI9163 with several resolutions
-
ST7735 with several resolutions
-
ST7796 with 480x320 pixels
-
ILI9481 with 480x320 pixels
-
ILI9486 with 480x320 pixels
-
ILI9488 with 480x320 pixels
-
ILI7789 with several resolutions
-
SSD1351 with 128x128 pixels
-
GC9A01 with 240x240 pixels
-
TM1637 4 and 6 digits 7-segments display
-
TM1638 8 digits 7-segments display including 8 leds and 8
buttons
-
MAX7219 8 digits 7-segments display
-
MAX7219 8x8 dot matrix display modules
-
Neopixel WS2812 led strips
-
Neopixel WS2812 8x8 dot matrix display
-
PCA9685 PWM/SERVO module
-
Infrared interface with many RC protocols (transmission and
reception)
-
RTC module (DS1307 or DS3231)
-
HC-SR04 ultrasonic sensor for distance measurement
-
BNO055 Absolute Orientation Sensor
-
MPU9250 / MPU6500 IMU units
-
MPU6886 IMU unit
-
BME280 Combined humidity and pressure sensor
-
BME680 Combined gas, pressure, temperature & humidity sensor /
Air Quality Sensor
-
HDC1080 High Accuracy Digital Humidity Sensor with Temperature
Sensor
-
CCS811 Air Quality Sensor
-
APDS9960 Digital Proximity, Ambient Light, RGB and Gesture
Sensor
-
W5500 RJ45 wired Ethernet interface
-
VL53L0X TOF (Time Of Flight) Distance Sensor
-
RFID MFRC522 cards reader
-
HX711 - Weight Measurement Module
-
SI5351 Clock Generator Module
-
Any compatible I2S DAC
-
Lora SX127x modules
-
STEP Motors
-
VGA output for ESP32–S3
-
RGB TFT output for ESP32-S3
Many ESP32 modules
/ units are supported and can be configured using the
“CONFIG” menu:
-
Almost all the ESP32 modules including ESP32 devkit, ESP32 wemos
mini, ESP32 lolin lite, ...
-
M5Stack
-
M5 Atom
-
M5 Atom matrix
-
M5 Atom Echo
-
ESP32-CAM
-
M5CAMERA
-
ODROID GO
-
M5Tough
-
WIFI LORA 32
-
ESP32-2432S028 (module with a 240x320 2.8” TFT with resistive
touchscreen)
-
ESP32-3248S035R (module with 320x480 3.5” TFT with resistive
touchscreen)
-
ESP32-3248S035C (module with 320x480 3.5” TFT with capacitive
touchscreen)
In addition to
the ESP32, Annex now extends its support to other family members,
including the ESP32-C3, ESP32-S2, and ESP32-S3. This support
encompasses both direct USB connection and variants with USB to
serial chip. For all of these modules, Annex offers compatibility
across different versions, considering the specific type of flash
memory installed, including DIO, QIO, and OPI, as well as the
presence of PSRAM, with* options for QIO and OPI configurations. As
a result of this diverse range of variants, Annex provides distinct
firmware releases tailored to each particular configuration. This
ensures optimal performance and seamless integration across the
ESP32 series.
The following
modules equipped with ESP32-S3 are also supported and can be
configured using the “CONFIG” menu:
-
ESP32-4848S040 (module with a 480x480 4” RGB TFT with capacitive
touchscreen)
-
ESP32-8048S070C (module with a 800x480 7” RGB TFT with
capacitive touchscreen)
-
ESP32-8048S043C (module with a 800x480 4.3” RGB TFT with
capacitive touchscreen)
-
Waveshare ESP32-S3-TOUCH-LCD-4.3 (module with a 800x480 4.3” RGB
TFT with capacitive touchscreen)
-
Waveshare ESP32-S3-TOUCH-LCD-7 (module with a 800x480 7” RGB TFT
with capacitive touchscreen)
-
ESP32-S3-GEEK (USB plug-in module with a 1.41 “ 240 x 135 IPS
LCD screen & 16Mb PSRAM)
The basic interpreter works by reading a
script file saved to the esp local disk filing system.
This is the default mode if no external
SDcard(s) are connected to the ESP32. In addition, Annex32 can use
an external SD card as file system permitting up to 16Gbytes or
32Gbytes of disk space.
During the startup, if an external SDcard is
detected it will be automatically connected and used as the default
file system, in which case the internal filing system will not be
used.
Because the ESP32 contains a good quantity of
RAM, the user script is copied from the disk into a dedicated
area in the RAM memory where it is executed, together with the list
of the program lines, the branch labels and the list of the user
defined subroutines.
This uses more RAM compared to other
approaches, but allows faster program execution.
Another performance consideration is that the
ESP32 must be capable of executing several activities in the
background (web server, file server, etc..) so needs sufficient
free memory for running such tasks, and those parallel tasks will
obviously have an impact on script performance.
So performance-wise, the interpreter is not
particularly fast, but it should be fast enough for most tasks you
may require. In particular it is around 2 times faster than Annex
for ESP8266, considering that many tasks can run in parallel
without any appreciable performance impact (such as playing music
in the background).
Basic program lines :
A typical script line should comply with the
following syntax :
[label:]
command [argument1 [,argument2 …..]]
Script lines may contain several commands on
the same line if separated by the colon character ":".
[label:]
command1 [argument1 [,argument2 …..]]: command2 [argument1
[,argument2 …..]]
It must be noted that use of several commands on the same line is
not recommended and will cause program errors if the line contains
GOSUB or user defined subroutine calls.
All program jumps (eg: GOTO, GOSUB) are
referenced by their branch label names - line numbers are not
referenced in scripts, they are merely available in the editor as a
programming convenience if wished, and for error references.
NOTE : The gosub and the call to user
defined subroutines must be used alone on the script line.
Branch labels should not be named the same as
a command name, and must follow the same format as variables (see
below).
A branch label definition must begin the line,
and a colon (":") must terminate the label definition.
Any references to the defined label (GOTOs and
GOSUBs etc) do not use a colon.
Example :
b
= 10
a
= 20 : c = 30
GOSUB LABEL1
END
LABEL1:
print "Label1"
RETURN
|
The interpreter has 2 types of variables:
-
Floating Point (double precision)
-
String
Floating point variables can store numbers
with decimal points; they can also store integer numbers with a
precision equivalent to 32bits.
Strings contain sequences of characters
(example "my program") and must be terminated by "$".
The strings are not limited in size, they are
only limited by the amount of memory available.
NOTE: The string variables cannot contain
the character with ASCII code 0 (zero) because it is used
internally as an end of string delimiter.
The variables are defined as any name starting
with an alpha character (a, b, ..z) followed by any alphanumeric
character (a..z, 0..9); it can also include the "_"
(underscore).
The case is don’t care, so ‘’Num"
is equivalent to "nuM".
The variable name length is limited to 31
characters maximum, including the "$" for the strings.
There are no limits in terms of number of
variables; the only limit is the RAM memory available.
Example:
NUM = 10.56
myString$ = "this is My
String"
this_is_my_value$
= "ESP8266"
number = 8826621
|
Numeric variables and string variables are
managed separately so the same name can be used; this means that
A and A$ are different variables that can coexist at
the same time (even if this could lead to confusion).
Constants:
The numeric constants can have the following
format :
A =
5 : Z = 1.5
B =
1.23456E5 -> same as 123456
C =
1.23456E+5 -> same as 123456
D =
1.23456E-3 -> same as 0.00123456
The string constants are simply defined as a
text between quotes:
A$
= "This
is my string" : B$ =
"another string"
The strings can include the character "
(quote) simply typing it two times :
A$
= "this
is ""MY"" string"
The | (vertical bar) can also be used
as a string literal.
This permit to include the " (quote) easily
inside a string constant :
A$
= |this
is a "string" constant|
The hexadecimal constants can be defined
simply prefixing it with &h :
E
= &hABCD -> equivalent of decimal
43981 (hexadecimal constant)
F
= &hA0 -> equivalent of decimal
160
The binary constants can be defined simply
prefixing it with &b :
E
= &b00000101 -> equivalent of decimal
5 (binary constant)
F
= &b10000001 -> equivalent of
decimal 129
The octal constants can be defined simply
prefixing it with &o :
E
= &o377 -> equivalent of decimal 255
(octal constant)
F
= &o17 -> equivalent of decimal
15
Arrays are defined using the DIM
command.
Their names follow the same rules as the
regular variables and are followed by parenthesis (brackets)
containing the index. The subscript starts from 0, but you can
adjust the lower limit using
The scope of the Arrays is always global (see
next paragraph).
Example:
DIM
A(100)
define a floating point array with 101 elements (index
from 0 to 100)
DIM
ABC$(50)
define a string array with 51 elements
(index from 0 to 50)
A(15) = 1234.5678
ABC$(49) = "Hi friend!"
The arrays can have up to 5 subscripts
(dimensions), examples:
DIM
A(50,50) -> create a floating point array with
51*51 elements (2601)
DIM
J$(4, 4, 4) -> create a string array with 5 * 5
* 5 elements (125)
If the command
OPTION.BASE 1
is executed the subscripts start from 1 and an error will be raised
when trying to use the index 0.
This line
OPTION.BASE 1
must be present in the code before array declaration.
In this case
DIM
A(100)
define a floating point array with 100 elements (index
from 1 to 100)
DIM
ABC$(50)
define a string array with 50 elements
(index from 1 to 50)
Notice that declaring a multi-dimensional
array with multiple subscripts uses elements for every possible
combination of subscripts, whereas in practice it may be preferable
to declare multiple arrays with the same subscript, eg:
users=4
DIM Name$(users)
DIM Address$(users)
DIM Tel$(users)
Which only uses 5 + 5 + 5 elements
(15)
NOTE:
The numerical Arrays are always
initialised at 0 with the command DIM.
The string Arrays are always initialised
as null string with the command DIM.
There are no limits to the number of
arrays or their size, the only restriction is the RAM memory
available.
The arrays can be re-dimensioned using the
same command DIM.
In this case all the existing elements will
maintain the previous value except the new elements that will be
initialised at 0 or null string.
Example :
DIM A(5)
' all the elements are initialised at
0
A(0)
= 123
Print A(0)
' print 123
Dim A(10)
Print A(0)
' print the same value
123
Print A(10)
' print 0
|
In addition the elements of the arrays can be
initialised with a given value during the command DIM.
Example :
DIM
A(5) = 0, 1, 2,
3, 4, 5 ' set A(0)= 0,
A(1)= 1, A(2)=2, ….
If the command
OPTION.BASE 1
is executed before
DIM
A(5) = 0, 1, 2,
3, 4, 5 ' set A(1)= 0,
A(2)= 1, A(3)=2, ….
The same can be done with string arrays.
Example :
DIM
A$(5) =
"zero", "one", "two", "three", "four", "five"
Two additional functions can be used to determine the bound limits
of arrays:
LBOUND(array()
[, dimension]) : Returns the lower bound of the
specified array dimension.
UBOUND(array()
[, dimension]) : Returns the upper bound of the
specified array dimension.
Example :
OPTION.BASE 0
DIM A(100)
print
LBOUND(a()) ' print 0
(option.base 0)
print
UBOUND(a()) ' print
100
OPTION.BASE 1
DIM A(10,
20)
print
LBOUND(a(), 1)
' print 1 (option.base
1)
print
LBOUND(a(), 1)
' print 1 (option.base
1)
print
UBOUND(a(), 1)
' print 10
print
UBOUND(a(), 2)
' print 20
|
Variables and arrays defined in the main code
are global, therefore any variable is accessible from any part of
the code after it has been previously defined there.
Variables and arrays defined inside
“user defined” subroutine (SUB) are visible only inside that sub
and inside all the code called by that subroutine; their content
(and their memory space) is removed at the end of the SUB
The LOCAL command permits defining local
variables inside of "user defined" subroutines; this permits to use
the same name of an “already existing” variable locally without
modifying the original.
As for all the variables defined inside SUB,
they will disappear at the end of the subroutine.
Example:
A
= 10
B
= 20
C
= 30
mysub
"Hello"
PRINT A,B,
C
END
SUB mysub(a$)
LOCAL A,B
A
= 123
B
= 456
C
= 789
D
= 8888
PRINT A$, D
END
SUB
|
In this example, calling the user-defined
subroutine "mysub" will not modify the content of the global
variables A and B (defined locally) but will modify the content of
the variable C (not defined locally) and the variable D will
disappear at the end of the SUB.
The keywords recognized by the interpreter can
be defined into 3 classes:
●
Operators
●
Commands
●
Functions
The Operators are symbols that tell the
compiler to perform specific mathematical or logical
manipulations.
Commands and Functions both execute an action,
but functions also return a data value.
For example
PRINTis a command and
SIN()
is a function whereas the ‘+’ in a = b
+ 5 is an operator.
The string functions are always followed by
the "$" symbol if they return a string value.
In addition to commands and functions there
are all the internal interpreter internal commands that are part of
the language itself.
The following operators are available. These
are listed in the following tables by order of precedence.
Operators on the same line are processed with a left to right
precedence.
Arithmetic operators:
^
|
Power
|
* / \ MOD
|
Multiplication,
division, integer division and modulo (remainder of the
division)
|
+ -
|
Addition and
subtraction
|
Shift operators:
x <<
y
x >> y
|
These operate in a
special way. << means that the value returned will be the
value of x shifted by y bits to the left while >> means the
same only right shifted. They are integer functions and any bits
shifted off are discarded and any bits introduced are set to
zero.
For more
information about the kinds of bitwise shifts, see Bitwise shifts.
|
Logical operators:
<> <
> <=
>=
=
|
Not Equal, less
than, greater than, less than or equal to,
greater than or
equal to, equal
|
AND OR NOT XOR
|
Conjunction,
disjunction, negation, Exclusive OR
|
String operators:
<> <
> <=
>=
=
|
Not Equal, less
than, greater than, less than or equal to,
greater than or
equal to, equal
|
+ &
|
Add strings
together
|
Bitwise operators:
AND OR XOR NOT
|
Binary AND, binary
OR, binary exclusive OR, binary negation
For more
information about the bitwise operators, see
Bitwise Operators
|
The operators AND, OR and XOR are integer
bitwise operators. For example PRINT (3 AND 6) will output 2.
Expressions beginning with open parenthesis
‘(‘ are always considered numerical but the parser is able to
determine if an expression is true or false even if the expression
represents a string.
Each expression representing a comparison,
returns a numerical value of 1 if the expression is true or 0 if
false. For example 10 =
10 represents a value of 1 whereas 10 = 5 represents a value of
0.
The same logic is applied for string
expressions where "abc" =
"abc" represents a value of 1 and "abc" = "def" represents a
value of 0.
This is very useful in the IF command and also
in other expressions.
For example the following code :
A$ = "on"
If
A$ = "on"
then
pin(4)
= 1
Else
pin(4)
= 0
End
if
|
Can be replaced by
pin(4)
= (a$ =
"on")
The strings can also be compared to determine
the alphabetical order.
To see whether a string is greater than
another, Annex uses the so-called “ASCII” order.
In other words, strings are compared
letter-by-letter.
For example:
("Z"
> "A") is true
("Glow"
> "Glee") is true
("Bee"
> "Be") is true
("Bas"
> "Bat") is false
The algorithm to compare two strings is
simple:
Compare the first character of both strings.If
the first character from the first string is greater (or less) than
the other string, then the first string is greater (or less) than
the second. We’re done. Otherwise, if both strings’ first
characters are the same, compare the second characters the same
way. Repeat until the end of either string.
If both strings end at the same length, then
they are equal. Otherwise, the longer string is greater.
In the examples above, the comparison
"Z" > "A" gets
to a result at the first step while the strings"Glow" and "Glee" are compared
character-by-character:
-
G is the same as G.
-
l is the same as l.
-
o is greater than e. Stop here. The first string is greater.
The comparison algorithm given above is
roughly equivalent to the one used in dictionaries or phone books,
but it’s not exactly the same. For instance, case matters. A
capital letter "A" is not equal to the lowercase "a". Which one is
greater?
The lowercase "a". Why? Because the lowercase
character has a greater index in the ASCII table.
The IF can have the following syntax :
1) IF
expression THEN statement
2) IF
expression THEN statement1 ELSE statement 2
3) IF
expression THEN
Statements
ELSE
Statements
END IF
4) IF
expression THEN
Statements
ELSEIF expression THEN
Statements
ELSEIF ……..
………
ELSE
Statements
END IF
Example:
IF a
> 100 THEN print
"a"
IF b
<a THEN print
"b" ELSE print
"a"
IF c
> d THEN
print "C"
print "is greater"
ELSE
print "D"
print "is greater"
END
IF ' (can also be ENDIF
without space between END and IF)
IF d
= a THEN
print "d"
print "is like a"
ELSEIF d
= b
print "d"
print "is like b"
ELSEIF d
= c
print "d"
print "is like c"
ELSE
print "d"
print "is unknown"
END
IF ' (can also be ENDIF
without space between END and IF)
|
When the conditional is all on one line it
does not need terminating with an END IF
Example
IF
a=2
THEN
PRINT "ok"
ELSE PRINT "not
ok"
The AND ,
OR keywords can be used
between the expressions as long as they are in
parenthesis.
Example:
IF
(a=1)
AND (b=2)
THEN PRINT "ok"
Or
IF ((a=2)
AND (b=3)
AND (c =
3)) OR (d=4)
THEN PRINT "ok"
The IF can be nested
Example:
IF
a=2 THEN
IF b = 2
THEN
IF c = 3 THEN
PRINT "ok"
END IF
END IF
END
IF
|
The “THEN” keyword can eventually be
removed, even if this is not recommended.
Example:
IF
a > 100 print
"a" else print
"b"
The FOR loop can
have the following syntax :
FOR
variable=init_value to end_value [step
value]
Statements
NEXT
variable
The ‘step’ value can be positive or
negative
Example:
FOR
i=1 to
5
Print i
NEXT
i
Will print 1, 2, 3, 4, 5
FOR
i=1 to 3
step 0.5
Print i
NEXT
i
Will print 1, 1.5, 2, 2.5, 3
FOR
i=3 to 1
step -0.5
Print i
NEXT
i
Will print 3, 2.5, 2, 1.5, 1
The command
EXIT
FOR can be
used to exit from the loop at any time:
FOR
i=1 to
50
IF
i=10 THEN
EXIT FOR
Print i
NEXT
i
Print
"end of loop"
Optionally, the variable in the
NEXT statement
can be omitted.
This means that this program is valid :
FOR
i=1 to
5
Print i
NEXT
The WHILE
WEND loop can have the following
syntax :
WHILE
expression
Statements
WEND
The loop is iterated as long as the expression
is true
Example:
i
= 0
WHILE
i < 3
Print i
i = i +
1
WEND
Will print 0, 1, 2
The DOLOOP
can have one of the following 4 syntax :
DO
WHILE expression
Statements
LOOP
DO
UNTIL expression
Statements
LOOP
DO
Statements
LOOP
WHILE expression
DO
Statements
LOOP
UNTIL expression
The command
EXIT
DO can be used to exit from the
loop at any time
Example
i
= 0
DO
Print
i
i = i
+ 0.5
LOOP
UNTIL i >3
Will print 0, 0.5, 1, 1.5, 2, 2.5, 3
i
= 0
DO
Print
i
i = i
+ 0.5
IF
i > 2 THEN
EXIT DO
LOOP
UNTIL i >3
Will print 0, 0.5,
1, 1.5, 2
The SELECTcan
have the following syntax:
SELECT
CASE expression
CASE exp1 [: Statements]
Statements
CASE exp2 TO exp3 [: Statements]
Statements
CASE exp4 [,exp5],
... [: Statements]
Statements
CASE ELSE
Statements
END
SELECT
Example:
a =
4
SELECT
CASE a
CASE 1
PRINT "case
1"
CASE 2 :
PRINT "case 2"
CASE 3 :
PRINT "case 3" : PRINT "can continue
on same line"
CASE 4 :
PRINT "case 4"
PRINT "can continue
also on next line"
CASE ELSE:
PRINT "case
else"
END
SELECT
Multiple cases:
a =
4
SELECT
CASE a
CASE1 :
PRINT "case 1"
CASE 2, 3, 5
: PRINT "case 2 or 3 or 5"
CASE4 :
PRINT "case 4"
CASE 6 TO
8 : PRINT "case 6 to 8"
CASE 9 TO 20
: PRINT "case 9 to 20"
CASE ELSE:
PRINT "case
else"
END
SELECT
The SELECT CASE can
also handle string content:
SELECT
CASE a$
CASE "a"
:
PRINT "case
a"
CASE "a",
"b", "c",
"d" :
PRINT "case a, b,
c, or d"
CASE "e"
TO "h" :
PRINT "case e to
h"
CASE ELSE:
PRINT "case
else"
END
SELECT
The GOTOcan have
the following syntax :
GOTO
[LABEL | LAB$]
Example
a =
5
IF a
> 5 THEN GOTO
LABEL1
END
....
LABEL1:
PRINT
"This is label1"
....
The goto must be
considered as an obsolete command and is provided just for backward
compatibility with old style Basic programs.
The GOSUBcan have
the following syntax :
GOSUB
[LABEL | LAB$]
The called function
must terminate with the command RETURN
Example
a =
5
IF a
> 5 THEN GOSUB LABEL1
END
....
LABEL1:
PRINT
"This is label1"
RETURN
The command DATA is used to store constant
information in the program code, and is associated with the command
READ. Each
DATA-line can contain one or more constants separated by commas.
Expressions containing variables will be also evaluated here. The
goal of the DATA is to avoid repetitive variable assignation lines,
in particular for arrays.
The DATA values will be read from left to right, beginning with the
first line containing a DATA statement. Each time a READ
instruction is executed the saved DATA position of the last READ is
advanced to the next value. Strings must be written in quotes like
string constants. The command
RESTORE resets the pointer of the current DATA
position, so the next READ will read from the first DATA found from
the beginning of the program.
In case READ uses the wrong variable type the error message
"Type mismatch" appears while referring to the line number
containing the READ statement that triggered the condition.
DATA lines may be scattered throughout the
whole program code, but for the sake of clarity they would be
better kept together at the beginning of the program.
The DATA can have
the following syntax
: DATA
const1 [,const2] …..
The constants can
be Numerical or String.
Example :
DATA 1, 55.88,
"constant", 99
READ A, B, C$,
D
PRINT A, B, C$,
D
Example without
DATA:
dim colors$(5)
colors$(1)
= "Red"
colors$(2)
= "Green"
colors$(3)
= "Blue"
colors$(4)
= "Yellow"
colors$(5)
= "Magenta"
Same example but
using DATA:
DATA
"Red", "Green",
"Blue", "Yellow", "Magenta"
dim colors$(5)
For i=1
to 5
Read colors$(i)
Next i
The command
RESTORE can optionally define a label to set the DATA
pointer to a specific point
Example
data 0, 1, 2,
3, 4, 5
block2:
data 10, 11,
12, 13, 14, 15
block3:
data 20, 21,
22, 23, 24, 25
block4:
data 30, 31,
32, 33, 34, 35
restore block3
for z
= 0 to 5
read a
print a,
next z
restore block2
print
" "
for z
= 0 to 5
read a
print a,
next z
print
"----------"
Define the end of
the program. With this command the program stops.
It can also be
:
END IF -> close the IF command
END SELECT -> closes the SELECT CASE command
END SUB -> closes the user defined SUB
Permit to exit from
a loop or a user defined SUB.
The syntax is :
EXIT
DO -> exit from a DO loop
EXIT
FOR
-> exit from a FOR loop
EXIT
SUB
-> exit from a user defined SUB.
Define a
user-defined subroutine, which the script can use like a command or
function.
User-defined
subroutines are effectively additional commands, so cannot be used
as branch labels.
Permit to create a
user defined command with optional parameters.
The syntax is SUB
subname[(arg1 [,arg2] …)]
The variables are
passed by reference; this means that the arguments, if modified
inside the subroutine, will modify the original variable. This can
be useful to return values from the subroutine (acting like a
function).
It is possible to
pass arrays using the syntax array_name().
Using the
LOCAL command will permit to define local variables (useful
to avoid to modify existing global variables).
Example 1 :
routine cube
SUB
cube(x)
PRINT X ^3
END
SUB
cube 3 ' will print 27
|
Example 2:
routine cube with returning argument
SUB
cube(x,y)
y = x ^3 ' the value is returned using the 2nd
argument
END
SUB
ret
= 0
cube 5,
ret
PRINT
ret
' will print 125
|
Example 3:
routine with local variables and returning argument
SUB left_trim(s$,
ret$)
LOCAL i
i
= 1
DO UNTIL i =
len(s$)
IF
mid$(s$, i, 1) <>
" " THEN EXIT
DO
i = i + 1
LOOP
ret$ = mid$(s$,
i)
END
SUB
z$
= ""
FOR i
= 1 to 3
left_trim " remove space from
left ", z$
PRINT z$ + "--"
NEXT i
|
Will print
remove space from
left --
remove space from
left --
remove space from
left --
As you can see in
this example, the variable i in the FOR loop is not modified by the
LOCAL variable i in the subroutine.
Example 4:
pass arrays
SUB pass_array(f(),
c$())
Dim myArray(10)
myArray(0)
= 456
Print f(0),
c$(0), myArray(0)
f(1) =
123
c$(1) =
"myText"
END
SUB
Dim alpha(10)
Dim beta$(10)
alpha(0)
= 456
beta$(0)
= "testme"
Pass_array
alpha(), beta$()
Print alpha(1),
beta$(1)
|
In this example,
the array alfa() is passed locally to the array f()
and the array beta$() is passed locally to the array
c$().
Modifying locally
these arrays change the value of the original one as their content
is passed by reference.
The array
“myArray” will disappear at the end of the SUB
As the numerical
variables are stored internally as double precision floating
numbers, it is possible to store numbers with a precision
equivalent to 32 bits.
Several boolean
operators are available to manipulate these numbers..
The first operator
is the bit shift; it can be shift left
<< or shift right >>
This operator
permits to shift the number of a specified number of positions to
left or right.
Example
A
= 1
Print A
<< 3 ' will print 8
A
= 16
Print A
>> 2 ' will print 4
The operators
AND
,
OR ,
XOR are also available :
A
= 24
A
= 15
Print A
AND B '
will print 8
A
= 24
A
= 15
Print A
OR B '
will print 31
A
= 24
A
= 15
Print A
XOR B '
will print 23
The unary operator
NOT
is also available. It inverts all the bits from 0 to 1:
A
= 0
Print
Hex$(NOT A)
' will print
FFFFFFFF
For a 32 bits
number, assuming 4 bytes ABCD where A is the MSB and D the LSB, the
bytes can be extracted as follows :
VAR
= &h12345678 ' this is a 32 bits variable
D = VAR
AND &hFF
C = (VAR
>> 8) AND
&hFF
B = (VAR
>> 16) AND
&hFF
A = (VAR
>> 24) AND
&hFF
For more
information, see
Bitwise
Operators
Annex allows to control and manage errors that
occur during the execution of the code.
This is managed with the command ONERROR.
This command defines what action is taken when
an error occurs, and applies to all errors, including syntax
errors.
It can be used in different ways, as specified
in the table below:
FUNCTIONS / COMMANDS
|
DESCRIPTION
|
|
Displays the error message then aborts the
program.
This is the normal behaviour and is the
default when a program starts running.
|
|
Any error will be simply ignored.
As this can make it very difficult to debug a
program it should be used wisely.
|
|
Ignore an error in the next command(s)
executed after the current command (the number of skipped commands
depends on whether the number ‘nn’ is specified).
'nn' is optional, the default is 1
if not specified.
After the number of skipped commands has
completed (with an error or not) the behaviour will revert to
ONERROR ABORT.
|
|
Reset the eventual pending error
|
ONERROR
GOTO [label
| OFF]
|
Jumps to the error handling routine defined by
the label.
It can be removed (hence reverting to ONERROR
ABORT) replacing the label with OFF.
Using RETURN inside the error handling routine
will continue the execution on the line following the error.
|
When an error occurs, the following constants
are available :
CONSTANT
|
DESCRIPTION
|
|
Returns the line
number where the error happened. Value of 0 means no error.
It is reset to 0
with the command ONERROR CLEAR or running the program or with
the command ONERROR IGNORE or ONERROR SKIP.
|
|
Returns a number
where non zero means that there was an error.
It is reset to 0
with the command ONERROR CLEAR or running the program or with
the command ONERROR IGNORE or ONERROR SKIP.
|
|
Return a string
representing the error message that would have normally been
displayed on the console. It is reset to “No Error” running the
program or with the command ONERROR CLEAR or ONERROR IGNORE or
ONERROR SKIP.
|
Example of error handling using the command
ONERROR GOTO :
ONERROR
GOTO
Error_Handler
Print
"start"
Print
3/0
' this generates a divide by zero
error
Print
space$(60000)
' this generates an out of memory
error
End
Error_Handler:
Print
"Error text
"; BAS.ErrMsg$
Print
"Error
num "; BAS.ErrNum
Print
"Error line
"; BAS.ErrLine
Return
' returns to
the line following the error
|
When a client
connects to the module using its IP address, the module will
redirect automatically to the url ‘/output?menu’, which sends an
empty html page present on the module.
That page contains
a bunch of javascript code permitting to interface the page with
the module using javascript.

This page will
automatically open a websocket connection with the module; the
"squared led" indicates if the connection was successful (green) or
not (red).
A mechanism of ping
- pong has been implemented into the javascript in order to hold
the connection alive all the time. If the connection is lost, the
page will try to reconnect automatically without any manual
action.
The button
"reconnect" permits to force the reconnection if the automatic
reconnection fails.
As soon as the
connection is done with the module, the html page is ready to send
and receive messages to / from the module.
Initially the page
is empty but its content can be easily filled.
To send HTML code
to the page, the command HTML is used.
The syntax is :
HTML HTML code.
For example the
line
HTML
"Hello, world <br>This is my first html
content<br>"
Will give this
result :

Continuing with the
HTML command, the content can be improved :
HTML
"Textbox: <input
type='text'><br>"

Continuing
again:
HTML
"Button: <button type='button'>Click
Here</button>"

All the html code
can be combined and sent with just one HTML command; this is much
faster:
a$ =
"Hello, world <br>This is my
first html content<br>"
a$ = a$
+ "Textbox: <input
type='text'><br>"
a$ = a$
+ "Button: <button type='button'>Click
Here</button>"
HTML
a$
|
To clear the content of the page, the command
is: CLS
Now we can try
another example
CLS
a$ =
"Now style me,
please<br>"
a$ = a$
+ "Button1: <button id='but1'
type='button'>ON</button> "
a$ = a$
+ "Button2: <button id='but2'
type='button'>OFF</button>"
HTML
a$

Now we will try to
style the buttons using css.
This can be done
using command CSS CSSID$()
For example the
line
CSS
CSSID$("but1",
"background-color:
red;")
Will give this
result :

Combining with the
style for the other button:
a$ = a$
+ cssid$("but1",
"background-color:
red;")
a$ = a$
+ cssid$("but2",
"background-color:
green;")
CSS
a$

A set of functions
is included to simplify the creation of HTML pages as we will see
later, so no need to worry if you are not familiar with writing
HTML code.
Now we will mention
an important ‘event’ that can be used to automatically fill the
content of the page each time a client connects to the module :
OnHtmlReload.
This ‘event’
defines a place where the program will jump to as soon as a
Websocket connection request is accepted.
Let’s clarify with
an example :
OnHtmlReload
Fill_Page
‘will jump to Fill_Page when the
page is reloaded
gosub
Fill_Page
'load the page for the first
time
Wait
‘pause waiting for the event
Fill_Page:
‘place where the page begins to
be created
CLS
a$ = "Now style me,
please<br>"
a$ = a$ +
"Button1: <button id='but1'
type='button'>ON</button> "
a$ = a$ +
"Button2: <button id='but2'
type='button'>OFF</button>"
HTML
a$
a$ = cssid$("but1",
"background-color:
red;")
a$ = a$ +
cssid$("but2",
"background-color:
green;")
HTML
a$
RETURN
|
The result will
be:

Now try to play
with the button "Reconnect"; you’ll see that, at each time the page
reconnects to the module, the HTML content is built and sent again.
This ensures that each time a client connects to the module it will
receive the correct content. At the same time, if other clients are
already connected, the content of all the pages will be refreshed
simultaneously. This ensures a synchronized content between all the
clients.
As said previously,
in order to simplify the creation of HTML pages there are several
functions available which can generate the html code
automatically.
Let’s start with
the button. A button is an object that is used to trigger an
action each time it is pressed on the web page.
The function is
BUTTON$.
Let’s explain with
an example:
CLS
HTML
BUTTON$("Button1", jump1)
Wait
'pause waiting for the
event
Jump1:
PRINT
"Clicked on Button1"
Return
|
The result will
be:

Try clicking on the
button then checking the result in the terminal console; the
message "Clicked on Button1" will be shown at each click.

To style the
button, we need to modify the syntax of the BUTTON$
command slightly; in fact we need to add another parameter to give
the button an ID:
CLS
HTML
BUTTON$("Button1", jump1, "but1") '
"but1" is the ID
Wait
'pause waiting for the
event
Jump1:
PRINT
"Clicked on Button1"
CSS
cssid$("but1",
"background-color:
red;") 'the same ID is used here
Return
|
Clicking on the
button now will change its color to red

Now we can now
introduce the LED object. The LED object is a circle that can be
filled in red or green depending on the content of a variable. The
function is LED$
As usual, let’s
start with an example:
CLS
led = 1 ‘this is the variable
associated with the LED. With 0 the led is red, with 1 the led is
green
HTML
LED$(led)
|
The result will
be:

Let’s also add a
button :
CLS
led
= 0
a$
= BUTTON$("Button1", jump1, "but1") '
"but1" is the ID
a$
= a$ + LED$(led)
HTML
a$
Wait
'pause waiting for the
event
Jump1:
PRINT
"Clicked on Button1"
led
= 1 -
led ' invert the
variable
REFRESH
' refresh (update) the variables between the code
and the html
Return
|
The result will
be:

Clicking on the
button will toggle the led between red and green colors.
The command
REFRESH
permits to update (synchronize) the variables in the code with the
corresponding objects variables on the web page. It should be run
each time a variable is modified.
As a simpler
alternative, the command AUTOREFRESH
will regularly sync the variables.
The command must be
run with the desired refresh timing.
Example
AutoRefresh
500 will refresh the variables each 500
milliseconds.
The interval
should not be less than 300 milliseconds (otherwise the module will
be too busy).
The example :
CLS
led = 0
a$ = BUTTON$("Button1", jump1, "but1") '
"but1" is the ID
a$ = a$ +
LED$(led)
HTML
a$
AutoRefresh
300
'sync each 300
milliseconds
Wait
'pause waiting for the
event
Jump1:
PRINT
"Clicked on Button1"
led = 1 - led
' invert the
variable
Return
|
The result will be
the same as the previous example.
Now it’s time to
introduce another object; the TEXTBOX with the corresponding
function TEXTBOX$.
The TEXTBOX will
display a ‘text box’ on the web page which is linked with a
variable. When the variable is modified in the code, the TEXTBOX
content will be updated on the web page, and vice-versa.
This lets us
introduce another ‘event’, the OnHtmlChange
command.
This ‘event’
defines a branch for the program to jump to whenever a variable is
modified inside the web page.
As usual, let’s
start with an example:
CLS
text$ = "Change me,
please"
HTML
TEXTBOX$(text$)
OnHtmlChange
Jump1
'will jump to Jump1 when a variable
changes on the web page
Wait
'pause waiting for the
event
Jump1:
Print
text$
'print the content of the variable
inside the terminal console
Return
|

Try now to change
the content of the textbox and press "Enter" on the keyboard.
Let’s see the
result in the terminal console:


With the concepts
already learned you’ll be able to use the other objects using the
similar logic.
Refer to the pages
below to understand the syntax of each object.
A timer is an "object" that permits the
execution of a particular action at regular intervals.
When the given time expires, the normal
execution of the program is interrupted while control is passed to
the "timer interrupt routine" until after the execution of the
return command.
Then the program continues from the point
where it was interrupted.
Let’s explain with an example :
timer0
1000,
mytimer
wait
mytimer:
wlog "mytimer " +
time$
return
|
Annex WI-Fi Basic
implements 2 timers, Timer0 and Timer1.
The Timer0 has a
higher priority against Timer1.
Many of the actions
are not executed directly by basic commands but can be executed as
asynchronous events. An "event" is simply an action that can
be executed when something happens. For example, pin change
interrupts are asynchronous events which can happen at any time
without user control.
In order to manage
the events, a list of commands "ONxxxx" is provided. These commands
define the place where the normal execution of the program will
branch to when the event occurs.
So, when the
"event" happens, the basic interpreter interrupts the normal
execution of the code and "jumps" to the location defined by the
corresponding command "ONxxx". As soon as the code associated with
the "event" is terminated with the command "return", the basic
interpreter continues from the previous interrupted location.
This is a special event that happens every
time aBUTTON$
object is clicked in the HTML pages.
When this happens,
a special variable
HtmlEventButton$ is created containing the name of the
button that was clicked.
This is useful to
determine the button within a group of buttons.
Let’s see an
example:
CLS
HTML
Button$("ON",
buttonEvent) +
" " + Button$("OFF",
buttonEvent)
wait
buttonEvent:
print
"You clicked
on ";
HtmlEventButton$
return
|
This event is triggered when an object present
in the HTML output page changes its value.
It is useful to make actions when something
changes in the HTML Pages.
When this event
happens, a special variable
HtmlEventVar$ is created containing the name of the
variable that changed its value.
This is useful to
determine the object that generated the event.
Let’s see an example :
CLS
text$ = "Change me,
please"
HTML
TEXTBOX$(text$)
OnHtmlChange
Jump1
'will jump to Jump1 when a variable
changes on the web page
Wait
'pause waiting for the
event
Jump1:
Print
text$
'print the content of the variable
inside the terminal console
Return
|
Note that the
special variable
HtmlEventVar$ is only created when the OnHtmlChange
event populates it due to a html object change, therefore it will
cause an error if tested for before an object is changed unless
specifically defined beforehand, eg: HtmlEventVar$ =
“”
This event is triggered when a Websocket
connection request is accepted.
This can be used to automatically fill the
content of the WEB page each time a client connects to the
module.
Let’s see an example :
CLS
OnHtmlReload
Fill_Page
'will jump to Fill_Page when the page
is reloaded
gosub
Fill_Page
'load the page for the first
time
Wait
'pause waiting for the
event
Fill_Page:
'place where the page begins to be
created
CLS
a$ = "Now style me,
please<br>"
a$ = a$ +
"Button1: <button id='but1'
type='button'>ON</button> "
a$ = a$ +
"Button2: <button id='but2'
type='button'>OFF</button>"
HTML
a$
a$ = cssid$("but1",
"background-color:
red;")
a$ = a$ +
cssid$("but2",
"background-color:
green;")
HTML
a$
Return
|
This event is
triggered when a code is received by the infrared receiver.
Refer to chapter
INFRARED INTERFACE for more details.
This event is
triggered when a message is received on the serial port.
Example:
print
"Ram Available "; ramfree
onserial rec1
wait
rec1:
'print serial.input$
print serial.chr$;
return
|
This event is
triggered when a message is received on the serial port #2.
Example
serial2.mode 9600, 2, 5
' set serial port #2 to 9600 pin 2 TX,
pin 5 RX
print2 "Ram Available "; ramfree
onserial2 rec2
wait
rec2:
print serial2.input$
return
|
This event is
triggered when the TFT screen is touched.
Refer to the
chapter TouchScreen for more details.
This event is
triggered when a UDP message is received.
Example:
udp.begin
5001
'set the UDP commmunication using port
5001
onudp
goudp
'Write several messages to the port
for i
=
0 to 100
udp.write
"192.168.1.44",
5001,
"Hello "
+
str$(i)
next i
wait
goudp:
v$
=
udp.read$
'receive the UDP data
print
v$
return
|
This event is
triggered when a WgetAsync message is received.
This is associated
with the command
WGETASYNC. The goal of the
WGETASYNC command is to start a html get request without
the module having to wait for the answer. Because the response is
async, this command specifies the location where the program should
branch to when a message is received.
Example:
ONWGETASYNC
answer_done
WGETASYNC("www.fakeresponse.com/api/?sleep=5",
80)
For
i =
0 to
10000
' a
kind of sleep just to demonstrate that the code continue to
run
Print i
Next
i
Wait
answer_done:
Print
WGETRESULT$
Return
|
This event is
triggered as soon as a web client requests for a web page with the
url composed with http://local_ip/msg?param=value.
This kind of request is typically called an AJAX request as it
permits to exchange in both directions between the client (the web
browser) and the server (the ESP module).
In fact, in the url
request, the client can send parameters in the form of couples of
"param=value" separated by the character "&". For example, if
the client wants to send 2 parameters, it can send the following
request :
http://local_ip/msg?param1=value1¶m2=value2.
As soon as this
message is received by the ESP module, the event OnUrlMessage is
triggered; this means that the program will continue from the
location defined by the command OnUrlMessage.
As soon as the
message is received, the parameters sent by the client can be got
with the function UrlMsgGet$ and a message can be sent back to the
client with the command UrlMsgReturn.
Let’s see an
example :
onUrlMessage
urlAjax
wait
urlAjax:
wlog
"message received " + UrlMsgGet$("a")
+ "
" + UrlMsgGet$("b")
UrlMsgReturn
"Message sent back " + time$
print
UrlMsgGet$("b"),
ramfree
return
|
Now using another
web browser window, let’s type the following url :
http://esp_local_ip/msg?a=10&b=20
As you can see in
the following picture, the message is received by the ESP
module

At the same time,
the client receives the message sent back from the ESP module

If the program is
stopped, the module will answer with the message "STOPPED"

Now, let’s see a more complete example :
cls
' this is the
default value for pwm out
R
= 512
G
= 512
B
= 512
'Setup the
pwm channels
PWM.SETUP
12, 1, R,
10000, 10
PWM.SETUP
15, 2, G,
10000, 10
PWM.SETUP
13, 3, B,
10000, 10
'Set the
default values
PWM.OUT
1,
R
PWM.OUT
2,
G
PWM.OUT
3,
B
' these are
the sliders
a$
= ""
a$
= a$ + |R <input
type="range" id="dimmer_R" oninput="setPWM()" onclick="setPWM()"
min="0" max="1023" value="| & str$(R)
& |"/><br>|
a$
= a$ + |G <input
type="range" id="dimmer_G" oninput="setPWM()" onclick="setPWM()"
min="0" max="1023" value="| & str$(G)
& |"/><br>|
a$
= a$ + |B <input
type="range" id="dimmer_B" oninput="setPWM()" onclick="setPWM()"
min="0" max="1023" value="| & str$(B)
& |"/><br>|
a$
= a$ + |<input
type='text' id="txbox" value='---'>|
html
a$
'this is the
javascript "AJAX" code
fun$
= |function setPWM() {|
fun$
= fun$ & |r=_$("dimmer_R").value;|
fun$
= fun$ & |g=_$("dimmer_G").value;|
fun$
= fun$ & |b=_$("dimmer_B").value;|
fun$
= fun$ & |var xmlHttp =
new XMLHttpRequest();|
fun$
= fun$ & |xmlHttp.open("GET", "msg?r=" + r +"&g=" + g
+"&b=" + b, false);|
fun$
= fun$ & |xmlHttp.send(null);|
fun$
= fun$ & |r =
xmlHttp.responseText;|
fun$
= fun$ & |_$("txbox").value = r;|
fun$
= fun$ & |return
r;}|
' this is
where the javascript code is inserted into the html
jscript
fun$
'this is
where the prog will jump on slider change
onUrlMessage
message
wait
message:
print
UrlMsgGet$()
PWM.OUT
1,
val(UrlMsgGet$("r"))
PWM.OUT
2,
val(UrlMsgGet$("g"))
PWM.OUT
3,
val(UrlMsgGet$("b"))
UrlMsgReturn
UrlMsgGet$()
return
|
Open the input page in another window and run
the program

Using an external RGB led, you’ll be able to
directly control its color.
You’ll see how the exchanges can be fast using
AJAX exchanges. This program uses javascript embedded into the
code. The javascript works with the function XMLHttpRequest.
A good reference for this function is here
AJAX - Send a Request To a Server
This event is
triggered when a ESP-NOW message is received.
Example:
espnow.begin
' init the ESP-NOW
onEspNowMsg message
' set the place where jump in case of message
reception
wait
message:
print "Message
Received!"
return
|
This event is
triggered when a ESP-NOW transmission error occurs.
This happens, in
particular, when the receiver device has not received the
message.
espnow.begin
' init the ESP-NOW
espnow.add_peer "60:01:94:51:D0:7D"
' set the MAC address of the receiver
onEspNowError status
' set the place where jump in case of TX error
espnow.write "TX
message"
' send the message
wait
status:
print "TX
error on ";
espnow.error$
' print the error
return
|
This event is generated when a MQTT message is
received or an MQTT event happens
Example:
....
onmqtt
mqtt_msg
wait
' receive messages from the server
mqtt_msg:
print
"TOPIC : ";
mqtt.topic$
print
"MESSAGE: ";
mqtt.message$
return
|
This event is generated when a “metadata” is
decoded when playing mp3 or streaming a web radio.
At startup, the module will try to
connect to the router using any parameters specified in the page
“Config”.
If no parameters are specified in
the “Config” page, or the connection is unsuccessful, it will
default to AP (Access Point) mode with IP address 192.168.4.1 with
the SSID composed of ESP(+ mac address). If the connection is
successful, the module will use the IP address defined in the
“Config” page or, if no IP address is specified, the IP will be
given automatically by the Router DHCP server. After the module has
connected to the router it will try to reconnect automatically if
the connection is lost.
There are several commands /
functions available to manage the WIFI.
The first function is
WIFI.STATUS which permits to get the status of
the connection.
print
WIFI.STATUS ’ print 3 if connected, 6 if
disconnected
The first useful command is
WIFI.CONNECT
SSID$, password$ [,
BSSID$] [, IP$ , MASK$ [, GATEWAY$]]
This command allows you to connect
to any WIFI network (STA mode) overriding the parameters defined
into the’ “Config” page. This function is async so the connection
is done in background, while the program continues to
run.
Is then possible to check the
status of the connection using the function
WIFI.STATUS
Example :
WIFI.CONNECT
"HOMENET", "MyPassword"
print
"connecting"
While
WIFI.STATUS <>
3
Print "."
pause 500
wend
Using the optional
parameter
BSSID$,
will enable the connection to a specific WiFi access
point.
The BSSID represents the MAC
address of the WiFi access point (the router) and it is defined as
6 bytes in hex format separated by colon, i.e.
AA:BB:CC:12:34:56.
For stand alone configuration or
for ESP-NOW applications, there is another command that puts the
module in AP mode.
This command is
WIFI.APMODE
SSID$,
password$ [, channel]
[,
IP$ , MASK$]
The result is immediate and the
status can be checked using the function
WIFI.MODE (see below).
The channel is optional and is 1
by default.
IMPORTANT : the password must be at
least 9 characters
It is eventually possible to
control the output power of the module with the command
WIFI.POWER pow
WIFI.POWER 5
’ set the output power
at 5 dBm.
The module can also be put in WiFi sleep mode.
This mode permits to turn off the WiFi reducing the power
requirements of the module; this is very useful for battery
oriented applications or for applications where the WiFi is not
required.
To put the module in “modem-sleep”, the
command to execute is
WIFI.SLEEP.
The module will stay in that mode until the
execution of the command
WIFI.AWAKE.
After this command, the module will reconnect
automatically to the router (the command
WIFI.CONNECT is not required).
Another function available
is
WIFI.CHANNEL that shows the current Radio
Channel used by the WIFI.
Using the function
WIFI.RSSI is it possible to get the
intensity of the signal received (RSSI)
It is also possible to scan for
the WiFi networks accessible around the module.
This can be done using the
command
WIFI.SCAN and the function
WIFI.NETWORKS(network$).
Example :
WIFI.SCAN
While
WIFI.NETWORKS(A$)
<
0
Wend
Print
a$
The result will be :
Vodaphone, 00:50:56:C0:00:08,
-50, 5
Orange, 00:50:56:C0:32:07, -70,
5
Xxxx,
00:50:56:C0:86:CA,-78, 12
These information represent, in
the order :
SSID, BSSID(mac address),
RSSI(signal intensity), Channel Radio
The function
WIFI.MODE returns the current mode of the WIFI
connection as below:
VALUE
|
MEANING
|
0
|
The WIFI is in sleep
mode
|
1
|
The WIFI is in STATION
mode
|
2
|
The WIFI is in AP mode
|
3
|
The WIFI in AP+STA mode
|
The WIFI in AP+STA mode can
be obtained by configuring the module in AP mode and then using the
command
WIFI.CONNECT in the program.
Using a “fake” SSID / password
(example
WIFI.CONNECT
"A",
"" ) can be used to switch the WIFI
into the AP+STA mode. This can be useful for mixed ESP32 /
ESP8266 ESP-NOW operations.
Another Wifi related command
is
OPTION.MAC
mac$ that
permits to modify the MAC address of the module.
This is very important for the ESP
Now functionality.
Example :
OPTION.MAC
"AA:BB:CC:DD:EE:FF"
In addition, the functions
BAS.SSID$ and
BAS.PASSWORD$ returns respectively the login and
the password used for the STATION wifi connection.
If a program is defined to run automatically
(“Autorun File” in the config page), the WiFi connection process is
slightly different. If the option “Fast boot” in the config
page is selected, the program will be executed immediately and the
WiFi will be powered ON after a little delay ( 0.1 sec ).
If the command
WIFI.SLEEP is executed during the very beginning of the
program ( for example as the first line of the program) the WiFi
will be simply disabled without using any power. This enhances the
use of the module in low power applications (i.e. on battery). The
WiFi connection can then be restored later using the
commandsWIFI.CONNECT
or
WIFI.APMODE.
If the command
WIFI.SLEEP is not executed at the beginning of the
program, the WiFi connection will be established by default as
described in the previous chapter (WiFI CONNECTIONS).
The function
BAS.RESETREASON can be used at the beginning of the
program to understand the reasons for the restart of the module
enabling it to take the appropriate actions.
In addition, the function
BAS.WAKEUPREASON can be used to determine the cause of
the wakeup from sleep if the module was in deep sleep mode.
In case of any IP or Autorun problem
preventing the module from being accessed, it is possible to
temporarily bypass the IP settings of the module and disable the
Autorun file by connecting the serial TX and RX pins together
(GPIO1 to GPIO3) during the startup phase (power up). This could
happen if, for example, a wrong IP address has been set.
Doing this action when restarting the module
will put it in AP mode with the IP address at 192.168.4.1, just
like a module that has not been configured. A message
“Recovery Mode” will be printed on the console, but none of the
existing files on the module will be modified, including the
internal configuration parameters.
In this mode it will be possible to gain
access to the module for changing such correct wrong IP parameters
using the configuration page.When the TX/RX link is removed, the
module can be rebooted to the configured settings at the next
restart.
The module can be put into low energy mode to
minimise as much as possible the power requirements.
This mode is called deep sleep and
should reduce the power consumption to a few µA but this is a
function of each ESP32 module as the power requirement
includes the different components installed on the module.
When the module is put into deep sleep all the
module activities are stopped, all the memory content of the module
is lost except for the RTC memory (this is a special memory block
inside the module that holds its content even if the module is
reset, but not when the module is powered OFF).
At the end of the sleep period, the
module restarts and reloads the program defined as autorun from the
beginning (from the first line).
To put the module in deep sleep the following
command is available :
SLEEP
value [, pin, level]
This command puts the ESP32 in deep sleep (low
energy) for 'value' seconds.
At the end of the period, the unit will reboot
and reload the default basic program.
Example
' Sleeps for 600 seconds (10 minutes)
The period can go from 1 second to
several years (1 year = 31,536,000 seconds)
Optionally, it is possible to wake up the
module using an external signal sent on an input pin
In this case the pin and the level must be
specified in addition to the time value.
Example
' Sleeps for 3600 seconds (1 Hour) or until the pin 32 goes to
high
SLEEP
3600, 32, 1
Only RTC IO can be used as a source for
external wake up.
They are pins: 0,2,4,12-15,25-27,32-39.
Level is 1 for wakeup on High and 0 for wakeup
on Low
Optionally, this command can be also used to
wake up the module using the capacitive touch on an input pin.
In this case the command SLEEP maintains the
same syntax but level defines the threshold value for the pin.
Only the following pins can be used for that
purpose (capacitive touch) : 0, 2, 4, 12, 13, 14, 15, 27 32, 33
Level must be > 1 to enable the touch (0
and 1 are reserved for the wake up on Low or Wake up on High).
Example
' Sleeps for 3600 seconds (1 Hour) or until the pin 15 is
touched
SLEEP
3600, 15, 40
' Threshold at 40
The RTC memory will survive after the wake up
permitting to take trace of the actions done before the sleep.
This memory can be set as below :
BAS.RTCMEM$ =
"data to be saved during deep sleep"
And can be read as below :
A$
=
BAS.RTCMEM$
Note : the RTC memory can hold up to 7680
bytes
The ESP module normally synchronises its date
and time from either of two NTP time servers ("pool.ntp.org" and
"time.nist.gov"). Optionally an alternative (eg: intranet) time
server can be defined using the [CONFIG] page. Using these servers
the ESP doesn’t require any date/time setting (except the
configuration of the Time Zone and DST done using the [CONFIG]
page).
The timezone is defined as a string
likeCET-1CEST,M3.5.0,M10.5.0/3
that describes how the local time must be managed in terms of time
shift and DST (summer / winter time).
A complete list of timezone strings can be
found here :
https://github.com/nayarsystems/posix_tz_db/blob/master/zones.csv
An internal timekeeper has been included if no
time server is available, e.g. no available internet access.
This timekeeper starts from 01/01/1970
00:00:00 and counts the seconds since the power on of the
module.
If internet connection becomes available
later, the internal timekeeper will sync its time with the NTP
servers.
The time can be sync with the NTP time server
at any moment using the command
OPTION.NTPSYNC.
This time and date can be manually set using
the command SETTIME.
The Syntax is :
SETTIME year, month, day, hours, minutes, seconds
Example
Set the date to 02 September 2017 at
13:58:12
SETTIME 17, 9, 2,
13, 58, 12
The time and date can also be
manually synchronised to the computer using the "Time Sync" button
in the File Manager window of the computer utility ‘tool’ if it has
a websocket connection.
WARNING:
In both cases of manual
setting, the time and date will default back to 1970 defaults at
the next module restart, so will require setting
again.
For more information about the
Time Zones and DST, please consult the following page
:
Time Zone and
DST It is also
possible to connect an RTC (DS1307 or DS3231) to the
module.
See the chapter
“RTC
Module”
for more details.
The following functions use the
“Unix Time Stamp” format :
DATEUNIX(date$),
TIMEUNIX(time$),
UNIXDATE$(value [,format]),
UNIXTIME$(value)
The “Unix Time Stamp” is a way
to track time as a running total of seconds. This count starts at
the Unix Epoch on January 1st, 1970 at UTC. Therefore, the unix
time is merely the number of seconds between a particular date and
the Unix Epoch.In synthesis :
-
DATEUNIX("01/01/18")
returns the number
of seconds from 01/01/1970 to the specified date 01/01/2018
(1514764800)
-
TIMEUNIX("12:30:55")
returns the number
of second since midnight (45055)
-
UNIXDATE$("1532773308")
returns
28/07/18
-
UNIXTIME$(1532773308)
returns
10:21:48
Annex32 includes a
FATFS file system hosted on the flash memory chip.
It “emulates” a
disk file system enabling it to save and load files in a
transparent way.
Depending on the
size of the flash chip, the following free space is available :
Flash Chip size
|
Free space available
|
4M
|
1MB
|
8M
|
5MB
|
16M
|
13MB
|
Annex32 can also
use an SD CARD connected as described in the chapter SD CARD
ADAPTER.
Both the internal
FATFS and the SD CARD utilise the FAT32 file system This means that
there are no particular limitations in terms of filename length and
directories, compared to the SPIFFS file system limitations hosted
in the ESP8266.
Unlike normal
variables, filenames and folders are case sensitive. Annex32
supports SD CARDS up to 16GB.
The internal and the external (SDcard)
space are mutually exclusive and cannot be accessed at the same
time. By default Annex32 will use the SD, if available, otherwise
it will use the internal flash disk space (FATFS).
Both the
internal FATFS and external SD CARD share the same command and
functions.
All the file
related functions share the same prefix FILE.
followed by the specific function.
FUNCTIONS / COMMANDS
|
DESCRIPTION
|
FILE.COPY(filename$,
newfile$)
|
Copy the file filename$
into the file newfile$
Returns 1 in case of success or
0 if error
|
|
Delete the file specified by filename$
Returns 1 in case of success or
0 if error
|
|
Returns 1 if filename$
exists, otherwise returns 0
|
|
Rename the file oldname$
to newname$
Returns 1 in case of success or
0 if error
|
|
Returns the size of the file (in bytes) if the
file exist, otherwise returns -1
|
|
Create a directory specified by
dirname$
Returns 1 in case of success or
0 if error
|
|
Remote the directory specified by
dirname$
Returns 1 in case of success or
0 if error
|
|
Will search for files and return the names of
entries found.
path$
represents the directory name.
path$ can
include wildcards characters as ‘*’,
‘.’ and
‘?’
The function will return the first entry
found.
To retrieve subsequent entries use the
function with no arguments. ie,
FILE.DIR$.
The return of an empty string indicates that
there are no more entries to retrieve.
|
FILE.READ$(filename$,
[line_num] | [start, length])
|
Returns the content of the file
filename$.
Specifying line_num,
only the corresponding line is read from the file.
If start
and length
options are specified, the file is read from the start
position for length
characters, otherwise the complete file is read in one go
The line number
starts from 1.
If the line is not
existing (reached the end of file), the function will return
“_EOF_” to indicate the end of the file.
|
|
Append the content of content$
to the file filename$.
If the file does not exist, it will be
created.
The file can be read back using the function
FILE.READ$(filename$)
File size is only limited by available disk
space (internal FFAT or external SD card)
|
FILE.SAVE
filename$,
content$
|
Save the content of content$
to the file filename$.
The file can be read back using the function
FILE.READ$(filename$)
File size is only limited by available disk
space (internal FFAT or external SD card)
|
|
Same functionalities as the previous
command.
Implemented for homogeneity with other
commands
|
|
Convert the file defined ‘source$’ into the
file defined in ‘dest$’.
The source file can be in any format but must
be encoded in base64 format. Useful for wokwi to store any file in
text format
|
|
Convert the file defined ‘source$’ into the
file defined in ‘dest$’.
The source file can be in any format and will
be encoded in base64 format.
|
|
See the chapter I/O buffer for more
details
|
|
See the chapter I/O buffer for more
details
|
|
See the chapter I/O buffer for more
details
|
|
See the chapter I/O buffer for more
details
|
Examples:
List all the files
in the directory /html
d$
= FILE.DIR$("/html")
While D$
<> ""
wlog d$
d$
= FILE.DIR$
Wend
|
File operations
file.save
"/test.bas",
"The quick brown fox "
wlog
"exists",
file.exists("/test.bas")
wlog
"size",
file.size("/test.bas")
file.append
"/test.bas",
"jumps over the lazy dog"
wlog
"size",
file.size("/test.bas")
wlog
"copy",
file.copy("/test.bas",
"/AAA.bas")
wlog
"size",
file.size("/AAA.bas")
wlog
"rename",
file.rename("/AAA.bas",
"/BBB.bas")
wlog
"size",
file.size("/BBB.bas")
wlog
"size",
file.size("/AAA.bas")
wlog
"read",
file.read$("/test.bas")
wlog
"delete",
file.delete("/BBB.bas")
|
The
command:
FILE.DOWNLOAD url$,
file_path$
retrieves a file from a specified URL (url$) and saves it
to the local file path (file_path$). This
can be used both as a standalone command or as a function that
returns a status code, indicating the success or failure of the
download operation.
●
url$: A string specifying the URL of the file to download.
This should be a valid HTTP or HTTPS URL.
●
file_path$: A string specifying the local path where the
downloaded file should be saved.
When used as a function,FILE.DOWNLOAD
returns an integer value that indicates the status of the
download:
●
1: Download completed successfully.
●
-1: Not enough space available to download the file.
●
-2: Failed to open the file for writing.
●
-3: Failed to create an HTTP client.
●
Other HTTP error codes: Various HTTP error codes that may be
returned by the server (e.g., 404 for "Not Found", 500 for
"Internal Server Error").
This command is
also useful for downloading (copying) a file from another Annex RDS
module. By providing the appropriate URL, you can easily transfer
files between modules, which is especially useful for distributing
updates or configurations across multiple devices.
● The
function handles both HTTP and HTTPS URLs, using a secure
client
● The
function checks for available space before attempting the download
and will abort if there is insufficient space.
● All
operations are logged to the serial output for debugging
purposes.
Example 1:
download from the WEB
FILE.DOWNLOAD
"https://updates.cicciocb.com/annex-logo.png",
"/logo.png"
or
Wlog
FILE.DOWNLOAD("http://updates.cicciocb.com/annex_bee_new.png",
"/logo2.png")
Example 1:
download from another Annex RDS Module with IP: 192.168.1.181
FILE.DOWNLOAD
"http://192.168.1.181/program1.bas",
"/program1.bas"
or
Wlog
FILE.DOWNLOAD("http://192.168.1.181/program1.bas",
"/program1.bas")
print file.download
("https://updates.cicciocb.com/annex-logo.png", "/logo.png")
The I/O BUFFER is a functionality that gives
the capability to hold and manage binary data. In short, the I/O
buffer is a block of RAM memory that can be exchanged as a block or
read and written byte per byte. It overcomes the limitation
of strings, which are unable to include the character ASCII 0
(NUL).
It has a defined length and can be freely
dimensioned and cleared.
It can be used in the code using the
IOBUFF keyword, and Annex exposes 5 I/O buffers numbered
from 0 to 4.
The I/O buffers can have any size within the
limits of the free RAM memory available. The main goal of this
functionality is to interface with all the functions that require
exchanges using binary data.
In the current implementation it can be used
with :
-
Files
-
Serial Ports
-
SPI
-
I2C
-
UDP
This command
allocates memory for an I/O buffer by defining its size.
●
Parameters:
○
buff_num:
Specifies the buffer ID, ranging from 0 (first buffer) to
4 (last buffer).
○
size:
Specifies the size of the buffer in bytes. The value can range from
0 to the maximum available RAM.
●
Return Value:
○ The
size of the allocated memory or 0 in case of error
●
Behaviour:
●
Allocates the specified amount of memory to the selected
buffer.
● The
buffer retains its size until it is manually destroyed or the
program ends.
Example:
IOBUFF.DIM(0,
1000) 'dimension the I/O buffer 0 with 1000
bytes
Print
IOBUFF.DIM(1,
25) 'dimension the I/O buffer 1 with 25 bytes (prints
25)
|
IOBUFF.DIM(buff_num,size)
= data_list
The
IOBUFF.DIM command can also initialise a buffer with a
sequence of values during its creation.
●
Parameters:
○
buff_num:
Specifies the buffer ID, ranging from 0 (first buffer) to
4 (last buffer).
○
size:
Specifies the size of the buffer in bytes. The value can range from
0 to the maximum available RAM.
○
data_list:
A list of values (e.g., integers, hexadecimal, binary) to store in
the buffer.
●
Return Value:
○ The
size of the allocated memory or 0 in case of error
●
Behaviour:
○
Reserves memory for the buffer and populates it with the specified
values.
Example:
' Fills buffer 0 with 10 values
Print
IOBUFF.DIM(0,
10) = 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
' prints 10
' Fills buffer 1 with 5 values
IOBUFF.DIM(1,
5) = &h12,
&hAA, &h50, &O377, &B10101010
|
Releases the memory allocated to a specific buffer.
●
Parameters:
○
buff_num:
Specifies the buffer ID to be destroyed (0–4).
●
Return Value:
○
Always 0
●
Behaviour:
○
Frees the memory allocated for the specified buffer.
○
After destruction, the buffer is no longer accessible until
reallocated.
Example:
IOBUFF.DESTROY(0)
' Destroys buffer 0, releasing its
allocated memory
|
Note: All buffers are automatically destroyed when the
program ends.
Returns the current size (in bytes) of the specified buffer.
●
Parameters:
○
buff_num:
The ID of the buffer to query (0–4).
●
Return Value:
○ The
size of the buffer in bytes.
Example:
Print
IOBUFF.LEN(0)
' Prints the size of buffer
0
|
Reads a single byte from a specified position in a buffer.
●
Parameters:
○
buff_num:
The ID of the buffer to read from (0–4).
○
position:
The byte position to read (0 to buffer length - 1).
●
Return Value:
○ The
value of the byte at the specified position (0–255).
Example:
Print
IOBUFF.READ(0,
4) '
Prints the byte at position 4 from buffer 0
A =
IOBUFF.READ(0, 7)
' Stores the byte at position 7 in
variable A
|
IOBUFF.WRITE(buff_num,position,
value)
Writes a single byte to a specified position in a buffer.
●
Parameters:
○
buff_num:
Specifies the buffer ID to be destroyed (0–4).
○
position:
The byte position to read (0 to buffer length - 1).
○
value:
The byte value to write (0–255).
●
Return Value:
○
Always 0
●
Behaviour:
○
Updates the specified position in the buffer with the given
value.
Example:
IOBUFF.WRITE(0,
5, 123) ' Writes the value 123 at position 5 of buffer
0
|
The I/O buffers communicate with the other
modules using the following syntax:
-
xxxx.READ_IOBUFF(buff_num)
Receive data in the
buffer buff_num
-
xxxx.WRITE_IOBUFF(buff_num,
start, size)
Transmit (send)
data from the buffer buff_num
starting from the position ‘start’
for ‘size’
bytes
-
xxxx.REPLY_IOBUFF(buff_num,
start, size)
Reply to the sender
data from the buffer buff_num
starting from the position ‘start’
for ‘size’
bytes
Where
xxxx can be :
UDP
SERIAL
SERIAL2
FILE
I2C
SPI
Detailed syntax :
UDP.READ_IOBUFF(buff_num)
SERIAL.READ_IOBUFF(buff_num)
SERIAL2.READ_IOBUFF(buff_num)
FILE.READ_IOBUFF(buff_num),
filename$ [, position, nb_of_bytes_to_read]
I2C.READ_IOBUFF(buff_num),
address, register, nb_of_bytes_to_read
SPI.READ_IOBUFF(buff_num),
nb_of_bytes_to_read
UDP.WRITE_IOBUFF(buff_num
[, start [, size]]), IP$,
port
SERIAL.WRITE_IOBUFF(buff_num
[, start [, size]])
SERIAL2.WRITE_IOBUFF(buff_num
[, start [, size]])
FILE.SAVE_IOBUFF(buff_num
[, start [, size]]),
filename$
FILE.WRITE_IOBUFF(buff_num
[, start [, size]]),
filename$
FILE.APPEND_IOBUFF(buff_num
[, start [, size]]),
filename$
I2C.WRITE_IOBUFF(buff_num
[, start [, size]]), address,
register
SPI.WRITE_IOBUFF(buff_num
[, start [, size]])
UDP.REPLY_IOBUFF(buff_num
[, start [, size]])
[,port]
SPI.REPLY_IOBUFF(buff_num
[, start [, size]]), (buff_num_reception)
The IOBUFFER can be used for sending or
receiving data.
When used for receiving data, the syntax is
always.READ_IOBUFF(buff_num).
When receiving data, it is not necessary to
dimension the buffer before as it will be automatically dimensioned
depending on the size of the data received. If the buffer was
already containing some data, these will be flushed and replaced by
the new data.
For example, the following command receives
all the data available from the serial port 2 in the buffer 3 :
SERIAL2.READ_IOBUFF(3)
This command receives the data coming from an
UDP connection in the buffer 1:
UDP.READ_IOBUFF(1)
Additionally some other arguments may be
required.
This command reads 512 bytes from the file
data.bin starting from the file position 123 in the buffer 0:
FILE.READ_IOBUFF(0),
“/data.bin”, 123, 512
This command reads 8 bytes from an I2C device
with address 63 from the register 19 in the buffer 4 :
I2C.READ_IOBUFF(4),
63, 19, 8
This command reads 32 bytes from the SPI bus
in the buffer 2 :
SPI.READ_IOBUFF(2),
32
When used for sending data, the syntax is
always
.WRITE_IOBUFF(buff_num
[, start [, size]])
When sending data, it is possible to send the
entire buffer or only a part of it. Specifying the optional
arguments start and size it is possible to define the part of the
buffer to be sent; otherwise, if omitted, the entire buffer will be
transferred.
For example, the following command sends 10
bytes from the buffer 1 starting from the position 45 to the serial
port :
SERIAL.WRITE_IOBUFF(1,
45, 10)
This command sends the complete buffer 1 to
the serial port 2
SERIAL2.WRITE_IOBUFF(1)
This command sends 8 bytes from the buffer 2
starting from the position 128 to the SPI bus
SPI.WRITE_IOBUFF(2,
128, 8)
Additionally some other arguments may be
required.
This command sends 12 bytes from the buffer 1
starting from the position 64 to the UDP on the address
192.168.1.89 and port 8080 :
UDP.WRITE_IOBUFF(2,
128, 8), “192.168.1.89”,
8080
This command sends the entire buffer 2 on the
same UDP device :
UDP.WRITE_IOBUFF(2),
“192.168.1.89”, 8080
This command writes the buffer 1 to the file
data.bin
FILE.WRITE_IOBUFF(1),
“data.bin”
This command has the same result and is
provided for compatibility with the existing syntax
FILE.SAVE_IOBUFF(1),
“data.bin”
This command appends 36 bytes from the buffer
0 starting from the position 25 to data.bin
FILE.APPEND_IOBUFF(0,
25, 36), “data.bin”
This command sends the buffer 2 to the I2C
device with address 63 and register 19 :
I2C.WRITE_IOBUFF(2),
63, 19
The same operation but sending only 4 bytes
starting from position 0:
I2C.WRITE_IOBUFF(2,
0, 4), 63, 19
The syntax
.REPLY_IOBUFF(buff_num
[, start [, size]])
defines some kind of special operations.
For example, this command sends the buffer 0
back to the UDP message sender:
UDP.REPLY_IOBUFF(0)
This is the equivalent of
UDP.REPLY message$
but with the IOBUFFER
Optionally it is also possible specify part of
the buffer and the destination port (eg: 5001) as below:
UDP.REPLY_IOBUFF(0,
2, 6), 5001
When used with the SPI bus, it transmits and
receives at the same time.
As this operation requires 2 buffers, both
must be specified.
For example, this command sends the buffer 0
and receive into the buffer 2:
SPI.REPLY_IOBUFF(0),
(2)
This command sends 4 bytes from the buffer 0
starting from the position 89 and receive 4 bytes in the buffer
3:
SPI.REPLY_IOBUFF(0,
89, 4), (3)
Several other functions / commands are
available for advanced users.
These enable bit, string and hex
operations
Convert a String
into Buffer Content
●
Parameters:
○
buff_num:
The ID of the buffer (0–4) where the string will be written.
○
var$:
The input string containing the text to be converted, e.g., "This
is a text string".
○
pos:
(Optional) The starting position in the buffer where the string
will be written.
Default: 0 (write from the beginning of the buffer).
●
Return Value:
○ The
number of characters successfully written into the buffer.
○ If
used as a command, the return value is ignored.
●
Behaviour:
○
Converts the input string (var$)
into its binary representation and writes it to the specified
buffer (buff_num).
○ If
pos
is specified, the string starts at the given byte position in the
buffer.
○ If
the buffer does not have enough space, it is automatically resized
to fit the string.
Example:
IOBUFF.FROMSTRING(0,
"Hello") ' Writes "Hello" into buffer 0 starting at position
0.
IOBUFF.FROMSTRING(0,
"World", 10) ' Writes
"World" into buffer 0 starting at position
10.
print
IOBUFF.FROMSTRING(0,
"World") ' Outputs "5"
(the size of the string)
|
Convert Buffer
Content to a String
●
Parameters:
○
buff_num:
The ID of the buffer (0–4) to read data from.
○
start
: (Optional) The starting position in the buffer for reading
data.
Default: 0 (start from the first byte).
○
size:
(Optional) The number of bytes to read from the buffer.
Default: Reads from the starting position to the end of the
buffer.
●
Return Value:
○ The
text string generated from the specified portion of the buffer
content.
●
Behaviour:
○
Converts binary data in the specified buffer (buff_num)
into a string representation.
○ If
start
and size
are not provided, the entire buffer content is converted to a
string.
○ If
the specified range (start
+ size)
exceeds the buffer length, only the available data within the range
is converted.
○
Non-printable or invalid text characters may result in an
incomplete or unexpected string.
●
Note:
○
start
and size
work like MID$ but the 1st byte is 0
Example:
IOBUFF.FROMSTRING(0,
"Hello, World!") ' Write
"Hello, World!" into buffer 0.
text$
= IOBUFF.TOSTRING$(0) ' Convert entire buffer content to a
string.
PRINT text$
' Outputs: "Hello,
World!"
partial$
= IOBUFF.TOSTRING$(0, 7, 5) ' Read 5
bytes starting from position 7.
PRINT partial$
' Outputs:
"World"
|
Convert
Hexadecimal String to Buffer Content
●
Parameters:
○
buff_num:
The ID of the buffer (0–4) to store the converted data.
○
var$:
The hexadecimal string to convert.
Must contain only valid hexadecimal characters (0–9
and A–F/a–f) with an even
length.
Example:
"aabbcc1235".
○
pos:
(Optional) The starting position in the buffer where the converted
data will be stored.
Default: 0 (start writing at the beginning of the buffer).
●
Return Value:
○ The
number of bytes successfully converted and written to the
buffer.
○ If
used as a command, this return value is ignored.
●
Behaviour:
○
Converts the specified hexadecimal string (var$)
into its binary representation and writes it into the buffer
(buff_num).
○ If
pos
is specified, the conversion starts from the given position in the
buffer.
○ If
the string contains invalid characters an error is raised.
○ If
the buffer does not have enough space, it is automatically
resized.
Example:
bytes_written
= IOBUFF.FROMHEX(0, "aabbcc1235")
PRINT bytes_written
' Outputs: 5 (bytes converted and
stored).
PRINT
IOBUFF.TOHEX$(0)
' Outputs:
"AABBCC1235"
IOBUFF.FROMHEX(0,
"ff", 10)
' Write single byte (FF) at position
10.
PRINT
IOBUFF.READ(0,
10)
' Outputs: 255 (decimal value of
FF).
' Advanced example
IOBUFF.FROMHEX(1,
"01020304050607080910")
IOBUFF.FROMHEX(1,
MID$("abcdef123456", 3, 4), 5) '
Convert "cdef" and write at position 5.
PRINT
IOBUFF.TOHEX$(1)
' Outputs:
"0102030405CDEF080910"
|
Convert Buffer
Content to Hexadecimal String
IOBUFF.TOHEX$(buff_num, [, start [,
size]])
●
Parameters:
○
buff_num:
The ID of the buffer (0–4) containing the data to convert.
○
start:
(Optional) The starting position in the buffer for the
conversion.
Default: 0 (start from the beginning of the buffer).
○
size:
(Optional) The number of bytes to convert from the starting
position.
Default: Converts all bytes from start to the end of the
buffer.
●
Return Value:
○
A hexadecimal string representing the converted binary data
from the buffer.
○
Each byte in
the buffer is converted to a two-character hexadecimal value (e.g.,
255 → "FF").
●
Behaviour:
○
Reads the specified range of bytes from the buffer (buff_num) and
converts them into a continuous hexadecimal string.
○ If
start
and size
are omitted, the entire buffer is converted.
○ The
conversion does not modify the content of the buffer.
●
Note:
○
start
and size
work like MID$ but the 1st byte is 0
Example:
IOBUFF.DIM(0,
10)
' Allocate buffer 0 with 10
bytes.
IOBUFF.WRITE(0,
0, &hFF)
' Write byte 255 (hex FF) at position
0.
IOBUFF.WRITE(0,
1, &hAA)
' Write byte 170 (hex AA) at position
1.
PRINT
IOBUFF.TOHEX$(0)
' Outputs:
"FFAA0000000000000000"
PRINT
IOBUFF.TOHEX$(0, 0,
2)
' Outputs: "FFAA" (first two
bytes).
PRINT
IOBUFF.TOHEX$(0, 1,
1)
' Outputs: "AA" (second byte
only).
' Advanced example
IOBUFF.DIM(1,
20)
' Allocate buffer 1 with 20
bytes.
IOBUFF.WRITE(1,
5, &h12)
' Write byte 18 (hex 12) at position
5.
IOBUFF.WRITE(1,
6, &h34)
' Write byte 52 (hex 34) at position
6.
hex_str$
= IOBUFF.TOHEX$(1, 5, 2) ' Convert bytes at position 5–6 to
hex.
PRINT hex_str$
'
Outputs: "1234"
|
Encode Buffer
Content to Base64
Encodes the
content of the specified buffer into a Base64-encoded
string.
●
Parameters:
○
buff_num:
The ID of the buffer (0–4) containing the data to encode.
●
Return Value:
○ The
size of the Base64-encoded string (in bytes).
○ If
used as a command, this return value is ignored.
●
Behaviour:
○
Converts the binary data in the buffer into a Base64 string.
○ The
original data in the buffer is replaced by the Base64 string
○
Automatically resizes the buffer to fit the decoded data.
Example:
' Encodes buffer 0 into Base64 and returns the size
Base64Size
= IOBUFF.TOBASE64(0)
Print Base64Size
' Displays the size of the Base64
string
|
Decode Base64
String into Buffer Content
Decodes a Base64
string and writes the resulting binary data into the specified
buffer.
●
Parameters:
○
buff_num:
The ID of the buffer (0–4) containing the data to decode.
○
Base64String$:
The Base64-encoded string to decode.
●
Return Value:
○ The
size of the decoded buffer (in bytes).
○ If
used as a command, this return value is ignored.
●
Behaviour:
○
Decodes the Base64 string into binary data.
○ The
original data in the buffer is replaced by the decoded data.
○
Automatically resizes the buffer to fit the decoded data.
Example:
' Decodes buffer 0 from Base64 format and returns the
size
DecodedSize
= IOBUFF.FROMBASE64(0)
Print DecodedSize
' Displays the size of the Decoded
buffers
|
Encrypts the data
in the buffer using the AES-128 algorithm with PKCS7
padding
●
Parameters:
○
buff_num:
ID of the buffer (0–4).
○
key$:
A 16-character string representing the encryption key (128
bits).
●
Return Value:
○ The
size of the encrypted buffer (in bytes).
○ If
used as a command, this return value is ignored.
●
Behaviour:
○
Encrypts the content of the specified buffer in place using
the AES-128 algorithm.
○ The
original data in the buffer is replaced by its encrypted form.
○ The
key must be exactly 16 characters long.
○ The
encrypted buffer can only be decrypted using the same key.
○ The
buffer content is padded according to the PKCS7 method to ensure
alignment with AES-128 block size (16 bytes).
Decrypts data in
the buffer using the AES-128 algorithm
●
Parameters:
○
buff_num:
ID of the buffer (0–4).
○
key$:
The 16-character encryption key used during encryption.
●
Return Value:
○ The
size of the decrypted buffer (in bytes).
○ If
used as a command, this return value is ignored.
●
Behaviour:
○
Decrypts the content of the specified buffer in place using
the AES-128 algorithm.
○ The
original encrypted data in the buffer is replaced by its decrypted
form.
○ The
key must match the one used for encryption.
○ The
buffer is unpadded to its original content according to the PKCS7
method.
Example:
key$
= "my_Personal_key1"
' Sets the crypting
key
IObuff.FromString(0,
"Hello, World!") ' Converts a
string into IO Buffer
print
IObuff.Encrypt(0,
key$)
' Encrypts using a 16 characters
key
wlog
IObuff.ToHex$(0)
' Shows the result in Hex
format
wlog
IObuff.Decrypt(0,
key$) ' Decrypts using the same key
wlog
IObuff.ToString$(0) '
shows the decrypted string (same as the
original)
|
Calculates a
Cyclic Redundancy Check (CRC) value for a given input
buffer.
IOBUFF.CRC(buff_num, nb_bits,
polynom, initial_value, ref_in, ref_out, xor_out)
●
Parameters:
○
buff_num:
ID of the buffer (0–4) containing the data for which the CRC needs
to be calculated.
○
nb_bits:
Bit order for the CRC calculation. It can be set from 8 to 32 (i.e.
16 for a 16-bit CRC).
○
polynom:
CRC polynomial used in the calculation .
○
initial_value:
Initial CRC value. This value is used to initialise the CRC
calculation.
○
ref_in:
Input reflection flag (1 for true, 0 for false). If set to 1, the
input data is processed in reverse bit order.
○
ref_out:
Output reflection flag (1 for true, 0 for false). If set to 1, the
CRC output is reflected (i.e., processed in reverse bit order).
○
xor_out:
Final XOR value. This value is applied to the final CRC value
before returning it.
●
Return Value:
○ The
calculated CRC value, or 0 if the input buffer is empty.
●
Behaviour:
○ This
function computes the CRC value for the data in the specified I/O
buffer. It supports customizable CRC parameters to accommodate
different CRC algorithms. You can define the polynomial, initial
value, and final XOR value, and also specify whether to reflect the
input data and/or output CRC.
○
Nb_bits
specifies the bit size of the CRC (e.g., 16-bit, 32-bit).
○
polynom
defines the polynomial used for the calculation (e.g.,
0x4c11db7 for CRC-32).
○
initial_value
is the initial CRC value, commonly 0xffffffff for
CRC-32.
○
ref_in
and ref_out
allow for reflection of input and output bits.
○
xor_out
applies an XOR operation to the final CRC value before
returning.
●
Note:
○
Ensure that the I/O buffer contains the data you want to calculate
the CRC for before calling this function. If the buffer is empty,
the function returns 0.
CRC Demo
Code
This demo code demonstrates how to calculate various CRC (Cyclic
Redundancy Check) values for the string
"123456789". It uses a variety of CRC algorithms, from
CRC-8 to CRC-32, with different settings for each. The results are
compared with expected CRC values, which can be verified using
online tools like crc-calculator.
'CRC demo code
'references to https://crccalc.com/
a$
= "123456789"
wlog
IObuff.fromstring(0,
a$)
wlog
"Algo CRC ", "Expected",
"Result"
wlog
"CRC-8/AUTOSAR", hex$(0xDF),
hex$(IObuff.CRC(0, 8, 0x2F, 0xFF, 0, 0, 0xFF))
wlog
"CRC-8/BLUETOOTH", hex$(0x26),
hex$(IObuff.CRC(0, 8, 0xA7, 0x00, 1, 1, 0x00))
wlog
"CRC-8/CDMA2000", hex$(0xDA),
hex$(IObuff.CRC(0, 8, 0x9B, 0xFF, 0, 0, 0x00))
wlog
"CRC-8/DARC", hex$(0x15),
hex$(IObuff.CRC(0, 8, 0x39, 0x00, 1, 1, 0x00))
wlog
"CRC-8/DVB-S2", hex$(0xBC),
hex$(IObuff.CRC(0, 8, 0xD5, 0x00, 0, 0, 0x00))
wlog
"CRC-8/GSM-A", hex$(0x37),
hex$(IObuff.CRC(0, 8, 0x1D, 0x00, 0, 0, 0x00))
wlog
"CRC-8/GSM-B", hex$(0x94),
hex$(IObuff.CRC(0, 8, 0x49, 0x00, 0, 0, 0xFF))
wlog
"CRC-8/HITAG", hex$(0xB4),
hex$(IObuff.CRC(0, 8, 0x1D, 0xFF, 0, 0, 0x00))
wlog
"CRC-8/I-432-1", hex$(0xA1),
hex$(IObuff.CRC(0, 8, 0x07, 0x00, 0, 0, 0x55))
wlog
"CRC-8/I-CODE", hex$(0x7E),
hex$(IObuff.CRC(0, 8, 0x1D, 0xFD, 0, 0, 0x00))
wlog
"CRC-8/LTE", hex$(0xEA),
hex$(IObuff.CRC(0, 8, 0x9B, 0x00, 0, 0, 0x00))
wlog
"CRC-8/MAXIM-DOW", hex$(0xA1),
hex$(IObuff.CRC(0, 8, 0x31, 0x00, 1, 1, 0x00))
wlog
"CRC-8/MIFARE-MAD", hex$(0x99),
hex$(IObuff.CRC(0, 8, 0x1D, 0xC7, 0, 0, 0x00))
wlog
"CRC-8/NRSC-5", hex$(0xF7),
hex$(IObuff.CRC(0, 8, 0x31, 0xFF, 0, 0, 0x00))
wlog
"CRC-8/OPENSAFETY", hex$(0x3E),
hex$(IObuff.CRC(0, 8, 0x2F, 0x00, 0, 0, 0x00))
wlog
"CRC-8/ROHC", hex$(0xD0),
hex$(IObuff.CRC(0, 8, 0x07, 0xFF, 1, 1, 0x00))
wlog
"CRC-8/SAE-J1850", hex$(0x4B),
hex$(IObuff.CRC(0, 8, 0x1D, 0xFF, 0, 0, 0xFF))
wlog
"CRC-8/SMBUS", hex$(0xF4),
hex$(IObuff.CRC(0, 8, 0x07, 0x00, 0, 0, 0x00))
wlog
"CRC-8/TECH-3250", hex$(0x97),
hex$(IObuff.CRC(0, 8, 0x1D, 0xFF, 1, 1, 0x00))
wlog
"CRC-8/WCDMA", hex$(0x25),
hex$(IObuff.CRC(0, 8, 0x9B, 0x00, 1, 1, 0x00))
wlog
"CRC-16/ARC", hex$(0xBB3D),
hex$(IObuff.CRC(0, 16, 0x8005, 0x0000, 1, 1,
0x0000))
wlog
"CRC-16/CDMA2000", hex$(0x4C06),
hex$(IObuff.CRC(0, 16, 0xC867, 0xFFFF, 0, 0,
0x0000))
wlog
"CRC-16/CMS", hex$(0xAEE7),
hex$(IObuff.CRC(0, 16, 0x8005, 0xFFFF, 0, 0,
0x0000))
wlog
"CRC-16/DDS-110", hex$(0x9ECF),
hex$(IObuff.CRC(0, 16, 0x8005, 0x800D, 0, 0,
0x0000))
wlog
"CRC-16/DECT-R", hex$(0x007E),
hex$(IObuff.CRC(0, 16, 0x0589, 0x0000, 0, 0,
0x0001))
wlog
"CRC-16/DECT-X", hex$(0x007F),
hex$(IObuff.CRC(0, 16, 0x0589, 0x0000, 0, 0,
0x0000))
wlog
"CRC-16/DNP", hex$(0xEA82),
hex$(IObuff.CRC(0, 16, 0x3D65, 0x0000, 1, 1,
0xFFFF))
wlog
"CRC-16/EN-13757", hex$(0xC2B7),
hex$(IObuff.CRC(0, 16, 0x3D65, 0x0000, 0, 0,
0xFFFF))
wlog
"CRC-16/GENIBUS", hex$(0xD64E),
hex$(IObuff.CRC(0, 16, 0x1021, 0xFFFF, 0, 0,
0xFFFF))
wlog
"CRC-16/GSM", hex$(0xCE3C),
hex$(IObuff.CRC(0, 16, 0x1021, 0x0000, 0, 0,
0xFFFF))
wlog
"CRC-16/IBM-3740", hex$(0x29B1),
hex$(IObuff.CRC(0, 16, 0x1021, 0xFFFF, 0, 0,
0x0000))
wlog
"CRC-16/IBM-SDLC", hex$(0x906E),
hex$(IObuff.CRC(0, 16, 0x1021, 0xFFFF, 1, 1,
0xFFFF))
wlog
"CRC-16/ISO-IEC-14443-3-A", hex$(0xBF05),
hex$(IObuff.CRC(0, 16, 0x1021, 0xC6C6, 1, 1,
0x0000))
wlog
"CRC-16/KERMIT", hex$(0x2189),
hex$(IObuff.CRC(0, 16, 0x1021, 0x0000, 1, 1,
0x0000))
wlog
"CRC-16/LJ1200", hex$(0xBDF4),
hex$(IObuff.CRC(0, 16, 0x6F63, 0x0000, 0, 0,
0x0000))
wlog
"CRC-16/M17", hex$(0x772B),
hex$(IObuff.CRC(0, 16, 0x5935, 0xFFFF, 0, 0,
0x0000))
wlog
"CRC-16/MAXIM-DOW", hex$(0x44C2),
hex$(IObuff.CRC(0, 16, 0x8005, 0x0000, 1, 1,
0xFFFF))
wlog
"CRC-16/MCRF4XX", hex$(0x6F91),
hex$(IObuff.CRC(0, 16, 0x1021, 0xFFFF, 1, 1,
0x0000))
wlog
"CRC-16/MODBUS", hex$(0x4B37),
hex$(IObuff.CRC(0, 16, 0x8005, 0xFFFF, 1, 1,
0x0000))
wlog
"CRC-16/NRSC-5", hex$(0xA066),
hex$(IObuff.CRC(0, 16, 0x080B, 0xFFFF, 1, 1,
0x0000))
wlog
"CRC-16/OPENSAFETY-A", hex$(0x5D38),
hex$(IObuff.CRC(0, 16, 0x5935, 0x0000, 0, 0,
0x0000))
wlog
"CRC-16/OPENSAFETY-B", hex$(0x20FE),
hex$(IObuff.CRC(0, 16, 0x755B, 0x0000, 0, 0,
0x0000))
wlog
"CRC-16/PROFIBUS", hex$(0xA819),
hex$(IObuff.CRC(0, 16, 0x1DCF, 0xFFFF, 0, 0,
0xFFFF))
wlog
"CRC-16/RIELLO", hex$(0x63D0),
hex$(IObuff.CRC(0, 16, 0x1021, 0xB2AA, 1, 1,
0x0000))
wlog
"CRC-16/SPI-FUJITSU", hex$(0xE5CC),
hex$(IObuff.CRC(0, 16, 0x1021, 0x1D0F, 0, 0,
0x0000))
wlog
"CRC-16/T10-DIF", hex$(0xD0DB),
hex$(IObuff.CRC(0, 16, 0x8BB7, 0x0000, 0, 0,
0x0000))
wlog
"CRC-16/TELEDISK", hex$(0x0FB3),
hex$(IObuff.CRC(0, 16, 0xA097, 0x0000, 0, 0,
0x0000))
wlog
"CRC-16/TMS37157", hex$(0x26B1),
hex$(IObuff.CRC(0, 16, 0x1021, 0x89EC, 1, 1,
0x0000))
wlog
"CRC-16/UMTS", hex$(0xFEE8),
hex$(IObuff.CRC(0, 16, 0x8005, 0x0000, 0, 0,
0x0000))
wlog
"CRC-16/USB", hex$(0xB4C8),
hex$(IObuff.CRC(0, 16, 0x8005, 0xFFFF, 1, 1,
0xFFFF))
wlog
"CRC-16/XMODEM", hex$(0x31C3),
hex$(IObuff.CRC(0, 16, 0x1021, 0x0000, 0, 0,
0x0000))
wlog
"CRC-32/AIXM", hex$(0x3010BF7F), hex$(IObuff.CRC(0, 32, 0x814141AB, 0x00000000, 0, 0,
0x00000000))
wlog
"CRC-32/AUTOSAR", hex$(0x1697D06A), hex$(IObuff.CRC(0, 32, 0xF4ACFB13, 0xFFFFFFFF, 1, 1,
0xFFFFFFFF))
wlog
"CRC-32/BASE91-D", hex$(0x87315576), hex$(IObuff.CRC(0, 32, 0xA833982B, 0xFFFFFFFF, 1, 1,
0xFFFFFFFF))
wlog
"CRC-32/BZIP2", hex$(0xFC891918), hex$(IObuff.CRC(0, 32, 0x04C11DB7, 0xFFFFFFFF, 0, 0,
0xFFFFFFFF))
wlog
"CRC-32/CD-ROM-EDC", hex$(0x6EC2EDC4), hex$(IObuff.CRC(0, 32, 0x8001801B, 0x00000000, 1, 1,
0x00000000))
wlog
"CRC-32/CKSUM", hex$(0x765E7680), hex$(IObuff.CRC(0, 32, 0x04C11DB7, 0x00000000, 0, 0,
0xFFFFFFFF))
wlog
"CRC-32/ISCSI", hex$(0xE3069283), hex$(IObuff.CRC(0, 32, 0x1EDC6F41, 0xFFFFFFFF, 1, 1,
0xFFFFFFFF))
wlog
"CRC-32/ISO-HDLC", hex$(0xCBF43926), hex$(IObuff.CRC(0, 32, 0x04C11DB7, 0xFFFFFFFF, 1, 1,
0xFFFFFFFF))
wlog
"CRC-32/JAMCRC", hex$(0x340BC6D9), hex$(IObuff.CRC(0, 32, 0x04C11DB7, 0xFFFFFFFF, 1, 1,
0x00000000))
wlog
"CRC-32/MEF", hex$(0xD2C22F51), hex$(IObuff.CRC(0, 32, 0x741B8CD7, 0xFFFFFFFF, 1, 1,
0x00000000))
wlog
"CRC-32/MPEG-2", hex$(0x0376E6E7), hex$(IObuff.CRC(0, 32, 0x04C11DB7, 0xFFFFFFFF, 0, 0,
0x00000000))
wlog
"CRC-32/XFER", hex$(0xBD0BE338), hex$(IObuff.CRC(0, 32, 0x000000AF, 0x00000000, 0, 0,
0x00000000))
|
These bit operations provide low-level control
over the buffer's contents, enabling manipulation of individual
bits in each byte.
Get the Value of a
Specific Bit in a Byte
IObuff.bit(buff_num,
position, bit)
●
Parameters:
○
buff_num:
The ID of the buffer (0–4).
○
position:
The byte position in the buffer to examine.
○
bit:
The bit position within the byte (0–7).
■ 0 is
the least significant bit (rightmost bit).
■ 7 is
the most significant bit (leftmost bit).
●
Return Value:
○ The
value of the specified bit within the byte.
■
Returns 0 if the bit is clear (0).
■
Returns 1 if the bit is set (1).
●
Behaviour:
○
Extracts the bit value from the specified byte in the buffer.
○ Does
not modify the buffer content.
Example:
IOBUFF.DIM(0,
2)
' Allocate buffer 0 with 2
bytes.
IOBUFF.WRITE(0,
0, &hF0)
' Write byte 240 (hex F0) at position
0.
PRINT
IOBUFF.BIT(0, 0,
7)
' Outputs: 1 (bit 7 of 0th byte is
set).
PRINT
IOBUFF.BIT(0, 0,
3)
' Outputs: 0 (bit 3 of 0th byte is
clear).
|
Set a Specific Bit
in a Byte
●
Parameters:
○
buff_num:
The ID of the buffer (0–4).
○
position:
The byte position in the buffer where the bit will be set.
○
bit:
The bit position (0–7) to be set to 1.
■ 0 is
the least significant bit (rightmost bit).
■ 7 is
the most significant bit (leftmost bit).
●
Return Value:
○ The
value of the bit after setting (should always return 1).
○ The
return value is ignored if used as a command.
●
Behaviour:
○ Sets
the specified bit in the specified byte of the buffer to 1.
○ Does
not affect other bits in the byte.
○ The
function returns 1 but this is typically ignored when used as a
command.
Example:
IOBUFF.DIM(0,
1)
' Allocate buffer 0 with 1
byte.
IOBUFF.WRITE(0,
0, &h01)
' Write byte 1 (hex 01) at position
0.
PRINT
IOBUFF.SETBIT(0, 0,
7)
' Set bit 7 in byte 0. Returns:
1.
PRINT
IOBUFF.BIT(0, 0,
7)
' Outputs: 1 (bit 7 is now
set).
|
Clear a Specific
Bit in a Byte
●
Parameters:
○
buff_num:
The ID of the buffer (0–4).
○
position:
The byte position in the buffer where the bit will be cleared.
○
bit:
The bit position (0–7) to be cleared to 0.
■ 0 is
the least significant bit (rightmost bit).
■ 7 is
the most significant bit (leftmost bit).
●
Return Value:
○ The
value of the bit after clearing (should always return 0).
○ The
return value is ignored if used as a command.
●
Behaviour:
○
Clears the specified bit in the specified byte of the buffer,
setting it to 0.
○ Does
not affect other bits in the byte.
○ The
function returns 0 but this is typically ignored when used as a
command.
Example:
IOBUFF.DIM(0,
1)
' Allocate buffer 0 with 1
byte.
IOBUFF.WRITE(0,
0, &hFF)
' Write byte 255 (hex FF) at position
0.
PRINT
IOBUFF.CLEARBIT(0, 0,
7) ' Clear bit 7 in byte 0. Returns: 0
(ignored).
PRINT
IOBUFF.BIT(0, 0,
7)
' Outputs: 0 (bit 7 is now
cleared).
|
Toggle a Specific
Bit in a Byte
●
Parameters:
○
buff_num:
The ID of the buffer (0–4).
○
position:
The byte position in the buffer where the bit will be toggled.
○
bit:
The bit position (0–7) to toggle
■ 0 is
the least significant bit (rightmost bit).
■ 7 is
the most significant bit (leftmost bit).
●
Return Value:
○ The
new value of the toggled bit (0 or 1).
○ The
return value is ignored if used as a command.
●
Behaviour:
○
Toggles the specified bit in the specified byte of the buffer:
■ If
the bit is 0, it becomes 1.
■ If
the bit is 1, it becomes 0.
○ Does
not affect other bits in the byte.
○ The
function returns the new value of the bit but this is typically
ignored when used as a command.
Example:
IOBUFF.DIM(0,
1)
' Allocate buffer 0 with 1
byte.
IOBUFF.WRITE(0,
0, &h0F)
' Write byte 15 (hex 0F) at position
0.
PRINT
IOBUFF.TOGGLEBIT(0, 0,
3) ' Toggle bit 3 in byte 0. Returns:
0.
PRINT
IOBUFF.BIT(0, 0,
3)
' Outputs: 0 (bit 3 is now
toggled).
|
Copy Data from One Buffer to
Another
IObuff.copy(dest_buff_num
[,pos]) , (source_buff_num, [,
start [, size]])
●
Parameters:
○
dest_buff_num:
The ID of the destination buffer (0–4) where the data will be
copied to.
○
pos:
(optional) The position within the destination buffer where the
copy will begin.
Defaults to 0 if not specified.
○
source_buff_num:
The ID of the source buffer (0–4) from which the data will be
copied.
○
start:
(optional) The starting byte in the source buffer from where
copying will begin.
Defaults to 0 if not specified.
○
size:
(optional) The number of bytes to copy from the source
buffer.
If omitted, it will copy from the start position to the end of the
source buffer.
●
Return Value:
○ The
number of bytes successfully copied to the destination buffer.
○ If
used as a command, the return value is ignored.
●
Behaviour:
○
Copies data from a source buffer to a destination buffer.
○ If
start and size are specified, only the selected portion of the
source buffer will be copied.
○ If
pos is specified, it determines where in the destination buffer the
data will be copied to.
○ The
content of the destination buffer is replaced or modified by the
copied data, depending on the pos value.
○ The
copy operation automatically resizes the destination buffer if the
size exceeds its capacity.
Example:
IOBUFF.DIM(1,
10)
' Allocate 10 bytes for buffer 1
(source).
IOBUFF.WRITE(1,
0, &h01) ' Write byte 1 at position 0 in buffer
1.
IOBUFF.WRITE(1,
1, &h02) ' Write byte 2 at position 1 in buffer
1.
IOBUFF.COPY(0,
0), (1, 0, 2) ' Copy 2
bytes from buffer 1 (starting from position 0) to buffer 0
(starting at position 0).
PRINT
IOBUFF.TOHEX$(0)
' Outputs: "0102" (2 bytes copied to
buffer 0).
|
UDP - use the remote controller APP for IOS
devices (iphone and Ipad)

' I/O buffers example using the RCWController
' available in the IOS app store.
' It uses by default the port 10000
' The APP sends a block of 10 bytes that
' will be printed in the console on the same line
udp.begin 10000
' define the place where jump on message reception
onudp received
wait
received:
' read the incoming data in the buffer 0
udp.read_iobuff(0)
size
= iobuff.len(0)
print
"received "; size; "
bytes"
for z
= 0 to 9
' read and print 1 byte at the time on
the same line
print iobuff.read(0, z),
next z
Print
' print an empty line
return
|
File read and transfer to the serial port
by blocks
' I/O BUFFERS example using files
' read a file in blocks of 512 characters
' and send them to the serial port (print)
fileName$
= "/data8.txt"
block_size
= 512 '
size of the block to be read
file_size
= file.size(fileName$)
print
"File size "; file_size
print file_size
for z
= 0 to file_size - 1 step
block_size
file.read_iobuff(0), fileName$, z, block_size
' send the block on the serial port
(print)
serial.write_iobuff(0)
next
|
Serial port data logger
' I/O BUFFERS example to create a serial data logger
' receive bytes from the serial port and
' write them into the file /mylog.txt
' all the characters will be recorded
' including the ASCII 0 (NUL)
filename$
= "/mylog.txt"
' define the place where jump on message reception
onserial received
wait
received:
' waits for 10 millisec giving time to receive all the
data
pause 10
' read the incoming data in the buffer 0
serial.read_iobuff(0)
size
= iobuff.len(0)
print
"received "; size; "
bytes"
' appends the received data to the file
file.append_iobuff(0),
filename$
return
|

This diagram
shows pin mapping for the popular ESP32 DEV Board
module.
(*) pins GPIO6 to
GPIO11 are not available.
Annex 32, as it
supports by default the M5stack wiring, assumes the following pins
already allocated/dedicated
PIN
|
FUNCTION
|
DESCRIPTION
|
32
|
PWM
BL TFT
|
Backlight TFT display
|
33
|
RST
TFT
|
RST
pin TFT
|
27
|
D/C
TFT
|
D/C
pin TFT
|
14
|
CS
TFT
|
CS
pin TFT
|
23
|
SPI
MOSI
|
SPI
MOSI pin (shared with SD and TFT)
|
19
|
SPI
MISO
|
SPI
MISO pin (shared with SD and TFT)
|
18
|
SPI
SCK
|
SPI
CLOCK pin (shared with SD and TFT)
|
4
|
CS
SDCARD
|
CS
pin SDCARD
|
0
|
CS
TFT TOUCH
|
CS
pin Touchscreen (from the TFT)
|
|
|
|
3
|
RX0
|
Serial Port RX pin
|
1
|
TX0
|
Serial Port TX pin
|
|
|
|
25
|
SPEAKER
|
Speaker or mono audio output
|
21
|
SDA
I2C
|
I2C
SDA pin
|
22
|
SCL
I2C
|
I2C
SCL pin
|
|
|
|
2
|
I2S
DATA
|
Audio
DAC I2S DATA pin
|
5
|
I2S
BCLK
|
Audio
DAC I2S BCLK pin
|
26
|
I2S
LRCK
|
Audio
DAC I2S LRCK pin
|
16
|
PSRAM
|
Optional PSRAM
|
17
|
PSRAM
|
Optional PSRAM
|

Pin numbers
correspond directly to the ESP32 GPIO pin numbering.
The function of the
pin (input / output) must be defined before using the function
PIN.MODE as below :
To define the pin 5
as input :
PIN.MODE 15,
INPUT
To define the pin 4
as input with a pullup:
PIN.MODE 4,
INPUT, PULLUP
To define the pin 4
as input with a pulldown:
PIN.MODE 4,
INPUT, PULLDOWN
To define the pin 2
as output
PIN.MODE 2,
OUTPUT
To define the pin 2
as output open collector
PIN.MODE 2,
OUTPUT, 1
Pins may also serve
other functions, like Serial, I2C, SPI.
These functions are
normally activated by the corresponding library.
The value from a
pîn can be read as shown below :
A
= PIN(5)‘ read from GPIO5 pin
The pin value can
be set as below
PIN(2)=
0
‘
set 0 on the GPIO2
pin
The pin value (0 or
1) can also be easily toggled by subtracting it from 1 (because
1-0=1 and 1-1=0), eg:
PIN(2)=
1 -
PIN(2)‘
toggles the value of GPIO2
pin
This part is applicable only
to the “classic” ESP32 as the other members of the family have
different H/W characteristics and
Although pin numbers can be from 0 to 39, gpio pins
6 to 11 should not be used because they are connected to
flash memory chips on most modules. Trying to use these pins as IOs
will likely cause the program to crash.
Pins 34 to 39 are
INPUT only and cannot be configured as
PULLUP or
PULLDOWN.
Pins 0 to 33 can be
INPUT,
OUTPUT,
INPUT, PULLUP or
INPUT, PULLDOWN.
Note:
If the module is equipped with PSRAM, the gpio pins
16 and 17 are reserved and must not be used.
The command
PIN.STRENGTH can be used to define the drive capability
of the output pins from a scale from 0 to 3.
For example, the
following command set the pin 15 with a drive capability of 2.
The ESP32 provides four drive strength levels for its GPIO
pins:
●
0: Weakest drive strength, approximately 5 mA.
●
1: Low drive strength, approximately 10 mA.
●
2: Medium drive strength, approximately 20 mA.
●
3: Maximum drive strength, approximately 40 mA.
Annex
supports two commands for serially shifting data:
-
PIN.SHIFTOUT for sending data
-
PIN.SHIFTIN for receiving data.
Both commands
allow control over bit order, bit count, and timing delays.
These commands are
in particular useful to control external shift registers or simple
SPI bus devices.
The
PIN.SHIFTOUT command is used to send data out serially
through a specified data pin. It shifts out data bits one at a
time, synchronised with a clock signal. The command allows you to
specify the order in which bits are shifted (least significant bit
first or most significant bit first), the number of bits to shift,
and the timing delay between each bit. This command drives the data
pin high or low according to the current bit in the data, and
toggles the clock pin to indicate when each bit should be read by
the receiving device.
Syntax:
PIN.SHIFTOUT
pin_data,
pin_clk, data [, bit_order] [, nb_bits] [,
delay_us]
Parameters:
●
pin_data:
○
Description: GPIO pin number used for the data line.
●
pin_clk:
○
Description: GPIO pin number used for the clock line that
synchronises the data transfer.
●
data
:
○
Description: Data to be shifted out.
●
Bit_order
(optional):
○
Description: Specifies the bit order for shifting data.
Possible values:
■
0
(default) : LSBFIRST Least Significant Bit first.
■
1
: MSBFIRST Most Significant Bit first.
●
Nb_bits
(optional):
○
Description: Number of bits to shift out from the data.
Default is 8 bits.
●
Delay_us
(optional):
○
Description: Delay in microseconds between each bit shift.
Default is 1 microsecond.
Details:
● This
command uses critical section management to ensure atomic
operations during the data shift process. However, because it
relies on software delays, the timing may not be very precise,
particularly for delays shorter than 10 microseconds
●
Bit Order: The bit order determines whether the least
significant bit (LSBFIRST) or the most significant bit (MSBFIRST)
is shifted out first.
●
Number of Bits: Specifies how many bits from the data value
will be shifted out. If not specified, the default is 8 bits.
●
Delay: Introduces a delay between the setting of the data
pin and toggling of the clock pin to control the timing of the data
shift.
Example:
PIN.SHIFTOUT 13, 14,
0xFF ' Shift out 8 bits
from data 0xFF
PIN.SHIFTOUT 13, 14,
0xFF, 1' Shift out 8 bits from data
0xFF with MSBFIRST
PIN.SHIFTOUT 13, 14,
0xFFFF, 1, 16, 2 ' Shift out 16
bits from data 0xFFFF with MSBFIRST, 2 µs
delay
|
The
PIN.SHIFTIN function is used to receive data serially
through a specified data pin. It shifts in data bits one at a time,
using a clock signal to determine when to sample the data pin.
Similar to
PIN.SHIFTOUT, it allows you to specify the bit order,
the number of bits to shift, and the timing delay between each bit.
This function reads the state of the data pin in sync with
the clock signal, capturing each bit as it arrives and storing it
in a variable.
Syntax:
PIN.SHIFTIN(
pin_data,
pin_clk [, bit_order] [, nb_bits] [, delay_us] )
Parameters:
●
pin_data:
○
Description: GPIO pin number used for the data line.
●
pin_clk
:
○
Description: GPIO pin number used for the clock line that
synchronises the data reading.
●
Bit_order
(optional):
○
Description: Specifies the bit order for shifting data.
Possible values:
■
0
(default) : LSBFIRST Least Significant Bit first.
■
1
: MSBFIRST Most Significant Bit first.
●
Nb_bits
(optional):
○
Description: Number of bits to read from the data line.
Default is 8 bits.
●
Delay_us
(optional):
○
Description: Delay in microseconds between each bit read.
Default is 1 microsecond.
Details:
● This
command uses critical section management to ensure atomic
operations during the data shift process. However, because it
relies on software delays, the timing may not be very precise,
particularly for delays shorter than 10 microseconds
●
Bit Order: Determines whether the least significant bit
(LSBFIRST) or the most significant bit (MSBFIRST) is read
first.
●
Number of Bits: Specifies how many bits will be read from
the data line. If not specified, the default is 8 bits.
●
Delay: Introduces a delay between each bit read, allowing
for control over timing and synchronisation.
Example:
A
= PIN.SHIFTIN(21, 22)
' Shift in 8 bits from data pin 21 with
clock pin 22
B
= PIN.SHIFTIN(13, 14, 1) ' Shift in 8
bits from data pin 13 with clock pin 14, reading
MSBFIRST
C
= PIN.SHIFTIN(13, 14, 1, 16, 2) ' Shift
in 16 bits from data pin 13 with clock pin 14, reading MSBFIRST, 2
µs delay
|
The
INTERRUPT command permits to trigger an event when the
signal on an input pin changes.
The interrupt is
triggered BOTH when the signal goes from LOW to HIGH and HIGH to
LOW.
Therefore a
momentary pulse actually generates 2 interrupts which need testing
for Hi or Lo as appropriate.
Example:
pin.mode 12,
input ' set pin 12 as input
interrupt 12, change_input
' set interrupt on pin 12
wait
change_input:
if pin(12)
= 0 then return ' if the pin is low, returns back
print "The pin changed to HIGH"
Return
|
It is possible to
add an optional parameter, mode,
that specify if the interrupt must be generated on the rising edge,
the falling edge or on change:
Syntax:
INTERRUPT pin_no,
{OFF | label} [, mode]
Parameters:
- pin_no: The input
pin number for which the interrupt is being defined. It must be an
integer value ranging from 0 to the maximum pin number supported by
the specific variant of the ESP32 (-s2, -c3, -s3).
- label: The branch
label to which the program will jump when the designated input pin
signal changes. It must be a valid label in the program's
context.
- OFF: Use this
keyword to remove the interrupt associated with the specified input
pin.
- mode (optional):
An integer parameter or keyword specifying the trigger condition
for the interrupt. It can take one of the following values:
- 1, RISING:
Rising edge trigger
- 2,
FALLING: Falling edge trigger
- 3, CHANGE:
Any change in signal trigger (default if 'mode' parameter is
omitted)
Examples:
-
To set up an interrupt that jumps to the 'PIN5_CHANGE' label when a
rising edge is detected on pin 5:
INTERRUPT 5,
PIN5_CHANGE, RISING
-
To remove the interrupt associated with pin 5:
INTERRUPT 5,
OFF
-
To set up an interrupt that jumps to the 'PIN13_TRANSITION' label
when any change is detected on pin 13:
INTERRUPT 13,
PIN13_TRANSITION , CHANGE
-
To set up an interrupt without specifying the trigger mode
(defaulting to any change in signal) that jumps to the
'PIN7_UPDATE' label when pin 7 signal changes:
INTERRUPT 7,
PIN7_UPDATE
Note:
-
Interrupts can provide a way to respond to external events
asynchronously.
-
The optional 'mode' parameter allows you to customize the trigger
condition for the interrupt to match your specific application
requirements.
The
input pin (pin_no) must be previously configured as an input before
setting up the interrupt.
Ensure
that the specified 'pin_no' and 'label' are valid within the scope
of your program.
The
maximum pin number supported by the ESP32 variant should be
considered based on the specific model (-s2, -c3, -s3).
Annex32 has 8 ADC
pins with 12 bits resolution which are available to users.
The function
ADC(pin)
can be used to read voltage on the pins defined in the table
below.
GPIO Pins Available as
Analog Input
|
32
|
33
|
34
|
35
|
36
|
37
|
38
|
39
|
To read the voltage applied at the pin, the
function ADC can be used as below :
print
ADC(39)' read voltage
from the pin 39
The voltage range is
0 ... 3.3V and the corresponding range returned by the function is
0 … 4095.
NOTE: When using the
function
ADC,the pin is automatically configured as an Analog
Input
Annex32
supports an additional ESP32 feature, the capacitive
touch.
With this
feature, it is possible to activate inputs with your fingers with
just one wire attached to the pin.
The
function
PIN.TOUCH(pin)
can be used to read the touch
value on the pins defined in the table below.
GPIO Pins Available as Touch
Input
|
0
|
2
|
4
|
12
|
13
|
14
|
15
|
27
|
32
|
33
|
The
function
PIN.TOUCH(pin)
returns a value that drops as soon
as the pin is touched.
Normal values
are around 70 when not touched and lower than 20 when
touched.
'Pin Touch
example
'Place a
wire on pin 13 and look how the value changes when touching
it
while
1
print pin.touch(13)
pause 100
wend
end
|
Annex32 has 2 DAC output pins with 8
bits resolution which are available to users.
This function is available only on the
pin GPIO25 and GPIO26
The function
PIN.DAC pin,
value can be used to set the output voltage on the
pin.
The output voltage is approximately 0V @
value=0 and 3.3V @ value=255
'DAC output
example
PIN.DAC 25,
128 'Set the pin
25 at ~1.65V
PIN.DAC 26,
64 'Set the pin
26 at ~0.82V
|
NOTE: When using the command
PIN.DAC,the pin is automatically configured as an
Analog Output
The ESP32 contains several H/W interfaces that
can be controlled by Annex32 WI-Fi using specific commands and
functions.
This functionality permits to control the
output duty cycle of any pin, acting like an analog output.
There are 16 channels available where each
channel can be connected to any output pin.
To use it, the function must first be
configured using the command
PWM.SETUP and then the value can be set using the
command
PWM.OUT.
The frequency and the
resolution can be defined individually for each channel.
The resolution can be from
1 to 15 bits.
The maximal frequency is
80000000 / 2^resolution
This table resumes the
maximal frequency available in function of the resolutions and the
associated range:
RESOLUTION (BITS)
|
MAX FREQUENCY
|
VALUE RANGE
|
1
|
40000000
|
0 ... 1
|
2
|
20000000
|
0 ... 3
|
3
|
10000000
|
0 ... 7
|
4
|
5000000
|
0 .. 15
|
5
|
2500000
|
0 .. 31
|
6
|
1250000
|
0 … 63
|
7
|
625000
|
0 … 127
|
8
|
312500
|
0 … 255
|
9
|
156250
|
0 … 511
|
10
|
78125
|
0 … 1023
|
11
|
39063
|
0 … 2047
|
12
|
19531
|
0 … 4095
|
13
|
9766
|
0 … 8191
|
14
|
4883
|
0 … 16383
|
15
|
2441
|
0 … 32767
|
All the output pins can be
used for the PWM (the pins from GPIO0 to GPIO33).
As there are 16 channels,
up to 16 individual output pins can be used.
If using the M5Stack, the
channels 0 and 7 are already reserved and attached to the pins 25
and 32.
In this case the channels
0 and 7 must be avoided.
To setup an output pin as
a PWM output the following command must be used :
PWM.SETUP
pin, channel,
default_value, [,frequency] [,resolution]
For example, to define a
PWM output at 5KHz with 12 bits of resolution on the pin GPIO5 the
command is :
PWM.SETUP 5, 1,
2048, 5000, 12 ‘ pin 5, channel 1, output value at 2048
(50%), 5KHz, 12 bits
As the resolution is set
at 12 bits, the range will be from 0 to 4095 (hence 2048 is
50%).
To define a PWM output at
10KHz with 8 bits on the pin GPIO22, the command is :
PWM.SETUP 22, 2,
128 ‘ pin 22, channel 2, value 128 ( 50%) , freq
10 KHz (default), resolution 8 bits (default)
As soon as the command
PWM.SETUP is done, the PWM output can simply be changed with the
command :
For example, the
command
PWM.OUT 1,
1000
Set the channel 1
(associated with the pin 5 in the previous command) at 1000.
And the command
PWM.OUT 2, 10
Set the channel 2 (associated with the pin 22
in the previous command) at 10
To disconnect the pin from the PWM output the
command is :
PWM.SETUP pin,
OFF.
For example the command
PWM.SETUP 5,
OFF
Disconnect the pin 5 fro the PWM
NOTE for the
M5stack:
The channel 0 is
dedicated to the internal speaker (pin 25)
The channel 7 is
dedicated to the TFT backlight (pin 32)
This functionality exposes the ability to
control RC (hobby) servo motors.
There are no special commands dedicated as the
servo can simply be used by setting a PWM pin with a 50Hz
frequency.
For example, the following command :
PWM.SETUP 17, 1,
150, 50, 12
Defines the pin 17 with the pwm channel 1 with
a default value of 150 (frequency at 50 Hz and resolution at 12
bits).
The output can then be set with the
command
PWM.OUT 1,
307‘ channel 1 set at 90°
A typical servo motor expects to be updated
every 20 ms with a pulse between 1 ms and 2 ms, or in other words,
between a 5 and 10% duty cycle on a 50 Hz waveform. With a 1.5 ms
pulse, the servo motor will be at the natural 90 degree position.
With a 1 ms pulse, the servo will be at the 0 degree position, and
with a 2 ms pulse, the servo will be at 180 degrees. You can obtain
the full range of motion by updating the servo with any value in
between.

Using a 12 bits resolution (max value = 4095
for 20 msec pulse (1/50 Hz)), the theoretical values should be
:
0° -> 1 msec -> 1/20 * 4096 =
205
90° -> 1.5 msec -> 1.5/20 * 4096 =
307
180° -> 2 msec -> 2/20 * 4096 =
409
Generating Tones
This section introduces the functionality of
generating tones using the
PWM.TONE command.
This command provides the means to create
tones using the PWM.
Syntax
The
PWM.TONE command follows a concise syntax:
PWM.TONE channel,
frequency [, duration_ms]
-
channel: Selects a specific PWM channel for tone output.
-
frequency: Specifies the frequency of the generated tone in Hertz
(Hz).
-
duration_ms: (Optional) Defines the duration of the tone in
milliseconds (ms). If omitted, the tone will play indefinitely.
Practical Examples
Example 1:
Single Tone
To generate a continuous tone at 1000 Hz on
channel 1, use:
PWM.TONE 1,
1000
This command establishes a steady 1000 Hz tone
on channel 1.
Example 2:
Timed Tone
For a tone lasting 200 ms at 2000 Hz on
channel 2, apply:
PWM.TONE 2, 2000,
200
Channel 2 will produce a tone at 2000 Hz for a
duration of 200 milliseconds.
Example 3:
Stopping a Tone
To halt an ongoing tone on channel 1, use the
following command
PWM.TONE 1,
0 command
Prior to using PWM.TONE, ensure proper channel
setup using the PWM.SETUP command, for example using
PWM.SETUP 5, 1,
0. (pin 5, channel1, default output at 0)
Be mindful of the channel's frequency range
and resolution limits.
I²S (Inter-IC Sound), is an electrical serial
bus interface standard used for connecting digital audio devices
together. It is used to communicate PCM audio data between
integrated circuits in an electronic device.
The I²S bus separates clock and serial data
signals, resulting in a lower jitter than is typical of
communications systems that recover the clock from the data
stream.
Despite the name similarity, I²S is
unrelated to the bidirectional I²C (I2C) bus.
The bus consists of three lines:
Bit clock line
-
Typically called "bit clock (BCLK)". PIN GPIO5
Word clock line
-
Typically called "left-right clock (LRCLK)" or “Word Select
(WSEL)”. PIN GPIO26
Data line
-
Typically called "serial data (SD)". Can also be called (SDIN,
SDOUT or DATA). PIN GPIO2
The typical use of the I2S is to connect an
external DAC to provide a High Quality stereo sound output.
Using the PLAY.xxx commands, it will be
possible to play MP3 and WAV files directly from the disk.
Any generic I2S DAC can be used.
Annex32 has been successfully tested with the
PC5102A and the UDA1334A
UDA1334A I2S DAC

PCM5102A I2S DAC
NOTE:
This module requires the following setting
(solder joints)
Component side:
Next to the sck connection
Back side:
1 set to L
2 set to L
3 set to H
4 set to L

It is now also possible to use the CODEC
ES8388 using the command
OPTION.ES8388
The M5stack contains an internal speaker
connected, via an audio amplifier, to the pin GPIO25.
This permits the generation of audio signals
using the internal 8 bits DAC.
Using the PLAY.xxx commands, it will be
possible to play MP3 and WAV files directly from the disk.
It is possible to connect an earphone directly
on the output between the pin GPIO25 and the ground but the best is
to connect a little audio amplifier.
NOTE: it is recommended to put a capacitor
( ~100nF) between the GPIO25 and the audio amplifier in order to
remove the DC component from the audio signal.
It is also possible to generate the sound
using a SPDIF output, in both cable or fiber optic format.
For that simple define the
PLAY.SETUP 3,
[buff_size, mono]
The pin for the output is the one defined for
the I2C_ Dout
The I²C bus allows the module to connect to
I²C devices.
I²C uses only two bidirectional open-drain
lines, Serial Data Line (SDA) and Serial Clock Line (SCL), pulled
up with resistors (typically 4.7K to 10K).
The I²C has a 7 bit address space permitting,
theoretically, to connect up to 126 I/O devices.
The maximal number of nodes is limited by the
address space and also by the total bus capacitance of 400 pF,
which restricts practical communication distances to a few meters.
The relatively high impedance and low noise immunity requires a
common ground potential, which again restricts practical use to
communication within the same PC board or small system of
boards.
The current implementation is master mode @
100Khz by default.
The SDA and SCL pins can be freely defined
using the command
I2C.SETUP sda_pin,
scl_pin.
For example, to define pins
21(SDA) and 22(SCL) the command is :
I2C.SETUP 21,
22
It is important to provide correct pullup
resistors on these lines; values between 4.7K to 10K should be
appropriate.
The commands available are :
I2C.BEGIN,
I2C.END, I2C.REQFROM, I2C.SETUP, I2C.WRITE
The functions available are :
I2C.LEN,
I2C.READ, I2C.END
There are also other advanced
functions / commands to simplify exchanges with the i2c
bus.
The advanced commands available
are :
I2C.READREGARRAY,
I2C.WRITEREGBYTE,I2C.WRITEREGARRAY
The advanced functions available are :
I2C.READREGBYTE
The I2C bus can also
be used with the IO Buffers ( look at the dedicated chapter)
As all the devices can have a "not well"
determined address, please find here a little i2c scanner program
which returns the address of all the devices found connected to the
bus
'I2C Address
Scanner
'print in the
console the address of the devices found
I2C.SETUP
21, 22
' set I2C port on pins 21 and
22
for
i
= 0 to 120
i2c.begin i
if i2c.end = 0
then
print "found "; i , hex$(i)
pause 10
end if
next
i
end
|
This is an example of connection of a module
with PCF8574 bought on Ebay at less than 2€

This drawing shows
how this module must be connected to the ESP32.
It provides 8
digital inputs or outputs.

This is an example of code that "drives" this
module:
I2C.SETUP 21,
22 ' set I2C
port on pins 21 and 22
device_address = 32 'set to
module i2c address
'Write from 0
to 255 on the module
'Each pin
will blink at different frequency
For
i
= 0 to 255
PCF8574_write
i
Next
i
'Read all the
inputs
'The result
is printed into the serial console
' put all the
inputs at pullup state
PCF8574_write
255
r
= 0
For
i
= 0 to 1000
PCF8574_read r
Print r
Next
i
End
sub
PCF8574_write(x)
i2c.begin
device_address
i2c.write x
i2c.end
end
sub
sub
PCF8574_read(x)
i2c.reqfrom device_address,
1
x
= i2c.read
i2c.end
end
sub
|
This is another example of connection of a
module with ADS1115 bought on Ebay at less than 2€.
This is a 16 Bit ADC 4 channel Module with
Programmable Gain Amplifier.


Because the module already contains two 10K
I2C pullups, no external resistors are required

As this device is quite simple to interface,
it can be directly driven using a “driver” written in basic.
' ADS1115
Driver for Annex
' datasheet
http://www.ti.com/lit/ds/symlink/ads1115.pdf
' ADS1115
Registers
ADS1115_ADDRESS
= &h48
ADS1115_CONV_REG
= 0 : ADS1115_CONF_REG = 1
ADS1115_HI_T_REG
= 2 : ADS1115_LO_T_REG = 3
i2c.setup
21, 22
' set I2C bus
' Set the
ADS1115 with :
'
AINp = AIN0 and AINn = AIN1
'
FSR = ±4.096 V
'
16 SPS
ADS1115_setup 0, 1,
1
' scale in
volt
scale = 4.096 /
32768
v = 0
for
i
= 0 to 100000
ADS1115_read v
' read from the
module
print v *
scale
next
i
end
'---------------------------------------------------------
' INPUT
MULTIPLEX :
' AINp is
the input positive
' AINn is
the input negative
'0 : AINp =
AIN0 and AINn = AIN1
'1 : AINp =
AIN0 and AINn = AIN3
'2 : AINp =
AIN1 and AINn = AIN3
'3 : AINp =
AIN2 and AINn = AIN3
'4 : AINp =
AIN0 and AINn = GND
'5 : AINp =
AIN1 and AINn = GND
'6 : AINp =
AIN2 and AINn = GND
'7 : AINp =
AIN3 and AINn = GND
'GAIN
'0 : FSR =
±6.144 V
'1 : FSR =
±4.096 V
'2 : FSR =
±2.048 V
'3 : FSR =
±1.024 V
'4 : FSR =
±0.512 V
'5 : FSR =
±0.256 V
'6 : FSR =
±0.256 V
'7 : FSR =
±0.256 V
'DATA
RATE
'0 : 8
SPS
'1 : 16
SPS
'2 : 32
SPS
'3 : 64
SPS
'4 : 128
SPS
'5 : 250
SPS
'6 : 475
SPS
'7 : 860
SPS
sub
ADS1115_setup(inp_mux, gain, rate)
local conf
conf = (inp_mux
<< 12) or
(gain << 9)
or (rate << 5)
or 3 ' +
disable comp
'use the IO Buffer 0 for
writing
iobuff.dim(0,2)
= (conf and
&hff00) >> 8
, conf and &hff
i2c.write_iobuff(0),
ADS1115_ADDRESS, ADS1115_CONF_REG
end
sub
sub
ADS1115_read(ret)
'use the IO Buffer 0 for
reading
i2c.read_iobuff(0),
ADS1115_ADDRESS, ADS1115_CONV_REG, 2
if iobuff.len(0)
= 0 then
print "No
communication"
ret
= 0
else
ret
= iobuff.read(0, 0)
<< 8 + iobuff.read(0, 1)
end
if
if ret >
32768 then ret = ret -
65536
end
sub
|
This is another example for connecting an I2C
module, an MCP20S17 bought on Ebay at less than 2€.
This module provides 16 GPIO pins that can be
used as digital inputs or outputs.

Because the module already contains two 10K
I2C pullups, no external resistors are required

As this device is quite simple to interface,
it can be directly driven using a “driver” written in basic.
' MCP23017
Driver for Annex
' datasheet
http://ww1.microchip.com/downloads/en/DeviceDoc/20001952C.pdf
I2C.SETUP
21, 22
' set I2C port on pins 21 and
22
device_address
= 32 'set to module i2c address
'MCP23017
internal registers
IODIRA
= 0 : IODIRB
= 1 : IPOLA = 2 : IPOLB = 3
GPINTENA = 4 : GPINTENB = 5 : DEFVALA =
6 : DEFVALB = 7
INTCONA = 8 : INTCONB = 9 : IOCONA = 10 : IOCONB = 11
GPPUA
= 12 : GPPUB
= 13 : INTFA
= 14 : INTFB
= 15
INTCAPA = 16 : INTCAPB =
17 : GPIOA = 18 :
GPIOB =
19
OLATA
= 20 : OLATB
= 21
i2C.WriteRegByte
device_address, IOCONA,
&h08 ' init MCP23S17 with bit HAEN
i2C.WriteRegByte
device_address, IODIRA,
&hFF ' all PORT A pins as input
i2C.WriteRegByte
device_address,
GPPUA, &hff ' set PORT A pullup on all
pins
i2C.WriteRegByte
device_address, IODIRB,
&h00 ' all PORT B pins as output
r = 0
for
z
= 0 to 255
I2C.WriteRegByte device_address, GPIOB, z
' pulse all GPIOB
pins
r = i2C.ReadRegByte(device_address, GPIOA) ' read
all GPIOA pins
print r
pause 100
next
z
|
The SPI bus allows
the module to connect to SPI devices.
The Serial
Peripheral Interface bus (SPI) is a synchronous serial
communication interface used for short distance communication
between devices.
SPI devices
communicate in full duplex mode using a master-slave architecture
where the ESP32 is the master. The ESP32 generates the frame for
reading and writing.
Multiple slave
devices are supported through selection with individual chip select
(CS) lines.
The SPI bus utilise four
logic signals:
SIGNAL
|
DESCRIPTION
|
I/O
PIN
|
SCLK
|
Serial
Clock (output from the ESP32)
|
GPIO18
|
MISO
|
Master
Input Slave Output (data input to the ESP32)
|
GPIO19
|
MOSI
|
Master
Output Slave Input (data output from the ESP32)
|
GPIO23
|
CS
|
Chip
Select (often active low, output from the ESP32)
|
Any
output pin, controlled automatically
|
Because these
pins are allocated by default, they may not not be available, by
default, to be used as generic GPIO pins.
For that the
command
SPI.STOP enable to recover the control on these I/O
pins
CS pin
As many devices can
be connected in parallel, sharing the same SCLK, MISO and MOSI
signals, each device is controlled individually using an individual
CS signal.
As Annex32
implements multitasking, in order to guarantee that the CS signal
is generated in phase with the data to be transferred, the CS pin
is managed automatically.
The command
SPI.CSPIN pin [,
polarity] permits the pin associated with the device to
be controlled. Additionally, it permits to define the
polarity as 0 = active low (default) and 1 = active high.
SPI
Mode: Polarity and Clock Phase
The SPI
interface defines no protocol for data exchange, limiting overhead
and allowing for high speed data streaming. Clock polarity (CPOL)
and clock phase (CPHA) can be specified as ‘0’ or ‘1’ to form four
unique modes to provide flexibility in communication between master
and slave as shown below :

If CPOL
and CPHA are both ‘0’ (defined as Mode 0) data is sampled at the
leading rising edge of the clock. Mode 0 is by far the most
common mode for SPI bus slave communication.
If CPOL
is ‘1’ and CPHA is ‘0’ (Mode 2), data is sampled at the leading
falling edge of the clock. Likewise, CPOL = ‘0’ and CPHA = ‘1’
(Mode 1) results in data sampled on the trailing falling edge and
CPOL = ‘1’ with CPHA = ‘1’ (Mode 3) results in data sampled on the
trailing rising edge.
The
table below summarizes the available modes.
Mode
|
CPOL
|
CPHA
|
0
|
0
|
0
|
1
|
0
|
1
|
2
|
1
|
0
|
3
|
1
|
1
|
The data can also
be sent MSB first or LSB first.
This is defined as
bit order and is MSB first by default
Even if the chip is
able to achieve 80Mhz, the maximum realistic SPI speed is
40Mhz.
The commands available are :
SPI.SETUP speed
[,data_mode [, bit_order]]
SPI.CSPIN pin [,
polarity]
The functions available are :
ret =
SPI.BYTE(byte)
a$ =
SPI.STRING$(data$,
len)
a$ =
SPI.HEX$(datahex$,
len)
As said
previously, because the ESP32 uses multitasking, it is
impossible to warrant the exclusive use of the SPI bus during the
execution of the script (it could be used by the SD card or the
TFT, for example).
For this reason, the
CS pin is managed internally by Annex directly by the SPI
functions.
This is defined with
the command
SPI.CSPIN pin [,
polarity]
The optional
parameter polarity
defines if the CS signal must be active low (0 = default) or active
high (1).
This command will set
the pin automatically as output.
The SPI bus can also
be used with the IO Buffers ( look at the dedicated chapter)
Look at the examples
below for more details:
This is an example of connection of a module
with 74HC595 bought on Ebay at less than 2€

This drawing shows
how this module must be connected to the ESP8266.
It provides 8
digital outputs.

This is an example
of code that "drives" this module:
'Write from 0
to 255 on the module
'Each pin
will blink at different frequency
spi.setup
100000
' set the SPI port at
100KHz
SPI.CSPIN 15,
1 ' defines the pin 15 as CS active
high
for
i
= 0 to 255
r
= spi.byte(i)
next
i
end
|
This is another example for connecting an SPI
module, an MCP23S17 bought on Ebay at less than 2€.
This module provides 16 GPIO pins that can be
used as digital inputs or outputs.



As this device is quite simple to interface,
it can be directly driven using a “driver” written in basic.
This is an example using the SPI pins and the
GPIO15 as CS signal
' MCP23S17 Driver for Annex
' datasheet
http://ww1.microchip.com/downloads/en/DeviceDoc/20001952C.pdf
spi.setup 1000000
'MCP23S17 SPI address
MCP23S17_ADDR
= &h40 '
assumes A2, A1, A0 to GND
'MCP23S17 internal registers
IODIRA
= 0 : IODIRB
= 1 : IPOLA = 2 : IPOLB = 3
GPINTENA
= 4 : GPINTENB = 5 : DEFVALA =
6 : DEFVALB = 7
INTCONA
= 8 : INTCONB
= 9 : IOCONA = 10 : IOCONB = 11
GPPUA
= 12 : GPPUB
= 13 : INTFA
= 14 : INTFB
= 15
INTCAPA
= 16 : INTCAPB = 17 : GPIOA = 18 : GPIOB = 19
OLATA
= 20 : OLATB
= 21
MCP23S17_WRITE
IOCONA, &h08 ' init MCP23S17 with bit HAEN
MCP23S17_WRITE
IODIRA, &h00 ' all PORT A pins as output
MCP23S17_WRITE
IODIRB, &hff ' all PORT B pins as input
MCP23S17_WRITE
GPPUB , &hff ' all PORT B pins as pullup
v
= 0
for i
= 0 to 255
for z
= 0 to 255
MCP23S17_WRITE GPIOA, z ' pulse all
GPIOA pins
MCP23S17_READ GPIOB, v '
read all GPIOB pins
print v
next z
next i
End
' function for read / write the MCP23S17
sub MCP23S17_WRITE(register,
value)
SPI.CSPIN
15
a
= SPI.byte(MCP23S17_ADDR)
a
= SPI.byte(register)
a
= SPI.byte(value)
end
sub
sub
MCP23S17_READ(register, value)
local a
SPI.CSPIN 15
a = SPI.byte(MCP23S17_ADDR or 1)
a = SPI.byte(register)
value = SPI.byte(0)
end
sub
|
A Controller Area Network (CAN bus) is a
robust vehicle bus
standard designed to allow microcontrollers
and devices to communicate with each other's applications without a
host computer.
It is a message-based
protocol, designed originally for multiplex
electrical wiring within automobiles to save on copper, but can
also be used in many other contexts.
The Annex32 implements the support for
standard CAN 2.0A (11-bit identifier) and CAN 2.0B (29-bit
identifier).
To interface with an external CAN BUS, the
ESP32 requires the use of a CAN transceiver like the
TJA1050, the MCP2551 or the SN65HVD230.
For example this module is based on the chip
TJA1050 and can be bought for around 1€ on the internet.

Annex32 supports the transmission and
reception of CAN BUS frames.
The bus can be initialised in NORMAL mode, NO
ACK mode and LISTEN ONLY mode
The following BUS speeds are supported 25, 50,
100, 125, 250, 500, 800, 1000 (Kbits / sec).
To use the CAN BUS, it must be initialised
before using the function
CAN.SETUP :
ret
= CAN.SETUP(speed, pin_tx, pin_rx, [can_mode [,
filter_code, filter_mask]])
where :
speed
is the bus speed in Kbit/sec and can be 25, 50, 100, 125, 250, 800,
1000
pin_tx
is the pin of the ESP32 used for the TX signal (connected to the
transceiver)
pin_rx
is the pin of the ESP32 used for the RX signal (connected to the
transceiver)
can_mode
can be 0 (NORMAL), 1 (NO ACK) or 2 (LISTEN ONLY). Optional,
defaults to 0 (NORMAL)
filter_code
is the reception filter code. Optional, defaults to &h00000000
(32 bits)
filter_mask
is the reception filter mask. Optional, defaults to &hFFFFFFFF
(32 bits)
The function returns 0 if OK or another value
in case of error
can_mode
represents how the ESP32 interfaces with the BUS
can_mode
|
DESCRIPTION
|
NORMAL
|
Normal operating mode where CAN controller can
send/receive/acknowledge messages
|
NO
ACK
|
Transmission does not require acknowledgment.
Use this mode for self testing
|
LISTEN ONLY
|
The CAN controller will not influence the bus
(No transmissions or acknowledgments) but can receive messages
|
filter_code
and filter_mask can be used to filter messages of a
particular ID.
Example:
ret
= CAN.SETUP(500, 4, 5, 1) 'Set the bus
at 500Kb/sec in NO ACK mode using the pins 4 and
5
Alternatively, the CAN BUS can be initialised
using the function
CAN.INIT; this function has the same functionality such
as the
CAN.SETUP but gives more control on the BUS timing
(for advanced users) :
ret
= CAN.INIT(pin_tx, pin_rx, can_mode, brp, tset_1,
tseg_2, sjw, triple_sampling, [filter_code,
filter_mask])
where :
pin_tx
is the pin of the ESP32 used for the TX signal (connected to the
transceiver)
pin_rx
is the pin of the ESP32 used for the RX signal (connected to the
transceiver)
can_mode
can be 0 (NORMAL), 1 (NO ACK) or 2 (LISTEN ONLY)
brp
is the Baudrate prescaler (i.e., APB clock divider) can be any even
number from 2 to 128
tset_1
is the Timing segment 1 (Number of time quanta, between 1 to
16)
tset_2
is the Timing segment 2 (Number of time quanta, 1 to 8)
sjw
is the Synchronization Jump Width (Max time quanta jump for
synchronize from 1 to 4)
triple_samp
can be 1 to enable the triple sampling when the CAN controller
samples a bit
filter_code
is the reception filter code. Optional, defaults to &h00000000
(32 bits)
filter_mask
is the reception filter mask. Optional, defaults to &hFFFFFFFF
(32 bits)
The function returns 0 if OK or another value
in case of error
Example:
PRINT
CAN.INIT(4,
5, 2, 8, 15, 4, 3, 0)
'Set the bus at 500Kb/sec in LISTEN
ONLY mode using the pins 4 and 5
The function
CAN.STOP permits to stop the driver disconnecting it
from the BUS :
ret
= CAN.STOP
The function returns 0 if OK or another value
in case of error
The function
CAN.WRITE permits to write a message on the BUS; the
message can be composed from 0 to 8 bytes.
ret
= CAN.WRITE( id, can_flags [,b0 [,b1 [,b2 [,b3 [,b4
[,b5 [,b6 [,b7 ]]]]]]]])
where :
id
is the ID of the message to be sent; must be 11 bits or 29 bits for
extended messages
can_flags
is used to indicate the type of
message transmitted/received.
b0 ...
b7 message
bytes. Any combination from 0 to 8 bytes can be specified
The function returns 0 if OK or 1 of
message not sent correctly
can_flags
represents the type of message transmitted/received.
can_flags
|
DESCRIPTION
|
0
|
No message flags (Standard Frame Format)
|
1
|
Extended Frame Format (29bit ID)
|
2
|
Message is a Remote Transmit Request
|
4
|
Transmit as a Single Shot Transmission
|
8
|
Transmit as a Self Reception Request
|
16
|
Message's Data length code is larger
than 8. This will break compliance with CAN2.0B
|
Example:
PRINT
CAN.WRITE(
&h12345678,
1, 10, 20, 30) 'Send an extended message with ID &h12345678
composed of 3 bytes (10, 20, 30)
The message can also be sent using the
IOBUFFERS with the function
CAN.WRITE_IOBUFF :
ret
= CAN.WRITE_IOBUFF(bufnum)
The function returns 0 if OK or 1 of
message not sent correctly
The iobuffer must be set before and must
contains from 5 to 13 bytes structured as below :
IOBUFFER
BYTE
|
DESCRIPTION
|
0
|
Message ID Byte 0 (Most significant byte)
|
1
|
Message ID Byte 1
|
2
|
Message ID Byte 2
|
3
|
Message ID Byte 3 (Least significant byte)
|
4
|
Can_flags defined as the previous table
|
5 to
12
|
Message bytes ( can span from 5 to 12 for
message bytes 0 to 8)
|
Another event,
ONCANBUS , has been included to determine when a CAN
message has been received.
ONCANBUS canbus_received
Inside this event, it is possible to read and
analyse the content of the message received.
When this event occurs, the following
functions are available :
CAN.IDENT
The function
CAN.IDENT that returns the ID of the message
received
Example:
id
= CAN.IDENT
CAN.FLAGS
The function
CAN.FLAGS that returns the flags of the message
received
Example:
flags
= CAN.FLAGS
CAN.LEN
The function
CAN.LEN that returns the length of the message received
(the content bytes)
Example:
ret
= CAN.LEN
CAN.BYTE
The content of the message can then be read
byte per byte using the function
CAN.BYTE :
ret
= CAN.BYTE(num)
Returns the content of the byte
num from the message received (the content bytes from 0
to 7)
CAN.READ_IOBUFF
The message can also be received using the
IOBUFFERS with the function
CAN.READ_IOBUFF :
ret
= CAN.READ_IOBUFF(bufnum)
Returns the number of bytes received (the
content)
This function “copies” the content of the
received buffer into the buffer bufnum
without any impact on the function
CAN.BYTE.
Example:
'CANBUS example
'init the canbus
'print can.setup(500, 26, 5, 1) ' speed, pin_tx,
pin_rx
' speed can be 25, 50, 100, 125, 250, 500 or 800
Kbits/sec
'can.setup can also have other optional arguments
'print can.setup(500, 4, 5, 0, &h00000000, &hffffffff) '
speed, pin_tx, pin_rx, mode, filter_code,
filter_mask
' the mode can be 0:normal, 1:no_ack_tx,
2:listen_only
print can.init(26,
5, 1, 8, 15, 4, 3, 1, &h0,
&hffffffff) ' pin_tx,
pin_rx, mode, brp, tset_1, tseg_2, sjw, triple_sampling,
filter_code, filter_mask
'prepare an iobuffer containing an iobuffer to be
sent
iobuff.dim(0,
13) = &h12,
&h34, &h56, &h78, 0 , &h33, &h44, &h55, &h66, &h77, &h88, &h99, &haa
'
id id id
id flag b0
b1 b2 b3
b4 b5 b6
b7
'defines the place where jumps when receiving CAN
messages
ONCANBUS
canbussi
for z
= 0 to 1000
' the message can be sent using
iobuffers
'print
can.write_iobuff(0)
'or directly using the command
write
print "tx "; can.write( z, 0, 0,
1,2,3,4,5,6,7,8)
'
id flag bytes 0 - 7
pause 1000
next z
print
"end sending"
wait
'can message reception routine
canbussi:
'the message can be extracted using these functions
print
"canbussi "; hex$(can.ident); " ";
can.flags; " "; can.len;
" bytes ";
'the content can be read byte per byte
for k
= 0 to 7
print can.byte(k),
next k
print
'or the message can be routed into an iobuffer and extracted byte
per byte
'print can.read_iobuff(1)
'print iobuff.len(1)
'print iobuff.read(1, 0), iobuff.read(1, 1),
iobuff.read(1, 2), iobuff.read(1, 3), iobuff.read(1,
4)
return
|
In addition to the previous
functions,Annex implements the support for up-to 32 (from 0 to 31)
dedicated reception buffers that can be read at any pace
individually.
Each buffer has its own filter
and mask and it can be polled without requiring the use of the
interrupt.
The filter / mask defined in
the
CAN.SETUP function will act as a global
filter and will be applicable to all the buffers.
When a new data arrives, it will
be filtered and stored in the corresponding buffer.
If an existing data is already
present, it will not be overridden (the new one will be discarded),
the reason is to avoid any change of data during the processing
phase.
To accept to receive new data,
the buffer must be released with the command
CAN.BUF_CLEAR(buf_num)
These are several additional
functions :
CAN..BUF_FILTER
ret =CAN.BUF_FILTER(buf_no,
code [,mask]) 'set the filter
example
ret =CAN.BUF_FILTER(0,
&h1234)
'defines the ID &h1234 for the buffer 0
ret =
CAN.BUF_FILTER(0,
&h1234, &hf)
'defines the ID &h1234 for the buffer 0 with a mask
of &hf .In this case the addresses accepted will be from
&h1230 to &h123f (last 4 bits at 1)
CAN.BUF_IDENT
ret =
CAN.BUF_IDENT(buf_no)
'returns the ident
CAN.BUF_LEN
ret =CAN.BUF_LEN(buf_no)
'returns the length of the data
received in the buffer
CAN.BUF_FLAGS
ret =
CAN.BUF_FLAGS(buf_no)
'returns the flags
CAN.BUF_BYTE
ret =
CAN.BUF_BYTE(buf_no,
byte_pos)
'returns the byte
CAN.BUF_CLEAR
ret =
CAN.BUF_CLEAR(buf_no)
'clear the buffer and returns 0
The
CAN.BUF_LEN can be used to determine if new
data has arrived and, when the processing of the data is
terminated, the buffer can be released using
CAN.BUF_CLEAR
Example:
'init the canbus
'can.setup can also have other optional arguments
print
can.setup(500,
26, 5, 0,
&h00000000,
&hffffffff)
' speed, pin_tx, pin_rx, mode, filter_code,
filter_mask
' the mode can be 0:normal, 1:no_ack_tx,
2:listen_only
print
can.BUF_FILTER(0,
&h123)
print
can.BUF_FILTER(1,
&h456)
print
can.BUF_FILTER(2,
&h789)
for
z
=
0
to
10000000
if
(can.BUF_LEN(0))
then
print
hex$(can.BUF_IDENT(0)),
can.BUF_FLAGS(0),
can.BUF_LEN(0),
can.BUF_BYTE(0,
0),
can.BUF_clear(0)
end
if
if
(can.BUF_LEN(1))
then
print
hex$(can.BUF_IDENT(1)),
can.BUF_FLAGS(1),
can.BUF_LEN(1),
can.BUF_BYTE(1,
0),
can.BUF_clear(1)
end
if
if
(can.BUF_LEN(2))
then
print
hex$(can.BUF_IDENT(2)),
can.BUF_FLAGS(2),
can.BUF_LEN(2),
can.BUF_BYTE(2,
0),
can.BUF_clear(2)
end
if
next
z
wait
|
The Remote Control Peripheral (RMT) module on the ESP32 is a
versatile and powerful feature designed to handle protocols that
require precise timing, such as infrared remote control
transmissions, LED strip control, and other time-sensitive
communication protocols. Unlike typical digital I/O operations, the
RMT module can generate and decode signals with highly accurate
timing, allowing it to handle various transmission standards with
minimal CPU involvement.
●
Precise timing control for generating and receiving signals
●
Flexible channel configuration
●
Support for continuous transmission using circular buffer mode
●
Carrier modulation and demodulation capabilities
The number of RMT channels, their configuration for transmission
(TX) and reception (RX), and the available buffer sizes depend on
the specific ESP32 chip variant:
ESP32
Variant
|
Total RMT
Channels
|
Buffer Size per
Channel
|
Total RMT
RAM
|
Memory
Management
|
Channel Sync
Capability
|
RX demodulation
Capability
|
ESP32
|
8
|
64 x 32-bit memory
blocks
|
512 x
32-bit
|
Each channel can use up to 64
memory blocks. Channels can share memory blocks if required. Memory
blocks are dynamically allocated to channels.
|
NO
|
NO
|
ESP32-S2
|
4
|
48 x 32-bit memory
blocks
|
192 x
32-bit
|
Each channel can use up to 48
memory blocks. Memory is dynamically allocated, and multiple blocks
can be assigned to a single channel.
|
YES
|
YES
|
ESP32-S3
|
8
4 TX Channels
(0-3)
4 RX Channels
(4-7)
|
48 x 32-bit memory
blocks
|
384 x
32-bit
|
Channels 0-3 are TX only, and
Channels 4-7 are RX only. Each channel can use up to 48 memory
blocks.
Memory allocation is dynamic,
and blocks can be shared among channels to optimise
usage.
|
YES
|
YES
|
ESP32-C3
|
4
2 TX Channels
(0-1)
2 RX Channels
(2-3)
|
48 x 32-bit memory
blocks
|
192 x
32-bit
|
Channels 0-1 are TX only, and
Channels 2-3 are RX only.
Each channel can use up to 48
memory blocks. Memory allocation is dynamic, and blocks can be
shared among channels to optimise usage.
|
YES
|
YES
|
The RMT module on each ESP32 chip variant uses a flexible memory
management system that allows memory blocks to be dynamically
assigned to individual channels based on the application's
needs:
- Memory
Blocks: Each channel is assigned a specific number of memory
items, which store 32-bit wide data per item. Depending on the
variant, each channel can use up to a maximum number of 48 or
64 items (a block). By default each channel is associated with a
single block.
- Dynamic Allocation: The allocation of
memory blocks to channels is dynamic, allowing a channel to be
configured to use multiple memory blocks based on the protocol
requirements. For example, a channel may need more memory blocks to
handle longer data sequences or more complex communication
protocols.
- Channel
Synchronisation: Some ESP32 variants support the
synchronisation between different RMT channels. This feature
enables precise coordination of signal generation across multiple
channels, which is especially useful for controlling multiple
devices simultaneously or handling complex communication protocols
that require synchronised timing.
The RMT module operates with a clock divider that scales the main
system clock down to a lower frequency suitable for precise timing
operations. The default clock source for the RMT module is derived
from the system clock running at 80 MHz. The clock divider
adjusts this frequency to meet the specific timing requirements of
the application.
● The
clock divider value determines how many system clock cycles are
used to produce one RMT clock cycle. The divider starts at 80,
meaning the RMT clock is derived by dividing the 80 MHz system
clock by the divider value. This scaling allows for various timing
configurations, enabling the RMT module to handle different pulse
widths and frequencies.
For example, with a clock divider of 80, the RMT clock frequency is
providing a time resolution of 1 microsecond per
tick. Adjusting the divider allows for finer control over timing
and signal generation.
The RMT module utilises dedicated RAM to store and process signal
data.
Each entry in the RMT RAM is a 32-bit word divided into four
fields, structured as follows:
Field
|
Description
|
Bits
|
level0
|
Level of the first pulse (high/low)
|
1 bit
|
duration0
|
Duration of the first pulse in ticks
|
15 bits
|
level1
|
Level of the second pulse (high/low)
|
1 bit
|
duration1
|
Duration of the second pulse in ticks
|
15 bits
|

Each memory block consists of these four fields, totaling 32 bits
(4 bytes) per item. This structure allows the RMT module to
precisely control pulse lengths and signal states, enabling
accurate signal generation and decoding. Each RMT item represents a
single pulse, with the following fields:
●
Level0: The state of the signal for the first half of the
pulse.
●
Duration0: The length of time the signal remains at Level0.
The value is set in ticks, where each tick is determined by the
clock divider.
●
Level1: The state of the signal for the second half of the
pulse.
●
Duration1: The length of time the signal remains at Level1.
Similar to Duration0, this is set in ticks.
The number of items used depends on the number of pulses that need
to be sent or received. Each channel can store multiple items, up
to the limit specified in the table above.
The minimum value for the duration is zero (0) and is interpreted
as a transmission end-marker.
The ‘duration’ fields represent the length of the pulse in terms of
clock ticks. By specifying the duration, you determine how long the
signal should be held at a particular level before transitioning to
the next state. This allows for the precise timing and modulation
of signals, crucial for tasks such as generating complex waveforms
or encoding data.
For example, using a clock divider of 80, each tick corresponds to
1 microsecond.
Therefore, the Duration0 and Duration1 fields
directly represent pulse lengths in microseconds.
● All
ESP32 variants allow for extending the memory blocks allocated to
certain RMT channels by reducing the total number of available
channels. This feature enables users to configure longer, more
complex signal patterns by increasing the buffer size for specific
channels. For example, on the ESP32, you can configure:
● 8
channels with 64 items each
● 4
channels with 128 items each
● 2
channels with 256 items each
● This
flexibility allows users to balance between the number of channels
and the complexity of signals they can generate or receive. By
reallocating memory, it is possible to tailor the RMT peripheral to
meet the specific needs of the application, whether it involves
fewer channels with longer signal patterns or more channels with
shorter patterns.
Transmit synchronisation in the context of RMT (Remote Control
Transceiver) refers to the ability to start multiple transmit
channels simultaneously with precise timing. This feature is
crucial for applications that require coordinated output across
multiple channels, such as:
●
Controlling complex LED matrices or strips
●
Generating multi-channel waveforms
●
Implementing protocols that require precise timing across multiple
signal lines
The goal of transmit synchronisation is to ensure that multiple RMT
channels begin their transmission at exactly the same moment,
eliminating any timing discrepancies between channels.
Different ESP32 variants have varying levels of support for
transmit synchronisation:
-
ESP32:
This earlier variant does not have built-in hardware support for TX
synchronisation.
-
ESP32-S2, ESP32-S3 and ESP32-C3:
These newer variants include hardware support for TX
synchronisation. They feature a synchronisation manager that can
coordinate the start of transmission across multiple TX channels
with high precision. This hardware-based approach allows for more
accurate and reliable synchronised transmissions.
In the transmitter mode, the RMT module of the ESP32 provides
versatile capabilities for transmitting data. Key features
include:
●
Idle Level (idle_level):
Set the signal level (high or low) on the RMT output when it is
idle. This ensures a consistent signal state between
transmissions.
●
Loop Enable (loop_en):
Enable or disable continuous looping of the data transmission.
●
Carrier Signal: The RMT module supports the use of a carrier
signal to modulate the output. This carrier signal can be
customised with the following parameters:
○
Enable Carrier Signal (carrier_en):
Activate the carrier signal to modulate the output as required.
○
Carrier Frequency (carrier_freq_hz):
Set a specific frequency (e.g., 38 kHz), which is commonly used in
IR communication.
○
Duty Cycle Percentage (carrier_duty_percent):
Adjust the duty cycle of the carrier signal to define the
proportion of time the signal is high within each period. This can
be set to values such as 33% or any other percentage based on
application needs.
○
Carrier Level (carrier_level):
Specify the level (high or low) of the RMT output when the carrier
is active, determining whether the carrier signal starts with a
high or low output.
In the reception mode, the RMT module provides several
configurable parameters to optimise signal reception and
processing:
●
Enable Filter (filter_en):
Activates a filter on the input of the RMT receiver to remove noise
and unwanted signals.
●
Filter Threshold (filter_ticks_thresh):
Sets the threshold for the filter in terms of the number of ticks.
Pulses shorter than this value will be filtered out. The acceptable
range for this value is from 0 to 255 ticks.
●
Idle Threshold (idle_threshold):
Defines a pulse length threshold in ticks that will cause the RMT
receiver to enter an idle state. Pulses longer than this threshold
will be ignored, helping to manage longer, non-relevant
signals.
Additionally, the RMT module can optionally demodulate the
input signal using the following parameters:
●
Enable Carrier Demodulation (rm_carrier):
Activates the carrier demodulation feature to process modulated
signals.
●
Carrier Frequency (carrier_freq_hz):
Specifies the frequency of the carrier signal in Hz, used for
demodulation. This allows the receiver to correctly interpret
signals modulated at specific frequencies.
●
Carrier Duty Cycle (carrier_duty_percent):
Sets the duty cycle of the carrier signal in percentage, which
helps in accurately decoding the modulated signal.
●
Carrier Level (carrier_level):
Defines the level of the RMT input where the carrier is modulated,
indicating whether the carrier signal affects the input when
active.
The RMT uses the
OnInfrared event for the reception of RX data. This
event is triggered immediately when the RMT module receives
incoming data.
RMT.SETUP_TX
channel,
pin [, clk_div] [, mem_block_num] [, idle_level] [, loop_en] [,
carrier_en] [, carrier_freq_hz] [, carrier_duty_percent] [,
carrier_level]
○
Purpose: Configures an RMT channel for transmission.
○
Arguments:
■
channel: RMT
channel number (integer)
■
pin:
GPIO pin number (integer)
■
clk_div: Clock
divider (optional integer, default is 80)
■
mem_block_num:
Number of memory blocks (optional integer, default is 1)
■
idle_level: Idle
level for the channel (optional integer, default is RMT_IDLE_LEVEL_LOW)
■
loop_en: Enable
looping (optional boolean, default is false (0))
■
carrier_en: Enable
carrier signal (optional boolean, default is false (0))
■
carrier_freq_hz:
Carrier frequency in Hz (optional integer, default is 38000)
■
carrier_duty_percent:
Carrier duty cycle percentage (optional integer, default is
33)
■
carrier_level:
Carrier level (optional integer, default is RMT_CARRIER_LEVEL_HIGH)
○
Description: Sets up the RMT channel for transmission with
specified parameters. Uninstalls and reconfigures the RMT
driver.
RMT.WRITE
channel,
num_items, name [, wait]
○
Purpose: Sends data items on an RMT channel.
○
Arguments:
■
channel: RMT
channel number (integer)
■
num_items: Number
of items to write (integer)
■
name:
Integer array containing the data items, where each element is a
32-bit word that encodes levels and periods.
■
wait:
Wait for transmission to complete (optional boolean, default is
true)
○
Description: Writes an array of RMT items to the specified
channel. The name parameter
represents an integer array where each element is a 32-bit word
combining both the levels (1-bit) and periods (15-bits each for
high and low durations) required for transmission. Optionally waits
for the transmission to complete.
RMT.ENCODE
channel,
num_items, array() [, wait]
○
Purpose: Encodes data items for transmission on an RMT
channel.
○
Arguments:
■
channel: RMT
channel number (integer)
■
num_items: Number
of items to encode (integer)
■
array:
A two-dimensional array containing the data to encode:
■
array[x][0]: Level
0
■
array[x][1]:
Duration 0
■
array[x][2]: Level
1
■
array[x][3]:
Duration 1
■
wait:
Wait for transmission to complete (optional boolean, default is
true)
○
Description: Encodes data for transmission from a
two-dimensional array where each row represents a data item to be
transmitted. The array must be defined beforehand with levels and
durations structured as shown. The encoded data is then written to
the specified channel, and it optionally waits for transmission to
complete.
RMT.SETUP_RX
channel,
pin [, clk_div] [, mem_block_num] [, invert] [, filter_en] [,
filter_ticks_thresh] [, idle_threshold] [, rm_carrier] [,
carrier_freq_hz] [, carrier_duty_percent] [,
carrier_level]
○
Purpose: Configures an RMT channel for reception.
○
Arguments:
■
channel: RMT
channel number (integer)
■
pin:
GPIO pin number (integer)
■
clk_div: Clock
divider (optional integer, default is 80)
■
mem_block_num:
Number of memory blocks (optional integer, default is 1)
■
invert: Inverts
the polarity of the signal (optional integer, default is
false
(0))
■
filter_en: Enable
filter (optional boolean, default is true (1))
■
filter_ticks_thresh:
Filter ticks threshold (optional integer, default is 100)
■
idle_threshold:
Idle threshold (optional integer, default is 65535)
■
rm_carrier: Remove
carrier signal (optional boolean, default is true)
■
carrier_freq_hz:
Carrier frequency in Hz (optional integer, default is 38000)
■
carrier_duty_percent:
Carrier duty cycle percentage (optional integer, default is
33)
■
carrier_level:
Carrier level (optional integer, default is RMT_CARRIER_LEVEL_HIGH)
○
Description: Configures the RMT channel for reception with
specified parameters. Uninstalls and reconfigures the RMT driver,
sets up a ring buffer for received data, and starts the
reception.
○
Purpose: Reads data items from an RMT channel.
○
Arguments:
■
array:
Integer array where the received data will be stored, with each
element being a 32-bit word that encodes levels and periods.
○
Description: Reads data from the RMT ring buffer and stores
it in an integer array (array). The array
will contain 32-bit words, with each word representing the levels
(1-bit) and periods (15-bits each for high and low durations) that
were received. The array must be pre-defined before use.
○
Purpose: Decodes received data from an RMT channel.
○
Arguments:
■
array:
A two-dimensional array to store the decoded data:
■
array[x][0]: Level
0
■
array[x][1]:
Duration 0
■
array[x][2]: Level
1
■
array[x][3]:
Duration 1
○
Description: Decodes data from the RMT ring buffer into a
two-dimensional array format where each row corresponds to a
decoded item with levels and durations structured as shown. The
array must be pre-defined before use.
○
Purpose: Adds an RMT channel to a group for synchronised
transmission.
○
Arguments:
■
channel: RMT
channel number (integer)
○
Description: Adds the specified RMT channel to a group. This
is used to define a set of channels that should transmit signals
simultaneously. The transmission is synchronised, starting only
when all channels in the group are ready.
○
Purpose: Removes an RMT channel from a group.
○
Arguments:
■
channel: RMT
channel number (integer)
○
Description: Removes the specified RMT channel from a group.
This action stops the channel from being part of a synchronised
transmission group.
○
Purpose: Terminates (unistall) an RMT channel.
○
Arguments:
■
channel: RMT
channel number (integer)
○
Description: Uninstall the specified RMT channel. This
action stops the channel from being active and frees the
corresponding GPIO pin.
The
RMT.ADD_GROUP andRMT.DEL_GROUP
commands manage the synchronisation of multiple RMT channels for
transmission. By adding channels to a group, the user specifies
which channels should start transmitting at the same time. The
transmission begins only when all channels in the group are ready,
ensuring synchronised signal output across multiple channels. When
a writing command is given on the last channel of the group, the
synchronised transmission can commence, providing coordinated
timing for applications that require multiple simultaneous
signals.
This example demonstrates how to use the RMT (Remote Control)
module on an ESP32 to transmit a sequence of pulses using the
RMT.ENCODE command. Let's break down the example to
understand what each part does and how it works.
' RMT example: set a sequence of 3 pulses of 1ms, 2ms, 3ms with
20msec between
dim a(10,5)
a(0,0)
= 1 : a(0,1)
= 1000: a(0,2)
= 0 : a(0,3)
= 20000
a(1,0)
= 1 : a(1,1)
= 2000: a(1,2)
= 0 : a(1,3)
= 20000
a(2,0)
= 1 : a(2,1)
= 3000: a(2,2)
= 0 : a(2,3)
= 20000
a(3,0)
= 0 : a(3,1)
= 0 : a(3,2)
= 0 : a(3,3)
= 0
' channel, pin, clk_div, num_blocks, idle_level, loop_en,
carrier_en, carrier_freq, carrier_duty_percent,
carrier_level
RMT.Setup_TX 0, 47, 80,
1, 0, 1, 1, 38000, 33, 1
RMT.ENCODE 0, 3,
a()
end
|
Pulse
Sequence Setup
The sequence of pulses is defined using a 2-dimensional array named
a in
the example, where each row represents one RMT item containing
pulse levels and durations.
dim a(10,5)
a(0,0)
= 1 : a(0,1)
= 1000: a(0,2)
= 0 : a(0,3)
= 20000
a(1,0)
= 1 : a(1,1)
= 2000: a(1,2)
= 0 : a(1,3)
= 20000
a(2,0)
= 1 : a(2,1)
= 3000: a(2,2)
= 0 : a(2,3)
= 20000
a(3,0)
= 0 : a(3,1)
= 0 : a(3,2)
= 0 : a(3,3)
= 0
|
●
a(n,
m): Represents a 2-dimensional array where:
○
a(0,0)
to a(3,3) define the
pulse sequence.
○
Column Definitions:
■
a(x,0):
Level0
- The logic level of the pulse for the first phase.
■
a(x,1):
Duration0 -
Duration (in ticks) for Level0.
■
a(x,2):
Level1
- The logic level of the pulse for the second phase.
■
a(x,3):
Duration1 -
Duration (in ticks) for Level1.
Explanation of the Sequence
●
a(0,0) to
a(0,3): First
pulse:
○
Level0
= 1 (High)
○
Duration0 = 1000
ticks (1ms)
○
Level1
= 0 (Low)
○
Duration1 = 20000
ticks (20ms gap)
●
a(1,0) to
a(1,3): Second
pulse:
○
Level0
= 1 (High)
○
Duration0 = 2000
ticks (2ms)
○
Level1
= 0 (Low)
○
Duration1 = 20000
ticks (20ms gap)
●
a(2,0) to
a(2,3): Third
pulse:
○
Level0
= 1 (High)
○
Duration0 = 3000
ticks (3ms)
○
Level1
= 0 (Low)
○
Duration1 = 20000
ticks (20ms gap)
●
a(3,0) to
a(3,3):
Terminates the sequence:
○ All
fields set to 0, indicating the end of transmission.
RMT Setup for Transmission
RMT.Setup_TX 0, 47, 80,
1, 0, 1, 1, 38000, 33, 1
|
The
RMT.Setup_TX command configures the transmitter with
specific parameters:
●
0:
Channel number (0).
●
47:
GPIO pin number (47).
●
80:
Clock divider, resulting in a 1 MHz RMT clock.
●
1:
Number of memory blocks.
●
0:
Idle level set to low.
●
1:
Loop enable, which allows the transmission to repeat
indefinitely.
●
1:
Carrier signal enabled.
●
38000:
Carrier frequency in Hz (38 kHz).
●
33:
Carrier duty cycle (33%).
●
1:
Carrier level set to high when the carrier is active.
Encoding and Transmitting the Pulse Sequence
The
RMT.ENCODEcommand encodes the pulse sequence for
transmission with the following parameters:
●
0:
Channel number.
●
3:
Number of items to encode (3 pulses).
●
a():
The name of the array containing the pulse sequence.
Explanation of
the Functionality
This example sets up the RMT module to send a series of three
pulses, each with increasing duration, followed by a 20 ms gap. The
RMT transmitter is configured to loop this sequence
indefinitely.
By using the RMT.ENCODE
command, the user specifies the pulse sequence data, which the
ESP32 will transmit on GPIO pin 47. The transmission repeats in a
loop until explicitly stopped.
Key
Points
●
Customizable Pulse Sequences: The example shows how to
define complex sequences of pulses with varying durations and
levels.
●
Loop Transmission: By setting the loop enable parameter to
1, the
transmission repeats indefinitely, which is useful for applications
that require a constant signal output.
●
Carrier and Idle Control: The carrier is enabled with a
frequency of 38 kHz and a 33% duty cycle, suitable for applications
like IR communication.
This example configures the ESP32's RMT module to transmit a
sinusoidal signal pattern using 256 data items. The waveform is
generated using the sin() function to
create a sequence of pulses that simulate a sine wave, which is
useful for applications like signal generation, testing, or remote
control emulation.
' RMT demo for generating a sinusoidal signal pattern using 256
data items
dim s(256,
4)
for z
= 0 to 256
s(z,0) =
1
s(z,1) =
sin(z/256*PI*2)
* 500 + 501
s(z,2) =
0
s(z,3) =
5000
next z
' channel, pin, clk_div, num_blocks, idle_level, loop_en,
carrier_en, carrier_freq, carrier_duty_percent,
carrier_level
RMT.Setup_TX 0, 47, 80,
6, 0, 1
rmt.ENCODE 0, 256,
s(), 0
end
|
Explanation of
the Example
- Define the Data
Array:
○ A
2-dimensional array s(256, 4) is
defined to store 256 items, where each item represents a part of
the sinusoidal waveform.
○ Each
item contains four fields:
■
s(z,0): Level of
the RMT output (1 or 0).
■
s(z,1): Duration
of the high or low level in clock ticks (calculated using a sine
function).
■
s(z,2): Level of
the RMT output after the initial duration (0 in this case).
■
s(z,3): Duration
of the low level after the initial pulse (fixed at 5000 ticks).
- Populate the Array with Sinusoidal
Data:
○ The
for
loop iterates from 0 to 256 to generate a sinusoidal pattern.
○ The
duration s(z,1) is
calculated using the sin() function to
create a value that oscillates between 1 and 1001, simulating a
sine wave. This is done by multiplying the sine function's result
by 500
and adding 501 to ensure a
minimum duration.
- RMT Setup for Transmission:
○
RMT.Setup_TX
initialises the RMT transmitter on channel 0, using GPIO pin
47, a
clock divider (clk_div) of
80,
and allocates 6 memory blocks
(num_blocks
= 6).
○
Idle_level is set
to 0
○ Loop
mode (loop_en) is
enabled to continuously transmit the configured data.
- Encode and Transmit the Data:
○
rmt.ENCODE encodes
the data array s() with
256
items and sends it on channel 0.
○ The
function prepares the RMT module to transmit the sinusoidal
pattern.
Memory Block
Usage
The example uses 6 memory blocks
to store at least 256 items:
●
Memory Block Capacity: Each block can store either 64
items or 48 items, depending on the ESP32 variant.
○ With
64 items per block, the 6 blocks can store a total of 384
items (6 × 64).
○ With
48 items per block, the 6 blocks can accommodate 288
items (6 × 48).
This ensures that the RMT module has enough capacity to handle the
entire sequence of 256 items required for the sinusoidal pattern
transmission.
Key Features
of This Example
●
Continuous Sinusoidal Waveform Generation: The example
demonstrates how to use the RMT module to generate a continuous
sinusoidal waveform.
●
Flexible Configuration: The setup uses 6 memory blocks to
ensure sufficient storage for the waveform, regardless of whether
the block size is 64 or 48 items.
This example demonstrates how to use the ESP32's RMT module to
transmit synchronised sinusoidal signal patterns using two
different channels (0 and 2). Both channels
are set up to transmit the same sinusoidal waveform, but the
transmissions are synchronised to start simultaneously. This is
useful in applications where multiple signals must be generated in
sync, such as in lighting systems.
' RMT demo for generating a sinusoidal signal pattern using 256
data items
K
= 95 '
95 points
dim s(K,
4)
for z
= 0 to K
s(z,0) =
1
s(z,1) =
sin(z/K*PI*2
- PI/2)
* 500 + 501
s(z,2) =
0
s(z,3) =
5000
next z
' channel, pin, clk_div, num_blocks, idle_level, loop_en,
carrier_en, carrier_freq, carrier_duty_percent,
carrier_level
RMT.Setup_TX 0, 47, 80,
2, 0, 1
RMT.Setup_TX 2, 21, 80,
2, 0, 1
rmt.add_group 0
rmt.add_group 2
rmt.ENCODE 0,
K-1, s(), 0
pause 500
rmt.ENCODE 2,
K-1, s(), 0
end
|
Explanation of
the Example
- Define the Data
Array:
○ The
array s(K,
4) is defined to store K items (where
K =
95), representing a sinusoidal waveform.
○ Each
item in the array has four fields:
■
s(z,0): Level of
the RMT output (1 or 0).
■
s(z,1): Duration
of the high or low level in clock ticks, calculated using the
sin()
function to generate a sinusoidal pattern.
■
s(z,2): Level of
the RMT output after the initial duration (0 in this case).
■
s(z,3): Duration
of the low level after the initial pulse (fixed at 5000 ticks).
- Populate the Array with Sinusoidal
Data:
○ The
for
loop iterates from 0 to K to generate the
sinusoidal pattern.
○ The
duration s(z,1) is
calculated using sin(z/K*PI*2 - PI/2) *
500 + 501, which creates a shifted sine wave oscillating
between 1 and 1001.
- Setup for RMT Transmission:
○
First Channel Setup (Channel
0):
■
RMT.Setup_TX
initialises the RMT transmitter on channel 0, using GPIO pin
47, a
clock divider (clk_div) of
80,
and allocates 2 memory blocks
(num_blocks
= 2).
■ Loop
mode (loop_en) is
enabled to continuously transmit the configured data.
○
Second Channel Setup (Channel
2):
■
Similarly, RMT.Setup_TX
initialises another RMT transmitter on channel 2, using GPIO pin
21,
the same clock divider (clk_div) of
80,
and 2
memory blocks.
■ Loop
mode (loop_en) is also
enabled for this channel.
- Add Channels to the Group for Synchronized
Transmission:
○
rmt.add_group adds
both channels (0 and 2) to a
synchronisation group. This allows the signals from both channels
to be transmitted simultaneously.
○ The
transmission for both channels will start only when all channels in
the group are ready.
- Encode and Transmit the Data:
○
rmt.ENCODE 0,
K, s(), 0 encodes the data array s() with
K
items and sends it on channel 0.
○
After a pause of 500 milliseconds,
rmt.ENCODE 2,
K, s(), 0 encodes the data array s() with the same
K
items and sends it on channel 2.
○ The
transmission will start simultaneously on both channels
Memory Block
Usage
● Each
channel is configured to use 2 memory
blocks.
○ Each
memory block can store 64 or 48 items, depending on
the configuration.
○ With
2
memory blocks, each channel can store a maximum of:
■
128 items (2 × 64) if the block size is 64 items.
■
96 items (2 × 48) if the block size is 48 items.
○ This
configuration is sufficient to store the 95 items
generated for the sinusoidal pattern.
Key Features
of This Example
●
Synchronised Sinusoidal Waveform Transmission: This example
demonstrates how to use two RMT channels to transmit synchronised
waveforms, which is useful in applications requiring precise timing
across multiple outputs.
●
Configurable Waveform: The sinusoidal pattern is generated
dynamically using the sin() function,
and its duration can be easily adjusted by modifying the
parameters.
●
Flexible Grouping: Adding channels to a group (rmt.add_group)
enables simultaneous transmission, which is critical in
applications like synchronised lighting
This example demonstrates how to configure an RMT channel on the
ESP32 to receive an infrared signal from a specified GPIO pin
and decode it into a usable format. The example showcases how to
set up the RMT receiver, handle the incoming signal, and convert it
into a binary value that represents the transmitted IR code.
'RMT example on IR signal decoding
pin.mode 42,
input
rmt.Setup_RX 4,42,80
dim rx(64)
onInfrared doRMT
wait
doRMT:
t
= millis
rmt.decode rx()
print
"RMT", ubound(rx()),
millis-t
res=0
for z=0
to ubound(rx())
'print z, rx(z,0), rx(z,1), rx(z,2),
rx(z,3)
t1
= rx(z,3)
res = (res <<
1) + (t1>1000)
next z
print
"code final", hex$(res),
millis-t
return
|
Explanation of
the Example
- Configure the
GPIO Pin for Input:
○
pin.mode 42,
input sets GPIO pin 42 as an input
pin. This pin will receive the infrared signal from the IR sensor
or receiver module.
- Setup RMT Receiver:
○
rmt.Setup_RX
4,42,80 configures the RMT channel 4 for receiving
mode on GPIO pin 42 with a clock
divider (clk_div) of
80.
This sets up the RMT module to capture incoming pulses on the
specified pin.
- Define an Array for Storing Received
Data:
○
dim
rx(64) declares an array rx with a size of
64 to
store the received data items. Each entry in this array will hold
information about the pulse width and levels captured by the RMT
receiver.
- Set Up an Event Handler for Infrared
Signals:
○
onInfrared
doRMT sets up an event handler named doRMT to be
triggered when an IR signal is detected.
- Wait for IR Signal:
○ The
wait
command puts the system in a waiting state until the IR signal is
received, and the doRMT handler is
triggered.
- Handle the IR Signal (doRMT
Function):
○
Capture Start Time: t = millis records
the current time in milliseconds to measure the duration of the
decoding process.
○
Decode Received Data: rmt.decode rx()
decodes the captured data items and stores them in the rx array.
○
Print Decoding Results: print "RMT",
ubound(rx()), millis-t prints the number of items in the
rx
array and the time taken to decode the signal.
○
Extract Data Bits from the Received Signal:
■
Initialise a result variable res to
0.
■ Loop
through each item in the rx array:
■
t1 =
rx(z,3) retrieves the duration of the low level for each
pulse.
■
res = (res
<< 1) + (t1>1000) shifts the result by one bit and
adds 1
if the duration t1 is greater than
1000
ticks, or adds 0 otherwise.
○
Print Final Decoded Code: print "code final",
hex$(res), millis-t displays the final decoded value in
hexadecimal format and the total decoding time.
Key Features
of This Example
●
IR Signal Reception and Decoding: The example demonstrates
the use of the ESP32's RMT module to receive an infrared signal,
store it in an array, and decode it into a binary code.
●
Timing Analysis: By measuring the time taken to decode the
signal, the example provides insights into the efficiency of the
decoding process.
●
Bitwise Operations for Decoding: The example uses bitwise
operations to efficiently extract data bits from the received
signal based on pulse durations.
Memory Block
Usage
● This
example uses a single RMT channel (4) for receiving
the IR signal. Since the rx array is
defined with 64 items, it fits
within the default memory block size allocated for a single RMT
channel.
Key
Configuration Parameters for Reception
●
Filter Enable and Threshold:
○ The
RMT receiver can filter out noise or unwanted short pulses by
setting the filter_en
parameter.
○ The
filter threshold filter_ticks_thresh
determines the minimum duration a pulse must have to be considered
valid. Pulses shorter than this will be ignored.
●
Idle Threshold:
○ The
idle_threshold is
used to detect when the signal becomes idle. Pulses longer than
this threshold are considered idle, which helps in recognizing the
end of a transmission.
●
Carrier Demodulation (Optional):
○ If
the input signal is modulated with a carrier frequency, the RMT
receiver can demodulate it using settings such as carrier_rm,
carrier_freq_hz,
carrier_duty_percent,
and carrier_level.
Applications
This example is useful for:
●
Infrared Remote Control Systems: Decoding commands sent from
an IR remote control.
●
Sensor Data Reception: Receiving data from sensors that use
infrared communication.
●
Wireless Communication Protocols: Implementing custom
communication protocols using IR signals.
By leveraging the ESP32's RMT module, this example shows how to
efficiently receive and process IR signals for a wide range of
applications.
This functionality exposes two
counters that permit to count pulses from any input pin.
Additionally, each counter can
also return the time occurred between consecutive pulses (period);
this is useful as this will permit to determine the frequency of
low frequency signals simply taking its reciprocal
(f = 1 / period).
These counters are not based on
H/W but are managed using processor interrupts, so the input
frequency should be limited to around 10 Khz.
It is possible to define when the
pulse is counted (on Rising Edge, on Falling Edge, on
Change).
The “on Change” is particularly
interesting when associated with low frequency measurement as it
will permit to double the number of pulses.
Before using the counters, the
input pin must be set as INPUT using the command
PIN.MODE.
To start to use the counters, the
following command is available:
COUNTER.SETUP cnt, pin
[,mode]
where:
‘cnt’ defines which counter (1 or 2)
‘pin’ defines the input pin (can be any valid
pin except GPIO16)
‘mode’ can be 1 (rising edge), 2 (falling
edge) or 3 (change). If not specified, the mode change is
enabled.
Example:
PIN.MODE 12,INPUT
‘defines the pin GPIO12 as INPUT
COUNTER.SETUP 1, 12,
1 ‘ Counter 1 using pin GPIO12, count on Rising
Edge
The pulses counted can be read
using the function
COUNTER.COUNT(cnt).
The period between 2 consecutive
pulses can be read using the function
COUNTER.PERIOD(cnt).
Example:
print
COUNTER.COUNT(1)
‘print the pulses counted from the counter 1
print
COUNTER.PERIOD(1)
‘print the period
from the counter 1
FInally the counters can be reset
with the command
COUNTER.RESET cnt
Example:
COUNTER.RESET 1
‘ reset the counter 1
A proportional–integral–derivative controller
(PID controller. or three-term controller) is a control loop
feedback mechanism widely used in industrial control systems and a
variety of other applications requiring continuously modulated
control. (ref wikipedia)
A PID controller continuously calculates an
error value e(t) as the difference between a desired setpoint (SP)
and a measured process variable (PV) and applies a correction based
on proportional, integral, and derivative terms (denoted P, I, and
D respectively), hence the name.
In practical terms it automatically applies
accurate and responsive correction to a control function.
An everyday example is the cruise control on a
car, where ascending a hill would lower speed if only constant
engine power is applied. The controller's PID algorithm restores
the measured speed to the desired speed with minimal delay and
overshoot, by increasing the power output of the engine.
Annex implements 4 PID controllers that can be
used simultaneously for any application.
The commands are :
PIDx.INIT Kp, Ki,
Kd
PIDx.SETMODE mode
PIDx.LIMITS min,
max
PIDx.PERIOD msec
PIDx.PARAMS Kp, Ki,
Kd
The main function is:
Pid_Out
= PIDx.COMPUTE(CURR_VALUE, TARGET_VALUE)
PIDx can bePID1,
PID2, PID3 or
PID4.
The first step is to initialise the PID
controller.
This can be done with the command
PIDx.INIT Kp, Ki,
Kd :
Example:
PID1.INIT 50, 80,
1 'initialise the controller with Kp = 50, Ki = 80 and
Kd = 1
Optionally the output limits can be set using
the command
PIDx.LIMITS min,
max.
If not defined the output is limited between 0
and 255
Example:
PID1.LIMITS 0,
1023 ' limits the output between 0 and 1023
Then the sampling period can be defined using
the command
PIDx.PERIOD msec
If not defined the period is set at 100
msec
Example:
PIDx.PERIOD 50
' define the period at 50 msec
Finally the main function
output =
PIDx.COMPUTE(input,
setpoint)
Example:
Pid_Out
=
PID1.COMPUTE(CURR_VALUE,
TARGET_VALUE)
This function must be called regularly in a
loop; the best is to call it using a timer.
The command
PIDx.SETMODE mode
can be used to put the loop in manual mode with
PIDx.SETMODE 0.
In this case the PID loop will be stopped and
the output value will be frozen.
To restore the auto mode (default), the
command is
PIDx.SETMODE 1.
At any moment the PID parameters can be
changed using the command
PIDx.PARAMS Kp, Ki,
Kd :
Example:
PID1.PARAMS 30, 80,
10 ' modify the PID parameters with Kp = 30, Ki = 80 and
Kd = 10
The following example shows how to control the
speed of a 3-wire 12V PC fan.
The PID utilises the counter to determine the
fans speed controlling it using the PWM.
A little circuit is required to drive the
positive side of the FAN.
CODE:
pid1.bas
' PID Test
program
' cicciocb
2019
' this
example controls the speed of a 3-wire PC fan
' using the
internal counter as input and the PWM as output
PID1.INIT
1, 5,
0 'init the PID
paramters
PID1.LIMITS
0,
1023 'the PWM goes up to
1023
pin.mode
12,
input, pullup 'GPIO12 is the tach input. Pullup is
ON
counter.setup
1, 12,
3 ' count changes so the output
is doubled
cnt_p
= 0 '
previous value of the counter
target
= 50 'the default target speed
(hz)
timer0
100,
do_pid 'the PID is updated each
100msec
onHtmlReload
create_web_page
gosub
create_web_page
wait
create_web_page:
cls
a$
= "PID
DEMO PROGRAM<br>"
a$
= a$ + "SPEED (Hz)
" + textbox$(target)
html
a$
return
do_pid:
' The
frequency is computed at each cycle counting the pulses
occurred
' As the
cycle is executed each 100msec, the frequency
computed
' is 1/10 of
the real one
cnt
= counter.count(1)
freq
= cnt - cnt_p ' the
frequency
cnt_p
= cnt
'the
frequency is doubled and divided by 10
'so the real
target is target *2 /10
out
= pid1.compute(freq, target *2 /10)
'compute the
PID
print
"pulses ";freq, "freq "; freq *10/2,
"pwm out
";out
pwm(13)
= out
return
|
Annex provides the functionality to play WAV
and MP3 sound directly from disk (FATFS or SD card).
The mp3 streaming from the web is also
supported permitting to play Web Radios.
As the ESP-32 is equipped with a dual core
CPU, this activity is done in parallel and does not impact the
overall performance of Annex-32.
The sound output can be sent to the internal
speaker (in particular for the m5stack) or to an external I2S
DAC.
Look at the previous chapters for more details
on the sound output.
To play sounds, the command available is
PLAY.xxx
Before using this command, the sound output
must be set as below :
PLAY.SETUP dest
[,buffer], [mono]
If ‘dest’ is 0 is the output will be
sent to the GPIO25 and 26 ( and the internal speaker for the
M5stack)
If ‘dest’ is 1 is the output will be
sent to the external DAC
If ‘dest’ is 2 is the output will be
sent to the GPIO25 and 26 ( and the internal speaker for the
M5stack) but using the PDM mode
The optional argument ’buffer’ defines
the size of the memory block allocated as an output buffer.
Its value is 8 by default and can be increased
up to 64.
Increasing the size of the buffer will permit
to reduce some glitches that may occur in case of strong WiFi
activity.
The optional argument ‘mono’, if set to
1, set the output in mono mode (useful for single channel
speaker)
If the command
PLAY.SETUP is run without arguments, the sound is sent
by default to the internal speaker.
To play mp3 files, the command is :
PLAY.MP3 mp3file$
Example
PLAY.MP3
"/mp3/MyMusic.mp3"
To play wav files, the command is:
PLAY.WAV wavfile$
Example
PLAY.WAV
"/wav/MySound.wav"
The position (the time) of the sound played
can be controlled using the command
PLAY.SEEK using a value from 0 (beginning) to 100
(end).
Example
PLAY.SEEK 50
position the sound at the middle of its length (50%)
PLAY.SEEK 0
rewind the sound
The function
PLAY.POS returns the current position of the file from 0
(beginning) to 100 (end)
Example:
print
PLAY.POS
It is also possible to play mp3 streaming web
radios with the command
PLAY.STREAM streaming_url$
[,buffer] [,disable_id3] [,use_http10] [,show_buffer]
[,preload_time]
Example:
PLAY.STREAM"http://91.121.159.124:8000/eko-des-garrigues-128k.mp3"
To avoid glitches, the stream is buffered
locally using a buffer of 20 Kbytes.
This can eventually be increased to improve
the performance of the streaming, in particular with ESP32 modules
that include the PSRAM.
Example:
PLAY.STREAM
"http://audio4.nemostream.tv:8011/autodj",
50000
To avoid glitches, the stream is preloaded in
the buffer for 4 seconds or until it reaches the 80% of the
allocated size; the optional argument ‘preload_time’ can be
used to modify this time.
It is important to note that streams using
https:, require more memory and more CPU power to process the
encrypted data. In this case, it is recommended to use modules with
PSRAM and set a big buffer size ( at least 150000, for
example).
The optional argument ‘disable_id3’
disables the parsing of the metadata included in the stream. This
is particularly useful for high rate streams that uses massively
the cpu (generating a lot of glitches)
The optional argument ‘use_http10’ is
useful for streams that still uses the HTTP 1.0 protocol
Example:
PLAY.STREAM
"http://icecast.radiofrance.fr/franceinter-lofi.mp3",
50000,,1
The optional argument ‘show_buffer’
will show how the buffer is managed and can be useful for debug
The sound is always played in the background,
even if the program is stopped, until the end of the file (or
forever for the web radios).
As the sound is played in the background, the
functionPLAY.ISPLAYING
returns the following values :
VALUE
|
DESCRIPTION
|
0
|
The sound is
stopped
|
1
|
The mp3 file is
playing
|
2
|
The wav file is
playing
|
To stop playing, the command is :
PLAY.STOP
The volume can be changed with the
command:
PLAY.VOLUME vol
‘vol’ is by default 100 and represents the
full volume (100%).
In case of sound files recorded with low
volume, it is also possible to specify a value greater than
100.
Take into account that the output audio will
saturate if the value is too high.
Example
PLAY.VOLUME 50
‘set the sound at 50% of normal volume.
A new feature has been included that enables
the creation of a VU meter for the left and right channels.
The functions
PLAY.VU_L and
PLAY_VU_R return the average value of the sound
currently playing for the left and right channel.
These functions return a value between 0 and
32767.
This value is computed with the average of the
last 1024 samples of the sound currently playing.
This can be eventually changed using the
function
PLAY.VU_AVERAGE value
It must be noted that this value must be
converted in logarithmic scale before being used as a vu meter.
Annex includes another functionality that
automatically extracts the metadata information from the media
playing.
The metadatas are information that are
included inside the stream of data and contain useful information
such as the title of the song, the artist, the name of the radio
station, etc.
These are usually named ICY for the web radios
and ID3 for the mp3 files.
As this information is “async” because it can
arrive at any time during the listening, another event has been
included for this purpose.
The name of this event is
ONPLAY label
and it simply jumps at the label specified as soon as a play event
occurs.
Is then possible to read the information
received using the function
play.message$
This function returns a message in the form of
metaname=value
Example Artist=Police
and Title=Roxanne
The following “metadata” information are
implemented
Name
|
DESCRIPTION
|
Group
|
Title
|
The title of the
song currently played
|
mp3
|
Artist
|
The mp3 file is
playing
|
mp3
|
SiteName
|
Name of the web
radio
|
Web radio
|
Genre
|
Genre of the web
radio
|
Web radio
|
StreamTitle
|
The title of the
song currently played
|
Web radio
|
Bitrate
|
Bitrate (in Kbs) of
the web radio
|
Web radio
|
Another “special” metadata is also included
that is raised when the mp3 song is over.
In this case
play.message$ returns Status=end
This is useful to indicate to switch to the
next song when using Annex as an mp3 file player.
Annex integrates SAM, a port of the
reverse-engineered speech synthesizer Software Automatic Mouth
(SAM)
Sam is a very small Text-To-Speech (TTS)
program written in C, that runs on most popular platforms. It is an
adaptation to C of the speech software SAM (Software Automatic
Mouth) for the Commodore C64 published in the year 1982 by Don't
Ask Software (now SoftVoice, Inc.). It includes a Text-To-Phoneme
converter called reciter and a Phoneme-To-Speech routine for the
final output. It is so small that it also works on embedded
computers.
The sound output and the volume follow the
same rules defined in the previous chapter
To use it, the command is:
PLAY.SPEAK“message”
[,
phonetic]
Example
PLAY.SPEAK
“The quick brown fox jumps over the lazy dog”
Using an optional parameter “phonetic” to 1,
it is possible to use the synthesys in phonetic mode
This table lists the phonemes available:
VOWELS VOICED
CONSONANTS
IY
f(ee)t
R red
IH
p(i)n
L allow
EH
beg
W away
AE
Sam
W whale
AA
pot
Y you
AH
b(u)dget
M Sam
AO
t(al)k
N man
OH
cone
NX so(ng)
UH
book
B bad
UX
l(oo)t
D dog
ER
bird
G again
AX
gall(o)n
J judge
IX
dig(i)t
Z zoo
ZH plea(s)ure
DIPHTHONGS V
seven
EY
m(a)de
DH (th)en
AY
h(igh)
OY
boy
AW
h(ow)
UNVOICED CONSONANTS
OW
slow
S Sam
UW
crew
Sh fish
F fish
TH thin
SPECIAL PHONEMES
P poke
UL
sett(le)
(=AXL)
T talk
UM
astron(omy) (=AXM)
K cake
UN
functi(on) (=AXN)
CH speech
Q
kitt-en (glottal stop)
/H a(h)ead
|
The complete documentation of the original SAM
can be found here :
http://www.retrobits.net/atari/sam.shtml
Annex32 implements a feature permitting speech
texts using the voice synthesis available in google translate.
Obviously this feature requires the module to
be connected to the internet.
The command is
PLAY.VOICE"message",
"language" [, "filename"] [, action]
Example:
PLAY.VOICE"Hello
World with Annex 32",
"en" 'speech this text in english
The voice sound (in mp3 format) is first
downloaded locally to the local disk then is played using the
internal MP3 player. By default the sound is saved as
/_voice.mp3 but the name can be changed using the
optional parameter
"filename".
This permits to “reuse” these saved “speech”
files at a later time, simply playing them like regular mp3
files.
This is particularly useful because the voice
download process is not immediate (it takes a few seconds).
The last optional parameter
(action) can be used to modify the default behaviour
as defined below :
VALUE
|
DESCRIPTION
|
0
|
Stop
a sound in progress and speech
|
1
(default)
|
Waits
for the end of the sound in progress and then speech
|
2
|
Simply save the sound as file on the disk
|
The message should
be limited to less than 200 characters.
The language should
be any valid google language code:
PLAY.VOICE"Hello
World with Annex 32",
"en" 'standard English British
PLAY.VOICE"Hello
World with Annex 32",
"en-US" ' US (American) English
PLAY.VOICE"Benvenuti
in Annex 32",
"it" ' Italian
PLAY.VOICE"Bonjour
avec Annex 32",
"fr" ' French
PLAY.VOICE"Bonjour
avec Annex 32",
"fr-CA" ' French Canadian
The complete list
of google “language codes” can be found here :
https://cloud.google.com/text-to-speech/docs/voices
Annex32 implements a feature permitting speech
texts using the voice synthesis using the free service provided by
voiceRSS (http://www.voicerss.org).
Before using this service it is necessary to
register and get your API key.
The command is
PLAY.voiceRSS"message",
"language", "key" [, "filename"] [, action]
Example:
key$
= "7c39b2b5d21b4bd4bd23782a15384512"
PLAY.voiceRSS"Hello
World with Annex 32","en-gb",
key$ 'standard English
British
The voice sound (in mp3 format) is first
downloaded locally to the local disk then is played using the
internal MP3 player. By default the sound is saved as
/_voice.mp3 but the name can be changed using the
optional parameter
"filename".
This permits to “reuse” these saved “speech”
files at a later time, simply playing them like regular mp3
files.
This is particularly useful because the voice
download process is not immediate (it takes a few seconds).
The last optional parameter
(action) can be used to modify the default behaviour
as defined below :
VALUE
|
DESCRIPTION
|
0
|
Stop
a sound in progress and speech
|
1
(default)
|
Waits
for the end of the sound in progress and then speech
|
2
|
Simply save the sound as file on the disk
|
The language should
be any valid language code defined in the API here http://www.voicerss.org/api/
key$
= "7c39b2b5d21b4bd4bd23782a15384512"
PLAY.voiceRSS"Hello
World with Annex 32",
"en-gb", key$'standard English British
PLAY.voiceRSS"Hello
World with Annex 32",
"en-us", key$ ' US
(American) English
PLAY.voiceRSS"Benvenuti
in Annex 32",
"it-it", key$ '
Italian
PLAY.voiceRSS"Bonjour
avec Annex 32",
"fr-fr", key$ '
French
PLAY.voiceRSS"Bonjour
avec Annex 32",
"fr-ca", key$ ' French
Canadian
Other parameters (such as the voice,
the sample rate, the speed, ..) can be passed inside the language
field (see below for the sample rate).
PLAY.voiceRSS"Hello
World with Annex 8",
"en-gb&f=8khz_16bit_mono",
key$
By default the mp3 file is requested with
22khz_16bit_mono resolution.
check this page for more information about all the
other optional parameters
http://www.voicerss.org/api/
The VS1053B is a highly versatile audio codec
chip known for its ability to decode a wide range of audio formats,
including MP3, AAC, WMA, MIDI, Ogg Vorbis, and FLAC. When utilised
together with Annex32, it enables users to seamlessly integrate
advanced audio decoding capabilities into their projects. This
combination facilitates the creation of multimedia applications
with support for diverse audio formats, ensuring high-fidelity
playback and enhancing the overall user experience.
Using this module, it is possible to play
sound files directly from the disk (FATFS or SD card) as well as
stream Web Radio. This is where the module provides significant
added value, as it allows listening to nearly all available Web
radio streams by decoding virtually all audio formats.
The VS1003B is also supported but with much
less functionalities (for example the aac audio is not
supported)
You can find easily several audio modules
based on this chip as, for example, the ones shown below :
Module with VS1053B and SDCARD that can be used at the same
time

This module can be wired as shown below
(including the SDCARD)

Module with VS1053B chip, (but take care that it's often sold
with the cheaper VS1003B chip.)


This module can be wired as shown below

Commands :
The usage of the module is very similar to
that of sound player commands, with nearly identical syntax.
The first command to use is
VS1053.SETUP
XCS_pin, XDCS_pin, DREQ_pin
[,info_enabled] [,SPIfreq] [SCI_CLOCKF]
Where XCS_pin,
XDCS_pin,
DREQ_pin
represent the pin used for the connection and the optional argument
info_enabled
if is 1, enable a more detailed report on what is happening in the
background.
The other optional arguments are for advanced
mode and will probably be removed in the future.
In the schematic examples above, the command
should be:
VS1053.SETUP 12, 13,
15
Executing this command, the following message
should be shown in the console:
The version is 4 (VS1053)
If the message is different, check the wiring
or check if the module is a VS1053B and not a VS1003B!
To play any music file, the command is
simply
Where file$
can be any valid music file identified by the extension of the file
as per the table below :
FILE
FORMAT
|
FILE
EXTENSION
|
MP3
|
.mp3
|
AAC
|
.aac
|
WAV
|
.wav
|
MPEG
4 Audio
|
.m4a
|
FLAC
|
.flac
|
OGG
|
.ogg
|
MIDI
(format 0 only)
|
.mid
|
Example
VS1053.PLAY
"/mp3/MyMusic.mp3"
or
VS1053.PLAY
"/wav/MySound.wav"
or
VS1053.PLAY
"/midi/MyMidi.mid"
To play web radios streaming the command
is
Example
VS1053.STREAM"http://audio4.nemostream.tv:8011/autodj"
or
VS1053.STREAM"https://radioitaliasmi.akamaized.net/hls/live/2093120/RISMI/stream01/streamPlaylist.m3u8"
Annex32 implements a feature permitting speech
texts using the voice synthesis available in google translate.
Obviously this feature requires the module to
be connected to the internet.
The command is
Example:
PLAY.VOICE"Hello
World with Annex 32",
"en" 'speech this text in english
The voice sound (in mp3
format) is first downloaded locally to the local disk as
/_voice.mp3 and then is played using the internal MP3
player.
To stop playing, the command is
The volume can be changed with the
command:
Vol
is by default 21 and represents the full volume (100%). It can vary
from 0 (mute) to 21 (loudest)
Example
VS1053.VOLUME 10
In case of problem, the module can be reset
using the command
Advanced functionalities
The VS1053B is a powerful DSP chip that can
also be "reprogrammed" via software "patches" loaded at runtime.
These "patches" can range from simple bug corrections to the
implementation of new audio codecs (such as FLAC) or new
functionalities (such as audio equaliser, spectrum analyser, MIDI
mode, etc.).
Annex implements a specific function that
enables the loading of these "patches" into the chip. The patches
are simply text files (usually with the .cmd extension) containing
a list of commands to be sent to the VS1053B. After this loading
phase, the new functionality/mode becomes available.
These “patches” can be downloaded directly
from the
VLSI website
The command to upload the patch is :
The example below upload a patch that
implements the FLAC decoder
VS1053.INIT
"/patches/vs1053b-patches-flac.cmd"
Some patches / functionalities require reading
/ writing inside the internal DSP registers.
For these reasons the following command /
function have been implemented :
MIDI special mode
Loading a special “patch” it is possible to
put the module in real-time MIDI mode.
This permits to send MIDI commands and play
MIDI notes directly using the following commands :
This example plays a note for 1 second :
vs1053.setup
12, 13,
15
vs1053.volume
21
vs1053.init
"/patches/rtmidistart.cmd" 'upload the start midi patch
vs1053.midi_cmd
&hC0, &h40, 0
vs1053.note_on
0, 60,
127
pause
1000
vs1053.note_off
0, 60,
127
|
An LCD display can be connected to the module
using I2C interface.
These displays are very cheap and available on
Ebay at less than 4€.
This picture shows an LCD with 4 lines at 20
characters per line.

In general these displays are based on the
chip HD44780 and work with a parallel interface.
Because the number of pins available on the
ESP module is very limited, there is an additional module (usually
supplied with the display) which allows connection using the 2-wire
I2C bus.
This picture shows the module (generally
soldered in the back of the display) enabling the I2C
connection.

These modules are based on the chip PCF8574
and have the following relationship between the display pins and
the bits of the PCF8574:
PCF8574
BIT
|
LCD
SIGNAL
|
|
PCF8574 BIT
|
LCD SIGNAL
|
BIT
0
|
RS
|
|
BIT 4
|
D4
|
BIT
1
|
RW
|
|
BIT 5
|
D5
|
BIT
2
|
E
|
|
BIT 6
|
D6
|
BIT
3
|
BACKLIGHT
|
|
BIT 7
|
D7
|
However, this mapping is managed directly into
the ESP module so you don’t need to worry about it.
The only important information is the I2C
address of the display which may change depending on the card.
The connection is very simple, just 2 pins for
the I2C and the power supply are required.

An important point is that the display must be
powered with 5V because it will not work at 3.3 V.
In order to use the LCD, there are 2 steps
:
-
Initialise the I2C bus
-
Init the display
This can be done with the following commands
:
I2C.SETUP 21,
22 ' set I2C port on pins 21 and 22
LCD.INIT 63, 20,
4 ‘ init an LCD at address 63 (3F in hex) with 20
characters per line and 4 lines
After these 2 lines, there are 2 additional
commands available :
LCD.CLS ‘ clear the screen of the LCD
LCD.PRINT x, y,
text$ ‘ print a text on the LCD at the position
(x, y)
Example:
I2C.SETUP 21,
22 ' set I2C
port on pins 21 and 22
'init an LCD
at address 63 (3F in hex) with 20 characters per line and 4
lines
LCD.INIT
63, 20,
4
LCD.CLS
' clear the screen of the
LCD
'print a
message on the LCD at the first char of the first
line
LCD.PRINT
1, 1,
"HELLO WORLD"
|
In addition it is possible to control the
backlight of the display using the functions
LCD.OFF
' turns OFF the backlight of the
LCD
LCD.ON '
turns ON the backlight of the
LCD
The LCD has the capability to hold 8 custom
characters identified as the ASCII chars from 0 to 7.
The command
LCD.CUSTOM char,
array() enables to define these custom characters.
For example, to define the custom char 2 :
dim a(8)
= 0, 0, 10, 21, 17, 10, 4, 0
'these are 8 bytes defining the 8
rows
LCD.CUSTOM 2,
a() 'set the character 2
LCD.PRINT 1,1,
CHR$(2)
' print the char
Finally the command
LCD.WRITE char
enables to print a single char;
It enables, in particular, to print the
character 0 (that is ignored in
LCD.PRINT).
For example, this program :
I2C.SETUP 4, 5
'set I2C port on pins 4 and
5
'init an LCD at address 63 (3F in hex) with 20 characters per line
and 4 lines
LCD.INIT 63, 20,
4
LCD.CLS
' clear the screen of the
LCD
'print a message on the LCD at the first char of the first
line
LCD.PRINT 1, 1,
"HELLO WORLD"
'Create 8 custom chars
dim a(8)
= 0, 0, 10, 21, 17, 10, 4, 0
'Heart
LCD.CUSTOM 0,
a()
dim a(8)
= 0, 0, 10, 31, 31, 14, 4, 0
'Heart filled
LCD.CUSTOM 1,
a()
dim a(8)
= 0, 10, 0, 0, 17, 14, 0, 0
'smile
LCD.CUSTOM 2,
a()
dim a(8)
= 0, 10, 0, 0, 14, 17, 0, 0
'sad
LCD.CUSTOM 3,
a()
dim a(8)
= 0, 14, 17, 17, 17, 10, 10, 27
'omega
LCD.CUSTOM 4,
a()
dim a(8)
= 4, 14, 31, 4, 4, 4, 4, 4
'arrow up
LCD.CUSTOM 5,
a()
dim a(8)
= 4, 4, 4, 4, 4, 31, 14, 4
'arrow down
LCD.CUSTOM 6,
a()
dim a(8)
= 0, 4, 10, 17, 10, 4, 0, 0
'diamond
LCD.CUSTOM 7,
a()
LCD.print 1 ,2,
"" 'set the cursor on the 2nd
line
'Print the 8 custom chars
for z
= 0 to 7
LCD.WRITE z
next z
|
Will give this result on the LCD:

The custom characters can be created online
using this website https://maxpromer.github.io/LCD-Character-Creator/

For example, the char defined in the image,
can be defined in annex as below :
dim a(8)
= &h04, &h0E, &h1F,
&h04, &h04, &h1F &h0E, &h04
LCD.CUSTOM 3,
a()
|
An OLED display can be connected to the module
using I2C interface.
These displays are very cheap and available on
Ebay at less than 3€.
This picture shows an OLED with 128 x 64
pixels monochrome but the size is only 0.96".

This display is based on the chipset
SSD1306
It is also possible to use a display based
on the chipset SH1106.
The connection is very simple, just 2 pins for
the I2C and the power supply are required.

In order to use the OLED, there are 2 steps
:
-
Initialise the I2C bus
-
Init the display
This can be done with the following commands
:
I2C.SETUP 21,
22 ' set I2C
port on pins 21 and 22
OLED.INIT orientation
'init with a
given orientation (0 = normal, 1 = upside-down)
In case of the display SH1106, the command
is
OLED.INIT orientation,
1 'init with a given orientation
(0 = normal, 1 = upside-down)
After these 2 lines, there are several
commands available :
OLED.CLS, OLED.COLOR, OLED.FONT, OLED.PIXEL, OLED.LINE, OLED.RECT,
OLED.CIRCLE, OLED.PRINT, OLED.IMAGE, OLED.BMP,
OLED.REFRESH
The current implementation of the OLED is
based on a double buffering; this permits drawing in background on
the screen while the current image is still shown. This technique
permits to avoid flickering while drawing objects on the screen.
The command
OLED.REFRESH fmt
allows users to choose between an automatic refresh
(OLED.REFRESH
1)
or a manual refresh (OLED.REFRESH
0).
By default the refresh is automatic.
When an automatic refresh is set, the image is
immediately updated after each drawing command, whereas with the
manual refresh, the image is refreshed only when an
OLED.REFRESH command is executed.
The
OLED.COLOR col
defines the color to be used by the different drawing commands. As
the display is monochrome, only the color 0 (black) and 1(white)
can be defined; an additional color 2 (reverse) permits to draw
objects in reverse to the existing color already present on the
screen; useful to draw and clear the same object. By default the
color is 1 (white).
The
OLED.IMAGE x, y,
image$ permits to draw an image on the screen from
a file. The file format must be XBM, a kind of ‘C’ source code.
This format is not really popular but it is supported by the free
tool Gimp.
The
OLED.BMP x, y,
image$ permits to draw an image on the screen from
a file. The file format must be BMP b&w (2 colors).
The command
OLED.FONT font_num
permits to define the font to be used by the command
OLED.PRINT.
There are 3 fonts available, ARIAL MT10,
ARIAL MT16, ARIAL MT24.
Example:
I2C.SETUP 21,
22 ' set I2C
port on pins 21 and 22
OLED.INIT
1
' init the
OLED upside-down
OLED.CLS
' clear the
screen
OLED.FONT
2
OLED.COLOR
1
OLED.PRINT
10,10, "HELLO
WORLD"
|
An ST7920 LCD display can be connected to the
module using SPI interface.
These displays are very cheap and available on
Ebay at less than 5€.
This picture shows an ST7920 with 128 x 64
pixel monochrome.
Some cheap boards will have PSB
connected to VDD (5v) This forces the parallel interface to be
used. Before you connect your display check that pin 2 (VDD ,5v)
and pin 15 (PSB) are not connected. If they are you may
need to cut a jumper. Otherwise you will short out your power
supply, and the display will not work.


This display is provided with a parallel
interface BUT it can be used with a SPI interface, so only 3 pins
are required.

In order to use the display, it must be
initialised.
This can be done with the following
command:
ST7920.INIT CS_pin
As per the wiring above, the command is
ST7920.INIT
15
After these 2
lines, there are several commands available :
ST7920.CLS,
ST7920.COLOR, ST7920.FONT, ST7920.PIXEL, ST7920.LINE, ST7920.RECT, ST7920.CIRCLE, ST7920.PRINT, ST7920.IMAGE, ST7920.BMP,ST7920.REFRESH
The current implementation of the ST7920 is
based on a double buffering; this permits drawing in background on
the screen while the current image is still shown. This technique
permits to avoid flickering while drawing objects on the screen.
The command
ST7920.REFRESH fmt
allows users to choose between an automatic refresh
(ST7920.REFRESH
1)
or a manual refresh (ST7920.REFRESH
0).
By default the refresh is automatic.
When an automatic refresh is set, the image is
immediately updated after each drawing command whereas, with the
manual refresh, the image is refreshed only when an
ST7920.REFRESH command is executed.
The
ST7920.COLOR col
defines the color to be used by the different drawing commands. As
the display is monochrome, only the color 0 (black) and 1(white)
can be defined; an additional color 2 (reverse) permits to draw
objects that reverse the existing color already present on the
screen; useful to draw and clear the same object. By default the
color is 1 (white).
The
ST7920.IMAGE x, y,
image$ permit to draw an image on the screen from a
file. The file format must be XBM, a kind of ‘C’ source code. This
format is not really popular but it is supported by the free tool
Gimp.
The
ST7920.BMP x, y,
image$ permits to draw an image on the screen from
a file. The file format must be BMP b&w (2 colors).
The command
ST7920.FONT font_num
permits to define the font to be used by the command
ST7920.PRINT.
There are 3 fonts available, ARIAL MT10,
ARIAL MT16, ARIAL MT24.
Example:
ST7920.INIT
15
' init the ST7920 with the CS at the
pin 15
ST7920.CLS
' clear the screen
ST7920.FONT
2
ST7920.COLOR
1
ST7920.PRINT
10,10,
"HELLO WORLD"
|
RTC module
A module based on chipset DS1307 or DS3231 can
be connected to the module using the I2C interface.
These modules are very cheap and available on
Ebay at less than 2€ (check if battery is included).
This picture shows a DS3231 module which is
very compact and already contains two 4.7K I2C pullups :

The connection is very simple, just 2 pins for
the I2C and the power supply are required.

Available Instructions:
RTC.DATE$[(format)]
RTC.TIME$
RTC.SETTIME Year,
Month, Day, Hours, Minutes, Seconds
The use of the RTC module is very simple.
First the I2C must be initialised with the
command
I2C.SETUP.
Then the date and the time can be read with
the string functions
RTC.TIME$ and
RTC.DATE$.
This time and date can be manually set using
the command
RTC.SETTIME.
The Syntax is :
RTC.SETTIME
Year, Month,
Day, Hours, Minutes, Seconds
Example
Set the date to 02 September 2017 at
13:58:12
RTC.SETTIME 17, 9, 2,
13, 58, 12
Example
I2C.SETUP 21,
22 ' set I2C
port on pins 21 and 22
Print
"The date is
" +
RTC.DATE$
Print
"The time is
" +
RTC.TIME$
|
A PWM / Servo module based on chipset
PCA9685 can be connected to the module using the I2C
interface.
These modules are very cheap and available on
Ebay at less than 2€.
This picture shows a PCA9685 module that makes
available up to 16 PWM / Servo outputs.
The PCA9685 is an I²C-bus controlled
16-channel controller optimized for Red/Green/Blue/Amber (RGBA)
color backlighting applications. It operates at a programmable
frequency from a typical of 24 Hz to 1526 Hz. All outputs share the
same PWM frequency.
The duty cycle for each output is adjustable
from 0 % to 100 % with 12-bit resolution (4096 steps).
It can also be used to control servo
actuators, simply specifying the PWM frequency at 50 Hz.


This module must be connected using I2C and,
because it already contains two 10K I2C pullups, no external
resistors are required.

Available Instructions:
PCA9685.SETUP address
PCA9685.SETFREQ freq
PCA9685.PWM
pin,
value
In order to use the module, it must be first
set with the command
PCA9685.SETUP address
Then the PWM frequency can be set with the
command
PCA9685.SETFREQ freq
FInally, the outputs can be driven with the
command
PCA9685.PWM pin,
value
This is an example that drives 2 servos
connected on outputs 0 and 1.
PCA9685.SETUP
&H40, 55
PCA9685.SETFREQ
50
PCA9685.PWM
0,
150
PCA9685.PWM
1,
100
DX
= 1
DY
= 1
MINX
= 100 : MAXX = 500
MINY
= 150 : MAXY = 300
X
= MINX : Y = MINY
WHILE
1
PCA9685.PWM 0, Y
PCA9685.PWM 1, X
PAUSE 30
PRINT Y, DY, MAXY
X
= X +
DX
Y
= Y +
DY
IF (X <
MINX) OR (X
> MAXX) THEN DX
= -
DX
IF (Y <
MINY) OR (Y
> MAXY) THEN DY
= -
DY
WEND
END
|
A display module based on the chipset TM1637
with 4 7-segments display can be connected to the module.
These modules are very cheap and available on
Ebay at around 1€.
This picture shows a module with 4 digits at
0.36”.

The following picture shows another module
with 4 digits at 0.56”.

The following picture shows another module
with 6 digits at 0.56”.

Notice that some modules have the “colon”
points in the middle, some have the decimal points and some other
have 6 digits including the decimal points
The connection is very simple, just 2 pins and
the power supply are required.
Even if the protocol is very similar to the
I2C, it is quite different, so the I2C pins used for other I2C
devices cannot be shared as this will conflict.

Available Instructions are:
TM1637.SETUP data_pin,
clock_pin [,
bit_delay] [,
display_type]
TM1637.PRINT msg$
[, brightness]
To use it, is very simple.
First initialise the display with the command
TM1637.SETUP
With the wiring above, the command must be
:
TM1637.SETUP 15,
16
Note that some modules may
already include i2c pullup resistors on board (so simply try first
without).
It is important to
highlight that some display modules may have a capacitor on
the input pins.
In that case it will
require an extra parameter (bit_delay) at the end of the
setup command.
This value can be
experimentally found, but a value of 100 should be appropriate for
all the modules.
Example :
TM1637.SETUP 15 16,
100
If a “6 digits display”
must be connected, another extra parameter (display_type)
is required.
Example :
TM1637.SETUP 15 16,
100, 1
The display can be used with the command
TM1637.PRINT msg$
[, brightness]
Where
msg$ is a text string that contains the
message to show
brightness defines the luminosity of
the display from 0 (OFF) to 7 (MAX); if omitted the value is 7
All ASCII
characters can be used but will be shown within the limitation of
the 7 segments of the display.
The decimal point
and the colon (:)
are automatically managed so, to print 12:34 on the display, simply
use
TM1637.PRINT
"12:34" or
TM1637.PRINT
"1.234"
Example
TM1637.SETUP
15, 16,
100
For
i
= 0 to 9999
TM1637.PRINT str$(i),
4
Next
i
|
A display module based on the chipset TM1638
with 8 7-segments display can be connected to the module.
These modules provide 8 LEDs, 8 Digits and 8
Keypad Interface.
These modules are very cheap and available on
Ebay at around 2€.
This picture shows a module with 8 digits at
0.36”, 8 leds and 8 buttons

The connection requires 3 pins plus the power
supply.

Available Instructions are:
TM1638.BUTTONS
TM1638.PRINT msg$
[, brightness ]
TM1638.SETUP data_pin,
clock_pin, strobe_pin
TM1638.LEDS val
To use it is very simple.
First initialise the display with the command
TM1638.SETUP data_pin,
clock_pin, strobe_pin
With the wiring above, the command must be
:
TM1638.SETUP 21, 22,
15
The display can then be used with the command
TM1638.PRINT msg$
[, brightness ]
Where
msg$ is a text string that can contain
up to 8 chars ,
brightness defines the luminosity of
the display from 0 (OFF) to 15 (MAX); if omitted the value is
15
All ASCII
characters can be used but will be shown within the limitation of
the 7 segments of the display.
Example
TM1638.SETUP
21, 22,
15
For
i
= 0 to 9999
TM1638.PRINT str$(i)
Next
i
|
As the module also contains 8 leds, it is
possible to control them using the command
TM1638.LEDS val.
val is a 8 bit number where each bit is
associated to a led.
Example
TM1638.SETUP
21, 22,
15
For
i
= 0 to 255
TM1638.LEDS i
Next
i
|
It is also possible to get the status of the
buttons with the function
TM1638.BUTTONS
Example
TM1638.SETUP
21, 22,
15
For
i
= 0 to 5000
Print TM1638.BUTTONS
Next
i
|
A display module based on the chipset MAX7219
with 8 7-segments display can be connected to the module.
These modules provides 8 Digits
7-segments display including dot points.
These modules are very cheap and available on
Ebay at around 2€.
This picture shows a module with 8 digits at
0.36”.


The wiring is done using the SPI bus plus a
dedicated CS pin.

Available Instructions are:
MAXDISPLAY.SETUP CS_pin
MAXDISPLAY.PRINT msg$
[,brightness]
To use it is very simple.
First initialise the display with the command
MAXDISPLAY.SETUP CS_pin
With the wiring above, the command must be
:
MAXDISPLAY.SETUP 15
The display can then be used with the command
MAXDISPLAY.PRINT msg$
[,brightness]
Where
msg$ is a text string that can contains
up to 8 chars ,
brightness defines the luminosity of
the display from 0 (OFF) to 15 (MAX); if omitted the value is
15
All ASCII
characters can be used but will be shown within the limitation of
the 7 segments of the display.
Example
MAXDISPLAY.SETUP
15
For
i
= 0 to 9999
MAXDISPLAY.PRINT str$(i)
Next
i
|
It is also possible to connect dot matrix
modules based on the chipset MAX7219.
These modules contain 4 8x8 dot matrix
displays each one with a dedicated MAX7219 chip.
These modules can be chained in order to
compose a larger display.
The picture shows a module available on Ebay
at around 5€.


The wiring is done using the SPI bus plus a
dedicated CS pin.

Available Instructions are:
MAXSCROLL.SETUP nb_devices,
CS_pin
MAXSCROLL.PRINT msg$
MAXSCROLL.NEXT msg$
MAXSCROLL.TEXT msg$
MAXSCROLL.SHOW position
[, brightness]
MAXSCROLL.SCROLL
[brightness]
MAXSCROLL.OSCILLATE
[brightness]
To use it, the first command required is the
setup of the display.
This can be done with the command
MAXSCROLL.SETUP nb_devices,
CS_pin.
The first argument defines
the number of 8x8 displays connected; using the module shown above,
the number is 4.
The 2nd argument defines
the pin used for the CS signal; using the schematic shown above the
pin is 15 (GPIO15). In our case the command must be :
MAXSCROLL.SETUP
4,
15
The text can then be set on the display with 3
different commands :
1.
MAXSCROLL.PRINT
msg$
2.
MAXSCROLL.NEXT
msg$
3.
MAXSCROLL.TEXT msg$
The first will set the text that will be shown
at the beginning, the 2nd will set the text that will be shown when
the first one will be scrolled out of the display and the 3rd will
permit to modify immediately the text shown.
For example,
MAXSCROLL.PRINT
"Hello"
MAXSCROLL.NEXT
"Friend"
Will permit to show “Hello” at the beginning;
then as soon as “Hello” is scrolled out of the screen, the text
“Friend” will be shown and it will scroll on the display forever
until the next execution of the command
MAXSCROLL.NEXT msg$
The command
MAXSCROLL.TEXT msg$
will permit to modify the text during the scrolling sequence,
useful for “dynamic” messages (i.e time/date information).
The command
MAXSCROLL.SHOW position
[,
brightness] will
permit to move the text in a given position.
The position 1 is the rightmost line of the
display, and increasing this value will move the text more to the
left.
Optionally it is possible to define the
brightness of the display.
The last set of commands is composed of
1.
MAXSCROLL.SCROLL
[brightness]
2.
MAXSCROLL.OSCILLATE
[brightness]
The first will permit to scroll the text from
the right to the left and, when the text will be completely
scrolled out, it will restart again with the same text or, if
defined, with the text set with the command
MAXSCROLL.NEXT.
The 2nd will permit to scroll the text from
the right to the left and, when the text will be completely
scrolled out, it will be scrolled back in the opposite direction
until it will reach the initial position, then the process will
restart again.
These 2 commands have an optional parameter
permitting to define the luminosity of the display in a range from
0 (min) to 15 (max); the default value is 0.
As the message requires a continuous
scrolling, these commands must be called on a timed interval (using
a timer).
Let us show an example using the SCROLL
command
'Set 4 8x8
displays with GPIO15 as CS pin
MAXSCROLL.SETUP
4,
15
'Set the
first message as the current time
MAXSCROLL.PRINT
TIME$
'Set the
second message as the current date
MAXSCROLL.NEXT
DATE$
'Set the
refresh rate of the display (50 msec) - lower values -> scroll
faster
TIMER0
50,
SCROLLME
WAIT
SCROLLME:
'Scroll the display with an intensity of
5
MAXSCROLL.SCROLL 5
RETURN
|
This is another example using the
OSCILLATE command:
'Set 4 8x8
displays with GPIO15 as CS pin
MAXSCROLL.SETUP
4, 15
'Set the
message
MAXSCROLL.PRINT
"Hello
World"
'Set the
refresh rate of the display (50 msec) - lower values -> scroll
faster
TIMER0
50,
SCROLLME
WAIT
SCROLLME:
'Oscillate
the display with an intensity of 5
MAXSCROLL.OSCILLATE
5
RETURN
|
It is possible to connect NeoPixel led strips
based on WS2812B Leds.
These strips are generally available in a
linear form but also as a circular array.


The wiring is very simple as only one output
pin is required for the ESP32.
The strips must be supplied at 5V with a
dedicated power-supply.
As each led could require up-to 60mA, the
power supply must be sized in consequence.
The strip is considered as a sequence of leds
where each one has a position and can have a different color.
From a logical point of view, even the
circular array is seen as a linear strip with a start and end
position.
Then the following commands are available
:
FUNCTIONS / COMMANDS
|
DESCRIPTION
|
|
Setup the led strip.
The first argument defines the GPIO pin used
and the 2nd argument defines the number of leds of the strip
|
NEO.STRIP
led_start_pos, led_end_pos,
R, G, B [, disable]
|
Set the leds from the position
led_start_pos to the position led_end_pos with the
color defined by R, G and B. The optional
argument [,
disable] if set to 1, permits to write new led values
into memory without refreshing the strip.
|
NEO.STRIP
led_start_pos, led_end_pos,
COLOR [, disable]
|
Set the leds from the position
led_start_pos to the position led_end_pos with the
color defined by COLOR. The optional argument
[, disable] if set to 1, permits to write new led values
into memory without refreshing the strip.
|
NEO.PIXEL
led_pos, R,
G, B [, disable]
|
Set the led at the position led_pos with
the color defined by R, G and B. The
optional argument [,
disable] if set to 1, permits to write new led values
into memory without refreshing the strip.
|
NEO.PIXEL
led_pos,
COLOR [, disable]
|
Set the led at the position led_pos with the
color defined by COLOR. The optional argument
[, disable] if set to 1, permits to write new led values
into memory without refreshing the strip.
|
|
Returns a combined color containing the
R, G and B components
|
|
Returns the combined color of the pixel at the
position led_pos
|
NEO.ROTATELEFT
num_steps,
[led_end_pos,
led_end_pos, disable]
|
Rotate left the leds of num_steps from
the position led_start_pos to the position
led_end_pos. The optional argument [,
disable] if set to 1, permits to write new led values
into memory without refreshing the strip.
|
NEO.ROTATERIGHT
num_steps,
[led_end_pos,
led_end_pos, disable]
|
Rotate right the leds of num_steps from
the position led_start_pos to the position
led_end_pos. The optional argument [,
disable] if set to 1, permits to write new led values
into memory without refreshing the strip.
|
NEO.SHIFTLEFT
num_steps,
[led_end_pos,
led_end_pos, disable]
|
Shift left the leds of num_steps from
the position led_start_pos to the position
led_end_pos. The optional argument [,
disable] if set to 1, permits to write new led values
into memory without refreshing the strip.
|
NEO.SHIFTRIGHT
num_steps,
[led_end_pos,
led_end_pos, disable]
|
Shift right the leds of num_steps from
the position led_start_pos to the position
led_end_pos. The optional argument [,
disable] if set to 1, permits to write new led values
into memory without refreshing the strip.
|
|
Refresh the strip from the internal buffer
memory
|
|
Returns a color with a given gain.
If gain is 1, returns the original color
If gain is below 1, returns a darker color
If gain is greater than 1, returns a brighter
color
|
|
Returns a color blended toward white
Gain can go from 0 (original COLOR)
to 1 (white)
|
|
Returns a color blended toward black
Gain can go from 0 (original COLOR)
to 1 (black)
|
|
Returns a color blended toward COLOR1
and COLOR2,
Gain can go from 0 (COLOR1)
to 1 (COLOR2)
|
|
Returns a color blended toward 4 colors by the
amount defined by 2 variables, x
and y.
With x=0
and y=0
returns Upper_Left_COLOR
With x=1
and y=0
returns Lower_Left_COLOR
With x=0
and y=1
returns Upper_Right_COLOR
With x=1
and y=1
returns Lower_Right_COLOR
|
The first command,
NEO.SETUP pin,
[nb_led], defines the pin to be used as output and the
size (in pîxels) of the led strip.
For example
NEO.SETUP 2,
60 defines a strip containing 60 leds (or a ring
with 60 leds) connected on the pin GPIO02.
This creates a local memory buffer of the
strip line permitting the manipulation of the colors in the
background.
Then, the leds of the strips can be addressed
taking into account that the first led has the position 0 and the
last has the position (nb_led - 1).
For example, using the declaration
NEO.SETUP 2,
60, the last led has the position 59.
The leds can then be addressed individually
using the command
NEO.PIXEL or as a block using the commandNEO.STRIP.
For example,
NEO.PIXEL 10, 255,
0, 0 sets the led at the position 10 with the
color RED and the command
NEO.STRIP 20, 30, 0,
0, 255 sets the leds at positions 20 through 30
with the color BLUE
The colors can be specified as a sequence of 3
numbers from 0 to 255 representing the intensity for the Red, Green
and Blue components, or as a single 24bit number where the 3 colors
are merged together as one.
The function
NEO.RGB(R,
G, B) permits to
generate this merged color.
For example, these 3 commands produce the same
effect :
NEO.STRIP
0, 10, 0,
255, 0
NEO.STRIP
0, 10,
NEO.RGB(0, 255, 0)
NEO.STRIP
0, 10,
65280
The optional argument [,
disable] if set to 1, permits to write new led values
into memory without refreshing the strip. This is useful to
manipulate several leds, refreshing the complete line only when
required.
For example, with the following program, all
the leds will be refreshed one by one at 100ms interval :
NEO.SETUP 2,
60
FOR z
= 0 TO 59
NEO.PIXEL z, 128
PAUSE 100
NEXT z
But, with the following program, all the leds
will be updated in a single shot at the end (after 6 seconds) :
NEO.SETUP 2, 60
FOR z
= 0
TO 59
NEO.PIXEL z, 128,
1
PAUSE 100
NEXT z
NEO.REFRESH
It is also possible to connect Dot Matrix
modules based on WS2812B Leds.
These modules contain 64 WS2812B leds
organised in an 8x8 matrix.
Several modules can be chained in order to
compose a large display.


They can also be spanned in several chained
lines to compose taller displays.
The wiring is very simple as only one output
pin is required for the ESP32.
The modules must be supplied at 5V with a
dedicated power-supply.

It must be taken into account that these 8x8
modules can require a lot of current, in particular if all the leds
are at max intensity.
As each led could require up-to 60mA, the
power supply must be sized accordingly.
From a practical point of view, the displays
will probably never show all the pixels at the same time, so we can
consider at least 2 amps per display (so 20 amps for 10
displays).
The displays available on the market can be
arranged differently using a “normal” or a “serpentine” layout.
Several configurations are supported; use the
LAYOUT number below each image below in the
NEOSCROLL.SETUP command
LAYOUT 0 and 1

LAYOUT 2 and 3

LAYOUT 4 and 5

The actual implementation is based on a
“canvas” where it is possible to draw any content using pixels,
texts, images and then scroll it horizontally or vertically as
desired.
This gives a great flexibility as the message
can be composed of any combination of elements (Text + images, for
example) and changed dynamically during the scrolling process.
This could be considered as a kind of TFT
display with the resolution determined by the number of leds
present.
For the same reason, the colors (65K) and the
fonts are managed in the same way as for the TFT (more details
inside the TFT chapter).
All the actions on the display (write text,
drawing bmp, …) are done internally into a memory space reserved
for that scope. The result will be transferred on the display
itself only when using the command
NEOSCROLL.SHOW or the commands
NEOSCROLL.SCROLL /
NEOSCROLL.OSCILLATE.
The advantage of this approach is that an
image containing several elements can be prepared in the background
and transferred to the display only when it has been completed.
Available Instructions are:
FUNCTIONS / COMMANDS
|
DESCRIPTION
|
NEOSCROLL.SETUP
nb_devices,
nb_lines, pin [,layout] [,width, height,
orientation]
|
Setup the Neoscroll display.
The first argument defines the number of
devices connected eventually spanned on several lines; for the
layouts 2 and 3, this represents the number of leds for each
line
The 2nd argument defines the number of lines
composed by the modules; for the layouts 2 and 3 this represents
the number of lines of pixels (and not modules) using the
schematic shown above, the number is 1.
The 3rd argument defines the pin used for the
input signal; using the schematic shown above the pin is 2
(GPIO2).
The 4th argument defines the layout of the
display itself arranged following the layout shown in the pictures
above.
The optional 5th and 6th arguments define the
size of the ‘canvas’ that will be created.
If not specified, the canvas will have the
same size as the display (in pixels).
The optional 7th argument, if set to 1, will
reverse the image upside-down.
|
|
Remove the driver from the memory in the
eventuality that is not required anymore.
|
NEOSCROLL.FILL
color, [x,
y, width, height]
|
Fill the display with a given color; by
default the complete canvas is filled with this color but only a
specific area can be defined giving the other parameters.
|
|
Set the position where the text will be drawn.
By default the position is set at the bottom left of the display to
comply with the Adafruit GFX font format that use the lower
position of the font as reference.
|
|
Set the font that must be used; by default
there is a font #1 that is 5x7 proportional. The font 10 to 13 can
be used loading them with the
TFT.LOADFONT command
|
|
Transfer the content of the internal memory
space to the display itself so that the image will be
refreshed.
‘x’ and ‘y’ represent the offset of the
initial position to be shown.
|
|
Set the brightness of the text to draw; can be
different for each text drawn.
Its value can be from 0 to 255 and defaults to
255
|
|
Set the brightness of the entire image; the
effect will be visible only at the next screen redraw.
Its value can be from 0 to 255 and defaults to
128
|
|
Print a text on the canvas at the current
cursor position using the current font..
The ‘text$’ itself is coupled to the ‘color$’
information where each character defines the color of each
character of the text. The logic is based on a one-to-one
correspondence between the text string and the color string.
If the color string is shorter than the text
or is missing the color will be the last color used.
B
|
TFT_BLUE
|
b
|
TFT_NAVY
|
C
|
TFT_CYA;
|
c
|
TFT_DARKCYAN
|
G
|
TFT_GREEN
|
g
|
TFT_DARKGREEN
|
K
|
TFT_BLACK
|
k
|
TFT_DARKGREY
|
M
|
TFT_MAGENTA
|
m
|
TFT_MAROON
|
R
|
TFT_RED
|
r
|
TFT_DARKRED
|
Y
|
TFT_YELLOW
|
y
|
TFT_GREENYELLOW
|
O
|
TFT_ORANGE
|
o
|
TFT_OLIVE
|
P
|
TFT_PURPLE
|
p
|
TFT_PINK
|
W
|
TFT_WHITE
|
w
|
TFT_LIGHTGREY
|
S
|
TFT_SILVER
|
|
|
Load a BMP color image in memory. Portions of
this image can be extracted and copied into the canvas
afterwards
|
NEOSCROLL.SPRITE
x, y, width,
height, x_in_bmp, y_in_bmp
|
Copy a portion of
the SPRITESHEET
image into the canvas using the parameters given
|
|
Defines the limits of the scrolling area. By
defaults these are automatically set at the size of the canvas but
can be modified dynamically to scroll only a given portion of the
canvas.
|
|
Can be used to sync the
LIMITS after a printing / drawing command.
|
|
Set the scrolling mode as below
0
|
Horizontal from right to left
|
1
|
Vertical from bottom to top
|
2
|
Horizontal from left to right
|
3
|
Vertical from top to bottom
|
|
|
If used as a
function, it returns a value of 1 when the animation is over (limit
reached); this is useful to determine when the message must be
changed
|
|
If used as a
function, it returns a value of 1 when the animation is over (limit
reached); this is useful to determine when the message must be
changed
|
|
Returns the current X position
|
|
Returns the current Y position
|
To use it, the first command required is the
setup of the display.
This can be done with the command
NEOSCROLL.SETUP nb_devices,
nb_lines, pin [,serpentine] [,width, height]
The first argument defines the number of 8x8
modules connected; using the schematic shown above, the number is
4.
The 2nd argument defines the number of lines
composed by the 8x8 modules; using the schematic shown above, the
number is 1.
The 3rd argument defines the pin used for the
input signal; using the schematic shown above the pin is 2
(GPIO2).
The 4th argument defines if the display itself
is arranged in a linear way or as a serpentine.
If it is 0 (default) the normal layout is
selected, if it is 1, the serpentine layout is chosen.
The optional 5th and 6th arguments define the
size of the ‘canvas’ that will be created.
If not specified, the canvas will have the
same size of the display (in pixels).
In our case the command must be :
NEOSCROLL.SETUP
4, 1, 2, 0
'4 displays, 1 row, pin 2, no
serpentine
The text can then be set on the display with
the following command
NEOSCROLL.PRINT
text$,
color$
This command will print a text at the actual
cursor position (the left lower corner of the display, by
default).
The cursor will be automatically moved at the
end of this text so, a successive print, will be attached at the
end
For example,
NEOSCROLL.PRINT
"Hello" , "RGBYM" 'will
print Hello with different colors
NEOSCROLL.PRINT
"Friend", "B" 'will print Friend in Blue after
Hello
The command
NEOSCROLL.SHOW x,
y will permit displaying the text in a given
position.
Negative and positive values are possible
The position 0,0
corresponds to the left lower corner.
Specifying, for example 1,0
the the text shown will be shifted of 1 pixel at the left
The last set of commands is composed of
NEOSCROLL.SCROLL
NEOSCROLL.OSCILLATE
The first will permit to scroll the text from
the right to the left and, when the text will be completely
scrolled out, it will restart again with the same text
The 2nd will permit to scroll the text from
the right to the left and, when the text will be completely
scrolled out, it will be scrolled back in the opposite direction
until it will reach the initial position, then the process will
restart again.
These 2 commands can optionally be used as
functions; in this case the returned value will be always 0 except
when the animation is terminated (one of the limits reached); this
can be used to determine the right moment for changing the
scrolling message.
As the message requires a continuous
scrolling, these commands must be called on a timed interval (using
a timer).
Let us show a basic example
'Set 4
WS2812B displays with GPIO2 as input
neoscroll.setup 16, 2, 5,
0
neoscroll.fill 0
neoscroll.show 0,
0
neoscroll.print
"Hello World", "R"
neoscroll.show 0,0
|
This is another example using the
OSCILLATE command and vertical scroll:
'Set 8
WS2812B displays with GPIO2 as input
data
"Hello World!", "rgbyMrgbyMrgbyM", 1
data
"How are you?", "gyMrgbyM", 10
data
"Annex&Neopixels", "byMvkwbrgbyM", 11
data
"Feel so good!", "yMrgbyMrgbyM", 1
dim
msg$(10)
dim
col$(10)
dim
myfont(10)
for
z
= 0 to 3
read msg$(z),
col$(z), myfont(z)
next
z
seq = 0
nb_messages = z
wlog
ramfree
neoscroll.setup
8, 1, 5, 0,
128, 128
for
z
= 0 to nb_messages -1
neoscroll.text.pos
0, z * 10 + 7
neoscroll.print
msg$(z)
+ chr$(10),
col$(z)
next
z
neoscroll.mode
1'vertical
neoscroll.sync
neoscroll.limits 0,0,
-7, 39
pause
100
timer0
100,
scrolla
timer1
900,
mytime
wait
scrolla:
a = neoscroll.oscillate
Return
mytime:
neoscroll.text.pos
0, 47
neoscroll.fill 0, 0, 40,
63, 47
neoscroll.print
TIME$, "b"
return
|
This is another example with horizontal scroll
and several fonts
'Set 16
WS2812B displays on 2 rows with GPIO2 as input
data
"Good Morning", "rgbyMrgbyMrgbyM", 1
data
"How are you?", "rgbyMrgbyM", 10
data
"ANNEX AND NEOPIXELS", "rgbyMvkwbrgbyM", 11
data
"WORKS VERY WELL TOGETHER", "rgbyMrgbyMrgMrgMrgMrgbyM", 1
dim msg$(10)
dim col$(10)
dim myfont(10)
for z
= 0 to 3
read msg$(z),
col$(z), myfont(z)
next z
seq
= 0
nb_messages
= z
wlog
ramfree
neoscroll.setup 16, 2, 2,
0, 512, 32
neoscroll.show 0,
0
tft.loadfont
"/fonts/T3_16_Bold10pt7b.bin", 1
tft.loadfont
"/fonts/FreeSerifBold12pt7b.bin", 2
neoscroll.spritesheet
"/bmp16x16/danger.bmp"
set_message
neoscroll.sprite neoscroll.x,
0, 16, 16, 0, 0
neoscroll.sync
neoscroll.mode
0'horizontal
timer0 30,
scrolla
wait
sub set_message
neoscroll.fill 0
neoscroll.text.pos 0,
15
neoscroll.text.font
myfont(seq)
neoscroll.print msg$(seq),
col$(seq)
wlog "dim", neoscroll.x,
neoscroll.y
neoscroll.sprite neoscroll.x, 0,
16, 16, 0, 0
neoscroll.sync
seq
= seq + 1
if seq >= nb_messages then seq =
0
end
sub
scrolla:
a
= neoscroll.oscillate
if
(a = 1) then
set_message
return
|
DMAMATRIX
-
Only the 64x64 panels are actually supported
-
The parameters specified with .INIT and .SETUP cannot be changed
without resetting the module (this is a driver limitation
limitation)
-
Only ESP32-S3 has been tested and supported
actually



FUNCTIONS / COMMANDS
|
DESCRIPTION
|
DMAMATRIX.INIT
R1, G1, B1,
R2, G2, B2, A, B, C, D, E, LAT, OE, CLK [,freq_DMA]
[,resolution]
|
Defines the pin to be used for the
display.
The optional ‘freq_DMA’ can be defined (by
default is 20000000 -> 20Mhz)
The optional ‘resolution’ from 2 to 8 bits can
be defined (by default is 8); lower value consumes less RAM
memory
|
DMAMATRIX.SETUP
nb_devices,
nb_lines [,layout] [,width, height, orientation]
|
Setup the Neoscroll display.
The first argument defines the number of
devices connected eventually spanned on several lines; for the
layouts 2 and 3, this represents the number of leds for each
line
The 2nd argument defines the number of lines
composed by the modules; for the layouts 2 and 3 this represents
the number of lines of pixels (and not modules) using the
schematic shown above, the number is 1.
The 3th argument defines the layout of the
display (not fully implemented; actually
if this is an odd number, it enables a double buffer for the
display itself; this speeds up the update operation as only the
modified pixels are transferred to the DMA buffer
memory).
The optional 4th and 5th arguments define the
size of the ‘canvas’ that will be created.
If not specified, the canvas will have the
same size as the display (in pixels).
The optional 6th argument, if set to 1, will
reverse the image upside-down (not yet
implemented).
IMPORTANT:
This command can be used only once in the
code.
Calling it again with other parameters will not have
any effects if the module is not rebooted before
|
|
Remove the driver from the memory in the
eventuality that is not required anymore.
Do not work
properly : the memory is released but a reset of the module is
required for restarting the image
|
DMAMATRIX.FILL
color, [x,
y, width, height]
|
Fill the display with a given color; by
default the complete canvas is filled with this color but only a
specific area can be defined giving the other parameters.
|
|
Set the position where the text will be drawn.
By default the position is set at the bottom left of the display to
comply with the Adafruit GFX font format that uses the lower
position of the font as reference.
|
|
Set the font that must be used; by default
there is a font #1 that is 5x7 proportional. The font 10 to 13 can
be used loading them with the
TFT.LOADFONT command
|
|
Set the default text color to be used
|
|
Transfer the content of the internal memory
space to the display itself so that the image will be
refreshed.
‘x’ and ‘y’ represent the offset of the
initial position to be shown; if omitted both default to 0
|
|
Set the brightness of the text to draw; can be
different for each text drawn.
Its value can be from 0 to 255 and defaults to
255
|
|
Set the brightness of the entire image; the
effect will be visible only at the next screen redraw.
Its value can be from 0 to 255 and defaults to
90
|
|
Print a text on the canvas at the current
cursor position using the current font..
The ‘text$’ itself is coupled to the ‘color$’
information where each character defines the color of each
character of the text. The logic is based on a one-to-one
correspondence between the text string and the color string.
If the color string is shorter than the text
or is missing the color will be the last color used.
B
|
TFT_BLUE
|
b
|
TFT_NAVY
|
C
|
TFT_CYA;
|
c
|
TFT_DARKCYAN
|
G
|
TFT_GREEN
|
g
|
TFT_DARKGREEN
|
K
|
TFT_BLACK
|
k
|
TFT_DARKGREY
|
M
|
TFT_MAGENTA
|
m
|
TFT_MAROON
|
R
|
TFT_RED
|
r
|
TFT_DARKRED
|
Y
|
TFT_YELLOW
|
y
|
TFT_GREENYELLOW
|
O
|
TFT_ORANGE
|
o
|
TFT_OLIVE
|
P
|
TFT_PURPLE
|
p
|
TFT_PINK
|
W
|
TFT_WHITE
|
w
|
TFT_LIGHTGREY
|
S
|
TFT_SILVER
|
|
|
Load a BMP color image in memory. Portions of
this image can be extracted and copied into the canvas
afterwards
|
DMAMATRIX.SPRITE
x, y, width,
height, x_in_bmp, y_in_bmp
|
Copy a portion of the
SPRITESHEET
image into the canvas using the parameters given
|
|
Defines the limits of the scrolling area. By
default these are automatically set at the size of the canvas but
can be modified dynamically to scroll only a given portion of the
canvas.
|
|
Can be used to sync the
LIMITS after a printing / drawing command.
|
|
Set the scrolling mode as below
0
|
Horizontal from
right to left
|
1
|
Vertical from
bottom to top
|
2
|
Horizontal from
left to right
|
3
|
Vertical from top
to bottom
|
|
|
If used as a
function, it returns a value of 1 when the animation is over (limit
reached); this is useful to determine when the message must be
changed
|
|
If used as a
function, it returns a value of 1 when the animation is over (limit
reached); this is useful to determine when the message must be
changed
|
|
Draws a pixel
|
|
Draws a line
|
|
Draws a circle
If ‘fill’ = 1 the circle will be filled
|
|
Draws a rectangle
If ‘fill’ = 1 the rectangle will be filled
|
|
Returns the current X position
|
|
Returns the current Y position
|
|
Returns the current X position in the
animation sequence
|
|
Returns the current Y position in the
animation sequence
|
|
Plays an animated GIF image from disk.
The frames of the GIF image are shown
immediately on the screen at the position x, y (or, if not defined,
from 0,0).
Important : This is a blocking
function
|
|
Load an animated GIF image in memory from
disk.
The frames of the GIF image can extracted and
copied into the canvas afterwards starting from the position x, y
(or, if not defined, from 0,0)
|
|
Shows a frame of the GIF image.
By default the frame is shown directly; if the
parameter ‘do_not_show” is 1, the frame is only loaded in the
buffer.
If the parameter ‘loop’ is 1, the gif will
loop (will repeat from the beginning when the last frame is
reached).
This function returns 0 if the last frame has
been reached or the number of ms to wait before the next frame to
respect the GIF framerate.
|
An SD CARD can be connected using a module
wired as below:

The following SD CARD modules have been
successfully tested with Annex32:
Module for MicroSD with active buffer on
board.
As this module sports a voltage regulator that
converts 5V to 3.3V, it is required to bypass it using the
connection as shown in the picture below:


Module for full size SD-CARD with passive
adapters:

A TFT Display based on chipset ILI9341 can be
connected to the module using the SPI interface.
These displays are available on Ebay at
different sizes from 2.2” to 3.2” and are very cheap.
The resolution of the display is 320 x 240
pixels with 65K colors.
They can also include a touchscreen controller
to receive positional feedback via the SPI interface.
The model shown below is a 2.8” and contains
an interface for the Touch Screen.
As the interface is SPI, the display requires
at least 5 pins when connected as a display only and 6 when the
touch screen is enabled.
Additionally these displays also include
a reader that can be used to connect an SDCARD to the
module.
The image below shows an 2.8” display provided
with touch screen interface:


These displays have a little jumper
zone (J1) that must be solder-bridged if powering the module from
3.3V else it will be configured to work at 5v.
Wiring with touch and
SDCARD


In order to use the
TFT, the first step is to initialise the Display
This
can be done with the following commands :
TFT.INIT Orientation
Orientation is
a number between 0 and 3 specifying the TFT orientation:
0
|
Portrait
|
1
|
Landscape
|
2
|
Portrait
reversed
|
3
|
Landscape
reversed
|
The
display is initialised, by default, at 40MHz (40 000 000) but many
displays can also work at 80Mhz.
This
can be changed with the command
TFT.SETFREQ 80000000
Increasing the speed at 80 Mhz improve the performances of the
display but this does not work for all the displays (for example
does not works for the M5Stack)
The
display can then be cleared with the command
TFT.FILL color
The
display is now ready to receive drawing commands.
The
list of commands and functions available is described further below
in the Chapter “Lovyan GFX”
The
color is defined as a number between 0 and 65535; this corresponds
to the color format named 565 where 5 bits are dedicated to Red, 6
to green and 5 to blue.
The
function TFT.RGB permits to specify the R,G,B components as numbers
from 0 to 255.
For
example the function TFT.RGB(255,0,0) defines the color RED and
TFT.RGB(0,255,0) defines the color green.
It is
also possible to define a color giving directly its name.
The
function is
TFT.COLOR(colorname)
Colorname can be :
BLACK
|
NAVY
|
DARKGREEN
|
DARKCYAN
|
MAROON
|
PURPLE
|
OLIVE
|
LIGHTGREY
|
DARKGREY
|
BLUE
|
GREEN
|
CYAN
|
RED
|
MAGENTA
|
YELLOW
|
WHITE
|
ORANGE
|
GREENYELLOW
|
PINK
|
BROWN
|
GOLD
|
SILVER
|
SKYBLUE
|
VIOLET
|
Optionally it is also possible to define the color directly with
its name even without using the TFT.COLOR syntax.
For sake of clarity
this shows all the possible ways to define the same color :
TFT.FILL 0
Or
TFT.FILL
TFT.RGB(0, 0,
0)
Or
TFT.FILL
TFT.COLOR(black)
Or
TFT.FILL black
The same logic can
be applied for any command requiring a color such as
TFT.TEXT.COLOR red
However,
TFT.COLOR(colorname)
can be used into regular expressions as it returns the numeric
value of the color whilst the colorname
itself can be used only as argument in the functions that require a
color.
For example
Col
= TFT.COLOR(red) + TFT.COLOR(blue)
Is a valid
expression
but
Col
= Red + blue
Is not a valid
expression.
The
backlight of the display is controlled using a PWM output on the
pin defined in the configuration of the module. By default, for the
classic ESP32, it is assigned to GPIO32.
The
command
TFT.BRIGHTNESS value
(from 0 to 255) can be used to control the luminosity.
Look at
the documentation for the details of each command.
Example
:
Tft.init 1
tft.fill 0
for r
= 0 to 30000 step 0.02
d=r/6
s=sin(r)*sin(5*r+d)*140+160
c=cos(r)*sin(5*r+d)*100+120
tft.circle
s,c,10,rnd(65535),1
next r
|
It is
also possible to save (dump) the content of the screen into a file
on the disk (LFS or SDCARD).
Note: This will not work for all modules/TFTs because some do
not allow reading through the SPI input bus or simply because the
SPI input is not wired to the TFT.
This is the case, in particular, for the M5Stack.
The
command is
TFT.SAVE “/dumpfile.bmp”.
The
file will be stored in .BMP format.
A TFT Display based on chipset ILI9163 can be
connected to the module using the SPI interface.
These displays are available on Ebay in
different sizes and are very cheap.
The model shown below is a 1.8” with a
resolution of 160 x 128 pixels with 65K colors.
As the interface is SPI, the display requires
at least 5 pins.
Additionally these displays also include a
card reader that can be used to connect an SDCARD to the
module.


These displays have a little jumper
zone (J1) that must be solder-bridged if powering the module from
3.3V else it will be configured to work at 5v.
A TFT Display based on chipset ILI9486 can be
connected to the module using the SPI interface.
These displays are available on Ebay with a
size of 3.5” and are quite cheap.
The resolution of the display is 480 x 320
pixels with 65K colors.
They can also include a touchscreen controller
to receive positional feedback via the SPI interface.
As the interface is SPI, the display requires
at least 5 pins when connected as a display only, and 6 when the
touch screen is used.
This display is a great option compared to the
ILI9341 as the higher resolution enables the creation of nicer GUI
pages with a better touchscreen interaction.
These displays have a connector adapter for
the Raspberry Pi but can easily be used with Annex.
They are built on the Waveshare design and use
a 16 bit serial interface based on the 74HC04, 74HC4040 and 2 x
74HC4094 logic chips.
The SPI max speed for these displays is
20Mhz.
This display is configured to be
supplied with 5V so the Voltage regulator must be bypassed (solder-
bridged) if it is supplied with 3.3V.



A TFT Display based on chipset ILI9481 can be
connected to the module using the SPI interface.
These displays are available on Ebay with a
size of 3.5” and are quite cheap.
The resolution of the display is 480 x 320
pixels with 65K colors.
They can also include a touchscreen controller
to receive positional feedback via the SPI interface.
As the interface is SPI, the display requires
at least 5 pins when connected as a display only, and 6 when the
touch screen is used.
This display is a great option compared to the
ILI9341 as the higher resolution and the quite large size of the
screen enables the creation of nicer GUI pages with a better
touchscreen interaction.
In addition it shares the same connector
pinout with the ILI9341 modules so can then be used on PCBs already
designed for the ILI9341.
The SPI max speed for these displays is 10 Mhz
so it is quite slow.
Additionally these displays also include
a reader that can be used to connect an SDCARD to the
module.

A TFT Display based on chipset ILI9488 can be
connected to the module using the SPI interface.
These displays are available on Ebay with a
size of 3.5” and are quite cheap.
The resolution of the display is 480 x 320
pixels with 65K colors.
They can also include a touchscreen controller
to receive positional feedback via the SPI interface.
As the interface is SPI, the display requires
at least 5 pins when connected as a display only, and 6 when the
touch screen is used.
This display is a great option compared to the
ILI9341 as the higher resolution and the quite large size of the
screen enables the creation of nicer GUI pages with a better
touchscreen interaction.
In addition it shares the same connector
pinout with the ILI9341 modules so can then be used on PCBs already
designed for the ILI9341.
The SPI max speed for these displays is 40
Mhz.
Additionally these displays also include
a reader that can be used to connect an SDCARD to the
module.

A TFT Display based on chipset ST7735 can be
connected to the module using the SPI interface.
These displays are available on Ebay in
different sizes and resolutions and are very cheap.
Because there are many variants of this
display, Annex32 supports 8 different ST7735 settings in the config
menu. You should try all of them until you find the one that
matches your display.
The model shown below is a 0.96” with a
resolution of 160 x 80 pixels with 65K colors.
As the interface is SPI, the display requires
at least 5 pins.
The backlight signal is not mandatory (the LED
pin can be put to +3.3V for max intensity).


A TFT Display based on chipset ST7796 can be
connected to the module using the SPI interface.
These displays are available on Ebay with a
size of 4.0” and are quite cheap.
The resolution of the display is 480 x 320
pixels with 65K colors.
They can also include a touchscreen controller
to receive positional feedback via the SPI interface.
As the interface is SPI, the display requires
at least 5 pins when connected as a display only, and 6 when the
touch screen is used.
This display is a great option compared to the
ILI9341 as the higher resolution and the quite large size of the
screen enables the creation of nicer GUI pages with a better
touchscreen interaction.
In addition it shares the same connector
pinout with the ILI9341 modules so can then be used on PCBs already
designed for the ILI9341 and is very fast as it can be used at
80Mhz.
Additionally these displays also include
a reader that can be used to connect an SDCARD to the
module.


These displays have a little jumper
zone (J1) that must be solder-bridged if powering the module from
3.3V else it will be configured to work at 5v.
These displays have
a design fault, a diode is fitted inline with the TFT_CS line, this
allows the CS line to be pulled low but only parasitic currents
pull it high (aided slightly by diode capacitance on a rising
edge). Since CS tends to stick low the SDO line never tristates and
the touch controller driver is too weak to overcome the TFT drive
output. This diode must be removed and replaced with a link
and so it can tristates the SDO output as it should (see image
below)

A TFT Display based on chipset ST7789 can be
connected to the module using the SPI interface.
These displays are available on Ebay in
different sizes and resolutions and are very cheap.
Because there are many variants of this
display, Annex32 supports 5 different ST7789 settings in the config
menu. You should try all of them until you find the one that
matches your display.
The supported resolutions are :
240 x 240, 135 x 240, 240 x 280, 172 x 320 and
170 x 320.
As the interface is SPI, the display requires
at least 5 pins.
The backlight signal is not mandatory (the LED
pin can be put to +3.3V or left open for max intensity).
The model shown below is a 1.3” with a
resolution of 240x 240 pixels with 65K colors.
The particularity of this display is that it
does not have the CS signal so it is always active.
This means that it cannot share the SPI bus
with other devices (such as the SD Card).
For motivated people, there is an instructable
that explains how add the CS signal
https://www.instructables.com/Adding-CS-Pin-to-13-LCD/


TBD -
schematics
A OLED Color Display based on chipset SSD1351
can be connected to the module using the SPI interface.
These modules have a very sharp image and high
brightness but are not very cheap.
As the interface is SPI, the display requires
at least 5 pins.
The backlight signal is not present and is not
required.
The model shown below is a 1.5” with a
resolution of 128 x 128 pixels with 65K colors.

TBD -
schematics
A TFT Display based on chipset GC9A01 can be
connected to the module using the SPI interface.
These are easily available as a 1.28” round
displays with a resolution of 240 x 240.
As the interface is SPI, the display requires
at least 5 pins.
The backlight signal is not mandatory (the LED
pin can be put to +3.3V or left open for max intensity).

TBD -
schematics
The touchscreen
functionality allows detecting the position of the point pressed on
the screen.
Both resistive and
capacitive controllers are supported.
Support is included
for the following touchscreen controllers:
-
XPT2046 (using the SPI bus)
-
GT911 (using the I2C bus)
-
FT5X06 (using the I2C bus)
The touchscreen
controller can be selected via the web configuration page.
For the XPT2046
controller using the SPI bus, its pins are shared with those of the
TFT display.
Therefore, only the
chip select (named TOUCH in the config page) pin for the touch
controller needs to be defined (with some exceptions for specific
modules that are handled differently).
For controllers
using the I2C bus, the corresponding I2C pins must be specified in
the configuration page.
The touchscreen
functionality permits to get the position of the point pressed on
the screen.
The support is
based on the chip XPT2416 that is connected using the bus
SPI.
It is associated
with the event
OnTouch and the functions
TOUCH.X ,
TOUCH.Y and
TOUCH.Z.
The touchscreen
must be calibrated before first use, and also if TFT.init
orientation is changed.
This can be done
with the command TOUCH.CALIB
The user will be
asked to click on the 4 crosses for the calibration.
The calibration
result will be stored permanently inside the module and will not be
required to do anymore.
There are 2 commands to read the touchscreen
:
TOUCH.READ -> read the touchscreen position
calibrated
TOUCH.RAW -> read the touchscreen without
calibration
There are 4 additional commands to setup /
customise the touchscreen :
TOUCH.RESET -> reset the specific H/W setup for the
module ESP32-2432S
TOUCH.THRESHOLD value
-> set the threshold sensitivity value (default 350)
TOUCH.AVERAGE value
-> set the average value (default 50)
TOUCH.DELAY value
-> set the delay value (default 30)
Note: these values are stored permanently
inside the module and will not be required to do anymore
There are 3 functions :
TOUCH.X -> returns the X position
TOUCH.Y -> returns the Y position
TOUCH.Z -> returns the touched status (if 1 means
touched)
Example:
OnTouch
touchme
wait
touchme:
touch.read 'Read
the calibrated position
print "touched", touch.x, touch.y, touch.z
return
|
The touchscreen
functionality permits to get the position of the point pressed on
the screen.
The support is
based on the chip GT911 that is connected using the bus
I2C.
It is associated
with the event
OnTouch and the functions
TOUCH.X ,
TOUCH.Y and
TOUCH.Z.
Before use the touchscreen, the following
commands are required:
OPTION.TOUCH 1
'Select the capacitive
controller
I2C.SETUP 19, 20
'Set the pins for the I2C
bus
'initialise the capacitive touch; the optional rotation can be from
0 to 3
TOUCH.INIT [rotation]
The commands to read the touchscreen is:
TOUCH.READ -> read the touchscreen position
calibrated
There are 3 functions :
TOUCH.X -> returns the X position
TOUCH.Y -> returns the Y position
TOUCH.Z -> returns the touched status (if 1 means
touched)
Example:
OPTION.TOUCH 1
'Select the capacitive
controller
I2C.SETUP 19, 20
'Set the pins for the I2C
bus
touch.init
'initialise the capacitive touch
OnTouch
touchme
wait
touchme:
touch.read 'Read
the calibrated position
print "touched", touch.x, touch.y, touch.z
return
|
Several text fonts are available to be used
for the TFT.
The commands are :
TFT.TEXT.FONT font_number
TFT.TEXT.SIZE font_size
TFT.LOADFONT"filename"
[, 1 | 2
| 3 | 4 | 10 | 11 | 12 | 13]
TFT.PRINT expression
[[,; ]expression] ...
TFT.TEXT.DRAW
"text", x, y
[font]
TFT.TEXT.ALIGN alignment
TFT.TEXT.PADDING width
There are actually 8 fonts installed as shown
in the pictures below as shown on the TFT at 320x240.








The fonts 6 to 8 have only a limited set of
characters as shown in the pictures.
The font 3 and 5 are the same as the font1 but
just increased in size.
The size of the characters can be controlled
for any font using the command TFT.TEXT.SIZE font_size.
This is essentially a multiplying
coefficient that is applied to the font.
For example the font 7 with TFT.TEXT.SIZE 2
will be drawn as below

It is important to note that, except for the
font 1, the 3 and 5, the character spacing is not fixed as
the fonts are not monospace but proportional.
In addition to these fonts available by
default, it is possible to load dynamically up to 4 new fonts from
file.
These will be loaded into the RAM and
available as font 10,11, 12 and 13.
The fonts available are essentially all the
freefonts available in the Adafruit_GFX library format simply
converted in binary ready to be loaded into Annex.
The list is very long (~50) and many others
can be also included after conversion.
A dedicated web site is available for the
conversion directly in the right format:
https://www.cicciocb.com/FontConverter/
To load a new font the command is :
TFT.LOADFONT “filename” [,slot]
Where ‘slot ‘ can be 1 (default), 2, 3 or 4
(they can also be from 10 to 13 for the same result)
For example, to load the font
“Orbitron_Light_32” and the font “Yellowtail_32” :
TFT.LOADFONT “/fonts/Orbitron_Light_32.bin”,
1
TFT.LOADFONT “/fonts/Yellowtail_32.bin”, 1
The result will be :

The text can be printed with or without a
background (in transparent mode), useful to superimpose the text
over an image.

This is controlled using the command
TFT.TEXT.COLOR text_color [, background_color]
If the background_color is not specified, the
text will be printed without background.
NOTE : the freefonts loaded from file
will always be “transparent” independently of the text color
setting.
The text can be printed using 2 commands :
TFT.PRINT expression
[[,; ]expression] …
and
TFT.TEXT.DRAW
"text", x, y
[font]
TFT.PRINT works in the same way as the serial print
command, including all the options, and prints the text at the
position previously defined by the command
TFT.TEXT.POS x,
y
As soon as the text is printed, the position
is automatically advanced on the next line or held on the same line
if the ; is attached at the end of the command.
It also has the advantage to wrap the text
automatically on the next line as soon as it goes out of the
screen.
However, this command is not very flexible and
is not adapted for text that changes dynamically.
On the other hand, the command
TFT.TEXT.DRAW is much more flexible as it enables
a strict control on the text to be drawn.
It rely on 2 other commands :
TFT.TEXT.ALIGN alignment
This command defines the alignment of the text
to be drawn, in relationship with the coordinates of the point
defined in the command
TFT.TEXT.DRAW
The table below shows all the possible
alignments
VALUE
|
KEYWORD
|
ALIGNMENT
|
0
|
ALIGN_TOP_LEFT
|
Top left
|
1
|
ALIGN_TOP_MID
|
Middle of top
|
2
|
ALIGN_TOP_RIGHT
|
Top right
|
3
|
ALIGN_MID_LEFT
|
Middle of left side
|
4
|
ALIGN_MID_MID
|
Center
|
5
|
ALIGN_MID_RIGHT
|
Middle of the right side
|
6
|
ALIGN_BOT_LEFT
|
Bottom left
|
7
|
ALIGN_BOT_MID
|
Middle of bottom
|
8
|
ALIGN_BOT_RIGHT
|
Bottom right
|
TFT.TEXT.PADDING width
This command defines the minimal width of the
text to be drawn, useful to overprint and erase old text
or numbers.
TFT.TEXT.DRAW
"text", x, y
[,font]
This command draws a text at the position
defined by x and y using the optional font
defined or the font defined with the command
TFT.TEXT.FONT.
The text is drawn using the alignment defined
with the command
TFT.TEXT.ALIGN
TFT.QRCODE
"message", x, y,
width [,version]
This command draws a text message on the TFT
as QR CODE that can be read using a mobile phone simply taking a
picture of the image shown on the display.

GRAPHIC GUI for TFT
A full set of graphical objects has been
included in Annex32.
There are several objects that can be defined
using a specific
GUI.xxxx function.
When defining the object, each function
returns a handler that must be stored into a variable to gain
access to this object later in the code.
All these graphical objects are strongly
associated with the touchscreen that must be calibrated before with
the command
TOUCH.CALIB.
At the beginning, the command
GUI.INIT Nb_objects,
back_color is required to define how many objects will
be declared and the initial background color.
Nb_objects
defines the max number of objects present on the screen at
the same time but the program can contain more objects.
The objects created using the functions
defined below, will not be drawn directly on the screen but will be
held in memory until the command
GUI.REFRESH is executed.
This permits us to update all the objects at
the same time.
Here is a simple example that will create two
GUI items, a textline and a button. When the button is clicked , or
the left button on M5stack is pressed, the textline changes.
'simple GUI
example
gui.init 20,
black 'reserve memory for 20 GUI
objects. clears screen to black
txt
= GUI.Textline(10,50,190,20, "Text Line Here", 2) 'x,y,w,h,text,fontsize
but
= GUI.Button(20, 200, 100, 20, "BUTTON!",2 ) 'x,y,w,h,text,fontsize
gui.setevent
but, TOUCH, buttonclick 'set
touched event, jump to buttonclick
interrupt
39,
buttonclick 'if using M5stack can't
click screen- so use left button
gui.autorefresh 30, 1
'display gui items automatically each
30ms including touch
wait
buttonclick:
gui.settext
txt,"Button Pressed"
'change text
line.
return
|
For example, defining a textline with:
TXT1
=
GUI.Textline(10,
10, 100, 20, "Hello
World!")
The variable txt1 will contain a handler
permitting to modify the properties of the textline; for example
the following line :
GUI.SetText TXT1,
"Text changed!"
Will change the text of the object previously
defined.
If it is not required to hold the handler of
the object into the code (for example if it never changes), it is
possible to ignore the handler and define the object using a
command syntax without parentheses:
GUI.Textline 10, 10,
100, 20, "Hello
World!"
Txt1
=GUI.Textline(x,
y, width, height, "text" [,font]
[,color_text] [,color_back] [,color_frame] [,alignment] [,margin]
)
Font is the number of the font.

But1
= GUI.Button(x, y, width, height, "text" [,font]
[,radius] [,toggle] [,group] [,color_text] [,color_pressed]
[,color_released] [,color_frame] )
Font is the number of the font.
Radius is the radius of the rounded part of
the button (0 by default is not rounded).
Toggle is 0 for momentary (default) or 1 for
toggle.
Toggle can also be expressed directly using
the keywords
MOMENTARY or
TOGGLE.
Group is a number that permits to associate
interactive buttons together; this permits to deactivate a toggle
button when selecting another in the group (like a group of radio
buttons).

Img1
= GUI.Image(x, y, width, height, fname$ [,background]
[,background_on] [,toggle] [,group] )
The width and the height are just used to
define the touch area, because the size of the image will be
defined by the image file content.
The file can be BMP or JPG format.
The BMP can be also with 32bits permitting to
define a color background that can be eventually changed with the
command gui.setcolor.
Toggle is 0 for momentary (default) or 1 for
toggle.
Toggle can also be expressed directly using
the keywords
MOMENTARY or
TOGGLE.
Background defines the normal background color
of the image and background_on defines the background color when
the image is set to 1.
Defining 2 different colors, it is possible to
use the image as a kind of “buttonImage” where the background color
changes as a function of the button state.
Optionally the background color can be
controlled from the code using the function Gui.SetColor.
NEW: if the background is -1, the
background around the image will be transparent

A combination of a button with 2 images
Img2
= GUI.ButtonImage(x, y, width, height, image1$, image2$
[,toggle], [group] ,
[background] )
The width and the height are just used to
define the touch area, because the size of the image will be
defined by the image file content.
The files can be BMP or JPG format.
The BMP can also be 32bits permitting to
define a color background with the command gui.setcolor.
Toggle is 0 for temporary (default) or 1 for
toggle.
Toggle can also be expressed directly using
the keywords
MOMENTARY or
TOGGLE.
Group is a number that permits to associate
interactive buttons together; this permits to deactivate a toggle
button when selecting another in the group (like a group of radio
buttons).
Background is the background color (for
transparent images)
NEW: if the background is -1, the
background around the image will be transparent


Chk1
= GUI.CheckBox(x, y, width, height, value [, style]
[,group] [,color_set] [,color_back] [,color_frame] )
Font is the size of the font.
Value is the initial value of the checkbox (0
or 1.)
Style is : 0 for squared checkbox, 1 for
crossed checkbox, 2 for circular checkbox (radio button).
Style can also be expressed directly using the
keywords
SQUARED ,
CROSSED or
RADIO.
By default the style is
SQUARED.
Group is a number that permits to associate
interactive checkboxes together; this permits to deactivate a
checkbox when selecting another in the group (like a group of radio
buttons).

Sld1
= GUI.Slider(x, y, width, height, value [,orientation]
[,color_cursor]
[,color_back] )
The slider has by default a range from 0 to
100.
Value permits to define the default value.
Orientation can be 0 (default) for horizontal
and 1 for vertical.
Orientation can also be expressed directly
using the keywords
HORIZONTAL or
VERTICAL.

Prg1
= GUI.ProgressBar(x, y, width, height, value
[,orientation] [,color_set] [,color_back]
[,color_frame] )
The progressBar has by default a range from 0
to 100.
Value permits to define the default value.
Orientation can be 0 (default) for horizontal
and 1 for vertical.
Orientation can also be expressed directly
using the keywords
HORIZONTAL or
VERTICAL.

Rmp1
= GUI.Ramp(x, y, width, height, value)
The ramp has by default a range from 0 to
100.

Gau1
= GUI.Gauge(x, y, width, height, value [,color_needle]
[,color_back] [,color_frame] [,color_ticks]
)
The gauge has by default a range from 0 to
100.


Box1
= GUI.Box(x, y, width, height, color1 [,frame_color [,color2]])
The box has by default a unique color with a
white frame around.
The optional parameter ‘frame_color’ defines
the color of the frame.
The optional parameter ‘color2’ allows the
color of the box to be swapped between the 2 colors using the
command gui.setvalue (example for a squared led).
By default color2 is black

Cir1
= GUI.Circle(x, y, radius, color1 [,frame_color [,color2]])
The circle has by default a unique color with
a white frame around.
The optional parameter ‘frame_color” defines
the color of the frame.
The optional parameter ‘color2’ allows the
color of the circle to be swapped between the 2 colors using the
command gui.setvalue (example for a circular led).
By default color2 is black.

Rect1
= GUI.Rect(x, y, width, height, color,[,color2])
The optional parameter ‘color2’ allows the
color of the circle to be swapped between the 2 colors using the
command gui.setvalue (example for a squared led).
By default color2 is black.
This draws a simple rectangle.

Line1
= GUI.Line (x1, y1 x2, y2, color)
This draws a simple line.

GUI.TEXTAREA(x,
y, width, height, "text", [,font] [,alignment] [,color_text]
[,color_back] [,color_frame] [,margin] )
|
Creates a text area on a graphical user
interface within the TFTdisplay. This function facilitates the
display of text, automatically formatting it into multiple lines.
The string can be split either by the newline character `chr$(10)`
or automatically wrapped by word.
Parameters
● x:
The x-coordinate position of the text area on the TFT display.
● y:
The y-coordinate position of the text area on the TFT display.
●
width: The width of the text area in pixels.
●
height: The height of the text area in pixels.
●
"text": The text string to be displayed within the text area.
● font
(Optional): An optional parameter specifying the font to be used
for the text. Default font may be used if not specified.
●
alignment (Optional): An optional parameter specifying the
alignment of the text within the text area.
●
color_text (Optional): An optional parameter specifying the color
of the text. Default color may be used if not specified.
●
color_back (Optional): An optional parameter specifying the
background color of the text area. Default color may be used if not
specified.
●
color_frame (Optional): An optional parameter specifying the color
of the text area's frame. Default color may be used if not
specified.
●
margin (Optional): An optional parameter specifying the margin
around the text within the text area.
Return Value
● A
variable representing the created text area. This variable can be
used to manipulate the text area in subsequent commands.
|
|
Parameters
● obj:
The object from which to retrieve the text.
●
var$: The variable to store the retrieved text.
|
|
Parameters
● obj:
The object from which to retrieve the text.
●
visible: 0=hidden, 1=visible.
|
Value
= GUI.GetValue(obj)
Returns the current value from any object.
Works for button, Imagebutton, checkbox,
slider, ….
Id
= GUI.Target
Returns the ID of the object that generated
the event.
Useful for having a common event handler
routine for several objects.
Gui.Init nb_elements
[, back_color]
Initialise the graphical GUI interface.
Nb_elements define how many graphical elements
can be defined.
This is just for memory reasons, if more
objects are defined, they will be ignored.
Back_color defines the background color (by
default is black).
Gui.Redraw
Redraw all the content of the GUI.
All the objects will be redrawn, even those
that have not changed since the last refresh.
Gui.Refresh
[touch]
Refresh the content of the GUI.
If ‘touch’ is 1, the touchscreen will also be
refreshed. This is useful if the module doesn’t have a touchscreen
(like the m5stack).
Gui.AutoRefresh interval
[, touch]
Refresh the content of the GUI at regular
intervals.
‘Interval’ defines the time interval in
milliseconds.
If ‘touch’ is 1, the touchscreen will also be
refreshed. This is useful if the module doesn’t have a touchscreen
(like the m5stack).
Gui.SetValue object,
value [, no_event]
Set the value for any valid object.
If no_event
is 1, the event associated with the object will not be raised
Gui.SetText object,
text$
Set the text for textline and for buttons.
Gui.SetImage object,
image1$ [,image2$]
Defines the image(s) for the IMAGE object and
the ImageButton Object.
Gui.SetColor object,
col1 [,col2 [,col3 [,col4]]]
Set the colors for all the objects.
This command is valid for all the objects, but
the syntax is different for each object.
The detail is :
Object
|
Format
|
TextLine
|
Gui.SetColor object,
color_text [,color_back
[,color_frame]]
|
Button
|
Gui.SetColor object,
color_text [,color_pressed
[,color_released [,color_frame]]]
|
Checkbox
|
Gui.SetColor object,
color_set [, color_back
[, color_frame]]
|
ProgressBar
|
Gui.SetColor object,
color_set [, color_back
[, color_frame]]
|
Slider
|
Gui.SetColor object,
color_cursor [, color_back
[, color_frame [, color_ticks]]]
|
Gauge
|
Gui.SetColor object,
color_needle [, color_back
[, color_frame [, color_ticks]]]
|
Box
|
Gui.SetColor object,
color_set [, color_back
[, color_frame [, color_released]]]
|
Circle
|
Gui.SetColor object,
color_set [, color_back
[, color_frame [, color_released]]]
|
Rectangle
|
Gui.SetColor object,
color
|
Line
|
Gui.SetColor object,
color
|
Image
|
Gui.SetColor object,
color_back ( this works
only with bmp with transparency)
|
ButtonImage
|
Gui.SetColor object,
color_back1, color_back2
|
Gui.SetRange object,
value_mini, value_maxi
Define the range for the slider, the
progressbar, the ramp and the gauge.
Gui.SetEvent object,
event_type [, label]
Define an event for any object.
Event
|
Value
|
Meaning
|
NONE
|
0
|
Disable the event
|
TOUCH
|
1
|
Triggered when touching on the object
|
LEAVE
|
2
|
Triggered when leaving the touch from the object
|
CHANGE
|
3
|
Triggered when the value of the object changes
|
Label is the place where it will jump; it is
not required if the event is NONE.
The events can be defined for button,
checkbox, slider, image and imagebutton.
ID
= Gui.Target
Returns the ID of the object that generated
the event.
Useful for having a common event handler
routine for several objects
Set the style for all the objects.
This command is valid for all the objects, but
the syntax is different for each object.
The detail is :
Object
|
Format
|
Slider
|
Gui.SetStyle object,
size_cursor [, number_of_ticks
[, tick_length]]
|
Gauge
|
Gui.SetStyle object,
needle_length [,
needle_width [,
number_of_ticks [,
tick_length]]]
|
TextLine
|
Gui.SetStyle object,
alignment [,
text_margin]
|
alignment
can be :
Keyword
|
Value
|
Alignement
|
ALIGN_TOP_LEFT
|
0
|
Top left
|
ALIGN_TOP_MID
|
1
|
Middle of
top
|
ALIGN_TOP_RIGHT
|
2
|
Top right
|
ALIGN_MID_LEFT
|
3
|
Middle of left
side
|
ALIGN_MID_MID
|
4
|
Center
|
ALIGN_MID_RIGHT
|
5
|
Middle of the
right side
|
ALIGN_BOT_LEFT
|
6
|
Bottom left
|
ALIGN_BOT_MID
|
7
|
Middle of
bottom
|
ALIGN_BOT_RIGHT
|
8
|
Bottom
right
|
Text_margin defines the margin in pixels.
LovyanGFX is a powerful and flexible graphics
library integrated into Annex 32 RDS starting from Release 2+. This
library significantly enhances graphical capabilities for
ESP32-based projects, replacing the previous TFT_eSPI library. It
provides advanced features and optimizations to support complex
graphical operations while maintaining efficiency and compatibility
with the previous implementation.
Font Management
-
Custom Fonts: Supports loading fonts in Adafruit GFX format,
converted using the Annex Font Converter.
-
Flexible Text Rendering: Allows customization of font size,
alignment, padding, and colors.
Image Handling
-
Supported Formats: Displays BMP, JPG, and PNG images
directly on the TFT display or sprites.
-
Advanced Manipulation: Includes options for scaling,
cropping, rotation, and transparency.
Sprite Support
-
Off-Screen Buffers: Enables creation and manipulation of
sprites for smooth animations and advanced graphical effects.
-
Dynamic Drawing: Allows text and image rendering directly
onto sprites.
-
Advanced Sprite Management: Up to 10 sprites can be used
simultaneously, numbered from 0 to 9. Sprites can be resized,
superposed, merged, rotated between them to create complex graphic
effects and animations easily.
-
Important Note: Sprites consume RAM memory, so it is
essential to use them cautiously, especially if the ESP32 device
lacks PSRAM. Excessive use of sprites can lead to out-of-memory
issues, affecting the stability and performance of your
application.
Geometric
Drawing
-
Shapes: Provides drawing functions for lines, rectangles
(including rounded corners), circles, ellipses, arcs, triangles,
and wedge lines.
-
Customization: Supports smoothing, thickness adjustments,
and filled shapes.
Hardware
Integration
-
Efficient SPI Usage: Optimized for high-performance
rendering with adjustable SPI frequencies.
-
Brightness Control: Allows adjustment of TFT display
brightness.
QR Code
Generation
-
Integrated Functionality: Includes support for generating QR
codes directly on the display.
LovyanGFX commands are mapped to Annex 32 RDS
functions, making it easy to leverage its capabilities within the
firmware. You can use dedicated commands for text rendering, image
handling, sprite management, geometric drawing, and more.
This integration not only ensures
compatibility with the previous TFT_eSPI library but also
significantly expands the range of functions available for
graphical applications.
For each command/function, the corresponding
LovyanGFX reference has been included so that you can consult the
official LovyanGFX documentation for further details.
Colors in LovyanGFX are
managed at 16 bits in RGB565 format. This encoding uses 5 bits for
red, 6 bits for green, and 5 bits for blue, resulting in efficient
color representation. Colors can be expressed either as a 16-bit
number or as a predefined color from a table provided in the
documentation. This approach ensures compatibility with various
graphical operations while maintaining high performance across
supported devices.
Description: Converts RGB color values to a 16-bit color
format.
Arguments:
● r:
Red component (from 0 to 255).
● g:
Green component (from 0 to 255).
● b:
Blue component (from 0 to 255).
Return: 16-bit color value.
TFT Command: tft3->color565()
LovyanGFX Command: color565()
Description: Retrieves a predefined color based on its
name.
Arguments:
●
colorName: Name of the color.
Return: Color value.
TFT Command: get_TFT_Color()
LovyanGFX Command: N/A (Custom function)
The list of the colors and their corresponding
RGB565 values (in hex format) is shown below :
Color Name
|
RGB565 Value
|
BLACK
|
0x0000
|
NAVY
|
0x000F
|
DARKGREEN
|
0x03E0
|
DARKCYAN
|
0x03EF
|
MAROON
|
0x7800
|
PURPLE
|
0x780F
|
OLIVE
|
0x7BE0
|
LIGHTGREY
|
0xD69A
|
DARKGREY
|
0x7BEF
|
BLUE
|
0x001F
|
GREEN
|
0x07E0
|
CYAN
|
0x07FF
|
RED
|
0xF800
|
MAGENTA
|
0xF81F
|
YELLOW
|
0xFFE0
|
WHITE
|
0xFFFF
|
ORANGE
|
0xFDA0
|
GREENYELLOW
|
0xB7E0
|
PINK
|
0xFE19
|
BROWN
|
0x9A60
|
GOLD
|
0xFEA0
|
SILVER
|
0xC618
|
SKYBLUE
|
0x867D
|
VIOLET
|
0x915C
|
Description: Gets the width of the TFT display.
Arguments: None
Return: Width of the display.
TFT Command: dest->width()
LovyanGFX Command: width()
Description: Gets the width of the specified sprite.
Arguments:
●
spriteNum: Sprite number.
Return: Width of the sprite.
TFT Command: dest->width()
LovyanGFX Command: width()
Description: Gets the height of the TFT display.
Arguments: None
Return: Height of the display.
TFT Command: dest->height()
LovyanGFX Command: height()
Description: Gets the height of the specified sprite.
Arguments:
●
spriteNum: Sprite number.
Return: Height of the sprite.
TFT Command: dest->height()
LovyanGFX Command: height()
Description: Gets the color of a pixel at specified
coordinates on the TFT display.
Arguments:
● x:
X-coordinate of the pixel.
● y:
Y-coordinate of the pixel.
Return: Color of the pixel.
TFT Command: dest->readPixel()
LovyanGFX Command: readPixel()
Description: Gets the color of a pixel at specified
coordinates on the specified sprite.
Arguments:
●
spriteNum: Sprite number.
● x:
X-coordinate of the pixel.
● y:
Y-coordinate of the pixel.
Return: Color of the pixel.
TFT Command: dest->readPixel()
LovyanGFX Command: readPixel()
Description: Gets the size of an image file.
Arguments:
●
filename$: Path to the image file.
Return: Image size.
TFT Command: getImageSize()
LovyanGFX Command: N/A (Custom function)
Description: Plays the next frame of a GIF animation.
Arguments:
●
loop (optional): Loop the GIF if
set to 1.
Return: Pause duration until the next frame or 0 if the end
of the animation is reached.
TFT Command: gif->playFrame()
LovyanGFX Command: playFrame()
Description: Loads a font from a file for use in text
rendering.
Arguments:
●
path$: Path for the file .bin containing the font.
●
font_num: font number (from 1 to 4 or 10 to 13);
Return: None
TFT Command: loadFont_generic()
LovyanGFX Command: lgfx::GFXfont,
setFont()
Notes: The font must be in Adafruit GFX format converted
with the Annex Font Converter
Description: Initializes the TFT display with a specified
rotation.
Arguments:
●
rot (optional): Rotation value
(default is 1).
Return: None
TFT Command: doTftInit()
LovyanGFX Command: init(),
setRotation(),
fillScreen(),
setTextFont()
Description: Sets the TFT SPI frequency.
Arguments:
●
freq: Frequency value.
●
read_freq (optional): If provided,
sets the read clock frequency.
Return: None
TFT Command: tft3->getPanel()->getBus()->setClock(TFT_SPI_frequency)
LovyanGFX Command: getPanel(),
getBus(),
setClock()
Description: Sets the cursor position for text drawing on
the TFT display or a specified sprite.
Arguments:
● x:
X-coordinate for the cursor position.
● y:
Y-coordinate for the cursor position.
Return: None
TFT Command: doTftTextPos()
LovyanGFX Command: setCursor()
Description: Sets the cursor position for text drawing on
the specified sprite.
Arguments:
●
spriteNum: Sprite number.
● x:
X-coordinate for the cursor position.
● y:
Y-coordinate for the cursor position.
Return: None
TFT Command: doTftTextPos()
LovyanGFX Command: setCursor()
Description: Sets the text color and optionally the
background color for the TFT display.
Arguments:
● col:
Text color.
●
back (optional): Background
color.
Return: None
TFT Command: doTftTextCol()
LovyanGFX Command: setTextColor()
Description: Sets the text color and optionally the
background color for the specified sprite.
Arguments:
●
spriteNum: Sprite number.
● col:
Text color.
●
back (optional): Background
color.
Return: None
TFT Command: doTftTextCol()
LovyanGFX Command: setTextColor()
Description: Sets the text size and optionally the font for
the TFT display.
Arguments:
●
size: Text size.
●
font (optional): Font number.
Return: None
TFT Command: doTftTextSize()
LovyanGFX Command: setTextSize(),
setTextFont()
Description: Sets the text size and optionally the font for
the specified sprite.
Arguments:
●
spriteNum: Sprite number.
●
size: Text size.
●
font (optional): Font number.
Return: None
TFT Command: doTftTextSize()
LovyanGFX Command: setTextSize(),
setTextFont()
TFT.PRINT str$
[, x] [,
y] [,
fontnum]
Description: Prints text or data to the TFT display.
Arguments:
●
str$: String to print.
●
x (optional): X-coordinate for
printing.
●
y (optional): Y-coordinate for
printing.
●
fontnum (optional): Font
number.
Return: None
TFT Command: doTftPrint(dest)
LovyanGFX Command: print()
TFT.SPRITE.PRINT spriteNum,
str$ [, x] [, y] [,
fontnum]
Description: Prints text or data to the specified
sprite.
Arguments:
●
spriteNum: Sprite number.
●
str$: String to print.
●
x (optional): X-coordinate for
printing.
●
y (optional): Y-coordinate for
printing.
●
fontnum (optional): Font
number.
Return: None
TFT Command: doTftPrint(dest)
LovyanGFX Command: print()
TFT.BMP filename$
[, x] [,
y] [,
scale]
Description: Draws a BMP image on the TFT display.
Arguments:
●
filename$: Path to the BMP file.
●
x (optional): X-coordinate for the
image.
●
y (optional): Y-coordinate for the
image.
●
scale (optional): Scale
factor.
Return: None
TFT Command: dotftbmp()
LovyanGFX Command: drawBmpFile()
TFT.JPG filename$
[, x] [,
y] [,
scale]
Description: Draws a JPG image on the TFT display.
Arguments:
●
filename$: Path to the JPG file.
●
x (optional): X-coordinate for the
image.
●
y (optional): Y-coordinate for the
image.
●
scale (optional): Scale
factor.
Return: None
TFT Command: dotftjpg()
LovyanGFX Command: drawJpgFile()
TFT.IMAGE filename$
[, x] [,
y] [, zoom] [, x1] [, y1]
[, w] [,
h]
Description: Draws an image (BMP, JPG, or PNG) on the TFT
display.
Arguments:
●
filename$: Path to the image file.
●
x (optional): X-coordinate for the
image.
●
y (optional): Y-coordinate for the
image.
●
zoom (optional): Zoom factor.
●
x1, y1 (optional): Cropping
coordinates.
●
w, h (optional): Width and height
for cropping.
Return: None
TFT Command: doTftImage()
LovyanGFX Command: drawBmpFile(),
drawJpgFile(),
drawPngFile()
TFT.SPRITE.IMAGE spriteNum,
filename$ [,x] [,y] [,zoom]
[,x1] [,y1] [,w]
[,h]
Description: Draws an image (BMP, JPG, or PNG) on the TFT
display or a specified sprite.
Arguments:
●
spriteNum: Sprite number.
●
filename$: Path to the image file.
●
x (optional): X-coordinate for the
image.
●
y (optional): Y-coordinate for the
image.
●
zoom (optional): Zoom factor.
●
x1, y1 (optional): Cropping
coordinates.
●
w, h (optional): Width and height
for cropping.
Return: None
TFT Command: doTftImage()
LovyanGFX Command: drawBmpFile(),
drawJpgFile(),
drawPngFile()
Description: Sets the brightness of the TFT display.
Arguments:
● brt:
Brightness intensity (0-255).
Return: None
TFT Command: dotftbrightness()
LovyanGFX Command: setBrightness()
Description: Sets the font for text rendering on the TFT
display.
Arguments:
●
fontnum: Font number.
Return: None
TFT Command: setTextFontandSize()
LovyanGFX Command: setTextFont()
Description: Sets the font for text rendering on the
specified sprite.
Arguments:
●
spriteNum: Sprite number.
●
fontnum: Font number.
Return: None
TFT Command: setTextFontandSize()
LovyanGFX Command: setTextFont()
Description: Draws a string at specified coordinates on the
TFT display .
Arguments:
●
str$: String to draw.
● x:
X-coordinate for the text.
● y:
Y-coordinate for the text.
●
fontnum (optional): Font
number.
Return: None
TFT Command: doTftPrint(dest)
LovyanGFX Command: drawString()
Description: Draws a string at specified coordinates on the
TFT display or a specified sprite.
Arguments:
●
spriteNum: Sprite number.
●
str$: String to draw.
● x:
X-coordinate for the text.
● y:
Y-coordinate for the text.
●
fontnum (optional): Font
number.
Return: None
TFT Command: doTftPrint(dest)
LovyanGFX Command: drawString()
Description: Sets the text alignment (datum) for rendering
on the TFT display.
Arguments:
●
datum: Alignment value.
Return: None
TFT Command: doTftTextAlign()
LovyanGFX Command: setTextDatum()
Description: Sets the text alignment (datum) for rendering
on the specified sprite.
Arguments:
●
spriteNum: Sprite number.
●
datum: Alignment value.
Return: None
TFT Command: doTftTextAlign()
LovyanGFX Command: setTextDatum()
Description: Sets the text padding for rendering on the TFT
display.
Arguments:
●
padding: Padding value.
Return: None
TFT Command: doTftTextPadding()
LovyanGFX Command: setTextPadding()
Description: Sets the text padding for rendering on the TFT
display or a specified sprite.
Arguments:
●
spriteNum: Sprite number.
●
padding: Padding value.
Return: None
TFT Command: doTftTextPadding()
LovyanGFX Command: setTextPadding()
TFT.QRCODE str$, x,
y, w [, version]
Description: Draws a QR code on the TFT display.
Arguments:
●
str$: QR code content.
● x:
X-coordinate for the QR code.
● y:
Y-coordinate for the QR code.
● w:
Width of the QR code.
●
version (optional): QR code
version.
Return: None
TFT Command: tft3->qrcode()
LovyanGFX Command: qrcode()
Description: Creates a sprite with specified dimensions.
Arguments:
●
spriteNum: Sprite number.
● w:
Width of the sprite.
● h:
Height of the sprite.
Return: None
TFT Command: LovyanSprite[spriteNum].createSprite(w,
h)
LovyanGFX Command: createSprite()
Description: Deletes a specified sprite.
Arguments:
●
spriteNum: Sprite number to delete.
Return: None
TFT Command: LovyanSprite[spriteNum].deleteSprite()
LovyanGFX Command: deleteSprite()
Description: Creates a sprite from a BMP file.
Arguments:
●
spriteNum: Sprite number.
●
filename$: Path to the BMP file.
Return: None
TFT Command: LovyanSprite[spriteNum].createFromBmpFile()
LovyanGFX Command: createFromBmpFile()
Description: Creates a sprite from an image file (BMP, JPG,
or PNG).
Arguments:
●
spriteNum: Sprite number.
●
filename$: Path to the image file.
Return: None
TFT Command: doTftImage()
LovyanGFX Command: createFromBmpFile(),
drawBmpFile(),
drawJpgFile(),
drawPngFile()
TFT.LINE x1, y1,
x2, y2, col [,
radius]
Description: Draws a line on the TFT display.
Arguments:
● x1:
Starting X-coordinate.
● y1:
Starting Y-coordinate.
● x2:
Ending X-coordinate.
● y2:
Ending Y-coordinate.
● col:
Line color.
●
radius (optional): Radius for line
width or smoothness. (-1 = aliased, >1 thickness)
Return: None
TFT Command: doTftLine()
LovyanGFX Command: drawLine(),
drawSmoothLine(),
drawWideLine()
TFT.SPRITE.LINE spriteNum,
x1, y1, x2, y2, col [,
radius]
Description: Draws a line on the TFT display or a specified
sprite.
Arguments:
●
spriteNum: Sprite number.
● x1:
Starting X-coordinate.
● y1:
Starting Y-coordinate.
● x2:
Ending X-coordinate.
● y2:
Ending Y-coordinate.
● col:
Line color.
●
radius (optional): Radius for line
width or smoothness. (-1 = aliased, >1 thickness)
Return: None
TFT Command: doTftLine()
LovyanGFX Command: drawLine(),
drawSmoothLine(),
drawWideLine()
TFT.WEDGELINE x1, y1,
x2, y2, col, radius1, radius2
Description: Draws a wedge line on the TFT display.
Arguments:
● x1:
Starting X-coordinate.
● y1:
Starting Y-coordinate.
● x2:
Ending X-coordinate.
● y2:
Ending Y-coordinate.
● col:
Line color.
●
radius1: Starting radius. (thickness)
●
radius2: Ending radius. (thickness)
Return: None
TFT Command: doTftWedgeLine()
LovyanGFX Command: drawWedgeLine()
TFT.SPRITE.WEDGELINE spriteNum,
x1, y1, x2, y2, col, radius1, radius2
Description: Draws a wedge line on the specified sprite.
Arguments:
●
spriteNum: Sprite number.
● x1:
Starting X-coordinate.
● y1:
Starting Y-coordinate.
● x2:
Ending X-coordinate.
● y2:
Ending Y-coordinate.
● col:
Line color.
●
radius1: Starting radius. (thickness)
●
radius2: Ending radius. (thickness)
Return: None
TFT Command: doTftWedgeLine()
LovyanGFX Command: drawWedgeLine()
TFT.RECT x, y, w,
h, col [, fill] [, radius]
Description: Draws a rectangle on the TFT display.
Arguments:
● x:
X-coordinate for the rectangle.
● y:
Y-coordinate for the rectangle.
● w:
Width of the rectangle.
● h:
Height of the rectangle.
● col:
Rectangle color.
●
fill (optional): Fill option (1
for filled, 2 for smooth filled).
●
radius (optional): Corner radius
for rounded rectangles.
Return: None
TFT Command: doTftRect()
LovyanGFX Command: drawRect(),
fillRect(),
drawRoundRect(),
fillRoundRect(),
fillSmoothRoundRect()
TFT.SPRITE.RECT spriteNum,
x, y, w, h, col [, fill]
[, radius]
Description: Draws a rectangle on the specified sprite.
Arguments:
●
spriteNum: Sprite number.
● x:
X-coordinate for the rectangle.
● y:
Y-coordinate for the rectangle.
● w:
Width of the rectangle.
● h:
Height of the rectangle.
● col:
Rectangle color.
●
fill (optional): Fill option (1
for filled, 2 for smooth filled).
●
radius (optional): Corner radius
for rounded rectangles.
Return: None
TFT Command: doTftRect()
LovyanGFX Command: drawRect(),
fillRect(),
drawRoundRect(),
fillRoundRect(),
fillSmoothRoundRect()
TFT.CIRCLE x,
y, radius, col [,
fill]
Description: Draws a circle on the TFT display.
Arguments:
● x:
X-coordinate for the circle center.
● y:
Y-coordinate for the circle center.
●
radius: Radius of the circle.
● col:
Circle color.
●
fill (optional): Fill option (1
for filled, 2 for smooth filled).
Return: None
TFT Command: doTftCircle()
LovyanGFX Command: drawCircle(),
fillCircle(),
fillSmoothCircle()
TFT.SPRITE.CIRCLE spriteNum,
x, y, radius, col
[, fill]
Description: Draws a circle on the specified sprite.
Arguments:
●
spriteNum: Sprite number.
● x:
X-coordinate for the circle center.
● y:
Y-coordinate for the circle center.
●
radius: Radius of the circle.
● col:
Circle color.
●
fill (optional): Fill option (1
for filled, 2 for smooth filled).
Return: None
TFT Command: doTftCircle()
LovyanGFX Command: drawCircle(),
fillCircle(),
fillSmoothCircle()
TFT.ELLIPSE x,
y, radius1, radius2, col
[, fill]
Description: Draws an ellipse on the TFT display.
Arguments:
● x:
X-coordinate for the ellipse center.
● y:
Y-coordinate for the ellipse center.
●
radius1: Horizontal radius of the ellipse.
●
radius2: Vertical radius of the ellipse.
● col:
Ellipse color.
●
fill (optional): Fill option (1
for filled).
Return: None
TFT Command: doTftEllipse()
LovyanGFX Command: drawEllipse(),
fillEllipse()
TFT.SPRITE.ELLIPSE spriteNum,
x, y, radius1,
radius2, col [, fill]
Description: Draws an ellipse on the specified sprite.
Arguments:
●
spriteNum: Sprite number.
● x:
X-coordinate for the ellipse center.
● y:
Y-coordinate for the ellipse center.
●
radius1: Horizontal radius of the ellipse.
●
radius2: Vertical radius of the ellipse.
● col:
Ellipse color.
●
fill (optional): Fill option (1
for filled).
Return: None
TFT Command: doTftEllipse()
LovyanGFX Command: drawEllipse(),
fillEllipse()
TFT.ARC x,
y, radius1, radius2,
angle1, angle2, col [,
fill]
Description: Draws an arc on the TFT display or a specified
sprite.
Arguments:
● x:
X-coordinate for the arc center.
● y:
Y-coordinate for the arc center.
●
radius1: Horizontal radius of the arc.
●
radius2: Vertical radius of the arc.
●
angle1: Starting angle of the arc.
●
angle2: Ending angle of the arc.
● col:
Arc color.
●
fill (optional): Fill option (1
for filled).
Return: None
TFT Command: doTftArc()
LovyanGFX Command: drawArc(),
fillArc()
TFT.SPRITE.ARC spriteNum,
x, y, radius1,
radius2, angle1, angle2, col
[, fill]
Description: Draws an arc on the specified sprite.
Arguments:
●
spriteNum: Sprite number.
● x:
X-coordinate for the arc center.
● y:
Y-coordinate for the arc center.
●
radius1: Horizontal radius of the arc.
●
radius2: Vertical radius of the arc.
●
angle1: Starting angle of the arc.
●
angle2: Ending angle of the arc.
● col:
Arc color.
●
fill (optional): Fill option (1
for filled).
Return: None
TFT Command: doTftArc()
LovyanGFX Command: drawArc(),
fillArc()
TFT.TRIANGLE x1,
y1, x2, y2,
x3, y3, col [,
fill]
Description: Draws a triangle on the TFT display.
Arguments:
● x1:
X-coordinate of the first vertex.
● y1:
Y-coordinate of the first vertex.
● x2:
X-coordinate of the second vertex.
● y2:
Y-coordinate of the second vertex.
● x3:
X-coordinate of the third vertex.
● y3:
Y-coordinate of the third vertex.
● col:
Triangle color.
●
fill (optional): Fill option (1
for filled).
Return: None
TFT Command: doTftTriangle()
LovyanGFX Command: drawTriangle(),
fillTriangle()
TFT.SPRITE.TRIANGLE spriteNum,
x1, y1, x2,
y2, x3, y3, col
[, fill]
Description: Draws a triangle on the specified sprite.
Arguments:
●
spriteNum: Sprite number.
● x1:
X-coordinate of the first vertex.
● y1:
Y-coordinate of the first vertex.
● x2:
X-coordinate of the second vertex.
● y2:
Y-coordinate of the second vertex.
● x3:
X-coordinate of the third vertex.
● y3:
Y-coordinate of the third vertex.
● col:
Triangle color.
●
fill (optional): Fill option (1
for filled).
Return: None
TFT Command: doTftTriangle()
LovyanGFX Command: drawTriangle(),
fillTriangle()
Description: Draws a pixel on the TFT display.
Arguments:
● x:
X-coordinate for the pixel.
● y:
Y-coordinate for the pixel.
● col:
Pixel color.
Return: None
TFT Command: doTftPixel()
LovyanGFX Command: drawPixel()
Description: Draws a pixel on the specified sprite.
Arguments:
●
spriteNum: Sprite number.
● x:
X-coordinate for the pixel.
● y:
Y-coordinate for the pixel.
● col:
Pixel color.
Return: None
TFT Command: doTftPixel()
LovyanGFX Command: drawPixel()
Description: Fills the entire TFT screen with a specified
color.
Arguments:
● col:
Fill color.
Return: None
TFT Command: doTftFill()
LovyanGFX Command: fillScreen()
Description: Fills a specified sprite with a specified
color.
Arguments:
●
spriteNum: Sprite number to fill.
● col:
Fill color.
Return: None
TFT Command: LovyanSprite[spriteNum].fillSprite()
LovyanGFX Command: fillSprite()
Description: Prints the pivot coordinates of the TFT
display.
Arguments: None
Return: None
TFT Command: Serial.printf()
LovyanGFX Command: getPivotX(),
getPivotY()
TFT.SAVE filename$
[, spriteDest]
Description: Saves the content of the TFT display or a
specified sprite to a BMP file.
Arguments:
●
filename$: Path to save the BMP file.
●
spriteDest (optional): Sprite
number to save.
Return: None
TFT Command: saveToBMP()
LovyanGFX Command: readRectRGB()
Description: Sets the pivot point for rotation and scaling
on the TFT display .
Arguments:
● xf:
X-coordinate for the pivot.
● yf:
Y-coordinate for the pivot.
Return: None
TFT Command: doTftPivot()
LovyanGFX Command: setPivot()
Description: Sets the pivot point for rotation and scaling
on the specified sprite.
Arguments:
●
spriteNum: Sprite number to fill.
● xf:
X-coordinate for the pivot.
● yf:
Y-coordinate for the pivot.
Return: None
TFT Command: doTftPivot()
LovyanGFX Command: setPivot()
TFT.SPRITE.COPY spriteNum,
spriteDest, x, y,
w, h, x1, y1
[,col] [,angle] [,zoom]
Description: Copies a portion of one sprite to another with
optional rotation and scaling.
Arguments:
●
spriteNum: Source sprite number.
●
spriteDest: Destination sprite number.
● x,
y: Source coordinates.
● w,
h: Width and height of the area to copy.
● x1,
y1: Destination coordinates.
●
col (optional): Color key for
transparency.
●
angle (optional): Rotation
angle.
●
zoom (optional): Zoom factor.
Return: None
TFT Command: doTftSpriteCopy()
LovyanGFX Command: readRect(),
pushImageRotateZoom()
TFT.PUSH spriteNum,
xf, yf [,
col] [, angle] [, zoom]
Description: Pushes a sprite to the TFT display at specified
coordinates with optional rotation and scaling.
Arguments:
●
spriteNum: Sprite number to push.
● xf,
yf: Coordinates to push the sprite.
●
col (optional): Color key for
transparency.
●
angle (optional): Rotation
angle.
●
zoom (optional): Zoom factor.
Return: None
TFT Command: LovyanSprite[spriteNum].pushSprite()
LovyanGFX Command: pushSprite()
TFT.SPRITE.PUSH spriteNum
[, spriteDest] [, xf] [, yf]
[, col] [, angle] [,
zoom]
Description: Pushes a sprite to the TFT display or another
sprite with optional parameters.
Arguments:
●
spriteNum: Sprite number to push.
●
spriteDest (optional): Destination
sprite number.
●
xf, yf (optional): Coordinates to
push the sprite.
●
col (optional): Color key for
transparency.
●
angle (optional): Rotation
angle.
●
zoom (optional): Zoom factor.
Return: None
TFT Command: LovyanSprite[spriteNum].pushRotateZoom()
LovyanGFX Command: pushRotateZoom()
TFT.SPRITE.PUSHAA spriteNum
[, spriteDest] [, xf] [, yf]
[, col] [, angle] [,
zoom]
Description: Pushes a sprite to the TFT display or another
sprite with anti-aliasing and optional parameters.
Arguments:
●
spriteNum: Sprite number to push.
●
spriteDest (optional): Destination
sprite number.
●
xf, yf (optional): Coordinates to
push the sprite.
●
col (optional): Color key for
transparency.
●
angle (optional): Rotation
angle.
●
zoom (optional): Zoom factor.
Return: None
TFT Command: LovyanSprite[spriteNum].pushRotateZoomWithAA()
LovyanGFX Command: pushRotateZoomWithAA()
Description: Loads a GIF file. It must be animated using the
function TFT.FRAMEGIF
Arguments:
●
path$: Path for the file .gif containing the animation.
●
x, y (optional): Coordinates for
the position of the animation; by default 0,0
Return: None
TFT Command: gif->open()
LovyanGFX Command: N/A
Description: Loads a GIF file. The animation will be played
until the end (blocking function)
Arguments:
●
path$: Path for the file .gif containing the animation.
●
x, y (optional): Coordinates for
the position of the animation; by default 0,0
Return: None
TFT Command: gif->open(),
gif->playFrame()
LovyanGFX Command: N/A
LVGL (Light and Versatile Graphics Library) is a powerful tool for
creating embedded graphical user interfaces (GUIs), and it's an
integral part of the Annex development environment. It allows
developers to design visually appealing and interactive user
interfaces with a minimal memory footprint, making it well-suited
for resource-constrained ESP32 projects.
The foundation of every UI element in LVGL is the base object.
Think of it as a basic rectangular building block upon which all
other widgets are constructed. It manages fundamental aspects like
position, size, and parent-child relations
Widgets are often composed of multiple parts that make up their
appearance and functionality. For example, a slider might have a
background, an indicator, and a knob. These parts allow for
fine-grained customization of each widget
Widgets can exist in different states, such as "default,"
"pressed," "focussed," or "disabled." The state of a widget can
influence its appearance and how it responds to user
interactions.
Flags are used to enable or disable specific features or behaviours
of an object. For instance, a flag can make an object clickable,
scrollable, or hidden.
LVGL objects within Annex are structured in a parent-child
hierarchy. This hierarchy provides a way to group related UI
elements and manage their layout and visibility.
Objects have various attributes and properties that define their
characteristics, such as their position, size, visibility, and
opacity.
Styles define the visual appearance of objects, including colors,
fonts, borders, and padding. Applying styles helps maintain a
consistent look and feel across the user interface.
LVGL is event-driven, meaning objects can respond to various events
such as clicks, touches, value changes, and more. Event handlers
can be attached to objects to define what happens when a particular
event occurs.
By grasping these core concepts, developers working with Annex can
effectively leverage LVGL to create engaging and functional user
interfaces for their ESP32-based applications.
LVGL provides flexible ways to manage colors. Colors are typically
defined using a structure that represents Red, Green, and Blue
components. Within Annex, you can set colors for various aspects of
a widget:
● Background Color: The color of the main background of the
widget.
● Text Color: The color of the text displayed on the widget.
● Border Color: The color of the widget's border.
● Image Color: Colors can be applied to images, allowing effects
like tinting.
LVGL supports various color formats, and Annex likely leverages
these to allow easy color definition using hexadecimal color codes
(e.g., &hRRGGBB) or predefined color constants.
In this implementation, the colors will be always specified as 24
bits RGB, even if the final display (the TFT) only supports 16 bits
colors.
As an example, the number &hFF0000 represents the RED color,
&h00FF00 the GREEN color and &h0000FF the BLUE color.
Opacity determines the level of transparency of an object, ranging
from fully transparent to fully opaque. In LVGL, opacity is
typically controlled using an 8-bit value, where:
● 0 means fully transparent (invisible).
● 255 means fully opaque (completely visible).
Opacity can be applied to the following elements:
● Background: Controls the transparency of the widget's
background.
● Text: Adjusts the transparency of the text displayed on the
widget.
● Images: Controls the transparency of images.
● Borders: Adjusts the transparency of the border.
Opacity settings are often combined with colors to create various
visual effects, such as semi-transparent backgrounds, faded text,
or subtle image overlays.
Within Annex, you would typically use specific commands or
functions to set colors and opacity for LVGL objects. For
example:
' Set background color to red with 50% opacity
LVGL.SET_BG_COLOR obj,
&hff0000
LVGL.SET_BG_OPA obj, 128
' 128 = 50% of
255
|
The specifics will depend on the actual API provided by Annex for
interacting with LVGL. Colors and opacity are essential tools for
creating visually appealing and informative user interfaces within
the Annex environment.
In LVGL, widgets are pre-built UI components that provide
ready-to-use functionality and visual elements for creating user
interfaces. They encapsulate both the appearance and behavior of
common UI elements, simplifying the development process. Widgets
are built upon the core concepts of LVGL, such as objects, styles,
events, and flags, allowing for customization and interaction.
Annex provides a specific set of LVGL widgets tailored for ESP32
projects. Let's explore these widgets, grouped by their general
function:
● Base (the base object): This is the fundamental building
block; a simple rectangle that serves as the foundation for all
other widgets. It manages basic properties like position, size, and
style. In Annex, it's likely used as a container or as a basis for
custom widgets.
● Label: Used to display text. Labels can be customized with
different fonts, colors, and alignments. Annex includes the option
relevant for controlling how labels handle long texts.
● Image: Used to display images. This allows you to
incorporate graphical elements into your UI. Annex likely supports
various image formats like BMP, JPG and PNG.
● Button: A standard clickable button used to trigger
actions. In Annex, you can customize the appearance and behavior of
buttons using styles and event handlers.
● ImageButton: A button that uses one or two images as its
visual representation. The documentation's LV_IMAGEBUTTON_STATE_*
enums are specific to these buttons, allowing you to define
different images for different button states (released, pressed,
disabled, etc.).
● ImageToggle: A button toggle (2 alternating states) that
uses one or two images as its visual representation. The
documentation's LV_IMAGEBUTTON_STATE_* enums are specific to these
buttons, allowing you to define different images for different
button states (released, pressed, disabled, etc.).
● Switch: A toggle switch used to turn something on or off.
Annex likely uses styles to customize its appearance.
● Slider: Allows the user to select a value along a
continuous range. Annex uses styles to modify indicator and
background
● Keyboard: Provides a virtual keyboard for text input,
particularly useful on touchscreens. The LV_KEYBOARD_MODE_* enums
in the documentation define the different keyboard layouts (text,
number, special characters) available in Annex.
● Text Area: A multi-line text input field where users can
enter and edit text. Often used in conjunction with the Keyboard
widget.
● Roller: A spinning wheel selector, allowing users to
choose from a list of options. ● List: Displays a scrollable list
of items, allowing users to select an option from the list.
● Dropdown : A compact widget that displays a single
selected value and expands to show a list of options when
activated.
● Tabview: Creates a tabbed interface, allowing users to
switch between different panels of content.
● Checkbox: A standard checkbox for toggling a boolean
value.
● Radio (a customized checkbox): A checkbox that is usually
grouped into multiple others, where only one of them is
selected
● LED: Simulates a light-emitting diode, typically used to
indicate status.
● Bar: Visually represents a value within a range, often
used for progress indicators or level meters.
● Arc: Displays values on an arc.
● Canvas: A blank rectangular area that is manipulated by
LVGL draw APIs.
● Scale: Used to draw a scale or a ruler with tick marks and
labels.
● Line: Draws a line used to create the needle for a Scale
widget.
● Message Box (MsgBox): Creates a pop-up window to display a
message with buttons for user interaction.
● GIF: Used to display GIF animated images.
Association of objects around a common objective (i.e. receive
events from a keyboard)
By combining these widgets and leveraging LVGL's customization
options, Annex allows developers to create a wide range of user
interfaces for ESP32 projects, from simple status displays to
complex interactive applications.
When starting an Annex project with LVGL for graphical user
interfaces, understanding memory allocation is paramount. LVGL
requires memory for the screen buffer and for storing the objects
(widgets) themselves.
The LVGL.INIT command in Annex sets up LVGL and allocates memory.
The syntax is:
LVGL.INIT col_fg,
col_bg [,
buff_size]
Arguments:
●
col_fg: The foreground color.
●
col_bg: The background color.
●
buff_size (Optional): Size of the
screen buffer in bytes.
Screen Buffer, if not explicitly specified will be :
● With PSRAM: If PSRAM is available, the screen buffer is allocated
in PSRAM and sized at SCREEN_WIDTH * SCREEN_HEIGHT * 2 bytes.
● Without PSRAM: If PSRAM is not available, the screen
buffer is allocated in internal RAM, and sized at SCREEN_WIDTH *
SCREEN_HEIGHT *2 / 10 bytes.
Object RAM: This memory is used to store the widgets (buttons,
labels, etc.) and their associated data.
● ESP32 and ESP32-S3: 1MB of RAM is allocated for objects.
(TBC)
● ESP32-S2: 256KB of RAM is allocated for objects.
● If PSRAM is NOT Available: In all cases, if PSRAM is not
available, the object RAM is allocated, and in this case, the RAM
allocated will be 16K for all the devices.
● PSRAM Impact: The presence of PSRAM significantly impacts the
available memory for the screen buffer, enabling larger and more
complex displays.
● Object RAM Limits: The amount of object RAM dictates the
complexity of your UI. Exceeding the available object RAM can lead
to crashes or unexpected behavior. The Documentation states what
you can configure using the object RAM
In the Annex environment, the LVGL.INIT command initializes the
LVGL library and sets up the memory buffers. Among its arguments,
col_fg and col_bg play a fundamental role in defining the initial
color scheme of the display.
Purpose of col_fg and col_bg:
● col_fg (Foreground Color): This parameter specifies the primary
color that will be used for elements like text, borders, and other
prominent visual features in your UI. It essentially sets the
"accent" color.
● col_bg (Background Color): This parameter defines the base color
for the background of your display and most widgets.
Why are they
important?
These two color settings establish the initial visual foundation
for your entire application. They determine the overall tone and
contrast of the UI. Choosing appropriate col_fg and col_bg values
is crucial for:
● Readability: Ensuring sufficient contrast between text and
background for easy reading.
● Visual Appeal: Creating an aesthetically pleasing color
scheme.
● Branding: Aligning the UI colors with your brand identity.
The specific format for specifying col_fg and col_bg will depend on
the Annex implementation and the capabilities of the underlying
LVGL library. Common methods include:
● Hexadecimal Color Codes: Using a representation of the color in
hexadecimal format (e.g., &hFF0000 for red).
● Predefined Color Constants:
List of predefined colors with the corresponding RGB888
values (in hexadecimal format)
Color Name
|
RGB88 Value
|
BLACK
|
0x000000
|
NAVY
|
0x000080
|
DARKGREEN
|
0x006400
|
DARKCYAN
|
0x008B8B
|
MAROON
|
0x800000
|
PURPLE
|
0x800080
|
OLIVE
|
0x808000
|
LIGHTGREY
|
0xD3D3D3
|
DARKGREY
|
0xA9A9A9
|
BLUE
|
0x0000FF
|
GREEN
|
0x008000
|
CYAN
|
0x00FFFF
|
RED
|
0xFF0000
|
MAGENTA
|
0xFF00FF
|
YELLOW
|
0xFFFF00
|
WHITE
|
0xFFFFFF
|
ORANGE
|
0xFFA500
|
GREENYELLOW
|
0xADFF2F
|
PINK
|
0xFFC0CB
|
BROWN
|
0xA52A2A
|
GOLD
|
0xFFD700
|
SILVER
|
0xC0C0C0
|
SKYBLUE
|
0x87CEEB
|
VIOLET
|
0x8A2BE2
|
Example:
Here's an example of using LVGL.INIT with col_fg and col_bg in
Annex:
' Initialize LVGL with a red foreground and a black
background
LVGL.INIT RED,
BLACK
LVGL.INIT &h0000FF, &hFFFFFF
' Using hexadecimal color codes
|
This command sets the theme for LVGL. The theme defines the overall
look and feel of the user interface, including colors, fonts, and
other visual attributes. The syntax is:
LVGL.SET_THEME col_primary,
col_secondary, fontnum, dark [,
theme_type]
Arguments:
●
col_primary: Primary color used for prominent UI elements like
buttons and active states.
●
col_secondary: Secondary color used for less prominent UI elements
and inactive states.
●
fontnum: Font number to be used for text elements.
●
dark: Dark mode flag (1 for dark mode, 0 for light mode).
●
theme_type (Optional) : theme
type:
○ 1:
Simple theme.
○ 2:
Mono theme.
○ 0:
Default theme (default).
- Primary Color (col_primary): This color is used for the
main interactive elements such as buttons in their active or
pressed state. It should contrast well with the background color to
ensure visibility and usability.
- Secondary Color (col_secondary): This color is used for
secondary elements and inactive states. It complements the primary
color and helps to create a harmonious color scheme.
- Font Number (fontnum): Specifies the font to be used for
text elements within the UI. Different fonts can be loaded and used
to customize the appearance of text.
- Dark Mode (dark): Enables or disables dark mode, which
uses a darker color palette that is easier on the eyes in low-light
environments.
- Theme Type (theme_type): Allows you to choose between
different predefined themes or create a custom theme. The simple
and mono themes provide quick ways to apply a consistent look,
while the default theme allows for full customization.
Examples:
1. Set a custom theme with a blue primary color, green
secondary color, font number 1, and dark mode enabled
LVGL.SET_THEME &h0000FF,
&h00FF00, 1, 1
2. Set a simple theme with a red primary color, black secondary
color, font number 2, and light mode enabled
LVGL.SET_THEME &hFF0000,
&h000000, 2, 0, 1
3. Set a mono theme with a white primary color, gray secondary
color, font number 3, and dark mode enabled
LVGL.SET_THEME &hFFFFFF,
&h808080, 3, 1, 2
By setting the theme, you can quickly apply a consistent look and
feel across your entire application, ensuring that all UI elements
are visually cohesive and aesthetically pleasing.
lv_style_selector_t is a key feature in LVGL that enables
the combination of two values to target a specific part of an
object in a particular state. This allows developers to apply
styles dynamically and precisely to objects.
Components of
lv_style_selector_t
●
Part (lv_part_t):
Specifies which part of the object to target.
Common parts include
LV_PART_MAIN,
LV_PART_SCROLLBAR, etc.
●
State (lv_state_t):
Defines the state of the object, such as
LV_STATE_PRESSED,
LV_STATE_HOVERED, etc.
It is possible, for example, to change the color of a part of an
object in a particular state.
The example below shows how change the color of a button when
pressed:
' Defines the constants (taken from the tables
below)
LV_PART_MAIN
= 0x0
LV_STATE_PRESSED
= 0x0020
' Create a button But
= LVGL.BUTTON "Button"
' Set the
background color for the button when pressed
LVGL.SET_BG_COLOR
But, RED,
LV_PART_MAIN or
LV_STATE_PRESSED
|
This argument is often optional and, in this case, it defaults to 0
=
LV_PART_MAIN
or
LV_STATE_DEFAULT that means the
main part of the object in its default state.
The current
implementation provides a comprehensive set of functions designed
to facilitate various operations within the library. These
functions are versatile and can be utilized in two distinct
ways:
-
As Functions: When used in this manner, they return a value
as specified in the documentation. This return value can be
meaningful and is often used for further processing or
decision-making within your application.
For instance, in the case of objects such as labels, buttons, etc.,
the returned value typically represents a reference or ID for the
created object. This ID is essential for interacting with the
object later in your code. By using this reference, you can
●
Modify Properties: Change attributes such as colors, sizes,
fonts, or alignment dynamically.
●
Update Content: Adjust the text of a label, the image of an
icon, or the state of a button.
●
Add Events: Attach event handlers to respond to user
interactions like clicks, drags, or gestures.
●
Perform Advanced Operations: Use the ID to group objects,
animate them, or manage their visibility.
-
As Commands: Alternatively, these functions can be invoked
solely to perform an action without considering their return value.
This approach is particularly useful when the result is either
meaningless or not required for the specific use case.
The example below shows this :
' Creates a
label and get its ID into the variable Lab1
Lab = LVGL.LABEL
"Label" ' used as Function
' Change the
text of the label LVGL.SET_TEXT
Lab,
"Change Text"
' Creates a
label with no use of its ID
LVGL.LABEL
"Label2"
' Used as
Command
|
LVGL.INIT col_fg,
col_bg [, buff_size [, buff_count = 1]
Description: Initializes LVGL with specified colors and
optional buffer size and buffer count.
Arguments:
●
col_fg: Foreground color.
●
col_bg: Background color.
●
buff_size: Optional buffer size.
Default is:
○ If
PSRAM is available:
■
Screen_width * screen_height * 2
○ If
PSRAM is NOT available:
■
Screen_width * screen_height * 2 / 10
●
buff_count = 1: Optional buffer
count. Default is 1.
Return: None
LVGL Commands: lv_init(),
lv_display_create(),
lv_display_set_flush_cb(),
lv_display_set_buffers()
LVGL.SET_THEME col_primary,
col_secondary, fontnum, dark [,
theme_type = 0]
Description: Sets the theme for LVGL.
Arguments:
●
col_primary: Primary color.
●
col_secondary: Secondary color.
●
fontnum: Font number.
●
dark: Dark mode flag.
●
theme_type = 0: Optional theme
type (1 for simple, 2 for mono, 0 for default). Default is 0.
Return: None
LVGL Commands: lv_theme_simple_init(),
lv_theme_mono_init(),
lv_theme_default_init()
Description: Refreshes the LVGL display. Must be called
regularly in a loop or with a timer for the update of the
screen.
Arguments: None
Return: None
LVGL Command: lv_timer_handler()
LVGL.START
[memory = 8192]
[, priority = 0]
[, core = 0]
Description: Starts the LVGL task with customizable memory
allocation, priority, and core assignment.
Arguments:
●
memory = 8192: Memory size for the
task. Default is 8192.
●
priority = 0: Optional task
priority. Default is 0 (lowest priority).
●
core = 0: Optional core to run the
task on. Default is 0.
Return: None
RTOS Command: xTaskCreatePinnedToCore()
Notes: This command utilizes a FreeRTOS function to create a
separate task for LVGL operations. The created task runs the
LVGL.REFRESH
function, which internally calls lv_timer_handler().
This approach offers an alternative to manually calling
LVGL.REFRESH
at regular intervals. This command is available only on modules
with dual core and should be used only if a PSRAM chip is
present.
Description: Stops the LVGL task.
Arguments: None
Return: None
LVGL Command: Sets lvgl_task_run to false and waits for the
task to stop.
Description: Resets the LVGL environment by stopping the
task and deinitializing LVGL.
Arguments: None
Return: None
LVGL Commands: lv_deinit()
Description: Cleans the content of active screen or the
content of the optional object.
Arguments:
●
obj: Optional object to be
cleaned; If not specified, the active screen will be cleaned..
Return: None
LVGL Command: lv_obj_clean()
Description: Deletes a specified LVGL object.
Arguments:
● obj:
Object to delete.
Return: None
LVGL Command: lv_obj_delete()
Description: Returns the active screen object. The active
screen represents the device where the image is shown (the
display). By default it is the “father” of all the objects.
Arguments: None
Return: Active screen object.
LVGL Command: lv_screen_active()
Link to LVGL Official DOC
Description: Returns the screen cursor object. Can be used
to hide / show or modify the default cursor pointer.
Arguments: None
Return: Screen cursor object.
LVGL Command: N/A
Description: Sets the default parent object. If 0 is
provided, the default parent will be the active screen object
(LVGL.SCREEN).
Each object created after this command will be a child of it.
Arguments:
● obj:
Object to set as the default parent.
Return: None
LVGL Command: Sets lv_father to the specified object.
LVGL.ARC
[x
[, y
[, w
[, h]]]]
Description: Creates an arc object with optional
dimensions.
Arguments:
● [x]:
Optional X position.
● [y]:
Optional Y position.
● [w]:
Optional width.
● [h]:
Optional height.
Return: Created arc object.
LVGL Command: lv_arc_create()
Link to LVGL Official
DOC
Description: Rotates an object to the current value of an
ARC object.
Arguments:
●
arc_obj: Arc object.
●
obj_to_rotate: Object to rotate.
●
radius_offset: Offset on the radius to be applied at the rotated
object.
Return: None
LVGL Command: lv_arc_rotate_obj_to_angle()
Notes: This command enables drawing a text along the cursor
of an ARC object.
LVGL.BASE
[x
[, y
[, w
[, h]]]]
Description: Creates a base object with optional dimensions.
The “base” object can be used as a container for other objects
acting like a “father” object.
Arguments:
● [x]:
Optional X position.
● [y]:
Optional Y position.
● [w]:
Optional width.
● [h]:
Optional height.
Return: Created base object.
LVGL Command: lv_obj_create()
Link to LVGL Official
DOC
LVGL.BAR
[x
[, y
[, w
[, h]]]]
Description: Creates a bar object with optional
dimensions.
Arguments:
● [x]:
Optional X position.
● [y]:
Optional Y position.
● [w]:
Optional width.
● [h]:
Optional height.
Return: Created bar object.
LVGL Command: lv_bar_create()
Link to LVGL Official
DOC
LVGL.BUTTON text$
[, x[,
y [, w [, h]]]]
Description: Creates a button with text.
Arguments:
●
text$: Button text.
● [x]:
Optional X position.
● [y]:
Optional Y position.
● [w]:
Optional width.
● [h]:
Optional height.
Return: Created button object.
LVGL Commands: lv_button_create(),
lv_label_create(),
lv_label_set_text()
Link to LVGL Official
DOC
Description: Creates a button matrix with a specified map
and optional dimensions.
Arguments:
●
but_map$: String defining the button names.
● [x]:
Optional X position.
● [y]:
Optional Y position.
● [w]:
Optional width.
● [h]:
Optional height.
Return: Created button matrix object.
LVGL Commands: lv_buttonmatrix_create(),
lv_buttonmatrix_set_map()
Button Map Composition
The but_map$
string defines the layout and labels of the buttons in the matrix.
Here’s how to structure it:
-
Button Separation: Button labels are separated by commas
(,). Each comma indicates a new
button within the same row.
-
Line Breaks: To create multiple rows, use the newline
character (\n). This places
buttons on separate lines within the matrix.
Example
Bm1
= LVGL.BUTTONMATRIX "UP,DOWN,\n,LEFT,RIGHT"
Link to LVGL Official
DOC
LVGL.CANVAS
[x
[, y
[, w
[, h [, col_bg]]]]]
Description: Creates a canvas object with a given
dimensions. The canvas object acts as a container for sprites drawn
in the TFT library.
Arguments:
● [x]:
Optional X position.
● [y]:
Optional Y position.
● [w]:
Optional width. Default is 50 px.
● [h]:
Optional height. Default is 50 px.
●
[bg_col]: Optional background color . Default is black.
Return: Created canvas object.
LVGL Command: lv_canvas_create(),lv_canvas_set_buffer(),lv_canvas_fill_bg()
Notes: The CANVAS requires at least 2 × image width × image
height bytes of RAM, so it should be used only with small images
and modules with PSRAM.
Link to LVGL Official
DOC
LVGL.CHECKBOX text$
[, x[,
y [, w [, h]]]]
Description: Creates a checkbox with text.
Arguments:
●
text$: Checkbox text.
● [x]:
Optional X position.
● [y]:
Optional Y position.
● [w]:
Optional width.
● [h]:
Optional height.
Return: Created checkbox object.
LVGL Commands: lv_checkbox_create(),
lv_checkbox_set_text()
Link to LVGL Official
DOC
LVGL.RADIO text$
[, x[,
y [, w [, h]]]]
Description: Creates a radio button with text.
Arguments:
●
text$: Radio button text.
● [x]:
Optional X position.
● [y]:
Optional Y position.
● [w]:
Optional width.
● [h]:
Optional height.
Return: Created radio button object.
LVGL Commands: lv_checkbox_create(),
lv_checkbox_set_text(),
lv_obj_set_style_radius(),
lv_obj_set_style_bg_image_src()
Link to LVGL Official
DOC
LVGL.DROPDOWN options$
[, x [,
y[, w [, h]]]]
Description: Creates a dropdown with options.
Arguments:
●
options$: Dropdown options — a string containing a list of options
separated by “\n”, e.g.[1] ,
“First\nSecond\nLong\nShort”.
● [x]:
Optional X position.
● [y]:
Optional Y position.
● [w]:
Optional width.
● [h]:
Optional height.
Return: Created dropdown object.
LVGL Commands: lv_dropdown_create(),
lv_dropdown_set_options()
Link to LVGL Official DOC
LVGL.GIF path$
[, x[,
y [, w [, h]]]]
Description: Creates a GIF object from a file path.
Arguments:
●
path$: File path of the GIF.
● [x]:
Optional X position.
● [y]:
Optional Y position.
● [w]:
Optional width.
● [h]:
Optional height.
Return: Created GIF object.
LVGL Commands: lv_gif_create(),
lv_gif_set_src()
Notes: The GIF requires at least 4 × image width × image
height bytes of RAM, so it should be used only with small
animations and modules with PSRAM.
Link to LVGL Official
DOC
Description: Controls the playback of a GIF.
Arguments:
● obj:
GIF object.
●
play_control: Playback control (0 to pause, 1 to resume, 2 to
restart).
Return: None
LVGL Commands: lv_gif_pause(),
lv_gif_resume(),
lv_gif_restart()
Description: Creates an image object from a file path
(supports BMP, JPEG, PNG).
Arguments:
●
path$: File path of the image.
Return: Created image object.
LVGL Commands: lv_readBmpFile(),
lv_readJpgFile(),
lv_readPngFile()
Notes: This command loads the images in RAM, so it should be
used sparingly, especially with modules without PSRAM.
Link to LVGL Official
DOC
Description: Creates an image button with optional images
for different states. This command works like a temporary button,
where the image changes when the button is pressed and reverts back
when released.
Arguments:
●
img1: Image for the pressed state.
●
[img2]: Optional image for the released state. If not specified,
img1 will be used with a lower level of luminosity for the released
state.
Return: Created image button object.
LVGL Commands: lv_imagebutton_create(),
lv_imagebutton_set_src()
Notes: This command loads the images in RAM, so it should be
used sparingly, especially with modules without PSRAM.
Link to LVGL Official
DOC
Description: Creates an image button with optional images
for different states. This command works like a toggle button,
where the image changes when the button is checked or
unchecked.
Arguments:
●
img1: Image for the checked state.
●
[img2]: Optional image for the unchecked state. If not specified,
img1 will be used with a lower level of luminosity for the
unchecked state.
Return: Created image button object.
LVGL Commands: lv_imagebutton_create(),
lv_imagebutton_set_src()
Notes: This command loads the images in RAM, so it should be
used sparingly, especially with modules without PSRAM.
Link to LVGL Official
DOC
Description: Creates a keyboard with an optional mode
map.
Arguments:
●
mode: Mode value. (lv_keyboard_mode_t)
Return: Created keyboard object.
LVGL Commands: lv_keyboard_create(),
lv_keyboard_set_mode()
Link to LVGL Official
DOC
Description: Sets the text area for a keyboard object. To
clarify, it designates the textarea that will receive the keys
coming from the keyboard object.
Arguments:
●
kbd_obj: Keyboard object.
●
txt_obj: Text area object.
Return: None
LVGL Command: lv_keyboard_set_textarea()
LVGL.LABEL text$
[, x[,
y [, w [, h]]]]
Description: Creates a label with text.
Arguments:
●
text$: Label text.
● [x]:
Optional X position.
● [y]:
Optional Y position.
● [w]:
Optional width.
● [h]:
Optional height.
Return: Created label object.
LVGL Commands: lv_label_create(),
lv_label_set_text()
Link to LVGL Official
DOC
LVGL.LED
[color [, x [, y [, w [, h]]]]]
Description: Creates an LED with optional color and
position.
Arguments:
●
[color]: Optional LED color.
● [x]:
Optional X position.
● [y]:
Optional Y position.
● [w]:
Optional width.
● [h]:
Optional height.
Return: Created LED object.
LVGL Commands: lv_led_create(),
lv_led_set_color()
Link to LVGL Official
DOC
LVGL.LIST
[x [, y [, w [, h]]]]
Description: Creates a list object.
Arguments:
● [x]:
Optional X position.
● [y]:
Optional Y position.
● [w]:
Optional width.
● [h]:
Optional height.
Return: Created list object.
LVGL Command: lv_list_create()
Link to LVGL Official
DOC
Description: Adds a button to a list.
Arguments:
●
list_obj: List object.
●
icon: Icon for the button (check table with the icon codes).
●
text$: Text for the button; it can contain an icon code too.
Return: Created button object.
LVGL Command: lv_list_add_button()
Description: Adds text to a list.
Arguments:
●
list_obj: List object.
●
text$: Text to add.
Return: Created text object.
LVGL Command: lv_list_add_text()
Description: Creates a message box with a title and
text.
Arguments:
●
title$: Title text.
●
msg$: Message text.
Return: Created message box object.
LVGL Commands: lv_msgbox_create(),
lv_msgbox_add_title(),
lv_msgbox_add_text(),
lv_msgbox_add_close_button(),
lv_msgbox_add_footer_button()
Link to LVGL Official
DOC
Description: Closes a message box.
Arguments:
●
msgbox_obj: Message box object to close.
Return: None
LVGL Command: lv_msgbox_close()
LVGL.ROLLER options$
[, x [, y [, w [,
h]]]]
Description: Creates a roller with options.
Arguments:
●
options$: Roller options — a string containing a list of options
separated by “\n”[2] , e.g.,
“First\nSecond\nLong\nShort”.
● [x]:
Optional X position.
● [y]:
Optional Y position.
● [w]:
Optional width.
● [h]:
Optional height.
Return: Created roller object.
LVGL Commands: lv_roller_create(),
lv_roller_set_options()
Link to LVGL Official
DOC
LVGL.SCALE
[x [, y [, w [, h]]]]
Description: Creates a scale object with optional
dimensions. By default, the scale is LV_SCALE_MODE_HORIZONTAL_BOTTOM
with a range from 0 to 100, 21
ticks with major ticks every 2. The mode can be changed with the
command LVGL.SET_MODE.
Arguments:
● [x]:
Optional X position.
● [y]:
Optional Y position.
● [w]:
Optional width.
● [h]:
Optional height.
Return: Created scale object.
LVGL Commands: lv_scale_create(),
lv_scale_set_text_src(),
lv_scale_set_mode(),
lv_scale_set_label_show(),
lv_scale_set_total_tick_count(),
lv_scale_set_major_tick_every(),
lv_obj_set_style_length(),
lv_scale_set_range()
Link to LVGL Official
DOC
Description: Sets the angle range for a scale object.
Arguments:
● obj:
Scale object.
● val:
Angle range value.
Return: Object type.
LVGL Command: lv_scale_set_angle_range()
Description: Sets the total tick count and major tick
interval for a scale object.
Arguments:
● obj:
Scale object.
●
total: Total tick count.
●
interval: Major tick interval.
Return: None.
LVGL Commands: lv_scale_set_total_tick_count(),
lv_scale_set_major_tick_every()
Description: Sets whether to show labels on a scale
object.
Arguments:
● obj:
Scale object.
● val:
Show labels flag (1 for true, 0 for false).
Return: None.
LVGL Command: lv_scale_set_label_show()
Description: Creates a line object.
Arguments: None.
Return: Created line object.
LVGL Command: lv_line_create()
Note: The line is actually used only as a needle for the
Scale Object.
Description: Sets the line needle value for a scale
object.
Arguments:
●
scale_obj: Scale object.
●
line_obj: Needle object.
●
length: Needle length.
● val:
Needle value.
Return: None.
LVGL Command: lv_scale_set_line_needle_value()
Description: Sets the image needle value for a scale object.
This allows an image to be used as the needle for the scale object.
The image must be loaded beforehand and aligned with the scale
object. The functions LVGL.SET_IMAGE_PIVOT or
LVGL.SET_IMAGE_PIVOT_PCT can be used to perfectly align the
rotation point (the pivot) of the needle.
Arguments:
●
scale_obj: Scale object.
●
line_obj: Needle object.
● val:
Needle value.
Return: None.
LVGL Command: lv_scale_set_image_needle_value()
Notes: The image must point to the right. E.g.
-O------>
Description: Creates a slider object with optional
dimensions.
Arguments:
● [x]:
Optional X position.
● [y]:
Optional Y position.
● [w]:
Optional width.
● [h]:
Optional height.
Return: Created slider object.
LVGL Command: lv_slider_create()
Link to LVGL Official
DOC
LVGL.SPINNER anim,
angle [, x [, y [, w [,
h]]]]
Description: Creates a spinner with animation
parameters.
Arguments:
●
anim: Animation time.
●
angle: Angle increment.
● [x]:
Optional X position.
● [y]:
Optional Y position.
● [w]:
Optional width.
● [h]:
Optional height.
Return: Created spinner object.
LVGL Commands: lv_spinner_create(),
lv_spinner_set_anim_params()
Link to LVGL Official DOC
Description: Creates a switch object with optional
dimensions.
Arguments:
● [x]:
Optional X position.
● [y]:
Optional Y position.
● [w]:
Optional width.
● [h]:
Optional height.
Return: Created switch object.
LVGL Command: lv_switch_create()
Link to LVGL Official
DOC
Description: Creates a tab view object.
Arguments:
● [x]:
Optional X position.
● [y]:
Optional Y position.
● [w]:
Optional width.
● [h]:
Optional height.
Return: Created tab view object.
LVGL Command: lv_tabview_create()
Link to LVGL Official DOC
Description: Adds a tab to a tab view.
Arguments:
●
tab_view_obj: Tab view object.
●
tab_name$: Tab name.
Return: Created tab object.
LVGL Command: lv_tabview_add_tab()
Description: Sets the tab bar position for a tab view.
Arguments:
●
tab_view_obj: Tab view object.
●
tab_pos: Position value (lv_dir_t).
Return: None.
LVGL Command: lv_tabview_set_tab_bar_position()
Description: Sets the active tab for a tab view object.
Arguments:
● obj:
Tab view object.
● idx:
Index of the tab to set as active.
●
[anim]: Optional animation flag (1 for animated, 0 for
immediate).
Return: Object type.
LVGL Command: lv_tabview_set_active()
LVGL.TEXTAREA text$
[, x [, y [, w [,
h]]]]
Description: Creates a text area with text.
Arguments:
●
text$: Text area text.
● [x]:
Optional X position.
● [y]:
Optional Y position.
● [w]:
Optional width.
● [h]:
Optional height.
Return: Created text area object.
LVGL Commands: lv_textarea_create(),
lv_textarea_set_one_line(),
lv_textarea_set_text()
Notes: By default, the textarea is a single line but can be
changed using the command LVGL.SET_MODE.
Link to LVGL Official
DOC
Description: Adds an event to an object.
Arguments:
● obj:
Object to add the event to.
●
event: Event code. (lv_event_code_t)
●
gotoline: Line number to go to when the event is triggered.
Return: None.
LVGL Command: lv_obj_add_event_cb()
Notes: This command adds an event to an object. The event
code and the line number to go to when the event is triggered are
specified.
Link to LVGL Official
DOC
Description: Removes an event from an object.
Arguments:
● obj:
Object to remove the event from.
●
event: Event code. (lv_event_code_t)
Return: None.
LVGL Command: lv_obj_remove_event()
Description: Adds one or more flags to an LVGL object.
Arguments:
● obj:
The LVGL object to add the flag(s) to.
●
flag: The flag or combination of flags to add (can use bitwise OR
for multiple flags). (lv_obj_flag_t)
Return: Object type.
LVGL Command: lv_obj_add_flag()
Link to LVGL Official
DOC
Description: Removes one or more flags from an LVGL
object.
Arguments:
● obj:
The LVGL object to remove the flag(s) from.
●
flag: The flag or combination of flags to remove (can use bitwise
OR for multiple flags). (lv_obj_flag_t)
Return: Object type.
LVGL Command: lv_obj_remove_flag()
Description: Updates a flag for an object.
Arguments:
● obj:
Object to update flag for.
● val:
Value for the flag (can be 0 or 1).
●
[flag]: Optional Flag to update (default = 1). (lv_obj_flag_t)
Return: Object type.
LVGL Command: lv_obj_update_flag()
Description: Returns the flags of an object. (lv_obj_flag_t)
Arguments:
● obj:
Object to get flags for.
Return: Flags of the object.
LVGL Command: Returns obj->flags.
Description: Adds one or more states to an LVGL object.
Arguments:
● obj:
The LVGL object to add the state(s) to.
●
state: The state or combination of states to add (can use bitwise
OR for multiple states). (lv_state_t)
Return: Object type.
LVGL Commands: lv_obj_add_state()
Link to LVGL Official
DOC
Description: Removes one or more states from an LVGL
object.
Arguments:
● obj:
The LVGL object to remove the state(s) from.
●
state: The state or combination of states to remove (can use
bitwise OR for multiple states). (lv_state_t)
Return: Object type.
LVGL Commands: lv_obj_remove_state()
Description: Sets the state of an LVGL object.
Arguments:
● obj:
The LVGL object to set the state for.
● val:
Boolean value (1 to set the state, 0 to clear it).
●
[state]: Optional. The specific state to set or clear. (default =
1). (lv_state_t)
Return: Object type.
LVGL Commands: lv_obj_set_state()
Link to LVGL Official
DOC
Description: Returns the state of an object. (lv_state_t)
Arguments:
● obj:
Object to get state for.
Return: State of the object.
LVGL Command: lv_obj_get_state()
LVGL.ALIGN_TO obj,
obj_base, align [, x [, y]]
Description: Aligns an object to another object.
Arguments:
● obj:
Object to align.
●
obj_base: The reference object to align obj to.
●
align: The alignment type, defined as (lv_align_t).
This determines how the objects are positioned relative to each
other.
● [x]:
Optional horizontal offset in pixels, applied after alignment.
● [y]:
Optional vertical offset in pixels, applied after alignment.
Return: None.
LVGL Command: lv_obj_align_to()
Notes: This command enables you to position an object (obj)
relative to another object (obj_base) using predefined alignment
types. The alignment types are numeric values defined in the
(lv_align_t)
table (refer to the image below for details).

The optional x and y arguments allow you to fine-tune the position
by shifting the aligned object horizontally and vertically by a
specified number of pixels.
Link to LVGL Official
DOC
Description: Returns the child object at a specific
index.
Arguments:
● obj:
Parent object.
● idx:
Index of the child object.
Return: Child object at the specified index.
LVGL Command: lv_obj_get_child()
Description: Returns the number of child objects.
Arguments:
● obj:
Parent object.
Return: Number of child objects.
LVGL Command: lv_obj_get_child_count()
Description: Returns the parent object.
Arguments:
● obj:
Child object.
Return: Parent object.
LVGL Command: lv_obj_get_parent()
Description: Sets the parent of an object.
Arguments:
● obj:
Child object.
●
obj_parent: New parent object.
Return: None.
LVGL Command: lv_obj_set_parent()
Description: Returns the class ID of an
object.[3]
Arguments:
● obj:
Object to get the class ID for.
Return: Class ID of the object.
LVGL Command: get_obj_type()
Description: Creates a new group.
Arguments:: None.
Return:: Created group.
LVGL Command:: :
lv_group_create()
Description: Adds an object to a group.
Arguments:
●
group: Group to add the object to.
● obj:
Object to add to the group.
Return:: Group.
LVGL Command:: :
lv_group_add_obj()
Description:: Removes an object from its group.
Arguments:
● obj:
Object to remove from the group.
Return: None.
LVGL Command: lv_group_remove_obj()
Description: Deletes a group.
Arguments:
●
group: Group to delete.
Return: None.
LVGL Command: lv_group_delete()
Description: Gets the group of an object.
Arguments:
● obj:
Object to get the group for.
Return: Group of the object.
LVGL Command: lv_obj_get_group()
Description: Returns the target object who triggered the
event.
Arguments: None.
Return: Target object.
LVGL Command: lv_obj_target
Description: Returns the gesture that triggered the
event.
Arguments: None.
Return: Gesture enum (lv_dir_t).
LVGL Command: lv_obj_gesture_dir
Description: Returns the value of an object. The value can
vary depending on the type of the object.
Arguments:
● obj:
Object to get value for.
○ For
Slider: Get the value.
○ For
Arc: Get the value.
○ For
Bar: Get the value.
○ For
Led: Get the brightness.
○ For
Roller: Get the index of the selected option.
○ For
Dropdown: Get the index of the selected option.
○ For
ImageButton: Get the state.
○ For
Keyboard: Get the index of the last "activated" key by the user
(pressed, released, focused, etc.).
○ For
ButtonMatrix: Get the index of the last "activated" button by the
user (pressed, released, focused, etc.).
Return: Value of the object.
LVGL Commands: lv_slider_get_value(),
lv_arc_get_value(),
lv_bar_get_value(),
lv_led_get_brightness(),
lv_roller_get_selected(),
lv_dropdown_get_selected(),
lv_obj_get_state()
Description: Loads a font from a file.
Arguments:
●
path$: File path of the font.
●
fontnum: Font index (from 100 to 103).
Return: None.
LVGL Command: lv_binfont_create()
Notes: The fonts are loaded from file and must be in .bin
format converted using the LVGL Online Font Converter
LVGL.SET_FONT obj,
fontnum [,style_selector]
Description: Sets the font of an object.
Arguments:
● obj:
Object to set font for.
●
fontnum: Font number.
●
style_selector: Optional state to
set font for. (lv_state_t)
and (lv_part_t)
Font Numbers:
● 1 :
unascii 8px
● 2 :
unascii 16px
● 8 :
montserrat 8
● 10 :
montserrat 10
● 12 :
montserrat 12
● 14 :
montserrat 14
● 16 :
montserrat 16
● 18 :
montserrat 18
● 20 :
montserrat 20
● 30 :
montserrat 30
● 100
: loaded font 100
● 101
: loaded font 101
● 102
: loaded font 102
● 103
: loaded font 103
Return: None.
LVGL Command: lv_obj_set_style_text_font()
Description: Sets the background angles of an arc
object.
Arguments:
● obj:
Arc object.
●
start: Start angle.
● end:
End angle.
Return: Object type.
LVGL Command: lv_arc_set_bg_angles()
Description: Sets the background color of an object.
Arguments:
● obj:
Object to set background color for.
●
col_bg: Background color.
●
style_selector: Optional state to
set background color for. (lv_state_t)
and (lv_part_t)
Return: None.
LVGL Command: lv_obj_set_style_bg_color()
Description: Sets the background opacity of an object.
Arguments:
● obj:
Object to set background opacity for.
● val:
Background opacity value (from 0=transparent to 255=cover).
●
style_selector: Optional state to
set background opacity for. (lv_state_t)
and (lv_part_t)
Return: None.
LVGL Command: lv_obj_set_style_bg_opa()
Description: Sets the border color of an object.
Arguments:
● obj:
Object to set border color for.
●
color: Border color.
●
style_selector: Optional state to
set border color for. (lv_state_t)
and (lv_part_t)
Return: None.
LVGL Command: lv_obj_set_style_border_color()
Description: Sets the border side for an object.
Arguments:
● obj:
Object to set border side for.
●
side: Border side value (lv_border_side_t).
●
style_selector: Optional state to
set border side for. (lv_state_t)
and (lv_part_t)
Return: None.
LVGL Command: lv_obj_set_style_border_side()
Description: Sets the border width for an object.
Arguments:
● obj:
Object to set border width for.
●
width: Border width value.
●
style_selector: Optional state to
set border width for. (lv_state_t)
and (lv_part_t)
Return: None.
LVGL Command: lv_obj_set_style_border_width()
Description: Sets the clip corner for an object.
Arguments:
● obj:
Object to set clip corner for.
● val:
Clip corner flag (1 for true, 0 for false).
●
style_selector: Optional state to
set clip corner for. (lv_state_t)
and (lv_part_t)
Return: None.
LVGL Command: lv_obj_set_style_clip_corner()
Note: Enable to clip the overflowed content on the rounded
corner. Can be true (1) or false (0).
Description: Sets the color of an ARC object. This command
is oriented for ARC, SPINNER, and SCALE objects.
Arguments:
● obj:
Object to set arc color for.
●
color: Arc color.
●
style_selector: Optional state to
set arc color for. (lv_state_t)
and (lv_part_t)
Return: None.
LVGL Command: lv_obj_set_style_arc_color()
Description: Sets the opacity of an ARC object. This command
is oriented for ARC, SPINNER, and SCALE objects.
Arguments:
● obj:
Object to set arc opacity for.
● val:
Opacity value (from 0=transparent to 255=cover).
●
style_selector: Optional state to
set arc opacity for. (lv_state_t)
and (lv_part_t)
Return: None.
LVGL Command: lv_obj_set_style_arc_opa()
Description: Sets the color of an object. This command tries
to be generic and should cover all objects, including LED.
Arguments:
● obj:
Object to set color for.
●
color: Color value. The effect depends on the object type:
○ For
LED: Sets the color of the LED (lv_led_set_color()).
○ For
other objects: Sets the lv_obj_set_style_line_color
property.
●
style_selector: Optional state to
set color for. (lv_state_t)
and (lv_part_t)
Return: Object type.
LVGL Commands: lv_obj_set_style_arc_color(),
lv_obj_set_style_line_color(),
lv_led_set_color()
Description: Sets the opacity of an object. This command
tries to be generic and should cover all objects.
Arguments:
● obj:
Object to set opacity for.
● val:
Opacity value (from 0=transparent to 255=cover).
●
style_selector: Optional state to
set opacity for. (lv_state_t)
and (lv_part_t)
Return: Object type.
LVGL Commands: lv_obj_set_style_line_opa()
Description: Sets the flex alignment for an object.
Arguments:
● obj:
Object to set flex alignment for.
●
main: Alignment for the main axis (lv_flex_align_t).
●
cross: Alignment for the cross axis (lv_flex_align_t).
●
track_cross: Alignment for the track cross (lv_flex_align_t).
Return: None.
LVGL Command: lv_obj_set_flex_align()
Link to LVGL Official DOC
Description: Sets the flex flow for an object.
Arguments:
● obj:
Object to set flex flow for.
●
flex_flow: Flex flow value (lv_flex_flow_t).
Return: None.
LVGL Command: lv_obj_set_flex_flow()
Link to LVGL Official
DOC
Description: Sets the height of an object.
Arguments:
● obj:
Object to set height for.
● h:
Height.
Return: None.
LVGL Command: lv_obj_set_height()
Description: Sets the image recolor of an object.
Arguments:
● obj:
Object to set image recolor for.
●
color: Recolor value.
●
style_selector: Optional state to
set image recolor for. (lv_state_t)
and (lv_part_t)
Return: None.
LVGL Command: lv_obj_set_style_image_recolor()
Description: Sets the image recolor opacity of an
object.
Arguments:
● obj:
Object to set image recolor opacity for.
● val:
Recolor opacity value (from 0=transparent to 255=cover).
●
style_selector: Optional state to
set image recolor opacity for. (lv_state_t)
and (lv_part_t)
Return: None.
LVGL Command: lv_obj_set_style_image_recolor_opa()
Description: Moves an object to a specified layer.
Arguments:
● obj:
Object to move.
●
layer: Layer index or special value:
○ 1000
for foreground
○
-1000 for background
○
-9999 bottom layer
○ 9999
top layer
○
10000 sys layer
Return: None.
LVGL Commands: lv_obj_move_foreground(),
lv_obj_move_background(),
lv_obj_move_to_index(),
lv_obj_set_parent()
Description: Sets the length for an object.
Arguments:
● obj:
Object to set length for.
● val:
Length value.
●
style_selector: Optional state to
set length for. (lv_state_t)
and (lv_part_t)
Return: None.
LVGL Command: lv_obj_set_style_length()
Description: Sets whether the line is rounded for an
object.
Arguments:
● obj:
Object to set line rounded for.
● val:
Line rounded flag (1 for true, 0 for false).
●
style_selector: Optional state to
set line rounded for. (lv_state_t)
and (lv_part_t)
Return: None.
LVGL Command: lv_obj_set_style_line_rounded()
Description: Sets the line width for an object.
Arguments:
● obj:
Object to set line width for.
● val:
Line width value.
●
style_selector: Optional state to
set line width for. (lv_state_t)
and (lv_part_t)
Return: None.
LVGL Command: lv_obj_set_style_line_width()
LVGL.SET_MARGIN obj, top,
[,bottom [,left [,right [,vert [,horiz [,
style_selector]]]]]]
Description: Sets the margin for an object.
Arguments:
● obj:
Object to set margin for.
● top:
Top margin value.
●
bottom: Optional bottom margin
value.
●
left: Optional left margin
value.
●
right: Optional right margin
value.
●
vert: Optional vertical margin
value.
●
horiz: Optional horizontal margin
value.
●
style_selector: Optional state to
set margin for. (lv_state_t)
and (lv_part_t)
Return: None.
LVGL Commands: lv_obj_set_style_margin_top(),
lv_obj_set_style_margin_bottom(),
lv_obj_set_style_margin_left(),
lv_obj_set_style_margin_right(),
lv_obj_set_style_margin_ver(),
lv_obj_set_style_margin_hor()
Link to LVGL Official DOC
LVGL.SET_MODE
obj,
val
Description: Sets the mode for an object. The mode can vary
depending on the type of the object.
Arguments:
● obj:
Object to set mode for.
● val:
Mode value. The acceptable values depend on the object type:
○
For Scale: Set how the scale is shown (lv_scale_mode_t):
■
0x00: The scale will be horizontal and the labels text aligned to
the top.
■
0x01: The scale will be horizontal and the labels text aligned to
the bottom.
■
0x02: The scale will be vertical and the labels text aligned to the
left.
■
0x04: The scale will be vertical and the labels text aligned to the
right.
■
0x08: The scale will be round and the labels text aligned to the
inner side.
■
0x10: The scale will be round and the labels text aligned to the
outer side.
○
For Keyboard: Set how the keyboard is shown (lv_keyboard_mode_t):
■ 0:
Lowercase text input mode.
■ 1:
Uppercase text input mode.
■ 2:
Special characters input mode.
■ 3:
Numeric input mode.
○
For Label: Set the long mode (lv_label_long_mode_t):
■ 0:
Wrap lines longer than the object width and expand the object
height.
■ 1:
Write dots at the end if the text is too long.
■ 2:
Roll the text back and forth.
■ 3:
Roll the text circularly.
■ 4:
Clip the text out of the object's size.
○
For Text Area: Set the line mode:
■ 0:
Multi-line text input mode.
■ 1:
Single-line text input mode.
Return: Object type.
LVGL Commands: lv_scale_set_mode(),
lv_keyboard_set_mode()
LVGL.SET_PAD obj, top,
[,bottom [,left [,right [,vert [,horiz
[,row [,column [, style_selector]]]]]]]]
Description: Sets the padding for an object.
Arguments:
● obj:
Object to set padding for.
● top:
Top padding value.
●
bottom: Optional bottom padding
value.
●
left: Optional left padding
value.
●
right: Optional right padding
value.
●
vert: Optional vertical padding
value.
●
horiz: Optional horizontal padding
value.
●
row: Optional row padding
value.
●
column: Optional column padding
value.
●
style_selector: Optional state to
set padding for. (lv_state_t)
and (lv_part_t)
Return: None.
LVGL Commands: lv_obj_set_style_pad_top(),
lv_obj_set_style_pad_bottom(),
lv_obj_set_style_pad_left(),
lv_obj_set_style_pad_right(),
lv_obj_set_style_pad_ver(),
lv_obj_set_style_pad_hor(),
lv_obj_set_style_pad_row(),
lv_obj_set_style_pad_column()
Link to LVGL Official DOC
Description: Sets the padding gap for an object.
Arguments:
● obj:
Object to set padding gap for.
● val:
Padding gap value.
●
style_selector: Optional state to
set padding gap for. (lv_state_t)
and (lv_part_t)
Return: None.
LVGL Command: lv_obj_set_style_pad_gap()
Description: Sets the position of an object.
Arguments:
● obj:
Object to set position for.
● x: X
position.
● y: Y
position.
Return: None.
LVGL Command: lv_obj_set_pos()
Link to LVGL Official DOC
Description: Sets the range of an object. This command
covers the following objects: Arc, Slider, Bar, Scale.
Arguments:
● obj:
Object to set range for.
●
start: Start value.
● end:
End value.
Return: Object type.
LVGL Commands: lv_arc_set_range(),
lv_slider_set_range(),
lv_bar_set_range(),
lv_scale_set_range()
Description: Sets the radius for an object.
Arguments:
● obj:
Object to set radius for.
● val:
Radius value.
●
style_selector: Optional state to
set radius for. (lv_state_t)
and (lv_part_t)
Return: None.
LVGL Command: lv_obj_set_style_radius()
Description: Sets the offset rotation of an ARC or SCALE
object.
Arguments:
● obj:
Object to set rotation for.
●
angle: Rotation value (°). The angular offset from the 3 o'clock
position (clockwise).
Return: Object type.
LVGL Commands: lv_arc_set_rotation(),
lv_scale_set_rotation()
Description: Sets the scroll direction for an object.
Arguments:
● obj:
Object to set scroll direction for.
●
scroll_dir: Scroll direction (1 for vertical, 2 for horizontal, 3
for all, 0 for none).
Return: None.
LVGL Command: lv_obj_set_scroll_dir()
Description: Sets the size of an object.
Arguments:
● obj:
Object to set size for.
● w:
Width.
● h:
Height.
Return: None.
LVGL Command: lv_obj_set_size()
Link to LVGL Official
DOC
Description: Sets the size of an object as a percentage.
Arguments:
● obj:
Object to set size for.
●
w_pct: Width percentage.
●
h_pct: Height percentage.
Return: None.
LVGL Command: lv_obj_set_size()
Link to LVGL Official
DOC
Description: Sets the text of an object. It works for the
following objects:
-
Button (including the buttons in the LIST)
-
Checkbox / Radio
-
Label (including the text in the LIST
-
Textarea
-
Scale : set the text of the scale labels (texts separated by ‘,’
)
Arguments:
● obj:
Object to set text for.
●
str$: Text to set.
Return: Object type.
LVGL Commands: lv_label_set_text(),
lv_checkbox_set_text(),
lv_textarea_set_text(),
lv_scale_set_text_src()
Description: Sets the text alignment of an object.
Arguments:
● obj:
Object to set text alignment for.
●
align: Text alignment value (lv_text_align).
Return: None.
LVGL Command: lv_obj_set_style_text_align()
Description: Sets the text color of an object.
Arguments:
● obj:
Object to set text color for.
●
color: Text color.
●
style_selector: Optional state to
set text color for. (lv_state_t)
and (lv_part_t)
Return: None.
LVGL Command: lv_obj_set_style_text_color()
Description: Sets the transformation pivot of an object.
Arguments:
● obj:
Object to set transformation pivot for.
● x: X
pivot value.
● y: Y
pivot value.
●
style_selector: Optional state to
set transformation pivot for. (lv_state_t)
and (lv_part_t)
Return: None.
LVGL Commands: lv_obj_set_style_transform_pivot_x(),
lv_obj_set_style_transform_pivot_y()
Description: Sets the transformation pivot as a percentage
for an object.
Arguments:
● obj:
Object to set transformation pivot for.
●
x_pct: X pivot percentage.
●
y_pct: Y pivot percentage.
●
style_selector: Optional state to
set transformation pivot for. (lv_state_t)
and (lv_part_t)
Return: None.
LVGL Commands: lv_obj_set_style_transform_pivot_x(),
lv_obj_set_style_transform_pivot_y()
Description: Set the rotation center of the image.
Arguments:
● obj:
Image object to set the rotation center for.
● x: X
pivot value.
● y: Y
pivot value.
Return: None.
LVGL Commands: lv_image_set_pivot()
Description: Set the rotation center in percentage of the
image.
Arguments:
● obj:
Object to set transformation pivot for.
●
x_pct: X pivot percentage.
●
y_pct: Y pivot percentage.
Return: None.
LVGL Commands: lv_image_set_pivot()
Description: Sets the transformation angle of an object.
Arguments:
● obj:
Object to set transformation angle for.
●
angle: Angle value (resolution 0.1°).
●
style_selector: Optional state to
set transformation angle for. (lv_state_t)
and (lv_part_t)
Return: None.
LVGL Command: lv_obj_set_style_transform_rotation()
Description: Sets the transformation scale of an object.
Arguments:
● obj:
Object to set transformation scale for.
● x: X
scale value.
● y: Y
scale value.
●
style_selector: Optional state to
set transformation scale for. (lv_state_t)
and (lv_part_t)
Return: None.
LVGL Commands: lv_obj_set_style_transform_scale_x(),
lv_obj_set_style_transform_scale_y()
Notes: The value 256 (or LV_SCALE_NONE) means normal size,
128 half size, 512 double size, and so on.
Description: Sets the value of an object. The value can vary
depending on the type of the object.
Arguments:
● obj:
Object to set value for.
● val:
Value to set.
●
anim: Optional animation flag (1
for animated, 0 for immediate); defaults to 1
For specific objects:
●
Slider: Set the value with the optional animation flag.
●
Arc: Set the value.
●
Bar: Set the value with the optional animation flag.
●
LED:
○ 0:
LED off.
○ 1:
LED on.
○ 2:
LED toggle.
○
Other values: Set luminosity (from 3 to 255).
●
Roller: Set the selected option with the optional animation
flag.
●
Dropdown: Set the selected option.
●
ImageButton: Set the state.
Return: Object type.
LVGL Commands: lv_slider_set_value(),
lv_arc_set_value(),
lv_bar_set_value(),
lv_led_on(),
lv_led_off(),
lv_led_toggle(),
lv_led_set_brightness(),
lv_roller_set_selected(),
lv_dropdown_set_selected(),
lv_imagebutton_set_state()
Description: Sets the width of an object.
Arguments:
● obj:
Object to set width for.
● w:
Width.
Return: None.
LVGL Command: lv_obj_set_width()
LVGL.SPRITE.PUSH canvas_obj,
sprite_num [, x [, y]]
Description: Push (copy) a sprite object, defined in the TFT
library, into a canvas object. If the dimensions of the canvas and
the sprite differ, only the overlapping portion (relative size)
will be copied. By default, the sprite is copied starting from the
top-left corner of the canvas. However, this behavior can be
modified using the optional x and y arguments to specify the
starting position.
This command allows you to draw graphics (such as lines, circles,
etc.) using TFT.xxx functions within sprites and then transfer the
resulting image into LVGL.
Arguments:
●
canvas_obj: Canvas object where the sprite will be copied
●
sprite_num : Sprite object number (from 0 to 9) as defined in the
TFT library.
● [x]:
Optional X position.
● [y]:
Optional Y position.
Return: None.
LVGL Commands: lv_canvas_get_image(),lv_obj_invalidate()
LVGL.SWAP
obj,
obj_base
Description: Swaps the positions of two objects.
Arguments:
● obj:
First object.
●
obj_base: Second object.
Return: None.
LVGL Command: lv_obj_swap()
Description: Sets the visibility of an object.
Arguments:
● obj:
Object to set visibility for.
● vis:
Visibility flag (1 for visible, 0 for hidden).
Return: None.
LVGL Command: lv_obj_update_flag()
LVGL.RGB(red,
green, blue)
Description: Combines the RGB components into a single
value.
Arguments:
● red:
Red color component (from 0 to 255).
●
green: Green color component (from 0 to 255).
●
blue: Blue color component (from 0 to 255).
Return: Combined RGB888 color.
LVGL Command: N/A
Description: Creates a mouse pointer object. The mouse
pointer is actually a purple arrow. The “mouse” position and status
can then be set using the commands LVGL.MOUSEMOVE
Arguments: None.
Return: None.
LVGL Commands: lv_indev_create(),
lv_indev_set_type(),
lv_indev_set_cursor(),
lv_indev_set_read_cb()
Description: Sets the position of the “mouse”.
Arguments: None.
●
mouse_x: X position of the mouse.
●
mouse_y: Y position of the mouse.
●
mouse_z: button of the mouse (0 = released, 1 = pressed)
Return: None.
LVGL Command: None.
Description: Returns the mouse cursor object. Can be used to
hide / show or modify the default mouse pointer.
Arguments: None
Return: Mouse cursor object.
LVGL Command: N/A
Description: Initializes a keyboard functionality permitting
to send keystrokes from an external hardware keyboard to LVGL
objects. The keystrokes can be sent using the command
LVGL.SET_KEYBOARD_KEY.
Arguments: None.
Return: None.
LVGL Commands: lv_indev_create(),
lv_indev_set_type(),
lv_indev_set_cursor(),
lv_indev_set_read_cb()
Description: Sends a keystroke to the active object.
Arguments:
● key:
ASCII code of the key to be sent; 0 means no key pressed.
Return: None.
LVGL Command: None.
Description: Sets the group of objects that will receive
keystrokes sent using the command LVGL.SET_KEYBOARD_KEY. The active
object in the group will receive the keystrokes.
Arguments: None.
Return: None.
LVGL Command: lv_indev_set_group()
Or
LVGL.SET_IMAGE_SRC obj,
ref
Description: Sets the source of an image object (obj) to
display either an icon or an image.
Arguments:
● obj:
Object to set icon for.
● Src:
The source of the image
○ If
src is a string, it sets
■ An
icon code (e.g., LV_SYMBOL_OK) or
■ A
file path to load an external image (e.g., "/:image.bmp").
■ P.S.
: image loaded in this way are very slow because are loaded
dynamically
○ If
src is a reference (memory address), it sets:
■ A
pointer to an image descriptor (lv_img_dsc_t) stored in memory,
generally shared with another image already loaded and get with
LVGL.GET_IMAGE_SRC
Return: None.
LVGL Command: lv_image_set_src()
Description: Gets the reference of the image source
(memory address)
Arguments:
● obj:
Object to get image source for.
Return: The image source .
LVGL Command: lv_image_get_src()
Description: Returns the class name of an object.
Arguments:
● obj:
Object to get class name for.
Return: Class name of the object (string).
LVGL Command: lv_obj_get_class()
Notes: Useful to determine the type of object (same as
GET_CLASS_ID but with a text output).
Description: Returns the text of an object. Covers the
following objects: Button, Checkbox / Radio, Label, Textarea,
Keyboard (the key pressed), Roller, Dropdown, ButtonMatrix (the
button pressed), and the buttons/text in the LIST.
Arguments:
● obj:
Object to get text for (string).
Return: Text of the object.
LVGL Commands: lv_label_get_text(),
lv_checkbox_get_text(),
lv_textarea_get_text(),
lv_roller_get_selected_str(),
lv_dropdown_get_selected_str(),
lv_keyboard_get_button_text()
The LVGL library provides
a rich and versatile set of predefined enums, states, flags, and
modes to manage and customize graphical user interface (GUI)
elements. These tables serve as a comprehensive reference for
developers, enabling them to understand and utilize the framework's
capabilities effectively. Below, all the tables available in LVGL
are listed with a brief explanation or introduction for each:
-
Widget States
This table summarizes the possible states of a widget, such as
LV_STATE_CHECKED or
LV_STATE_PRESSED.
Each state is represented by a hexadecimal value and can be
combined using bitwise operations to represent multiple states
simultaneously.
-
Widget Parts
Describes the internal components of widgets, such as scrollbars,
indicators, knobs, and custom parts. These parts contribute to the
widget's appearance and functionality.
-
Object Flags
Lists on/off features that control object behavior in the GUI.
Flags like
LV_OBJ_FLAG_CLICKABLE or
LV_OBJ_FLAG_SCROLLABLE determine how objects respond to user
interactions and layout management.
-
Image Button States
Defines the visual and interactive states of image buttons, such as
pressed, released, disabled, or checked.
-
Alignment Enums
Specifies alignment options for objects relative to their parent
containers or other objects (e.g.,
LV_ALIGN_CENTER,
LV_ALIGN_TOP_LEFT).
-
Text Alignment Enums
Defines how text is aligned within its container, offering options
like left-aligned (LV_TEXT_ALIGN_LEFT)
or center-aligned (LV_TEXT_ALIGN_CENTER).
-
Direction Enums
Enumerates possible directions for scrolling or other operations,
such as horizontal (LV_DIR_HOR)
or vertical (LV_DIR_VER).
-
Border Side Enums
Specifies which sides of an object should have borders (e.g.,
LV_BORDER_SIDE_FULL,
LV_BORDER_SIDE_BOTTOM).
-
Flexbox Layout Options and Enumerations
Includes flexbox layout options (e.g.,
LV_FLEX_FLOW_ROW,
LV_FLEX_ALIGN_CENTER) for arranging items in flexible and
responsive layouts.
-
Scale Modes
Describes how scales are displayed in objects like sliders or arcs
(e.g., horizontal top-aligned or round outer-aligned).
-
Label Long Mode Options
Specifies how labels handle text that exceeds their width, such as
wrapping (LV_LABEL_LONG_WRAP)
or scrolling circularly (LV_LABEL_LONG_SCROLL_CIRCULAR).
-
Keyboard Modes and Keys
Provides modes for keyboard input (e.g., numeric mode:
LV_KEYBOARD_MODE_NUMBER) and key enums for navigation (e.g.,
arrow keys:
LV_KEY_UP,
LV_KEY_DOWN).
-
Event Codes
Lists event codes representing interactions like clicks
(LV_EVENT_CLICKED)
or presses (LV_EVENT_PRESSED)
-
Symbol Definitions (unicode from FontAwesome)
This table lists LVGL's built-in symbols derived from FontAwesome
icons, represented as UTF-8 encoded strings for consistent UI
elements:
These tables
provide developers with structured information to configure
widgets, manage object behavior, and implement advanced GUI
features in LVGL applications efficiently.
This table summarizes the possible states of a
widget, with each state represented by a hexadecimal value. The
states can be combined using bitwise OR operations to represent
multiple states simultaneously.
State
|
Value (Hex)
|
Description
|
|
0x0000
|
Default state.
|
|
0x0001
|
Widget is checked.
|
|
0x0002
|
Widget is focused.
|
|
0x0004
|
Widget is focused via keyboard.
|
|
0x0008
|
Widget is being edited.
|
|
0x0010
|
Widget is hovered over.
|
|
0x0020
|
Widget is pressed.
|
|
0x0040
|
Widget is scrolled.
|
|
0x0080
|
Widget is disabled.
|
|
0x1000
|
Custom user state 1.
|
|
0x2000
|
Custom user state 2.
|
|
0x4000
|
Custom user state 3.
|
|
0x8000
|
Custom user state 4.
|
|
0xFFFF
|
Special value to target all states in some
functions.
|
The following table describes the possible
parts of widgets in a graphical user interface (GUI) framework.
These parts are the internal building blocks of widgets, such as
sliders, buttons, and checkboxes. Each part serves a specific
function within the widget, contributing to its overall appearance
and behavior.
Part
|
Value (Hex)
|
Description
|
|
0x000000
|
A background-like rectangle.
|
|
0x010000
|
The scrollbar(s).
|
|
0x020000
|
Indicator, e.g., for slider, bar, switch, or
the tick box of the checkbox.
|
|
0x030000
|
Like handle to grab to adjust the value.
|
|
0x040000
|
Indicate the currently selected option or
section.
|
|
0x050000
|
Used if the widget has multiple similar
elements (e.g., table cells).
|
|
0x060000
|
Mark a specific place, e.g., for text area's
cursor or on a chart.
|
|
0x080000
|
Extension point for custom widgets.
|
|
0x0F0000
|
Special value to target all parts in some
functions.
|
The following table lists the on/off features
that control an object's behavior in a GUI framework. These flags
can be combined using bitwise OR operations to enable multiple
behaviors simultaneously. They determine how an object responds to
user interactions and how it is managed within the layout.
Flag
|
Value (Hex)
|
Description
|
|
0x000001
|
Make the object hidden.
|
|
0x000002
|
Make the object clickable by the input
devices.
|
LV_OBJ_FLAG_CLICK_FOCUSABLE
|
0x000004
|
Add focused state to the object when
clicked.
|
|
0x000008
|
Toggle checked state when the object is
clicked.
|
|
0x000010
|
Make the object scrollable.
|
LV_OBJ_FLAG_SCROLL_ELASTIC
|
0x000020
|
Allow scrolling inside but with slower
speed.
|
LV_OBJ_FLAG_SCROLL_MOMENTUM
|
0x000040
|
Make the object scroll further when
"thrown".
|
|
0x000080
|
Allow scrolling only one snappable
children.
|
LV_OBJ_FLAG_SCROLL_CHAIN_HOR
|
0x000100
|
Allow propagating the horizontal scroll to a
parent.
|
LV_OBJ_FLAG_SCROLL_CHAIN_VER
|
0x000200
|
Allow propagating the vertical scroll to a
parent.
|
|
0x000300
|
Combination of horizontal and vertical scroll
chain.
|
LV_OBJ_FLAG_SCROLL_ON_FOCUS
|
0x000400
|
Automatically scroll object to make it visible
when focused.
|
LV_OBJ_FLAG_SCROLL_WITH_ARROW
|
0x000800
|
Allow scrolling the focused object with arrow
keys.
|
|
0x001000
|
If scroll snap is enabled on the parent it can
snap to this object.
|
|
0x002000
|
Keep the object pressed even if the press slid
from the object.
|
|
0x004000
|
Propagate the events to the parent too.
|
LV_OBJ_FLAG_GESTURE_BUBBLE
|
0x008000
|
Propagate the gestures to the parent.
|
|
0x010000
|
Allow performing more accurate hit (click)
test.
|
LV_OBJ_FLAG_IGNORE_LAYOUT
|
0x020000
|
Make the object not positioned by the
layouts.
|
|
0x040000
|
Do not scroll the object when the parent
scrolls and ignore layout.
|
LV_OBJ_FLAG_SEND_DRAW_TASK_EVENTS
|
0x080000
|
Send
LV_EVENT_DRAW_TASK_ADDED events.
|
LV_OBJ_FLAG_OVERFLOW_VISIBLE
|
0x100000
|
Do not clip the children to the parent's ext
draw size.
|
LV_OBJ_FLAG_FLEX_IN_NEW_TRACK
|
0x200000
|
Start a new flex track on this item.
|
|
0x800000
|
Custom flag, free to use by layouts.
|
|
0x1000000
|
Custom flag, free to use by layouts.
|
|
0x2000000
|
Custom flag, free to use by widget.
|
|
0x4000000
|
Custom flag, free to use by widget.
|
|
0x8000000
|
Custom flag, free to use by user.
|
|
0x10000000
|
Custom flag, free to use by user.
|
|
0x20000000
|
Custom flag, free to use by user.
|
|
0x40000000
|
Custom flag, free to use by user.
|
The following table describes the possible
states of an image button in a graphical user interface (GUI)
framework. These states define the visual and interactive behavior
of the image button, such as whether it is pressed, released,
disabled, or checked. Each state can be used to customize the
appearance and functionality of the button in different
scenarios.
State
|
Value (Hex)
|
Description
|
LV_IMAGEBUTTON_STATE_RELEASED
|
0x00
|
The button is in its default, unpressed
state.
|
LV_IMAGEBUTTON_STATE_PRESSED
|
0x01
|
The button is currently being pressed by the
user.
|
LV_IMAGEBUTTON_STATE_DISABLED
|
0x02
|
The button is disabled and does not respond to
user interactions.
|
LV_IMAGEBUTTON_STATE_CHECKED_RELEASED
|
0x03
|
The button is checked (toggled on) and in its
default, unpressed state.
|
LV_IMAGEBUTTON_STATE_CHECKED_PRESSED
|
0x04
|
The button is checked and currently being
pressed by the user.
|
LV_IMAGEBUTTON_STATE_CHECKED_DISABLED
|
0x05
|
The button is checked but disabled, not
responding to interactions.
|
|
0x06
|
Represents the total number of states
available for the image button.
|
The following table describes the alignment
options available in the LVGL framework. These enums define how
objects can be aligned relative to each other or to their parent
containers. Each alignment option specifies a particular position
or orientation for an object within its layout.
Alignment Option
|
Value
|
Description
|
|
0
|
Default alignment
|
|
1
|
Align to the top-left corner
|
|
2
|
Align to the top-middle
|
|
3
|
Align to the top-right corner
|
|
4
|
Align to the bottom-left corner
|
|
5
|
Align to the bottom-middle
|
|
6
|
Align to the bottom-right corner
|
|
7
|
Align to the middle of the left side
|
|
8
|
Align to the middle of the right side
|
|
9
|
Align to the center
|
|
10
|
Align outside the top-left corner
|
|
11
|
Align outside the top-middle
|
|
12
|
Align outside the top-right corner
|
|
13
|
Align outside the bottom-left corner
|
|
14
|
Align outside the bottom-middle
|
LV_ALIGN_OUT_BOTTOM_RIGHT
|
15
|
Align outside the bottom-right corner
|
|
16
|
Align outside the top of the left side
|
|
17
|
Align outside the middle of the left side
|
|
18
|
Align outside the bottom of the left side
|
|
19
|
Align outside the top of the right side
|
|
20
|
Align outside the middle of the right side
|
LV_ALIGN_OUT_RIGHT_BOTTOM
|
21
|
Align outside the bottom of the right side
|
The following table describes the text
alignment options available in the LVGL framework. These enums
define how text is aligned within its container, allowing for
precise control over the text layout and appearance.
Text Alignment Option
|
Value
|
Description
|
|
0
|
Align text automatically
|
|
1
|
Align text to the left
|
|
2
|
Align text to the center
|
|
3
|
Align text to the right
|
The following table describes the direction
enums available in the LVGL framework. These enums define the
possible directions for scrolling or other directional operations
within a graphical user interface.
Enum
|
Value (Hex)
|
Description
|
|
0x00
|
No direction specified.
|
|
0x01
|
Direction is left.
|
|
0x02
|
Direction is right.
|
|
0x04
|
Direction is top.
|
|
0x08
|
Direction is bottom.
|
|
0x03
|
Horizontal direction (left or right).
|
|
0x0C
|
Vertical direction (top or bottom).
|
|
0x0F
|
All directions (horizontal and vertical).
|
The following table describes the border side
enums available in the LVGL framework.
These enums define which sides a border should be drawn on. Values
can be combined using bitwise OR.
Enum
|
Value (Hex)
|
Description
|
|
0x00
|
No border.
|
|
0x01
|
Border on the bottom side.
|
|
0x02
|
Border on the top side.
|
|
0x04
|
Border on the left side.
|
|
0x08
|
Border on the right side.
|
|
0x0F
|
Borders on all sides (top, bottom, left,
right).
|
|
0x10
|
Used for matrix-like objects (e.g., Button
matrix).
|
The following tables describe various flexbox
layout options and enumerations in a graphical user interface (GUI)
framework. These options and enumerations control the arrangement,
alignment, and behavior of elements within a flex container,
allowing for flexible and responsive layouts.
The following table describes the flexbox
layout options available in the LVGL framework. These options
define how flex items are arranged within a flex container,
providing control over the layout direction, wrapping behavior, and
alignment.
Option
|
Value (Hex)
|
Description
|
|
0x01
|
Arrange the flex items in a column, stacking
them vertically.
|
|
0x04
|
Allow the flex items to wrap onto multiple
lines if there isn't enough space.
|
|
0x08
|
Reverse the direction of the flex items within
the container.
|
The following table describes the flex
alignment options available in the LVGL framework. These options
define how flex items are aligned within their container, providing
control over the distribution and spacing of items.
Alignment
|
Value (Hex)
|
Description
|
|
0x00
|
Align items to the start of the container.
|
|
0x01
|
Align items to the end of the container.
|
|
0x02
|
Center items within the container.
|
LV_FLEX_ALIGN_SPACE_EVENLY
|
0x03
|
Distribute items evenly with equal space
around them.
|
LV_FLEX_ALIGN_SPACE_AROUND
|
0x04
|
Distribute items evenly with equal space
around the outer edges.
|
LV_FLEX_ALIGN_SPACE_BETWEEN
|
0x05
|
Distribute items evenly with space only
between them.
|
The following table describes the flex flow
options available in the LVGL framework. These options define the
direction in which flex items are arranged within a flex container,
including row and column layouts, as well as wrapping and reversing
behaviors.
Flow
|
Value (Hex)
|
Description
|
|
0x00
|
Arrange items in a row.
|
|
0x01
|
Arrange items in a column.
|
|
0x04
|
Arrange items in a row with wrapping.
|
|
0x08
|
Arrange items in a reversed row.
|
LV_FLEX_FLOW_ROW_WRAP_REVERSE
|
0x0C
|
Arrange items in a reversed row with
wrapping.
|
|
0x05
|
Arrange items in a column with wrapping.
|
LV_FLEX_FLOW_COLUMN_REVERSE
|
0x09
|
Arrange items in a reversed column.
|
LV_FLEX_FLOW_COLUMN_WRAP_REVERSE
|
0x0D
|
Arrange items in a reversed column with
wrapping.
|
The following table describes the mode options
available for Scale objects in LVGL.
Mode
|
Value (Hex)
|
Description
|
LV_SCALE_MODE_HORIZONTAL_TOP
|
0x00
|
The scale will be horizontal and the labels
text aligned to the top.
|
LV_SCALE_MODE_HORIZONTAL_BOTTOM
|
0x01
|
The scale will be horizontal and the labels
text aligned to the bottom.
|
LV_SCALE_MODE_VERTICAL_LEFT
|
0x02
|
The scale will be vertical and the labels text
aligned to the left.
|
LV_SCALE_MODE_VERTICAL_RIGHT
|
0x04
|
The scale will be vertical and the labels text
aligned to the right.
|
LV_SCALE_MODE_ROUND_INNER
|
0x08
|
The scale will be round and the labels text
aligned to the inner side.
|
LV_SCALE_MODE_ROUND_OUTER
|
0x10
|
The scale will be round and the labels text
aligned to the outer side.
|
The following table describes the long mode
options available for labels in the LVGL framework. These options
define how text that exceeds the label's width is handled,
providing various ways to manage and display long text content.
Mode
|
Value (Hex)
|
Description
|
|
0x00
|
Wrap lines longer than the object width and
expand the object height.
|
|
0x01
|
Write dots at the end if the text is too
long.
|
|
0x02
|
Roll the text back and forth.
|
LV_LABEL_LONG_SCROLL_CIRCULAR
|
0x03
|
Roll the text circularly.
|
|
0x04
|
Clip the text out of the object's size.
|
The following table describes the keyboard
mode enums available in the LVGL framework. These enums define the
different modes that a keyboard object can operate in, such as text
input, special characters, numeric input, and user-defined
modes.
Keyboard Mode
|
Value
|
Description
|
LV_KEYBOARD_MODE_TEXT_LOWER
|
0
|
Standard text input mode with lowercase
letters.
|
LV_KEYBOARD_MODE_TEXT_UPPER
|
1
|
Text input mode with uppercase letters.
|
|
2
|
Mode for inputting special characters.
|
|
3
|
Numeric input mode.
|
|
4
|
User-defined mode 1.
|
|
5
|
User-defined mode 2.
|
|
6
|
User-defined mode 3.
|
|
7
|
User-defined mode 4.
|
The following table describes the keyboard key
enums available in the LVGL framework. These enums represent
various keys that can be used to control a focused object via the
lv_group_send function. Each enum corresponds to a specific key,
such as arrow keys, escape, delete, and other functional keys,
allowing for navigation and interaction within the graphical user
interface.
Enum Value
|
Value
|
Description
|
|
17
|
Up arrow key
|
|
18
|
Down arrow key
|
|
19
|
Right arrow key
|
|
20
|
Left arrow key
|
|
27
|
Escape key
|
|
127
|
Delete key
|
|
8
|
Backspace key
|
|
10
|
Enter key
|
|
9
|
Next key (Tab)
|
|
11
|
Previous key
|
|
2
|
Home key
|
|
3
|
End key
|
The following table describes the event codes
available in the LVGL framework. These codes represent various
events that can occur within the graphical user interface, such as
clicks, presses, releases, and other interactions.
Event
|
Value (Hex)
|
Description
|
|
0x00
|
Represents all events.
|
|
0x01
|
The object has been pressed.
|
|
0x02
|
The object is being pressed continuously.
|
|
0x03
|
The object is still pressed but the
cursor/finger slid off.
|
|
0x04
|
The object was pressed for a short period and
released.
|
|
0x05
|
The object has been pressed for at least
long_press_time.
|
LV_EVENT_LONG_PRESSED_REPEAT
|
0x06
|
Called repeatedly after long_press_time.
|
|
0x07
|
Called on release if not scrolled.
|
|
0x08
|
Called when the object has been released.
|
|
0x09
|
Scrolling begins.
|
LV_EVENT_SCROLL_THROW_BEGIN
|
0x0A
|
Scroll throw begins.
|
|
0x0B
|
Scrolling ends.
|
|
0x0C
|
Scrolling is in progress.
|
|
0x0D
|
A gesture is detected.
|
|
0x0E
|
A key is sent to the object.
|
|
0x0F
|
An encoder or wheel was rotated.
|
|
0x10
|
The object is focused.
|
|
0x11
|
The object is defocused.
|
|
0x12
|
The object is defocused but still
selected.
|
|
0x13
|
Perform advanced hit-testing.
|
|
0x14
|
Input device has been reset.
|
|
0x15
|
Input device hover over object.
|
|
0x16
|
Input device hover leave object.
|
|
0x17
|
Check if the object fully covers an area.
|
LV_EVENT_REFR_EXT_DRAW_SIZE
|
0x18
|
Get the required extra draw area around the
object.
|
|
0x19
|
Starting the main drawing phase.
|
|
0x1A
|
Perform the main drawing.
|
|
0x1B
|
Finishing the main drawing phase.
|
|
0x1C
|
Starting the post draw phase.
|
|
0x1D
|
Perform the post draw phase.
|
|
0x1E
|
Finishing the post draw phase.
|
|
0x1F
|
Adding a draw task.
|
|
0x20
|
The object's value has changed.
|
|
0x21
|
A text is inserted to the object.
|
|
0x22
|
Notify the object to refresh something.
|
|
0x23
|
A process has finished.
|
|
0x24
|
A process has been cancelled.
|
|
0x25
|
Object is being created.
|
|
0x26
|
Object is being deleted.
|
|
0x27
|
Child was removed, added, or its size/position
changed.
|
|
0x28
|
Child was created.
|
|
0x29
|
Child was deleted.
|
LV_EVENT_SCREEN_UNLOAD_START
|
0x2A
|
A screen unload started.
|
LV_EVENT_SCREEN_LOAD_START
|
0x2B
|
A screen load started.
|
|
0x2C
|
A screen was loaded.
|
|
0x2D
|
A screen was unloaded.
|
|
0x2E
|
Object coordinates/size have changed.
|
|
0x2F
|
Object's style has changed.
|
|
0x30
|
The children position has changed due to a
layout recalculation.
|
|
0x31
|
Get the internal size of a widget.
|
|
0x32
|
Invalidate an area.
|
LV_EVENT_RESOLUTION_CHANGED
|
0x33
|
Resolution has changed.
|
LV_EVENT_COLOR_FORMAT_CHANGED
|
0x34
|
Color format has changed.
|
|
0x35
|
Refresh request.
|
|
0x36
|
Refresh start.
|
|
0x37
|
Refresh ready.
|
|
0x38
|
Render start.
|
|
0x39
|
Render ready.
|
|
0x3A
|
Flush start.
|
|
0x3B
|
Flush finish.
|
LV_EVENT_FLUSH_WAIT_START
|
0x3C
|
Flush wait start.
|
LV_EVENT_FLUSH_WAIT_FINISH
|
0x3D
|
Flush wait finish.
|
|
0x3E
|
Vertical sync event.
|
|
0x3F
|
Number of default events.
|
|
0x8000
|
Process event before the class default event
processing.
|
This table lists LVGL's built-in symbols
derived from FontAwesome icons, represented as UTF-8 encoded
strings for consistent UI elements:
Symbol
|
Unicode Sequence
|
Icon
|
|
"\xEF\x80\x81"
|

|
|
"\xEF\x80\x88"
|

|
|
"\xEF\x80\x8B"
|

|
|
"\xEF\x80\x8C"
|

|
|
"\xEF\x80\x8D"
|

|
|
"\xEF\x80\x91"
|

|
|
"\xEF\x80\x93"
|

|
|
"\xEF\x80\x95"
|

|
|
"\xEF\x80\x99"
|

|
|
"\xEF\x80\x9C"
|

|
|
"\xEF\x80\xA1"
|

|
|
"\xEF\x80\xA6"
|

|
|
"\xEF\x80\xA7"
|

|
|
"\xEF\x80\xA8"
|

|
|
"\xEF\x80\xBE"
|

|
|
"\xEF\x81\x83"
|

|
|
"\xEF\x81\x88"
|

|
|
"\xEF\x81\x8B"
|

|
|
"\xEF\x81\x8C"
|

|
|
"\xEF\x81\x8D"
|

|
|
"\xEF\x81\x91"
|

|
|
"\xEF\x81\x92"
|

|
|
"\xEF\x81\x93"
|

|
|
"\xEF\x81\x94"
|

|
|
"\xEF\x81\xA7"
|

|
|
"\xEF\x81\xA8"
|

|
|
"\xEF\x81\xAE"
|

|
|
"\xEF\x81\xB0"
|

|
|
"\xEF\x81\xB1"
|

|
|
"\xEF\x81\xB4"
|

|
|
"\xEF\x81\xB7"
|

|
|
"\xEF\x81\xB8"
|

|
|
"\xEF\x81\xB9"
|

|
|
"\xEF\x81\xBB"
|

|
|
"\xEF\x82\x93"
|

|
|
"\xEF\x82\x95"
|

|
|
"\xEF\x83\x84"
|

|
|
"\xEF\x83\x85"
|

|
|
"\xEF\x83\x87"
|

|
|
"\xEF\x83\x89"
|

|
|
"\xEF\x83\xA0"
|

|
|
"\xEF\x83\xA7"
|

|
|
"\xEF\x83\xAA"
|

|
|
"\xEF\x83\xB3"
|

|
|
"\xEF\x84\x9C"
|

|
|
"\xEF\x84\xA4"
|

|
|
"\xEF\x85\x9B"
|

|
|
"\xEF\x87\xAB"
|

|
|
"\xEF\x89\x80"
|

|
|
"\xEF\x89\x81"
|

|
|
"\xEF\x89\x82"
|

|
|
"\xEF\x89\x83"
|

|
|
"\xEF\x89\x84"
|

|
|
"\xEF\x8A\x87"
|

|
|
"\xEF\x8A\x93"
|

|
|
"\xEF\x8B\xAD"
|

|
|
"\xEF\x8C\x84"
|

|
|
"\xEF\x95\x9A"
|

|
|
"\xEF\x9F\x82"
|

|
|
"\xEF\xA2\xA2"
|

|
|
"\xEF\xA3\xBF"
|
|
It is possible to connect USB devices, the
ESP32-S3 acting as an HOST controller.
The USB device must be connected using the
default USB pins (GPIO19 D- , GPIO20 D+).
Only one device can be connected on the port
(the USB hubs don’t work) but is possible to use combined devices
such as mixed mouse / keyboard remote controller using a wireless
dongle, such as the devices shown below::



It is possible to connect directly the USB
device to the module, using an USB type C adapter and shorting the
jumpers IN-OUT and USB-OTG on the ESP32-S3 modules
like shown in the images below:


The primary command for using USB devices is
USB.SETUP WIDTH,
HEIGHT
This command defines the screen size,
establishing the position limits for the mouse.
For instance, to set up for a VGA display with
a resolution of 640x480, the command would be:
USB.SETUP
640,
480
This setup enables
the use of various USB input devices such as a mouse, keyboard, or
gamepad.
When a mouse is
connected, the system automatically generates and activates the
following variables:
●
mouseX: Current
X-coordinate of the mouse cursor.
●
mouseY: Current
Y-coordinate of the mouse cursor.
●
mouseZ:
Represents mouse buttons.
●
mouseW:
Represents the mouse wheel.
For a connected
keyboard, the following variable is automatically generated and
active:
●
Kbdcode:
Contains the code of the last key pressed.
Gamepad
Input
When a gamepad is
connected, the system generates and activates the following array
of variables:
●
gamepadcodes(8):
An array of 8 elements containing the codes of the gamepad.
There are four
events associated with these USB devices:
1.
onMouseMove
: Triggered when the mouse moves.
Inside these events, it is possible to access
the content of the variables when changes occur.
The example below demonstrates all the events
available:
USB.Setup
640,
480
onMouseMove
Mouse_Move
onMouseClick
Mouse_Click
onKeyboard
Keyboard_Press
onGamePad
Gamepad_Change
wait
Mouse_Move:
print
"mouse move", mouseX, mouseY, mouseZ
return
Mouse_Click:
print
"mouse click", mouseX, mouseY, mouseZ
return
Keyboard_Press:
print
"keyboard", kbdcode
return
Gamepad_Change:
print
"Gamepad",
gamepadcodes(1),
gamepadcodes(2), gamepadcodes(3), gamepadcodes(4), gamepadcodes(5),
gamepadcodes(6)
return
|
Annex implements support for commands to emulate a USB mouse or
keyboard using an ESP32-S3.
This functionality allows controlling a PC by simulating a user
interacting with the mouse and keyboard, either through scripts
written in Annex or via WiFi.
The USB device must be connected using the default USB pins (GPIO19
D-, GPIO20 D+), which are generally accessible through the USB
connector labeled 'USB'—not the 'COM' connector, as that is
typically linked to a USB-to-serial converter chip.
●
Description: Initializes the USB system and keyboard
emulation. Optionally sets a custom key mapping.
●
Arguments:
●
keymap$: A string containing hex values for custom key
mappings.
If omitted, the default EN_US keyboard mapping is used.
●
This command must be executed before using other commands.
It can be reused to change keyboard mappings.
●
By running this command, you should hear the classic sound in
Windows when USB devices are recognized. This sound indicates that
the system has successfully detected the connected devices.
●
Description: Simulates typing a string of text.
●
Arguments:
●
text$: The string to be typed.
●
Note:
●
If the text “typed” is not correct, this likely means that you need
to set up the keymap for your specific keyboard language. In this
case, run the command USB.START with the keymap corresponding to
your local keyboard layout.
●
Description: Simulates pressing and holding a specific
key.
●
Arguments:
●
keycode: The numerical value representing the key code.
●
Note:
●
Take care that you can easily lose control of the PC with this
command as the key will remain pressed until the command
USB.KEYRELEASE is executed. This can result in your
screen being filled with repeated characters from the key that is
pressed.
●
Description: Simulates releasing a specific key.
●
Arguments:
●
keycode: The numerical value representing the key code.
●
Description: Simulates releasing all currently pressed
keys.
●
Arguments: None.
●
Description: Simulates moving the mouse cursor by specified
distances with optional scrolling and panning.
●
Arguments:
●
width: Horizontal movement (-127 to 127).
●
height: Vertical movement (-127 to 127).
●
wheel (optional): Wheel movement (scrolling). Defaults to zero if
not provided.
●
pan (optional): Panning movement. Defaults to zero if not
provided.
●
Description: Simulates clicking a mouse button.
●
Arguments:
●
button: The numerical value representing the mouse button.
●
Description: Simulates pressing and holding a mouse
button.
●
Arguments:
●
button: The numerical value representing the mouse button.
●
Description: Simulates releasing a mouse button.
●
Arguments:
●
button: The numerical value representing the mouse button.
Example of Mouse / Keyboard actions:
pause
1000
px
= 200 : py =
0
for z
= 0 to
2*pi+0.001 step pi/360
x
= cos(z)
* 200
y
= sin(z)
* 200
USB.MOUSEMOVE x-px, y-py
px
= x : py = y
pause 1
next z
for z
= 1 to
16
USB.TYPETEXT chr$(&hB3)
' TAB
pause 100
next z
pause
500
USB.TYPETEXT
chr$(&hB0) '
ENTER
USB.TYPETEXT
"This is a Text typed directly by Annex into another TAB "
+ str$(rnd())
|
By default, the
keyboard is set to EN-US. It can be changed by specifying the
keymap in the
USB.START function.
For example, to set the keyboard to
Italian
IT_IT$
=
"00000000000000002A2B280000000000000000000000000000000000000000002C9E9F74A1A2A32DA5A6B030363837A4271E1F20212223242526B7B632A7B2AD738485868788898A8B8C8D8E8F909192939495969798999A9B9C9D6F3570AEB8000405060708090A0B0C0D0E0F101112131415161718191A1B1C1D00B5000000"
USB.START IT_IT$
|
Button
|
Description
|
Value
|
MOUSE_LEFT
|
Left mouse button
|
1
|
MOUSE_RIGHT
|
Right mouse button
|
2
|
MOUSE_MIDDLE
|
Middle mouse button (scroll wheel)
|
4
|
MOUSE_BACKWARD
|
Backward navigation button
|
8
|
MOUSE_FORWARD
|
Forward navigation button
|
16
|
MOUSE_ALL
|
All mouse buttons pressed simultaneously
|
31
|
Key
|
Description
|
Value
|
KEY_LEFT_CTRL
|
Left control key
|
&h80
|
KEY_LEFT_SHIFT
|
Left shift key
|
&h81
|
KEY_LEFT_ALT
|
Left alt key
|
&h82
|
KEY_LEFT_GUI
|
Left GUI key (Windows/Command)
|
&h83
|
KEY_RIGHT_CTRL
|
Right control key
|
&h84
|
KEY_RIGHT_SHIFT
|
Right shift key
|
&h85
|
KEY_RIGHT_ALT
|
Right alt key
|
&h86
|
KEY_RIGHT_GUI
|
Right GUI key (Windows/Command)
|
&h87
|
KEY_UP_ARROW
|
Up
arrow key
|
&hDA
|
KEY_DOWN_ARROW
|
Down arrow key
|
&hD9
|
KEY_LEFT_ARROW
|
Left arrow key
|
&hD8
|
KEY_RIGHT_ARROW
|
Right arrow key
|
&hD7
|
KEY_BACKSPACE
|
Backspace key
|
&hB2
|
KEY_TAB
|
Tab key
|
&hB3
|
KEY_RETURN
|
Return key
|
&hB0
|
KEY_ESC
|
Escape key
|
&hB1
|
KEY_INSERT
|
Insert key
|
&hD1
|
KEY_DELETE
|
Delete key
|
&hD4
|
KEY_PAGE_UP
|
Page up key
|
&hD3
|
KEY_PAGE_DOWN
|
Page down key
|
&hD6
|
KEY_HOME
|
Home key
|
&hD2
|
KEY_END
|
End key
|
&hD5
|
KEY_CAPS_LOCK
|
Caps lock key
|
&hC1
|
KEY_F1
|
F1
key
|
&hC2
|
KEY_F2
|
F2
key
|
&hC3
|
KEY_F3
|
F3
key
|
&hC4
|
KEY_F4
|
F4
key
|
&hC5
|
KEY_F5
|
F5
key
|
&hC6
|
KEY_F6
|
F6
key
|
&hC7
|
KEY_F7
|
F7
key
|
&hC8
|
KEY_F8
|
F8
key
|
&hC9
|
KEY_F9
|
F9
key
|
&hCA
|
KEY_F10
|
F10 key
|
&hCB
|
KEY_F11
|
F11 key
|
&hCC
|
KEY_F12
|
F12 key
|
&hCD
|
EN_US$ =
"00000000000000002A2B280000000000000000000000000000000000000000002C9EB4A0A1A2A434A6A7A5AE362D3738271E1F20212223242526B333B62EB7B89F8485868788898A8B8C8D8E8F909192939495969798999A9B9C9D2F3130A3AD350405060708090A0B0C0D0E0F101112131415161718191A1B1C1DAFB1B0B500"
|
FR_FR$ =
"00000000000000002A2B280000000000000000000000000000000000000000002C38206030B41E21222D31AE1023B6B7A79E9FA0A1A2A3A4A5A63736322EB290679485868788898A8B8C8D8E8FB39192938495969798999D9B9C9A62656D6625641405060708090A0B0C0D0E0F331112130415161718191D1B1C1A61636E5F00"
|
IT_IT$ =
"00000000000000002A2B280000000000000000000000000000000000000000002C9E9F74A1A2A32DA5A6B030363837A4271E1F20212223242526B7B632A7B2AD738485868788898A8B8C8D8E8F909192939495969798999A9B9C9D6F3570AEB8000405060708090A0B0C0D0E0F101112131415161718191A1B1C1D00B5000000"
|
DE_DE$ =
"00000000000000002A2B280000000000000000000000000000000000000000002C9E9F31A1A2A3B1A5A6B030363837A4271E1F20212223242526B7B632A7B2AD548485868788898A8B8C8D8E8F909192939495969798999A9B9D9C656D6600B8000405060708090A0B0C0D0E0F101112131415161718191A1B1D1C6472677000"
|
ES_ES$ =
"00000000000000002A2B280000000000000000000000000000000000000000002C9E9F74A1A2A32DA5A6B030363837A4271E1F20212223242526B7B632A7B2AD738485868788898A8B8C8D8E8F909192939495969798999A9B9C9D6F3570AEB8000405060708090A0B0C0D0E0F101112131415161718191A1B1C1D00B5000000"
|
PT_BR$ =
"00000000000000002A2B280000000000000000000000000000000000000000002C9E9F20A1A2A3B1A5A6B030363837A4271E1F20212223242526B7B632A7B2AD548485868788898A8B8C8D8E8F909192939495969798999A9B9D9C656D6600B8000405060708090A0B0C0D0E0F101112131415161718191A1B1D1C6472677000"
|
PT_PT$ =
"00000000000000002A2B280000000000000000000000000000000000000000002C9E9FA0A1A2A32DA5A6AF2F363837A4271E1F20212223242526B7B632A7B2AD5F8485868788898A8B8C8D8E8F909192939495969798999A9B9C9D65356600B8000405060708090A0B0C0D0E0F101112131415161718191A1B1C1D64B5670000"
|
SV_SE$ =
"00000000000000002A2B280000000000000000000000000000000000000000002C9E9FA061A2A331A5A6B12D363837A4271E1F20212223242526B7B632A7B2AD5F8485868788898A8B8C8D8E8F909192939495969798999A9B9C9D656D6600B8000405060708090A0B0C0D0E0F101112131415161718191A1B1C1D6472670000"
|
DA_DK$ =
"00000000000000002A2B280000000000000000000000000000000000000000002C9E9FA061A2A331A5A6B12D363837A4271E1F20212223242526B7B632A7B2AD5F8485868788898A8B8C8D8E8F909192939495969798999A9B9C9D65726600B8000405060708090A0B0C0D0E0F101112131415161718191A1B1C1D646E670000"
|
HU_HU$ =
"00000000000000002A2B280000000000000000000000000000000000000000002CA19F5B73A2469EA5A678A0363837A3351E1F20212223242526B77672A45DB6598485868788898A8B8C8D8E8F909192939495969798999A9B9D9C49544A60B8640405060708090A0B0C0D0E0F101112131415161718191A1B1D1C455A515E00"
|
INFRARED INTERFACE
An infrared receiver can be connected to the
module permitting to decode messages received from RC remote
controllers.
It is also possible to connect an IR led
permitting to generate RC codes from the module.
This picture shows a kit containing an IR
receiver, an IR LED and a controller available on ebay at around
1€.

The following drawing shows an example of
connection using the pins GPIO12 and GPIO13:


Details of wiring for the VS1838B
There are several commands associated with the
IR functions :
IR.INIT,
IR.GET$,
IR.SEND and
ONINFRARED.
In order to use the Infrared functions, the
first command to use is IR.INIT.
This command defines the pins to be used for
the IR receiver and the IR transmitter.
As per the wiring given above, the command
must be:
IR.INIT 13,
12
The command
ONINFRARED defines the label where the program will jump
when a code is received by the Infrared receiver. Then, using the
function
IR.GET$ it will be possible to retrieve the code of the
message received:
Example
IR.INIT
13,
12
ONINFRARED
irReceived
Wait
irReceived:
PRINT
IR.GET$
RETURN
|
The transmission can be done using the command
IR.SEND:
The format is
IR.SEND format,
code$, bits
Example for a NEC code:
IR.SEND 3,
"20DF40BF", 32
The following formats are supported for the
reception and the transmission :
VALUE
|
FORMAT
|
-1
|
UNKNOWN
|
0
|
UNUSED
|
1
|
RC5
|
2
|
RC6
|
3
|
NEC
|
4
|
SONY
|
5
|
PANASONIC
|
6
|
JVC
|
7
|
SAMSUNG
|
This is an example working with the RC
controller shown in the picture above.
It shows the status of the button 1 to 8
pressed on the web page and can control 8 leds wired to a PCF8574
using the I2C bus :
oninfrared
irReceived
onHtmlReload
mypage
l1
= 0: l2 = 0: l3=0:
l4=0: l5=0: l6=0:
l7=0: l8=0
ir.init
13
i2c.setup
21,
22
l
= 0
PCF8574_write
l
gosub
mypage
wait
irReceived:
print
ir.get$, ir.get$(1),
ir.get$(2),
val("&h"
+ ir.get$(3)),
ir.get$(4),
ir.get$(5)
code_type
= val(ir.get$(1))
address
= val(ir.get$(2))
cmd
= val("&h"
+ ir.get$(3))
' if NEC
CODE
if
code_type
= 3 then
' if RC address is
0
if address = 0 then
if cmd = 22 then l
= l xor 1
if cmd = 25 then l
= l xor 2
if cmd = 13 then l
= l xor 4
if cmd = 12 then l
= l xor 8
if cmd = 24 then l
= l xor 16
if cmd = 94 then l
= l xor 32
if cmd = 8 then l = l
xor 64
if cmd = 28 then l
= l xor 128
PCF8574_write l
setleds l
end if
end
if
return
mypage:
cls
a$
= ""
a$
= a$ + |<h1> TEST
OF IR REMOTE CONTROLLER COUPLED<br>|
a$
= a$ + | WITH AN I2C
PCF8574 AND 8 LEDS</h1>|
a$
= a$ + led$(l1)
+ led$(l2)
+ led$(l3)
+ led$(l4)
+ led$(l5)
+ led$(l6)
+ led$(l7)
+ led$(l8)
html
a$
return
sub
setleds(x)
' set the status for the
leds
l1
= (x and
1)
l2
= (x and
2)
l3
= (x and
4)
l4
= (x and
8)
l5
= (x and
16)
l6
= (x and
32)
l7
= (x and
64)
l8
= (x and
128)
refresh
end
sub
sub
PCF8574_write(x)
i2c.begin 32 'PCF8574
i2c.write x
i2c.end
end
sub
|
An Ultrasonic distance sensor HC-SR04 can be
connected to the module.
This sensor permits to measure the distance
from a target positioned in front in a range going from a minimum
of 3 cm to a maximum of 3 meters.

For the connection, it requires 2 pins plus
the power supply. (5 Volts).

The only function is
DISTANCE(pin_trig,
pin_echo) which returns the distance from the target in
cm.
Example:
' Measure
the distance from the target 2 times / second
print
"DISTANCE MEASUREMENT"
for
i
= 0 to 1000
print str$(DISTANCE(15,12),
"%4f") +
"cm"
pause 500
next
i
end
|
A Temperature / Humidity sensor of the DHTxx
family can be connected.
The picture below shows the ones that are
currently supported.

These sensors requires a single wire
connection like shown below:

To use them is very simple.
First initialise the sensor with the command
DHT.SETUP pin,
model
The pin can be any available pin of the
device, and model can be 11, 21 or 22 (for DHT11, DHT21 or
DHT22).
Assuming that we are using the DHT22 on the
pin GPIO2, the command must be :
DHT.SETUP 2,
22
Then 3 functions are available :
DHT.TEMP
DHT.HUM
DHT.HEATINDEX
The first returns the value of the temperature
in °C
The 2nd returns the value of the Humidity in
%
The 3rd returns the value of the heat index in
°C
.
Example
DHT.SETUP
2
,22
Print
"The Temperature is "; DHT.TEMP ; "°C"
Print
"The Humidity is "; DHT.HUM ; "%"
Print
"The Heat Index is "; DHT.HEATINDEX ; "°C"
|
One or several DS18B20 Temperature
sensors can be connected.
The picture below shows the ones that are
currently supported.

These Dallas 1-wire sensors use a single wire
connection as shown below, allowing multiple sensors to be
connected in parallel on the same 1-wire bus from a single gpio
pin.

There is just one function available :
TEMPR$(pin_number,
[ID], [resolution])
This function will return the temperature or
the ID of the device depending on the parameter ‘ID’ specified.
In the schematic above, to read the 3
temperatures, the example code is :
Print
"The Temperature 1 is ";TEMPR$(2,
1) ; "°C"
Print
"The Temperature 2 is ";TEMPR$(2,
2) ; "°C"
Print
"The Temperature 3 is ";TEMPR$(2,
3) ; "°C"
|
The ‘pin number’ is
any available pin of the device; it can change between calls
permitting to use several pins at the same time.
The ID can be a
number, a String, or not specified:
- If is a number
(say 'n'), the result will be the temperature (in °C) of the nth
device connected on that pin
- If is a string,
it must contains the Hex address of the device requested; this
address can be recovered using the command without this
argument
- If not specified,
the result will be the address list of the devices connected on the
pin (blocks of 8 bytes separated by ',')
Example using 2
DS18B20 connected on the pin 12 :
Print
TEMPR$(12, 1) ' will print
20.5
Print
TEMPR$(12, 2) ' will print
22.3
Print
TEMPR$(12) ' will print
28ff5bdb701604f0,28ff5bdb7016045
Print
TEMPR$("28ff5bdb701604f0") ' will print
20.5
|
Additionally, the
parameter ‘resolution’ can be provided (from 9 to 12 bits).
The resolution
determine the minimal increment of temperature and also the
conversion time (see table below)
BITS
|
Resolution
°C
|
Conversion
Time (msec)
|
9
|
0.5
|
94
|
10
|
0.25
|
188
|
11
|
0.125
|
375
|
12
|
0.0625
|
750
|
If the resolution
is not specified, it defaults to 12 as before.
The sensors
can also be read in async mode:
Giving 0 as ID,
starts the conversion on all the DS18B20 sensors connected without
waiting for the answer
For example
ret$
=
TEMPR$(2,
0)
' starts an
async read on the pin 2
The result will be
the string "START"
Then, it will be
possible to read the devices as below
ret1$
=
TEMPR$(2,
1)
'read the 1st
sensor on the pin 2
ret2$
=
TEMPR$(2,
2)
'read the 2nd
sensor on the pin 2
In this case, if
the value is not yet available (during the conversion time) the
result will be "WAIT' that will be replaced by the good value at
the end of the conversion.
To restart another
conversion, the same command must be executed
ret$
=
TEMPR$(2,
0)
' starts an
async read on the pin 2
A BNO055 Absolute Orientation Sensor can be
connected to the module using I2C interface.
This sensor contains 3 accelerometers, 3 gyros
and 3 magnetometers BUT also contains an integrated 32 bits
controller running Bosch Sensortec sensor fusion software.
This permits unloading the module from all the
calculations related to the implementation of a Fusion
algorithm.

This component is quite expensive ( ~10 €)
compared to the classic MPU6050, MPU9250, ... but the quality of
the internal fusion algo permits to use it without any effort.
Before connecting it, the links S0 and S1 must
be soldered with the ‘-’ position as shown in the picture, to
enable I2C.
The connection is very simple, just 2 pins for
the I2C bus and the power supply are required.
The module is already provided with on-board
pull-up resistors, so external pull-up resistors are not
required.

Available instructions are :
BNO055.SETUP(address)
BNO055.HEADING
BNO055.PITCH
BNO055.ROLL
BNO055.VECTOR ( param )
BNO055.CALIB [(param)]
The use of the BNO055 module is very
simple.
First the I2C must be initialised with the
command
I2C.SETUP.
Then the module must be initialised with the
function
BNO055.SETUP(address).
‘address’ must be &h28 if the pin ‘I2C’ is
connected to GND or &h29 if connected to VCC.
This function returns 1 if the module has been
initialised properly otherwise it returns 0.
After the initialisation, the euler angles can
be simply read using the corresponding functions
BNO055.HEADING,
BNO055.PITCH and
BNO055.ROLL
Another useful function is
BNO055.CALIB
[(param)]
which returns the calibration status of the BNO055 internal
sensors.
If used without any parameters it returns 1
when all the internal sensors are calibrated, otherwise it returns
0.
The BNO055 is put in auto calibration mode so
it will calibrate by itself in the background.
Refer to the following link for more
information :
BNO055 Calibration
Example
I2C.SETUP 21, 22
' set I2C port on pins 21 and 22
if bno055.setup(&h28) = 0
then
print "BNO module not found"
end
end if
for z = 1 to
1000
print "Pitch:", bno055.pitch
print "Roll:", bno055.roll
print
"Heading:", bno055.heading
print
"Calibrated:", bno055.calib
pause 100
next z
end
|
A BME280 Sensor can be connected to the module
using the I2C interface.
The BME280 combines individual high linearity,
high accuracy sensors for pressure, humidity and temperature.
The cheaper BMP280 could be used instead, but
it doesn’t contain a humidity sensor.


The connection is very simple, just 2 pins for
the I2C bus and the power supply are required.
The module is already provided with on-board
pull-up resistors, so external pull-up resistors are not
required.

Available instructions are :
BME280.SETUP(address)
BME280.ALT(qnh)
BME280.HUM
BME280.QFE
BME280.QNH(altitude)
BME280.TEMP
The use of the BME280 module is very
simple.
First the I2C must be initialised with the
command
I2C.SETUP.
Then the module must be initialised with the
function
BME280.SETUP(address).
‘address’ must be &h76 if the pin ‘SDO’ is
connected to GND or &h77 if connected to VCC.
This function returns 1 if the module has been
initialised properly, otherwise it returns 0.
After the initialisation, the temperature,
pressure and humidity can be simply read using the corresponding
functions
BME280.TEMP,
BME280.QFE and
BME280.HUM.
The function
BME280.ALT(qnh)
returns the altitude information but requires, as a parameter, the
pressure at sea level.
At the opposite, the function
BME280.QNH(altitude)
returns the sea level pressure but requires, as a parameter, the
current altitude.
Example
I2C.SETUP 21,
22 ' set I2C
port on pins 21 and 22
if bme280.setup(&h76)
= 0 then print
"BME280 not found" :
end
for z = 1 to
1000
print "Temperature", bme280.temp
print "Humidity", bme280.hum
print "Pressure", bme280.qfe
qnh = bme280.qnh(150)
' assume the altitude at 150
meters
print "Qnh ", qnh
print "Altitude", bme280.alt(1019)
' assume a sea level pressure at 1019
Hpa
pause 100
next z
|
The BME680 is an integrated environmental
sensor that combines gas, humidity, pressure, and temperature
measurements. This sensor can be connected to the module using the
I2C interface and now utilises the BSEC (Bosch Sensortec
Environmental Cluster) library for advanced features and improved
accuracy.

The connection is very simple, just 2 pins for
the I2C bus and the power supply are required.
The module is already provided with on-board
pull-up resistors, so external pull-up resistors are not
required.

The use of the BME680
module with the BSEC library is straightforward:
-
Initialise the I2C bus using the I2C.SETUP command.
-
Initialise the BME680 sensor with BME680.BEGIN(address):
●
Use &h76 if SDO is connected to GND
●
Use &h77 if SDO is connected to VCC or left floating
●
This function returns 0 if successful, otherwise it returns an
error code
- Configure the sensor
using BME680.SETUP(rate, filename):
●
Set the sampling rate and optionally load a BSEC configuration
file
- After initialization,
you can read various parameters:
●
Temperature: BME680.TEMP
●
Pressure: BME680.PRESS
●
Humidity: BME680.HUM
●
Gas resistance: BME680.GAS_RES
●
Indoor Air Quality (IAQ): BME680.IAQ
●
CO2 equivalent: BME680.CO2
●
Breath VOC equivalent: BME680.BREATH_VOC
- Use BME680.RUN() to
update the sensor readings. It returns 1 if new data is
available.
Additional functions
like BME680.SAVE_STATE() and BME680.LOAD_STATE() are available for
managing the sensor's state, and BME680.SET_OFFSET() for
temperature calibration.
BSEC Configuration Files
These are files that contain pre-configured settings for the BSEC
algorithm, optimised for different use cases. They are typically
provided by Bosch Sensortec as text files containing CSV data.
Common configurations include:
●
Generic_18v_3s_4d
●
Generic_18v_300s_4d
●
Generic_18v_300s_28d
●
Generic_33v_3s_4d
●
Generic_33v_300s_4d
●
Generic_33v_300s_28d
The naming convention typically indicates:
●
Voltage (1.8V or 3.3V)
●
Sampling period (3s or 300s)
●
Run-in time (4 days or 28 days)
These configuration files are usually
distributed with the BSEC library and can be downloaded from Bosch
Sensortec's official resources.
https://github.com/boschsensortec/BSEC-Arduino-library/tree/master/src/config
|
DESCRIPTION
|
|
Initialise the sensor
connected using I2C. 'address' must be &h76 if the pin 'SDO' is
connected to GND or &h77 if connected to VCC. Returns 0 if the
BME680 sensor has been found, otherwise returns an error code
|
|
Configure the sensor and
load BSEC configuration if provided. 'rate' is the sampling rate in
seconds, 'filename' is the path to a CSV file containing a BSEC
configuration.
Typical rates are
0.0033333 for ULP
0.3333333 for LP
(recommended)
1 for CONTINUOUS
|
|
Save the current BSEC
state to a file. 'filename' is the path to save the state CSV
file
|
|
Load a previously saved
BSEC state from a file. 'filename' is the path to the state CSV
file to load
|
|
Sets the temperature offset for more accurate
readings. 'offset' is the temperature offset in °C
|
|
Run the BSEC algorithm to
update sensor readings. Returns 1 if new data is available, 0
otherwise
|
|
Returns the Temperature
parameter from the sensor in °C
|
|
Returns the raw
temperature reading
|
|
Returns the Humidity
parameter from the sensor in %
|
|
Returns the raw humidity
reading
|
|
Returns the Barometric
Pressure parameter from the sensor in hPa
|
|
Returns the Indoor Air
Quality index
|
|
Returns the static Indoor
Air Quality index
|
|
Returns the IAQ accuracy
(0-3)
|
|
Returns the CO2 equivalent
estimate in ppm
|
|
Returns the breath VOC
equivalent estimate in ppm
|
|
Returns the gas
percentage
|
|
Returns the gas resistance
in Ohms
|
|
Returns the BME680 sensor
status
|
|
Returns the BSEC library
status
|
|
Returns the sensor
stabilisation status
|
|
Returns the sensor run-in
status
|
Example
I2C.SETUP
21, 22
' set I2C port on pins 21 and
22
if
BME680.Begin(&h77)
<> 0 then print
"BME680 not found" :
end
r = BME680.Setup(0.333333, "/config/generic_33v_3s_4d/bsec_iaq.txt")
r = BME680.Set_Offset(4) '
4°C of offset for the Temperature
r = BME680.Load_State("/bsec_state.csv") ' load
the saved state
z = 1
while
1
if BME680.RUN =
1 then
print "Temperature", BME680.TEMP
print "Humidity", BME680.HUM
print "Pressure", BME680.PRESS
print "IAQ", BME680.IAQ
print "CO2 Equivalent", BME680.CO2
print "Breath VOC", BME680.BREATH_VOC
print "Gas Resistance", BME680.GAS_RES
' Save state every 100
iterations
if z mod 100 = 0
then
ret = BME680.SAVE_STATE("/bsec_state.csv")
endif
z
= z +
1
endif
pause 1000
wend
|
The HDC1080 is a digital humidity sensor with
integrated temperature sensor that provides excellent measurement
accuracy at very low power. The HDC1080 operates over a wide supply
range, and is a low cost, low power alternative to competitive
solutions in a wide range of common applications. The humidity and
temperature sensors are factory calibrated.
The device can be connected to the ESP32 using the I2C
interface.

The following functions are available :
HDC1080.SETUP(address)
'the
address is always &h40
Start
the device using the given I2C address.
Returns 0 if OK or 1 in case of error
HDC1080.TEMP
Returns the temperature in °C
HDC1080.HUM
Returns the humidity in %
HDC1080.HEATUP(time)
Heat up the sensor for ‘time’ seconds
The heater helps in reducing the accumulated
offset after long exposure at high humidity conditions.
Example
'HDC1080
simple demo
i2c.setup 21, 22
if
hdc1080.Setup(&h40)
= 1 then print
"HDC1080 not found" :
end
While 1
print
"Temperature "; hdc1080.temp, "Humidity "; hdc1080.hum
pause 1000
wend
|
The CCS811 is an ultra-low power digital gas sensor solution which
integrates a metal oxide (MOX) gas sensor to detect a wide range of
Volatile Organic Compounds (VOCs) for indoor air quality monitoring
with a microcontroller unit (MCU), which includes an
Analog-to-Digital converter (ADC), and an I²C interface.
Annex32 includes the support for this device using the full
implementation of the Sparkfun Library.
The device can be connected to the ESP32 using the I2C
interface.
Generic CCS811 module
|
Module that combines a CCS811 with an HDC1080
|

|

|
Return Status codes:
Most of the functions returns 0 is the result
is OK otherwise a number following this error table :
Return Value
|
MEANING
|
0
|
OK
|
1
|
ID Error
|
2
|
I2C Error
|
3
|
INTERNAL ERROR
|
4
|
UNKNOWN ERROR
|
5
|
GENERIC ERROR
|
The following functions are available :
CCS811.SETUP(address)
'the
address can be &h5A or &h5B
Start the device using the given I2C address.
Returns 0 if OK or a value following the
status codes table
CCS811.READ
Updates
the total volatile organic compounds (TVOC) in parts per billion
(PPB) and the CO2 value.
Returns 0
if OK or a value following the status codes table
CCS811.CHECKSTATERROR
Checks to see if the error bit is set.
Returns 1 if an error is set otherwise 0
CCS811.AVAIL
Checks to see if data is available (
DATA_READY flag is set in the status register).
Return 1 if data is available otherwise 0
CCS811.APPVALID
Checks to see if a valid application firmware
is loaded (APP_VALID flag is set in the status register).
Return 1 if application is valid otherwise
0
CCS811.GETERRORREG
Returns the status of the
error register
CCS811.GETBASELINE
Returns the baseline
value.
Used for telling the
sensor what 'clean' air is.
You must put the sensor in
clean air and record this value.
CCS811.SETBASELINE(baseline)
Set the baseline value taken from the function
CCS811.GETBASELINE
Returns 0 if OK or a
value following the status codes table
CCS811.INT_ENABLE
Enable the nINT signal
Returns 0 if OK or a
value following the status codes table
CCS811.INT_DISABLE
Disable the nINT signal
Returns 0 if OK or a
value following the status codes table
CCS811.SETDRIVEMODE(mode)
Set the operation mode of the device following
the table below:
MODE
|
MEANING
|
EXPLANATION
|
0
|
Idle
|
Measurements are disabled in this mode
|
1
|
Read every 1 sec
|
Constant power mode, IAQ measurement every
second
|
2
|
Read every 10 sec
|
Pulse heating mode IAQ measurement every 10
seconds
|
3
|
Read every 60 sec
|
Low power pulse heating mode IAQ measurement
every 60 seconds
|
4
|
Raw mode
|
Constant power mode, sensor measurement every
250ms.
In this mode the internal chip algo is not
updated and the processing must be done on the host system.
|
After each measurement interval, a new sample
is processed by the internal chip algo and the function
CCS811.AVAIL will return 1 indicating that the data is
ready.
If the nINT signal is enabled, the CCS811 nINT
pin will be set to 0 until the data will be read with
CCS811.READ
SETENVDATA(humidity,
temperature) 'humidity in %, temperature in
°C
Given a temp and humidity, write this data to
the CSS811 for better compensation
Returns 0 if OK or a
value following the status codes table
CCS811.TVOC
Returns the TVOC computed value
CCS811.CO2
Returns the CO2 computed value
Example 1
'CCS811
simple demo
i2c.setup 21, 22
if
ccs811.Setup(&h5a)
<> 0 then print
"CCS811 not found" :
end
print
ccs811.setdrivemode(1)
'update every second
While 1
if
ccs811.avail = 1 then
a = ccs811.read
print "CO2 "; ccs811.CO2, "TVOC "; ccs811.TVOC
end
if
Wend
|
Example 2
'CCS811
combined with a HDC1080 module demo
i2c.setup 21,
22
if
ccs811.Setup(&h5a)
<> 0 then print
"CCS811 not found" :
end
if
hdc1080.Setup(&h40)
<> 0 then print
"HDC1080 not found" :
end
print
ccs811.setdrivemode(2)
'update every 10 seconds
While 1
a
= ccs811.setenvdata(hdc1080.hum, hdc1080.temp)
print
"Temperature "; hdc1080.temp, "Humidity "; hdc1080.hum
if
ccs811.avail = 1 then
a = ccs811.read
print "CO2 "; ccs811.CO2, "TVOC "; ccs811.TVOC
end
if
pause 1000
wend
|
An APDS9960 Sensor can be connected to the
module using the I2C interface.
The APDS-9960 device features advanced Gesture
detection, Proximity detection, Digital Ambient Light Sense (ALS)
and Color Sense (RGBC).
Gesture detection utilises four directional
photodiodes to sense reflected IR energy (sourced by the integrated
LED) to convert physical motion information (i.e. direction and
distance) into digital information.

The connection is very simple, just 2 pins for
the I2C bus and the power supply are required.
The module is already provided with on-board
pull-up resistors, so external pull-up resistors are not
required.

Available functions are :
APDS9960.SETUP(mode)
APDS9960.READGESTURE
APDS9960.AMBIENT
APDS9960.RED
APDS9960.GREEN
APDS9960.BLUE
APDS9960.PROXIMITY
APDS9960.GESTUREGAIN
APDS9960.GESTURELED
There is also an
associated
ONGESTURE event.
The use of the
APDS9960 module is quite simple.
First the I2C must be
initialised with the command
I2C.SETUP.
Then the module must be initialised with the
function
APDS9960.SETUP(mode).
“mode”
must be 1 for “GESTURE” mode.
As soon as a gesture is recognised, the event
ONGESTURE is triggered, so it is then possible to get
the recognised gesture with the function
APDS9960.READGESTURE
Example
'APDS9960
GESTURE SENSOR DEMO
i2c.setup 21,22
'set the sensor in GESTURE
mode
if apds9960.Setup(1)
= 0 then print
"APDS9960 not found" :
end
'define the Gesture event
ongesture gesture
'Wait for the event
wait
gesture:
r = apds9960.ReadGesture
select case r
case 1
print
"LEFT"
case 2
print
"RIGHT"
case 3
print
"UP"
case 4
print
"DOWN"
case 5
print
"NEAR"
case 6
print
"FAR"
case else
print
"none"
end select
return
|
The module can also be configured as an
Ambient & RGB light sensor.
In this case “mode”
must be 2 for “Ambient Light and RGB Color” mode.
Example
'APDS9960
LIGHT SENSOR DEMO
i2c.setup 21,22
'set the sensor in Ambient
light and RGB Color mode if
apds9960.Setup(2)
= 0 then print
"APDS9960 not found" :
end
for z = 1 to 10000
print "Light:",
apds9960.ambient, apds9960.red, apds9960.green, apds9960.blue
pause 100
next z
end
|
The module can, finally, be configured also as
a Proximity sensor.
In this case “mode”
must be 3 for “Proximity” mode.
Example
'APDS9960
PROXIMITY SENSOR DEMO
i2c.setup 21,22
'set the sensor in Proximity
mode if apds9960.Setup(3)
= 0 then print
"APDS9960 not found" :
end
for z = 1 to 10000
print "Distance:", apds9960.proximity
pause 100
next z
end
|
A RFID card/key reader module based on the
chipset MFRC522 can be connected to the module using the SPI
Interface. These modules are very cheap and available on Ebay at
less than 2€.

These modules enable to read/write these kind
of devices, also easily available and very cheap


These devices are based on a chip manufactured
by NXP (MIFARE 1K) that contains 1KBytes of memory.
Each device has a 4 bytes identifier (NUID)
that is unique and cannot be modified.
For this reason this NUID is normally used as
a simple way to identify the device.
For more secured applications, personal data
can be written on the device and secured using passwords.
For more information, there is a nice article
on that subject here and the datasheet of the card
here
Annex implements all the functions permitting
reading and writing these devices.
The module must be connected using the SPI bus
as below:

The pin RST can be eventually left unconnected
or put to +3.3V.
To start using the module, it must be setup
using the function
RFID.SETUP(CS_pin,
RST_pin)
Example:
ret
=
RFID.SETUP(15,
0)
Note: if the RST pin is left unconnected, it
can be replaced by -1
in the function
This function returns a value following the
table below :
VALUE
|
REASON
|
0
|
Failed
|
18
|
Counterfeit chip
|
136
|
Clone
|
144
|
Version 0.0
|
145
|
Version 1.0
|
146
|
Version 2.0
|
255
|
Failed
|
Then it is possible to set the gain
(sensitivity) of the module with the function
RFID.SETGAIN(gain)
By default the gain is 4 and can range from 0
(minimum) to 7 (maximum)
Example:
ret
=
RFID.SETGAIN(7)
This function returns the value set or another
value in case of error.
Another event,
ONRFID , has been included to determine when a device is
detected.
All the actions related to the card (read /
write), must be done inside this event
Example
ONRFID card_detected
When this event occurs, the following
functions are available :
RFID.NUID$ that returns the NUID of the card detected
(ex. CD788821)
Example:
nuid$
= RFID.NUID$
RFID.TYPE$ that returns the type (model) of the card
detected (typically MIFARE
1KB )
Example:
type$
= RFID.TYPE$
It can return any of the following values:
TYPE
|
PICC
compliant with ISO/IEC 14443-4
|
PICC
compliant with ISO/IEC 18092 (NFC)
|
MIFARE Mini, 320 bytes
|
MIFARE 1KB
|
MIFARE 4KB
|
MIFARE Ultralight or Ultralight C
|
MIFARE Plus
|
MIFARE DESFire
|
MIFARE TNP3XXX
|
SAK
indicates UID is not complete.
|
Unknown type
|
Example:
'MRFC522
RFID CARD READER DEMO
print
"Setup", hex$(rfid.setup(15, 0))
print
"SetGain", rfid.setgain(7)
'define the RFID event
ONRFID card_detected
wait
card_detected:
print
"card detected"
print
"Type", rfid.type$
print
"NUID", rfid.nuid$
return
|
In addition to the function described above,
there are also other “advanced” functions.
These enable you to read and write blocks on
the card.
Each block is 16 bytes long and the card
(MIFARE 1K) contains 64 blocks.
The memory is organised into 16 sectors of 4
blocks each.
To note that :
-
The sector 0 is read only as it contains the NUID that cannot be
changed
-
The sector 3, 7, 11, 15, 19, 23, 27, 31, 35, 39, 43, 47, 51, 55,
59, 63 have a special function and should not be written; in
particular they contain the passwords.
-
Writing and reading to the card requires a password (6 bytes) that,
by default, is set to FFFFFFFFFFFF; this must be known and
cannot be extracted from the card.
-
So the first “advanced” function is
RFID.SETKEY that permit to define another password if
the card doesn’t use the default FFFFFFFFFFFF
Example:
ret
=
RFID.SETKEY("A1B2C3D4E5F6")
The function returns 1 if OK or 0 in case of
non valid password
Important : this function set the
key that is valid for all the blocks of the same sector
(i.e. the blocks 4 to 7).
Then, the function
RFID.READ$(block
[,key_b]) can be used
to read a block of 16 bytes.
The result will be a string like
“010102030405060708090A0B0C0D0E0F” or a message indicating
that an error is occurred :
MESSAGE
|
REASON
|
Auth
Failed
|
Error
during the authorisation phase.
Probably the password is not valid
|
Read
Failed
|
Error
during the reading phase.
Probably the card has been moved too far from the reader
|
Important: The KEY A is selected
by default but the KEY B can be selected putting a ,1
extra argument in the function
RFID.READ$ (example
RFID.READ$(block,
1)
If the card stops
responding or answers with an error, it is required to remove the
card from the reader and then bring it closer.
To avoid this action,
use the function
RFID.RESET or the function
RFID.AWAKE to reset the reader.
This is particularly
useful when reading using a wrong KEY as these functions reset the
module and enable it to retry again with another KEY.
Last function is
RFID.WRITE(block,
data$) that can be
used to write a block of 16 bytes.
block
must be a number from 0 to 63 and data$
a string like “010102030405060708090A0B0C0D0E0F”
The function returns the following error
values:
MESSAGE
|
REASON
|
0
|
No
error
|
1
|
Error
during the authorisation phase.
Probably the password is not valid
|
2
|
Error
during the writing phase.
Probably trying to write into a read only block or the content to
be written is not valid
|
Writing NUID for UID
changeable card (4 byte UID version)
In general, the standard MIFARE RFID modules
have a unique NUID identifier that cannot be changed.
However, there exist some special “chinese”
modules that enable the feature to set an arbitrary NUID.
For that, the special function
RFID.SETNUID(NUID$)
can be used for this purpose where NUID$
represents an 4 bytes hex code
Example:
ret
=
RFID.SETNUID("AABBCCDD")
The function returns 1 if OK or 0 in case of
error
Important : this function works only
for UID changeable cards
The VL53L0X is a new generation Time-of-Flight
(ToF) laser-ranging module providing accurate distance measurement
whatever the target reflectances unlike conventional technologies.
It can measure absolute distances up to 2m, setting a new benchmark
in ranging performance levels, opening the door to various new
applications.
It must connected using I2C using
the wiring as shown below :


To start to use, it must be initialised using
the
The syntax is:
Ret
=
VL53L0X.INIT
It returns 1 if the initialisation was
successful or 0 if not OK.
Then, the following commands are available
:
Set the distance range (sensitivity); by
default the value is 0 for a max range of 600 mm
VL53L0X.SETRANGE
|
Range (mm)
|
0 ( default)
|
~ 600
|
1
|
~ 2000
|
Set the accuracy of the readout modifying the
time required for the measurement.
By default the value is 0 for a Measurement
time of 33 msec.
VL53L0X.SETACCURACY
|
Measurement time (msec)
|
0 ( default)
|
33
|
1
|
200
|
2
|
400
|
Finally it is possible to read the distance
using the function
The value returned is the distance measured in
millimeters.
If the measurement is not valid, for example
if the distance is out of range, this function returns
8190.
This is a “blocking” function meaning that the
program will stop during the time required for the measurement,
i.e. 400 ms when using the accuracy at 2.
For this reason the alternative function
returns the same information but without
blocking the execution of the code.
Obviously, the distance measured will be
“refreshed” only at the rate defined with the function
VL53L0X.SETACCURACY
Example:
' VL53L0X example program
print
VL53L0X.init
' will print 1 if the device has been found
VL53L0X.SetAccuracy 2
' set the refresh rate at 400 msec (max
accuracy)
VL53L0X.SetRange 1
' set the range at 2000 mm ( 2 meters
)
for z
= 1 to 100000
print
VL53L0X.Distance
' get the distance
next z
|
An additional “custom” function is also
available for experienced users:
VL53L0X.CUSTOM
signal_rate_limit,
VcselPeriodPreRange, VcselPeriodFinalRange,
MeasurementTimingBudget
Check the documentation of the driver for more information.
The HX711 is a high-precision
analog-to-digital converter (ADC) chip designed for weighing scale
and industrial control applications. It is commonly used in load
cells, which are transducers that convert physical force into an
electrical signal, and is capable of amplifying and digitising the
low-level signals produced by these sensors.
The HX711 chip contains two differential
analog inputs for the load cell signal, and provides a 24-bit
digital output that can be read by a microcontroller or other
digital device. It has programmable gain amplifiers with a
selectable gain of 128 or 64, allowing for greater sensitivity and
resolution of the load cell readings.
You can buy for very cheap a kit composed of a
“Load Cell” and an HX711 module as shown below:

The connection require only 2 wires for the
Data and the Clock signal as below:

The current implementation use a single -very
simple - function :
ret =
HX711(data_pin, clk_pin [,resolution])
the optional parameter resolution can be:
0 -> Input A GAIN 128 (default)
1 -> Input A Gain 64
2 -> Input B Gain 32
Example:
' HX711 example program
' The offset and scale must be adapted in function of the load
cell;
' You can start setting offset to 0 and the scale to 1 and then
find
' your numbers using an object with "known" weight as
reference
dat
= 32
clk
= 26
dim sample(30)
weight
= 0
offset
= 100671 ' must be
adapted to the specific load cell
scale
= 0.009663 ' must
be adapter to the specific load cell
samples
= 5 ' The average
is done on 5 samples
gosub webpage
onHtmlReload webpage
while
1
media = 0
for r = 1
to samples
sample(r)=
HX711(dat,clk)
' input A GAIN 128
(default)
next r
'computes the average removing the
lowest and the highest value
max=sample(1)
min=sample(1)
sum=0
for i= 1
to samples
sum = sum + sample(i)
if sample(i)
> max then max=sample(i)
if sample(i)
< min then min=sample(i)
next i
avg = (sum - max
- min) /
(samples-2)
w
= avg - offset
weight = fix(w *
scale)
wlog weight, avg
'pause 500
wend
end
tare:
offset
= avg
return
webpage:
cls
a$
= ""
a$
= a$ + CSSID$("wgt", "width:300px; font-size:150px; border:none;
pointer-events:none;")
a$
= a$ + CSSID$("bt", "width:300px; height:50px")
a$
= a$ + "weight (g):
" + textbox$(weight, "wgt")
+ "<br>"
a$
= a$ + button$("Tare", tare, "bt")
+ "<br><br>"
a$
= a$ + "scale: "
+ textbox$(scale)
html a$
autorefresh
200
return
|
The
Si5351 clock generator is an I2C controller clock generator. It
uses the onboard precision clock to drive multiple PLL's and clock
dividers using I2C instructions. By setting up the PLL and dividers
you can create precise and arbitrary frequencies.
There are three
independent outputs, and each one can have a different frequency.
Outputs are 3Vpp, either through a breadboard-friendly header or,
for RF work, an optional SMA connector.
The outputs can go from
8Khz to 160Mhz and the output drive strength can go from 2 to 8
mA.
The chip contains 2
PLL:
-
PLL 0 → Shared
with the outputs 0 and 1
-
PLL 1 →
Dedicated to the output 2.

The connection is very simple, just 2 pins for
the I2C bus and the power supply are required.
The module is already provided with on-board
pull-up resistors, so external pull-up resistors are not
required.

FUNCTIONS / COMMANDS
|
DESCRIPTION
|
SI5351.INIT
[capacitor
[,crystal]]
|
Initialise the module.
The optional parameter ‘capacitor’ can be as
below
DESCRIPTION
|
VALUE
|
CAPACITOR 0 pF
|
0
|
CAPACITOR 6 pF
|
1
|
CAPACITOR 8 pF
|
2
|
CAPACITOR 10 pF
|
3
|
The optional parameter ‘crystal’ can be
25000000 or 27000000.
The default values are 8pF and 25MHz
|
|
Set the correction for the frequency
calibration
|
|
Set the frequency for the output ‘out_nb’
‘frequency’ can go from 8000 to 160000000
|
|
Set the frequency manually for the output
‘out_nb’
‘frequency’ is the output frequency and
‘pll’ is the PLL frequency
|
|
Set the strength for the output ‘output’
The parameter strength can be as below
DESCRIPTION
|
VALUE
|
DRIVE 2MA
|
0
|
DRIVE 4MA
|
1
|
DRIVE 6MA
|
2
|
DRIVE 8MA
|
3
|
|
|
Set the phase for the output ‘out_nb’
|
|
Reset the PLL ‘pll_nb’
‘pll_nb’ can be 0 or 1
|
|
Enable / disable the output ‘out_nb’
If ‘enable’ = 1, the output is enabled
If ‘enable’ = 0, the output is disabled
|
|
Enable / disable the output ‘out_nb’
If ‘invert’ = 1, the output is inverted
If ‘invert’ = 0, the output is normal
|
|
Load a file containing the parameters
generated by the software “ClockBuilder Pro”
|
Example:
' SI5351 example program
SDA
= 21
SCL
= 22
I2C.SETUP SDA,
SCL 'Pins as
shown
si5351.init
'3, 25000000
si5351.calib 212000
'set the correction to calibrate the
frequency error
si5351.setfreq 0, 5000000
'set 5MHz on output
0
si5351.setfreq 2,
30000000 'set 30MHz on output
2
si5351.phase 0,
0
si5351.phase 1,
0
si5351.phase 2,
127
si5351.reset_pll 0
si5351.reset_pll 1
si5351.invert 0, 0
'do not invert out
0
si5351.invert 2, 0
'do not invert out
1
si5351.enable 0, 1
'enable out 0
si5351.enable 1, 0
'disable out 1
si5351.enable 2, 1
'enable out 2
si5351.strength 0, 1
'set 4mA on out 0
si5351.strength 2, 3
'set 8mA on out 2
counter.init 17
'set the internal H/W frequency counter
on pin 17
while 1
wlog counter.cpufreq 'read the frequency (up to ~40MHz
max)
pause 1000
wend
|
-
Based on the library https://github.com/gin66/FastAccelStepper
-
Controls up to 3 motors
-
allows up to 200000 generated steps per second
-
Works in background (the pulses are automatically generated even if
the program is stopped)
-
ESP32 only
FUNCTIONS / COMMANDS
|
DESCRIPTION
|
STEPPER.SETUP
stepper_id,
pin_step, pin_dir
|
Setup the driver to use the step motor
stepper_id can be from 1 to 3 (0 to 2 ?)
pin_step and pin_dir can be any output capable
pin
Default speed is 100Hz and default
acceleration is 10 step/sec^2
|
|
Set the step motor speed and acceleration
parameters
stepper_id can be from 1 to 3 (0 to 2 ?)
speed is in pulses/sec (Hz)
acceleration is in step/sec^2
|
|
Set the current position of the motor (like a
reset but at a given position)
stepper_id can be from 1 to 3 (0 to 2 ?)
position is the desired position (in steps),
and can be positive or negative (is a 32 bits number)
|
|
Move the motor relatively to the current
position (can be positive / negative)
stepper_id can be from 1 to 3 (0 to 2 ?)
position is the desired position (in steps),
and can be positive or negative (is a 32 bits number)
|
|
Move the motor to the absolute position (can
be positive / negative)
stepper_id can be from 1 to 3 (0 to 2 ?)
position is the desired position (in steps),
and can be positive or negative (is a 32 bits number)
|
|
stops the motor using the current
deceleration
stepper_id can be from 1 to 3 (0 to 2 ?)
|
|
stops the motor immediately (kind of
abort)
stepper_id can be from 1 to 3 (0 to 2 ?)
|
|
Run the motor in the Forward direction and
continue until STEPPER.STOP is executed.
The motor accelerate and reach the speed
defined with the parameters defined with STEPPER.SETPARAM
stepper_id can be from 1 to 3 (0 to 2 ?)
|
|
Run the motor in the Backward direction and
continue until STEPPER.STOP is executed.
The motor accelerate and reach the speed
defined with the parameters defined with STEPPER.SETPARAM
stepper_id can be from 1 to 3 (0 to 2 ?)
|
|
Returns he current position (change during the
movement)
stepper_id can be from 1 to 3 (0 to 2 ?)
|
|
Returns the final target position (the one
reached at the process)
stepper_id can be from 1 to 3 (0 to 2 ?)
|
The MPU-9250 is a 9-DOF System in Package
(SiP) that combines two chips: the MPU-6500, which contains a
3-axis gyroscope as well as a 3-axis accelerometer, and the AK8963,
which features a 3-axis magnetometer.
It also contains a temperature sensor.


It must be connected using I2C wiring.
For that the I2C must be initialised before
using the command
I2C.Setup
21,22, 400000
'400000 set the I2C to max speed
To start to use, it must be initialised using
theMPU9250.SETUP
function.
The syntax is:
Ret
=MPU9250.SETUP(address)
‘Address’ can be &h68 or &h69
depending on the wiring of the MPU9250.
The address depends on the voltage applied to
the pin AD0 :
LEVEL ON PIN
AD0
|
ADDRESS
(HEXADECIMAL)
|
GND or open
|
68
|
VCC
|
69
|
It returns 1 if the initialisation was
successful, or 0 if not OK.
The chip temperature can then be read using
the function
Ret
=
MPU9250.TEMP
Example:
Print MPU9250.TEMP
Then all the chip values can then be read
using the function
Ret
=
MPU9250.VECTOR(array())
Using an array guarantees that all the data
received will be synchronised with each other as read at the same
time.
The function returns 1 if the action was
successful; otherwise 0.
NOTE: The array must be defined before
with the command DIM with a minimum size of 10
The variables are read in a one-shoot
operation, as per the table below:
INDEX
|
PARAMETER
|
UNITS
|
0
|
Accelerometer X
axis
|
m/sec2
|
1
|
Accelerometer Y
axis
|
2
|
Accelerometer Z
axis
|
3
|
Gyroscope X
axis
|
deg / sec
|
4
|
Gyroscope Y
axis
|
5
|
Gyroscope Z
axis
|
6
|
Magnetometer X
axis
|
micro tesla
|
7
|
Magnetometer Y
axis
|
8
|
Magnetometer Z
axis
|
Example:
I2C.Setup 21,22,
400000 '400000 set the I2C to max
speed
if
MPU9250.Setup(&h68)
= 0 then print
"MPU9250 not found" :
end
Print
"Temperature", MPU9250.TEMP ; "°C"
Dim vect(10)
'dimension the
array
'read the values for all the axis
Ret
= MPU9250.VECTOR(vect())
'Print all the values
Print
"ax "; vect(0), "ay ";
vect(1), "az ";
vect(2)
Print
"gx "; vect(3), "gy ";
vect(4), "az ";
vect(5)
Print
"mx "; vect(6), "my ";
vect(7), "mz ";
vect(8)
|
It must be noted that, because of the
different internal orientation of the MPU6500 part and the AK8963,
the axis of the magnetometers are not aligned with the
accelerometers and the gyros.
However, this has been taken into account
so this function will always return the correct values.
The MPU9250 can be straightly connected with
the IMU Fusion functions (see below) enabling it to compute, in a
single operation, all the orientation angles (pitch, roll and
yaw).
The Madgwick algorithm can be run using the
following functions :
Ret
= MPU9250.MADGWICK
This function reads all the values from the
MPU9250 and processes them using the Madgwick algorithm.
The result can then be read using
FUSION.PITCH,FUSION.ROLL
and
FUSION.YAW.
In the same way, the Mahony algorithm can be
run using the following functions :
Ret
= MPU9250.MAHONY
This function reads all the values from the
MPU9250 and processes them using the Mahony algorithm.
The result can then be read using
FUSION.PITCH,FUSION.ROLL
and
FUSION.YAW.
Note: The FUSION must be initialised
before using the command
FUSION.INIT
Example:
I2C.Setup 21,22,
400000 '400000 set the I2C to max
speed
if
MPU9250.Setup(&h68)
= 0 then print
"MPU9250 not found" :
end
Print
"Temperature", MPU9250.TEMP ; "°C"
FUSION.Init
' initialise the fusion algorithms
while 1
' infinite loop
a
= MPU9250.Madgwick 'runs the Madgwick algo
Print FUSION.Pitch, FUSION.Roll, FUSION.Yaw 'prints the result
wend
|
The MPU-6500 is a 6-DOF MotionTracking device
that combines a 3-axis gyroscope and a 3-axis accelerometer in a
small package. It also contains a temperature sensor.


It must be connected using I2C wiring.
For that the I2C must be initialised before
using the command
I2C.Setup
21,22, 400000
'400000 set the I2C to max speed
To start to use, it must be initialised using
theMPU6500.SETUP
function.
The syntax is:
Ret
=MPU6500.SETUP(address)
‘Address’ can be &h68 or &h69
depending on the wiring of the MPU6500.
The address depends on the voltage applied to
the pin AD0 :
LEVEL ON PIN AD0
|
ADDRESS (HEXADECIMAL)
|
GND or open
|
68
|
VCC
|
69
|
It returns 1 if the initialisation was
successful or 0 if not OK.
The chip temperature can then be read using
the function
Ret
=
MPU6500.TEMP
Example:
Print MPU6500.TEMP
Then all the chip values can then be read
using the function
Ret
=
MPU6500.VECTOR(array())
Using an array guarantees that all the data
received will be synchronised with each other as read at the same
time.
The function returns 1 if the action was
successful; otherwise 0.
NOTE: The array must be defined before
with the command DIM with a minimum size of 10
The variables are read in a one-shoot
operation, as per the table below:
INDEX
|
PARAMETER
|
UNITS
|
0
|
Accelerometer X
axis
|
m/sec2
|
1
|
Accelerometer Y
axis
|
2
|
Accelerometer Z
axis
|
3
|
Gyroscope X
axis
|
deg / sec
|
4
|
Gyroscope Y
axis
|
5
|
Gyroscope Z
axis
|
Example:
I2C.Setup 21,22,
400000 '400000 set the I2C to max
speed
if
MPU6500.Setup(&h68)
= 0 then print
"MPU6500 not found" :
end
Print
"Temperature", MPU6500.TEMP ; "°C"
Dim vect(10)
'dimension the
array
'read the values for all the axis
Ret
= MPU6500.VECTOR(vect())
'Print all the values
Print
"ax "; vect(0), "ay ";
vect(1), "az ";
vect(2)
Print
"gx "; vect(3), "gy ";
vect(4), "az ";
vect(5)
|
The MPU6886 can be straightly connected with
the IMU Fusion functions (see below) enabling it to compute, in a
single operation, all the orientation angles (pitch, roll and
yaw).
The Madgwick algorithm can be run using the
following functions :
Ret
= MPU6500.MADGWICK
This function reads all the values from the
MPU6500 and processes them using the Madgwick algorithm.
The result can then be read using
FUSION.PITCH,FUSION.ROLL
and
FUSION.YAW.
In the same way, the Mahony algorithm can be
run using the following functions :
Ret
= MPU6500.MAHONY
This function reads all the values from the
MPU6500 and processes them using the Mahony algorithm.
The result can then be read using
FUSION.PITCH,FUSION.ROLL
and
FUSION.YAW.
Note: The FUSION must be initialised
before using the command
FUSION.INIT
Example:
I2C.Setup 21,22,
400000 '400000 set the I2C to max
speed
if
MPU6500.Setup(&h68)
= 0 then print
"MPU6500 not found" :
end
Print
"Temperature", MPU6500.TEMP ; "°C"
FUSION.Init
' initialise the fusion algorithms
while 1
' infinite loop
a
= MPU6500.Madgwick 'runs the Madgwick algo
Print FUSION.Pitch, FUSION.Roll, FUSION.Yaw 'prints the result
wend
|
Note: As this IMU does not contain a
magnetometer, you will experience yaw drift over an extended period
of time. This is unavoidable and a limitation of the
technology.
The MPU-6886 is a 6-DOF MotionTracking device
that combines a 3-axis gyroscope and a 3-axis accelerometer in a
small package. It also contains a temperature sensor.
This is in particular installed inside the
M5Stack Atom Matrix using an internal I2C bus (pin 21 and 25).

For this reason it is not required to
initialise the I2C bus as it will be done automatically.
To start to use, it must be initialised using
theMPU6886.SETUP
function.
The syntax is:
Ret
=MPU6886.SETUP
The address is set automatically to HEX 68 so
it is not required
It returns 1 if the initialisation was
successful or 0 if not OK.
The chip temperature can then be read using
the function
Ret
=
MPU6886.TEMP
Example:
Print MPU6886.TEMP
Then all the chip values can be read using the
function
Ret
=
MPU6886.VECTOR(array())
Using an array guarantees that all the data
received will be synchronised with each other as read at the same
time.
The function returns 1 if the action was
successful; otherwise 0.
NOTE: The array must be defined before
with the command DIM with a minimum size of 10
The variables are read in a one-shoot
operation, as per the table below:
INDEX
|
PARAMETER
|
UNITS
|
0
|
Accelerometer X
axis
|
m/sec2
|
1
|
Accelerometer Y
axis
|
2
|
Accelerometer Z
axis
|
3
|
Gyroscope X
axis
|
deg / sec
|
4
|
Gyroscope Y
axis
|
5
|
Gyroscope Z
axis
|
Example:
if
MPU6886.Setup = 0
then print "MPU6686 not
found" : end
Print
"Temperature", MPU6886.TEMP ; "°C"
Dim vect(10)
'dimension the
array
'read the values for all the axis
Ret
= MPU6886.VECTOR(vect())
'Print all the values
Print
"ax "; vect(0), "ay ";
vect(1), "az ";
vect(2)
Print
"gx "; vect(3), "gy ";
vect(4), "az ";
vect(5)
|
The MPU6886 can be straightly connected with
the IMU Fusion functions (see below) enabling it to compute, in a
single operation, all the orientation angles (pitch, roll and
yaw).
The Madgwick algorithm can be run using the
following function :
Ret
= MPU6886.MADGWICK
This function reads all the values from the
MPU6886 and processes them using the Madgwick algorithm.
The result can then be read using
FUSION.PITCH,FUSION.ROLL
and
FUSION.YAW.
In the same way, the Mahony algorithm can be
run using the following functions :
Ret
= MPU6886.MAHONY
This function reads all the values from the
MPU6886 and processes them using the Mahony algorithm.
The result can then be read using
FUSION.PITCH,FUSION.ROLL
and
FUSION.YAW.
Note: The FUSION must be initialised
before using the command
FUSION.INIT
Example:
if
MPU6886.Setup = 0
then print "MPU6686 not
found" : end
Print
"Temperature", MPU6886.TEMP ; "°C"
FUSION.Init
' initialise the fusion algorithms
while 1
' infinite loop
a
= MPU6886.Madgwick 'runs the Madgwick algo
Print FUSION.Pitch, FUSION.Roll, FUSION.Yaw 'prints the result
wend
|
Note: As this IMU does not contain a
magnetometer, you will experience yaw drift over an extended period
of time. This is unavoidable and a limitation of the
technology.
Annex includes 2 fusion algorithms designed to
provide pitch, roll and yaw orientation from data coming from IMUs
like the MPU9250.
The 2 algorithms are Madgwick and Mahony.
Both are provided in 2 forms, with 6-DOF and
9-DOF..
To start, the algos must be initialised with
the command
FUSION.INIT
Then the different algos can be called as
below :
For the 6-DOF Madgwick:
FUSION.MADGWICK ax, ay,
az, gx, gy, gz
For the 9-DOF Madgwick:
FUSION.MADGWICK ax, ay,
az, gx, gy, gz, mx, my, mz
For the 6-DOF Mahony:
FUSION.MAHONY ax, ay,
az, gx, gy, gz
For the 9-DOF Mahony:
FUSION.MAHONY ax, ay,
az, gx, gy, gz, mx, my, mz
The angles can be read using the function
FUSION.ANGLE(axis)
following the table below:
AXIS
|
RETURNED INFORMATION
|
UNIT
|
1
|
PITCH
|
°
|
2
|
ROLL
|
°
|
3
|
YAW
|
°
|
In a simpler way,
it is also possible to read the values using the functions :
Pitch
= FUSION.PITCH
Roll
= FUSION.ROLL
Yaw
= FUSION.YAW
The 2 algos can be
tuned using the following coefficients :
For Madgwick :
FUSION.BETA
=
0.6
'
default value 0.6
FUSION.ZETA
=
0.6
'
default value 0.6 - only for 6-DOF algo
For Mahony:
FUSION.Kp
=
2
' proportional feedback default value
2
FUSION.Ki
=
0
' integral
feedback default value 0
Example with the MPU9250 and a Madgwick
algo:
I2C.Setup 21,22,
400000 '400000 set the I2C to max
speed
'initialise the MPU9250 with address hex 68
if
MPU9250.Setup(&h68)
= 0 then print
"MPU9250 not found" :
end
FUSION.Init
' initialise the fusion algorithms
FUSION.Beta
= 0.6 'set beta parameter to
0.6
Dim p(10)
'dimension the
array
while 1
' infinite loop
i = MPU9250.vector(p())
'read the values for all the
axis
'note: the syros must be converted to
RAD/sec
FUSION.Madgwick p(0),
p(1), p(2),
(p(3)
* PI/180),
(p(4)*
Pi/180),
(p(5)
* Pi/180),
p(6), p(7),
p(8)
Print FUSION.Pitch, FUSION.Roll, FUSION.Yaw 'prints the result
wend
|
An Ethernet module based on the chipset WIZnet
W5500 can be connected to the module using SPI interface.
These modules are very cheap and available on
Ebay at less than 5€.
This picture shows 2 modules based on this
chipset which have been successfully tested with Annex32.




This schematic shows how to connect the W5500
module to the ESP32 module.

This module permits to connect the ESP32 to
the network using a wired connection.
Annex32 implements the functionalities to send
and receive TCP and UDP packets.
It can be used in ADDITION to the existing
WI-FI functionalities, as it exposes all the functionalities
permitting to communicate with other modules / web services.
However, Annex32 cannot be administered
through this connection, administration must continue to be done
using Wi-Fi.
The actual implementation introduces a new
keyword, ETHERNET, which is used as the prefix for all the commands
/ functions related to it.
For simplicity, all the commands / functions
replicate the same existing Wi-Fi functionality.
For example Ethernet.wget$ is the equivalent
of wget$, Ethernet.IP$ is the equivalent of IP$, etc.
a = ETHERNET.init( cs_pin [, ip$, mask$,
gateway$ ] ) Initialise the interface,
variable a holds the status result.
If ip, mask, gateway are not defined, the
module will request a DHCP address from a DHCP server.
DHCP status returns =0 if failed to
receive a DHCP IP, =1 if DHCP IP received successfully,
=2 if using a manually configured fixed IP address, =-1 if
ethernet module not found, =-2 if UTP cable is not connected
a$ = ETHERNET.IP$ returns the IP
address of the module (same format as IP$)
a$ = ETHERNET.WGET$( url$, [port] ) same
as WGET$ but the syntax has been modified also for the WGET$
make a GET request on a remote server. The
arguments http_server [, port ]
the format of the url is
[protocol]://web_address:port/path
Example for the same website (all are
valid):
print
ethernet.wget$(“jsonplaceholder.typicode.com/posts”) ‘ use by
default the port 80
print
ethernet.wget$(“http://jsonplaceholder.typicode.com/posts”) ‘
use by default the port 80
print
ethernet.wget$(“jsonplaceholder.typicode.com:80/posts”) ‘
define the the port 80
print
ethernet.wget$(“jsonplaceholder.typicode.com/posts”, 80) ‘
define the the port 80
Another example
print
ethernet.wget$("http://portquiz.net:8080/") ‘ define the port
8080
print ethernet.wget$("http://portquiz.net/",
8080) ‘ define the port 8080
a$ = ETHERNET.WPOST$( url$, [ [, port |
payload$] [,port] ] )
make a POST request on a remote server
the arguments http_server [ [, port |
payload$] [,port] ]
the format of the url is
[protocol]://web_address:port
These functions :
ETHERNET.UDP.BEGIN
ETHERNET.UDP.STOP
ETHERNET.UDP.WRITE
ETHERNET.UDP.REPLY
ETHERNET.UDP.READ$ ETHERNET.UDP.REMOTE$
Have the same function and format as the
corresponding wifi versions but are for the ethernet network
WEB SERVER:
ETHERNET.SERVER.BEGIN [port] ‘ start the
ethernet web server on the defined port (by default 80)
ETHERNET.SERVER.STOP ‘ stop the ethernet
web server
ETHERNET.SERVER.GETURL$ ‘ returns the url of
the request done on the server
ETHERNET.SERVER.GETARG$ ‘ returns the arg from
the request (same as
ETHERNET.SERVER.RETURN ret$ [,
content_type$]
‘ permit to return a content to the caller
page
EVENTS:
ONETHERNETUDP label
same event as ONUDP but for the ETHERNET
ONETHERNETURL label
Is triggered when a request is done with any
url
The url can be read with the function
ethernet.server.geturl$ and:
The arguments can be read with the function
ethernet.server.getarg$
The File
Transfer Protocol (FTP) is a standard network protocol
used for the transfer of computer files
between
a client and server on a computer
network.
Annex implements a
function permitting to send files stored locally to the
remote server.
The function is :
The FTP port is
defined by default at the standard value 21.
To send a file the
command is
res$
= BAS.FTP$(host$, login$, password$, file$,
folder$)
Where :
●
host$
is the address of the FTP server
●
login$
is the login of the account on the FTP server
●
password$
is the password of the account on the FTP server
●
file$
is the file that will be sent
●
folder$
is the folder where the file will be sent
Note :
●
If the remote folder does not
exist, it will be created automatically.
●
in this case make sure you have
the right to create the directories on the FTP
server
If the transmission
was successful, the function returns a message like this:
-
226 Transfer complete (153.536 KB/s).
In case of
problems, the function returns a self explaining messages like this
:
-
550 Can't change directory to
"/newfolder".
-
530 Permission denied
-
-2 File not found
-
…...
Example :
res$
= BAS.FTP$("192.168.1.57", "myLogin", "myPass", "/test.bas", "/")
This is a useful example that permit to backup the module sending
all the local files to the FTP server
' FTP function example revised
' cicciocb 2019
' send all the local files to the remote server
' in the folder /
' The directory structure will be also copied
'starts from the root
d$
= FILE.DIR$("/")
'Then lists all the files
While D$
<> ""
print "I'm sending ", d$
path$ = left$(d$,
instr(-1, d$,
"/")) ' extract the
path
print bas.ftp$(
"192.168.1.57", "robin", "hood", d$, path$)
d$
= FILE.DIR$
Wend
end
|
Annex includes the functionality to
request/send data from/to the server using HTTP GET, POST and PUT
requests.
The GET is the most common HTTP method,
generally used to request (GET) data from a server but can also be
used to send data to the server.
This is what your web browser does when typing
a url in the address bar.
This method uses the url to include all the
data to be transferred to the server and returns the answer from
the server.
As support, there is a nice site https://jsonplaceholder.typicode.com/
that permits you to exercise into issuing GET requests.
For example, http://jsonplaceholder.typicode.com/comments/1
is composed of :
http:// => protocol. By default uses the
port 80.
jsonplaceholder.typicode.com => base
url
/comments/1 => url used to transfer
arguments (comments = 1)
Another way to transfer arguments is using
them after a ? as below:
http://jsonplaceholder.typicode.com/comments?id=1
In this case we transfer the request for
comments with id=1
Another example :
http://jsonplaceholder.typicode.com/comments?id=1&id=4
In this case we transfer the request for
comments with id=1 and id=4.
To note that the arguments are composed of
couples arg=value separated by &
The same requests can be done using an
encrypted protocol, the https:// that uses the port 443 :
https://jsonplaceholder.typicode.com/comments?id=1&id=4
(to note the https://)
The POST method is less used than the GET but
it is the most appropriate to send data to the server.
In contrast to the GET method where the data
is transferred inside the url of the request, the POST method
transfers the data in the body of the message.
The PUT method is very similar to POST but is
generally used to modify a resource.
Annex implements 4 methods to make HTTP
requests :
-
WGET$(server$, port, [,rx_header]
[,header$])
-
WGET$(url$ [,rx_header]
[,header$])
-
WPOST$(server$, body$, port [,rx_header]
[,header$] )
-
WPOST$(url$, body$ [,rx_header]
[,header$])
-
WPUT$(server$, body$, port [,rx_header]
[,header$] )
-
WPUT$(url$, body$ [,rx_header]
[,header$])
-
WGETASYNC[(]
server$, port, [,rx_header]
[)]
Basically
WGET$ and
WGETASYNC both do the same operation but
WGET$ waits until the server answers whilst
WGETASYNC continues the normal execution of the program
and triggers (asynchronously) an event when the answer arrives
.
Example with
WGET$ :
' do an HTTP GET request
a$
= WGET$("jsonplaceholder.typicode.com/comments?id=1&id=4",
80)
' do an HTTPS GET request
a$
= WGET$("jsonplaceholder.typicode.com/comments?id=1&id=4",
443)
' or with the alternative syntax
' do an HTTP GET request
a$
= WGET$("http://jsonplaceholder.typicode.com/comments?id=1&id=4")
' do an HTTPS GET request
a$
= WGET$("https://jsonplaceholder.typicode.com/comments?id=1&id=4")
' do an HTTPS GET request
a$
= WGET$("https://httpbin.org/get?Annex=10&GET=20&text=30&Data=40")
|
To note :
The leading HTTP:// or HTTPS://
must be removed if the port is specified
The protocol is specified using the port
number; by default is HTTP but will be HTTPS if the port is
443.
Example with
WPOST$ :
' do an HTTP POST request
a$
= WPOST$("ptsv2.com/t/annextest/post", "name=Annex&version=1.39",
80)
' check at https://ptsv2.com/t/annextest for the
result
' or with the alternative syntax
a$
= WPOST$("http://ptsv2.com/t/annextest/post",
"name=Annex&version=1.39")
'
a$
= WPOST$("http://httpbin.org/post?a=10", "Annex POST text Data")
|
To note :
The leading HTTP:// or HTTPS://
must be removed if the port is specified
The protocol is specified using the port
number; by default is HTTP but will be HTTPS if the port is
443.
Example with
WPUT$ :
' do an HTTP POST request
a$
= WPOST$("ptsv2.com/t/annextest/put", "name=Annex&version=1.39",
80)
' check at https://ptsv2.com/t/annextest for the
result
' or with the alternative syntax
a$
= WPOST$("http://ptsv2.com/t/annextest/put",
"name=Annex&version=1.39")
'
a$
= WPOST$("http://httpbin.org/put?a=10", "Annex POST text Data")
|
To note :
The leading HTTP:// or HTTPS://
must be removed if the port is specified
The protocol is specified using the port
number; by default is HTTP but will be HTTPS if the port is
443.
Example with
WGETASYNC:
ONWGETASYNC
answer_done
' do an HTTPS GET request
WGETASYNC
"jsonplaceholder.typicode.com/comments?id=1&id=4",
443
' or with the alternative syntax
'WGETASYNC
"https://jsonplaceholder.typicode.com/comments?id=1&id=4"
Wait
answer_done:
Print
WGETRESULT$
Return
|
To note :
The leading HTTP:// or HTTPS://
must be removed if the port is specified
The protocol is specified using the port
number; by default is HTTP but will be HTTPS if the port is
443.
The brackets around
WGETASYNC are optional.
Optionally it is possible to specify an extra
parameter rx_header
for
WGET$,
WPOST$, WPUT$ and
WGETASYNC.
If this parameter is 1, the header of the
received message will be included in the answer.
This will be helpful for debugging.
Note: if you don’t know what the header
is, just ignore this option.
Another optional argument is header$
that enables you to include a specific header inside the content
requested from the remote server.
It can be
"Content-Type: application/json" or
"Content-Type: text/html", for example.
Multiple information can be included simply
separating each
“key:value” couplet with chr$(10).
MQTT
stands for MQ Telemetry Transport. It is a publish/subscribe,
extremely simple and lightweight messaging protocol, designed for
constrained devices and low-bandwidth, high-latency or unreliable
networks. The design principles are to minimise network bandwidth
and device resource requirements whilst also attempting to ensure
reliability and some degree of assurance of delivery. These
principles also turn out to make the protocol ideal of the emerging
“machine-to-machine” (M2M) or “Internet of Things” world of
connected devices, and for mobile applications where bandwidth and
battery power are at a premium.
The current implementation supports the
unencrypted (port 1883) or encrypted SSL connections (port
8883).
The url must specify the protocol and
optionally the port.
Example:
"mqtt://test.mosquitto.org" or
"mqtt://test.mosquitto.org:1883" for unencrypted
"mqtts://test.mosquitto.org" or
"mqtts://test.mosquitto.org:8883" for encrypted
Annex implements the protocol with the
following characteristics :
-
It can publish QoS 0, QoS 1 or QoS 2 messages.
-
It can subscribe at QoS 0, QoS 1 or QoS 2.
-
The maximum message size is 1024 characters
-
The keepalive interval is set to 120 seconds
-
The network timeout is set to 10 seconds
-
The client uses MQTT 3.1.1
If the MQTT connection with the remote server
is lost, the module will retry to reconnect automatically.
When using SSL connections, it might be
required to use certificates / private keys.
In general a CERTIFICATE is a text block like
this :
-----BEGIN CERTIFICATE-----
MIIB9TCCAWACAQAwgbgxGTAXBgNVBAoMEFF1b1ZhZGlzIExpbWl0ZWQxHDAaBgNV
BAsME0RvY3VtZW50IERlcGFydG1lbnQxOTA3BgNVBAMMMFdoeSBhcmUgeW91IGRl
…
…
Awel8LzGx5uMOshezF/KfP67wJ93UW+N7zXY6AwPgoLj4Kjw+WtU684JL8Dtr9FX
ozakE+8p06BpxegR4BR3FMHf6p+0jQxUEAkAyb/mVgm66TyghDGC6/YkiKoZptXQ
98TwDIK/39WEB/V607As+KoYazQG8drorw==
-----END CERTIFICATE-----
|
And a PRIVATE KEY is a text block like
this
-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEAz2ZbLZ45k/G0O+dKxshu3WaN+pfSZov6Q1tZ/Vsbjt7bS0Qk
LSTXrMP4OdiLBtC7ynqhkGL39ktFnFqRTx67XuyL0YmjyPX5e4DbveY/riGwK4MZ
…
…
JwQV3escd6MlQEAxvKFPH5+csDnDxXlJ9Mz+4DY7ElVJyhGiwyPrmigZ9Ph1FPc1
h8xSYmkCgYEAkbvPyMR/q5XQ4Cg2J8BPci3lw38Hhfb1Mr5mpDpRhocPRqWL2Vb0
4CxYKMT65wl1voa5wmsDukbUlrqBq6LPaIeCF2MqKLAahrSOI9O5U3r29wRYhxcD
49FDJGTr/0eTMl+/d8f08W/XmJC1YtF9edVIfpJejelQCElB4zSEgFU=
-----END RSA PRIVATE KEY-----
|
These certificates / Private keys can be
stored into a string variable and given as arguments to the
MQTT.certif function. The best is to store them into text files and
get into a string variable using FILE.READ$
The following table describes the functions
available.
FUNCTIONS / COMMANDS
|
DESCRIPTION
|
|
Setup the MQTT communications.
Server$ is the MQTT server url
‘debug’, if set to 1, enable some useful debug
messages
This function clears all the existing
certificates and PSK
Returns 258 at the first initialisation and
then 0
|
MQTT.Certif(cert_pem$
[,client_cert_pem$] [,client_key_pem$])
|
Set the SSL certificates.
‘cert_pem$’ is used for
the main server authorisation
‘client_cert_pem’ and
‘client_key_pem$’ are used for a more complex authorisation scheme
(for advanced users)
When setting the
certificates, the PSK will be removed
|
|
Set the PSK as an alternative to certificate
verification.
When setting this PSK all the certificates
will be removed
|
MQTT.LWT(topic$,
message$ [,Qos] [,retain])
|
Set the last will and testament (LWT) message
in the specified topic
Qos can be 0, 1 or 2; if not defined defaults
to 0
‘retain’, if set to 1, the message is
retained
Returns 0 if OK
|
|
Connect to the server using the provided login
and password.
Optionally id$ permit to define an arbitrary
ID
Returns 0 if OK
|
|
Connect to the server without
identification
Optionally id$ permit to define an arbitrary
ID
Returns 0 if OK
|
|
Disconnects from the MQTT server
Returns 0 if OK
|
MQTT.Publish(topic$,
message$ [,Qos] [,retain])
|
Publish a string message in the specified
topic
Qos can be 0, 1 or 2; if not defined defaults
to 0
‘retain’, if set to 1, the message is
retained
Returns the msg_id of the message sent
|
|
Subscribes to messages published to the
specified topic.
Qos can be 0, 1 or 2; if not defined defaults
to 0
Returns 0 if OK
|
|
Unsubscribes from the specified topic
Returns 0 if OK
|
|
Returns the current connection status.
Returns 1 if connected or 0 if
disconnected
|
|
Returns the current status. It can be:
MQTT_STATE_INIT = 0
MQTT_STATE_DISCONNECTED =
1
MQTT_STATE_CONNECTED =
2
MQTT_STATE_WAIT_RECONNECT =
3
|
OnMQTT
label
|
Define a label where the program will jump
when an MQTT message is received
|
MQTT.Message$
|
Returns the MQTT message received
|
MQTT.Topic$
|
Returns the MQTT topic received or the event
name.
The event can be:
Value
|
Event
|
_BEFORE_CONNECT_
|
Raised
before the connection is done. Useful to determine if the module is
trying to (re)connect
|
_CONNECTED_
|
Raised
when the connection is done
|
_DISCONNECTED_
|
Raised when the
connection is lost
|
_ERROR_
|
Raised
in case of error
|
|
This is an example based on the free MQTT test
server “test.mosquitto.org”.
The program subscribes and sends messages to
the same “/AnnexTest” topic.
It should print the same messages that are
sent to the server.
' MQTT SSL test program
' Using mosquitto test server
onmqtt mqtt_msg
print
mqtt.setup("mqtts://test.mosquitto.org", 1)
print
mqtt.connect("", "")
' No login / pass
required
print
mqtt.subscribe("/AnnexTest") ' subscribe to
the topic /AnnexTest
for z
= 1 to 10
' send messages to the topic
/AnnexTest
print mqtt.publish("/AnnexTest", "Annex"+str$(z))
pause 100
next z
print
ramfree
wait
' receive messages from the server
mqtt_msg:
print
"TOPIC : "; mqtt.topic$
print
"MESSAGE: "; mqtt.message$
return
|
This is another example based on the free MQTT
test server “test.mosquitto.org” or “mqtt.eclipseprojects.io”
It uses a certificate stored into an external
file; it can be omitted removing the function
mqtt.Certif
The program subscribes and sends several
messages to several topics and receives them back.
This also shows how to use the event
"_CONNECTED_" for starting the process.
' MQTT SSL test program
' Using mosquitto or eclipseprojects.io test server
' MQTT SSL DEMO
a$
= file.read$("/mosquitto.pem") ' reads the
certificate from file
'a$ = file.read$("/eclipseprojects.pem") ' reads the certificate
from file
onmqtt mqtt_event
print
mqtt.setup("mqtts://test.mosquitto.org", 1) ' set
debug
'print
mqtt.setup("mqtts://mqtt.eclipseprojects.io:8883")
print
mqtt.Certif(a$)
' set the
certificate
print
mqtt.connect("", "")
prev
= ramfree
wait
mqtt_event:
print
"event mqtt", MQTT.Topic$, MQTT.Message$
if
(MQTT.Topic$ = "_CONNECTED_") then
print "subscribe 0" , mqtt.subscribe("/AnnexTest/QOS0", 0)
print "subscribe 1" , mqtt.subscribe("/AnnexTest/QOS1", 1)
print "subscribe 2" , mqtt.subscribe("/AnnexTest/QOS2", 2)
timer0 2000,
publisher
end
if
return
publisher:
r$
= str$(rnd(10000))
print mqtt.publish("/AnnexTest/QOS0", "Test 0 " +
r$, 0)
print mqtt.publish("/AnnexTest/QOS1", "Test 1 " +
r$, 1)
print mqtt.publish("/AnnexTest/QOS2", "Test 2 " +
r$, 2)
rf
= ramfree
print "ramfree ", rf, rf - prev
prev = rf
return
|
This program is the same of the previous one
but it uses a full authorisation using CA certificate, client
certificate and client key stored into external files
' MQTT SSL test program
' Using mosquitto test server
' MQTT SSL DEMO using full certificates
ca$
= file.read$("/mosquitto.org.crt") ' reads the
certificate from file
cert$
= file.read$("/client.crt") ' read the
client certificate from file
key$
= file.read$("/client.key") ' reads the
key from file
onmqtt mqtt_event
print
mqtt.setup("mqtts://test.mosquitto.org:8884",
1) '
set debug
print
mqtt.Certif(ca$, cert$,
key$) ' set the certificates
ca$
= "" : cert$ =
"" : key$ = ""
' free these
variables
print
mqtt.connect("", "")
prev
= ramfree(1)
wait
mqtt_event:
print
"event mqtt", MQTT.Topic$, MQTT.Message$
if
(MQTT.Topic$ = "_CONNECTED_") then
print "subscribe 0" , mqtt.subscribe("/AnnexTest/QOS0", 0)
print "subscribe 1" , mqtt.subscribe("/AnnexTest/QOS1", 1)
print "subscribe 2" , mqtt.subscribe("/AnnexTest/QOS2", 2)
timer0 2000,
publisher
end
if
return
publisher:
r$
= str$(rnd(10000))
print mqtt.publish("/AnnexTest/QOS0", "Test 0 " +
r$, 0)
print mqtt.publish("/AnnexTest/QOS1", "Test 1 " +
r$, 1)
print mqtt.publish("/AnnexTest/QOS2", "Test 2 " +
r$, 2)
rf
= ramfree(1)
print "ramfree ", rf, rf - prev
prev = rf
return
|
An MQTT broker is a central component in
MQTT-based communication systems, acting as an intermediary between
devices that publish messages and those that subscribe to receive
them. In the context of Annex RDS for ESP32, the MQTT broker is a
simplified, lightweight implementation designed to run directly on
the microcontroller.
This embedded MQTT broker provides core MQTT
functionalities within the constraints of the microcontroller's
resources. It can handle up to 12 connected devices simultaneously,
making it suitable for small to medium-scale IoT applications. The
broker manages client connections, handles message routing based on
topics, and facilitates the publish/subscribe model of
communication. Importantly, this broker supports Quality of Service
(QoS) levels 0 and 1, allowing for flexible message delivery
guarantees depending on the application's needs.
A unique feature of this implementation is
that the broker itself can participate in the communication as if
it were a pre-connected client. This means the broker can both
subscribe to topics and publish messages, allowing it to listen for
specific messages and respond or act upon them directly. This
capability enables the ESP32 to not only mediate communication
between other devices but also to be an active participant in the
IoT ecosystem it manages.
Key features of this lightweight broker
include:
●
Managing up to 12 simultaneous client connections
●
Processing basic MQTT commands (CONNECT, PUBLISH, SUBSCRIBE,
etc.)
●
Routing messages between publishers and subscribers
●
Maintaining a list of topics and subscriptions
●
Implementing basic authentication
●
Acting as a client to subscribe and publish messages
●
Supporting QoS levels 0 and 1 for message delivery
●
Supports the Last Will Testament messages
●
Supports messages up to :
○
Client ID : 50 characters
○
Topic : 100 characters
○
Payload : 1024 characters
This lightweight broker enables ESP32 devices
to act as central hubs in small-scale IoT networks, allowing for
efficient, event-driven communication between multiple devices
without the need for an external broker. It's particularly useful
in scenarios where low latency, local processing, or offline
operation is required, with the added benefit of the broker being
able to actively participate in the communication flow. The support
for QoS 0 and 1 ensures that users can choose between best-effort
delivery and at-least-once delivery, depending on their specific
application requirements.
Set up the MQTT broker.
●
port: Integer. The port number for the MQTT broker (default is
1883).
●
login$: String. The login username for broker authentication. If it
is an empty string (""), it will be ignored.
●
password$: String. The password for broker authentication. If it is
an empty string (""), it will be ignored.
●
debug: Optional Boolean. Enable debug mode if set to 1.
Returns: 0 on success, -1 on failure.
Example
result
= MqttBroker.Setup(1883, "user", "pass", 1)
Starts the MQTT broker task.
●
ramsize: Integer. The stack size in bytes for the MQTT broker
task.
Returns: 0 on success, -1 if the task is already running.
Example
result
= MqttBroker.Start(20000)
Stops the MQTT broker task.
Returns: 0 (always successful).
Example
result
= MqttBroker.Stop
Restarts the MQTT broker.
Returns: 0 (always successful).
Example
result
= MqttBroker.Restart
Publishes a
message to a specified topic.
●
topic$: String. The topic to publish to.
●
payload$: String. The message content.
● qos:
Optional Integer. Quality of Service level (0 or 1). Default is
0.
●
retain: Optional Boolean. Whether to retain the message. Default is
0.
Returns: 0 (always successful).
Example
result
= MqttBroker.Publish("sensors/temperature", "25.5", 1, 1)
Subscribes
to a specified topic.
●
topic$: String. The topic to subscribe to.
● The
broker can manage up to 20 different topics.
Returns:
●
0: Subscription successful.
●
1: Topic already exists (already subscribed).
●
-1: Cannot add more topics (maximum limit of 20 topics
reached).
Example
result =
MqttBroker.Subscribe("sensors/temperature")
IF
result
=
0
THEN
PRINT
"Successfully subscribed to topic"
ELSEIF
result
=
1
THEN
PRINT
"Already subscribed to this topic"
ELSEIF
result
= -1
THEN
PRINT
"Cannot subscribe: maximum number of topics reached"
ENDIF
|
Special Characters in
Topics:
●
'/': Used as a topic level separator.
●
'#': Multi-level wildcard. Must be the last character in the topic
string.
●
'+': Single-level wildcard. Can be used at any level in the topic
string.
Examples of topic
patterns:
●
"sensors/#": Subscribes to all topics under "sensors"
●
"sensors/+/temperature": Subscribes to temperature topics for all
sensors
●
"home/+/room1/#": Subscribes to all messages for room1 in any
house
Unsubscribes from a specified topic.
●
topic: String. The topic to unsubscribe from.
Returns: 0 on success, -1 on failure.
Example
result =
MqttBroker.UnSubscribe("sensors/temperature")
Lists all subscribed topics by the server.
The list does not include the topics
subscribed by the clients.
If the optional variable List$ is specified,
it will contain the list of topics, separated by newlines
(CHR$(10)).
Returns: Number of subscribed topics.
Example
topicCount =
MqttBroker.ListTopics
Print
topicCount
'or
topicCount =
MqttBroker.ListTopics(topicList$)
Print
topicList$
|
Clears all
subscribed topics.
Returns: 0
(always successful).
Example
result =
MqttBroker.ClearTopics
Lists all connected clients, including their
IP address.
If the optional variable List$ is specified,
it will contain the list of “client,ip” separated by newlines
(CHR$(10)).
Returns: Number of connected clients.
Example
clientCount =
MqttBroker.ListClients
Print
clientCount
'or
clientCount =
MqttBroker.ListClients(clientsList$)
Print
clientsList$
|
The ONMQTT event handler allows you to respond
to MQTT events, including incoming messages and connection status
changes.
●
label: The
label where the program will jump when an MQTT event
occurs.
Returns:
Does not return a value.
Example
OnMQTT label
When an MQTT event occurs, you can access
these special variables:
●
MQTT.Topic$: Contains the topic of the received message
or the name of the event.
●
MQTT.Message$: Contains the payload of the received
message or, for special events, the IP address of the client.
●
MQTT.Client$: Contains the ID of the client connected to
the broker.
MQTT.Topic$ can contain these special values for
non-message events:
●
"_CONNECTED_": Triggered when a connection is
established
●
"_DISCONNECTED_": Triggered when the connection is
lost
●
"_WRONG_LOGIN_": Triggered when the login credentials
are incorrect
For these special events, MQTT.Message$
contains the IP address of the client.
MyMqttHandler:
PRINT
"Client ID: ";
MQTT.Client$
IF
MQTT.Topic$ =
"sensors/temperature"
THEN
PRINT
"Received temperature: ";
MQTT.Message$
ELSEIF
MQTT.Topic$ =
"_CONNECTED_"
THEN
PRINT
"MQTT connection established for IP: ";
MQTT.Message$
ELSEIF
MQTT.Topic$ =
"_DISCONNECTED_"
THEN
PRINT
"MQTT connection lost for IP: ";
MQTT.Message$
ELSEIF
MQTT.Topic$ =
"_WRONG_LOGIN_"
THEN
PRINT
"Login failed for client IP: ";
MQTT.Message$
ENDIF
RETURN
|
To disable the ONMQTT event handler:
Example
OnMQTT OFF
● All
string arguments should be enclosed in quotes.
●
Optional arguments are shown in square brackets [ ].
● The
MQTT broker must be set up and started before using other
functions.
●
Error handling: If a function fails, it may return a negative value
or set an error state. Check the return value or system error state
after calling these functions.
●
Always end your OnMQTT handler with a RETURN statement.
● Use
special characters carefully to efficiently manage your
subscriptions and avoid unnecessary message traffic.
Minimalist example of mini MQTT server
' Setup
broker on port 1883 with login/password and debug mode
enabled
print
MqttBroker.Setup 1883, "mylogin", "mypass", 1
' Start the
MQTT broker with a stack size of 20000 bytes
print
MqttBroker.Start
20000
|
Example of mini MQTT server tracking
connection / disconnections
' Setup
broker on port 1883 with login/password and debug mode
enabled
print
MqttBroker.Setup 1883, "mylogin", "mypass", 1
' Start the
MQTT broker with a stack size of 20000 bytes
print
MqttBroker.Start
20000
' Set up the
MQTT event handler to jump to 'doMQTT' when an event
occurs
onMQTT
doMQTT
' Keep the
program running indefinitely
wait
' MQTT event
handler for processing incoming messages
doMQTT:
' Print the topic of the received
message
print "TOPIC ===
"; MQTT.Topic$
' Print the content of the received
message
print "MESSAGE =
"; MQTT.Message$
' Print the ID of the client that sent the
message
print "CLIENT ==
"; mqtt.Client$
' Return from the event
handler
return
|
Complete example of mini MQTT server
' Setup
broker on port 1883 with login/password and debug mode
enabled
print
MqttBroker.Setup 1883, "mylogin", "mypass", 1
' Start the
MQTT broker with a stack size of 20000 bytes
print
MqttBroker.Start
20000
' Clear any
existing topic subscriptions
print
Mqttbroker.ClearTopics
' Subscribe
to a simple topic
print
Mqttbroker.Subscribe("/AnnexTest")
' Subscribe
using a single-level wildcard for temperature topics from Tasmota
devices
print
Mqttbroker.Subscribe("/tasmota/+/temperature")
' Subscribe
using a multi-level wildcard for all messages in room1 of any
home
print
Mqttbroker.Subscribe("/home/+/room1/#")
' List all
currently subscribed topics
print
mqttbroker.ListTopics
' Set up the
MQTT event handler to jump to 'doMQTT' when an event
occurs
onMQTT
doMQTT
' Keep the
program running indefinitely
wait
' MQTT event
handler for processing incoming messages
doMQTT:
' Print the topic of the received
message
print "TOPIC ===
"; MQTT.Topic$
' Print the content of the received
message
print "MESSAGE =
"; MQTT.Message$
' Print the ID of the client that sent the
message
print "CLIENT ==
"; mqtt.Client$
' Return from the event
handler
return
|
ESP-NOW is a fast, connectionless
communication technology featuring short packet transmission.
ESP-NOW is ideal for smart lights, remote
control devices, sensors and other applications.
This is a special protocol developed by
Espressif that enables the ESP8266 / ESP32 modules to
communicate between themselves easily without any specific network
connection (i.e. no router).
The modules (peers) can inter-communicate even
if they are not connected on a common network, the unique
requirement is to share the same Wifi radio channel.
Practically, each peer of the ESP-NOW network
can send a message to any other peer(s) directly and very fast
without establishing a network link before. After sending, it will
be able to know if the message has been received
In the same way, it can also receive a message
from any other peer.
The ESP-NOW is very fast and simple to put in
place but there are the following limitations :
-
The max number of peers is 20
-
The transmitted message size can be max 250 characters
-
For the ESP32 it does not work in STA mode (only in AP+STA mode)
when used in combination with the ESP8266 (works OK between ESP32
only)
The ESP-NOW network does not use TCP/IP, so
uses the peers MAC addresses to communicate instead of IP
addresses.
As Annex is very versatile, a network module
can use its wifi interface for ESP-NOW and for standard routed IP
WiFi networking, so it can communicate with both types of network
modules, allowing it to function as a kind of “Gateway” between
ESP-NOW and routed WiFi.
Each module (peer) holds a list of ‘receivers”
containing the MAC addresses of all the peers that will receive a
message when using the command
EspNow.Write(msg$)
Functions and commands available :
FUNCTIONS / COMMANDS
|
DESCRIPTION
|
|
starts the ESP-NOW communications
|
|
stops the ESP-NOW communications
|
EspNow.Add_Peer(MAC_add$
[,interface] [,channel])
|
add a peer (module) to the ‘receiver’ list
where interface is 0 = AUTO (default), 1=STA,
2=AP
and channel is any valid channel numbers or 0
= current channel (default)
|
|
delete a peer (module) from the ‘receiver’
list
|
|
write a message to the peers defined in the
list
|
|
write a message to a specific peer defined by
its MAC address
|
All these functions return a value; a non-zero
value indicates that an error has occurred.
If the returned value is not required, the
functions can be used as commands without reading into a
variable.
Example :
Ret
= EspNow.Write(msg$)
used as function
EspNow.Write msg$
used as command (without brackets)
STRING FUNCTIONS
|
DESCRIPTION
|
|
Read the message received
|
|
Read the MAC address of the emitter of the
message received
|
|
Read the MAC address of the device(s) that
didn’t received the message
|
All these functions return a string value
EVENTS
|
DESCRIPTION
|
|
Trigger an event each time a message is
received
|
|
Trigger an event each time that a transmission
error occurs.
This happen, in
particular, when the receiver device has not received the
message
|
These pictures shows some 3 typical ESP-NOW
communication models:



Let’s see an example with 3 modules with 2
acting like sensors and the 3rd as receiver.
The sensor modules will send a message each
second to the receiver.
The receiver will print these messages in the
console.

Code for the SENSOR1 module
'ESP-NOW sensor1 example
RECEIVER_MAC$
= "60:01:94:51:D0:7D" ' MAC address of the receiver
print
"init " ; espnow.begin
' should print 0 if all
OK
espnow.add_peer RECEIVER_MAC$
' set the address of the
receiver
onEspNowError status
' set the place where jump in case of
TX error
timer0 1000,
sendMessage ' trigger a message at each
second
wait
sendMessage:
espnow.write
"Sensor 1 : " + str$(rnd(1000))
' send the
message
return
status:
print
"TX error on "; espnow.error$ ' print the error
return
|
Code for the SENSOR2 module
'ESP-NOW sensor2 example
RECEIVER_MAC$
= "60:01:94:51:D0:7D" ' MAC address of the receiver
print
"init " ; espnow.begin
' should print 0 if all
OK
espnow.add_peer RECEIVER_MAC$
' set the address of the
receiver
onEspNowError status
' set the place where jump in case of
TX error
timer0 1000,
sendMessage ' trigger a message at each
second
wait
sendMessage:
espnow.write
"Sensor 2 : " + str$(rnd(1000))
' send the
message
return
status:
print
"TX error on "; espnow.error$ ' print the error
return
|
Code for the RECEIVER module
'ESP-NOW receiver example
print
"init " ; espnow.begin
' should print 0 if all
OK
onEspNowMsg message
' set the place where jump in case of
message reception
wait
message:
print
"RX:"; espnow.read$;
" from "; espnow.remote$ '
print the message
return
|
Let’s see another example always with 2
sensors and one receiver.
In this case the receiver will retransmit back
to the sensor 1 the message received.
This means that the sensor 1 will receive the
message coming from the sensor 2 and also its own message.
The sensor 1 and the receiver will print the
messages received in the console

Code for the SENSOR1 module
'ESP-NOW sensor example
RECEIVER_MAC$
= "60:01:94:51:D0:7D"
print
"init " ; espnow.begin
' should print 0 if all
OK
espnow.add_peer RECEIVER_MAC$
' set the address of the
receiver
onEspNowMsg message
' set the place where jump in case of
message reception
onEspNowError status
' set the place where jump in case of
TX error
timer0 1000,
sendMessage ' trigger a message at each
second
wait
sendMessage:
espnow.write
"Sensor 1 : " + str$(rnd(1000))
' send the
message
return
message:
print
"RX:"; espnow.read$;
" from "; espnow.remote$ '
print message
return
status:
print
"TX error on "; espnow.error$ ' print the error
return
|
Code for the SENSOR2 module
'ESP-NOW sensor2 example
RECEIVER_MAC$
= "60:01:94:51:D0:7D" ' MAC address of the receiver
print
"init " ; espnow.begin
' should print 0 if all
OK
espnow.add_peer RECEIVER_MAC$
' set the address of the
receiver
onEspNowError status
' set the place where jump in case of
TX error
timer0 1000,
sendMessage ' trigger a message at each
second
wait
sendMessage:
espnow.write
"Sensor 2 : " + str$(rnd(1000))
' send the
message
return
status:
print
"TX error on "; espnow.error$ ' print the error
return
|
Code for the RECEIVER module
'ESP-NOW receiver example #2
SENSOR1_MAC$
= "68:C6:3A:C3:06:DB"
print
"init " ; espnow.begin
' should print 0 if all
OK
espnow.add_peer SENSOR1_MAC$
' set the address of the sensor
1
onEspNowMsg message
' set the place where jump in case of
message reception
wait
message:
msg$
= espnow.read$
rem$
= espnow.remote$
print
"RX:"; msg$; " from ";
rem$
ret
= espnow.write( msg$ +
" Transferred from "
+ rem$ ) ' transfer the
message received
return
status:
print
"TX error on "; espnow.error$ '
print the message
return
|
Let’s see now another example where a sensor
will send a message to 2 receivers :

Code for the SENSOR module
'ESP-NOW sensor example
RECEIVER1_MAC$
= "60:01:94:51:D0:7D"
RECEIVER2_MAC$
= "68:C6:3A:C3:06:DB"
print
"init " ; espnow.begin
' should print 0 if all
OK
espnow.add_peer RECEIVER1_MAC$
' set the address of the receiver
1
espnow.add_peer RECEIVER2_MAC$
' set the address of the receiver
2
onEspNowError status
' set the place where jump in case of
TX error
timer0 1000,
sendMessage ' trigger a message at each
second
wait
sendMessage:
espnow.write
"Sensor : " + str$(rnd(1000))
' send the
message
return
status:
print
"TX error on "; espnow.error$ 'print the error
return
|
Code for the RECEIVER 1 module
'ESP-NOW receiver example
print
"init " ; espnow.begin
' should print 0 if all
OK
onEspNowMsg message
' set the place where jump in case of
message reception
wait
message:
print
"RX:"; espnow.read$;
" from "; espnow.remote$ '
print the message
return
|
Code for the RECEIVER 2 module
'ESP-NOW receiver example
print
"init " ; espnow.begin
' should print 0 if all
OK
onEspNowMsg message
' set the place where jump in case of
message reception
wait
message:
print
"RX:"; espnow.read$;
" from "; espnow.remote$ '
print the message
return
|
—--------------
The ESP32 supports Bluetooth Low Energy (BLE), operating alongside
WiFi, allowing mobile devices such as smartphones, tablets, and
computers to connect. Both free (open) and secure
(password-protected) connections are supported.
●
Server Mode:
In this mode, other devices can connect to the ESP32. This is a
primary mode for BLE on the ESP32.
●
Client Mode:
In client mode, the ESP32 can connect to other BLE server devices,
such as BLE keyboards, sensors, or other peripherals, enabling
versatile two-way communication.
●
Scan:
The ESP32 can scan for all nearby BLE devices, identifying those
within range for potential connections.
UUIDs and Characteristics
The ESP32 is recognized as a Nordic UART device with the following
UUIDs:
●
Service UUID:
6E400001-B5A3-F393-E0A9-E50E24DCCA9E
Identifies the BLE service on the ESP32 as a Nordic UART
service.
●
Characteristic UUIDs:
○
RX Characteristic UUID:
6E400002-B5A3-F393-E0A9-E50E24DCCA9E
Purpose:
Used to receive messages from the connected BLE client. Messages
can be up to 512 characters long.
Note: When defined as part of the BLE service, this UUID
allows message reception through the
ONBLUETOOTH event.
○
TX Characteristic UUID:
6E400003-B5A3-F393-E0A9-E50E24DCCA9E
Purpose: Used to send notifications (messages) from the
ESP32 to the connected BLE client. The maximum message length is 20
characters. This is the faster and preferred method of
communication.
●
Service UUID:
Used to identify the ESP32 as a Nordic UART device. Devices can
discover this service and interact with the associated
characteristics.
●
RX Characteristic:
Used to receive data from the connected BLE client. The maximum
message length is 512 characters.
●
TX Characteristic:
Used for sending notifications from the ESP32 to the connected BLE
client, with a maximum message length of 20 characters. This method
is fast and efficient for real-time communication.
The following commands are available for setting up and managing
the BLE functionality:
Sets the name of
the BLE device as visible to other devices. An optional pin code
can be set for secure connections. The pin must be a 6-digit
number; if a shorter number (e.g., 1) is set, it will be
interpreted as 000001.
Example Usage:
'Sets the BLE device name to "ESP32_Device" with no pin
code.
BLUETOOTH.SETUP
"ESP32_Device"
' Sets the BLE device name to "ESP32_Device" with the pin code
123456.
BLUETOOTH.SETUP
"ESP32_Device", 123456
|
Clears the BLE
configuration, freeing up approximately 20KB of RAM. An error
message might appear in the console, but this is normal and can be
ignored.
Deletes the BLE
configuration, freeing up approximately 40KB of RAM. After
executing this command, the BLE cannot be used again without
restarting the ESP32 module. This is applicable only to the
“classic ESP32.”
Sets the output
power level from 0 to 7, corresponding to -12dBm to +9dBm.
Writes a text
message to the connected device using the notification channel.
Returns a text
message from the connected device.
Returns the
length of the message received from the connected device.
Returns 1 if a
device is connected, or 0 if not.
Returns the status
of the BLE connection, useful in event handling.
Possible return
values:
0:
None
1:
Device connected
2:
Device disconnected
3:
Message received in server mode
4:
Scan terminated
5:
Message received in client mode
Writes data from
an IO BUFFER to the connected device using the notification
channel.
Reads data into
an IO BUFFER from the connected device.
Initiates a BLE
scan for time
seconds.
Returns the list
of devices found during the scan in JSON format.
The following commands support BLE client mode functionality,
enabling the ESP32 to connect to external BLE server devices:
BLUETOOTH.CLIENT
mac,
service_UUID, characteristic_UUID
Connects the
ESP32 to a BLE server device with the specified MAC address,
service UUID, and characteristic UUID. This command is essential
for establishing direct communication with specific BLE
peripherals, such as sensors or keyboards.
Note: The mac
address for this command can be obtained by performing a
BLUETOOTH.SCAN, which lists nearby BLE devices along
with their MAC addresses. Additionally, when the characteristic
UUID is defined in
BLUETOOTH.CLIENT, it enables message reception via the
ONBLUETOOTH event, similar to the RX Characteristic
UUID.
Writes a text
string to the specified characteristic UUID on the connected BLE
server.
BLUETOOTH.CLWRITE_IOBUFF
characteristic_UUID,
(buff_num [, start [,
size]])
Writes data from
an IO BUFFER to a characteristic on the connected BLE server,
useful for managing binary data transfers.
The ESP32 provides an event mechanism to handle BLE-related events
asynchronously:
Defines the event routine for Bluetooth (BLE)
operations. The
BLUETOOTH.STATUS function is useful within this event
handler to determine the specific type of event that occurred.
Examples for the Server Mode:
print
ramfree(1) 'ramfree
before
onbluetooth ble_receive
bluetooth.setup
"bleServer", 1
print
ramfree(1) 'ramfree
after
IOBUFF.DIM(1,
10) = 65, 66, 67, 68, 69, 70, 71, 72, 73,
74
timer0 500,
send_msg
wait
Send_msg:
'bluetooth.write_iobuff(1, 5,
2)
bluetooth.write "_" +
str$(rnd(1000))
+ chr$(10)
return
ble_receive:
print bluetooth.len, bluetooth.status
if bluetooth.status = 3 then
bluetooth.read_iobuff(0)
for z = 1 to
iobuff.len(0)
print iobuff.read(0, z-1),
next z
print
end if
return
|
Receiving parameters from Xiaomi Mijia
“Hacked” temperature sensors where the information are included
into the Advertising message
wlog
ramfree(1)
onbluetooth ble_receive
bluetooth.scan 10
z
= 1
while 1
while (bluetooth.status <> 4)
print z
pause 100
z = z + 1
wend
gosub ble_receive
bluetooth.scan 10
wend
wait
ble_receive:
'print bluetooth.len,
bluetooth.status
select case bluetooth.status
case 1: print "BLE Device
Connected"
case 2: print "BLE Device
Disconnected"
case 3:
bluetooth.read_iobuff(0)
for z = 1 to
iobuff.len(0)
print iobuff.read(0, z-1),
next z
print
case 4:
print "scan terminated"
a$ = bluetooth.scanresult$
' wlog a$
sens1$ = json$(a$,
"ATC_941E4C.Data")
extract_params sens1$, "Bedroom"
sens2$ = json$(a$,
"ATC_C5C5B9.Data")
extract_params sens2$, "Kitchen"
bluetooth.scan 10 ' restart the scan
end
select
return
sub extract_params
(sens$, id$)
if (sens$ <> "not
found") then
a = iobuff.fromhex(0, sens$)
temp = iobuff.read(0, 6)
* 256 + iobuff.read(0, 7)
if (temp >
32767) then temp = temp -
65536
hum = iobuff.read(0, 8)
batt = iobuff.read(0, 9)
cnt = iobuff.read(0, 12)
wlog "sensor: "; id$, "humidity "; hum, "Temperature "; temp/10, "Battery
"; batt, "counter
";cnt
endif
end
sub
|
Example for the client mode
bluetooth.clear
onbluetooth ble_receive
bluetooth.scan 5
pause 6000
' this is the mac address of an HLK LD2450
bluetooth.client
"13:BC:0F:4E:67:E8", "FFF0", "FFF1"
wait
ble_receive:
print
bluetooth.len, bluetooth.status, ramfree(1)
select
case bluetooth.status
case 1
print "------>Device Connected"
case 2
print "======<Device
Disconnected"
case 4
a$ = bluetooth.scanresult$
wlog a$
case 5
bluetooth.READ_IOBUFF(0)
print iobuff.tohex$(0)
end
select
return
|
Example with the extraction of parameters
using IoBuffers
bluetooth.clear
onbluetooth ble_receive
bluetooth.scan 5
pause 6000
' this is the mac address of an HLK LD2450
bluetooth.client
"13:BC:0F:4E:67:E8", "FFF0", "FFF1"
wait
ble_receive:
print
bluetooth.len, bluetooth.status, ramfree(1)
select
case bluetooth.status
case 1
print "------>Device Connected"
case 2
print "======<Device
Disconnected"
case 4
a$ = bluetooth.scanresult$
wlog a$
case 5
bluetooth.READ_IOBUFF(0)
print iobuff.tohex$(0)
if iobuff.len(0)
= 30 then
buff$ = iobuff.tohex$(0)
k = iobuff.read(0,4)
+ iobuff.read(0,5)
* 256
if (k >
32767) k = -k+32768
x = k
k = iobuff.read(0,6)
+ iobuff.read(0,7)
* 256
if (k >
32767) k = -k+32768
y = k
k = iobuff.read(0,8)
+ iobuff.read(0,9)
* 256
if (k >
32767) k = -k+32768
speed = k
dist = sqr(x^2
+ y^2)
k = iobuff.read(0,10)
+ iobuff.read(0,11)
* 256
if (k >
32767) k = -k+32768
r = k
print x, y, speed, dist,
r
end if
end
select
return
|
Annex implements the direct support for the
TELEGRAM messenger
Using these commands/functions it is possible
to:
-
Send full text messages
-
Send html styled text
messages
-
Get user Ident
-
Get text messages
-
Get text messages async
-
Send Images
For more information please refer to the official
telegram API
https://core.telegram.org/bots/api
The commands are :
Set the Telegram Token ID
TELEGRAM.SetToken
"token"
Set the operating mode
TELEGRAM.SetMode 0
'set the basic https communications (this is the
default)
TELEGRAM.SetMode 1
'set the https communication using a certificate
(internal)
Set the max time that the commands will wait for an
answer from the telegram server
TELEGRAM.SetWait 10
‘ set the max time at 10 seconds (the
default is 10 seconds)
Receive incoming messages update in json format but
in async mode.
It uses the same event
ONWGETASYNCused by the
command
WGETASYNC
TELEGRAM.getUpdatesAsync
The functions are :
A simple method for testing your bot's auth token.
Returns basic information about the bot in form of a
User object.
ret$
= TELEGRAM.getMe$
Send a text message. If the optional html is 1, the
text can be formatted using some html tags
ret$
= TELEGRAM.sendMessage$( chat_id, "message" [, html] )
More informations here https://core.telegram.org/bots/api#html-style
Receive incoming messages update in json
format
ret$
= TELEGRAM.getUpdates$
Send an image; the image can be in jpeg, bmp, gif
or png format
ret$
= TELEGRAM.sendImage$( chat_id, image_path$)
Example of basic commands
telegram.settoken
"1234567890:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdef"
telegram.setwait
10
telegram.setmode
0
wlog
telegram.getMe$
'get the
user’s informations
wlog
telegram.getUpdates$
'get the new
messages
'Send a
message to the chat_id 1234567890
wlog
telegram.sendmessage$(1234567890,
"Hello, world! " + str$(rnd(1000)))
'Send
pictures from the disk to the chat_id 1234567890
wlog
telegram.sendimage$(1234567890,
"/images/sam.png")
wlog
telegram.sendimage$(1234567890,
"/images/poisson.bmp")
'Prepare an
HTML formatted message
nl$
=
chr$(10)
b$
=
||
b$
=
b$
+
|<b>bold</b>,
<strong>bold</strong>| +
nl$
b$
=
b$
+
|<i>italic</i>,
<em>italic</em>| +
nl$
b$
=
b$
+
|<u>underline</u>,
<ins>underline</ins>| +
nl$
b$
=
b$
+
|<s>strikethrough</s>,
<strike>strikethrough</strike>,
<del>strikethrough</del>| +
nl$
b$
=
b$
+
|<b>bold
<i>italic bold <s>italic bold strikethrough</s>
<u>underline italic bold</u></i>
bold</b>| +
nl$
b$
=
b$
+
|<a
href='http://www.example.com/'>inline URL</a>|
+
nl$
b$
=
b$
+
|<a
href='tg://user?id=123456789'>inline mention of a
user</a>| +
nl$
b$
=
b$
+
|<code>inline
fixed-width code</code>| +
nl$
b$
=
b$
+
|<pre>pre-formatted
fixed-width code block</pre>| +
nl$
b$
=
b$
+
|<pre><code
class='language-python'>pre-formatted fixed-width code block
written in the Python programming
language</code></pre>|
'Send the
message in HTML format
wlog
telegram.sendmessage$(1234567890,
b$, 1)
end
|
Example of echo bot (reply the command
received)
telegram.settoken
"1234567890:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdef"
telegram.setwait
10
telegram.setmode
0
onwgetasync asynco
'Get the
update each 5 seconds
timer0 5000,
getmessages
wait
getmessages:
telegram.GetUpdatesAsync
return
'Receive the
messages
asynco:
r$
= WGETRESULT$
wlog r$
text$
= json$(r$,
"text")
if
(text$ <> "not found") then
c$
= json$(r$,
"chat.id") 'get the chat_id
wlog
telegram.sendmessage$(val(c$),
"echo : " + text$)
end
if
return
|
LoRa is a wireless modulation technique
derived from Chirp Spread Spectrum (CSS) technology. It
encodes information on radio waves using chirp pulses - similar to
the way dolphins and bats communicate!
LoRa modulated transmission is robust against
disturbances and can be received across great distances.
LoRa is ideal for applications that transmit
small chunks of data with low bit rates. Data can be transmitted at
a longer range compared to technologies like WiFi, Bluetooth or
ZigBee.
These features make LoRa well suited for
sensors and actuators that operate in low power mode.
LoRa can be operated on the license free
sub-gigahertz bands, for example, 915 MHz, 868 MHz, and 433
MHz.
A detailed description on LoRa can be found
here
The WiFi LoRa 32 module is supported, which
includes the SX127x Heltec Module.
This module includes the SX127x LoRa
modules

As it has a specific configuration for the SPI
bus, the Config Menu includes a dedicated choice

An SDCard can be connected on the module using
the following pinout :

The OLED display present on the module is
supported with the
OLED.xxx functions already implemented.
As this OLED has an additional RST pin, the
corresponding GPIO16 must be put to 1 before use.
FUNCTIONS / COMMANDS
|
DESCRIPTION
|
|
Defines the pins to be used for the module
SX127x.
The SPI pins are the default pins defined for
the module
|
|
Initialise the driver with the specified
frequency.
The frequency must be specified in Hz.
Returns 1 if OK or 0 in case of error.
Example
Print LoRa.Begin(886e6) ‘for 886 Mhz
|
|
Terminates the operations
|
|
Start the sequence of sending a packet.
Returns 1 if OK or 0 in case of error.
|
|
Write a message into the lora packet
Returns the number of character written
|
|
Terminate the packet and send it
|
|
Puts the radio in continuous receive mode
|
|
Returns the RSSI of the received packet
|
|
Returns the estimated SNR of the received
packet in dB
|
|
Put the radio in idle (standby) mode.
|
|
Put the radio in sleep mode.
|
|
Change the TX power of the radio.
Can be from 0 to 20 dBm
The default value is`14`
|
LoRa.SpreadFactor factor
|
Change the spreading factor of the radio.
Supported values are between `6` and `12`
The default value is`11`
|
LoRa.SignalBandwidth band
|
Change the signal bandwidth of the radio (in
Hz)
Supported values are `7.8E3`, `10.4E3`,
`15.6E3`, `20.8E3`, `31.25E3`, `41.7E3`, `62.5E3`, `125E3`, and
`250E3`.
The default value is`125E3`
|
LoRa.CodingRate rate
|
Change the coding rate of the radio.
Supported values are between `5` and `8`,
these correspond to coding rates of `4/5` and `4/8`. The coding
rate numerator is fixed at `4`.
The default value is ‘5’
|
LoRa.PreambleLen len
|
Change the preamble length of the radio.
Supported values are between `6` and
`65535`.
The default value is ‘8’
|
|
Change the sync word of the radio.
‘Word’ is a byte value to use as the sync
word
The default value is `&h34`
|
|
Enable or disable CRC usage
‘enable’ can be 1 or 0 (enable / disable)
By default a CRC is not used.
|
|
Define a label where the program will jump
when an LoRa message is received
The script branch
must be terminated with ‘RETURN’.
To disable OnLora OFF
|
|
Returns the LoRa message received
|
Examples
Simple transmitter program
' LoRa test program
' Using the WIFI LoRa 32 module
' Send a simple message to the receiver
' use the default values
LoRa.Setup 18, 14,
26 ' SS, RESET,
DIO0
print
LoRa.Begin(886e6)
' 886 MHz
for pkt
= 1 to 10000
LoRa.BeginPacket
LoRa.Print "SEND:" +
str$(pkt)
LoRa.EndPacket
pause 1000
next pkt
|
Simple receiver program
' LoRa test program
' Using the WIFI LoRa 32 module
' Receive a simple message from the sender
' and prints in the wlog console
' use the default values
LoRa.Setup 18, 14,
26 ' SS, RESET,
DIO0
print
LoRa.Begin(886e6)
' 886 MHz
onLoRa receive
LoRa.Receive
wait
receive:
r$
= LoRa.Message$
wlog r$,
ramfree, LoRa.RSSI, LoRa.SNR
return
|
More complex example using OLED with
transmission and receptions
' LoRa test program
' Using the WIFI LoRa 32 module
' Send and receive messages to another module
' running the same code
'''''''''''''''''''''''''
' set the RST pin of the OLED to 1
pin.mode 16,
output
pin(16)
= 1
I2C.SETUP 4, 15
' set I2C port on pins 4 and
15
Oled.Init 2, 1
' initialise the
OLED
Oled.Cls
' clear the screen
Oled.Font 2
Oled.Color 1
Oled.Print 0, 10,
"LORA XMT/RCV"
pin.mode 25,
output ' enable the internal white
led
LoRa.Setup 18, 14,
26 ' SS, RESET,
DIO0
print
LoRa.Begin(886e6)
' 886 MHz
LoRa.SpreadFactor 7
LoRa.SignalBandwidth 125e3
LoRa.SyncWord
&h88 'default if
&h34
LoRa.TXpower 020
onLoRa receive
LoRa.Receive
pkt
= 0
timer0 1000, send
'send a message each
second
wait
receive:
r$
= LoRa.Message$
print r$,
ramfree, LoRa.RSSI, LoRa.SNR
Oled.Cls
Oled.Font 2
Oled.Print 0, 10,
"LORA XMT/RCV"
Oled.Font 1
Oled.Print 0, 30,
r$
Oled.Print 0, 40,
"RSSI: " + str$(LoRa.RSSI)
Oled.Print 0, 50,
"SNR: " + str$(LoRa.SNR)
pin(25)
= 1 '
blinks the internal white led
Oled.Refresh 0
pause 100
pin(25)
= 0
return
send:
LoRa.BeginPacket
LoRa.Print "SEND:" +
str$(pkt)
+ "
" + str$(LoRa.RSSI)
LoRa.EndPacket
pkt = pkt + 1
return
|
Annex implements support
for MODBUS TCP in client mode. The underlying library (eModbus) is
built on an asynchronous model where all communication occurs in
separate tasks, enabling Modbus requests and responses to be
non-blocking. Answer reception is handled asynchronously via an
event (the
WGETASYNC event). To maintain simplicity, only a select
few commands have been implemented, each with a simple syntax.
The command
MODBUS.CONNECT is used to establish a connection to a
Modbus device or server. It requires specifying the IP address of
the device.
Optionally, you can also specify the port
number to connect to. Additionally, you can configure timeout and
idle timeout parameters to control how long the system waits for
responses and when it considers a connection idle. These settings
help manage communication and resource usage efficiently.
The complete syntax is :
MODBUS.CONNECTIP$,
[port] [,timeout] [,idleTimeout]
Where:
●
IP$: This parameter specifies the IP address of the
device or server to which the Modbus connection will be
established. It's a required parameter, as it defines the target
for the connection.
●
port: This optional parameter specifies the port
number to connect to on the target device. If not provided, it
defaults to the standard Modbus TCP port (port 502). It allows for
connecting to a specific port if the Modbus server is configured to
listen on a non-standard port.
●
timeout: This optional parameter defines the maximum
time the library will wait for a response after sending a request.
If not provided, it uses a default timeout value of 2000ms (2sec).
It ensures that the communication doesn't hang indefinitely waiting
for a response from the server.
●
idleTimeout: This optional parameter sets the
duration of inactivity allowed before considering the connection
idle and potentially closing it. If not provided, the library uses
a default idle timeout value of 60000ms (60sec). It helps in
managing resources by closing connections that are inactive for a
specified period.
To disconnect from the device or server, the
command is
To note that the disconnection will happen
automatically after an idleTimeout period of
inactivity (by default 60 seconds)
The token concept
The token concept involves assigning a
user-defined token value to each request. This token is associated
with the request and is subsequently returned in the callback. The
token remains unchanged throughout the process, allowing users to
easily correlate requests with their corresponding responses.
Consider an application with multiple
ModbusClients, each interacting with different types of Modbus
servers or with several async requests enqueued. If you wish to
handle all responses with a single event function, irrespective of
the server origin, distinguishing between responses becomes
essential.
By utilising the token assigned during request
initiation, you can precisely identify and match responses to their
respective requests, regardless of the server they originate
from.
Requests
Annex implements a common
MODBUS.REQUEST command to set up and enqueue a
request.
MODBUS.REQUEST
token, serverID, functionCode [,p1] [,p2]
[,p3]
This command enables the sending of various
kinds of requests depending on the number of arguments specified.
The request is added to a queue of a maximum of 100 elements, and
control is returned to the program without blocking the execution.
In async mode, the library will send the elements present in the
queue depending on the capacity of the device or server.
The token argument is a 32-bit number
provided at request time, which will be returned exactly as it is
in the response.
The argument serverID must be an
8-bit number, while the argument functionCode must
contain a value as defined in the table below :
FUNCTION CODE
|
VALUE
|
ANY_FUNCTION_CODE
|
&h00
|
READ_COIL
|
&h01
|
READ_DISCR_INPUT
|
&h02
|
READ_HOLD_REGISTER
|
&h03
|
READ_INPUT_REGISTER
|
&h04
|
WRITE_COIL
|
&h05
|
WRITE_HOLD_REGISTER
|
&h06
|
READ_EXCEPTION_SERIAL
|
&h07
|
DIAGNOSTICS_SERIAL
|
&h08
|
READ_COMM_CNT_SERIAL
|
&h0B
|
READ_COMM_LOG_SERIAL
|
&h0C
|
WRITE_MULT_COILS
|
&h0F
|
WRITE_MULT_REGISTERS
|
&h10
|
REPORT_SERVER_ID_SERIAL
|
&h11
|
READ_FILE_RECORD
|
&h14
|
WRITE_FILE_RECORD
|
&h15
|
MASK_WRITE_REGISTER
|
&h16
|
R_W_MULT_REGISTERS
|
&h17
|
READ_FIFO_QUEUE
|
&h18
|
ENCAPSULATED_INTERFACE
|
&h2B
|
USER_DEFINED_41
|
&h41
|
USER_DEFINED_42
|
&h42
|
USER_DEFINED_43
|
&h43
|
USER_DEFINED_44
|
&h44
|
USER_DEFINED_45
|
&h45
|
USER_DEFINED_46
|
&h46
|
USER_DEFINED_47
|
&h47
|
USER_DEFINED_48
|
&h48
|
USER_DEFINED_64
|
&h64
|
USER_DEFINED_65
|
&h65
|
USER_DEFINED_66
|
&h66
|
USER_DEFINED_67
|
&h67
|
USER_DEFINED_68
|
&h68
|
USER_DEFINED_69
|
&h69
|
USER_DEFINED_6A
|
&h6A
|
USER_DEFINED_6B
|
&h6B
|
USER_DEFINED_6C
|
&h6C
|
USER_DEFINED_6D
|
&h6D
|
USER_DEFINED_6E
|
&h6E
|
If you specify an invalid server ID or a Modbus standard function
code taking a different number of parameters, an error message is
sent to Serial and the message is not generated.
Parameters to known standard Modbus messages are checked for
conformity.
Message with no parameter
MODBUS.REQUEST token,
serverID,
functionCode
This is usable to set up Modbus standard
messages for the Modbus function codes requiring no additional
parameter, as 0x07, 0x0B, 0x0C and 0x11.
Message with 1 parameter
MODBUS.REQUEST token,
serverID,
functionCode, p1
There is one standard Modbus message requiring
exactly one 16 bit parameter: &h18, READ_FIFO_QUEUE. This
format will help set it up correctly, but of course may be used for
any other proprietary function code with the same signature. Please
note that in this case the p1 parameter will not be
range-checked.
Message with 2 parameters
MODBUS.REQUEST token,
serverID,
functionCode, p1, p2
This format will be one of the most used
throughout, as the most relevant Modbus messages have this
signature (taking two 16 bit parameters).
These are the Function Codes &h01,
&h02, &h03, &h04, &h05 and &h06.
Message with 3 parameters
MODBUS.REQUEST token,
serverID,
functionCode, p1, p2, p3
Modbus standard function code &h16
(MASK_WRITE_REGISTER) does take three 16 bit arguments.
Sending Custom Messages
In addition to the standard Modbus commands,
there's also a provision for sending custom messages.
This is facilitated by another variant of this
command, which allows for the transmission of raw messages in the
form of a sequence of hex bytes directly onto the Modbus bus.
The exact syntax for sending a raw message
is:
MODBUS.REQUEST token,
raw_message$
Where
●
token is the token used for the request
●
raw_message$ is a string composed of a sequence of hex
bytes, such as "01 03 00 FD 00 01". The spaces are optional and can
be removed (i.e. “01 03 00 FD 00 01” or “010300FD0001” are
equivalent). The CRC (Cyclic Redundancy Check) is automatically
calculated.
This feature provides flexibility for
implementing custom communication protocols or executing advanced
operations that may not be covered by the standard Modbus
commands.
Additionally, support is extended to Modbus
RTU, a widely used variant of the Modbus protocol. Modbus RTU
operates over serial communication, making it suitable for
applications where wired connections are preferred or where
long-distance communication is required. It offers robustness and
reliability, especially in industrial environments.
The command
modbus.setupRTU is used to configure the RTU interface
connection.
The syntax is as follows:
MODBUS.SetupRTURX_pin,
TX_pin, RE_DE_pin, ["BBBB,P,D,S"]
Where:
●
RX_pin: The pin used for receiving data.
●
TX_pin: The pin used for transmitting data.
●
RE_DE_pin: The pin where the RE/DE wire of the
attached RS485 adapter is connected
●
BBBB: Defines the baud rate, which can be any valid
serial speed (e.g., 9600, 19200, ..., 115200).
●
P: Specifies the parity, which can be N (None), E
(Even), or O (Odd).
●
D: Indicates the number of data bits, which can be 7
or 8.
●
S: Denotes the number of stop bits, which can be 1 or
2.
By default, the
configuration is set to "9600,N,8,1".
Modbus RTU utilises RS485 for serial
communication. While microcontrollers typically use UART for serial
communication, an external RS485 adapter is necessary for
Modbus RTU. These adapters convert UART signals to the electrical
specifications of RS485, enabling communication over extended
distances and with multiple devices on the bus due to its
differential signalling. RS485 adapters are readily available
and cost-effective.
Similar to Modbus TCP, Modbus RTU operates
asynchronously. Reception of data also occurs asynchronously using
the same event mechanism, ensuring a consistent approach to
communication handling across both protocols. Modbus RTU also
leverages the same concept of tokens, where communication tasks are
executed independently, promoting efficiency and reliability.
To send messages, the same logic of
MODBUS.REQUEST is applied, except that the command is
named
This ensures uniformity in the command
structure while facilitating communication over Modbus RTU.
Reception of the data
The reception of the data
happens inside a
WGETASYNC event and the message can be retrieved inside
the variable
WGETRESULT$
The received message is composed of a sequence
of hexadecimal bytes (2 hex chars) separated by spaces.
This is an example of received message,
correspondent to the request
MODBUS.REQUEST 1234, 1,
3, 5:
1234
01 03 02
00 01
Each message starts with
the token used in the corresponding request (1234) followed by the message content
(01 03 02 00
01).
The content always starts
with the serverID (01), the
functionCode (03) and the
data (02 00 01).
Here's a received message
corresponding to the request
MODBUS.REQUEST 4567, 1,
6, 3, 1:
4567 01
06 00
03 00 01
As in the previous example, the message starts
with the token used in the corresponding request (4567) followed by the serverID
(01), the functionCode
(06) and the data
(00 03 00 01).
In case of error, the message content will be
replaced with a detailed error message.
Here's a received error message
1234
Error response: E0 -
Timeout
TCP Example:
'MODBUS TCP example - write and read in the HOLD_REGISTER
0
READ_HOLD_REGISTER
= 3
WRITE_HOLD_REGISTER
= 6
SERVER_ID
= 1
onWgetAsync modbus_received
'set the event handler
function
modbus.connect
"192.168.1.130" 'address of the
remote server
for z
= 0 to 1000
'write to the address
0
modbus.request 1234, SERVER_ID,
WRITE_HOLD_REGISTER, 0, z
'read from the address 0
modbus.request 4567, SERVER_ID,
READ_HOLD_REGISTER, 0, 1
pause 1000
next z
end
modbus_received:
r$
= WGETRESULT$
print r$
token$
= word$(r$,
1) 'extract the token (first
word)
if
(token$ ="4567")
then ' if the token correspond to the read
request
if (word$(r$,
2) <> "Error")
then 'if is not an error
'assemble the 2 bytes in one 16 bits
word
value$ = "&h"+
word$(r$, 5)
+ word$(r$,
6)
wlog val(value$)
'converts from hex to
integer
end if
endif
return
|
The pictures below show a typical RS485
adapter that can be used with the ESP32


The following schematic illustrates how to
connect this adapter to the ESP32:

The picture below shows a typical device
(AHT20 temperature / humidity sensor) that can be connected using
the MODBUS RTU

This example shows how to read temperature and
humidity data from the device shown above
'Example of MODBUS RTU with the sensor N434E01 AHT20
READ_INPUT_REGISTER
= 4
SERVER_ID
= 1
onWgetAsync modbus_received
'set the event handler
function
modbus.setupRTU 2,5,26
' by default is
9600,N,8,1
do
modbus.requestRTU 1234, SERVER_ID,
READ_INPUT_REGISTER, 0, 2
pause 1000
loop
end
modbus_received:
r$
= WGETRESULT$
'wlog r$,ramfree(1)
token$
= word$(r$,
1) 'extract the token (first
word)
if
(token$ ="1234")
then ' if the token correspond to the read
request
if (word$(r$,
2) <> "Error")
then 'if is not an error
'assemble the 2 bytes in one 16 bits
word
temp$ = "&h"+
word$(r$, 5)
+ word$(r$,
6)
'assemble the 2 bytes in one 16 bits
word
hum$ = "&h"+
word$(r$, 7)
+ word$(r$,
8)
wlog "Temp:"; val(temp$)/10 ,
"Hum:"; val(hum$)/10
end if
endif
return
|
Regular expressions (regex) are sequences of
characters that form a search pattern, used to match and manipulate
text strings based on certain rules. They provide a powerful way to
search, replace, and validate strings using patterns that define
sets of strings, characters, or character classes. Regular
expressions are widely used in text processing tasks, such as
pattern matching, data validation, and text manipulation, across
various programming languages and software applications.
The current implementation processes regular
expressions identical in syntax to Lua's string.match, string.find,
and similar functions. This adaptation allows seamless integration
with Lua code, facilitating familiar usage patterns for users
accustomed to Lua's regular expression syntax.
The regex functions available are :
ret =
regex.find(string$, pattern$, [start],
[result$])
This function retrieves the position of the
substring within the string$ that matches the specified
pattern$, starting from the specified start position.
If a capture is designated in the pattern$ (further
elaborated below) the function returns the position of the captured
substring and if the result$ string variable is specified,
the captured substring will be copied into it.
ret =
regex.match(string$, pattern$,
[result_array$()])
This function returns the number of captures
designated in the pattern$ (further elaborated below) that
match in the string$. If the array variable
result_array$() is specified, all captures are copied into
the array.
The standard patterns
(character classes) you can search for are:
. --- (a dot) represents
all characters.
%a --- all letters.
%c --- all control
characters.
%d --- all digits.
%l --- all lowercase
letters.
%p --- all punctuation
characters.
%s --- all space
characters.
%u --- all uppercase
letters.
%w --- all alphanumeric
characters.
%x --- all hexadecimal
digits.
%z --- the character with hex
representation 0x00 (null).
%% --- a single '%'
character.
%1 --- captured pattern
1.
%2 --- captured pattern 2 (and
so on).
%f[s] transition from not
in set 's' to in set 's'.
%b() balanced
nested pair ( ... ( ... ) ... )
Important!
- the uppercase
versions of the above represent the complement of the class. eg. %U
represents everything except uppercase letters, %D
represents everything except digits.
There are some "magic
characters" (such as %) that have special meanings. These
are:
^ $ ( ) % . [ ] * + -
?
If you want to use those in a
pattern (as themselves) you must precede them by a %
symbol.
eg. %% would match a single %
.
In practice, it is safe to put
% in front of any non-alphanumeric character. If in doubt, put a %
in front of a special character.
Sets
You can build your own pattern
classes (sets) by using square brackets, eg.
[abc] ---> matches a, b or
c
[a-z] ---> matches lowercase
letters (same as %l)
[^abc] ---> matches anything
except a, b or c
[%a%d] ---> matches all
letters and digits
[%a%d_] ---> matches all
letters, digits and underscore
[%[%]] ---> matches square
brackets (had to escape them with %)
You can use pattern classes in
the form %x in the set. If you use other characters (like periods
and brackets, etc.) they are simply themselves.
You can specify a range of
characters inside a set by using simple characters (not pattern
classes like %a) separated by a hyphen. For example, [A-Z] or
[0-9]. These can be combined with other things. For example
[A-Z0-9] or [A-Z,.].
The end-points of a range must
be given in ascending order. That is, [A-Z] would match upper-case
letters, but [Z-A] would not match anything.
A hyphen at the start or end
of a set is itself (matches a hyphen).
You can negate a set by
starting it with a "^" symbol, thus [^0-9] is everything except the
digits 0 to 9. The negation applies to the whole set, so [^%a%d]
would match anything except letters or digits. In anywhere except
the first position of a set, the "^" symbol is simply
itself.
Inside a set (that is a
sequence delimited by square brackets) the only "magic" characters
are:
] ---> to end the set,
unless preceded by %
% ---> to introduce a
character class (like %a), or magic character (like "]")
^ ---> in the first position
only, to negate the set (eg. [^A-Z)
- ---> between two
characters, to specify a range (eg. [A-F])
Thus, inside a set, characters
like "." and "?" are just themselves.
The repetition characters,
which can follow a character, class or set, are:
+ ---> 1 or more
repetitions (greedy)
* ---> 0 or more
repetitions (greedy)
- ---> 0 or more
repetitions (non greedy)
? ---> 0 or 1
repetition only
A "greedy" match will match on
as many characters as possible, a non-greedy one will match on as
few as possible.
The standard "anchor"
characters apply:
^ ---> anchor to start
of subject string (must be the very first character)
$ ---> anchor to end
of subject string (must be the very last
character)
For example:
^You
see ---> string must start with "You
see"
experience$ --->
string must end with "experience"
^Tick$
---> string must be exactly "Tick" with no other
characters
You can also use round
brackets to specify "captures":
You see (.*) here
Here, whatever matches (.*)
becomes the first capture.
You can also refer to matched
substrings (captures) later on in an expression:
wlog
regex.find("You see dogs
and dogs", "You see (.*) and
%1", , z$)'print 9 (pos
of dogs)
wlog
z$'print
dogs
wlog
regex.find("You see dogs
and cats", "You see (.*) and
%1", , z$)'print 0 (not
found)
wlog
z$'empty
string
This example shows how you can
look for a repetition of a word matched earlier, whatever that word
was ("dogs" in this case).
As a special case, an empty
capture string returns as the captured pattern, the position of
itself in the string. eg.
wlog
regex.find("You see dogs and cats", "You .* ()dogs .*")
'print 9 (pos of dogs)
What this is saying is that
the word "dogs" starts at column 9.
There is a limit of 32
captures that can be returned.
Balanced
sequences
Finally you can look for
nested "balanced" things (such as parentheses) by using %b, like
this:
print (string.find ("I see a
(big fish (swimming) in the pond) here",
"%b()")) --> 9 41
After %b you put 2 characters,
which indicate the start and end of the balanced pair. If it finds
a nested version it keeps processing until we are back at the top
level. In this case the matching string was "(big fish (swimming)
in the pond)".
A "frontier" (or boundary)
pattern is used to assert a transition from one set of characters
to another (eg. non-letters to letters, or non-digits to digits).
This can be useful to detect words, such as "log" but omit
"blog" or "logging".
A frontier is specified as
%f[set] and matches on a transition from not-in-set to in-set. For
example, to match "log" on its own:
wlog
regex.find ("There is a log here", "%f[%a]log%f[%A]")
'print 12 (pos of log)
wlog
regex.find ("There is a blog here", "%f[%a]log%f[%A]")
'print 0 (not found)
wlog
regex.find ("There is a logging here", "%f[%a]log%f[%A]")
'print 0 (not found)
The first frontier ("%f[%a]")
matches on the transition from not-letters to letters. The second
frontier ("%f[%A]") matches on letters to not-letters. Effectively
this gives you a word boundary match.
Using the function regex.match is
possible to see if a string matches captures inside a given
pattern.
Example :
wlog
regex.match ("You see dogs and cats" , "(dogs)")
'print 1 (1 capture)
wlog
regex.match ("You see dogs and cats" , "(dogs).*(cats)")
'print 2 (2 captures)
wlog
regex.match ("You see dogs and cats" , "(dos)")
'print 0 (no capture)
But this function has also a more powerful
functionality enabling it to extract multiple captures from a given
string.
Example:
str$
= "date:1/11/2022 time:12:10:55 lat:N43.6047
long:E1.4442 elev:151"
pat$
= "date:(%d+/%d+/%d+) time:(%d+:%d+:%d+)
lat:([NS][%d%.]+) long:([EW][%d%.]+)
elev:(%d+)"
wlog
regex.match(str$ , pat$,
a$())
'print 5 (5 captures)
for z
= lbound(a$())
to ubound(a$())
wlog a$(z)
'print 1/11/2022 12:10:55 N43.6047 E1.4442 151
next z
This function creates a new array (a$, in this
example) that contains all the captures.
Is the array is already existing, its content
will be replaced (and automatically redimensioned)

The M5Stack Tough is a
Waterproof ESP32 Module that includes a combination of 8M PSRAM +
16M FLASH memory, a rich set of peripherals and an expansion
interface.
M5 TOUGH has full-coverage support dustproof
and waterproof`, which can ensure the stability of circuit
operation even in complex industrial applications. The M5 TOUGH is
ideal for industrial control, smart buildings, outdoor node data
acquisition, and other applications.
The peripherals included
are :
● 2
inches LCD capacitive Multi-touch screen
●
NS4168 16 bits I2S power amplifier + 1W speaker
●
TFCard slot
●
AXP192 power management chip
●
BM8563-RTC clock
●
RS485 interface
More detailed information
can be found on the official page
This module is fully
supported by Annex32, including the power management functions
through a set of dedicated commands / functions starting with the
prefix
M5Tough.
The Config Menu includes a
dedicated choice for this module, including the selection of the
right TFT driver

● The
touch screen is supported and operational with all the GUI
functions and requires no calibration
● The
SDcard is supported and can be enabled
● The
I2S audio chip is automatically configured for using the internal
speaker.
● The
RTC is supported using the same
RTC.xxx functions already implemented
● The
power and battery management, including the sleep functionalities,
are fully supported
FUNCTIONS / COMMANDS
|
DESCRIPTION
|
|
Returns the charge status of the battery in
%
|
|
Returns the battery voltage in Volts
|
|
Returns the battery current in mA.
A positive value means that the battery is
charging
A negative value means that the battery is
discharging
|
|
Returns the input voltage in Volts
|
|
Returns the input current in mA
|
|
Returns the VBUS voltage in Volts
|
|
Returns the VBUS current in mA
|
|
Returns the battery charge current in mA.
|
|
Returns the battery power in mW
|
|
Returns the AXP192 internal temperature in
°C
|
|
Returns the APS voltage in Volts ????
|
|
Returns the Axp192 state
Bit Value
|
Description
|
128
|
isACIN()
|
32
|
isVBUS()
|
4
|
isCharging()
|
|
|
Select the power for the TFT (1 = on, 0 =
off)
|
|
Select the power for the internal speaker (1 =
on, 0 = off)
|
|
Select the input power mode :
0 - From USB or Battery
1 - From external input
|
|
Turn off the power from the module and power
on it again after
sec seconds.
The max time is 15300 seconds (approx
4.25 Hours)
During the power off time, it can be restarted
using the power button.
This mode remove completely the power from
the module (minimal power consumption) as it rely on the external
RTC for restarting the power (and not using the deep sleep mode of
the ESP32)
|
|
Puts the module in light sleep for
sec seconds
|
|
Puts the module in deep sleep for
sec seconds
|
Example
' Example for the M5 Tough
' The RTC must be set before running this
' program to show the correct time
wlog
rtc.time$
wlog
rtc.date$
wlog
"BATLEVEL ", M5Tough.BATLEVEL
wlog
"BATVOLTAGE ", M5Tough.BATVOLTAGE
wlog
"BATCURRENT ", M5Tough.BATCURRENT
wlog
"VINVOLTAGE ", M5Tough.VINVOLTAGE
wlog
"VINCURRENT ", M5Tough.VINCURRENT
wlog
"VBUSVOLTAGE ", M5Tough.VBUSVOLTAGE
wlog
"VBUSCURRENT ", M5Tough.VBUSCURRENT
wlog
"AXPTEMP ", M5Tough.AXPTEMP
wlog
"BATPOWER ", M5Tough.BATPOWER
wlog
"BATCHGCURRENT ", M5Tough.BATCHGCURRENT
wlog
"APSVOLTAGE ", M5Tough.APSVOLTAGE
wlog
"AXPSTATE", M5Tough.AXPSTATE
|
The AnnexCam is a special version of Annex32
specially developed for camera support.
It is essentially the same firmware as
the Annex32 except that many drivers have been removed to gain
space and memory.
The main reason is because the camera itself
uses practically all the ESP32 pins available leaving very few pins
for the I/O.
The ESP32-CAM module and the M5Camera model B
are supported.
These modules include an OV2640 camera and an
additional PSRAM for big size pictures.
The actual implementation allows you to use
this module to take snapshots or use it as a web camera while
running basic scripts in parallel.

For the ESP32-CAM, AnnexCam follows the pinout
of the SDCARD that is wired differently compared to the
M5stack..

AnnexCAM supports the SDCARD for the ESP32-CAM
using the SPI mode wiring.
This permits to free 2 pins, the GPIO4 and the
GPIO12 that can be used as general I/O.
As the pin GPIO4 is already connected to the
“Flash” led, the unique I/O pin available is the GPIO12.
In addition, the GPIO1 and GPIO3 (serial TX
and RX) can also be used as general I/O pins.
The M5CAMERA do not supports the SDCARD and
exposes only 2 pins (GPIO4 and GPIO13) via the GROVE connector.
Only the model B is actually supported.

FUNCTIONALITY
|
ENABLED
|
TFT
display
|
❌
|
QRCODE
|
❌
|
ESPNOW
|
✅
|
PID
|
❌
|
ETHERNET
|
❌
|
CONVERT
|
✅
|
MQTT
|
✅
|
OLED
|
❌
|
APDS9960
|
❌
|
BME280
|
✅
|
INFRARED
|
❌
|
PLAY
(WAV, MP3, VOICE)
|
❌
|
NEOPIXEL
|
❌
|
VL53L0X
|
❌
|
RFID
|
❌
|
FREQUENCY METER
|
❌
|
IOBUFFER
|
✅
|
WDT
|
✅
|
MPU9250
|
❌
|
MPU6886
|
❌
|
MPU6050
|
❌
|
FUSION
ALGO
|
❌
|
BNO055
|
❌
|
PCA9685
|
❌
|
TM1637
AND TM1638
|
❌
|
MAXDISPLAY
|
❌
|
BLUETOOTH
|
❌
|
CCS811
|
✅
|
HDC1080
|
✅
|
TELEGRAM
|
✅
|
The AnnexCam version introduce the following
functions:
Ret
= CAMERA.SETUP(framesize)
Initialise and set the initial resolution of
the camera.
The parameter can be a number from 0 to 10 as
described in the table below.
Returns 0 in case of error otherwise 1
Example :
Print
CAMERA.SETUP(7)
' init the camera at 800 x
600
Note:
This command is not required anymore as
the camera initialises automatically at the reboot.
Ret
= CAMERA.PICTURE(filename$)
Get a picture from the camera and save it
locally using the filename provided.
It works on both SDcard and internal FFAT
space within the limits of the free space available.
Returns 0 in case of error otherwise 1
Example :
Print
CAMERA.PICTURE("/image.jpg")
' save the picture in the file
image.jpg
Ret
= CAMERA.STOP()
Stops the camera driver
Returns 0 in case of error otherwise 1
Ret
= CAMERA.GETVALUE(param$)
Returns the value of the parameter as defined
in the table below:
Example :
Print
CAMERA.GETVALUE("hmirror")
' get the hmirror
parameter
Ret
= CAMERA.PARAMS(param$, value)
Set the parameter as defined in the table
below :
Returns 1 in case of error otherwise 0
Example :
Print
CAMERA.PARAMS("vflip",
1) ' set the vflip parameter to
1
The parameter
param$ can be :
PARAMETER
|
DESCRIPTION
|
framesize
|
Resolution of the image as per table below
0
|
96 x 96
|
1
|
160 x 120
|
2
|
176 x 144
|
3
|
240 x 176
|
4
|
240 x 240
|
5
|
320 x 240
|
6
|
400 x 296
|
7
|
480 x 320
|
8
|
640 x 480
|
9
|
800 x 600
|
10
|
1024 x 768
|
11
|
1280 x 720
|
12
|
1280 x 1024
|
13
|
1600 x 1200
|
|
quality
|
Quality of the image from 10 to 63 (0 = max
quality) (default 10)
|
brightness
|
Brightness of the image from -2 to 2 (default
0)
|
contrast
|
Contrast of the image from -2 to 2 (default
0)
|
saturation
|
Saturation (color) of the image from -2 to 2
(default 0)
|
vflip
|
Flip vertically the image is 1 (default 0)
|
hmirror
|
Mirror horizontally the image if 1 (default
0)
|
flash
|
Turns on/off the bright white led connected on
the module (default 0)
|
detection
|
Enables the face detection algo (0=disable,
1=enable)
|
recognition
|
Enables the face recognition algo
(0=disable, 1=enable)
|
enroll
|
Enroll the face detected by the camera and
store it in the RAM (0=disable, 1=enable)
|
savefaces
|
Save the faces enrolled from the RAM to the
disk (FFAT or SDCARD) (must be 1 to save)
|
readfaces
|
Read the faces enrolled from the disk (FFAT or
SDCARD) to the RAM (must be 1 to read)
|
special_effect
|
//0 - 6
|
colorbar
|
1= enabled / 0= disabled
|
wb_mode
|
//0 - 4
|
awb
|
TBD
|
awb_gain
|
TBD
|
aec
|
TBD
|
aec2
|
TBD
|
ae_level
|
//-2 - 2
|
aec_value
|
//0 - 1200
|
agc
|
TBD
|
agc_gain
|
//0 - 30
|
gaincancelling
|
//0 - 6
|
bpc
|
TBD
|
wpc
|
TBD
|
raw_gma
|
TBD
|
lenc
|
TBD
|
dcw
|
TBD
|
Using the url
http://module_ip/picture will show directly the
image in the browser.
Refreshing the web page (using F5, for
example) will refresh the image.
To use the camera in the output page, the
following html line is required :
HTML
|<img id='camera'>|
Alternatively, the following line can be used
to have an image that resize automatically
HTML
|<img id='camera' src="picture"
style=width:100%;height:auto;">|
Then a javascript command is required to start
the video
JSCALL
|set_pictimer(30);|
' try to refresh each 30 msec
Example:
' set the resolution at 640 x 480
if camera.setup(7)
= 0 then "Camera
Error" : end
cls
html
|<img id='camera' src="picture"
style=width:100%;height:auto;">|
jscall
|set_pictimer(30);|
|
A slightly more complete example :
rate
= 30 '
rate between each picture sample (msec)
pause 100
' set the max resolution in terms of memory
if camera.setup(10)
= 0 then end
print camera.params("vflip",
1)
print camera.params("hmirror",
1)
'set at 800x600
print camera.params("framesize",
7)
pause 100
onHtmlReload setpage
gosub setpage
wait
setpage:
cls
a$
= ""
a$
= a$ + |<h2>AnnexCAM Demo mini</h2>
|
a$
= a$ + |<img
id='camera' src="picture"
style=width:100%;height:auto;">|
html a$
jscall
"set_pictimer(" +
str$(rate)
+ ");"
return
|
To save a picture on the disk :
' set the resolution at 800 x 600
if camera.setup(7)
= 0 then "Camera
Error" : end
Print CAMERA.PICTURE("/image.jpg")
|
The image can then be downloaded / seen using
the file manager page.
The camera parameters can be modified using
the following URL:
http://module_ip/cam_setpar?param=value
Where param can be any parameter from the
table below
Example:
http://192.168.1.66/cam_setpar?brightness=2
The value returned can be -1 if the parameter
is unknown, 1 in case of error or 0 if all was OK
The parameters can be read using the following
url:
http://module_ip/cam_status
The value returned will be a string like
this
framesize=4 quality=10 brightness=0 contrast=0 saturation=0 vflip=1
hmirror=1 colorbar=0 special_effect=0 flash=0
Where all the parameters are separated by the
newline character
PARAMETER
|
DESCRIPTION
|
framesize
|
Resolution of the image as per table below
0
|
96 x 96
|
1
|
160 x 120
|
2
|
176 x 144
|
3
|
240 x 176
|
4
|
240 x 240
|
5
|
320 x 240
|
6
|
400 x 296
|
7
|
480 x 320
|
8
|
640 x 480
|
9
|
800 x 600
|
10
|
1024 x 768
|
11
|
1280 x 720
|
12
|
1280 x 1024
|
13
|
1600 x 1200
|
|
quality
|
Quality of the image from 10 to 63 (10 = max
quality)
|
brightness
|
Brightness of the image from -2 to 2 (default
0)
|
contrast
|
Contrast of the image from -2 to 2 (default
0)
|
saturation
|
Saturation (color) of the image from -2 to 2
(default 0)
|
vflip
|
Flip vertically the image is 1 (default 0)
|
hmirror
|
Mirror horizontally the image if 1 (default
0)
|
flash
|
Turns on/off the bright white led connected on
the module
|
special_effect
|
TBD
|
colorbar
|
TBD
|
AnnexCAM includes the support for face
recognition.
This is basically based on 2 parts :
1) Face
detection
2) Face
recognition
The face detection enables the detection of
faces whilst the face recognition compares the face detected
against a list of previously stored faces.
This is very CPU time and resources consuming
so it works only with resolutions of 320x240 and below.
The detection / recognition can be controlled
using the following URL:
http://module_ip/cam_setpar?param=value
PARAMETER
|
DESCRIPTION
|
detection
|
Enables the face detection algo (0=disable,
1=enable)
|
recognition
|
Enables the face recognition algo
(0=disable, 1=enable)
|
enroll
|
Enroll the face detected by the camera and
store it in the RAM (0=disable, 1=enable)
|
savafaces
|
Save the faces enrolled from the RAM to the
disk (FFAT or SDCARD) (must be 1 to save)
|
readfaces
|
Read the faces enrolled from the disk (FFAT or
SDCARD) to the RAM (must be 1 to read)
|
The faces enrolled are stored in the file
named “/face.fh”.
This file can then be backuped and transferred
to another module.
If the face detection is enabled, as soon as
the camera detect a face, AnnexCAM will include a special
parameters in the header of the image transferred :
Detected:x1,
y1, x2, y2
Where (x1, y1) and (x2, y2) are the
coordinates (in pixels) that describe the corners of the box
surrounding the face detected
If the face recognition is enabled, as soon as
the camera recognise a face, AnnexCAM will include a special
parameters in the header of the image transferred :
Recognition:Match
ID:xx
Where xx is a number that identify the subject
identified
Or
Recognition:No
Match
If the face has not been recognised
This information can be extracted from the
browser side using javascript.
Annex includes the feature to receive the
image from another module with AnnexCAM and show them on the TFT
display.
This can be done using the function
Ret$
= TFT.CAMERA(url$
[,x ,y] [,scale])
where
url$ is the address of the camera
x
and y
represent the position where the image will be shown on the
display
scale
is a number that enable to scale down the image, useful to display
an image with higher resolution than the display
‘scale’(optional)
enable to scale the image (see next table)
scale
|
Scaling effect
|
0
|
1:1
|
1
|
1:2
|
2
|
1:4
|
3
|
1:8
|
For example, to
receive a simple stream of images ( a video) from the camera with
IP 192.168.1.13:
while 1
a$
= tft.camera$("http://192.168.1.13/picture")
wend
|
This function returns a string value that
represents the header of the answer coming from the camera.
The header contains very interesting
information such as the detection or the recognition of a face.
This is a typical content
HTTP/1.1
200 OK
Content-Length: 7229
Content-Type: image/jpeg
Access-Control-Allow-Origin:
*
Access-Control-Allow-Headers:
Content-Type,Authorization
Access-Control-Expose-Headers: Detected,
Recognition, Resolution
Resolution: 320x240
Detected:
57.469482,0.000000,190.526123,186.304199
Recognition: No
Match
Connection: close
Accept-Ranges: none
The highlighted part contains the
coordinates of the detected face and eventually if the face has
been detected compared to a list of stored profiles
This more complete
example shows how to manage the value returned by TFT.CAMERA$.
It also shows how
include the login and password for camera with restricted
access
timer0 1000,
count
tft.init 1
tft.fill
tft.color(red)
tft.brightness 255
a$=
""
c
= 0 : z = 0
while 1
'Read from the camera using the given
login:password
a$
= tft.camera$("http://mylogin:mypassword@192.168.1.13/picture")
'Check inside the answer is a face has been detected /
recognised
p
= instr(a$,
"Detected:")
if p <> 0 then
d$ = mid$(a$,
p + 9)
x1 = val(word$(d$,
1, ",")) : y1 =
val(word$(d$,
2, ","))
x2 = val(word$(d$,
3, ",")) : y2 =
val(word$(d$,
4, ","))
r = instr(a$,
"Recognition:")
if r = 0 then
tft.rect x1, y1, x2-x1, y2-y1, 65504
'(yellow)
else
if instr(d$,
"No Match") <> 0
then
tft.rect x1, y1, x2-x1, y2-y1, 63488
'(red)
else
tft.rect x1, y1, x2-x1, y2-y1, 2016
'(green)
end if
end if
end if
wend
end
count:
print
"frames / sec ", z-c,
ramfree
c
= z
return
|
The AnnexEpaper is a special version of
Annex32 specially developed for this module.
It is essentially the same firmware as
the Annex32 except that this version fully supports the e-paper
display including the optional touchscreen and many drivers have
been removed to gain space and memory.
The main reason is because the e-paper display
itself uses practically all the ESP32 pins available leaving very
few pins for the I/O.
This module includes an EPD4.7” e-paper
display, a 16Mbytes Flash chip and an additional PSRAM for big size
pictures.

EPAPER.SETUP rotation
'
rotation from 0 to 3
Setup the display with the correct
orientation
The orientation cannot be changed without
restarting the device (will be fixed)
EPAPER.ON
Turns the display ON
EPAPER.OFF
Turns the display OFF
EPAPER.CLS
Clear the display and the buffer memory
EPAPER.CLEAR
Clear the the buffer memory but not the
display itself
Useful to refresh the image on the display
EPAPER.REFRESH mode
[,temperature]
'temperature
by default it 25°C
Refreshes the image on the display; the mode
must be defined
EPAPER.PIXEL x, y,
color
EPAPER.LINE x1, y1,
x2, y2, color
EPAPER.RECT x, y, w,
h, color [,fill]
EPAPER.CIRCLE x, y, r,
color [,fill]
EPAPER.TEXT.ALIGN align
Defines the text alignment
1
|
EPD_DRAW_BACKGROUND
|
2
|
EPD_DRAW_ALIGN_LEFT
|
4
|
EPD_DRAW_ALIGN_RIGHT
|
8
|
EPD_DRAW_ALIGN_CENTER
|
EPAPER.TEXT.COLOR color
Defines the text color from 0 (black) to 15
(white)
EPAPER.TEXT.FONT font
Set the font to be displayed
0
|
FiraSans 12
|
1
|
Verdana 20
|
10
|
Loaded Font 1
|
11
|
Loaded Font 2
|
12
|
Loaded Font 3
|
EPAPER.TEXT.DRAW
"string",
x,
y
EPAPER.LOADFONT
"/fontfile.fnt" [,
fontnum]
Loads a font from file; the fontnum can be
1(default), 2 or 3
EPAPER.BMP
"/bmpfile.bmp",
x, y [,
reverse]
Draws a bmp file on the display; it must be in
B/W 8 bits format
If reverse=1 the color will be reversed
(negative image)
EPAPER.QRCODE
"message", x, y,
width [,version]
This command draws a text message on the
display as QR CODE that can be read using a mobile phone simply
taking a picture of the image shown on the display.
By default the version is 6

EPAPER.SAVE
"/bmpfile.bmp",
x, y [,
reverse]
Save the image shown on the display in a bmp 8
bits format.
If the adapted touchscreen is available, the
following functions are available as in the normal ESP32
version
TOUCH.READ,
TOUCH.X,
TOUCH.Y,
TOUCH.Z
Additionally, the command
TOUCH.SLEEP sleeps the touch screen controller to reduce
power
The AnnexEpaper version includes all the GUI
objects as defined in the GRAPHIC GUI
for TFT chapter (except for the RAMP object) using
the same syntax but with the colors adapted to the monochromatic
display.
The following images show some screenshots
taken directly from the display itself (using the command
EPAPER.SAVE) with some demo programs.
Example 1
Bluetooth.delete
' free the RAM used by the bluetooth
epaper.setup 0
epaper.cls
print
touch.setup
gui.init 50
gui.textline(200,
10, 550, 60, "Touch E-Paper 4.7
Demo", 1)
t1
= gui.textline( 20, 100, 200, 50, "Top Left", 0, 0, 15, 0,
ALIGN_TOP_LEFT)
t2
= gui.textline(380, 100, 200, 50, "Top Mid", 0, 0, 15, 0,
ALIGN_TOP_MID)
t3
= gui.textline(740, 100, 200, 50, "Top Right", 0, 0, 15, 0,
ALIGN_TOP_RIGHT)
t4
= gui.textline( 20, 180, 200, 50, "Mid Left", 0, 0, 15, 0,
ALIGN_MID_LEFT)
t5
= gui.textline(380, 180, 200, 50, "Mid Mid", 0, 0, 15, 0,
ALIGN_MID_MID)
t6
= gui.textline(740, 180, 200, 50, "Mid Right", 0, 0, 15, 0,
ALIGN_MID_RIGHT)
t7
= gui.textline( 20, 260, 200, 50, "Bot Left", 0, 0, 15, 0,
ALIGN_BOT_LEFT)
t8
= gui.textline(380, 260, 200, 50, "Bot Mid", 0, 0, 15, 0,
ALIGN_BOT_MID)
t9
= gui.textline(740, 260, 200, 50, "Bot Right", 0, 0, 15, 0,
ALIGN_BOT_RIGHT)
ta
= gui.textline( 20, 340, 300, 60, "Mid Left", 1, 0, 15, 0,
ALIGN_MID_LEFT)
tb
= gui.textline(330, 340, 300, 60, "Mid Mid", 1, 0, 15, 0,
ALIGN_MID_MID)
tc
= gui.textline(640, 340, 300, 60, "Mid Right", 1, 0, 15, 0,
ALIGN_MID_RIGHT)
td
= gui.textline( 20, 420, 300, 60, "Top Left", 1, 15, 0, 0,
ALIGN_TOP_LEFT)
te
= gui.textline(330, 420, 300, 60, "Mid Mid", 1, 15, 0, 0,
ALIGN_MID_MID)
tf
= gui.textline(640, 420, 300, 60, "Top Right", 1, 15, 0, 0,
ALIGN_TOP_RIGHT)
gui.textline(150,
500, 700, 35, "Demo of text
alignements")
gui.autorefresh 100,
1
wait
|

Example 2
Bluetooth.delete
' free the RAM used by the bluetooth
epaper.setup 0
epapercls
print
touch.setup
gui.init 50
gui.textline(200,
10, 550, 60, "Touch E-Paper 4.7
Demo", 1)
gui.textline(20,
120, 200, 50, "Squared", 1
)
gui.textline(320,
90, 1, 30, "Option 1", 0, 0, 15,
15)
gui.textline(520,
90, 1, 30, "Option 2", 0, 0, 15,
15)
gui.textline(720,
90, 1, 30, "Option 3", 0, 0, 15,
15)
c1
= gui.checkbox(300, 120, 50, 50, 0, squared)
c2
= gui.checkbox(500, 120, 50, 50, 0, squared)
c3
= gui.checkbox(700, 120, 50, 50, 0, squared)
gui.textline(20,
220, 200, 50, "Crossed", 1
)
gui.textline(320,
220, 1, 30, "Option 4", 0, 0,
15, 15)
gui.textline(520,
220, 1, 30, "Option 5", 0, 0,
15, 15)
gui.textline(720,
220, 1, 30, "Option 6", 0, 0,
15, 15)
c4
= gui.checkbox(300, 250, 50, 50, 0, crossed)
c5
= gui.checkbox(500, 250, 50, 50, 0, crossed)
c6
= gui.checkbox(700, 250, 50, 50, 0, crossed)
gui.textline(20,
350, 200, 50, "Radio", 1
)
gui.textline(320,
350, 1, 30, "Option 7", 0, 0,
15, 15)
gui.textline(520,
350, 1, 30, "Option 8", 0, 0,
15, 15)
gui.textline(720,
350, 1, 30, "Option 9", 0, 0,
15, 15)
c7
= gui.checkbox(300, 380, 50, 50, 1, radio, 1)
c8
= gui.checkbox(500, 380, 50, 50, 0, radio, 1)
c9
= gui.checkbox(700, 380, 50, 50, 0, radio, 1)
gui.textline(150,
500, 700, 35, "Demo of Button Image
Groups")
gui.autorefresh 100,
1
wait
|










FUNCTIONALITY
|
ENABLED
|
TFT display
|
❌
|
QRCODE
|
✅
|
ESPNOW
|
✅
|
PID
|
❌
|
ETHERNET
|
❌
|
CONVERT
|
✅
|
MQTT
|
✅
|
OLED
|
❌
|
APDS9960
|
✅
|
BME280
|
✅
|
INFRARED
|
✅
|
PLAY (WAV, MP3,
VOICE)
|
❌
|
NEOPIXEL
|
✅
|
VL53L0X
|
✅
|
RFID
|
❌
|
FREQUENCY METER
|
❌
|
IOBUFFER
|
✅
|
WDT
|
✅
|
MPU9250
|
✅
|
MPU6886
|
✅
|
MPU6050
|
✅
|
FUSION ALGO
|
✅
|
BNO055
|
✅
|
PCA9685
|
✅
|
TM1637 AND
TM1638
|
✅
|
MAXDISPLAY
|
❌
|
BLUETOOTH
|
✅
|
CCS811
|
✅
|
HDC1080
|
✅
|
TELEGRAM
|
✅
|
The functions PEEK and POKE are commands used
for accessing the contents of a specific memory cell referenced by
its memory address.
PEEK gets the byte located at the specified
memory address.
POKE sets the memory byte at the specified
address.
The memory can be accessed by byte (uint8_t),
by word (uint8_16) or by double word (uint32_t).
Generally the internal CPU registers are 32
bits so this should be the “normal” access mode
The following functions / commands are
available
FUNCTION
|
DESCRIPTION
|
|
Read a double word (32 bits) from ‘addr’
memory address
|
|
Read a word (16 bits) from ‘addr’ memory
address
|
|
Read a byte(8 bits) from ‘addr’ memory
address
|
|
Write a double word (32 bits) ‘data’ into
‘addr’ memory address
|
|
Write a word (16 bits) ‘data’ into ‘addr’
memory address
|
|
Write a byte (8 bits) ‘data’ into ‘addr’
memory address
|
Example
'EXAMPLE SHOWING THE USE OF PEEK AND POKE FOR BLINKING
LEDS
'-------------------------------------------------------------
'Name Description Address Access
'GPIO_OUT_REG GPIO 0-31 output register 0x3FF44004
R/W
'GPIO_OUT_W1TS_REG GPIO 0-31 output register_W1TS 0x3FF44008
WO
'GPIO_OUT_W1TC_REG GPIO 0-31 output register_W1TC 0x3FF4400C
WO
'GPIO_OUT1_REG GPIO 32-39 output register 0x3FF44010
R/W
'GPIO_OUT1_W1TS_REG GPIO 32-39 output bit set register 0x3FF44014
WO
'GPIO_OUT1_W1TC_REG GPIO 32-39 output bit clear register 0x3FF44018
WO
'GPIO_ENABLE_REG GPIO 0-31 output enable register 0x3FF44020
R/W
'GPIO_ENABLE_W1TS_REG GPIO 0-31 output enable register_W1TS
0x3FF44024 WO
'GPIO_ENABLE_W1TC_REG GPIO 0-31 output enable register_W1TC
0x3FF44028 WO
'GPIO_ENABLE1_REG GPIO 32-39 output enable register 0x3FF4402C
R/W
'GPIO_ENABLE1_W1TS_REG GPIO 32-39 output enable bit set register
0x3FF44030 WO
'GPIO_ENABLE1_W1TC_REG GPIO 32-39 output enable bit clear register
0x3FF44034 WO
'-------------------------------------------------------------
pin.mode 4,
output
pin.mode 5,
output
do
pin(4)
= 0
pin(5)
= 0
print bin$(bas.peek(&h3FF44004))
pause 1000
pin(4)
= 1
pin(5)
= 1
print bin$(bas.peek(&h3FF44004))
pause 1000
bas.poke &h3FF4400C,
&b110000
print bin$(bas.peek(&h3FF44004))
pause 1000
bas.poke &h3FF44008,
&b110000
print bin$(bas.peek(&h3FF44004))
pause 1000
loop
|
A set of conversion functions have been
implemented.
These permit conversion from different units /
formats in a simple way.
All these functions share the same prefix
CONVERT. followed by the specific conversion name.
The functions implemented are :
FUNCTION
|
DESCRIPTION
|
|
Converts from °C to °F
|
|
Converts from °F to °C
|
|
Converts from float number to IEEE754 binary
format
|
|
Converts from IEEE754 binary format to float
number
|
CONVERT.MAP(number,
fromLow, fromHigh, toLow, toHigh)
|
Re-maps a number from one range to
another. That is, a value of fromLow would get mapped to
toLow, a value of fromHigh to toHigh, values
in-between to values in-between, etc.
|
|
Converts a byte to BCD format
|
|
Convert to a byte from BCD format
|
|
Restricts a number within a specified
range.
`number` is the value to be limited.
`min` is the minimum allowed value for
the number.
`max` is the maximum allowed value for
the number.
|
Several constants are available in the
interpreter using the
BAS.xxx format.
All these constants share the same prefix
BAS. followed by the specific option.
Some of them (i.e.
BAS.RTCMEM$) can also be written using it as a
destination..
CONSTANT
|
DESCRIPTION
|
|
Returns the version
of the Basic in numerical format
Example:
Print BAS.VER
1.37
|
|
Returns the version
of the Basic in string format
Example:
Print BAS.VER$
Annex32 WI-Fi
1.37
|
|
Returns the line
number where the error happened. Value of 0 means no error.
It is reset to 0
with the command ONERROR CLEAR or running the program or with
the command ONERROR IGNORE or ONERROR SKIP.
|
|
Returns a number
where non zero means that there was an error.
It is reset to 0
with the command ONERROR CLEAR or running the program or with
the command ONERROR IGNORE or ONERROR SKIP.
|
|
Return a string
representing the error message that would have normally been
displayed on the console. It is reset to “No Error” running the
program or with the command ONERROR CLEAR or ONERROR IGNORE or
ONERROR SKIP.
|
|
Returns the name of
the current basic file
|
|
Returns the content
of the CPU RTC internal memory.
This memory
maintains the content between reset so it is useful in association
with the SLEEP command when the module goes in low power mode.
This memory is
limited at 7680 bytes and can be set with the corresponding
command BAS.RCTMEM$ = “xxx”.
The content of this memory is lost in case of power
OFF.
|
|
Returns the login
used for the STATION
wifi connection.
|
|
Returns the
password used for the
STATION wifi connection.
|
|
Loads another .bas
program and runs it immediately.
Returns 0 if
successful or -1 if the file was not found
Example:
Print BAS.LOAD
"/test.bas"
|
|
Returns the reason
for the last reset.
The reason is
defined in the table below
VALUE
|
REASON
|
0
|
Unknown
|
1
|
Power
on reset
|
2
|
Unknown
|
3
|
Software reset digital core
|
4
|
Legacy
watch dog reset digital core
|
5
|
Deep
Sleep reset digital core
|
6
|
Reset
by SLC module, reset digital core
|
7
|
Timer
Group0 Watch dog reset digital core
|
8
|
Timer
Group1 Watch dog reset digital core
|
9
|
RTC
Watch dog reset digital core
|
10
|
Intrusion tested to reset CPU
|
11
|
Time
Group reset CPU
|
12
|
Software reset CPU
|
13
|
RTC
Watch dog reset CPU
|
14
|
for APP
CPU, reset by PRO CPU
|
15
|
Reset
when the vdd voltage is not stable
|
16
|
RTC
Watch dog reset digital core and rtc module
|
|
|
Returns the reason
for the wake up if the module was in deep sleep
The reason is
defined in the table below
VALUE
|
REASON
|
0
|
Unknown
|
1
|
N/A
|
2
|
EXT0 - Input
Pin
|
3
|
EXT1
|
4
|
Timer
|
5
|
Touch - Touch
pin
|
6
|
ULP
|
7
|
GPIO (in
light sleep only)
|
8
|
UART (in light
sleep only)
|
9
|
WIFI (in
light sleep only)
|
10
|
COCPU interrupt
|
11
|
COCPU crash
|
12
|
BT (in light sleep
only)
|
|
|
Returns a number
representing the current module connected
VALUE
|
MODULE
|
0
|
Generic
ESP32
|
1
|
Custom
|
100
|
M5 Stack
|
101
|
M5
ATOM
|
102
|
M5 ATOM ECHO
|
103
|
M5 ATOM MATRIX
|
104
|
M5
Tough
|
120
|
WIFI
loRa 32
|
150
|
ODROID
GO
|
151
|
ESP32-2432S028
|
152
|
ESP32-3248S035R
|
153
|
ESP32-3248S035C
|
160
|
ESP32-4848S040
|
161
|
ESP32-8048S070C
|
201
|
ESP32-CAM
|
202
|
M5
CAMERA
|
|
|
Returns a number
representing the TFT display connected
VALUE
|
DISPLAY
|
0 to 7
|
ST7735
|
11
|
GC9A01
|
51
|
SSD1351
|
81
|
ILI9481
|
86
|
ILI9486
|
88
|
ILI9488
|
89
|
ST7789 #0
|
91
|
ILI9163
|
93
|
ILI9341
|
94
|
M5stack
|
95
|
M5stack with
different TFT
|
96
|
ST7796
|
101 to 106
|
ST7789 #1 to ST7789
#6
|
255
|
NO TFT
|
|
It is possible to define some options in the
interpreter using the
OPTION.xxx commands.
All these commands share the same prefix
OPTION. followed by the specific option.
The options available are :
COMMAND
|
DESCRIPTION
|
|
Defines the lower
limit for array subscripts.
Can be 0 (default)
or 1.
This command must
be executed before the declaration of any array (best in the first
lines of the program)
|
|
Define CPU speed in
Mhz of the module.
The value can be
80, 160 or 240.
The default value
is 240Mhz.
Setting the speed
at 80Mhz, will divide by 3 the speed of the module but lower the
power requirement of the module to around 5mA
|
|
Enable the ES8388
Codec for the AI-Thinker Audio Kit
It uses the
following pins:
I2C SDA -> pin
33
I2C SCL -> pin
32
I2S_MCLK
-> pin 0
PA_ENABLE -> pin
21
The other pins must
be defined in the advanced config page
|
|
Define an arbitrary
MAC address for the module.
‘mac$’ must be a
valid MAC address.
Example :
OPTION.MAC
"AA:BB:CC:DD:EE:FF"
|
|
Define the RAM
available lower limit. If during the execution of the program this
limit is reached, the program automatically stops with an OUT OF
MEMORY error message. By default the value is defined at 10000.
As it introduces a
little overhead, it can be disabled setting this option at 0
(however this is not recommended).
|
|
Sync the local time
with the remote NTP servers
|
|
Define the time for
the Watchdog timer.
If the WDT is not
reset regularly with the command OPTION.WDTRESET
within the defined time, the module
will reset automatically.
Setting
time
at 0, will disable the watchdog.
|
|
Reset the Watchdog
timer
|
|
Define how the log
will be printed in the Editor page
value
|
Description
|
0
|
WLOG
will be ignored
|
1
|
WLOG
will be printed (default)
|
2
|
All
will be logged, including the command HTML, CSS, JSCALL, ....
|
|
|
Define the kind of
touchscreen controller to use
value
|
Description
|
0
|
Resistive based on
XPT2046 (default)
|
1
|
Capacitive based on
GT911
|
|
OPTION.I2S
BCLK_pin,
WSEL_pin, DOUT_pin
|
Set / override the
default pins allocated for the I2S output
|
|
When external
memory is in use, the allocation strategy is to initially try to
satisfy smaller allocation requests with internal memory and larger
requests with external memory.
The limit parameter
helps balance the use of internal and external memory. Adjusting
this value can optimise memory allocation based on the specific
needs and constraints of your application.
By default the
limit is
8192.
When changed the
value is stored internally and will be automatically loaded at the
next restart.
|
The ESP32 contains an internal sensor that can
be read using the following function:
Example
PRINT
BAS.HALL
However, this functionality is very marginal
as the sensor is not sensitive at all.
The functions are divided into 2 groups :
-
Numerical functions (Double precision / integer)
-
String functions
The string functions are always terminated by
a ‘$’ (dollar) sign.
|
Returns the
absolute value of the argument 'number'
|
|
Returns the
arccosine value of the argument 'number' in radians
|
|
Returns the
external voltage applied to the ADC pin defined as a digital value
ranging from 0 (0v) to 4095.
Input voltage range
is 0 ... 3.3V.
|
|
Initialise a
APDS9960 sensor connected using I2C to the module.
‘mode’ determine
the sensing modality as per the table below :
MODE
|
SENSING
MODALITY
|
1
|
Gesture
Detection
|
2
|
Ambient
Light and RGB Color Sensing
|
3
|
Proximity Sensing
|
Before using it, the I2C bus must be
initialised with the command I2C.SETUP
This function returns 1 if the APDS9960 sensor
is found, otherwise it returns 0
|
|
Returns the last
gesture detected by the APDS9960 sensor.
The APDS9960 sensor
must be set in “Gesture Detection” mode before using this function
( APDS9960.SETUP(1) )
The returned value
is :
VALUE
|
GESTURE
|
0
|
NONE
|
1
|
LEFT
|
2
|
RIGHT
|
3
|
UP
|
4
|
DOWN
|
5
|
NEAR
|
6
|
FAR
|
|
|
Returns the ambient
luminosity detected by the APDS9960 sensor.
The APDS9960 sensor
must be set in “Ambient Light and RGB Color Sensing” mode before
using this function ( APDS9960.SETUP(2) )
The range of the
returned value is from 0 to 65535
|
|
Returns the red
light intensity detected by the APDS9960 sensor.
The APDS9960 sensor
must be set in “Ambient Light and RGB Color Sensing” mode before
using this function ( APDS9960.SETUP(2) )
The range of the
returned value is from 0 to 65535
|
|
Returns the green
light intensity detected by the APDS9960 sensor.
The APDS9960 sensor
must be set in “Ambient Light and RGB Color Sensing” mode before
using this function ( APDS9960.SETUP(2) )
The range of the
returned value is from 0 to 65535
|
|
Returns the blue
light intensity detected by the APDS9960 sensor.
The APDS9960 sensor
must be set in “Ambient Light and RGB Color Sensing” mode before
using this function ( APDS9960.SETUP(2) )
The range of the
returned value is from 0 to 65535
|
|
Returns the
distance information detected by the APDS9960 sensor.
The APDS9960 sensor
must be set in “Proximity Sensing” mode before using this function
( APDS9960.SETUP(3) )
The range of the
returned value is from 0 to 255
|
|
Set the gain of the
gesture sensing provided by the APDS9960 sensor.
‘gain’ can be one
of the following values:
GAIN
|
MEANING
|
0
|
1x
|
1
|
2x
|
2
|
4x
|
3
|
8x
|
This function returns 1 if the function was
successful, otherwise it returns 0
|
|
Set the inensity of
the LED used during the gesture sensing provided by the APDS9960
sensor.
‘intensity’ can be
one of the following values:
INTENSITY
|
MEANING
|
0
|
100 mA
|
1
|
50 mA
|
2
|
25 mA
|
3
|
12.5 mA
|
This function returns 1 if the function was
successful, otherwise it returns 0
|
|
Returns the ASCII
code of the first char in ‘string$’
|
|
Returns the arcsine
value of the argument 'number' in radians
|
|
Returns the
arctangent of the argument 'number' in radians
|
|
Returns the angle
whose tangent is the quotient of two specified numbers.
|
|
Returns the version
of the Basic in numerical format
Example:
Print BAS.VER
1.25
|
|
Returns the line
number where the error happened. Value of 0 means no error.
It is reset to 0
with the command ONERROR CLEAR, or by running the program, or with
the command ONERROR IGNORE, or ONERROR SKIP.
|
|
Returns a number
where non zero means that there was an error.
It is reset to 0
with the command ONERROR CLEAR, or by running the program, or with
the command ONERROR IGNORE, or ONERROR SKIP.
|
|
Initialise a BME280
sensor connected using I2C to the module.
‘address’ defines
the I2C address of the sensor. The value can be &h76 or
&h77.
Before using it, the I2C bus must be
initialised with the command I2C.SETUP
Returns 1 if the BME280 sensor has been found,
otherwise returns 0
|
|
Returns the current
altitude using the baro pressure from the sensor BME280.
The sea level
pressure (in HectoPascal) must be given as a reference
argument.
The unit of the
value returned is Meters (m)
|
|
Returns the
Humidity parameter from the sensor BME280.
The unit of the
value returned is ‘%’
If the value
returned is always 0, the sensor is probably a BMP280.
|
|
Returns the
Barometric Pressure parameter from the sensor BME280.
The unit of the
value returned is HectoPascal ‘Hpa’
|
|
Returns the sea
level pressure using the baro pressure from the sensor BME280.
The current
altitude (in meters) must be given as a reference argument.
The unit of the
value returned is HectoPascal ‘Hpa’
|
|
Returns the
Temperature parameter from the sensor BME280.
The unit of the
value returned is ‘%’
|
|
Initialise a BNO055
connected using I2C to the module.
‘address’ defines
the I2C address of the sensor. The value can be &h28 or
&h29.
Before using it, the I2C bus must be
initialised with the command I2C.SETUP
Returns 1 if the BNO055 sensor has been found,
otherwise returns 0
|
|
Returns the Heading
angle information from the sensor BNO055.
The unit of the
value returned is ‘degrees’
|
|
Returns the Pitch
angle information from the sensor BNO055.
The unit of the
value returned is ‘degrees’
|
|
Returns the Roll
angle information from the sensor BNO055.
The unit of the
value returned is ‘degrees’
|
|
Returns different
type of information from the sensor BNO055.
Refer to the table
below for the details of the information returned.
Example:
Print “Gyro infos
x,y “, BNO055.VECTOR(3,1), BNO055.VECTOR(3,2)
PARAM
|
AXIS
|
PARAMETER
|
UNITS
|
1
|
1
|
Accelerometer X
axis
|
m/sec2
|
2
|
Accelerometer Y
axis
|
3
|
Accelerometer Z
axis
|
2
|
1
|
Magnetometer X
axis
|
micro tesla
|
2
|
Magnetometer Y
axis
|
3
|
Magnetometer Z
axis
|
3
|
1
|
Gyroscope X
axis
|
deg / sec
|
2
|
Gyroscope Y
axis
|
3
|
Gyroscope Z
axis
|
4
|
1
|
Linear
Accelerometer X axis
|
m/sec2
|
2
|
Linear
Accelerometer Y axis
|
3
|
Linear
Accelerometer Z axis
|
5
|
1
|
Gravity Data X
axis
|
m/sec2
|
2
|
Gravity Data Y
axis
|
3
|
Gravity Data Z
axis
|
6 or any other value
|
1
|
Euler Angle
Heading
|
deg
|
2
|
Euler Angle
Roll
|
3
|
Euler Angle
Pitch
|
|
|
Returns the
calibration status of the BNO055 sensor.
Used without any
argument, it will return the global calibration status ( 1 =
calibrated, 0 = not calibrated).
Refer to the table
below when the function is called with an argument
PARAM
|
PARAMETER
|
1
|
System
Status
|
2
|
Gyroscopes Status
|
3
|
Accelerometers Status
|
4
|
Magnetometers Status
|
none
|
Global
Status (returns 1 if all are OK)
|
Example:
Print “Is
Calibrated“, BNO055.CALIB
|
|
Round numbers with
fractional portions up or down to the next whole number or
integer.
For example :
●
15.46 will round to 15
●
15.57 will round to 16
●
-83.45 will round to -83
●
-83.55 will round to -84
See also INT() and
FIX().
|
|
Converts from °C to
°F
|
|
Converts from °F to
°C
|
|
Converts from float
number to IEEE754 binary format
|
|
Converts from
IEEE754 binary format to float number
|
|
Re-maps a number from one range to
another. That is, a value of fromLow would get mapped to
toLow, a value of fromHigh to toHigh, values
in-between to values in-between, etc.
|
|
Converts a byte to BCD format
|
|
Convert to a byte from BCD format
|
|
Returns the cosine
of the argument 'number' in radians.
|
|
Returns
the number of pulses recorded by the counter.
‘cnt’
identifies the counter, which can be 1 or 2
It is
associated with the commands COUNTER.SETUP, COUNTER.RESET
|
|
Returns the period
of time between 2 successive pulses recorded by the counter.
The value returned
is expressed in uS (micro seconds).
‘cnt’ identifies
the counter, which can be 1 or 2
It is associated
with the commands COUNTER.SETUP, COUNTER.RESET
|
|
Converts a date in format dd/mm/yy into UNIX FORMAT.
See
also TIMEUNIX, and the complementary UNIXDATE$ and UNIXTIME$
|
|
Returns
the temperature of the DHT sensor set with "DHT.SETUP"
The
syntax is temp = DHT.TEMP
Returns
the temperature in °C
|
|
Returns the
humidity of the DHT sensor set with "DHT.SETUP"
The
syntax is hum = DHT.HUM
Returns
the humidity in %
|
|
Returns the heat
index of the DHT sensor set with "DHT.SETUP"
The
syntax is heat = DHT.HEATINDEX
Returns
the heatindex in °C
|
|
Using a HC-SR04
ultrasonic sensor, this function returns the distance in cm to a
target. The range is approximately from 3 cm to 3 meters.
‘pin_trig’ and
‘pin_echo’ define the pins where the HC-SR04 module is
connected.
|
|
Send an e-mail and
return the status of the sending.
The program will
stop the execution until the message is sent or an error
occurs.
The result will be
1 if OK or 0 if a problem happend.
‘from$’ is the
email address of the sender (ex: from_me@yahoo.com)
‘to$’’ is the email
address of the receiver (ex: to_you@yahoo.com)
‘subject$’ is the
subject of the message
‘message$’ is the
content of the message
The sender and
receiver must both be valid email addresses.
Example :
r = EMAIL
("from_me@yahoo.com", "to_you@gmail.com", "Important message " +
date$, "The memory available is " + str$(ramfree) )
|
|
Add a peer
(module) to the ‘receiver’ list.
The peer is
specified by its MAC address
‘interface’ can be
0 = AUTO (default), 1=STA, 2=AP
‘channel’ can be
any valid channel numbers or 0 = current channel (default)
Returns 0 if OK or
another number in case of error
|
|
Starts the ESP-NOW
communications.
Returns 0 if OK or
another number in case of error
|
|
Delete a peer
(module) from the ‘receiver’ list.
The peer is
specified by its MAC address (MAC_add$)
Returns 0 if OK or
another number in case of error
|
|
Stops the ESP-NOW
communications.
Returns 0 if OK or
another number in case of error
|
|
write a message to
the peers defined in the list
The message ‘msg$’
must be less than 250 characters.
Returns 0 if OK or
another number in case of error
|
|
write a message to
a specific peer defined by its MAC address (MAC_add$)
The message ‘msg$’
must be less than 250 characters.
Returns 0 if OK or
another number in case of error
|
|
Returns the
exponential value of 'number'.
|
|
Truncate a number
to a whole number by eliminating the decimal point and all
characters to the right of the decimal point.
For example :
● 7.11
will return 7
● 7.85
will return 7
●
-2.11 will return -2
●
-2.75 will return -2
The major
difference between FIX and INT is that FIX provides a true integer
function (ie, does not return the next lower number for negative
numbers as INT() does).
See also INT() and
CINT() .
|
|
Delete the file
specified by ‘filename$’.
Returns 1 if the
delete was successful, otherwise returns 0
|
|
Returns 1 if the
file ‘filename$’ exists, otherwise returns 0
|
|
Returns the size of
the file (in bytes) if the file exist, otherwise returns -1
|
|
Returns the free
disk memory available (number of bytes)
|
|
Returns the angles
(in degrees) calculated by the FUSION algorithm.
The returned value
is :
AXIS
|
RETURNED INFORMATION
|
1
|
PITCH
|
2
|
ROLL
|
3
|
YAW
|
|
|
Returns the
position at which 'pattern$’ is located into ‘string$’, starting
from (optional) start.
‘start’ can also be
a negative number. In this case the pattern will be searched from
the end of the string.
The function
returns 0 if pattern$ is not found
|
|
Returns the number
of bytes available for retrieval with I2C.READ. This should be
called on a master device after a call to I2C.REQFROM.
Example:
Len = I2C.LEN
|
|
Reads a byte that
was transmitted from a slave device to a master after a call to
I2C.REQFROM.
Example:
b = I2C.READ
|
|
Read a byte from a
slave device using a given device register address.
‘i2c_address’
define the I2C slave address
‘register’ defines
the device register
Example:
i2c_addr = &h60
: register = 33
value =
I2C.ReadRegByte i2c_addr , register
Will read the value
of the register address 33 on the device with i2c address
&h60.
For clarification,
this command is equivalent to the following program:
i2c.begin
i2c_addr
I2c.write
register
i2c.end
i2c.reqfrom
i2c_addr, 1
value =
i2c.read
I2c.end
TBD : the syntax
must be conformed to the other functions (using parentheses)
|
|
Ends a transmission
to a slave device that was begun by I2C.BEGIN and transmits the
bytes that were queued by I2C.WRITE.
It returns a
value indicating the status of the transmission:
0:success
1:data too long to
fit in transmit buffer
2:received NACK on
transmit of address
3:received NACK on
transmit of data
4:other error
Example:
stat = I2C.END
|
|
Truncate an
expression to the next whole number less than or equal to the
argument.
For example :
● 7.11
will return 7
● 7.85
will return 7
●
-2.11 will return -3
●
-2.75 will return -3
The FIX() function
provides a true integer function.
See also FIX() and
CINT() .
|
|
Returns the length
of the string ‘string$’
|
|
Returns the natural
logarithm of the argument 'number'
|
|
Returns the number
of milliseconds elapsed since the start-up of the module
|
|
Setup the MQTT communications.
Server$ is the MQTT server url
‘debug’, if set to 1, enable some useful debug
messages
Returns 258 at the first initialisation and
then 0
|
|
Set the SSL certificates.
‘cert_pem$’ is used for the main server
authorisation
‘client_cert_pem’ and ‘client_key_pem$’ are
used for a more complex authorisation scheme (for advanced
users)
When setting the certificates, the PSK will be
removed
|
|
Set the PSK as an alternative to certificate
verification.
When setting this PSK all the certificates
will be removed
|
|
Set the last will and
testament (LWT) message in the specified topic
Qos can be 0, 1 or 2; if
not defined defaults to 0
‘retain’, if set to 1, the
message is retained
Returns 0 if OK
|
|
Connect to the server using the provided login
and password.
Optionally ID$ permits to define an arbitrary
ID
Returns 0 if OK
|
|
Connect to the server without
identification
Optionally ID$ permits to define an arbitrary
ID
Returns 0 if OK
|
|
Disconnects from the MQTT server
Returns 0 if OK
|
|
Publish a string message in the specified
topic
Qos can be 0, 1 or 2; if not defined defaults
to 0
‘retain’, if set to 1, the message is
retained
Returns the msg_id of the message sent
|
|
Subscribes to messages published to the
specified topic.
Qos can be 0, 1 or 2; if not defined defaults
to 0
Returns 0 if OK
|
|
Unsubscribes from the specified topic
Returns 0 if OK
|
|
Returns the current connection status.
Returns 1 if connected or 0 if
disconnected
|
|
Returns the current status. It can be:
MQTT_STATE_INIT = 0
MQTT_STATE_DISCONNECTED =
1
MQTT_STATE_CONNECTED =
2
MQTT_STATE_WAIT_RECONNECT =
3
|
|
Gets, in a
stripline, the 32bit merged color value of the led at position
'led_pos'
|
|
Returns the 3
supplied R,G,B colours merged into a single 32bit RGB color value,
useful for the NEO.PIXEL function and web page colors
|
|
Returns the value
3.1415925….
|
|
Returns the
computed value of the given PID controller.
The ‘target_value’
is desired output value while ‘current_value’ is the value coming
from the sensor.
This function must
be called regularly in a loop
As there are 4 PID
controllers, the prefix can be PID1, PID2, PID3 or PID4.
|
|
Returns the value
of any external I/O pin.
The pin_number
refers to GPIO and can be from 0 ... 5 or 12 ...15
The value returned
is 0 if the pin is LOW and 1 if the pin is HIGH
|
|
Returns the touch
value for the pin ‘pin_number’.
‘Pin_number’ can be
0, 2, 4, 12, 13, 14, 15, 27 32, 33.
The value returned
is around 70 when not touched and around 15 when touched.
|
|
The ping function
can be used to test the ability of the ESP32 to reach a specified
destination computer. The ping command is usually used as a simple
way to verify that a computer can communicate over the network with
another computer or network device.
‘host$’ is the
remote address to ping. Can be also an IP address.
Returns 1 if the
remote host is reachable, otherwise returns 0 if unreachable
Example:
Print
PING("www.google.com")
Print
PING("192.168.1.1")
Important:
This is a
script-only function which doesn’t work in ‘immediate’ mode.
|
|
Return the number x
raised to the power of y
|
|
Returns the free
ram available (number of bytes)
|
|
Setup the RFID
module.
The module must be
connected using the SPI BUS (see wiring in the RFID chapter)
‘CS_pin’ is the pin
where the CS signal is connected
‘RST_pin’ is the
pin where the RST signal is connected.
The RST signal can
be left unconnected; in this case the value of -1 must be set.
This function returns a value following the
table below :
VALUE
|
REASON
|
0
|
Failed
|
18
|
Counterfeit chip
|
136
|
Clone
|
144
|
Version 0.0
|
145
|
Version 1.0
|
146
|
Version 2.0
|
255
|
Failed
|
|
|
Set the gain (sensitivity) of the RFID module
.
By default the gain is 4 and can range from 0
(minimum) to 7 (maximum)
|
|
Define another password if the card doesn’t
use the default FFFFFFFFFFFF
|
|
Reset the RFID
reader.
This is particularly
useful when reading using a wrong KEY as this function reset the
module and enables it to retry again with another KEY.
|
|
Awake the reader.
This is particularly
useful when reading using a wrong KEY as this function awake the
module and enables it to retry again with another KEY.
|
|
Write the NUID for
“UID changeable card”
See the RFID
chapter for more details
|
|
Write a block of 16
bytes to the RFID card
‘block’ is the
number of the block (from 0 to 63 for MIFARE 1K)
Data is a string
like “010102030405060708090A0B”
The function returns the following error
values:
MESSAGE
|
REASON
|
0
|
No
error
|
1
|
Error
during the authorisation phase.
Probably the password is not valid
|
2
|
Error
during the writing phase.
Probably trying to write into a read only block or the content to
be written is not valid
|
|
|
Returns a random
number in the range from 0 to ‘number' -1
If ‘number’ is
equal to 1, the result will be a value less than 1 but greater than
or equal to zero.
If ‘number’ is a
negative number, it will be used as seed by the pseudo-random
number generator algorithm. This will force a deterministic
sequence.
If used without
arguments (i.e. RND() ), it will return a value from the true
random generator with a random number in the range from 0 to 1.
|
|
Returns the number
of chars available in the receive buffer of the serial port
|
|
Returns the number
of chars available in the receive buffer of the serial port #2
|
|
Returns the sign of
the argument 'number', +1 for positive numbers, 0 for 0, and -1 for
negative numbers.
|
|
Returns the sine of
the argument 'number' in radians.
|
|
Write and receive a
byte on the SPI bus.
Send the content of
‘byte’ and returns the byte received
Example:
r =
SPI.BYTE(&haa)
|
|
Return the square
root of the argument ‘number’
|
|
Returns the tangent
of the argument 'number' in radians.
|
|
Returns a 16 bit
number representing the RGB565 conversion of a color specified with
8 bit resolution.
‘r’ is the
red component; must be in the range 0 to 255
‘g’ is the
green component; must be in the range 0 to 255
‘b’ is the
blue component; must be in the range 0 to 255
Example :
TFT.FILL
TFT.RGB(0,255,0) ‘ fill the screen with a full green
color
|
|
Converts a time in
format hh:mm:ss into UNIX FORMAT.
See also DATEUNIX,
and the complementary UNIXTIME$ and UNIXDATE$
|
|
Returns the state
of the 8 buttons installed on the module TM1638.
It returns an 8-bit
value where each bit is associated with a button
Example :
Print
TM1638.BUTTONS ‘print 1 if the button 1 is pressed
|
|
Returns the X
position of the touched position on the TFT screen.
Useful in
combination with the function TOUCH.Y and the command ONTOUCH
|
|
Returns the X
position of the touched position on the TFT screen.
Useful in
combination with the function TOUCH.X and the command ONTOUCH
|
|
Returns
the supplied string converted into a numeric value.
Example :
a$ = “12.34”
b = val(a$)
The same function
can also be used to convert from HEX :
a$ =
"&hFF01"
b = val(a$)
|
|
Returns the current
radio channel used for the WIFI communication.
Can be a number
from 1 to 13
|
|
Return the current
mode of the WIFI connection.
The returned value
is:
VALUE
|
MEANING
|
0
|
The WIFI is in sleep
mode
|
1
|
The WIFI is in STATION
mode
|
2
|
The WIFI is in AP mode
|
3
|
The WIFI in AP+STA mode
|
|
|
Returns
the number of networks found after the command WIFI.SCAN.
The
returned value is :
-2 if the scan is not started
-1 if the scan is not terminated
or the number of networks found (can be 0 if none)
The
variable ‘network$’ will contain the list of any networks
found.
‘network$’ will contain a line for each network with the SSID, the
BSSID and the RSSI separated by comma (,).
Example
:
WIFI.SCAN
While
WIFI.NETWORKS(A$) = -1
Wend
Print
a$
The
result will be (for example) :
Vodaphone, 00:50:56:C0:00:08, -50
Orange,
00:50:56:C0:32:07, -70
Xxxx, 00:50:56:C0:86:CA,-78
|
|
Returns the
intensity of the WIFI signal received when connected in STA
mode.
The unit of the
value received is in db from 0 (zero) to -120 (minus 120). The
closer the value to 0 (zero), the stronger the signal will be. An
RSSI of -55 (minus 55) is a stronger signal than -70 (minus
70).
|
|
Returns
the status of the WIFI connection.
The
returned value is :
VALUE
|
MEANING
|
0
|
IDLE
|
1
|
NO SSID
AVAILABLE
|
2
|
SCAN
COMPLETED
|
3
|
CONNECTED
|
4
|
CONNECTION
FAILED
|
5
|
CONNECTION
LOST
|
6
|
DISCONNECTED
|
255
|
OFF
|
|
|
This
function returns the number of words in the specified string.
The
string delimiter is optional; when it is not used, the space
character is the delimiter.
Example
:
a$ = "abc def
ghi ijk"
Print
WORD.COUNT(a$) ‘ will print 4
b$ =
"the-!-quick-!-brown-!-fox-!-jumps-!-over"
Print
WORD.COUNT(b$ "-!-") ‘ will print 6
See also WORD$,
WORD.DELETE$ and WORD.FIND.
|
|
This
function returns the word position in the string.
The
string delimiter is optional; when it is not used, the space
character is the delimiter.
If the word is not
found, the result is 0.
Example :
a$ = "abc def ghi ijk"
Print WORD.FIND(a$,
"ghi") ‘ will print 3
b$ =
"the-!-quick-!-brown-!-fox-!-jumps-!-over"
Print WORD.FIND(b$, "fox",
"-!-") ‘ will
print 4
See also WORD$,
WORD.DELETE$ and WORD.COUNT.
|
|
Return a string
representing the error message that would have normally been
displayed on the console. It is reset to “No Error” by: running the
program, or with the command ONERROR CLEAR, or ONERROR IGNORE, or
ONERROR SKIP.
|
|
Returns the name of
the current basic file
|
|
Transfer a file
stored locally on an FTP server.
Returns an explicit
text message as the result of the operation.
host$ is the
address of the FTP server
login$ is the login
of the account on the FTP server
password$ is the
password of the account on the FTP server
file$ is the file
that will be sent
folder$ is the
folder where the file will be sent
|
|
Returns the
password used for the STATION wifi connection.
|
|
Returns the content
of the CPU RTC internal memory.
This memory
maintains the contents between resets, so it is useful in
association with the SLEEP command when the module goes in low
power mode.
This memory is
limited at 7680 bytes and can be set with the corresponding
command BAS.RCTMEM$ = “xxx”.
The content of this
memory is lost in case of power OFF.
|
|
Returns the login
used for the STATION wifi connection.
|
|
Returns the version
of the Basic in string format
Example:
Print BAS.VER$
Annex WI-Fi Basic
1.36 beta
|
|
Returns the Binary
representation of the argument ‘number’.
The number is
converted to integer before the conversion.
|
|
Returns a string
containing the html representation of a button.
‘name$’ represent
the text shown in the button,
‘label’ is the
GOSUB label where it will branch to when clicked,
‘id’ is an optional
argument that can be used to define the ID of the object (useful to
style it with CSS).
The function called
when clicking on the button must always terminate with the RETURN
command
Check the chapter
about html objects for more details
|
|
Returns a string
containing the html representation of a checkbox.
‘variable’ is the
variable associated with the checkbox; changing the value of the
variable in the basic code will change also the value in the html
and vice-versa (0 = unchecked, 1 = checked).
The variable must
be Numerical.
‘id’ is an optional
argument and can be used to define the ID of the object (useful to
style it with CSS).
When the value is
changed by the user, the event ‘onHtmlChange’ is triggered.
Check the chapter
about html objects for more details
|
|
Returns a string
containing the ASCII character with the code ‘number’
Example: z$ =
CHR$(64)
now z$ contains the
"@" character
number must be
between 0-255
|
|
Returns a string
containing the css representation of style defined for a given
object.
‘object_id’
represents the ID of the object to be styled.
‘object _style’
represents the property to be given to the object.
Check the chapter
about html objects for more details
|
|
Returns the actual
date with the format dd/mm/yy
The time takes into
account the Time Zone parameter defined into the "Config" page.
If ‘format’ is
specified, the format can be :
format = 1
=> American format M/D/Y
format = 2 =>
Canadian format Y/M/D
|
|
Returns the MAC
address of the device(s) that didn’t received the message
|
|
Returns the message
received from the ESP-NOW peer
|
|
Returns the MAC
address of the emitter of the message received
|
|
Will search for
files and return the names of entries found.
'path$'
represents the directory name.
'path$' can
include wildcards characters as ‘*’, ‘.’ and ‘?’
The function will
return the first entry found.
To retrieve
subsequent entries use the function with no arguments. ie,
DIR$.
The return of an
empty string indicates that there are no more entries to
retrieve.
Example, to get all
the files present in the directory /html :
d$ =
FILE.DIR$("/html")
While D$ <>
""
Print d$
d$ =
FILE.DIR$
Wend
Valid wildcard
expressions are :
d$ =
FILE.DIR$(“/html/ex*.html”) ‘ returns all the files starting
with the “ex”
d$ =
FILE.DIR$(“/html/list.*”) ‘ returns all the files named
list.xxx
|
|
Returns the content
of the file ‘filename$’.
Specifying
'line_num', only the corresponding line is read from the file.
If start and length
options are specified, the file is read from the ‘start’ position
for ‘length’ characters, otherwise the complete file is read in one
go.
The line number
starts from 1.
If the line is not
existing (reached the end of file), the function will return
“_EOF_” to indicate the end of the file.
|
|
Returns the
Hexadecimal representation of the argument ‘number’
The number is
converted to integer before the conversion.
|
|
returns the name of the button that generates
the jump.
Useful to manage several buttons in the same
function
|
|
Returns the name of the variable changed
during the event onHtmlChange.
Useful to determine the object that changed
its value
|
|
Returns a string
containing the html representation of an image.
‘Path’ represents
the url of the image; it can be local or from the internet.
‘id’ is an optional
argument and can be used to define the ID of the object (useful to
style it with CSS)
Check the chapter
about html objects for more details
|
|
Returns a string
containing the html representation of an image that can be clicked
as a button.
‘Path’ represents
the url of the image; it can be local or from the internet.
‘label’ is the
GOSUB label where it will branch to when clicked,
‘id’ is an optional
argument and can be used to define the ID of the object (useful to
style it with CSS)
The function called
when clicking on the image must always terminate with the RETURN
command
Check the chapter
about html objects for more details
|
|
Returns the local
IP address, the Subnet mask and the Gateway address separated by
space.
Example:
Print IP$ ‘print
the complete address separated by single space
192.168.1.45
255.255.255.0 192.168.1.1
Print WORD$(IP$,1)
‘ will print only the IP
192.168.1.45
|
|
Returns the code
received by the IR receiver.
In function of the
param value, the function returns :
PARAM
|
RETURNED
VALUE
|
0 or
missing
|
Hexadecimal code
|
1
|
Decode
type
|
2
|
Address
|
3
|
Command
|
4
|
Bits
|
5
|
Repeat
|
Must be used in
association with the command IR.INIT and ONINFRARED
Example
IR.GET$ ‘ will
print the HEX code received
|
|
Will parse a json
string for a named data element within it.
If the element is
found, its value is returned in String format, else the text "not
found".
The key can have
the following syntax :
"Key.subkey.innerkey….." .
Array can
also be included such as "weather[5].description"
|
|
Returns ‘string$’
converted to lowercase characters
|
|
Returns a string
containing the html representation of a led.
‘variable’
represents the variable associated with the led; changing the value
of the variable in the basic code will change the led from red (0)
to green ( any value not equal to 0).
The variable must
be Numerical.
‘id’ is an optional
argument and can be used to define the ID of the object (useful to
style it with CSS)
Check the chapter
about html objects for more details
|
|
Returns the
leftmost ‘num’ characters of ‘string$’
|
|
Returns a string
containing the html representation of a listbox / combobox.
‘variable$’
represent the variable associated with the listbox;
changing the value
of the variable in the basic code will change also the value in the
html and vice-versa. The variable must be type String.
‘option1’,
‘option2’, …. represent the content of the listbox.
‘height’ is an
optional parameter and defines the height of the listbox; if not
specified, the object will be a combobox
‘id’ is an optional
argument used to define the ID of the object (useful to style it
with CSS).
When the value is
changed by the user, the event ‘onHtmlChange’ is triggered.
Check the chapter
about html objects for more details
|
|
Returns the active
MAC address. It consists of 6 hex bytes separated by colons.
It must be noted
that the MAC address can be different if the module is connected in
Station mode or in AP mode.
Example:
Print MAC$
62:01:94:5E:37:8D
Optionally it is
possible to select the address to be shown using the argument
‘id’
Example :
Print MAC$(0)
‘ print the Station mode address
60:01:94:5E:37:8D
Print MAC$(1) ‘
print the AP mode address
62:01:94:5E:37:8D
|
|
Returns a string
containing the html representation of a meter.
‘variable’
represents the variable associated with the slider; changing the
value of the variable in the basic code will change the value in
the html.
The variable must
be Numerical.
‘min’ and max
represent the minimum and maximum value of the meter.
‘id’ is an optional
argument which can be used to define the ID of the object (useful
to style it with CSS)
Check the chapter
about html objects for more details
|
|
Returns a substring
of ‘string$’ starting from ‘start’ with a length of ‘num’
characters. If ‘num’ is not defined, the result will continue until
the end of the line
Start must be
integer starting at 1
example:
z$="Hello
World"
wlog mid$(z$,4,5)
‘will print "lo Wo"
|
|
Returns the MQTT message received
|
|
Returns the MQTT topic received or the event
name.
The event can be:
Value
|
Event
|
_BEFORE_CONNECT_
|
Raised before the
connection is done. Useful to determine if the module is trying to
(re)connect
|
_CONNECTED_
|
Raised when the
connection is done
|
_DISCONNECTED_
|
Raised when the
connection is lost
|
_ERROR_
|
Raised in case of
error
|
|
|
Returns the Octal
representation of the argument ‘number’
The number is
converted to integer before the conversion.
|
|
Returns a string
containing the html representation of a password textbox..
‘variable’
represents the variable associated with the textbox; changing the
value of the variable in the basic code will change also the value
in the html and vice-versa. The variable can be Numerical or
String.
‘id’ is an optional
argument which can be used to define the ID of the object (useful
to style it with CSS)
Check the chapter
about html objects for more details
|
|
Returns a substring
of ‘expression$’ where any instances of the text inside ‘find$’ is
replaced with ‘replacewith$’
|
|
Returns the NUID of the RFID card detected
|
|
Returns the type (model) of the RFID card detected
It can return any of the following values:
TYPE
|
PICC
compliant with ISO/IEC 14443-4
|
PICC
compliant with ISO/IEC 18092 (NFC)
|
MIFARE Mini, 320 bytes
|
MIFARE 1KB
|
MIFARE 4KB
|
MIFARE Ultralight or Ultralight C
|
MIFARE Plus
|
MIFARE DESFire
|
MIFARE TNP3XXX
|
SAK
indicates UID is not complete.
|
Unknown type
|
|
|
Reads a block of 16
bytes from the RFID card.
‘block’ is the
number of the block (from 0 to 63 for MIFARE 1K)
‘key_b’ if not
present or 0 the card will be read using the KEY A
If ‘key_b” is equal
to 1, the card will be read using the KEY B
The result will be
a string like “010102030405060708090A0B0C0D0E0F”
or a message indicating that an error is
occurred :
MESSAGE
|
REASON
|
Auth
Failed
|
Error
during the authorisation phase.
Probably the password is not valid
|
Read
Failed
|
Error
during the reading phase.
Probably the card has been moved too far from the reader
|
|
|
Returns the
rightmost ‘num’ characters of ‘string$’
|
|
Returns the RTC
module date with the format dd/mm/yy
The module can be
DS1307 or DS3231
If ‘format’ is
specified, the format can be :
format = 1
=> American format M/D/Y
format = 2 =>
Canadian format Y/M/D
See also the
RTC.SETTIME and RTC.TIME$
NOTE : If no RTC is
connected, (or is not connected correctly) then will return
"165/165/165"
|
|
Returns the RTC
module time with the format hh:mm:ss.
The module can be
DS1307 or DS3231
See also the
RTC.SETTIME and RTC.DATE$
NOTE : If no RTC is
connected, (or is not connected correctly) then will return
"45:165:165"
|
|
Returns the first
character present in the input buffer of the serial port
Useful in
association with the command ONSERIAL
|
|
Returns all the
characters present in the input buffer of the serial port.
Useful in
association with the command ONSERIAL
|
|
Returns the first
character present in the input buffer of the serial port #2
Useful in
association with the command ONSERIAL
|
|
Returns all the
characters present in the input buffer of the serial port #2
Useful in
association with the command ONSERIAL2
|
|
Returns a string
containing the html representation of a slider.
‘variable’
represents the variable associated with the slider; changing the
value of the variable in the basic code will change also the value
in the html and vice-versa. The variable must be Numerical.
‘Min’ and max
represent the minimum and maximum value of the slider.
The optional
argument ‘step’ represents the minimal increment (by default the
value is 1).
‘id’ is an optional
argument which can be used to define the ID of the object (useful
to style it with CSS).
When the value is
changed by the user, the event ‘onHtmlChange’ is triggered.
Check the chapter
about html objects for more details
|
|
Returns a string
consisting of the specified number of spaces.
|
|
Write and receive a
string on the SPI bus.
Write the content
of ‘len’ characters of the string ‘data$’
Example:
a$ =
SPI.STRING("hello", 5)
|
|
Write and receive
an HEX string on the SPI bus.
The string is a
sequence of hex characters (2 for each byte)
Write the content
of ‘len’ characters of the string ‘data$’
Example:
a$ =
SPI.HEX("A0B1C2D3E4F5", 6) ‘ send 6 bytes (sequence of A0, B1, C2,
D3, E4, F5) and receive the result in a$
|
|
Returns the
argument ‘‘number’ converted to string format.
The optional
‘format$’ permits to define how the number is printed.
The format is based
on ‘C’ printf command.
The additional ",1"
is required for the number types marked “Integer” in the table
below.
Example :
a = 12.34567890
Print STR$(a,
"%7.4f") ‘ will print 12.3456
Print STR$(a,
"%8.5f") ‘ will print 12.34567
a = 255
Print STR$(a,
"%04x", 1) ‘ will print 00FF ‘HEX
Print STR$(a,
"%04o", 1) ‘ will print 0377 ‘OCT
The formats
available are :
FORMAT
|
DESCRIPTION
|
TYPE
|
c
|
Char
|
Integer
|
d
|
Signed
Integer
|
Integer
|
e
|
Exponential
|
Float
|
f
|
Floating Point
|
Float
|
g
|
Use
shorter of the two formats
f or
e
|
Float
|
o
|
Octal
|
Integer
|
p
|
Pointer
(8 digits hex)
|
Integer
|
P
|
Pointer
without 0x
|
Integer
|
u
|
Unsigned Integer
|
Integer
|
x
|
Hexadecimal (lower case letters)
|
Integer
|
X
|
Hexadecimal (upper case letters)
|
Integer
|
The format must
observe the following rule :
%[integer_with][.][precision][format]
For example to
specify a floating number composed of 4 digits before the decimal
point and 3 digit after the point you must write : %4.3f
Example for several
formats
Format
|
Number
|
Result
|
%2.1f
|
14.33
|
14.3
|
28.128
|
28.1
|
%4.3f
|
15
|
15.000
|
4152.3751
|
4152.375
|
%1.4e
|
128
|
1.2800e+02
|
12852
|
1.2852e+02
|
%04f
|
12
|
0012
|
%4x
|
255
|
ff
|
%04X
|
255
|
00FF
|
|
|
Returns
a string ‘num’ chars long composed of the char ‘char$’ - char$ can
also be a string of chars, eg: "<BR>" or " "
|
|
Returns
information from the DS18B20 temperature sensor
The
syntax is a$ = TEMPR$(pin_number [, ID])
The
‘pin number’ is any available pin of the device; it can change
between calls permitting to use several pins at the same time.
The ID
can be a number, a String, or not specified:
- If is
a number (say 'n'), the result will be the temperature (in °C) of
the nth device connected on that pin
- If is
a string, it must contains the Hex address of the device requested;
this address can be recovered using the command without this
argument
- If
not specified, the result will be the address list of the devices
connected on the pin (blocks of 8 bytes separated by ',')
Example
using 2 DS18B20 are connected on the pin 12 :
Print
TEMPR$(12,1) ‘ will print 20.5
Print TEMPR$(12,2)
‘ will print 22.3
Print
TEMPR(12) ‘will print 28ff5bdb701604f0,28ff5bdb7016045
Print
TEMPR(12,"28ff5bdb701604f0") ‘will print 20.5
The sensors can
also be read in async mode:
Giving 0 as ID,
starts the conversion on all the DS18B20 sensors connected without
waiting for the answer
For example
ret$ = TEMPR$(2, 0)
' starts an async read on the pin 2
The result will be
the string "START"
Then, it will be
possible to read the devices as below
ret1$ = TEMPR$(2,
1) 'read the 1st sensor on the pin 2
ret2$ = TEMPR$(2,
2) 'read the 2nd sensor on the pin 2
In this case, if
the value is not yet available (during the conversion time) the
result will be "WAIT' that will be replaced by the good value at
the end of the conversion.
To restart another
conversion, the same command must be executed
ret$ = TEMPR$(2, 0)
' starts an async read on the pin 2
|
|
Returns a string
containing the html representation of a textarea.
‘variable’
represent the variable associated with the textarea;
changing the value
of the variable in the basic code will change also the value in the
html and vice-versa. The variable can be Numerical or String.
‘id’ is an optional
argument and can be used to define the ID of the object (useful to
style it with CSS).
‘Variable’ can have
several lines separated by the character chr$(13).
When the value is
changed by the user, the event ‘onHtmlChange’ is not triggered
automatically but only when the focus is lost (for example when
another html element is selected).
Check the chapter
about html objects for more details
|
|
Returns a string
containing the html representation of a textbox.
‘variable’
represent the variable associated with the textbox;
changing the value
of the variable in the basic code will change also the value in the
html and vice-versa. The variable can be Numerical or String.
‘id’ is an optional
argument which can be used to define the ID of the object (useful
to style it with CSS).
When the value is
changed by the user, the event ‘onHtmlChange’ is triggered.
Check the chapter
about html objects for more details
|
|
Returns ‘string$’
with the leading and trailing spaces removed
|
|
Returns the actual
time with the format hh:mm:ss.
The time takes into
account the Time Zone parameter defined into the "Config" page.
|
|
Returns ‘string$’
converted to uppercase characters
|
|
Returns the UDP
message received, or an empty string if no message received.
Useful in
association with the command ONUDP
|
|
Returns the IP
address and the port of the sender of the message received.
The format is IP:port (example 192.168.1.88:5541).
Useful in
association with the command ONUDP
|
|
Returns a date with
the format dd/mm/yy extract from ‘value’ given in UNIX format. The
value can be Numerical or String.
This is useful to
extract the date from the JSON string given by OpenWeatherApi
if ‘format’ is
specified, the format can be :
format = 1
=> American format M/D/Y
format = 2 =>
Canadian format Y/M/D
See also the
complementary DATEUNIX()
|
|
Returns a time with
the format hh:mm:ss extract from ‘value’ given in UNIX format. The
value can be Numerical or String.
This is useful to
extract the time from the JSON string given by OpenWeatherApi
See also the
complementary TIMEUNIX()
|
|
Get the message
received from the URL AJAX GET request.
Returns the value
of the url argument defined in arg$.
If arg$ is missing,
all the arguments are returned (useful for debugging).
Useful in
combination with ONURLMESSAGE and URLMSGRETURN
Example : if a
remote client makes the following url request :
http://esp_local_ip/msg?red=10&green=20&blue=30
Print
URLMSGGET$("red") ‘ will return 10
Print
URLMSGGET$("green") ‘ will return 20
Print
URLMSGGET$("blue") ‘ will return 30
Print URLMSGGET$()
‘ will return red=10&green=20&blue=30
More information here
|
|
Returns the result
of a GET server request.
‘http_server$’ is
the server url request
‘port’ is the port
number; if port=443, the connection will be done using SSL
(secure).
‘Header’, if =1,
will include the header in the answer (useful for debug)
The program will
stop waiting for the answer.
Example :
print
WGET$("www.fakeresponse.com/api/?sleep=5", 80)
In this case the
program will stop 5 seconds waiting for the answer of the
server.
See the command
WGETASYNC to avoid this limitation.
|
|
Returns the result
of a GET server request.
url$’ is the web
server url request
if ‘url$’ starts
with https:// , the connection will be done using SSL
(secure).
‘Header’, if =1,
will include the header in the answer (useful for debug)
The program will
stop waiting for the answer.
Example :
print
WGET$("https://jsonplaceholder.typicode.com/comments?id=1&id=4")
In this case the
program will stop waiting for the answer of the server.
See the command
WGETASYNC to avoid this limitation.
|
|
Return the message
received asynchronously from the command WGETASYNC
|
|
This function
returns the nth word in the string, where n=1 or greater.
The string
delimiter is optional; when it is not used, the space character is
the delimiter.
Example :
a$ = "abc def ghi
ijk"
Print WORD$(a$,
3) ‘ will print ghi
b$ =
"the-!-quick-!-brown-!-fox"
Print WORD$(b$, 2,
"-!-") ‘ will print quick
See also
WORD.COUNT, WORD.FIND and WORD.DELETE$
|
|
This function
returns a string where the nth word has been deleted.
The string
delimiter is optional; when it is not used, the space character is
the delimiter.
Example :
a$ = "abc def ghi
ijk"
Print
WORD.DELETE$(a$, 3) ‘ will print abc def ijlk
b$ =
"the-!-quick-!-brown-!-fox"
Print
WORD.DELETE$(b$, 2, "-!-") ‘ will print the-!-brown-!-fox
See also WORD,
WORD.COUNT and WORD.FIND.
|
|
Returns the
substring included between lead$ and trail$.
Example
a$ = “https://www.google.com/test”
Print
WORD.EXTRACT$(a$, “https://”, “/test”) ‘ will print
www.google.com
|
|
Get a parameter
from a string containing a series of parameters stored as
below:
param1=value1
param2=value2
…….
paramx=valuex
‘setting$’ defines
the string containing the set of parameters
‘parameter$’
defines the parameters to be got.
‘separator$’ is an
optional parameter specifying a different separator character.
Example, assuming
that setting$ contains the parameters :
print
WORD.GETPARAM$(setting$, "param2")‘will print value2
By default the
separator is the character ‘=’.
Useful in
combination with WORD.SETPARAM and FILE.READ$
|
|
Returns the result
of a POST server request.
‘http_server$’ is
the server url request
‘body$’ is the
field that will be sent in the request
‘port’ is the port
number; if port=443, the connection will be done using SSL
(secure).
‘Header’, if =1,
will include the header in the answer (useful for debug)
The program will
stop while waiting for the answer.
Example :
print
WPOST$("ptsv2.com/t/annextest/post", "name=Annex&version=1.39",
80)
|
|
Returns the result
of a POST server request.
‘url$’ is the web
server url request
‘body$’ is the
field that will be sent in the request
If ‘url$’ starts
with https:// the connection will be done using SSL
(secure).
‘Header’, if =1,
will include the header in the answer (useful for debug)
The program will
stop while waiting for the answer.
Example :
print
WPOST$("https://ptsv2.com/t/annextest/post",
"name=Annex&version=1.39")
|
|
Same function of
the command REFRESH but with an automatic interval.
Define the
variables refresh interval in milliseconds.
This should never
be lower than 300ms due to performance reasons.
NOTE: It must be
run after the command CLS as it is managed into the javascript.
|
|
Loads another .bas
program and runs it immediately.
Returns 0 if the
successful or -1 if the file was not found
Example:
Print BAS.LOAD
"/test.bas"
|
|
Set the content of
the CPU RTC internal memory.
This memory
maintains the content between reset, so it is useful in association
with the SLEEP command when the module goes in low power mode.
The content of this
memory is lost in case of power OFF.
This memory is
limited at 7680 bytes, and can be read with the corresponding
command val$ = BAS.RCTMEM$
|
|
Clear
the html content of the page to all the clients connected by
Websockets.
Check
the chapter about html objects for more details
See
also the commands HTML, JSCALL, JSCRIPT, JSEXTERNAL, CSS and
WLOG
|
|
Send a CSS style
code to the page to all the clients connected by Websockets.
Check the chapter
about html objects for more details
See also the
commands HTML, JSCALL, JSCRIPT, JSEXTERNAL, CLS and WLOG
|
|
Permit to execute
any basic command defined into ‘cmd$’.
It acts as a macro
command like the immediate window
Example :
COMMAND ("print
sin(PI/2)") ‘will print 1
|
|
Reset the counter
to 0 (count and period).
‘cnt” defines the
counter and can be 1 or 2
|
|
Setup a counter in
association with a pin.
There are 2
counters that can count the number of pulses or the period between
pulses.
‘cnt” defines the
counter and can be 1 or 2
‘pin’ defines the
pin and can be any valid pin number
‘mode’ defines the
when the pulses are taken into account :
MODE
|
EDGE
|
1
|
On the RISING
edge
|
2
|
On the FALLING
edge
|
3
|
On CHANGE
|
If not
specified, the mode is 3 (on change)
|
|
Define an external
css file to be used in the page of all the clients connected by
Websockets.
Check the chapter
about html objects for more details
See also the
commands CLS, HTML, JSCALL, JSCRIPT, CSS and WLOG
|
|
Stores numerical
and string constants to be accessed by READ.
String constant
must be between double quotes "
Expressions can be
used for the numerical constants (ex. PI * 2)
|
DECR var [,
decrement]
|
Decrements the
variable "var" by 1 or, if specified, by the value in
"decrement".
This functionally
is equivalent to var = var - decrement but executes more
efficiently.
|
|
Set the parameters
for Temperature / Humidity sensor DHT11, DHT21 or DHT22
The syntax is
DHT.SETUP pin, model
The pin number is
any available pin of the device;
The model can be
11, 21 or 22 (for DHT11, DHT21 or DHT22)
See also the
functions DHT.TEMP, DHT.HUM and DHT.HEATINDEX
|
|
Setup the
parameters for an SMTP server to be used to send e-mails.
This command must
be executed before using the command EMAIL or EMAILASYNC.
An SMTP account
like <mail.smtp2go.com> is required.
NEW : The command
uses an SSL connection, so it should work with any SMTP service
provider; the port should be 465
‘server$’ is the
url of the service provider (ex. mail.smtp2go.com)
‘Port’ is the port
required (ex. 465)
‘user_name$’ is the
login name of the SMTP account
‘password$’ is the
password of the SMTP account
All the parameters
are required.
The last optional
parameter ‘debug’ if set to 1, enables a debug mode useful to catch
connection problems.
Example :
EMAIL.SETUP
"mail.smtp2go.com", 465, "my_login", "my_pass"
|
|
Send an e-mail in
async mode; this means that the request is managed in the
background and the program will continue to run without
interruptions.
‘from$’ is the
email address of the sender (ex: from_me@yahoo.com)
‘to$’’ is the email
address of the receiver (ex: to_you@yahoo.com)
‘subject$’ is the
subject of the message
‘message$’ is the
content of the message
The sender and
receiver must be a valid email addresses.
Example :
EMAILASYNC
("from_me@yahoo.com", "to_you@gmail.com", "Important message " +
date$, "The memory available is " + str$(ramfree) )
|
|
Convert the file defined ‘source$’ into the
file defined in ‘dest$’.
The source file can be in any format but must
be encoded in base64 format.
Useful for wokwi to store any file in text
format
|
|
Save the content of
‘content$’ in the file ‘filename$’.
The file can be
read back using the function FILE.READ$(filename$).
File size is only
limited by available disk space (FFAT or external SD card)
|
|
Convert the file defined ‘source$’ into the
file defined in ‘dest$’.
The source file can be in any format and will
be encoded in base64 format.
|
|
Initialise the
FUSION IMU / AHRS algorithm
|
|
Execute the
MADGWICK 6 DOF algo
The input
parameters are the following :
PARAM
|
MEANING
|
UNITY
|
ax
|
Acceleration on x axis
|
g *
|
ay
|
Acceleration on y axis
|
g *
|
az
|
Acceleration on z axis
|
g *
|
gx
|
Gyro on x axis
|
°/sec
|
gy
|
Gyro on y axis
|
°/sec
|
gz
|
Gyro on z axis
|
°/sec
|
(*) the unit is not
really important but must be consistent between the group
This algo utilise
the variables FUSION.BETA and FUSION.ZETA
|
|
Execute the
MADGWICK 9 DOF algo
The input
parameters are the following :
PARAM
|
MEANING
|
UNITY
|
ax
|
Acceleration on x axis
|
g *
|
ay
|
Acceleration on y axis
|
g *
|
az
|
Acceleration on z axis
|
g *
|
gx
|
Gyro on x axis
|
°/sec
|
gy
|
Gyro on y axis
|
°/sec
|
gz
|
Gyro on z axis
|
°/sec
|
mx
|
Magnetometer on x axis
|
milligauss *
|
my
|
Magnetometer on y axis
|
milligauss *
|
mz
|
Magnetometer on z axis
|
milligauss *
|
(*) the unit is not
really important but must be consistent between the group
This algo utilise
the variable FUSION.BETA
|
|
Execute the MAHONY
9 DOF algo
The input
parameters are the following :
PARAM
|
MEANING
|
UNITY
|
ax
|
Acceleration on x axis
|
g *
|
ay
|
Acceleration on y axis
|
g *
|
az
|
Acceleration on z axis
|
g *
|
gx
|
Gyro on x axis
|
°/sec
|
gy
|
Gyro on y axis
|
°/sec
|
gz
|
Gyro on z axis
|
°/sec
|
mx
|
Magnetometer on x axis
|
milligauss *
|
my
|
Magnetometer on y axis
|
milligauss *
|
mz
|
Magnetometer on z axis
|
milligauss *
|
(*) the unit is not
really important but must be consistent between the group
This algo utilise
the variables FUSION.KP and FUSION.KI
|
|
Set the BETA
parameter. This is used for the MADGWICK algo 6 DOF and 9 DOF.
|
|
Set the ZETA
parameter. This is used for the MADGWICK algo 6 DOF.
|
|
Set the KI
parameter. This is used for the MAHONY algo 9 DOF.
|
|
Set the KP
parameter. This is used for the MAHONY algo 9 DOF.
|
|
Send html content
to the page of all the clients connected by Websockets.
Check the chapter
about html objects for more details
See also the
commands CLS, JSCALL, JSCRIPT, JSEXTERNAL, CSS and WLOG
|
|
Initiate the Wire library and join the I2C bus as a master. The
‘sda_pin’ and ‘scl_pin’ define the pins to be used as SDA and SCL
signals.
The
frequency (up-to 4 Mhz) can be defined using the parameters ‘freq’
in hertz
Example:
I2C.SETUP 21, 22 ‘ define the pin 21 as SDA and the pin 22 as
SCL
|
|
Begin a
transmission to the I2C slave device with the given address.
Subsequently, queue bytes for transmission with the I2C.WRITE
command and transmit them by calling I2C.END command.
‘address’ defines the 7-bit address of the device to transmit
to
Example:
I2C.BEGIN &h57 ‘ begins the transmission on the address hex
57
|
|
Ends a
transmission to a slave device that was begun by I2C.BEGIN and
transmits the bytes that were queued by I2C.WRITE.
Example:
I2C.END
It can
also returns a value indicating the status of the transmission:
0:success
1:data
too long to fit in transmit buffer
2:received NACK on transmit of address
3:received NACK on transmit of data
4:other
error
Example:
stat = I2C.END
|
|
Used by
the master to request bytes from a slave device. The bytes may then
be retrieved with the I2C.LEN and I2C.READ functions.
‘address’ defines the 7-bit address of the device to request bytes
from
‘Length’ defines the number of bytes to request
Example:
I2C.REQFROM &h57, 8 ‘ requests for 8 bytes from the address hex
57
|
|
Read a
series of bytes from a slave device using a given device register
address.
The
result is copied into an array given as argument.
Each
received byte will be placed into an element of the array (starting
from 0).
The
array must be defined before the command with enough space to
receive the bytes.
Example
:
Dim
MyArray(10) : i2c_addr = &h60 : register = 33 : length = 7
I2C.ReadRegArray i2c_addr , register, length , MyArray()
Will
read 7 bytes from the register address 33 on the device with i2c
address &h60.
The
result will be placed into MyArray where MyArray(0) will contain
the 1st received byte, MyArray(1) the 2nd, …..
For
clarification, this command is equivalent to the following
program:
i2c.begin i2c_addr
i2c.write register
i2c.end
i2c.reqfrom i2c_addr, length
for i = 0 to length - 1
MyArray(i) = i2c.read
next i
i2c.end
|
|
Writes
queues bytes for transmission from a master to slave device
(in-between calls to I2C.BEGIN and I2C.END).
‘value’
represents a value to send as a single byte
Example:
I2X.WRITE &h55
|
|
Write a byte to a
slave device using a given device register address.
‘i2c_address’
define the I2C slave address
‘register’ defines
the device register
‘value’ defines the
value to be written into the device
Example:
i2c_addr = &h60
: register = 33 : value = 55
I2C.WriteRegByte
i2c_addr , register, value
Will write 55 in
the register address 33 on the device with i2c address
&h60.
For clarification,
this command is equivalent to the following program:
i2c.begin
i2c_addr
I2c.write
register
i2c.write
value
i2c.end
|
|
Write a series of
bytes to a slave device using a given device register address.
The values to be
written are taken from an array given as argument.
Each byte must be
placed into an element of the array (starting from 0).
The array must be
defined before the command and set with the desired byte sequence
to be sent
Example :
Dim MyArray(10) :
MyArray(0) = 12 : MyArray(1) = 34 : MyArray(2) = 56
i2c_addr = &h60
: register = 33 : length = 3
I2C.WriteRegArray
i2c_addr , register, length , MyArray()
Will write 3 bytes
to the register address 33 on the device with i2c address
&h60.
The sequence 12,
34, 56 will be written to the device
For clarification,
this command is equivalent to the following program:
i2c.begin
i2c_addr
i2c.write
register
for i = 0 to
length - 1
i2c.write MyArray(i)
next i
i2c.end
|
|
Increments the
variable "var" by 1 or, if specified, by the value in
"increment".
This functionally
is equivalent to var = var + increment but executes more
efficiently.
|
|
Define the time (in
milliseconds) that the INPUT command will wait for an input from
the serial port (console). After this time the INPUT will return an
empty value.
INPUT.TIMEOUT 0
removes the timeout
|
|
Allows input from
the console to a variable.
The input command
will prompt with a question mark (?).
If the "prompt
string$" is specified it will be printed before the question
mark.
During the input
command the execution of the program will be stopped waiting for an
input from the serial port. This can be an issue as the program can
get stuck.
The command
INPUT.TIMEOUT will permit to interrupt the command after a given
timeout duration to prevent it waiting for input indefinitely.
|
|
Specifies a branch
label for the interrupt to jump to when the designated input pin
signal changes. The optional 'mode' parameter allows you to specify
the trigger condition for the interrupt: rising edge, falling edge,
or any change in signal. The 'OFF' keyword can be used to remove
the interrupt associated with the specified input pin.
Parameters:
- pin_no: The input
pin number for which the interrupt is being defined. It must be an
integer value ranging from 0 to 39.
- label: The branch
label to which the program will jump when the designated input pin
signal changes. It must be a valid label in the program's
context.
- OFF: Use this
keyword to remove the interrupt associated with the specified input
pin.
- mode (optional):
An integer parameter specifying the trigger condition for the
interrupt. It can take one of the following values:
- 1, RISING:
Rising edge trigger
- 2,
FALLING: Falling edge trigger
- 3, CHANGE:
Any change in signal trigger (default if 'mode' parameter is
omitted)
|
|
Initialise the IR
receiver and the IR transmitter
‘pin_rx’ is the pin
where the IR receiver is connected
‘pin_tx’ is the pin
where the IR led is connected
If ‘pin_rx’ is OFF,
the receiver is disabled
If ‘pin_tx’ is not
defined, the transmitter is disabled
Example :
IR.INIT 14, 12
‘define the pin 14 for the receiver and the pin 12 for the
transmitter
|
|
Send a code via the
IR transmitter
‘type’ is the type
of RC (3 = NEC, ...)
‘code$’ is the code
in hexadecimal format
‘bits’ is the
number of bits (32, ...)
|
|
Send javascript
content to the page of all the clients connected by Websockets.
Check the chapter
about html objects for more details
See also the
commands CLS, HTML, JSCRIPT, JSEXTERNAL, CSS and WLOG
|
|
Execute a
javascript content in the page of all the clients connected by
Websockets.
Check the chapter
about html objects for more details
See also the
commands CLS, HTML, JSCALL, JSEXTERNAL, CSS and WLOG
|
|
Define an external
javascript file to be used in the page of all the clients connected
by Websockets.
Check the chapter
about html objects for more details
See also the
commands CLS, HTML, JSCALL, JSCRIPT, CSS and WLOG
|
|
Initialize a LCD
display connected using I2C to the module.
‘address’ is the
I2C slave address of the LCD display
‘cols’ is the
number of columns of the LCD display
‘rows’ is the
number of rows of the LCD display
Before using it,
the I2C bus must be initialised with the command I2C.SETUP
Example:
I2C.SETUP 21, 22 ‘init the I2C on pins 21 and 22
LCD.INIT 63, 20, 4 ‘init the LCD at I2C address 63 with 20
columns and 4 rows
LCD.PRINT 1,1 "HELLO WORLD"
|
|
Clear the content
of the LCD display connected using I2C to the module
|
|
Print a text on the
LCD.
‘x’ and ‘y’ define
the position where ‘text$’ will be printed
|
|
Defines local
variables inside user named subroutines.
Using this command
inside the subroutines, permits to create variables that exist only
during the routine; they will vanish at the end of the routine.
This will permit also to avoid to unintentionally modify variables
that have the same name which were already used elsewhere in the
code.
See the paragraph
"Scope of the variables" for more details.
Example:
LOCAL I,
A$
|
|
Setup a
8 digit 7-segments display based on the chip MAX7219.
The display must be
connected using the SPI bus plus a CS_pin.
‘CS_pin’ defines the pin used for the CS signal
Example:
MAXDISPLAY.SETUP 15
|
|
Print a
message on the 8 digit 7-segments MAX7219 display.
All ASCII
characters can be used but will be shown within the limitation of
the 7 segments of the display.
‘msg$’ defines the
message to be printed
‘brightness”
defines the luminosity of the display from 0 (blank) to 15
(max)
By default the
luminosity is at 15
|
|
Set Up
a DotMatrix chain display based on the chip MAX7219.
The
chain can be composed by one or more modules in daisy chain.
The
display must be connected using the SPI bus plus a CS_pin.
‘Nb_devices’ defines how many modules are connected
‘CS_pin’ defines the pin used for the CS signal
Example
for a 4 digit module available on ebay :
MAXSCROLL.SETUP 4, 15 ‘ 4 digits, CS on pin 15
|
|
Print a
message on the DotMatrix Display.
The
message will be shown using the command MAXSCROLL.SCROLL
‘msg$’
defines the message to be shown
|
|
Define
the message that will be shown on the DotMatrix Display as soon as
the message set with the command MAXSCROLL.PRINT is terminated.
Permit
to maintain a continuity on the message shown.
‘msg$’
defines the message that will be printed
|
|
Set a new message
without resetting the message at the initial position.
Useful to modify
the message while it’s already scrolling.
‘msg$’ defines the
new message to be shown
|
|
Show in a given
position the message defined with the command MAXSCROLL.PRINT or
the command MAXSCROLL.NEXT
‘Pos’ define the
position of the message (in pixels)
‘brightness”
defines the luminosity of the display from 0 (blank) to 15
(max)
The position 1 if the rightmost line of the
display and increasing this value will move the text more on the
left. Decrementing (negative numbers) this value will move the text
more on the right.
|
|
Execute
a single pixel scroll from the right to left of the message set on
the DotMatrix display. In order to maintain a continuity of the
scrolling, this command must be called on a timed interval (using a
timer)
‘brightness”
defines the luminosity of the display from 0 (blank) to 15
(max)
|
|
Execute a single
pixel scroll oscillating the message set on the DotMatrix display.
In order to maintain a continuity of the scrolling, this command
must be called on a timed interval (using a timer)
‘brightness”
defines the luminosity of the display from 0 (blank) to 15
(max)
|
|
Set, in
a stripline, the led at position 'led_pos' with the color
R,G,B.
The
optional argument 'disable' (if = 1) is useful for updating several
pixels together; it will write the new value into memory, but it
will not be displayed until the next non-‘disable’ write causes all
‘disabled’ pixels to display their updated values at the same
time.
|
|
Set, in a
stripline, the led at position 'led_pos' with the color
‘COLOR’.
The content of
‘COLOR’ is a merged color value; it can be generated using the
function NEO.RGB().
The optional
argument 'disable' (if = 1) will permit to write in the memory
without refreshing the strip; this is useful to show several leds
at the same time
|
|
The
NEOPIXEL are led strips based on the WS2812 Leds
define
the pin to be used for the NEO PIXEL commands
‘Pin’
define the pin number to be used
Optionally it is possible to define the number of leds presents in
the string.
By
default the strip contains 512 leds.
NOTE:
it is recommended to define the number of leds to have a faster
refresh, in particular for small strips.
|
|
Set, in
a stripline, the leds from the position 'led_start_pos' to
'led_end_pos' with the color R,G,B.
The optional
argument 'disable' (if = 1) will permit to write in the memory
without refreshing the strip; this is useful to show several leds
at the same time
|
|
Set, in a
stripline, the leds from the position 'led_start_pos' to
'led_end_pos' with the color ‘COLOR’
The content of
‘COLOR’ is a merged color value; it can be generated using the
function NEO.RGB().
The optional
argument 'disable' (if = 1) will permit to write in the memory
without refreshing the strip; this is useful to show several leds
at the same time
|
|
Set Up a NeoMatrix
chain display based on WS2812 dot matrix led modules.
The chain can be
composed by one or more modules in daisy chain.
The display must be
connected using a single pin
‘Nb_devices’
defines how many modules are connected
‘pin’ defines the
pin used for the signal
‘Serpentine’
defines if the display is arranged as a serpentine; can be 0
(normal) or 1 (serpentine). By default is 0.
Example for a 4
digit module available on ebay :
NEOSCROLL.SETUP 4,
15 ‘ 4 digits, using the pin 15
|
|
Print a message on
the NeoMatrix Display.
The message will be
shown using the command NEOSCROLL.SCROLL
‘msg$’ defines the
message to be shown
|
|
Define the message
that will be shown on the NeoMatrix Display as soon as the message
set with the command NEOSCROLL.PRINT is terminated.
Permit to maintains
a continuity on the message shown.
‘msg$’ defines the
message that will be printed
|
|
Defines the colors
associated with the character to be shown on the NeoMatrix display.
The logic of the colors is described in the specific NeoMatrix
chapter
|
|
Defines the colors
of the message defined with the command NEOSCROLL.NEXT
|
|
Show in a given
position the message defined with the command NEOSCROLL.PRINT or
the command NEOSCROLL.NEXT
‘Pos’ define the
position of the message (in pixels)
‘brightness”
defines the luminosity of the display from 0 (blank) to 255
(max)
The position 1 if the rightmost line of the
display and increasing this value will move the text more on the
left. Decrementing (negative numbers) this value will move the text
more on the right.
|
|
Set a new message
without resetting the message at the initial position.
Useful to modify
the message while it’s already scrolling.
‘msg$’ defines the
new message to be shown
|
|
Execute a single
pixel scroll from the right to left of the message set on the
DotMatrix display. In order to maintain a continuity of the
scrolling, this command must be called on a timed interval (using a
timer)
‘brightness”
defines the luminosity of the display from 0 (blank) to 255
(max)
|
|
Execute a single
pixel scroll oscillating the message set on the DotMatrix display.
In order to maintain a continuity of the scrolling, this command
must be called on a timed interval (using a timer)
‘brightness”
defines the luminosity of the display from 0 (blank) to 255
(max)
|
|
Clear the content
of the OLED display connected using I2C to the module
|
|
Initialise an OLED
display connected using I2C to the module.
‘orientation’ is a
number that can be 0 or 1 specifying the orientation:
0
|
Landscape
|
1
|
Landscape
reversed
|
By default the OLED
SSD1306 is enabled but specifying ‘model’ as 1 the display SSH1106
will be enabled.
The OLED predefined
I2C address is 60 (3c in hex).
Before using it,
the I2C bus must be initialised with the command I2C.SETUP
Example :
I2C.SETUP 21,
22 ' set I2C port on pins 21 and 22
OLED.INIT 1 ‘ init
OLED at landscape reversed
In case of the display SH1106, the command
is
OLED.INIT 1, 1 'init OLED at landscape
reversed, SSH1106
|
|
Defines
how the image is sent on the OLED after each drawing command.
If
‘fmt’ = 1, the image is automatically refreshed after each drawing
command.
If
‘fmt’ = 0, the image must be manually refreshed with OLED.REFRESH
0
This
method provides a double buffer permitting to draw several objects
on the screen avoiding flickering.
|
|
Set the
color used by the OLED drawing commands.
The
color is defined as above:
0
|
Black
|
1
|
White
|
2
|
Reverse
|
|
|
Draw a
pixel at the position x, y on the OLED display
|
|
Draw a line between
the point (x1,y1) and the point (x2,y2) on the OLED
display
|
|
Draw a rectangle at the point (x,y) with the
specified width, height on the OLED.
Specifying 1 for the argument fill, the
rectangle will be filled.
|
|
Draw a circle at the point (x,y) with the
specified radius on the OLED display.
Specifying 1 for the argument fill, the circle
will be filled.
|
|
Set the font used
by the OLED.PRINT command.
The font_num is
defined as above (by default the font 1 is selected)
1
|
Arial MT 10
|
Width : 10px
|
Height:13px
|
2
|
Arial MT 16
|
Width : 16px
|
Height:19px
|
3
|
Arial MT 24
|
Width : 24px
|
Height:28px
|
|
|
Print a
text on the OLED display.
‘x’ and
‘y’ define the position where ‘text$’ will be printed.
An
optional ‘background’ parameter permit to specify the background
color.
|
|
Shows
an image in XBM format from the internal disk on the OLED
display.
‘X’ and
‘y’ define the position where the image will be shown
‘image$’ is the name of the file containing the image
|
|
Shows an image in
BMP format from the internal disk on the OLED display.
‘X’ and ‘y’ define
the position where the image will be shown
‘image$’ is the
name of the file containing the image
|
|
This controls the
action taken if an error occurs while running a program and applies
to all errors including syntax errors.
ONERROR ABORT will
display the error message and abort the program. This is the normal
behaviour and is the default when a program starts running.
ONERROR IGNORE will
cause any error to be ignored.
ONERROR SKIP will
ignore an error in a number of commands (specified by the number
'nn') executed following this command. 'nn' is optional, the
default if not specified is one.
After the number of
commands has completed (with an error or not) the behaviour will
revert to ONERROR ABORT.
If an error occurs
and is ignored/skipped the read only variable BAS.ERRNUM will be
set to non zero and BAS.ERRMSG$ will be set to the error message
that would normally be generated. These are reset to zero and an
empty string by ONERROR CLEAR. They are also cleared when the
program is run and when ONERROR IGNORE and ONERROR SKIP are used.
ONERROR IGNORE can make it very difficult to debug a program so it
is strongly recommended that only ONERROR SKIP be used.
In addition the
command ONERROR GOTO label permits to define a routine that can
manage the error; issuing RETURN inside this routine, will return
to the line following the error.
|
|
Define the label
where the program will jump when an error occurs during the
transmission of an ESP-NOW message.
This happen, in
particular, when the receiver device has not received the
message
|
|
Define the label
where the program will jump when an ESP-NOW message is received
|
|
Define a label
where the program will jump when the APDS9960 sensor detects a
gesture. To disable ONGESTURE OFF
|
|
Define
a label where the program will jump when an html object present in
the output html page changes its value. The code must be terminated
with ‘RETURN’.
To
disable ONHTMLCHANGE OFF
|
|
Define a label
where the program will jump when a reload of the output html page
is requested or a new client connects to this page. The code must
be terminated with ‘RETURN’. To disable ONHTMLRELOAD OFF
|
|
Define a label
where the program will jump when an IR code is received by the
Infrared receiver. The script branch must be terminated with
‘RETURN’.
To disable
ONINFRARED OFF
|
|
Define a label where the program will jump
when an MQTT message is received
The script branch
must be terminated with ‘RETURN’.
To disable ONMQTT
OFF
|
|
Define a label where the program will jump
when an RFID device is detected
The script branch
must be terminated with ‘RETURN’.
To disable ONRFID
OFF
|
|
Define a label
where the program will jump when a message is received on the
serial port (console). The code must be terminated with
‘RETURN’.
To disable ONSERIAL
OFF
|
|
Define a label
where the program will jump when a message is received on the
serial port #2. The code must be terminated with ‘RETURN’
To disable
ONSERIAL2 OFF
|
|
Define a label
where the program will jump when the TFT screen is touched. The
code must be terminated with ‘RETURN’
To disable ONTOUCH
OFF.
Useful in
combination with the functions TOUCH.X and TOUCH.Y
|
|
Define a label
where the program will jump when a UDP message is received. The
code must be terminated with ‘RETURN’.
To disable ONUDP
OFF
|
|
Define a label
where the program will jump when a URL AJAX GET request is
received. This is typically when the url http://local_ip/msg?param=value is
accessed. For more detail refers to the dedicated paragraph..
To disable
ONURLMESSAGE OFF.
Useful in
combination with URLMSGRETURN and URLMSGGET$
More information here
|
|
Define a label
where the program will jump when a WGETASYNC message is received.
The code must be terminated with ‘RETURN’.
To disable
ONWGETASYNC OFF
|
|
Define CPU speed in
Mhz of the module.
The value can be
80, 160 or 240. The default value is 240Mhz.
Setting the speed
at 80Mhz, will divide by 3 the speed of the module but lower the
power requirement of the module by around 5mA
|
|
Define the RAM
available lower limit. If during the execution of the program this
limit is reached, the program automatically stops with an OUT OF
MEMORY error message. By default the value is defined at 10000.
As it introduces a
little overhead, it can be disabled setting this option at 0
(however this is not recommended).
|
|
Pause the module
for ‘delay’ milliseconds.
During the pause,
all the activities are not suspended (it is non-blocking).
This means that all
interrupts will continue to be managed.
|
|
Setup a PWM / SERVO
drive module based on the chip PCA 9685.
This module must be
connected using the bus I2C.
‘Add’ defines the
I2C address of the chip (normally 64)
Example:
PCA9685.SETUP 64 ‘
set the module at the I2C address 64 (40 in hexadecimal)
|
|
Set the PWM
frequency of the PWM / Servo module PCA 9685
‘Freq’ defines the
frequency of the PWM signal
The value can be
from 24 Hz to 1526 Hz.
To drive servos,
the frequency must be 50 Hz
Example:
PCA9685.SETFREQ 50
‘ set the PWM frequency at 50 Hz
|
|
Set the PWM signal
on one of the 16 outputs of the PCA9685 module.
‘Pin’ can be from 0
to 15
‘Value’ can be from
0 to 4095.
Example:
PCA9685.PWM 0, 2048
‘ put the output 0 at 50% duty cycle
|
|
Initialise the PID
controller with the Kp, Ki, and Kd parameters.
As there are 4 PID
controllers, the prefix can be PID1, PID2, PID3 or PID4.
|
|
Set the output
limits of the given PID controller.
If not defined the
limits are defined as 0 to 255.
As there are 4 PID
controllers, the prefix can be PID1, PID2, PID3 or PID4.
|
|
Set the sampling
period for the given PID controller.
If not defined the
default value is 100 msec.
As there are 4 PID
controllers, the prefix can be PID1, PID2, PID3 or PID4.
|
|
Modify the PID
parameters for the given PID controller.
As there are 4 PID
controllers, the prefix can be PID1, PID2, PID3 or PID4.
|
|
Set the working
mode of the given PID controller.
If ‘mode’ is set to
0, the controller will be stopped and the output value will be
frozen.
By default the
‘mode’ is set to 1.
As there are 4 PID
controllers, the prefix can be PID1, PID2, PID3 or PID4.
|
|
Set the value of
any external I/O pin.
The pin_number
refers to GPIO and can be from 0 ... 5 or 12 ...33
The val can be 0 or
1 to set the pin to LOW or HIGH
Before being used,
the pin must be set as OUTPUT with the command PIN.MODE
|
|
The function
PIN.DAC pin,
value can be used to set the output voltage on the pin
25 or 26 (only these pins are available for analog output)
The output voltage is approximately 0V @
value=0 and 3.3V @ value=255
|
|
Set any pin to
digital mode as input or output.
The ‘pin_number’
can be from 0 to 39.
The ‘mode can’ be
INPUT or OUTPUT or SPECIAL
The optional
parameter PULLUP permits to add a weak pullup resistor on the
pin.
The optional
parameter PULLDOWN permits to add a weak pulldown resistor on the
pin.
The mode SPECIAL
can be used to restore the normal functionality to any pin.
For example, if the
pin GPIO1 (normally assigned to the TX functionality) has been
defined as input (with the command PIN.MODE 1, INPUT), its normal
functionality can be restored with the command
PIN.MODE 1,
SPECIAL
|
|
Play
mp3 files stored in the internal disk or from the SD card.
The sound is played in the background, even if
the program is stopped, until the end of the record or executing
the command PLAY.STOP.
Example:
PLAY.MP3 “/mp3/music.mp3”
|
|
Play an
mp3 streaming web radio.
The sound is played in the background, even if
the program is stopped, until the execution of the command
PLAY.STOP.
The optional argument ’buffer’ defines the
size of the memory block allocated as an input buffer. Its value is
20000 by default and can be increased up to the free RAM
available..
Example:
PLAY.STREAM
"http://91.121.159.124:8000/eko-des-garrigues-128k.mp3"
|
|
Set the
destination output for the sound player commands.
If ‘dest’ is 0 is the output will be sent to
the GPIO25 and 26 ( and the internal speaker for the M5stack)
If ‘dest’ is 1 is the output will be sent to
the external DAC
If ‘dest’ is 2 is the output will be sent to
the GPIO25 and 26 ( and the internal speaker for the M5stack) but
using the PDM mode
The optional argument ’buffer’ defines the
size of the memory block allocated as an output buffer.
Its value is 8 by default and can be increased
up to 64.
Increasing the size of the buffer will permit
to reduce some glitches that may occur in case of strong WiFi
activity.
The optional argument ‘mono’, if set to 1, set
the output in mono mode (useful for single channel speaker)
If the command PLAY.SETUP is run without
arguments, the sound is sent by default to the internal
speaker.
Example:
PLAY.SETUP 1 ‘ define the output to the external DAC
|
|
Speaks
a vocal message using the internal SAM speech synthesizer.
The
message must be composed of english words and limited to 255
characters.
It can
optionally talk using phonemes; in this case ‘phonetic’ must be
1.
Example
:
PLAY.SPEAK “The quick brown fox jumps over the
lazy dog”
|
|
Stop
the playing of sound
|
|
Speaks a vocal message using the voice
synthesis available in google translate.
|
|
Defines
the output volume.
It can
be from 0 to 100 but greater than 100 values are accepted if the
sound file was recorded with low volume
Example:
PLAY.VOLUME 50 ‘ set the sound at 50%
|
|
Play wav files
stored in the internal disk or from the SD card.
The sound is played in the background, even if
the program is stopped, until the end of the record or executing
the command PLAY.STOP.
Example:
PLAYWAV “/wav/music.wav”
|
|
Outputs
text to the serial port (console)
Multiple expressions can be used and must be separated by either
a:
-
Comma (,) which will output the tab character
-
Semicolon(;) which will not output anything (it is just used to
separate expressions).
A
semicolon (;) at the end of the expression list will suppress the
automatic output of a carriage return/ newline at the end of a
print statement.
Integers (whole numbers) are printed without a decimal point while
fractions are printed with the decimal point and the significant
decimal digits. Large floating point numbers are printed in
scientific number format.
|
|
Outputs text to the
serial port #2.
Multiple
expressions can be used and must be separated by either a:
-
Comma (,) which will output the tab character
-
Semicolon(;) which will not output anything (it is just used to
separate expressions).
A semicolon (;) at
the end of the expression list will suppress the automatic output
of a carriage return/ newline at the end of a print statement.
Integers (whole
numbers) are printed without a decimal point while fractions are
printed with the decimal point and the significant decimal digits.
Large floating point numbers are printed in scientific number
format.
|
|
Attach a PWM
channel to a given output pin.
‘pin’ can be any
output pin
‘chan’ can be from
0 to 15.
‘default is the
initial pwm value set to the output
‘freq’ is the pwm
frequency; by default is 10KHz
‘resol’ is the
resolution; by default is 8bits
Frequency limits depend on resolution.
For duty resolution of 8 bits, the maximal
frequency is 312.5 kHz.
The available duty levels are (2^bit_num)-1,
where bit_num can be 1-15.
The maximal frequency is 80000000 /
2^bit_num
NOTE for the M5stack:
The channel 0 is dedicated to the internal
speaker (pin 25)
The channel 7 is dedicated to the TFT
backlight (pin 32)
See the PWM chapter for more details
|
|
Detach the pin from
the PWM output.
|
|
Set a given value
to the PWM channel.
The channel is
associated to a given pin with the command PWM.SETUP
‘chan’ can be from
0 to 15
‘value’ can be from
0 to the max defined by the resolution (by default 0 to 255)
|
|
Reads values from
DATA statements and assigns these values to the named variables.
Variable types in a READ statement must match the data types in
DATA statements as they are read.
See also DATA and
RESTORE.
|
|
Reboots the module
(software reset)
|
|
Refresh (sync) the
variables in the basic code with the corresponding variables in the
input html page (one shot)
|
|
Resets the line and
position counters for the READ statement at the beginning or a
specific position defined by ‘label’
|
|
Set the RTC module
(DS1307 or DS3231) with the supplied date / time
‘Year’ can be from
0 (for 2000) to 99 (for 2099)
‘Month’ can be from
1 (january) to 12 (december)
‘Day’ can be from 1
to 31
‘Hours’ can be from
0 to 23
‘Minutes’ can be
from 0 to 59
‘Seconds’ can be
from 0 to 59
See also RTC.DATE$
and RTC.TIME$
|
|
Send one or more
bytes to the serial port (console).
The bytes can be
one or more separated by a comma.
The values can be
any value from 0 to 255.
Example :
SERIAL.BYTE
&h10, &h00, &h12, &h09
|
|
Send one or more
byte to the serial port #2.
The bytes can be
one or more separated by a comma.
The values can be
any value from 0 to 255.
Example :
SERIAL2.BYTE
&h10, &h00, &h12, &h09
|
|
Set the speed for
the Serial Port (console)
The format is fixed
to 8 bits No parity 1 bit stop.
‘baudrate’ defines
the speed (can be any allowed value)
‘bits’ can be from
5 to 8
‘parity’ {0 = none
: 1 = odd, 2 = even)
‘stop’ can be 1 or
2
|
|
Set the speed and
the pins for the serial port #2
It is possible to
specify any pin for the TX and RX signals.
The format is fixed
to 8 bits No parity 1 bit stop.
‘baudrate’ defines
the speed (can be any allowed value)
‘pin_tx’ defines
the pin for the TX signal
‘pin_rx’ defines
the pin for the RX signal.
‘bits’ can be from
5 to 8
‘parity’ {0 = none
: 1 = odd, 2 = even)
‘stop’ can be 1 or
2
‘TXbuffer’ defines
the size of the TX buffer (default is 256)
‘RXbuffer’ defines
the size of the RX buffer (default is 256)
|
|
Set the internal
timekeeper with the supplied date / time
‘Year’ can be from
70 (for 1970) to 38 (for 2038); values >100 are accepted so 2017
can be specified as 17 or 117.
‘Month’ can be from
1 (january) to 12 (december)
‘Day’ can be from 1
to 31
‘Hours’ can be from
0 to 23
‘Minutes’ can be
from 0 to 59
‘Seconds’ can be
from 0 to 59
|
|
Put the ESP in deep
sleep (low energy) for 'value' seconds.
At the end of the
period, the unit will reboot and reload the default basic
program.
Optionally, it is possible to wake up the
module using an external signal sent on an input pin
In this case the pin and the level must be
specified in addition to the time value.
Only RTC IO can be used as a source for
external wake up.
They are pins: 0,2,4,12-15,25-27,32-39.
Level is 1 for wakeup on High and 0 for wakeup
on Low
|
|
Send a WebSocket
message only to a specific client.
This command should
not be used as It will probably be removed in the future
‘client’ is the
number of the client
‘msg$’ is the
message to be sent
|
|
Defines the ‘pin’
used as CS for the SPI functions.
Because the ESP32
uses multitasking, the CS pin is managed directly by Annex
The optional
parameter ‘polarity’ defines if the CS signal must be
active low (0 = default) or active high (1).
This command will set
the pin automatically as output.
|
|
Initialise the SPI
port with the speed (bits/sec)
The speed can be
max 80000000 (80MHz for CPU running at 160MHz)
The optional
parameters are:
data_mode : can be
0 (default) 1, 2 or 3.
bit_order : can be
0 (lsb_first) or 1 (msb_first - default)
|
|
Stops the SPI bus
activity and restore the control on the SPI I/O pins (18 - 19 -
23).
After this command
these pins can be used again as standard GPIO
|
|
Initialize an
ST7920 display connected using SPI to the module.
‘CS_pin’ defines
the pin used for the CS signal
This command
initialise automatically the SPI bus at 1 Mhz (max frequency
allowed by the display)
Example :
ST7920.INIT 15 ‘
init the ST7920 with the CS at pin 16
|
|
Clear the content
of the ST7920 display connected using SPI to the module
|
|
Defines how the
image is sent on the ST7920 after each drawing command.
If ‘fmt’ = 1, the
image is automatically refreshed after each drawing command.
If ‘fmt’ = 0, the
image must be manually refreshed with ST7920.REFRESH 0
This method
provides a double buffer permitting to draw several objects on the
screen avoiding flickering.
|
|
Set the color used
by the ST7920 drawing commands.
The color is
defined as above:
0
|
Black
|
1
|
White
|
2
|
Reverse
|
|
|
Draw a pixel at the
position x, y on the ST7920 display
|
|
Draw a line between
the point (x1,y1) and the point (x2,y2) on the ST7920
display
|
|
Draw a rectangle at the point (x,y) with the
specified width, height on the ST7920.
Specifying 1 for the argument fill, the
rectangle will be filled.
|
|
Draw a circle at the point (x,y) with the
specified radius on the ST7920 display.
Specifying 1 for the argument fill, the circle
will be filled.
|
|
Set the font used
by the ST7920.PRINT command.
The font_num is
defined as above (by default the font 1 is selected)
1
|
Arial MT 10
|
Width : 10px
|
Height:13px
|
2
|
Arial MT 16
|
Width : 16px
|
Height:19px
|
3
|
Arial MT 24
|
Width : 24px
|
Height:28px
|
|
|
Print a text on the
ST7920 display.
‘x’ and ‘y’ define
the position where ‘text$’ will be printed.
An optional
‘background’ parameter permits to specify the background color.
|
|
Shows an image in
XBM format from the internal disk on the ST7920 display.
‘X’ and ‘y’ define
the position where the image will be shown
‘image$’ is the
name of the file containing the image
|
|
Shows an image in
BMP format from the internal disk on the ST7920 display.
‘X’ and ‘y’ define
the position where the image will be shown
‘image$’ is the
name of the file containing the image
|
|
Print a message on
the display TM1637.
All ASCII
characters can be used but will be shown within the limitation of
the 7 segments of the display. The decimal point and the colon (:)
are automatically managed if the display support them.
‘msg$’ defines the
message to be shown
‘brightness”
defines the luminosity of the display from 0 (blank) to 7 (max)
By default the
luminosity is at 7
|
|
Defines the pins to
be used for the display TM1637.
‘data_pin’ defines
the pin allocated for the signal DIO of the display
‘clock_pin” defines
the pin allocated for the signal CLK of the display
‘bit_delay’ permit
to add a delay when the display module is provided with capacitors
on the input pin. Its value is 5 by default and should be defined
at 100 in this case.
‘display_type’ must
be 1 if a “6 digits” display is connected
|
|
Print a message on
the display TM1638. The message can be up to 8 chars.
All ASCII
characters can be used but will be shown within the limitation of
the 7 segments of the display.
‘msg$’ defines the
message to be printed
‘brightness”
defines the luminosity of the display from 0 (blank) to 15
(max)
By default the
luminosity is at 15
|
|
Defines the pins to
be used for the display TM1638.
‘data_pin’ defines
the pin allocated for the signal DIO of the display
‘clock_pin” defines
the pin allocated for the signal CLK of the display
‘strobe_pin”
defines the pin allocated for the signal STB of the display
|
|
Controls the 8 leds
installed on the module TM1638.
‘Val’ is an 8-bits
value where each bit is associated with a led.
Example :
TM1638.LEDS 1 ‘
illuminated the led 1
|
|
Display a bitmap
file on the TFT display.
The file must be
present on the local disk before use.
The file format
must be ".bmp" with 24 or 32 bits.
The image can be of
any size but is limited to 320 x 240 (resolution of the
display).
The position (x, y)
is optional; if specified, the image will be drawn from that
point.
The back color is
useful for 32bit images when a transparent color is defined; in
this case the transparency will be replaced by the
‘back_color’.
Defining a
back_color at -1, the transparency will be maintained, useful to
put icons on the top of an image.
‘filename$’ is the
name of the bmp file
‘x’ is the
horizontal position of the image
‘y’ is the vertical
position of the image
‘back_color’
(optional) is the background color (-1 by default)
Example
TFT.BMP
"/icon1.bmp", 50, 50
|
|
Set the TFT
backlight intensity.
‘val’ can be from 0
(dark) to 255 (max)
Example:
TFT.BRIGHTNESS 128
‘ set the luminosity at 50%
|
|
Trace a circle at
the point (x,y) with the specified radius.
Specifying 1 for
the argument fill, the circle will be filled.
Example
A filled circle at
20,20 radius 18, with a reddish color
TFT.CIRCLE
20,20,18,TFT.RGB(255,10,10),1
|
|
Fill the whole
screen with a given color.
‘color’ is the
color; as it must be a 16 bit color (RGB565), its value can be from
0 to 65535.
The color can be
obtained specifying the R,G,B components with the function
TFT.RGB.
Example:
TFT.FILL 0 ‘
fill the screen with black (equivalent of CLS)
|
|
Display a BMP or
JPG file on the TFT display.
The file must be
present on the local disk before use.
The file format
must be ".bmp" with 24 or 32 bits or “.jpg”
The image can be of
any size but is limited to 320 x 240 (resolution of the
display).
The position (x, y)
is optional; if specified the image will be drawn from that
point.
The back color is
useful for 32bit images when a transparent color is defined; in
this case the transparency will be replaced by the
‘back_color’.
Defining a
back_color at -1, the transparency will be maintained, useful to
put icons on the top of an image.
‘filename$’ is the
name of the image file
‘x’ is the
horizontal position of the image
‘y’ is the vertical
position of the image
‘back_color’
(optional) is the background color (-1 by default)
Example
TFT.IMAGE
"/icon1.bmp", 50, 50
TFT.IMAGE
“/roses.jpg”, 64, 64
|
|
Initialize a TFT
ILI9431 display connected to the module.
‘orientation’ is a
number between 0 and 3 specifying the orientation:
0
|
Portrait
|
1
|
Landscape
|
2
|
Portrait
reversed
|
3
|
Landscape
reversed
|
Example :
TFT.INIT
1 ‘
Landscape
Check the chapter
about the TFT display for more details
|
|
Display a JPG file
on the TFT display.
The file must be
present on the local disk before use.
The file format
must be “.jpg”
The image can be of
any size but is limited to 320 x 240 (resolution of the
display).
The position (x, y)
is optional; if specified the image will be drawn from that
point.
‘filename$’ is the
name of the jpg file
‘x’ is the
horizontal position of the image
‘y’ is the vertical
position of the image
‘scale’(optional)
enable to scale the image (see next table)
scale
|
Scaling
effect
|
0
|
1:1
|
1
|
1:2
|
2
|
1:4
|
3
|
1:8
|
Example
TFT.JPG
“/roses.jpg”, 64, 64
|
|
Trace a line on the
TFT between the point (x1,y1) and the point (x2,y2) with the
color ‘col’
Example:
TFT.LINE 50, 50,
150, 150, TFT.RGB(255, 0, 0)
|
|
Draw a pixel at the
position x, y with the color ‘col’
TFT.PIXEL 50, 50,
red
|
|
Draw a text on the
TFT display.
Multiple
expressions can be used and must be separated by either a:
-
Comma (,) which will output the tab character
-
Semicolon(;) which will not output anything (it is just used to
separate expressions).
A semicolon (;) at
the end of the expression list will suppress the automatic output
of a carriage return/newline at the end of a print statement.
Integers (whole
numbers) are printed without a decimal point while fractions are
printed with the decimal point and the significant decimal digits.
Large floating point numbers are printed in scientific number
format.
|
|
Trace a rectangle
at the point (x,y) with the specified width, height and color.
Specifying 1 for
the argument fill, the rectangle will be filled.
Specifying a value
for ‘round_radius’, the rectangle will be rounded at the corners
with the value specified.
Example:
TFT.RECT 100, 50,
50, 50, TFT.RGB(255, 128, 0)
|
|
Sets the SPI frequency for the TFT. The
default value is typically 40MHz (40,000,000), but it can vary
depending on the specific TFT model being used.
Increasing the speed to 80MHz can enhance
display performance, but this may not be compatible with all TFT
displays. For instance, it may not work with the M5Stack.
|
|
Set the color and
the background of the text that will be printed with the command
TFT.PRINT
‘color’ define the
color of the text
‘backcolor’
(optional) defines the background of the text
If ‘backcolor’ is
not defined, the background will be black
|
|
Position the text
cursor at the point (x, y).
The text will be
printed at that position with the command TFT.PRINT
|
|
Set the size of the
text that will be printed with the command TFT.PRINT
The ‘size’ can be
from 1 to 8.
|
|
Starts a timer
causing the program to periodically jump to the defined label.
The RETURN at the
end of the timer branch causes program control to return to where
it was before being interrupted by TIMER0.
‘Interval’ defines
the periodicity (milliseconds)
‘Label’ defines the
place where the timer will jump regularly.
Setting the
interval to 0 will disable it.
Note: The Timer0
has a higher priority than Timer1.
Example
TIMER0 1000,
cycle -> jumps to ‘cycle’ at each second
|
|
Starts a timer
causing the program to periodically jump to the defined label.
The RETURN at the
end of the timer branch causes program control to return to where
it was before being interrupted by TIMER1.
‘Interval’ defines
the periodicity (milliseconds)
‘Label’ defines the
place where the timer will jump regularly.
Setting the
interval to 0 will disable it.
Example
TIMER1 1000,
cycle -> jumps to ‘cycle’ at each second
|
|
Start the calibration of the touch screen. The
user will be asked to click on 4 crosses.
The calibration values will be stored inside
the module and stay in effect even after restarts.
|
|
Start the UDP
Server.
‘port’ is the udp
port to be open (numerical).
All the messages
received on this port can be read with the function UDP.READ$
|
|
Send an UDP message
back to the original transmitter.
Permits to answer
directly without specifying the IP and port.
It is optionally
possible to specify the remote port with the argument ’port’
|
|
Stop the UDP
server.
|
|
Send a UDP message
to the client defined with the IP address ‘ip’ and the port ‘port".
The message ‘msg$" must be a String.
UDP.Begin must be
used to initialise the UDP port before using UDP.write
|
|
Returns a message
to the client that sent the URL AJAX GET request.
Is an async
request, so it can work in parallel with other tasks.
When the program is
not running, any request will receive the message "STOPPED".
The message can be
optionally composed of an hex string in the format of 2 hex char
per byte (ex: “3a552b23”) associated with a content type string
(ex: "image/gif").
For more detail
refers to the dedicated paragraph..
Useful in
combination with ONURLMESSAGE and URLMSGGET$
More information here
|
|
Stops the execution
of the program while waiting for events.
Useful when using
"event driven" code (timers, interrupts, triggered events, ..)
|
|
Start a GET server
request in async mode
‘server$’ is the
server url request
‘port’ is the port
number; if port=443, the connection will be done using SSL
(secure).
‘header’, if =1,
will include the header in the answer (useful for debug)
The program will
continue and the answer will be received in background.
As soon as the
answer is completed, the program will jump to the label defined
with the command ONWGETASYNC.
To get the result,
use the function WGETRESULT$.
Example :
ONWGETASYNC
answer_done
WGETASYNC("www.fakeresponse.com/api/?sleep=5", 80)
For i = 0 to
10000
‘ a kind of sleep
just to demonstrate that the code continues to run
Print i
Next i
Wait
answer_done:
Print
WGETRESULT$
Return
|
|
Start a GET server
request in async mode
url$’ is the web
server url request
If ‘url$’ starts
with https:// the connection will be done using SSL
(secure).
‘header’, if =1,
will include the header in the answer (useful for debug)
The program will
continue and the answer will be received in background.
As soon as the
answer is completed, the program will jump to the label defined
with the command ONWGETASYNC.
To get the result,
use the function WGETRESULT$.
Example :
ONWGETASYNC
answer_done
WGETASYNC("http://www.fakeresponse.com/api/?sleep=5")
For i = 0 to
10000
‘ a kind of sleep
just to demonstrate that the code continues to run
Print i
Next i
Wait
answer_done:
Print
WGETRESULT$
Return
|
|
Put the module in AP-Mode using
the given SSID and Password.
Optionally it is possible to
define the Radio Channel, the IP and the MASK address
IMPORTANT : the password must be
at least 9 characters
|
|
Wake Up the WiFi
from the sleep mode triggered with the command WIFI.SLEEP
|
|
Connect the module
to a WiFi network using the given SSID and password.
Using the optional parameter
BSSID$ will start the connection to a specific WiFi access
point.
It is possible to
gather the connection status using the function WIFI.STATUS
The IP address
configuration set in the config page will be used for the new
connection; this may cause the module to fall outside the WIFI
network IP range.
This can be avoided
leaving the IP address blank in the config page relying on DHCP to
assign them.
Optionally it is
possible to define the IP, the MASK and the GATEWAY using the
optional string parameters.
|
|
Set the output
power of WiFi
‘pow’ defines the
value in dBm
The range is
between 0 and 20.5
|
|
Starts to scan WiFi
networks available.
Must be used in
association with WIFI.NETWORKS
|
|
Put the WiFi in
sleep mode.
The module will be
placed in “modem-sleep” mode.
This mode turns the
WiFi OFF but the module will continue to work.
In this mode the
power requirement is lowered to around 25mA.
Important: this
will work only if the module is in AP mode with static IP address
or in STA mode
|
|
Send text content
to the debug page.
Check the chapter
about html objects for more details
See also the
commands CLS, HTML, JSCRIPT, JSEXTERNAL, CSS and JSCALL
|
|
Delete a parameter
from a string containing a series of parameters. If the parameter
exists, it will be removed, otherwise the string will not be
modified.
The parameters are
stored as below :
param1=value1
param2=value2
…….
paramx=valuex
‘setting$’ defines
the string containing the set of parameters
‘parameter$’
defines the parameters to be deleted.
‘separator$’ is an
optional parameter specifying a different separator character.
Example, assuming
that a$ is empty :
WORD.SETPARAM a$,
"light", "on"
WORD.SETPARAM a$,
"temp", "10"
WORD.SETPARAM a$,
"pump", "off"
A$ will contain
:
light=on
temp=10
pump=off
Using the following
line:
WORD.DELPARAM a$,
"temp"
A$ will contain
:
light=on
pump=off
By default the
separator is the character ‘=’.
Useful in
combination with WORD.GETPARAM$, WORD.SETPARAM and FILE.SAVE
|
|
Put a parameter
into a string containing a series of parameters. If the same
parameter already exists, its value will be replaced with the new
one.
The parameters are
stored as below :
param1=value1
param2=value2
…….
paramx=valuex
‘setting$’ defines
the string containing the set of parameters
‘parameter$’
defines the parameters to be set.
‘value$’ defines
the value to be set.
‘separator$’ is an
optional parameter specifying a different separator character.
Example, assuming
that a$ is empty :
WORD.SETPARAM a$,
"light", "on"
WORD.SETPARAM a$,
"temp", "10"
WORD.SETPARAM a$,
"pump", "off"
A$ will contain
:
light=on
temp=10
pump=off
Using the following
line:
WORD.SETPARAM a$, "temp",
"20"
A$ will contain
:
light=on
temp=20
pump=off
By default the
separator is the character ‘=’.
Useful in
combination with WORD.GETPARAM$, WORD.DELPARAM and FILE.SAVE
|
|
Keyword :
Used in combination with the SELECT command
|
|
Permits to define
arrays.
The arrays can be
floating point or string.
The number of
dimensions (subscripts) is limited to 5.
Look at the chapter
"Arrays" for more details
|
|
The DO loop
|
|
Keyword : Used in
combination with the IF and SELECT commands
|
|
Keyword : Used in
combination with the IF command
|
|
Used in several
forms:
END alone terminate
the execution of the program
END IF to
terminate the IF
END SELECT : to
terminate a SELECT CASE
END SUB : to
terminate a SUB
|
|
Used in combination
with the IF command; can be also written as END IF
|
|
Permit to exit from
a DO LOOP (EXIT DO), a FOR LOOP (EXIT FOR) or a SUB (EXIT SUB)
|
|
FOR command;
Used in combination with the NEXT command
|
|
Jumps to a named
label; the flow control will come back as soon as the command
RETURN is reached.
The label must
begin with a letter, not a number.
The contents of a
string variable can be used instead of a static label name,
allowing choice of destinations for creating dynamic function
calls
|
|
Jumps to a named
label; the label must begin with a letter, not a number.
The contents of a
string variable can be used instead of a static label name,
allowing choice of destinations for creating dynamic jumps
|
|
IF command; used in
combination with THEN, ELSE, ELSEIF, ENDIF and END IF
|
|
Optional for
variable assignment
|
|
Keyword : Used in
combination with the DO command
|
|
Keyword : Used in
combination with the FOR command
|
|
Keyword : used in
combination with the INTERRUPT command
|
|
Keyword : Used in
combination with the PIN.MODE command
|
|
Keyword : Used in
combination with the PIN.MODE command
|
|
Keyword : Used in
combination with the PIN.MODE command
|
|
Define a
comment(remark); the symbol ‘ can be used instead
|
|
Returns to the
caller after a Gosub or an Event happened
|
|
The SELECT CASE
|
|
Keyword : Used in
combination with the PIN.MODE command
|
|
Keyword : Used in
combination with the FOR command
|
|
Defines "user
named" subroutines.
Refer to the
paragraph "SUB" and "Scope of the variables" for more details.
|
|
Keyword : Used in
combination with the IF command; this keyword is optional in the IF
command
|
|
Keyword : Used in
combination with the FOR command
|
|
Keyword :
Used in combination with the DO command
|
|
Keyword : Used in
combination with the WHILE command
|
|
The WHILE LOOP;
also used as condition for the DO LOOP
|