ANNEX WI-FI RDS
© ciccioCB 2022
COPYRIGHT
The Annex firmware including the AnnexToolKit and this manual are Copyright 2017-2020 by Francesco Ceccarella (ciccioCB).
The compiled object code (the .bin file) for the Annex firmware is free software: you can use or redistribute it as you please except for commercial purposes. It is not allowed to distribute or embed it into products that are sold or for any other activity making or intended to make a profit.
The compiled object code (the .exe file) for the AnnexToolKit utility is free software: you can use or redistribute it as you please except for commercial purposes. It is not allowed to distribute or embed it into products that are sold or for any other activity making or intended to make a profit.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
This manual is distributed under a Creative Commons Attribution-NonCommercial-ShareAlike 3.0 France license (CC BY-NC-SA 3.0)
The above copyright notice and this permission notice shall be included in all copies or redistributions of the Software in any form.
License and credits
Adafruit BNO055 Orientation Sensor library is written by KTOWN is Copyright (c) Adafruit Industries. It is released under MIT license.
TFT_eSPI display Library is Copyright © 2017 Bodmer. It is released under FreeBSD license.
Adafruit NeoPixel library is Copyright (c) Adafruit. It is released under MIT license.
Makuna/NeoPixelBus library is Copyright © by Michael C. Miller. It is released under LGPL license.
Adafruit PWM Servo Driver Library is Copyright (c) Adafruit. It is released under MIT license.
Arduino Library for Dallas Temperature ICs is Copyright (c) Miles Burton <miles@mnetcs.com>. It is released under LGPL license.
OneWire Library is Copyright 1999-2006 Dallas Semiconductor Corporation and Copyright (c) 2007, Jim Studt.
Adafruit DHT Humidity & Temperature Sensor Library is Copyright (c) Adafruit. It is released under MIT license.
ESP8266 and ESP32 Oled Driver library is Copyright (c) 2016 by Daniel Eichhorn and Copyright (c) 2016 by Fabrice Weinberg. It is released under MIT license.
ESP8266Ping is Copyright (c) Daniele Colanardi. It is released under LGPL license.
ESP AsyncTCP library is Copyright (c) 2016 Hristo Gochkov. It is released under LGPL license.
ESP AsyncWebServer library is Copyright (c) 2016 Hristo Gochkov. It is released under LGPL license.
IRremoteESP8266 library is Copyright (c) Sebastien Warin, Mark Szabo, Ken Shirriff, David Conran. It is released under LGPL license.
uRTCLib is Copyright (c) 2015 Naguissa (naguissa.com@gmail.com). It is released under LGPL license.
BME280 library is written by Limor Fried/Ladyada for Adafruit Industries. It is released under BSD license,
APDS9960 library is written by Shawn Hymel for Sparkfun Electronics. It is released under Beerware license.
PID Library is written by Brett Beauregard (br3ttb@gmail.com). It is released under MIT license.
MQTT library pubsubclient is Copyright (c) 2008-2015 Nicholas O'Leary. It is released under MIT license
MFRC522 library is written by Miguel Balboa.
The Javascript Editor EditArea is Copyright © 2008 Christophe Dolivet. It is released under LGPL license.
The base of the interpreter comes from the original project "MiniBasic" by Malcom Mclean.
The MFRD522 library is written by Miguel Balboa and is released as free and unencumbered software released into the public domain.
Contributions
A very big thank you to Robin Baker (Electroguard) for his great involvement in the project by supporting all the tests on the real hardware (bought with his money), and all the advices that allowed me to add a lot of functionality, not to mention the Huge work he did while documenting the project on the website.
Content :
Interpreter: 17
Variables: 17
Arrays: 19
IF command : 22
FOR loop 23
DO LOOP loop 24
SELECT CASE 25
GOTO 25
GOSUB 26
DATA 26
END 27
EXIT 27
SUB 27
Logical / boolean Operations 29
BAS.ERRLINE 31
BAS.ERRNUM 31
BAS.ERRMSG$ 31
HOW the interpreter works with the HTML code and Objects : 31
HTML Objects 35
TIMERS 40
EVENTS 40
Button Event 40
OnUDP Event 42
OnMQTT Event 47
Ret = FILE.COPY(filename$, newfile$) 53
Ret = FILE.DELETE(filename$) 53
Ret = FILE.EXISTS(filename$) 53
Ret = FILE.RENAME(oldname$, newname$) 53
Ret$ = FILE.READ$(filename$, [line_num] | [start, length]) 53
FILE.APPEND filename$, content$ 53
FILE.SAVE filename$, content$ 53
I/O BUFFERS 54
Buffer copy 58
DIGITAL I/O 60
Analog input 62
PWM 63
SERVO 63
COUNTERS 64
I2C BUS 67
SPI BUS 73
OLED DISPLAY 81
RTC module 85
PCA9685 (PWM / Servo) Module 86
MAX7219 8-Digits 7-segment display 91
NeoPixel WS2812B led strips 95
NeoPixel based WS2812b Dot Matrix DIsplay 96
TouchScreen 104
ULTRASONIC DISTANCE SENSOR HC-SR04 112
DHT xx Temperature / Humidity Sensors 113
DS18B20 Temperature Sensors 115
BNO055 Absolute Orientation Sensor 116
BME280 Combined humidity and pressure sensor 118
APDS9960 Digital Proximity, Ambient Light, RGB and Gesture Sensor 120
RFID MFRC522 RFID cards reader 122
Writing NUID for UID changeable card (4 byte UID version) 126
AC LIGHT DIMMER 126
DIMMER.SETUP pin_in, pin_out, [,invert [,swap]] 127
DIMMER.STOP 127
SONOFF B1 LAMP 128
SONOFFB1.INIT 128
TUYA RGBCW LAMP 129
TUYALAMP.INIT [max_current_RGB, max_current_WHITE] 129
FTP 131
BAS.FTP$ 131
Server data requests (GET and POST) 132
WGET$(server$, port, [,header]) 133
WPOST$(server$, body$, port [,header]) 133
WPOST$(url$, body$ [,header]) 133
WGETASYNC[(] server$, port, [,header [,ping]] [)] 133
WGETASYNC[(] url$, [,header [,ping]] [)] 133
MQTT 134
Ret = MQTT.Fingerprint(fingerprint$) 136
Ret = MQTT.Connect(login$, pass$ [id$]) 136
Ret = MQTT.Connect("", "", [id$]) 136
Ret = MQTT.Publish(topic$, message$) 136
Ret = MQTT.Subscribe(topic$ [,Qos]) 136
Ret = MQTT.UnSubscribe(topic$) 136
ESP-NOW 138
TELEGRAM (messenger) support 148
CONVERT.FROM_IEEE754(iee754_bin) 150
CONVERT.MAP(number, fromLow, fromHigh, toLow, toHigh) 150
BAS CONSTANTS 150
BAS.VER 152
BAS.VER$ 152
BAS.ERRLINE 152
BAS.ERRNUM 152
BAS.ERRMSG$ 152
BAS.FILENAME$ 152
BAS.RTCMEM$ 152
BAS.SSID$ 152
BAS.PASSWORD$ 152
BAS.LOAD 152
BAS.RESETREASON 152
OPTION COMMANDS 153
OPTION.MAC mac$ 153
OPTION.NTPSYNC 153
OPTION.WDTRESET 153
FUNCTIONS: 154
ABS(number) 168
ACOS(number) 168
ADC 168
APDS9960.AMBIENT 168
APDS9960.RED 168
APDS9960.GREEN 168
APDS9960.BLUE 168
APDS9960.GESTUREGAIN (gain) 168
APDS9960.GESTURELED (intensity) 168
ASC(string$) 168
ASIN(number) 168
ATAN(number) 168
ATAN2(x, y) 168
BAS.VER 168
BAS.ERRLINE 157
BAS.ERRNUM 157
BME280.ALT(qnh) 168
BME280.HUM 168
BME280.QFE 168
BME280.TEMP 168
BNO055.HEADING 168
BNO055.PITCH 168
BNO055.ROLL 168
BNO055.VECTOR ( param, axis) 168
CINT(number) 168
CONVERT.FROM_IEEE754(ieee754_bin) 168
CONVERT.MAP(number, fromLow, fromHigh, toLow, toHigh) 160
COS(number) 160
DATEUNIX(date$) 168
DHT.TEMP 168
DHT.HUM 168
DHT.HEATINDEX 168
DISTANCE(pin_trig, pin_echo) 168
EMAIL from$, to$, subject$, message$ 168
ESPNOW.BEGIN 168
ESPNOW.STOP 168
ESPNOW.WRITE( msg$,MAC_add$) 168
EXP(number) 168
FIX(number) 168
FILE.COPY(filename$, newfile$) 168
FILE.RENAME(oldname$, newname$) 168
FLASHFREE 168
INSTR([start], string$, pattern$) 168
I2C.LEN 168
I2C.READ 168
I2C.READREGBYTE (i2c_address, register) 168
I2C.END 168
INT(number) 168
LEN(string$) 168
LOG(number) 168
MILLIS 168
MQTT.Fingerprint(fingerprint$) 165
MQTT.Connect(login$, pass$, [id$]) 165
MQTT.Connect("", "", [id$]) 168
MQTT.Publish(topic$, message$) 168
MQTT.Subscribe(topic$ [,Qos]) 168
MQTT.Status[()] 168
NEO.RGB(R, G, B) 168
PI 168
PID1.COMPUTE( current_value, target_value) 168
PIN(pin_number) 168
PING(host$) 168
POW(x, y) 168
RAMFREE 168
RND(number) 168
SERIAL.LEN 168
SERIAL2.LEN 168
SGN(number) 168
SIN(number) 168
SPI.BYTE(byte) 168
SQR(number) 168
TAN(number) 168
TFT.RGB(r,g,b) 168
TIMEUNIX(time$) 168
TM1638.BUTTONS 168
TOUCH.X 168
TOUCH.Y 168
VAL(string$) 168
WIFI.CHANNEL 168
WIFI.MODE 168
WIFI.NETWORKS ( network$ ) 168
WIFI.RSSI 169
WIFI.STATUS 169
WORD.COUNT( string$ [,delimiter$]) 169
WORD.FIND( string$, find$ [,delimiter$]) 169
STRING FUNCTIONS 170
BAS.ERRMSG$ 181
BAS.FILENAME$ 181
BAS.FTP$( host$, login$, password$, file$, folder$) 181
BAS.PASSWORD$ 181
BAS.RTCMEM$ 181
BAS.SSID$ 181
BAS.VER$ 181
BIN$(number) 181
BUTTON$(name$, label [, id] ) 181
CHECKBOX$( variable [,id]) 181
CHR$(number) 181
CSSID$(object_id, object_style) 181
DATE$[(format)] 181
ESPNOW.ERROR$ 181
ESPNOW.READ$ 181
ESPNOW.REMOTE$ 181
FILE.READ$(filename$,[line_num] | [start, length]) 181
HEX$(number) 181
HtmlEventButton$ 181
HtmlEventVar$ 181
IMAGEBUTTON$(path, label [,id]) 181
IP$ 181
LCASE$(string$) 181
LISTBOX$(variable$, "option1, option2, option3, ..." [, height] [,id]) 181
METER$(variable, min, max [,id]) 181
MID$(string$, start [,num]) 181
MAC$[ (id) ] 181
MQTT.Message$ 181
MQTT.Topic$ 181
OCT$(number) 181
PASSWORD$(variable [, id] ) 181
REPLACE$(expression$, find$, replacewith$) 181
RTC.TIME$ 181
SERIAL.CHR$ 181
SERIAL.INPUT$ 181
SERIAL2.CHR$ 181
SERIAL2.INPUT$ 181
SLIDER$(variable, min, max [,step] [,id]) 181
SPACE$(number) 181
STR$ (number [,format$ [,toint]]) 181
TEXTAREA$(variable [, id] ) 181
TEXTBOX$(variable [, id] ) 181
TRIM$(string$) 181
TIME$ 181
UCASE$(string$) 181
UDP.READ$ 181
UDP.REMOTE$ 181
UNIXDATE$(value [,format]) 181
UNIXTIME$(value) 181
WGET$( http_server$, port [,header] ) 181
WGETRESULT$ 180
WPOST$(server$, body$, port [,header]) 181
WPOST$(url$, body$, [,header]) 180
WORD$(string$, position [,delimiter$]) 181
WORD.DELETE$(string$, position [delimiter$]) 181
WORD.EXTRACT$(string$, lead$, trail$) 181
WORD.GETPARAM$( setting$, parameter$ [,separator$]) 181
COMMANDS: 181
CLS 212
CSS style_code$ 212
COMMAND cmd$ 212
COUNTER.SETUP cnt, pin [,mode] 212
EMAIL.SETUP server$, port, user_name$, password$ [, debug] 212
EMAILASYNC from$, to$, subject$, message$ 212
FILE.APPEND filename$, content$ 212
FILE.SAVE filename$, content$ 212
FUSION.INIT 212
FUSION.MADGWICK ax, ay, az, gx, gy, gz 212
FUSION.MADGWICK ax, ay, az, gx, gy, gz, mx, my, mz 212
FUSION.MAHONY ax, ay, az, gx, gy, gz, mx, my, mz 212
FUSION.BETA = 212
FUSION.ZETA = 212
FUSION.KI = 212
FUSION.KP = 212
HTML code$ 212
I2C.SETUP sda_pin, scl_pin [,freq [,stretch]] 212
I2C.END 212
I2C.REQFROM address, length 212
I2C.READREGARRAY i2c_address, register, nb_of_bytes, Array() 212
I2C.WRITE value 212
I2C.WRITEREGBYTE i2c_address,register, value 212
I2C.WRITEREGARRAY i2c_address, register, nb_of_bytes, Array() 212
INPUT["prompt$";] variable 212
INTERRUPT pin_no, {OFF | label} 212
IR.INIT pin_rx | OFF [, pin_tx] 212
JSCALL javaCode$ 212
JSCRIPT script$ 212
JSEXTERNAL file$ 212
LCD.INIT address, cols, rows 212
LCD.CLS 212
LCD.WRITE char 212
MAXDISPLAY.PRINT msg$ [,‘brightness] 212
MAXSCROLL.SETUP nb_devices, CS_pin [,reverse] 212
MAXSCROLL.SHOW pos [, brightness] 212
MAXSCROLL.SCROLL [brightness] 212
MAXSCROLL.OSCILLATE [brightness] 212
NEO.PIXEL led_pos, R, G, B [, disable] 212
NEO.PIXEL led_pos, COLOR [, disable] 212
NEO.STRIP led_start_pos, led_end_pos, R, G, B [, disable] 212
NEO.STRIP led_start_pos, led_end_pos, COLOR [, disable] 212
NEOSCROLL.SETUP nb_devices, pin [,serpentine] 212
NEOSCROLL. NEXTCOLORS col$ 212
NEOSCROLL.SHOW pos [, brightness] 212
NEOSCROLL.SCROLL [‘brightness] 212
NEOSCROLL.OSCILLATE [‘brightness] 212
OLED.CLS 212
OLED.INIT orientation [,model] 212
OLED.REFRESH fmt 212
OLED.COLOR color 212
OLED.PIXEL x, y 212
OLED.RECT x,y, width, height [,fill] 212
OLED.CIRCLE x, y, radius [, fill] 212
OLED.PRINT x, y, text$ [background] 212
ONERROR ABORT or ONERROR IGNORE or ONERROR SKIP [nn] or ONERROR CLEAR or ONERROR GOTO label 212
ONESPNOWERROR [label | OFF] 212
ONHTMLCHANGE [label | OFF] 212
ONHTMLRELOAD [label | OFF] 212
ONINFRARED label 212
OnMQTT label 212
ONURLMESSAGE [label | OFF] 212
OPTION.MAC mac$ 212
OPTION.NTPSYNC 212
OPTION.WDTRESET 212
PAUSE delay 212
PCA9685.SETUP addr [,freq] 212
PID1.PERIOD msec 212
PIN.MODE pin_number, mode [,PULLUP] 212
PIN.TONE pin, freq [,duration] 212
PRINT expression[[,; ]expression] ... 212
PRINT2 expression [[,; ]expression] ... 212
REBOOT 212
REFRESH 212
RESTORE 212
RTC.SETTIME Year, Month, Day, Hours, Minutes, Seconds 212
SERIAL.BYTE ch1 [,ch2] . . . 212
SERIAL2.BYTE ch1 [,ch2] . . . 212
SERIAL.MODE baudrate [, bits, parity, stop] 212
SERIAL2.MODE baudrate, pin_tx, pin rx [, bits, parity, stop] 212
SERVO id, value 212
SERVO.SETUP id, pin_number | OFF 212
SETTIME Year, Month, Day, Hours, Minutes, Seconds 212
SLEEP value 212
SPI.SETUP speed [,data_mode [, bit_order]] 212
ST7920.CLS 212
ST7920.LINE x1, y1, x2, y2 212
ST7920.RECT x,y, width, height [,fill] 212
ST7920.CIRCLE x, y, radius [, fill] 212
ST7920.PRINT x, y, text$ [background] 212
TM1637.PRINT msg$ [, brightness] 212
TM1637.SETUP data_pin, clock_pin [, bit_delay] [, display_type]] 212
TM1638.PRINT msg$ [, brightness ] 212
TM1638.SETUP data_pin, clock_pin, strobe_pin 212
TM1638.LEDS val 212
TFT.BMP filename$, [x, y [, back_color] ] 212
TFT.CIRCLE x, y, radius [, fill] 212
TFT.FILL color 212
TFT.INIT CS_pin, DC_pin, orientation [Display_width, Display_height, Variant] 212
TFT.LINE x1, y1, x2, y2, col 212
TFT.PRINT expression [[,; ]expression] ... 212
TFT.RECT x, y, width, height, color [ [,fill] ,[round_radius] ] 212
TFT.TEXT.COL color [,backcolor] 212
TRACE message 212
UDP.BEGIN(port) 212
UDP.REPLY msg$ 212
UDP.STOP 212
URLMSGRETURN msg$ [,content_type$] 212
WAIT 212
WGETASYNC [(] server$, port, [,header [,ping]] [)] 212
WGETASYNC [(] url$, [,header [,ping]] [)] 211
WIFI.APMODE SSID$, password$ [, channel] [, IP$ , MASK$] 211
WIFI.AWAKE 211
WIFI.CONNECT SSID$, password$ [, BSSID$] [, IP$ , MASK$ [, GATEWAY$]] 211
WIFI.POWER pow 212
WIFI.SCAN 212
WIFI.SLEEP 212
WLOG expression[[,; ]expression] ... 212
WORD.DELPARAM setting$, parameter$, [,separator$] 212
WORD.SETPARAM setting$, parameter$, value$ [,separator$] 212
BASIC KEYWORDS 213
CASE 215
DIM array(size) [, …] [= init1, init2, …] 215
DO 215
ELSE 215
ENDIF 215
FOR 215
IF 215
LOOP 215
NEXT 215
OFF 215
OUTPUT 215
PULLUP 215
REM 215
RETURN 215
SELECT 215
SPECIAL 215
STEP 215
SUB 215
THEN 215
TO 215
UNTIL 215
WEND 215
WHILE 215
Annex WI-Fi RDS (Rapid Development Suite) is a version of the "basic" language developed to run on low cost ESP8266 WIFI devices.
It takes from the original concept of ESPbasic - which I cooperated on and contributed to in the past - but is a completely re-designed breakaway project designed to offer improved functionality and reliability.
The intention was to create a Basic language for the ESP which complies as much as possible with the original GWbasic / Visual Basic - from which it shares many concepts / ideas / syntax - and also from the excellent project "Micromite" of Geoff Graham.
The base of the interpreter comes from the original project "MiniBasic" by Malcom Mclean.
The text editor comes from the original project "EditArea" by Christophe Dolivet.
Functionalities:
- Includes an internal IDE so can be programmed directly using your web browser without any additional utility (even with your phone/tablet).
- Syntax highlighting with context sensitive Help
- A programmable web server including 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, multidimensional 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
- Support for ESP-NOW communications
- Support for MQTT communications
- Support for FTP communications
- 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)
- 4 Channels PID controller
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 based on Chipset ILI9341 with 320x240 pixels and 16 bits colors
- TM1637 4 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
- BME280 Combined humidity and pressure sensor
- APDS9960 Digital Proximity, Ambient Light, RGB and Gesture Sensor
- RFID MFRC522 cards reader
The basic interpreter works by reading a script file saved to the esp local disk filing system (SPIFFS).
In order to use less RAM, the user script is copied from the disk into a dedicated area in the flash memory where it is executed, so only the list of the program lines, the branch labels and the list of the user defined subroutines get loaded into memory.
This is slower compared to other approaches, but permits maximum memory to be available for user variables and program use.
Another performance consideration is that the ESP8266 must be capable of executing several activities in the background (web server, file server, ..) so needs sufficient free memory for running such tasks, and those parallel tasks must 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. I tried to run some "1980s BASIC benchmark" taken from "the back shed" forum and I can say that the performance is around 2 to 4 times slower than a micromite @48 Mhz; but (IMHO) that’s not bad considering all the additional connectivity and web functionalities provided by the esp module.
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.
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 point; 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 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 always starts from 0.
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)
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, ….
The same can be done with string arrays.
Example :
DIM A$(5) = "zero", "one", "two", "three", "four", "five"
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 tells 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 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
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) |
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"
New feature : 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 [,exp2], ... [: Statements]
Statements
CASE exp3 [,exp4], ... [: Statements]
CASEfrom TO to [: 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 5, 6 : PRINT "case 5 or 6"
CASE 7 TO 10 : PRINT "case 7 to 10"
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
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 number, 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 permit 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 happened during the execution of the code.
This is managed with the command ONERROR.
This command defines the action done 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:
When an error occurs, the following constants are available :
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" permit 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 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 insures a synchronized content between all the clients.
As said previously, in order to simplify the creation of HTML pages, there are several functions permitting to generate the html code automatically.
Let’s start with the button.
A button is an object that is used to generate 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.
The refresh
interval should not be less than 300 milliseconds (otherwise the
module will be too busy).
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.
This command does not have the same timing limitation of REFRESH so the timing can be faster.
The example :
CLS led = 0 a$ = BUTTON$("Button1", jump1, "but1") ' "but1" is the ID a$ = a$ + LED$(led) HTML a$ AutoRefresh 100 'sync each 100 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 will 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 and control is passed to the "timer interrupt routine" until the execution of the return command.
Then the program continues from the point where it has been 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, the pin change interrupts is an asynchronous event as it 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 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 execution 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 |
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 |
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 |
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
print
v$ |
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.
As the answer is async, this command will define the place where the program execution will continue when the message will be 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 permit 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 want sent 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 get 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 receive 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 pwm(12) = R pwm(15) = G pwm(13) = 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(12) = val(UrlMsgGet$("r")) pwm(15) = val(UrlMsgGet$("g")) pwm(13) = val(UrlMsgGet$("b")) UrlMsgReturn UrlMsgGet$() return |
Open the input page into another window and run the program
If you have a ESP-202, you’ll be able to control the color of the RGB led present on the card.
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 a 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
Example:
.... onmqtt mqtt_msg
wait ' receive messages from the server mqtt_msg: print "TOPIC : "; mqtt.topic$ print "MESSAGE: "; mqtt.message$ return |
At startup, the module tries to connect to the router with the parameters provided in the page “Config”.
If the connection is unsuccessful, it will default to AP (Access Point) mode .
By default, if no parameters are specified into the “Config” page, the module will default to the IP address 192.168.4.1 in AP mode 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 not specified, the IP will be given automatically by the Router DHCP server.
As soon as the module is connected to the router, it will reconnect automatically if the connection is lost.
There are several commands / functions available to manage the WIFI.
The first function is WIFI.STATUS that 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.
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$)
=
-1
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 commands WIFI.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 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 config.ini.
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 next restart.
A watchdog timer (or simply a WDT) is an electronic timer that is used to detect and recover from computer malfunctions. During normal operation, the computer regularly resets the watchdog timer to prevent it from elapsing, or "timing out".
If, due to a hardware fault or program error, the computer fails to reset the watchdog, the timer will elapse and generate a timeout signal. The timeout signal is used to initiate corrective action or actions. The corrective actions typically include placing the computer system in a safe state and restoring normal system operation.
Annex implements a watchdog timer with the command OPTION.WDT timeout_msec.
As soon as the watchdog has been defined, the command OPTION.WDTRESET must be executed regularly within the defined timeout otherwise the module will reset automatically.
At the beginning of the program, It is possible to know if the module has been reset by the WDT using the functionBAS.RESETREASON.
Example:
' WDT example select case bas.ResetReason case 0: print "normal startup" case 1: print "hardware WDT" case 2: print "exception reset" case 3: print "software WDT" case 4: print "software restart" case 5: print "wake up from deep sleep" case 6: print "external reset" end select
option.WDT 1000 ' set the WDT at 1 second
print "WDT reset regularly" for z = 1 to 50 print z, pause 100 option.WDTreset next z
print "WDT not reset regularly, so should crash after 1 sec" for z = 1 to 50 print z, pause 100 next z |
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 as soon as the timezone is correctly defined into the [CONFIG] page.
The timezone is defined as a string likeCET-1CEST,M3.5.0,M10.5.0/3 that describe 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, eg 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 be reset back to 1970 default at next restart of the module, so will require setting again.
For more information about the Time Zones and DST, please consult the following page :
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 utilises the time following 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 synthesys :
- DATEUNIX("01/01/18") returns the number of seconds between the 01/01/1970 and the 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
Annex includes a SPIFFS file system hosted on the flash memory chip.
It “emulates” a disk file system enabling 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 |
1M |
256 Kb |
2M |
1MB |
4M |
3MB |
8M |
7MB |
16M |
15MB |
As the SPIFFS has been designed to be very light in terms of resources, it comes with some limitations :
- First the SPIFFS does not support directories, it just stores a “flat” list of files. But contrary to traditional filesystems, the slash character '/' is allowed in filenames, so the functions that deal with directory listing (e.g. FILE.DIR$("/website")) basically just filter the filenames and keep the ones that start with the requested prefix (/website/). Practically speaking, that makes little difference though.
- Second, there is a limit of 31 chars in total for filenames.
- Combined, that means it is advised to keep file names short and not use deeply nested directories, as the full path of each file (including directories, '/' characters, base name, dot and extension) has to be 31 chars at a maximum. For example, the filename /website/images/bird_thumbnail.jpg is 34 chars and will cause some problems if used, for example in FILE.EXISTS() or in case another file starts with the same first 31 characters.
Warning: That limit is easily reached and if ignored, problems might go unnoticed because no error message will appear at runtime.
All the file related functions share the same prefix FILE. followed by the specific function.
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 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 surpasses the limit of the Strings that cannot hold 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
As it is essentially a block of memory, the first command is IOBUFF.DIM(buff_num, size) that defines its size.
buff_num can span from 0 (first buffer) to 4 (last buffer)
size can span from 0 to the maximum RAM memory available
Example:
IOBUFF.DIM(0, 1000) 'dimension the I/O buffer 0 with 1000 bytes
The I/O buffer can be filled with a given set of data directly using the function IOBUFF.DIM
Example:
IOBUFF.DIM(0, 10) = 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
IOBUFF.DIM(1, 5) = &h12, &hAA, &h50, &O377, &B10101010
As soon as the buffer is dimensioned, the given amount of RAM is reserved for the buffer.
When not required anymore, it can be removed with the command IOBUFF.DESTROY(buff_num)
Example:
IOBUFF.DESTROY(0) 'remove the buffer releasing the memory reserved
Note : The I/O buffers are automatically destroyed each time the program is run.
It is possible to know the size of the buffer using the function IOBUFF.LEN(buff_num)
Example
Print IOBUFF.LEN(buff_num) 'print the length of the buffer
The I/O buffer can be read byte per byte using the function IOBUFF.READ(buff_num, position)
position can span from 0 (first byte) and the buffer length - 1 (last byte)
Example:
Print IOBUFF.READ(0, 4) 'print the byte 4 from the I/O buffer 0
A = IOBUFF.READ(0, 7) ' read in the variable A the byte 7 from the I/O buffer 0
The I/O buffer can be written byte per byte using the command IOBUFF.WRITE(buff_num, position, value)
position can span from 0 (first byte) and the length - 1 (last byte)
value can span from 0 to 255 (byte)
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 receive all the data available from the serial port 2 in the buffer 3 :
SERIAL2.READ_IOBUFF(3)
This command receive the data coming from an UDP connection in the buffer 1:
UDP.READ_IOBUFF(1)
Additionally some other arguments may be required.
This command read 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 read 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 read 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 send 10 bytes from the buffer 1 starting from the position 45 to the serial port :
SERIAL.WRITE_IOBUFF(1, 45, 10)
This command send the complete buffer 1 to the serial port 2
SERIAL2.WRITE_IOBUFF(1)
This command send 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 send 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(1, 64, 12), “192.168.1.89”, 8080
This command send the entire buffer 2 on the same UDP device :
UDP.WRITE_IOBUFF(2), “192.168.1.89”, 8080
This command write 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 send 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 send the buffer 0 back to the UDP message original transmitter :
UDP.REPLY_IOBUFF(0)
This is the equivalent of UDP.REPLY message$
Optionally it is also possible specify part of the buffer and the destination port 5001 as below:
UDP.REPLY_IOBUFF(0, 2, 6), 5001
When used with the SPI bus, it enables it to transmit and receive at the same time.
As this operation requires 2 buffers, both must be specified.
For example, this command send the buffer 0 and receive into the buffer 2:
SPI.REPLY_IOBUFF(0), (2)
This command send 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
conversion from hex string :
IObuff.FromHex(buff_num, var$ [, pos])
var$ must contain a hex string in the form of "aabbcc1235"
pos is the position where the HEX must be included in the buffer (0 by default)
A part of the string can be converted in combination with mid$
conversion from string:
IObuff.FromString(buff_num, var$ [, pos])
var$ must contain a text string in the form of "This is a text string"
pos is the position where the HEX must be included in the buffer (0 by default)
A part of the string can be converted in combination with mid$
conversion to hex string:
A$ = IObuff.ToHex$(buff_num, [, start [, size]])
returns an hex string in the form of "aabbcc1235"
start and size are optional and define the start and length (like MID$ but the 1st byte is 0)
conversion to string:
A$ = IObuff.ToString$(buff_num, [, start [, size]])
returns an hex string in the form of "This is a string"
start and size are optional and define the start and length (like MID$ but the 1st byte is 0)
a = IObuff.bit(buff_num, position, bit)
returns the value of the bit of the byte at the position of the buff_num
returns 0 or 1
IObuff.setbit(buff_num, position, bit)
set the bit of the byte at the position of the buff_num
IObuff.clearbit(buff_num, position, bit)
clear the bit of the byte at the position of the buff_num
IObuff.togglebit(buff_num, position, bit)
toggle the bit of the byte at the position of the buff_num
IObuff.copy(dest_buff_num [,pos]) , (source_buff_num, [, start [, size]])
Copy the from source_buff to dest_buff
pos is the position where the source must be copied in the source (0 by default)
start and size define what must be copied (have the same meaning as in .WRITE_IOBUFF)
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 |
Pin numbers correspond directly to the ESP8266 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 5, INPUT
To define the pin 4 as input with a pullup:
PIN.MODE 4, INPUT, PULLUP
To define the pin 2 as output
PIN.MODE 2, OUTPUT
Although pin numbers can be from 0 to 16, 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.
Digital pins 0 to 5 and 12 to 15 can be INPUT, OUTPUT, or INPUT, PULLUP .
Pin 16 can be INPUT, OUTPUT. At startup, all available pins are configured as INPUT.
Pins may also serve other functions, like Serial, I2C, SPI.
These functions are normally activated by the corresponding library.
This diagram shows pin mapping for the popular ESP-12F module.
(*) pins not available.
The value from a pîn can read as below :
A = PIN(5)‘ read from pin GPIO5
The pin value can be set as below
PIN(2)= 0 ‘ set 0 on the pin GPIO2
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
As many modules use the NodeMCU pin numbering, please use the table below to find the corresponding reference:
NodeMCU and Wemos Pin Reference |
Standard GPIO Reference |
D0 |
16 |
D1 |
5 |
D2 |
4 |
D3 |
0 |
D4 |
2 |
D5 |
14 |
D6 |
12 |
D7 |
13 |
D8 |
15 |
D9 |
3 |
D10 |
1 |
In order to use the Wemos / NodeMcu references, it could be useful to add this code to create the pin constants at the beginning of the program :
D0=16:D1=5:D2=4:D3=0:D4=2:D5=14:D6=12:D7=13:D8=15:D9=3:D10=1
Then refer to the pin constants as below :
a = PIN(D1)
PIN(D3) = 1
The pins GPIO1 (TXD0) and GPIO3 (RXD0) can be used as normal GPIO pins simply declaring them as input or output using the command PIN.MODE .
However, they can be restored at their normal function using the same command with the keyword SPECIAL :
PIN.MODE 1,
INPUT ' set pin 1 (TX) as input
PIN.MODE 3, OUTPUT ' set pin 3
(RX) as output
PIN.MODE 1, SPECIAL ' restore the pin 1 as (TX)
PIN.MODE 3, SPECIAL ' restore the pin 3 as (RX)
The INTERRUPT command permit 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.
Example:
pin.mode 12,
input ' set pin 12 as input |
ESP8266 has a single ADC channel available to users. It can be used to read voltage at ADC pin.
To read the voltage applied at the pin, the function ADC can be used as below :
print ADC
The voltage range is 0 ... 1.0V and the corresponding range returned by the function is 0 … 1024.
Some modules (like the NodeMCU) have a voltage divider that modify this range.
In particular, the NodeMCU have a full scale range of 3.3V.
The ESP8266 contains several H/W interfaces that can be controlled by Annex WI-Fi Basic using specific commands and functions.
This functionality permits to control the output duty cycle of any pin, acting like an analog output.
The pin can be any available pin and the range of the value can be from 0 to 1023.
To use it, there is no need to configure the pin, the command PWM can be used directly as below:
PWM(12) = 512
To disable PWM :
PWM(12) = 0
The default PWM Frequency is 1000 Hz but can be changed using the command
OPTION.PWMFREQ freq where freq can be any value from 1 Hz to 40000 Hz
NOTE :
The ESP doesn't have hardware PWM, so the implementation is by software.
With one PWM output at 40KHz, the CPU is already rather loaded. The more PWM outputs used, and the higher their frequency, the closer you get to the CPU limits, and the less CPU cycles are available for sketch execution.
TONE
It is possible to generate a tone on any pin using the command PIN.TONE.
The syntax is PIN.TONE pin, freq [, duration]
The pin can be any valid GPIO, the frequency can be between 1 and 5000Hz, the optional parameter duration define the duration of the tone in msec; if not defined the tone will last forever and can be removed using the same command with frequency equal to 0.
Example :
PIN.TONE 14, 1000, 200 ‘ tone of 1000Hz on pin 14 for 200 msec
PIN.TONE 14, 100 ‘ tone of 100Hz non stop
PIN.TONE 14, 0 ‘ clear the tone
This functionality exposes the ability to control RC (hobby) servo motors. It support up to 4 servos on any available pin.
While many RC servo motors will accept the 3.3V IO data pin from a ESP8266, most will not be able to run off 3.3v and will require another power source that matches their specifications. Make sure to connect the grounds between the ESP8266 and the servo motor power supply.
Before using it, the servo channel (from 1 to 4) and the pin must be defined.
This can be done using the command SERVO.SETUP id, pin as below :
SERVO.SETUP 1, 12 ' attach the servo #1 to pin GPIO12
SERVO.SETUP 2, 13 ' attach the servo #2 to pin GPIO13
After the definition, the servo can be controlled with the command SERVO value as below:
SERVO 1, 90 ' set the servo 1 at 90°
SERVO 2, 45 ' set the servo 2 at 45°
The value must be within the range from 0 to 180
To detach the servo from the pin, use the command SERVO.SETUP id, OFF as below :
SERVO.SETUP 1, OFF
SERVO.SETUP 2, OFF
This functionality exposes two counters that permit to count pulses from any input pin.
Each counter can return the frequency of the signal using a timeframe of one second.
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 frequency can be read using the function COUNTER.FREQ(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.FREQ(1) ‘print the frequency 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 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 control the speed of a 3-wire 12V PC fan.
The PID utilise 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 |
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 4(SDA) and 5(SCL) the command is :
I2C.SETUP 4, 5
It is important to provide the correct pullup resistor on these lines; values from 10K to 100K 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
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 4, 5 ' set I2C port on pins 4 and 5
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 ESP8266.
It provides 8 digital inputs or outputs.
This is an example of code that "drives" this module:
I2C.SETUP 4, 5 ' set I2C port on pins 4 and 5 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.begin device_address i2c.reqfrom device_address, 1 x = i2c.read i2c.end end sub |
This is another example of a 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
dim BUFF_IN(2) ' buffer used for read/write to module i2c.setup 4,5 ' 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 4, 5 ' set I2C port on pins 4 and 5 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 ESP8266 is the master. The ESP 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 ESP8266) |
GPIO14 |
MISO |
Master Input Slave Output (data input to the ESP8266) |
GPIO12 |
MOSI |
Master Output Slave Input (data output from the ESP8266) |
GPIO13 |
[1] [2] Chip Select (often active low, output from the ESP8266) |
Any pin, controlled by user program |
The commands available are :
SPI.SETUP speed [,data_mode [, bit_order]]
SPI.SETMODE data_mode
SPI.SETFREQ speed
The functions available are :
ret = SPI.BYTE(byte)
a$ = SPI.STRING$(data$, len)
a$ = SPI.HEX$(datahex$, len)
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 pin.mode 16,output ' set the Pin used for CS as output
for i = 0 to 255 M_74HC595 i next i
end
sub M_74HC595(x) pin(16) = 1 'put the CS HIGH r = spi.byte(x) pin(16) = 0 'pulse the CS low then high pin(16) = 1 end sub |
This is another example of a connection of a module with MCP23S17 bought on Ebay at less than 2€.
This module provides 16 GPIO pins that can be used as digital input or output.
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 pin(15) = 1 'the GPIO15 is the CS pin.mode 15, output
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) local a pin(15) = 0 a = SPI.byte(MCP23S17_ADDR) a = SPI.byte(register) a = SPI.byte(value) pin(15) = 1 end sub
sub MCP23S17_READ(register, value) local a pin(15) = 0 a = SPI.byte(MCP23S17_ADDR or 1) a = SPI.byte(register) value = SPI.byte(0) pin(15) = 1 end sub |
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 works with a parallel interface.
Because the number of pins available on the ESP module is very limited, there is an additional module (in general sold with the display itself) permitting the connection using the bus I2C.
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 4, 5 ' set I2C port on pins 4 and 5
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 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" |
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 the 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 4, 5 ' set I2C port on pins 4 and 5
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.REFRESH
The current implementation of the OLED is based on a double buffering; this permit to draw in background on the screen while the current image is still shown. This technique permit to avoid flickering while drawing objects on the screen. The command OLED.REFRESH fmt permit 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) permit to draw object 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 OLED.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 command OLED.FONT font_num permits to define the font to be used by the command OLED.PRINT.
There are 4 fonts available, FIXED_5X7, ARIAL MT10, ARIAL MT16, ARIAL MT24.
Example:
I2C.SETUP 4, 5 ' set I2C port on pins 4 and 5 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 the 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.
As this display use the SPI bus and its speed it is limited at around 1Mb/sec the first command must be:
SPI.INIT 1000000
Then, 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.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 permits you 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 command ST7920.FONT font_num permits to define the font to be used by the command ST7920.PRINT.
There are 4 fonts available, FIXED_5X7, ARIAL MT10, ARIAL MT16, ARIAL MT24.
Example:
SPI.SETUP 1000000 ' set the SPI at 1MB/sec 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" |
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€.
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 4, 5 ' set I2C port on pins 4 and 5 Print "The date is " + RTC.DATE$ Print "The time is " + RTC.TIME$ |
A PWM / Servo module based on the chip 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 [,freq]
PCA9685.SETFREQ freq
PCA9685.PWM pin, value
In order to use the module, it must be first set with the command PCA9685.SETUP address [,freq]
If not specified, the PWM frequency is set by default at 1000Hz
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 displays 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.
As the protocol used by this chip is very similar to the I2C, this display can share the same pins used for other I2C devices.
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 4, 5
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 4, 5, 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 4, 5 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 4, 5, 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 4, 5, 15 For i = 0 to 9999 TM1638.PRINT str$(i) Next i |
As the module contains also 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 4, 5, 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 4, 5, 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 provide 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 [,reverse]
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 [,reverse].
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).
The 3rd argument, if =1, permit to use modules with a reversed order digits.
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 if the rightmost line of the display and increasing this value will move the text more on the left.
Optionally is 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 show with 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 ESP8266.
This pin must be the pin GPIO2 that is fixed and cannot be changed.
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 :
NEO.SETUP nb_led
NEO.STRIP led_start_pos, led_end_pos, R, G, B [, disable]
NEO.STRIP led_start_pos, led_end_pos, COLOR [, disable]
NEO.PIXEL led_pos, R, G, B [, disable]
NEO.PIXEL led_pos, COLOR [, disable]
NEO.RGB(R, G, B)
NEO.GETPIXEL(pos)
The first command, NEO.SETUP [nb_led], defines the size (in pîxels) of the led strip.
For example NEO.SETUP 60 defines a strip containing 60 leds (or a ring with 60 leds).
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 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 set the led at the position 10 with the color RED and the command NEO.STRIP 20, 30, 0, 0, 255 set the leds at the position 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 number where the 3 colors are merged together as a whole.
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, permit to write in 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 refresh one by one at 100ms interval :
NEO.SETUP 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 60
FOR z = 0 TO 59
NEO.PIXEL z, 128, 1
PAUSE 100
NEXT z
NEO.PIXEL 59, 128
It is also possible to connect Dot Matrix modules based on WS2812B Leds.
These modules contain 64 WS2812B leds organised in 8x8 matrix.
Several modules can be chained in order to compose a large display.
The wiring is very simple as only one output pin is required for the ESP8266.
This pin must be the pin GPIO2 that is fixed and cannot be changed.
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 in consequence.
From a practical point of view, the displays will 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).
Available Instructions are:
NEOSCROLL.SETUP nb_devices [, serpentine]
NEOSCROLL.PRINT msg$
NEOSCROLL.NEXT msg$
NEOSCROLL.COLORS col$
NEOSCROLL.NEXTCOLORS col$
NEOSCROLL.SHOW pos [, brightness]
NEOSCROLL.TEXT msg$
NEOSCROLL.SCROLL [brightness]
NEOSCROLL.OSCILLATE [brightness]
NEOSCROLL.CLS [refresh]
To use it, the first command required is the setup of the display.
This can be done with the command NEOSCROLL.SETUP nb_devices [, serpentine].
The first argument defines the number of 8x8 modules connected; using the schematic shown above, the number is 4.
The 2nd 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 is 1, the serpentine layout is chosen.
In our case the command must be :
NEOSCROLL.SETUP 4
The text can then be set on the display with 3 different commands :
4. NEOSCROLL.PRINT msg$
5. NEOSCROLL.NEXT msg$
6. NEOSCROLL.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,
NEOSCROLL.PRINT "Hello"
NEOSCROLL.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 NEOSCROLL.NEXT msg$
The command NEOSCROLL.TEXT msg$ will permit you to modify the text during the scrolling sequence, useful for “dynamic” messages (i.e time/date information).
As the display permit to show colors, 2 more commands are available:
1. NEOSCROLL.COLORS col$
2. NEOSCROLL.NEXTCOLORS col$
The first defines the colors of the text set with the commandNEOSCROLL.PRINT whilst the 2nd defines the colors of the text set with the command NEOSCROLL.NEXT.
These command NEOSCROLL.COLORS defines the color of each character of the text set with the command NEOSCROLL.PRINT .
The logic is based on a one-to-one correspondence between the text string and the color string.
The color is based on this table :
COLOR |
CODE |
Blue |
B |
Green |
G |
Cyan |
C |
Red |
R |
Magenta |
M |
Yellow |
Y |
Black |
K |
White |
W |
White |
Any other char |
For example, the commands
NEOSCROLL.PRINT "Hello"
NEOSCROLL.COLOR "RGBCM"
Will show the string “Hello” where the first character is Red, the 2nd Green, the 3rd Blue, ….
With the same logic, the commands
NEOSCROLL.NEXT "Friend"
NEOSCROLL.NEXTCOLOR "YWRGBM"
Will show the string “Friend” where the first character is Yellow, the 2nd White, the 3rd Red, ….
The command NEOSCROLL.SHOW position [, brightness] will permit to move the text in a given position.
The position 1 if the rightmost line of the display and increasing this value will move the text more on the left.
Optionally is is possible to define the brightness of the display.
The last set of commands is composed of
3. NEOSCROLL.SCROLL [brightness]
4. NEOSCROLL.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 NEOSCROLL.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 (off) to 255 (max); the default value is 5.
Take into account that these displays are very bright so a luminosity of 5 is already enough.
As the message requires a continuous scrolling, these commands must be called on a timed interval (using a timer).
Let show with an example using the SCROLL command
'Set 4 WS2812B displays with GPIO2 as input NeoScroll.Setup 4 'Set the first message as the current time NeoScroll.print "TRY Annex WiFi BASIC" NeoScroll.colors "CMYRGCRGBYWRGBCMYRGB"
'Set the next message NeoScroll.next "Hello World!" NeoScroll.nextcolors "BYWRGBCMYRGB"
'Set the refresh rate of the display (30 msec) - lower values -> scroll faster timer0 30, scrollme wait
Scrollme: 'Scroll the display with an intensity of 5 NeoScroll.scroll 5 return |
This is another example using the OSCILLATE command:
'Set 4 WS2812B displays with GPIO2 as input NeoScroll.Setup 4 'Set the first message as the current time NeoScroll.print "000" NeoScroll.colors "RBG"
'Set the refresh rate of the display (50 msec) - lower values -> scroll faster timer0 50, scrollme
'Set the counter at 0 v = 0 'Set the incrementing rate timer1 100, increment
wait
Scrollme: 'Scroll the display with an intensity of 5 NeoScroll.oscillate 5 return
increment: v = (v + 1) mod 1000 'increment and limits the value at 999 NeoScroll.text str$(v, "%03f") return |
A TFT Display based on the 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 2.8” and are very cheap.
The resolution of the display is 320 x 240 pixels with 65K colors.
They can also contain a touchscreen controller that permits receiving feedback from the user 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.
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 for display only
Wiring for Display and Touchscreen
In order to use the TFT, the first step is to initialise the Display
This can be done with the following commands :
TFT.INIT 16, 4, 1 ‘ (16 is the pin for CS, 4 is the pin for D/C, 1 is the landscape orientation)
The display is initialized, by default, for a SPI speed of 40 Mhz.
In case of problems (spurious pixels and lines) this can be changed using the command SPI.SETUP speed.
Example
SPI.SETUP 20000000 ‘ set the speed at 20 Mhz.
The display can then be cleared with the command
TFT.FILL 0
The display is now ready to receive drawing commands.
The list of commands available is :
TFT.CIRCLE, TFT.LINE, TFT.PRINT, TFT.RECT, TFT.TEXT.COL, TFT.TEXT.POS, TFT.TEXT.SIZE, TFT.BMP
The list of the functions available is:
TFT.RGB
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 RGB(255,0,0) defines the color RED and TFT.RGB(0,255,0) defines the color green.
Look at the documentation for the details of each command.
Example :
tft.init 16, 4, 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 |
This is a little pong game given as a TFT example.
It uses an iphone as a remote controller using an UDP connection.
The iphone application is the RCW controller already shown in the I/O buffer chapter
' simple pong example using the remote UDP controller ' RCW controller for IOS (ipad and iphone) ' control the paddle with up and down arrow ' the controller must be connected using the port 10000 udp.begin 10000 onudp received ' set the TFT tft.init 16, 4, 3 tft.fill 0 tft.text.size 2 ' text size of the score tft.text.col tft.rgb(0, 255, 0), 0 ' color of the score
speed = 5 ' speed of game. lower is faster dx = 1 dy = 1 x = 100 y = 100 py = 120 py_p = py dp = 0 score = 0
tft.rect 0, py-30, 4, 30, 63488, 1 'paddle while 1 tft.rect x, y, 10, 10, 0, 1 ' clear the ball x = x + dx y = y + dy tft.rect x, y, 10, 10, 65535, 1 'redraw the ball in the new position 'limits the position of the ball if (x <= 0) or (x >= 319) then dx = - dx if (y <= 0) or (y >= 239) then dy = - dy py_p = py py = py + dp
if py_p <> py then if py > py_p then tft.rect 0, py, 4, 1 , 63488, 1 'paddle tft.rect 0, py-31 , 4, 1 , 0, 1 'paddle else tft.rect 0, py+1 , 4, 1 , 0, 1 'paddle tft.rect 0, py-30, 4, 1 , 63488, 1 'paddle end if end if ' limits of the paddle if (py <= 30) or (py >= 239) then dp = 0 pause speed ' determine the speed of the game tft.text.pos 280, 0 tft.print score if (x = 4) then pp = py - y if (pp >=0 ) and (pp < 35 ) then score = score + 1 if (pp < 10) then dy = 1 if (pp > 20) then dy = -1 dx = 1 else tft.rect 0, py-30, 4, 30, 63488, 1 'redraw paddle tft.rect x, y, 10, 10, 0, 1 'clear ball pause 1000 score = 0 'reset the score dx = 1 if rnd(2) = 0 then dy = 1 else dy = -1 y = rnd(239) end if end if wend
received: udp.read_iobuff(0) ' use the byte 1 top detemine the button pushed arrows = iobuff.read(0, 1)
if arrows = 1 then dp = -1 if arrows = 2 then dp = 1 if arrows = 0 then dp = 0 return |
The touchscreen functionality permits to get the position of the point pressed on the screen.
It is associated with the event OnTouch and the functions TOUCH.X and TOUCH.Y.
The command Touch.Setup defines the pin used for the Touchscreen.
Example:
Touch.Setup 15 OnTouch touchme wait
touchme: print "touched", touch.x, touch.y return |
A TFT Display based on the chipset ST7735 can be connected to the module using the SPI interface.
These displays are available on Ebay at different sizes and are very cheap.
The resolution is variable in function of the display and is in general available with a resolution going from 80 x 160 to 128 x 160 pixels with 65K colors.
The pictures below shows a 1.8” model with a resolution of 128 x 160 with a RED TAB
The pictures below shows a 1.44” model with a resolution of 128 x 128 with a GREEN TAB
The pictures below shows a 0.96” model with a resolution of 80 x 160
These displays may 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.
This display can be controlled using the same commands as for the ILI9341 except for the initialisation command TFT.INIT that has specific parameters:
TFT.INIT CS_PIN, DC_PIN, Orientation, Display_width, Display_height, Variant
CS_PIN defines the pin where CS signal is connected
DC_PIN defines the pin where DC signal is connected
Orientation defines the orientation of the display (see table below)
Display_height defines the height (in pixels) of the display in portrait orientation
Display_width defines the height (in pixels) of the display in portrait orientation
Variant defines the variant of the display (see text below)
Variant define the type of display, originally this was based on the colour of the tab on the screen protector film but this is not always true, so try out the different options below if the screen does not display graphics correctly, e.g. colours wrong, mirror images, or tray pixels at the edges.
Variant |
Display model |
0 |
Green Tab (default) |
1 |
Red Tab |
2 |
Black Tab |
3 |
Green Tab 2 |
4 |
Green Tab 3 |
5 |
Green Tab 128 x 128 |
6 |
Green Tab 80 x 160 |
7 |
Red Tab 80 x 160 |
8 |
Other |
Orientation |
Display model |
0 |
Portrait |
1 |
Landscape |
2 |
Portrait reversed |
3 |
Landscape reversed |
The display is initialized, by default, for a SPI speed of 40 Mhz and this is in general too fast for these displays.
In case of problems (spurious pixels and lines) this can be changed using the command SPI.SETUP speed.
Example
SPI.SETUP 20000000 ‘ set the speed at 20 Mhz.
Initialisation examples :
Initialise the first display (1.8” model with a resolution of 128 x 160 with a RED TAB )
TFT.INIT 16, 4, 1, 128, 160, 1
Initialise the 2nd display (1.44” model with a resolution of 128 x 128 with a GREEN TAB )
TFT.INIT 16, 4, 1, 128, 128, 5
Initialise the 3rd display ( 0.96” model with a resolution of 80 x 160 )
TFT.INIT 16, 4, 1, 80, 160, 6
Look at the documentation for the details of each command.
Example :
' setup a display 128 x 128 tft.init 16, 4, 1, 128, 128, 5 ' reduce the speed at 20 Mhz Spi.setup 20000000 tft.fill 0 for r = 0 to 30000 step 0.02 d=r/6 s=sin(r)*sin(5*r+d)*50+64 c=cos(r)*sin(5*r+d)*50+64 tft.circle s,c,10,rnd(65535),1 next r |
An infrared receiver can be connected to the module permitting it 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 GPIO14:
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 14, 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 14, 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 14 i2c.setup 4,5 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).
There is just one function, DISTANCE(pin_trig, pin_echo) that 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 the ones that are actually 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.TEMP ; "°C" |
One or several DS18B20 Temperature sensors can be connected.
The picture below shows the ones that are actually 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])
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" |
To read the temperature from a unique device connected, the code is :
Print "The Temperature is ";TEMPR$(2, 1) ; "°C"
|
It is important to note that, if the ID is not specified, the command will return the Hex address of the device(s) connected.
A BNO055 Absolute Orientation Sensor can be connected to the module using the 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 frees the ESP8266 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 enables 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)] that 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 background.
Refers to the following link for more information : BNO055 Calibration
Example
i2c.setup 4, 5
' set I2C port on pins 4 and
5 print "Heading:", bno055.heading print "Calibrated:", bno055.calib
pause 100 |
A BME280 Sensor can be connected to the module using the I2C interface.
This unit combines individual high linearity, high accuracy sensors for pressure, humidity and temperature.
A unit based on the chip BMP280 can also be used, except that this one doesn’t contain the 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
4, 5
' set I2C port on pins 4 and
5 |
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 utilizes four directional photodiodes to sense reflected IR energy (sourced by the integrated LED) to convert physical motion information (i.e. direction and distance) to 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 then possible to get the recognised gesture with the function APDS9960.READGESTURE
Example
'APDS9960
GESTURE SENSOR DEMO |
The module can also be configured as Ambient & RGB light sensor.
In this case “mode” must be 2 for “Ambient Light and RGB Color” mode.
Example
'APDS9960
LIGHT SENSOR DEMO |
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 |
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 sectors 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 A that is valid for all the blocks of the same sector (i.e. the blocks 4 to 7).
Then, the function RFID.READ$(block) 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 |
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 |
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
An AC light dimmer including a Z-C detector (Zero Cross detector) is also supported by Annex.
A good example is the Robodyn module that is easily available on the internet for very cheap.
In order to achieve a very precise timing, the input side of the serial port is used as a timer.
For this reason, as soon as this functionality is enabled, the console is lost (the print command will not work anymore) but this is not a problem as the WLOG command is always available.
The module must be connected using as below:
As the GPIO3 is often connected in the ESP8266 modules to a USB/serial converter chip, it is possible to swap this connection toward the GPIO13 using the argument “swap” available in DIMMER.SETUP
To start using the module, it must be setup using the command
Where :
pin_in is the pin used for the Z-C input signal
pin_out is the pin used for the output dimmer signal
The optional argument invert enable to use a module with an inverted Z-C pulse
The optional argument enables to swap use the GPIO13 pin instead of the GPIO3
Example:
DIMMER.SETUP 4, 5 'set GPIO4 as input, GPIO5 as output and GPIO3 as RX
DIMMER.SETUP 4, 5, 0, 1 'set GPPIO4 as input, GPIO5 as output and GPIO13 as RX
Is then possible to set the light intensity using the command
For 50 Hz it can be from 0 (intensity max) to 10000 (off)
For 60 Hz it can be from 0 (intensity max) to 8333 (off)
As each AC light dimmer brand may have different characteristics, the best is to try experimentally the values that correspond to the min and max intensity.
As soon as these values are known, it is possible to put them into the command
Doing that, it will be possible to set the light intensity with the command
using a range from 0 to 100.
Finally, the command
stops all and restores the serial port.
Note : by default DIMMER.LIMITS is set with 1000 and 7000 (values adapted for 60Hz)
Example:
'ROBODYN LIGHT DIMMER DEMO DIMMER.SETUP 4, 5 'set GPIO4 as input, GPIO5 as output and GPIO3 as RX DIMMER.LIMITS 1000, 7000 'set limits at 1000 and 7000 uSec DIMMER.BRIGHTNESS 50 'set the intensity at 50% |
Annex also supports the Sonoff B1 lamps, easily available on the internet at low cost.
These lamps contain an ESP8266 with 1MB of flash that can be easily hacked to be re-flashed with Annex.
Inside the lamp there are 5 blocks of leds that can be controlled independently :
- Red
- Green
- Blue
- Warm White
- Cold White
As soon Annex is flashed inside, the following commands are available :
Lamp driver initialisation
Control of the RGB intensity
Where each color can be from 0 to 255
Where color is a 24 bits RGB color
Where cold and warm can be from 0 to 255
Example:
'SONOFF B1 LAMP DEMO SONOFFB1.INIT 'init the lamp driver SONOFFB1.RGB 255, 0, 0 'set full red color SONOFFB1.WHITE 0, 255 'set full warm white color |
Annex also supports the TUYA RGBCW lamps, easily available on the internet at low cost.
These lamps contain an ESP8266 or an ESP8285 with 1 or 2 MB of flash that can be easily hacked to be re-flashed with Annex.
They are quite generic (based on the chip sm2135) as Tuya distributes them under several brand names.
Inside the lamp there are 5 blocks of leds that can be controlled independently :
- Red
- Green
- Blue
- Warm White
- Cold White
As soon Annex is flashed inside, the following commands are available :
Lamp driver initialisation
Where max_current_RGB represents the max current allowed for the RGB leds
and max_current_WHITE represents the max current allowed for the Cold and Warm white leds
If not defined, the default values are 20mA for the RGB and 15mA for the White.
Their value can span from 10mA to 60mA but should be changed with care as excessive values could damage the lamp.
Control of the RGB intensity
Where each color can be from 0 to 255
Where color is a 24 bits RGB color
Where cold and warm can be from 0 to 255
Example:
'Tuya Lamp RGBCW demo 'initialise the lamp with full Warm White 'and create a little web page to control each color individually tuyalamp.init 20, 50 red = 0 : green = 0 : blue = 0 cold = 0 : warm = 0 tuyalamp.rgb red, green, blue tuyalamp.white cold, warm
onHtmlReload draw_page onHtmlChange change_colors gosub draw_page wait
draw_page: cls a$ = "TUYA LAMP COLOR CONTROL DEMO<br>" a$ = a$ + "red " + replace$(slider$(red, 0, 255, "slider"), "onchange", "oninput") + "<br>" a$ = a$ + "green" + replace$(slider$(green, 0, 255, "slider"), "onchange", "oninput") + "<br>" a$ = a$ + "blue" + replace$(slider$(blue, 0, 255, "slider"), "onchange", "oninput") + "<br>" a$ = a$ + "cold" + replace$(slider$(cold, 0, 255, "slider"), "onchange", "oninput") + "<br>" a$ = a$ + "warm" + replace$(slider$(warm, 0, 255, "slider"), "onchange", "oninput") + "<br>" html a$ return
change_colors: tuyalamp.rgb red, green, blue tuyalamp.white cold, warm return |
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 and POST 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 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 are transferred inside the url of the request, the POST method transfers the data in the body of the message.
Annex implements 3 methods to make HTTP requests :
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 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 header for WGET$, WPOST$ and WGETASYNC.
If this parameter is 1, the server header 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.
By default the command WGETASYNC execute a ping on the remote server before trying the connection.
This can avoid memory leaks in case of a server not alive.
This behaviour can be modified specifying 0 for the parameter ping
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 only publish QoS 0 messages.
- It can subscribe at QoS 0, QoS 1.
- The maximum message size is 1024 characters
- The keepalive interval is set to 15 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 is possible to use a Server Fingerprint. (to be described deeply)
In general a SERVER FINGERPRINT is a text block like this :
"B9:82:D3:A3:A8:64:9B:BD:A3:4E:46:84:BB:DB:B3:DF:1A:44:67:76" |
The SERVER FINGERPRINT can be used as a simple validation mechanism to ensure that the ESP8266 is connected to the right MQTT server.
The following table describes the functions available.
All the numerical functions return 0 if successful or 1 if there is a problem.
This is an example based on the free MQTT test server “test.mosquitto.org”.
It uses the protocol mqtt on the default port 1883
The program subscribes and sends messages to the same “/AnnexTest” topic.
It should print the same messages it sent to the server.
' MQTT test program ' Using mosquitto test server print mqtt.setup("mqtt://test.mosquitto.org") print mqtt.connect("", "") ' No login / pass required print mqtt.subscribe("/AnnexTest") ' subscribe to the topic /AnnexTest onmqtt mqtt_msg
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” using a Server Fingerprint.
It uses the protocol mqtts on the default port 8883
The program subscribes and sends messages to the same “/AnnexTest” topic.
It should print the same messages it sent to the server.
' MQTT test program ' Using mosquitto test server - check the instructions on https://test.mosquitto.org/ print "setup" , mqtt.setup("mqtts://test.mosquitto.org") f$ = "EE:BC:4B:F8:57:E3:D3:E4:07:54:23:1E:F0:C8:A1:56:E0:D3:1A:1C" print "finger", mqtt.fingerprint(f$) i = mqtt.connect("", "") ' No login / pass required if (i = 1) then print "Connection error", mqtt.status end end if print "subscribe", mqtt.subscribe("/AnnexTest") ' subscribe to the topic /AnnexTest onmqtt mqtt_msg
for z = 1 to 10 ' send messages to the topic /AnnexTest print "publish", 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” using a Server Fingerprint.
It uses the protocol mqtts on the port 8885 where is authenticated with the user rw / readwrite
The program subscribes and sends messages to the same “/AnnexTest” topic.
It should print the same messages it sent to the server.
' MQTT test program ' Using mosquitto test server ' Check the instructions on https://test.mosquitto.org/ print "setup" , mqtt.setup("mqtts://test.mosquitto.org:8885") f$ = "EE:BC:4B:F8:57:E3:D3:E4:07:54:23:1E:F0:C8:A1:56:E0:D3:1A:1C" print "finger", mqtt.fingerprint(f$) i = mqtt.connect("rw", "readwrite") ' No login / pass required if (i = 1) then print "Connection error", mqtt.status end end if print "subscribe", mqtt.subscribe("/AnnexTest") ' subscribe to the topic /AnnexTest onmqtt mqtt_msg
for z = 1 to 10 ' send messages to the topic /AnnexTest print "publish", 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 |
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 peers(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.
In order to simplify the setup of the communication between the modules, the command OPTION.MAC mac$ has been implemented.
It permit to define an arbitrary MAC address of the module :
OPTION.MAC "AA:BB:CC:DD:EE:FF" ' set the MAC address to AA:BB:CC:DD:EE:FF
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 |
Ret = EspNow.Begin |
starts the ESP-NOW communications |
Ret = EspNow.Stop |
stops the ESP-NOW communications |
Ret = EspNow.Add_Peer(MAC_add$) |
add a peer (module) to the ‘receiver’ list |
Ret = EspNow.Del_Peer(msg$) |
delete a peer (module) from the ‘receiver’ list |
Ret = EspNow.Write(msg$) |
write a message to the peers defined in the list |
Ret = EspNow.Write(msg$, MAC_add$) |
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 a 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 |
Msg$ = EspNow.READ$ |
Read the message received |
MAC_add$ = ESPNow.REMOTE$ |
Read the MAC address of the emitter of the message received |
Err$ = ESPNow.ERROR$ |
Read the MAC address of the device(s) that didn’t received the message |
EVENTS |
DESCRIPTION |
OnEspNowMsg label |
Trigger an event each time a message is received |
OnEspNowError label |
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 message 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 also 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 |
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
- 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 max time that the commands will wait for an answer from the telegram server
TELEGRAM.SetWait 20 ‘ set the max time at 10 seconds (the default is 10 seconds)
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
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
'Get the update each 5 seconds timer0 5000, getmessages wait
getmessages: 'Receive the messages r$ = telegram.getUpdates$ 'get the new messages 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 |
A set of conversion functions has 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 |
CONVERT.DEGC_TO_F(degC) |
Converts from °C to °F |
CONVERT.F_TO_DEGC(degF) |
Converts from °F to °C |
CONVERT.TO_IEEE754(num) |
Converts from float number to IEEE754 binary format |
CONVERT.FROM_IEEE754(iee754_bin) |
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. |
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 also be written using it as destination..
CONSTANT |
DESCRIPTION |
||||||||||||||||
BAS.VER |
Returns the version of the Basic in numerical format Example: Print BAS.VER 1.37 |
||||||||||||||||
BAS.VER$ |
Returns the version of the Basic in string format Example: Print BAS.VER$ Annex WI-Fi 1.37 |
||||||||||||||||
BAS.ERRLINE |
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. |
||||||||||||||||
BAS.ERRNUM |
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. |
||||||||||||||||
BAS.ERRMSG$ |
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. |
||||||||||||||||
BAS.FILENAME$ |
Returns the name of the current basic file |
||||||||||||||||
BAS.RTCMEM$ |
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 512 bytes and can be set with the corresponding command BAS.RTCMEM$ = “xxx”. |
||||||||||||||||
BAS.SSID$ |
Returns the login used for the STATION wifi connection. |
||||||||||||||||
BAS.PASSWORD$ |
Returns the password used for the STATION wifi connection.
|
||||||||||||||||
BAS.LOAD |
Loads another .bas program and run it immediately. Returns 0 if successful or -1 if the file was not found Example: Print BAS.LOAD "/test.bas" |
||||||||||||||||
BAS.RESETREASON |
Returns the reason of last reset. The reason is defined in the table below
|
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 |
||||||||
OPTION.CPUFREQ 80|160 |
Define CPU speed in Mhz of the module. The value can be 80 or 160. The default value is 160Mhz. Setting the speed at 80Mhz, will divide by 2 the speed of the module but lower the power requirement of the module of around 5mA |
||||||||
OPTION.MAC mac$ |
Define an arbitrary MAC address for the module. ‘mac$’ must be a valid MAC address. Example : OPTION.MAC "AA:BB:CC:DD:EE:FF" |
||||||||
OPTION.LOWRAM memory |
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). |
||||||||
OPTION.PWMFREQ freq |
Define PWM frequency speed in Hz of the module. The value can be from 1 to 40000 Hz. The default value is 1000 Hz |
||||||||
OPTION.NTPSYNC |
Sync the local time with the remote NTP servers |
||||||||
OPTION.WDT timeout_msec |
Define the timeout (in msec) for the Watchdog timer. If the WDT is not reset regularly with the command OPTION.WDTRESET within the defined timeout_msec, the module will reset automatically. Setting timeout_msec at 0, will disable the watchdog. |
||||||||
OPTION.WDTRESET |
Reset the Watchdog timer |
||||||||
OPTION.WLOG value |
Define how the log will be printed in the Editor page
|
The functions are divided into 2 groups :
- Numerical functions (Double precision / integer)
- String functions
The string functions are always terminated by a ‘$’ (dollar) sign.
ABS(number) |
Returns the absolute value of the argument 'number' |
||||||||||||||||||||||||||||||||||||||||||||||||||||
ACOS(number) |
Returns the arccosine value of the argument 'number' in radians |
||||||||||||||||||||||||||||||||||||||||||||||||||||
ADC |
Returns external voltage applied to the ADC pin. The value goes from 0 to 1024. Input voltage range is 0 ... 1.0V. Note: some modules implement a voltage divider that modify the range (example the nodeMCU full scale is 3.3V) |
||||||||||||||||||||||||||||||||||||||||||||||||||||
APDS9960.SETUP (mode) |
Initialise a APDS9960 sensor connected using I2C to the module. ‘mode’ determine the sensing modality as per the table below :
Before using it, the I2C bus must be initialised with the command I2C.SETUP This function returns 1 if the APDS9960 sensor has been found, otherwise returns 0 |
||||||||||||||||||||||||||||||||||||||||||||||||||||
APDS9960.READGESTURE |
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 :
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
APDS9960.AMBIENT |
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 |
||||||||||||||||||||||||||||||||||||||||||||||||||||
APDS9960.RED |
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 |
||||||||||||||||||||||||||||||||||||||||||||||||||||
APDS9960.GREEN |
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 |
||||||||||||||||||||||||||||||||||||||||||||||||||||
APDS9960.BLUE |
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 |
||||||||||||||||||||||||||||||||||||||||||||||||||||
APDS9960.PROXIMITY |
Returns a 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 |
||||||||||||||||||||||||||||||||||||||||||||||||||||
APDS9960.GESTUREGAIN (gain) |
Set the gain of the gesture sensing provided by the APDS9960 sensor. ‘gain’ can be one of the following values:
This function returns 1 if the function was successful, otherwise returns 0 |
||||||||||||||||||||||||||||||||||||||||||||||||||||
APDS9960.GESTURELED (intensity) |
Set the inensity of the LED used during the gesture sensing provided by the APDS9960 sensor. ‘intensity’ can be one of the following values:
This function returns 1 if the function was successful, otherwise returns 0 |
||||||||||||||||||||||||||||||||||||||||||||||||||||
ASC(string$) |
Returns the ASCII code of the first char in ‘string$’ |
||||||||||||||||||||||||||||||||||||||||||||||||||||
ASIN(number) |
Returns the arcsine value of the argument 'number' in radians |
||||||||||||||||||||||||||||||||||||||||||||||||||||
ATAN(number) |
Returns the arctangent of the argument 'number' in radians |
||||||||||||||||||||||||||||||||||||||||||||||||||||
ATAN2(x, y) |
Returns the angle whose tangent is the quotient of two specified numbers. |
||||||||||||||||||||||||||||||||||||||||||||||||||||
BAS.VER |
Returns the version of the Basic in numerical format Example: Print BAS.VER 1.37 |
||||||||||||||||||||||||||||||||||||||||||||||||||||
BAS.ERRLINE |
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. |
||||||||||||||||||||||||||||||||||||||||||||||||||||
BAS.ERRNUM |
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. |
||||||||||||||||||||||||||||||||||||||||||||||||||||
BME280.SETUP(address) |
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 |
||||||||||||||||||||||||||||||||||||||||||||||||||||
BME280.ALT(qnh) |
Returns the current altitude using the baro pressure from the sensor BME280. The sea level pressure (in HectoPascal) must be given as argument. The unit of the value returned is Meters (m) |
||||||||||||||||||||||||||||||||||||||||||||||||||||
BME280.HUM |
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. |
||||||||||||||||||||||||||||||||||||||||||||||||||||
BME280.QFE |
Returns the Barometric Pressure parameter from the sensor BME280. The unit of the value returned is HectoPascal ‘Hpa’ |
||||||||||||||||||||||||||||||||||||||||||||||||||||
BME280.QNH(altitude) |
Returns the sea level pressure using the baro pressure from the sensor BME280. The current altitude (in meters) must be given as argument. The unit of the value returned is HectoPascal ‘Hpa’ |
||||||||||||||||||||||||||||||||||||||||||||||||||||
BME280.TEMP |
Returns the Temperature parameter from the sensor BME280. The unit of the value returned is ‘%’ |
||||||||||||||||||||||||||||||||||||||||||||||||||||
BNO055.SETUP( address) |
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 |
||||||||||||||||||||||||||||||||||||||||||||||||||||
BNO055.HEADING |
Returns the Heading angle information from the sensor BNO055. The unit of the value returned is ‘degrees’ |
||||||||||||||||||||||||||||||||||||||||||||||||||||
BNO055.PITCH |
Returns the Pitch angle information from the sensor BNO055. The unit of the value returned is ‘degrees’ |
||||||||||||||||||||||||||||||||||||||||||||||||||||
BNO055.ROLL |
Returns the Roll angle information from the sensor BNO055. The unit of the value returned is ‘degrees’ |
||||||||||||||||||||||||||||||||||||||||||||||||||||
BNO055.VECTOR ( param, axis) |
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)
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
BNO055.CALIB [(param)] |
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
Example: Print “Is Calibrated“, BNO055.CALIB |
||||||||||||||||||||||||||||||||||||||||||||||||||||
CINT(number) |
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(). |
||||||||||||||||||||||||||||||||||||||||||||||||||||
CONVERT.DEGC_TO_F(degC) |
Converts from °C to °F |
||||||||||||||||||||||||||||||||||||||||||||||||||||
CONVERT.F_TO_DEGC(degF) |
Converts from °F to °C |
||||||||||||||||||||||||||||||||||||||||||||||||||||
CONVERT.TO_IEEE754(num) |
Converts from float number to IEEE754 binary format |
||||||||||||||||||||||||||||||||||||||||||||||||||||
CONVERT.FROM_IEEE754(ieee754_bin) |
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. |
||||||||||||||||||||||||||||||||||||||||||||||||||||
COS(number) |
Returns the cosine of the argument 'number' in radians. |
||||||||||||||||||||||||||||||||||||||||||||||||||||
COUNTER.COUNT (cnt) |
Returns the number of pulses recorded by the counter. ‘cnt’ identify the counter and can be 1 or 2 It is associated with the commands COUNTER.SETUP, COUNTER.RESET, COUNTER.FREQ |
||||||||||||||||||||||||||||||||||||||||||||||||||||
COUNTER.FREQ (cnt) |
Returns the frequency of the pulses recorded by the counter. The frequency is refreshed once per second. ‘cnt’ identify the counter and can be 1 or 2 It is associated with the commands COUNTER.SETUP, COUNTER.RESET, COUNTER.PERIOD |
||||||||||||||||||||||||||||||||||||||||||||||||||||
COUNTER.PERIOD (cnt) |
Returns the period of time between 2 successive pulses recorded by the counter. The value returned is expressed in uS (micro seconds). ‘cnt’ identify the counter and can be 1 or 2 It is associated with the commands COUNTER.SETUP, COUNTER.RESET, COUNTER.FREQ |
||||||||||||||||||||||||||||||||||||||||||||||||||||
DATEUNIX(date$) |
Converts a date in format dd/mm/yy into UNIX FORMAT. See also TIMEUNIX, and the complementary UNIXDATE$ and UNIXTIME$ |
||||||||||||||||||||||||||||||||||||||||||||||||||||
DHT.TEMP |
Returns the temperature of the DHT sensor set with "DHT.SETUP" The syntax is temp = DHT.TEMP Returns the temperature in °C |
||||||||||||||||||||||||||||||||||||||||||||||||||||
DHT.HUM |
Returns the humidity of the DHT sensor set with "DHT.SETUP" The syntax is hum = DHT.HUM Returns the humidity in % |
||||||||||||||||||||||||||||||||||||||||||||||||||||
DHT.HEATINDEX |
Returns the heat index of the DHT sensor set with "DHT.SETUP" The syntax is heat = DHT.HEATINDEX Returns the heatindex in °C |
||||||||||||||||||||||||||||||||||||||||||||||||||||
DISTANCE(pin_trig, pin_echo) |
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. |
||||||||||||||||||||||||||||||||||||||||||||||||||||
EMAIL from$, to$, subject$, message$ |
Send an e-mail and returns the status of the sending. The program will stop the execution until the message is sent or an error occurred. The result will be 1 if OK or 0 is a problem happened. ‘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 : r = EMAIL ("from_me@yahoo.com", "to_you@gmail.com", "Important message " + date$, "The memory available is " + str$(ramfree) ) |
||||||||||||||||||||||||||||||||||||||||||||||||||||
ESPNOW.ADD_PEER(MAC_add$) |
Add a peer (module) to the ‘receiver’ list. The peer is specified by its MAC address Returns 0 if OK or another number in case of error |
||||||||||||||||||||||||||||||||||||||||||||||||||||
ESPNOW.BEGIN |
Starts the ESP-NOW communications. Returns 0 if OK or another number in case of error |
||||||||||||||||||||||||||||||||||||||||||||||||||||
ESPNOW.DEL_PEER(MAC_add$) |
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 |
||||||||||||||||||||||||||||||||||||||||||||||||||||
ESPNOW.STOP |
Stops the ESP-NOW communications. Returns 0 if OK or another number in case of error |
||||||||||||||||||||||||||||||||||||||||||||||||||||
ESPNOW.WRITE( msg$) |
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 |
||||||||||||||||||||||||||||||||||||||||||||||||||||
ESPNOW.WRITE( msg$,MAC_add$) |
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 |
||||||||||||||||||||||||||||||||||||||||||||||||||||
EXP(number) |
Returns the exponential value of 'number'. |
||||||||||||||||||||||||||||||||||||||||||||||||||||
FIX(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() . |
||||||||||||||||||||||||||||||||||||||||||||||||||||
FILE.COPY(filename$, newfile$) |
Copy the file filename$ into the file newfile$ Returns 1 in case of success or 0 if error
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
FILE.DELETE(filename$) |
Delete the file specified by ‘filename$’. Returns 1 if the delete was successful, otherwise returns 0 |
||||||||||||||||||||||||||||||||||||||||||||||||||||
FILE.EXISTS(filename$) |
Returns 1 if the file ‘filename$’ exists, otherwise returns 0 |
||||||||||||||||||||||||||||||||||||||||||||||||||||
FILE.RENAME(oldname$, newname$) |
Rename the file oldname$ to newname$ Returns 1 in case of success or 0 if error
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
FILE.SIZE(filename$) |
Returns the size of the file (in bytes) if the file exist, otherwise returns -1 |
||||||||||||||||||||||||||||||||||||||||||||||||||||
FLASHFREE |
Returns the free disk memory available (number of bytes) |
||||||||||||||||||||||||||||||||||||||||||||||||||||
FUSION.ANGLE(axis) |
Returns the angles (in degrees) calculated by the FUSION algorithm. The returned value is :
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
INSTR([start], string$, pattern$) |
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 |
||||||||||||||||||||||||||||||||||||||||||||||||||||
I2C.LEN |
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 |
||||||||||||||||||||||||||||||||||||||||||||||||||||
I2C.READ |
Reads a byte that was transmitted from a slave device to a master after a call to I2C.REQFROM. Example: b = I2C.READ |
||||||||||||||||||||||||||||||||||||||||||||||||||||
I2C.READREGBYTE (i2c_address, register) |
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 parenthesis) |
||||||||||||||||||||||||||||||||||||||||||||||||||||
I2C.END |
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 |
||||||||||||||||||||||||||||||||||||||||||||||||||||
INT(number) |
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() . |
||||||||||||||||||||||||||||||||||||||||||||||||||||
LEN(string$) |
Returns the length of the string ‘string$’ |
||||||||||||||||||||||||||||||||||||||||||||||||||||
LOG(number) |
Returns the natural logarithm of the argument 'number' |
||||||||||||||||||||||||||||||||||||||||||||||||||||
MILLIS |
Returns the number of milliseconds passed from the start-up of the module |
||||||||||||||||||||||||||||||||||||||||||||||||||||
MQTT.Setup(server$ ) |
Setup the MQTT communications. Server$ is the MQTT server url This function clears the existing Server Fingerprint. Returns 0 if OK |
||||||||||||||||||||||||||||||||||||||||||||||||||||
MQTT.Fingerprint(fingerprint$) |
Set the server Fingerprint; it is a string composed of 20 hex bytes separated by colon, i.e. "B9:82:D3:A3:A8:64:9B:BD:A3:4E:46:84:BB:DB:B3:DF:1A:44:67:76" |
||||||||||||||||||||||||||||||||||||||||||||||||||||
MQTT.Connect(login$, pass$, [id$]) |
Connect to the server using the provided login and password. Optionally ID$ permits to define an arbitrary ID Returns 0 if OK |
||||||||||||||||||||||||||||||||||||||||||||||||||||
MQTT.Connect("", "", [id$]) |
Connect to the server without identification Optionally ID$ permits to define an arbitrary ID Returns 0 if OK |
||||||||||||||||||||||||||||||||||||||||||||||||||||
MQTT.Disconnect[()] |
Disconnects from the MQTT server Returns 0 if OK |
||||||||||||||||||||||||||||||||||||||||||||||||||||
MQTT.Publish(topic$, message$) |
Publish a string message in the specified topic Returns 0 if OK |
||||||||||||||||||||||||||||||||||||||||||||||||||||
MQTT.Subscribe(topic$ [,Qos]) |
Subscribes to messages published to the specified topic. Qos can be 0 or 1; if not defined defaults to 0 Returns 0 if OK |
||||||||||||||||||||||||||||||||||||||||||||||||||||
MQTT.UnSubscribe(topic$) |
Unsubscribes from the specified topic Returns 0 if OK |
||||||||||||||||||||||||||||||||||||||||||||||||||||
MQTT.Connected[()] |
Returns the current connection status. Returns 1 if connected or 0 if disconnected |
||||||||||||||||||||||||||||||||||||||||||||||||||||
MQTT.Status[()] |
Returns the current status. It can be:
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
NEO.GETPIXEL(pos) |
Gets, in a stripline, the merged color value of the led at position 'led_pos' |
||||||||||||||||||||||||||||||||||||||||||||||||||||
NEO.RGB(R, G, B) |
Returns the 3 supplied R,G,B colours merged into a single 24bit RGB color value, useful for the NEO.PIXEL function and web page colors |
||||||||||||||||||||||||||||||||||||||||||||||||||||
PI |
Returns the value 3.1415925…. |
||||||||||||||||||||||||||||||||||||||||||||||||||||
PID1.COMPUTE( current_value, target_value) |
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. |
||||||||||||||||||||||||||||||||||||||||||||||||||||
PIN(pin_number) |
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 |
||||||||||||||||||||||||||||||||||||||||||||||||||||
PING(host$) |
The ping function can be used to test the ability of the ESP8266 to reach a specified destination computer. The ping command is usually used as a simple way 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 0 Example: Print PING("www.google.com") Print PING("192.168.1.1") Important: This function doesn’t works in immediate mode. |
||||||||||||||||||||||||||||||||||||||||||||||||||||
POW(x, y) |
Return the number x raised to the power of y |
||||||||||||||||||||||||||||||||||||||||||||||||||||
RAMFREE |
Returns the free ram available (number of bytes) |
||||||||||||||||||||||||||||||||||||||||||||||||||||
RND(number) |
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. |
||||||||||||||||||||||||||||||||||||||||||||||||||||
SERIAL.LEN |
Returns the number of chars available in the receive buffer of the serial port |
||||||||||||||||||||||||||||||||||||||||||||||||||||
SERIAL2.LEN |
Returns the number of chars available in the receive buffer of the serial port #2 |
||||||||||||||||||||||||||||||||||||||||||||||||||||
SGN(number) |
Returns the sign of the argument 'number', +1 for positive numbers, 0 for 0, and -1 for negative numbers. |
||||||||||||||||||||||||||||||||||||||||||||||||||||
SIN(number) |
Returns the sine of the argument 'number' in radians. |
||||||||||||||||||||||||||||||||||||||||||||||||||||
SPI.BYTE(byte) |
Write and receive a byte on the SPI bus. Send the content of ‘byte’ and returns the byte received Example: r = SPI.BYTE(&haa) |
||||||||||||||||||||||||||||||||||||||||||||||||||||
SQR(number) |
Return the square root of the argument ‘number’ |
||||||||||||||||||||||||||||||||||||||||||||||||||||
TAN(number) |
Returns the tangent of the argument 'number' in radians. |
||||||||||||||||||||||||||||||||||||||||||||||||||||
TFT.RGB(r,g,b) |
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 |
||||||||||||||||||||||||||||||||||||||||||||||||||||
TIMEUNIX(time$) |
Converts a time in format hh:mm:ss into UNIX FORMAT. See also DATEUNIX, and the complementary UNIXTIME$ and UNIXDATE$ |
||||||||||||||||||||||||||||||||||||||||||||||||||||
TM1638.BUTTONS |
Returns the state of the 8 buttons installed on the module TM1638. It returns an 8-bits value where each bit is associated with a button Example : Print TM1638.BUTTONS ‘print 1 if the button 1 is pressed |
||||||||||||||||||||||||||||||||||||||||||||||||||||
TOUCH.X |
Returns the X position of the touched position on the TFT screen. Useful in combination with the function TOUCH.Y and the command ONTOUCH |
||||||||||||||||||||||||||||||||||||||||||||||||||||
TOUCH.Y |
Returns the Y position of the touched position on the TFT screen. Useful in combination with the function TOUCH.X and the command ONTOUCH |
||||||||||||||||||||||||||||||||||||||||||||||||||||
VAL(string$) |
Returns the supplied string 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$) |
||||||||||||||||||||||||||||||||||||||||||||||||||||
WIFI.CHANNEL |
Returns the current radio channel used for the WIFI communication. Can be a number from 1 to 13 |
||||||||||||||||||||||||||||||||||||||||||||||||||||
WIFI.MODE |
Return the current mode of the WIFI connection. The returned value is:
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
WIFI.NETWORKS ( network$ ) |
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, the RSSI and the Channel radio separated by comma (,).
Example : WIFI.SCAN While WIFI.NETWORKS(A$) = -1 Wend Print a$
The result will be : Vodaphone, 00:50:56:C0:00:08, -50, 5 Orange, 00:50:56:C0:32:07, -70, 6 Xxxx, 00:50:56:C0:86:CA,-78, 11 |
||||||||||||||||||||||||||||||||||||||||||||||||||||
WIFI.RSSI |
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). |
||||||||||||||||||||||||||||||||||||||||||||||||||||
WIFI.STATUS |
Returns the status of the WIFI connection. The returned value is :
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
WORD.COUNT( string$ [,delimiter$]) |
This function returns the number of the words in the 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. |
||||||||||||||||||||||||||||||||||||||||||||||||||||
WORD.FIND( string$, find$ [,delimiter$]) |
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. |
BAS.ERRMSG$ |
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. |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
BAS.FILENAME$ |
Returns the name of the current basic file |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
BAS.FTP$( host$, login$, password$, file$, folder$) |
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 |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
BAS.PASSWORD$ |
Returns the password used for the STATION wifi connection.
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
BAS.RTCMEM$ |
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 512 bytes and can be set with the corresponding command BAS.RTCMEM$ = “xxx”. |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
BAS.SSID$ |
Returns the login used for the STATION wifi connection. |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
BAS.VER$ |
Returns the version of the Basic in string format Example: Print BAS.VER$ Annex WI-Fi 1.37 |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
BIN$(number) |
Returns the Binary representation of the argument ‘number’. The number is converted to integer before the conversion. |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
BUTTON$(name$, label [, id] ) |
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 |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
CHECKBOX$( variable [,id]) |
Returns a string containing the html representation of a checkbox. ‘variable’ represent 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 |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
CHR$(number) |
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 |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
CSSID$(object_id, object_style) |
Returns a string containing the css representation of style defined for a given object. ‘object_id’ represent the ID of the object to be styled. ‘object _style’ represent the property to be given to the object. Check the chapter about html objects for more details |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
DATE$[(format)] |
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 |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
ESPNOW.ERROR$ |
Returns the MAC address of the device(s) that didn’t received the message |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
ESPNOW.READ$ |
Returns the message received from the ESP-NOW peer |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
ESPNOW.REMOTE$ |
Returns the MAC address of the emitter of the message received |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
FILE.DIR$[(path$)] |
Will search for files and return the names of entries found. 'path$' represent the directory name. 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 |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
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. |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
HEX$(number) |
Returns the Hexadecimal representation of the argument ‘number’ The number is converted to integer before the conversion. |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
HtmlEventButton$ |
returns the name of the button that generate the jump. Useful to manage several buttons in the same function |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
HtmlEventVar$ |
Returns the name of the variable changed during the event onHtmlChange. Useful to determine the object that changed its value |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
IMAGE$(path [,id]) |
Returns a string containing the html representation of an image. ‘Path’ represent the url of the image; it can be local or from 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 |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
IMAGEBUTTON$(path, label [,id]) |
Returns a string containing the html representation of an image that can be clicked as a button. ‘Path’ represent the url of the image; it can be local or from 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 |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
IP$ |
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 |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
IR.GET$[ (param) ] |
Returns the code received by the IR receiver. In function of the param value, the function returns :
Must be used in association with the command IR.INIT and ONINFRARED Example IR.GET$ ‘ will print the HEX code received |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
JSON$(string$, field$) |
Will parse a json string for a named data element within it. It 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" |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
LCASE$(string$) |
Returns ‘string$’ converted to lowercase characters |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
LED$(variable[$] [,id]) |
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). If the variable is a string (variable$), the color of the led can be freely defined using html colors. ‘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 Example: b = 1 : html led$(b) ‘ draw a green led b$ = “yellow” : html led$(b$) ‘ draw a yellow led b$ = “#ff9900” : html led$(b$) ‘ draw a amber led b$ = “#f00” : html led$(b$) ‘ draw a red led |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
LEFT$(string$, num) |
Returns the leftmost ‘num’ characters of ‘string$’ |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
LISTBOX$(variable$, "option1, option2, option3, ..." [, height] [,id]) |
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 String. ‘option1’, ‘option2’, …. represent the content of the listbox. ‘height’ is an optional parameter and define the height of the listbox; if not defined, the object will be a combobox ‘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 |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
METER$(variable, min, max [,id]) |
Returns a string containing the html representation of a meter. ‘variable’ represent 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 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 |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
MID$(string$, start [,num]) |
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" |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
MAC$[ (id) ] |
Returns the active MAC address. It consists of 6 hex bytes separated by colon. 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 |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
MQTT.Message$ |
Returns the MQTT message received |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
MQTT.Topic$ |
Returns the MQTT topic received |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
OCT$(number) |
Returns the Octal representation of the argument ‘number’ The number is converted to integer before the conversion. |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
PASSWORD$(variable [, id] ) |
Returns a string containing the html representation of a password 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 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 |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
REPLACE$(expression$, find$, replacewith$) |
Returns a substring of ‘expression$’ where the text inside ‘find$’ is replaced with ‘replacewith$’ |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
RIGHT$(string$, num) |
Returns the rightmost ‘num’ characters of ‘string$’ |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
RTC.DATE$[(format)] |
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" |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
RTC.TIME$ |
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" |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
SERIAL.CHR$ |
Returns the first character present in the input buffer of the serial port Useful in association with the command ONSERIAL |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
SERIAL.INPUT$ |
Returns all the characters present in the input buffer of the serial port. Useful in association with the command ONSERIAL |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
SERIAL2.CHR$ |
Returns the first character present in the input buffer of the serial port #2 Useful in association with the command ONSERIAL |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
SERIAL2.INPUT$ |
Returns all the characters present in the input buffer of the serial port #2 Useful in association with the command ONSERIAL2 |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
SLIDER$(variable, min, max [,step] [,id]) |
Returns a string containing the html representation of a slider. ‘variable’ represent 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’ represent the minimal increment (by default the value is 1). ‘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 |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
SPACE$(number) |
Returns a string consisting of the specified number of spaces. |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
SPI.STRING$(data$, len) |
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) |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
SPI.HEX$(datahex$, len) |
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$ |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
STR$ (number [,format$ [,toint]]) |
Returns the argument ‘‘number’ converted to string format.
The optional ‘format$’ permit to define how the number is printed. The format is based on ‘C’ printf command. The last optional format ‘toint’, if =1, permit to convert the number in integer format. This is useful to convert the number in integer format. Example : a = 12.34567890 Print STR$(a, "%2.4f") ‘ will print 12.3456 Print STR$(a, "%3.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 :
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
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
STRING$(num, char$) |
Returns a string ‘num’ chars long composed of the char ‘char$’ - char$ can also be a string of chars, eg: "<BR>" or " " |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
TEMPR$(pin_number [,ID]) |
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 |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
TEXTAREA$(variable [, id] ) |
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 |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
TEXTBOX$(variable [, id] ) |
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 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 |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
TRIM$(string$) |
Returns ‘string$’ with the leading and trailing spaces removed |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
TIME$ |
Returns the actual time with the format hh:mm:ss. The time takes into account the Time Zone parameter defined into the "Config" page. |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
UCASE$(string$) |
Returns ‘string$’ converted to uppercase characters |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
UDP.READ$ |
Returns the UDP message received or an empty string if no message received. Useful in association with the command ONUDP |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
UDP.REMOTE$ |
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 |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
UNIXDATE$(value [,format]) |
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() |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
UNIXTIME$(value) |
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() |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
URLMSGGET$ ([arg$]) |
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 |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
WGET$( http_server$, port [,header] ) |
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. |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
WGET$( url$, [,header] ) |
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. |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
WGETRESULT$ |
Return the message received asynchronously from the command WGETASYNC |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
WPOST$(server$, body$, port [,header]) |
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 waiting for the answer. Example : print WPOST$("ptsv2.com/t/annextest/post", "name=Annex&version=1.39", 80) |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
WPOST$(url$, body$, [,header]) |
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") |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
WORD$(string$, position [,delimiter$]) |
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$ |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
WORD.DELETE$(string$, position [delimiter$]) |
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. |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
WORD.EXTRACT$(string$, lead$, trail$) |
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 |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
WORD.GETPARAM$( setting$, parameter$ [,separator$]) |
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 get. ‘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$ |
AUTOREFRESH interval |
Same function of the command REFRESH but with an automatic interval. Define the variables refresh interval in milliseconds. NOTE: It must be run after the command CLS as it is managed into the javascript. This command does not have the same timing limitation of REFRESH so the timing can be faster. |
||||||||||||||||||||||||||||||
BAS.LOAD filename$ |
Loads another .bas program and run it immediately. Returns 0 if the successful or -1 if the file was not found Example: Print BAS.LOAD "/test.bas" |
||||||||||||||||||||||||||||||
BAS.RTCMEM$ = val$ |
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. This memory is limited at 512 bytes and can be read with the corresponding command val$ = BAS.RTCMEM$ |
||||||||||||||||||||||||||||||
CLS |
Clear the html content of the page to all the clients connected by Websockets. This command is equivalent to TRACE "cls"
Check the chapter about html objects for more details See also the commands TRACE, HTML, JSCALL, JSCRIPT, JSEXTERNAL, CSS and WLOG |
||||||||||||||||||||||||||||||
CSS style_code$ |
Send a CSS style code to the page to all the clients connected by Websockets. This command is equivalent to TRACE "csshtml" + style_code$
Check the chapter about html objects for more details See also the commands TRACE, HTML, JSCALL, JSCRIPT, JSEXTERNAL, CLS and WLOG |
||||||||||||||||||||||||||||||
COMMAND cmd$ |
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 |
||||||||||||||||||||||||||||||
COUNTER.RESET cnt |
Reset the counter to 0 (count and period). ‘cnt” defines the counter and can be 1 or 2 It is associated with the commands COUNTER.SETUP, COUNTER.COUNT, COUNTER.FREQ, COUNTER.PERIOD |
||||||||||||||||||||||||||||||
COUNTER.SETUP cnt, pin [,mode] |
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 :
If not specified, the mode is 3 (on change) It is associated with the commands COUNTER.RESET, COUNTER.COUNT, COUNTER.FREQ, COUNTER.PERIOD |
||||||||||||||||||||||||||||||
CSSEXTERNAL file$ |
Define an external css file to be used in the page of all the clients connected by Websockets. This command is equivalent to TRACE "extcss" + file$
Check the chapter about html objects for more details See also the commands TRACE, CLS, HTML, JSCALL, JSCRIPT, CSS and WLOG |
||||||||||||||||||||||||||||||
DATA const1 [,const2] ... |
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) |
||||||||||||||||||||||||||||||
DHT.SETUP pin, model |
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 |
||||||||||||||||||||||||||||||
EMAIL.SETUP server$, port, user_name$, password$ [, debug] |
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 rely on a 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, enable a debug mode useful to catch connection problems. Example : EMAIL.SETUP "mail.smtp2go.com", 465, "my_login", "my_pass" |
||||||||||||||||||||||||||||||
EMAILASYNC from$, to$, subject$, message$ |
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) ) |
||||||||||||||||||||||||||||||
FILE.APPEND filename$, content$ |
Append the content of ‘content$’ to the file ‘filename$’. If the file does not exists, it will be created. The file can be read back using the function FILE.READ$(filename$). File size is only limited by available SPIFFS memory, but the length of filename$ is limited to 31 characters including folder and "/" separators |
||||||||||||||||||||||||||||||
FILE.SAVE filename$, content$ |
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 SPIFFS memory, but the length of filename$ is limited to 31 characters including folder and "/" separators |
||||||||||||||||||||||||||||||
FUSION.INIT |
Initialise the FUSION IMU / AHRS algorithm |
||||||||||||||||||||||||||||||
FUSION.MADGWICK ax, ay, az, gx, gy, gz |
Execute the MADGWICK 6 DOF algo The input parameters are the following :
(*) the unit is not really important but must be consistent between the group This algo utilise the variables FUSION.BETA and FUSION.ZETA |
||||||||||||||||||||||||||||||
FUSION.MADGWICK ax, ay, az, gx, gy, gz, mx, my, mz |
Execute the MADGWICK 9 DOF algo The input parameters are the following :
(*) the unit is not really important but must be consistent between the group This algo utilise the variable FUSION.BETA |
||||||||||||||||||||||||||||||
FUSION.MAHONY ax, ay, az, gx, gy, gz, mx, my, mz |
Execute the MAHONY 9 DOF algo The input parameters are the following :
(*) the unit is not really important but must be consistent between the group This algo utilise the variables FUSION.KP and FUSION.KI |
||||||||||||||||||||||||||||||
FUSION.BETA = |
Set the BETA parameter. This is used for the MADGWICK algo 6 DOF and 9 DOF. |
||||||||||||||||||||||||||||||
FUSION.ZETA = |
Set the ZETA parameter. This is used for the MADGWICK algo 6 DOF. |
||||||||||||||||||||||||||||||
FUSION.KI = |
Set the KI parameter. This is used for the MAHONY algo 9 DOF. |
||||||||||||||||||||||||||||||
FUSION.KP = |
Set the KP parameter. This is used for the MAHONY algo 9 DOF. |
||||||||||||||||||||||||||||||
HTML code$ |
Send html content to the page of all the clients connected by Websockets. This command is equivalent to TRACE "html" + code$
Check the chapter about html objects for more details See also the commands TRACE, CLS, JSCALL, JSCRIPT, JSEXTERNAL, CSS and WLOG |
||||||||||||||||||||||||||||||
I2C.SETUP sda_pin, scl_pin [,freq [,stretch]] |
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 700 Khz) and the stretch timeout can also be defined using the parameters ‘freq’ and ‘stretch’ Example: I2C.SETUP 4, 5 ‘ define the pin 4 as SDA and the pin 5 as SCL |
||||||||||||||||||||||||||||||
I2C.BEGIN address |
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 the 7-bit address of the device to transmit to Example: I2C.BEGIN &h57 ‘ begins the transmission on the address hex 57 |
||||||||||||||||||||||||||||||
I2C.END |
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 |
||||||||||||||||||||||||||||||
I2C.REQFROM address, length |
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
|
||||||||||||||||||||||||||||||
I2C.READREGARRAY i2c_address, register, nb_of_bytes, Array() |
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 |
||||||||||||||||||||||||||||||
I2C.WRITE value |
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 |
||||||||||||||||||||||||||||||
I2C.WRITEREGBYTE i2c_address,register, value |
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 |
||||||||||||||||||||||||||||||
I2C.WRITEREGARRAY i2c_address, register, nb_of_bytes, Array() |
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 |
||||||||||||||||||||||||||||||
INPUT.TIMEOUT timeout |
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 remove the timeout |
||||||||||||||||||||||||||||||
INPUT["prompt$";] variable |
Allows input from the console to a variables. 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 stuck. The command INPUT.TIMEOUT will permit to interrupt the command after a given timeout time. |
||||||||||||||||||||||||||||||
INTERRUPT pin_no, {OFF | label} |
Define a place where jumps when the signal on an input pin changes. ‘Pin_no’ defines the input pin - can be from 0 to 15 (pin 16 not supported) ‘Label’ is the place where it will jumps ; putting OFF instead of the label will remove the interrupt Example INTERRUPT 5, pin5_change |
||||||||||||||||||||||||||||||
IR.INIT pin_rx | OFF [, pin_tx] |
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 |
||||||||||||||||||||||||||||||
IR.SEND type, code$, bits |
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, ...) |
||||||||||||||||||||||||||||||
JSCALL javaCode$ |
Send javascript content to the page of all the clients connected by Websockets. This command is equivalent to TRACE "JSCALL:" + javaCode$
Check the chapter about html objects for more details See also the commands TRACE, CLS, HTML, JSCRIPT, JSEXTERNAL, CSS and WLOG |
||||||||||||||||||||||||||||||
JSCRIPT script$ |
Execute a javascript content in the page of all the clients connected by Websockets. This command is equivalent to TRACE "jscript" + script$
Check the chapter about html objects for more details See also the commands TRACE, CLS, HTML, JSCALL, JSEXTERNAL, CSS and WLOG |
||||||||||||||||||||||||||||||
JSEXTERNAL file$ |
Define an external javascript file to be used in the page of all the clients connected by Websockets. This command is equivalent to TRACE "extjs" + file$
Check the chapter about html objects for more details See also the commands TRACE, CLS, HTML, JSCALL, JSCRIPT, CSS and WLOG |
||||||||||||||||||||||||||||||
LCD.INIT address, cols, rows |
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 4,5 ‘init the I2C on pins 4 and 5 LCD.INIT 63, 20, 4 ‘init the LCD at I2C address 63 with 20 columns and 4 rows LCD.PRINT 1,1 "HELLO WORLD" |
||||||||||||||||||||||||||||||
LCD.CLS |
Clear the content of the LCD display connected using I2C to the module |
||||||||||||||||||||||||||||||
LCD.CUSTOM char, array() |
Define the LCD custom characters. ‘char’ can be from 0 to 7 ‘array()’ must contains 8 numerical values that identify the character Check the LCD chapter for more details |
||||||||||||||||||||||||||||||
LCD.PRINT x, y, text$ |
Print a text on the LCD. ‘x’ and ‘y’ define the position where ‘text$’ will be printed |
||||||||||||||||||||||||||||||
LCD.WRITE char |
Write a single char on the LCD. ‘char’ is defined using its ASCII code (i.e. 65 -> A ) The char is printed at the current position |
||||||||||||||||||||||||||||||
LOCAL var1 [,var2], ... |
Defines local variables inside user named subroutines. Using this command inside the subroutines, permit to create variables that exists only during the routine; they will vanish at the end of the routine. This will permit also to avoid to modify unintentionally variables with the same name that are already used elsewhere in the code. See the paragraph "Scope of the variables" for more details. Example: LOCAL I, A$ |
||||||||||||||||||||||||||||||
MAXDISPLAY.SETUP CS_pin |
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 |
||||||||||||||||||||||||||||||
MAXDISPLAY.PRINT msg$ [,‘brightness] |
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 |
||||||||||||||||||||||||||||||
MAXSCROLL.SETUP nb_devices, CS_pin [,reverse] |
Setup 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 The optional argument ‘reverse’, if =1 will permit to use modules with a reversed order of the digit. Example for a 4 digit module available on ebay : MAXSCROLL.SETUP 4, 15 ‘ 4 digits, CS on pin 15 |
||||||||||||||||||||||||||||||
MAXSCROLL.PRINT msg$ |
Print a message on the DotMatrix Display. The message will be shown using the command MAXSCROLL.SCROLL ‘msg$’ defines the message to be shown |
||||||||||||||||||||||||||||||
MAXSCROLL.NEXT msg$ |
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 maintains a continuity on the message shown. ‘msg$’ defines the message that will be printed |
||||||||||||||||||||||||||||||
MAXSCROLL.SHOW pos [, brightness] |
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. |
||||||||||||||||||||||||||||||
MAXSCROLL.SCROLL [brightness] |
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) |
||||||||||||||||||||||||||||||
MAXSCROLL.OSCILLATE [brightness] |
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) |
||||||||||||||||||||||||||||||
NEO.PIXEL led_pos, R, G, B [, disable] |
Set, in a stripline, the led at position 'led_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 |
||||||||||||||||||||||||||||||
NEO.PIXEL led_pos, COLOR [, disable] |
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 |
||||||||||||||||||||||||||||||
NEO.SETUP [nb_led] |
The NEOPIXEL are led strips based on the WS2812 Leds define the pin to be used for the NEO PIXEL commands This pin must be the pin GPIO2 that is fixed and cannot be changed. 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. |
||||||||||||||||||||||||||||||
NEO.STRIP led_start_pos, led_end_pos, R, G, B [, disable] |
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 |
||||||||||||||||||||||||||||||
NEO.STRIP led_start_pos, led_end_pos, COLOR [, disable] |
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 |
||||||||||||||||||||||||||||||
NEOSCROLL.SETUP nb_devices, pin [,serpentine] |
Setup 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 |
||||||||||||||||||||||||||||||
NEOSCROLL.PRINT msg$ |
Print a message on the NeoMatrix Display. The message will be shown using the command NEOSCROLL.SCROLL ‘msg$’ defines the message to be shown |
||||||||||||||||||||||||||||||
NEOSCROLL.NEXT msg$ |
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 |
||||||||||||||||||||||||||||||
NEOSCROLL.COLORS col$ |
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 |
||||||||||||||||||||||||||||||
NEOSCROLL. NEXTCOLORS col$ |
Defines the colors of the message defined with the command NEOSCROLL.NEXT |
||||||||||||||||||||||||||||||
NEOSCROLL.SHOW pos [, brightness] |
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. |
||||||||||||||||||||||||||||||
NEOSCROLL.TEXT msg$ |
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 |
||||||||||||||||||||||||||||||
NEOSCROLL.SCROLL [‘brightness] |
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) |
||||||||||||||||||||||||||||||
NEOSCROLL.OSCILLATE [‘brightness] |
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) |
||||||||||||||||||||||||||||||
OLED.CLS |
Clear the content of the OLED display connected using I2C to the module |
||||||||||||||||||||||||||||||
OLED.INIT orientation [,model] |
Initialise an OLED display connected using I2C to the module. ‘orientation’ is a number that can be 0 or 1 specifying the orientation:
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 4, 5 ' set I2C port on pins 4 and 5 OLED.INIT 1 ‘ init OLED at landscape reversed |
||||||||||||||||||||||||||||||
OLED.REFRESH fmt |
Defines how the image is sent on the OLED after each drawing command. If ‘fmt’ = 1, the image is automatically refreshed after each draawing 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. |
||||||||||||||||||||||||||||||
OLED.COLOR color |
Set the color used by the OLED drawing commands. The color is defined as above:
|
||||||||||||||||||||||||||||||
OLED.PIXEL x, y |
Draw a pixel at the position x, y on the OLED display |
||||||||||||||||||||||||||||||
OLED.LINE x1, y1, x2, y2 |
Draw a line between the point (x1,y1) and the point (x2,y2) on the OLED display |
||||||||||||||||||||||||||||||
OLED.RECT x,y, width, height [,fill] |
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. |
||||||||||||||||||||||||||||||
OLED.CIRCLE x, y, radius [, fill] |
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. |
||||||||||||||||||||||||||||||
OLED.FONT font_num |
Set the font used by the OLED.PRINT command. The font_num is defined as above (by default the font 1 is selected)
|
||||||||||||||||||||||||||||||
OLED.PRINT x, y, text$ [background] |
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. |
||||||||||||||||||||||||||||||
OLED.IMAGE x, y, image$ |
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 |
||||||||||||||||||||||||||||||
ONERROR ABORT or ONERROR IGNORE or ONERROR SKIP [nn] or ONERROR CLEAR or ONERROR GOTO label |
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. |
||||||||||||||||||||||||||||||
ONESPNOWERROR [label | OFF] |
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 |
||||||||||||||||||||||||||||||
ONESPNOWMSG [label | OFF] |
Define the label where the program will jump when an ESP-NOW message is received |
||||||||||||||||||||||||||||||
ONGESTURE [label | OFF] |
Define a label where the program will jump when the APDS9960 sensor detects a gesture. To disable ONGESTURE OFF |
||||||||||||||||||||||||||||||
ONHTMLCHANGE [label | OFF] |
Define a label where the program will jump when an html object present in the output html page change its value. The code must be terminated with ‘RETURN’. To disable ONHTMLCHANGE OFF |
||||||||||||||||||||||||||||||
ONHTMLRELOAD [label | 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 |
||||||||||||||||||||||||||||||
ONINFRARED label |
Define a label where the program will jump when a code is received by the Infrared receiver. The code must be terminated with ‘RETURN’. To disable ONINFRARED OFF |
||||||||||||||||||||||||||||||
OnMQTT label |
Define a label where the program will jump when an MQTT message is received |
||||||||||||||||||||||||||||||
ONSERIAL [label | 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 |
||||||||||||||||||||||||||||||
ONSERIAL2 [label | 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 |
||||||||||||||||||||||||||||||
ONTOUCH [label | 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 |
||||||||||||||||||||||||||||||
ONUDP [label | OFF] |
Define a label where the program will jump when an UDP message is received. The code must be terminated with ‘RETURN’. To disable ONUDP OFF |
||||||||||||||||||||||||||||||
ONURLMESSAGE [label | OFF] |
Define a label where the program will jump when an 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$ |
||||||||||||||||||||||||||||||
ONWGETASYNC [label | OFF] |
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 |
||||||||||||||||||||||||||||||
OPTION.CPUFREQ 80|160 |
Define CPU speed in Mhz of the module. The value can be 80 or 160. The default value is 160Mhz. Setting the speed at 80Mhz, will divide by 2 the speed of the module but lower the power requirement of the module of around 5mA |
||||||||||||||||||||||||||||||
OPTION.MAC mac$ |
Define an arbitrary MAC address for the module. ‘mac$’ must be a valid MAC address. Example : OPTION.MAC "AA:BB:CC:DD:EE:FF" |
||||||||||||||||||||||||||||||
OPTION.LOWRAM value |
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). |
||||||||||||||||||||||||||||||
OPTION.PWMFREQ value |
Define PWM frequency speed in Hz of the module. The value can be from 1 to 40000 Hz. The default value is 1000 Hz |
||||||||||||||||||||||||||||||
OPTION.NTPSYNC |
Sync the local time with the remote NTP Servers |
||||||||||||||||||||||||||||||
OPTION.WDT timeout_msec |
Define the timeout (in msec) for the Watchdog timer. If the WDT is not reset regularly with the command OPTION.WDTRESET within the defined timeout_msec, the module will reset automatically. Setting timeout_msec at 0, will disable the watchdog. |
||||||||||||||||||||||||||||||
OPTION.WDTRESET |
Reset the Watchdog timer |
||||||||||||||||||||||||||||||
PAUSE delay |
Pause the module for ‘delay’ milliseconds. During the pause, all the activities are not suspended (it is non-blocking). This means that the all interrupts will continue to be managed. |
||||||||||||||||||||||||||||||
PCA9685.SETUP addr [,freq] |
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) The optional parameter ‘freq’ defines the PWM frequency; is not set, the default value is 1000Hz Example: PCA9685.SETUP 64 ‘ set the module at the I2C address 64 (40 in hexadecimal) |
||||||||||||||||||||||||||||||
PCA9685.SETFREQ freq |
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 |
||||||||||||||||||||||||||||||
PCA9685.PWM pin, value |
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 |
||||||||||||||||||||||||||||||
PID1.INIT Kp, Ki, Kd |
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. |
||||||||||||||||||||||||||||||
PID1.LIMITS min, max |
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. |
||||||||||||||||||||||||||||||
PID1.PERIOD msec |
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. |
||||||||||||||||||||||||||||||
PID1.PARAMS Kp, Ki, Kd |
Modify the PID parameters for the given PID controller. As there are 4 PID controllers, the prefix can be PID1, PID2, PID3 or PID4. |
||||||||||||||||||||||||||||||
PID1.SETMODE mode |
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. |
||||||||||||||||||||||||||||||
PIN(pin_number) = val |
Set the value of any external I/O pin. The pin_number refers to GPIO and can be from 0 ... 5 or 12 ...15 The val can be 0 or 1 to set the pin to LOW or HIGH Before be used, the pin must be set as OUTPUT with the command PIN.MODE |
||||||||||||||||||||||||||||||
PIN.MODE pin_number, mode [,PULLUP] |
Set any pin to digital mode as input or output. The ‘pin_number’ can be from 0 to 16. The ‘mode can’ be INPUT or OUTPUT or SPECIAL The optional parameter PULLUP permit to add a weak pullup resistor on the pin. The PULLUP is not valid for the pin 16 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
NOTE: The pulldown is not available as not supported by the chip itself |
||||||||||||||||||||||||||||||
PIN.TONE pin, freq [,duration] |
Generates a tone signal on any valid GPIO pin. The ‘frequency’ can be between 1 and 5000Hz. The optional parameter ‘duration’ define the duration of the tone in msec; if not defined the tone will last forever and can be removed using the same command with frequency equal to 0.
Example : PIN.TONE 14, 1000, 200 ‘ tone of 1000Hz on pin 14 for 200 msec PIN.TONE 14, 100 ‘ tone of 100Hz non stop PIN.TONE 14, 0 ‘ clear the tone |
||||||||||||||||||||||||||||||
PRINT expression[[,; ]expression] ... |
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. |
||||||||||||||||||||||||||||||
PRINT2 expression [[,; ]expression] ... |
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. |
||||||||||||||||||||||||||||||
PWM(pin_number) = value |
Set a PWM output on any I/O pin. The ‘pin_number’ can be from 0 to 16. The ‘value’ can be from 0 to 1023. To disable put the value at 0. The PWM frequency is 1KHz |
||||||||||||||||||||||||||||||
READ var1 [,var2] ... |
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. |
||||||||||||||||||||||||||||||
REBOOT |
Reboots the module (software reset). Pay attention that some pins have a specific function and must be at the following logical state during reboot : GPIO0 : High GPIO2 : High GPIO15 : LOW If these conditions aren’t respected, the module will not reboot. |
||||||||||||||||||||||||||||||
REFRESH |
Refresh (sync) the variables in the basic code with the corresponding variables in the input html page (one shot) |
||||||||||||||||||||||||||||||
RESTORE |
Resets the line and position counters for the READ statement at the beginning. |
||||||||||||||||||||||||||||||
RTC.SETTIME Year, Month, Day, Hours, Minutes, Seconds |
Set the RTC module (DS1307 or DS3231) with the date / time provided. ‘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$ |
||||||||||||||||||||||||||||||
SERIAL.BYTE ch1 [,ch2] . . . |
Send one or more byte to the serial port (console). The bytes can one or more separated by a comma. The values can be any value from 0 to 255. Example : SERIAL.BYTE &h10, &h00, &h12, &h09 |
||||||||||||||||||||||||||||||
SERIAL2.BYTE ch1 [,ch2] . . . |
Send one or more byte to the serial port #2. The bytes can one or more separated by a comma. The values can be any value from 0 to 255. Example : SERIAL2.BYTE &h10, &h00, &h12, &h09 |
||||||||||||||||||||||||||||||
SERIAL.MODE baudrate [, bits, parity, stop] |
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 |
||||||||||||||||||||||||||||||
SERIAL2.MODE baudrate, pin_tx, pin rx [, bits, parity, stop] |
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 Note: although it can be used up to 115200 in transmission, reception is limited to 9600 baud. For higher reception speeds, consider the utilisation of the console port. |
||||||||||||||||||||||||||||||
SERVO id, value |
Set the angle of servo connected on the channel ‘id’ ‘id’ define the servo channel (from 1 to 4) ‘Value’ is the desired angle (from 0 to 180) The pin is defined by the command SERVO.SETUP |
||||||||||||||||||||||||||||||
SERVO.SETUP id, pin_number | OFF |
Define the pin that must be used by the servo channel. ‘id’ define the servo channel (from 1 to 4) The ‘pin_number’ can be from 0 to 16. To detach the pin, use ‘OFF’ instead of the pin_number |
||||||||||||||||||||||||||||||
SETTIME Year, Month, Day, Hours, Minutes, Seconds |
Set the internal timekeeper with the date / time provided. ‘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 |
||||||||||||||||||||||||||||||
SLEEP value |
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. Note : GPIO16 must be connected to RST pin to wakeup from sleep NOTE: Maximum time is 4294 seconds (around 71 minutes) It is possible to know if the module has been woken-up from the deep sleep using the function BAS.RESETREASON. |
||||||||||||||||||||||||||||||
SPI.SETUP speed [,data_mode [, bit_order]] |
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. (see the command SPI.SETMODE) bit_order : can be 0 (lsb_first) or 1 (msb_first - default) |
||||||||||||||||||||||||||||||
SPI.SETMODE data_mode |
Set the SPI data mode data_mode : can be 0, 1, 2 or 3.
|
||||||||||||||||||||||||||||||
SPI.SETFREQ speed |
Set the SPI speed (bits/sec) The speed can be max 80000000 (80MHz for CPU running at 160MHz) |
||||||||||||||||||||||||||||||
ST7920.INIT CS_pin |
Initialize an ST7920 display connected using SPI to the module. ‘CS_pin’ defines the pin used for the CS signal This command set automatically the SPI bus speed at 1 Mhz (max frequency allowed by the display) but the SPI bus must be initialised before with the command SPI.SETUP
Example : SPI.SETUP 1000000 ‘ init the SPI bust at 1Mhz ST7920.INIT 15 ‘ init the ST7920 with the CS at pin 15 |
||||||||||||||||||||||||||||||
ST7920.CLS |
Clear the content of the ST7920 display connected using SPI to the module |
||||||||||||||||||||||||||||||
ST7920.REFRESH fmt |
Defines how the image is sent on the ST7920 after each drawing command. If ‘fmt’ = 1, the image is automatically refreshed after each draawing 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. |
||||||||||||||||||||||||||||||
ST7920.COLOR color |
Set the color used by the ST7920 drawing commands. The color is defined as above:
|
||||||||||||||||||||||||||||||
ST7920.PIXEL x, y |
Draw a pixel at the position x, y on the ST7920 display |
||||||||||||||||||||||||||||||
ST7920.LINE x1, y1, x2, y2 |
Draw a line between the point (x1,y1) and the point (x2,y2) on the ST7920 display |
||||||||||||||||||||||||||||||
ST7920.RECT x,y, width, height [,fill] |
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. |
||||||||||||||||||||||||||||||
ST7920.CIRCLE x, y, radius [, fill] |
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. |
||||||||||||||||||||||||||||||
ST7920.FONT font_num |
Set the font used by the ST7920.PRINT command. The font_num is defined as above (by default the font 1 is selected)
|
||||||||||||||||||||||||||||||
ST7920.PRINT x, y, text$ [background] |
Print a text on the ST7920 display. ‘x’ and ‘y’ define the position where ‘text$’ will be printed. An optional ‘background’ parameter permit to specify the background color. |
||||||||||||||||||||||||||||||
ST7920.IMAGE x, y, image$ |
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 |
||||||||||||||||||||||||||||||
TM1637.PRINT msg$ [, brightness] |
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 |
||||||||||||||||||||||||||||||
TM1637.SETUP data_pin, clock_pin [, bit_delay] [, display_type]] |
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 |
||||||||||||||||||||||||||||||
TM1638.PRINT msg$ [, brightness ] |
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 |
||||||||||||||||||||||||||||||
TM1638.SETUP data_pin, clock_pin, strobe_pin |
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 |
||||||||||||||||||||||||||||||
TM1638.LEDS val |
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 |
||||||||||||||||||||||||||||||
TFT.BMP filename$, [x, y [, back_color] ] |
Display a bitmap file on the TFT display. The file must be present on the local disk before use it. The file format must be ".bmp" with 24 or 32 bits. The image can be of any size but is limited at 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 32bits images when a transparent color is defined; in this case the transparence will be replaced by the ‘back_color’. Defining a back_color at -1, the transparence 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 |
||||||||||||||||||||||||||||||
TFT.CIRCLE x, y, radius [, fill] |
Trace a circle at the point (x,y) with the specified radius. Specifying 1 for the argument fill, the circle will be filled.
|
||||||||||||||||||||||||||||||
TFT.FILL color |
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) |
||||||||||||||||||||||||||||||
TFT.INIT CS_pin, DC_pin, orientation [Display_width, Display_height, Variant] |
Initialize a TFT ILI9431 display connected to the module. ‘CS_pin’ is the pin where the TFT pin ‘CS’ is connected ‘DC_pin’ is the pin where the TFT pin ‘DC’is connected ‘orientation’ is a number between 0 and 3 specifying the orientation:
‘Display_height’ defines the height (in pixels) of the display in portrait orientation ‘Display_width’ defines the height (in pixels) of the display in portrait orientation ‘Variant defines’ the variant of the display (see TFT chapter for more details)
Example : TFT.INIT 16, 4, 1 ‘(pin 16 CS, Pin 4 DC, Landscape) Check the chapter about the TFT display for more details |
||||||||||||||||||||||||||||||
TFT.LINE x1, y1, x2, y2, col |
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) |
||||||||||||||||||||||||||||||
TFT.PRINT expression [[,; ]expression] ... |
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. |
||||||||||||||||||||||||||||||
TFT.RECT x, y, width, height, color [ [,fill] ,[round_radius] ] |
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) |
||||||||||||||||||||||||||||||
TFT.TEXT.COL color [,backcolor] |
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 |
||||||||||||||||||||||||||||||
TFT.TEXT.POS x, y |
Position the text cursor at the point (x, y). The text will be printed at that position with the command TFT.PRINT |
||||||||||||||||||||||||||||||
TFT.TEXT.SIZE size |
Set the size of the text that will be printed with the command TFT.PRINT The ‘size’ can be from 1 to 8. |
||||||||||||||||||||||||||||||
TIMER0 interval, label |
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’ define the place where the timer will jump regularly. Setting the interval to 0 will disable it. Nota: The Timer0 has a higher priority against the timer1. Example TIMER0 1000, cycle -> jumps to ‘cycle’ at each second |
||||||||||||||||||||||||||||||
TIMER1 interval, label |
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’ define 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 |
||||||||||||||||||||||||||||||
TOUCH.SETUP T_CS_pin |
Enable the touch screen functionality. ‘T_CS_pin’ defines the pin used for the Touchscreen CS (T_CS). |
||||||||||||||||||||||||||||||
TRACE message |
Send a message to all the clients connected by Websockets. ‘message’ can be a string or a number In coordination with the javascript code present into the file /input.html, there are 4 kind-of commands available :
Check the chapter about html objects for more details See also the commands CLS, HTML, JSCALL, JSCRIPT, JSEXTERNAL, CSS and WLOG |
||||||||||||||||||||||||||||||
UDP.BEGIN(port) |
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$ |
||||||||||||||||||||||||||||||
UDP.REPLY msg$ |
Send an UDP message back to the original transmitter. Permit to answer directly without specify the IP and port |
||||||||||||||||||||||||||||||
UDP.STOP |
Stop the UDP server. |
||||||||||||||||||||||||||||||
UDP.WRITE ip, port, msg$ |
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 |
||||||||||||||||||||||||||||||
URLMSGRETURN msg$ [,content_type$] |
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$ |
||||||||||||||||||||||||||||||
WAIT |
Stops the execution of the program while waiting for events. Useful when using "event driven" code (timers, events, ..) |
||||||||||||||||||||||||||||||
WGETASYNC [(] server$, port, [,header [,ping]] [)]
|
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)
By default this command executes a ping on the remote server before trying the connection. This can avoid memory leaks in case of a server not alive. This behaviour can be modified specifying 0 for the parameter ‘ping’
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 continue to run Print i Next i Wait answer_done: Print WGETRESULT$ Return |
||||||||||||||||||||||||||||||
WGETASYNC [(] url$, [,header [,ping]] [)] |
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)
By default this command executes a ping on the remote server before trying the connection. This can avoid memory leaks in case of a server not alive. This behaviour can be modified specifying 0 for the parameter ‘ping’
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 |
||||||||||||||||||||||||||||||
WIFI.APMODE SSID$, password$ [, channel] [, IP$ , MASK$] |
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 |
||||||||||||||||||||||||||||||
WIFI.AWAKE |
Wake Up the WiFi from the sleep mode triggered with the command WIFI.SLEEP |
||||||||||||||||||||||||||||||
WIFI.CONNECT SSID$, password$ [, BSSID$] [, IP$ , MASK$ [, GATEWAY$]] |
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. |
||||||||||||||||||||||||||||||
WIFI.POWER pow |
Set the output power of WiFi ‘pow’ defines the value in dBm The range is between 0 and 20.5 |
||||||||||||||||||||||||||||||
WIFI.SCAN |
Starts to scan WiFi networks available. Must be used in association with WIFI.NETWORKS |
||||||||||||||||||||||||||||||
WIFI.SLEEP |
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 |
||||||||||||||||||||||||||||||
WLOG expression[[,; ]expression] ... |
Send text content to debug page. This command has the same syntax of the PRINT command, so the PRINT command can be easily replaced with WLOG. 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.
Check the chapter about html objects for more details See also the commands TRACE, CLS, HTML, JSCRIPT, JSEXTERNAL, CSS and JSCALL |
||||||||||||||||||||||||||||||
WORD.DELPARAM setting$, parameter$, [,separator$] |
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 contains : 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 |
||||||||||||||||||||||||||||||
WORD.SETPARAM setting$, parameter$, value$ [,separator$] |
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 contains : light=on temp=10 pump=off
Using the following line: WORD.SETPARAM a$, "temp", "20" A$ will contains : light=on temp=20 pump=off
By default the separator is the character ‘=’. Useful in combination with WORD.GETPARAM$, WORD.DELPARAM and FILE.SAVE |
CASE |
Keyword : Used in combination with the SELECT command |
DIM array(size) [, …] [= init1, init2, …] |
Permit to define arrays. The arrays can be floating point or string. The number of dimensions (subscripts) is limited to 5. The floating point arrays are initialised at 0 while the string arrays are initialized as null string. The array can be re-dimensioned using again the same command DIM. Look at the chapter "Arrays" for more details. |
DO |
The DO loop |
ELSE |
Keyword : Used in combination with the IF and SELECT commands |
END [IF | SELECT | SUB] |
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 |
ENDIF |
Used in combination with the IF command; can be also written as END IF |
EXIT {DO | FOR | SUB} |
Permit to exit from a DO LOOP (EXIT DO), a FOR LOOP (EXIT FOR) or a SUB (EXIT SUB) |
FOR |
FOR command; Used in combination with the NEXT command |
GOSUB [label | lab$] |
Jumps to a named label; the flow control will come back as soon as the command RETURN is reached. Its is possible to specify a string variable instead of a static label name (this permit to create dynamic function calls) |
GOTO [label | lab$] |
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 |
IF command; used in combination with THEN, ELSE ENDIF and END IF |
LET var = expression |
Optional for variable assignment |
LOOP |
Keyword : Used in combination with the DO command |
NEXT |
Keyword : Used in combination with the FOR command |
OFF |
Keyword : used in combination with the INTERRUPT command |
OUTPUT |
Keyword : Used in combination with the PIN.MODE command |
PULLUP |
Keyword : Used in combination with the PIN.MODE command |
REM |
Define a comment(remark); the symbol ‘ can be used instead |
RETURN |
Returns to the caller after a Gosub or an Event happened |
SELECT |
The SELECT CASE |
SPECIAL |
Keyword : Used in combination with the PIN.MODE command |
STEP |
Keyword : Used in combination with the FOR command |
SUB |
Defines "user named" subroutines. Refer to the paragraph "SUB" and "Scope of the variables" for more details. |
THEN |
Keyword : Used in combination with the IF command |
TO |
Keyword : Used in combination with the FOR command |
UNTIL |
Keyword : Used in combination with the DO command |
WEND |
Keyword : Used in combination with the WHILE command |
WHILE |
The WHILE LOOP; also used a s condition for the DO LOOP |