Almost every Arduino beginners kit contains a small 16x2 LCD display, either as a shield or as a separate component. This tutorial is how to use these shield with the BASIC programming language to build little things.
Little things are small machines and applications that can be but together quickly with a few components to do useful jobs. I use BASIC for little things these days, because the BASIC interpreter has many of the standard components like the small LCD screen integrated. This makes everything quick and easy.
This tutorial works is a sequel of two other tutorials on BASIC on Arduinos BASIC programming language for Arduino and The built-in examples in BASIC. It works standalone and doesn't depend on these texts.
A Look at the HardwareThe small LCD shields are based on a 16x2 LCD module. These modules use a standard text based controller from Hitachi and have been around for ages. On C++ they are supported by the LiquidCrystal library. The standard Arduino LCD shields address the display in 4 bit mode. This way only pins 4-9 are needed. The digital I/O pins 2, 3, 10, 11, 12, 13 are free.
The analog pin A0 is used for the keypad. 5 keys are connected to it with varying resistances to distinguish them. The 6th pin is connected to reset. Analog pins A1-A5 are free for applications.
The shield has open connectors for the free pins of the Arduino but usually no headers. I solder small header pins into the shield for lab use. If you don't like to do this, another alternative would be to cut breadboard wires and squeeze them into the headers of the Arduino before putting the shield on it.
For this tutorial, one GND and the 5V pin are needed as well as D3 and A1. This is how I prepare the board "solder free".
A small breadboard is added for the additional electronics of the application.
Installing the BASIC interpreterDownload the sketch Basic2/IoTBasic from my repo https://github.com/slviajero/tinybasic/
Open hardware.h and add look for the section
#define PREDEFINEDBOARD "boards/dummy.h"
change this to
#define PREDEFINEDBOARD "boards/avrlcd.h"
Compile and upload the code to your Arduino UNO. Then connect with the serial monitor. Make sure that in the serial monitor the baudrate is set to 9600 baud and the newline setting is Newline. CR or Newline CR will not work. BASIC will show the command prompt:
To learn more about the language and its basic features, please also have a look at BASIC programming language for Arduino and The built-in examples in BASIC as well as the manual file MANUAL.md.
Test the DisplayOn the command prompt, type
print &2, "Hello World"
and watch the display. The string should show on the first line of the display.
Type
CLS
and the display should be clear again.
PRINT prints any text and expression. The modifier &2 directs the output to the display. If you leave this away, the text is sent to the serial output instead.
Test the keypadType in the little program
10 GET &2,A
20 IF A<>0 THEN PUT &2,A
30 GOTO 10
Then type SAVE to save the program to the EEPROM. Type RUN to run it.
Pressing the buttons of the keypad should display the numbers 1, 2, 3, or 4. Pressing select will send a newline.
GET reads one character from a stream, while PUT writes one or more characters. &2 again is the modifier for the display and the keypad. Without it the program would write on the serial input and output.
The display scrolls automatically as the BASIC display driver implements a buffer and a scrolling terminal. Actually, the terminal is a tiny VT52 with a few useful features.
The running program can be interrupted by sending the '#' character through the serial monitor.
Analog Input - Voltmeters and SensorsSmall display are ideal to display analog data. Put a small 10kOhm potentiometer on the breadboard. Then wire it like this
The sides of the potentiometer are connected to GND and 5V, middle pin goes to A1 of the Arduino.
Then type in the program
100 CLS
110 A=AREAD(15)
120 PRINT &2,A;
130 DELAY 500
140 GOTO 100
Start it with RUN. The program clears the screen, reads an analog input from pin 15 which is A1 and displays it. The semicolon at the end of the PRINT statement suppresses the newline. After 500ms the next measurement is started.
The raw analog values are shown on the display. You also will notice a slight flicker. This is due to the CLS command which has to erase the entire display. There is a better way to do it, which will be shown later.
To make this a bit more fancy, we could remove the flicker and display a voltage instead of a raw value.
Modify the program like this
10 CLS
20 @X=5: @Y=0: PRINT &2,"mV";
100 @X=0: @Y=0: PRINT &2," ";
110 A=AREAD(15)
120 V=MAP(A,0,1023,0,5000)
130 @X=0: @Y=0: PRINT &2,V;
140 DELAY 500
150 GOTO 100
The CLS is now at the beginning, out of the loop. @X and @Y are the cursor position variables. We set the cursor to the first line and the 5th column, print "mV" there and suppress the newline. The loop starts at line 100. We position the cursor, clear the output field, read and map the value to mV. The we rewrite the output field.
The display is calmer now because only 4 digits are updated.
For this example, we still need the potentiometer wired like before and add either a small loudspeaker with a 200 Ohm resistor or a passive piezo buzzer. The loudspeaker or buzzer are connected to pin 3 and ground.
Type in the following BASIC program
10 CLS
20 R=3000
100 V=MAP(AREAD(15),0,1023,0,R)
110 @X=0: @Y=0: PRINT &2,V;" ";
120 GET &2,S
130 IF S="2" THEN PLAY 3,V
140 IF S="1" THEN PLAY 3,0
180 DELAY 250
190 GOTO 100
and RUN it. The display will show the frequency in Hz. Adjust the frequency you like then press the 'Right' button. The sound will play. Stop it with the 'Left' button.
PLAY is the BASIC equivalent of tone().
Add the following lines to make the program even a bit more useful.
150 IF S="4" AND R<9000 THEN R=R+1000
160 IF S="3" AND R>1000 THEN R=R-1000
170 @X=0: @Y=1: PRINT &2,R;
RUN the program again. Now the sound range is displayed in the lower line. Pressing the 'UP' and 'DOWN' button adjusts the range. With 12 lines of code a small lab frequency generator is completed.
Type SET 1, 1 on the command line. The program is now in the EEPROM in autorun mode. The next time the Arduino is restarted, it runs automatically.
The ultrasonic sensor is a piece which is found in many Arduino starter kit. Everyone has one. I use the SR04 type with a separate input and output pin.
The sensor is activated with a pulse on the trigger pin and then one listens to the echo pin for the signal. This is done with the pulseIn() function in Arduino C++. With BASIC the PULSEIN command does this job.
We wire the trigger pin to analog pin A1 and the echo pin to analog pin D3.
Type in the following program
10 PINM 15,1
20 PINM 3,0
100 DWRITE 15,0: DWRITE 15,1: DWRITE 15,0
110 D=PULSEIN(3,1,100)
120 IF D=0 THEN 100
130 C=MAP(D,0,10000,0,17241)
140 @X=0: @Y=0
150 PRINT &2,"d=";C;" mm ";
160 DELAY 500
170 GOTO 100
then SAVE and RUN it. The display shows the distance to the next solid object in mm. It is updated every 500ms. The MAP function is used to convert the time PULSEIN delivers in millimetres. PULSEIN in BASIC reports the time back in 10 microsecond units and not in microseconds like in pulseIn(). This way 16 bit integers can be used to do sound wave stuff.
Sometimes it is more intuitive to show analog values with a status bar than with a number. In this little application the light intensity is displayed with a simple status bar.
A 10 kOhm resistor and a 10 kOhm photoresistor is needed for this. Wire the two components as shown in the picture.
The resistor and the photo sensor are connected on one side to ground and on the other side to 5V. Analog pin A1 is used to measure the voltage. This is just like the schematic of the original Arduino built-in example.
Type in the following program
10 CLS
20 PRINT &2,"Light Intensity";
100 A=AREAD(15)
110 V=MAP(A,0,1023,17,32)
120 FOR I=17 TO V: @D(I)=255: NEXT
130 FOR I=V+1 TO 32: @D(I)=0: NEXT
140 DELAY 200
150 GOTO 100
SAVE and RUN it.
The program reads the analog input and maps it to numbers between 17 and 32. It uses the display buffer array @D() of BASIC. Writing to this array modifies the display buffer directly and immediately displays the character. The ASCII value 255 used in the example is a filled box in LCD displays. The first loop displays filled boxes and the second loop clears all the remaining fields of the second line of the display. The display arrays is read/write. If can be used to check what was written to the display.
Build a Small ClockThe last example in this tutorial uses a real time clock module. These modules are mostly based on the DS1307, DS3231, or DS3232 chips.
BASIC supports all three modules without the help of an additional library if the RTC language feature is compiled in.
For this open hardware.h once more, set the feature
#define ARDUINORTC
right bellow the predefined boards line, then compile and upload to the ARDUINO.
Connect the respective pins of the clock to GND and 5V. Connect the SDA pin of the clock to A4 and the SCL pin to A5 of the Arduino.
To check the clock function, on the command line type
@T(0)=1
PRINT @t$
A string of the form
00:00:01-1/1/22
should be displayed. Checking the string multiple times with the PRINT command should show the seconds increasing. Check the wiring if this doesn't work.
The clock can be accessed in two ways. The array elements 0-6 of the array @T() contains the seconds, minutes, hours, day of week, day, month, and year. All array elements can be read and written. To start some of the clocks (DS1307 models) they have to be set once with the command @T(0)=1 to run. You can set it to any time, but the second field has to be written at least once.
The clock can also be accessed with the string @T$. It contains date and time in one line. This string is read only.
Please type in the following program
10 CLS
100 @X=0: @Y=0
110 PRINT &2,@T$(1,8)
120 PRINT &2,@T$(10,17);
130 DELAY 500
150 GOTO 100
then SAVE it and RUN it.
The output shows the time in the first line and the date in the second line.
With 6 lines of code a working clock has been build. Typing SET 1, 1 on the command line switches on the autorun feature. The clock will start running as soon as it is connected to power.
The CounterSmall displays are ideal to count events. One use case I am proud of the the refrigerator counter. I used this device during lock-down in the pandemic to keep track of how often I would go to my refrigerator to get a snack. After gaining several kilos of weight in the first 3 month of home office, this seemed like a good idea.
For this application you need a standard PIR counter. These devices have a power and a ground connector plus one digital output. The output goes to HIGH if someone approached the sensor. Two potentiometers control sensitivity and duration of the alert. I set them both to minimum as the device was close to my refrigerator and I never spend much time there.
Connect the PIR sensor to analog PIN A1 then type in the snack counter program
10 CLS
20 PRINT &2,"Snacks: ";
30 PINM 15,0
40 S=0
100 @X=8: @Y=0
110 PRINT &2,N;
120 T=DREAD(15)
130 IF T=1 THEN @D(17)="X" ELSE @D(17)="0"
140 IF T=S THEN DELAY 500: GOTO 100
150 IF S=0 AND T=1 THEN N=N+1
160 S=T
170 GOTO 100
SAVE it and type RUN. The display shows the number of events. A small X or = in the lower left corner of the display shows if the sensor has fired.
The program is a standard state engine. S contains the previous state of the program. If the state has changed from LOW to HIGH, the variable N is increased by one and the new state is recorded.
The Tiny VT52 TerminalBASIC has a built-in VT52 terminal. Most of the display operations shown in the examples above can also be done via a serial line.
To use the terminal, type in the program
10 CLS
100 GET A
110 IF A<>0 THEN PUT &2,A
120 GET &2, A
140 IF A<>0 THEN PUT A
150 GOTO 100
SAVE it and then type SET 1, 1 to activate autorun. Restart the Arduino. You have now a serial VT52 compatible terminal listening to the Arduino's RX pin with 9600 baud speed and transmitting the key inputs on the keypad on the TX pin.
The program reads data with GET from the serial input and if data is received, PUT &2 writes it to the display stream. Then it checks for keypad input with GET&2 and writes this to the serial stream.
If you have a second Arduino at hand, you can try this out. Upload the BASIC interpreter on it, then connect the second devices TX pin to the RX pin of the display device and also connect GND of both devices.
If you start sending commands you will see them on the display.
Input the program
10 PUT 27,"E"
20 PRINT "Arduino Terminal";
100 PUT 27,"Y",32,31
110 PRINT I;
120 I=I+1
130 DELAY 3000
140 GOTO 100
to the second device and type RUN. The output of the second device will now show on the display. Line 10 and 100 are PUT commands that send VT52 escape sequences to the terminal. The first one clears the screen and the second one positions the cursor to the beginning of the second line.
Most standard VT52 commands and GEMDOS extensions described in the Wikipedia article on these terminals are implemented now.
I will write another tutorial on how to build VT52 like terminals soon. It will deal with bigger displays and on how to use VT52 codes for display control. Until then, enjoy BASIC on Arduinos.
Comments
Please log in or sign up to comment.