Back in the summer, I posted some musings about a very small programming language that I named SIMPL - Serial Interpreted Micro Programming Language. It's an extended version of Ward Cunningham's Txtztme, described as a Nano Interpreter - which is documented here.
Well over the period of the Christmas break, I have had the opportunity to port SIMPL, which is written in fairly standard C, across to the STM32F4 ARM Discovery board. It is now working to the point where I can program simple I/O operations and loops on the Discovery board.
SIMPL is fast on the STM32F4x you can create a pulse as short as 200nS, or toggle a pin on and off at 372kHz. By comparison on the Arduino (using digitalWrite) the pulse time is 10uS and 47.8kHz maximum frequency, though better could be achieved by direct port manipulation.
Ward Cunningham has ported txtzyme to the Teensy board, as a means of controlling hardware over a USB connection, and from a remote server. Ward is using txtzyme to control hardware remotely as part of his Federated Wiki project. A video explaining the project with some demos is here, and well worth a watch for some interesting background.
I've chosen to follow a slightly different route to Ward's project, to use SIMPL more as a programming language, but as the txtzyme interpreter is common to both the Teensy and my ARM implementation, then either hardware can interpret txtzyme strings.
Although SIMPL started off life on an Arduino, it seemed a natural choice to port over to the ARM Discovery board. The additional RAM and program space allow far more elaborate programs to be written, and as the ARM runs at 10 times the clock speed of the Arduino Uno, - the code is blistering quick.
You might recall that SIMPL is based on an interpreter, which interprets serial character strings and decodes them into functions which are executed in turn.
SIMPL generally uses a mix of small characters and punctuation marks as the primitive command set, and then a capital letter can be used in a similar way to a Forth word, to execute a sequence of commands.
Small characters, maths symbols and punctuation marks are used as the primitives. When encountered by the interpreter, they are used to call a function directly, such as p to print a character, or h to set a port line high. The maths symbols are used, obviously to allow maths operations to be executes, such as + - * / and tests such as < and >. The overall simplicity of using a single ascii character as a command, means that the entire interpreter can be coded as a simple switch-case statement in C. For example when h is encountered:
case 'h': // set bit high
digitalWrite(x, HIGH);
break;
Where the interpreter encounters a number character 0 to 9, these are scanned in, and accumulated into variable x with the correct decimal place shift, for as long as the next character in the buffer is a number. The following few lines of C perform this number interpretation
x = ch - '0';
while (*buf >= '0' && *buf <= '9') {
x = x*10 + (*buf++ - '0');
}
Punctuation marks are used to help program flow. For example the open and close brace structure defines a portion of code to be repeated as in a loop. Suppose we want to loop some code 10 times, for example print 10 Green Bottles. The Green Bottles will be printed if it is written thus _Green Bottles_ and the loop structure uses a loop index k, which is decremented each time around the loop. kp will print the current value of k, each time decrementing.
10{kp_Green Bottles_}
Unfortunately p also introduces a newline character, so the output is not quite as desired :-(
Words
In this interpretation scheme, I have reserved the upper case letters to represent "words" - in the Forth sense. In order to maintain the same simplicity in the interpreter, single characters are decoded as calls to the code stored in the word definition. This may sound confusing, so to illustrate with an example.
Suppose I liked the "Green Bottles" code so much, that I wanted to preserve it and use it again, and again. Well I can do this by making it into the form of a colon definition (again borrowed from Forth), such that I can assign it to a memorable word, say B for bottles.
The colon : tells the interpreter that the next character will be a word, followed by the code that will be executed when the word is called
:B 10{kp_Green Bottles_}
This will place the code 10{kp_Green Bottles_} at a location in memory that can be accessed everytime that the interpreter sees the letter B. Instead of interpreting the contents of the keyboard buffer, the interpreter is now pointed to a word buffer, containing the code body that makes up B.
This process can be extended by adding together words to make new words
:A 10{B}
This defines A as ten iterations of B, or about 100 Green Bottles!
The word definitions are stored in a RAM array, and the ? command can be used as a means of listing all the current word definitions.
SIMPL is now starting to take the form of a very concise language. It can handle numbers, character commands from the terminal and perform simple maths. It can perform loops and output numbers and text to the terminal. The next thing is to allow it to access the peripherals and I/O.
SIMPL has been developed to be "close to the hardware". As almost all microcontrollers have a mix of on chip peripherals, such as timers, ADCs, DACs and general purpose I/O, SIMPL has primitive commands designed to exercise this hardware directly.
For example, suppose you have an output port on Port D13 controlling a LED, then the command 13h will turn the LED on and 13l will turn it off, h and l being the commands to set the named port 13, either high or low.
For analogue input from an ADC channel, the command s for "sample" is used. So to read the ADC channel 10 and print to the terminal, we enter 10sp.
Commands can be repeated within loops using the { } loop structure.
To read the ADC channel 10, ten times and print the result to the terminal, we use:
10{10sp}
or to slow this down to once a second, we can delay with the millisecond delay m command which puts a 1000mS pause in the loop.
10{10sp1000m}
We can now put a few of these commands together so as to flash the LED for 100mS each time we take an ADC reading
10{10sp900m13h100m13l}
Note that we are still looping 10 times,
reading ADC channel 10 and printing it out,
pausing for 900mS,
setting LED 13 high,
pausing for 100mS,
setting the LED low,
returning to the start of the loop.
So it's quite easy to build up complex commands, just by concatenating a few primitives together.
What if you were to write this in C? It would be somewhat longer, about 8 to 10 lines of code, and then need to be compiled, tested, and if you weren't happy, edited and compiled again. SIMPL breaks us out of the edit, compile, test cycle, and allows ideas to be tested quickly and easily, straight from the terminal.
This was exactly what Forth language pioneer, Charles Moore realised in the mid-1960s. He too wanted to break free from the edit-compile-test cycle, in order to improve his efficiency in coding, as computer time was expensive back then, and also to make himself no longer reliant on compilers and assemblers that he had no control over. He wanted to develop a self-written, self-contained programming environment that could easily be moved from one system to another, and require few and simple resources to get it running.
If you are interested in the early history of Forth, Charles "Chuck" Moore describes the early development of the language here:
History of Forth
Whilst SIMPL is not Forth, and never will be, there are several nice techniques borrowed from Forth, which are used to enhance SIMPL.
We have come a long way since the early development of the computer languages, such as C and Forth, which were often hosted on very primitive machines, with limited RAM and tiny disks by today's standards.
One early machine, the PDP-8, was of a simple enough architecture, that it has often formed the basis of study in computer science courses. Additionally, the PDP-8 has been implemented in many different technologies over the years, including TTL, VLSI and as a FPGA implemented in Verilog or VHDL.
The reason for interest in the PDP-8, is that whist primitive by machine standards now, it represented a revolution in architecture simplification, such that the whole system could be sold for $18,000 back in 1965. It was the first of the true minicomputers, available at a tenth of the cost of competing systems.
Additionally, the PDP-8, is comparable in resources to those that we find on a low cost microcontroller, costing a few dollars. So the practices used in the 1960s to write code for the early minicomputers has significant relevance these days.
Whilst generally we use open source C compilers, such as GCC, and integrated design environments (IDEs) to develop programs, there is no reason why a simple interpreted language, running in the background would not make sense, when developing applications on a new microcontroller. It puts the control of the hardware, directly at your fingertips and allows quick experimentation.
Modern 32 bit microcontrollers, such as the ARM range of cores, are now rapidly replacing 8-bit devices in a range of applications, at very little additional extra cost. The resources and peripherals available on a typical ARM device, are vast compared to 8-bit processors, and with clock speeds roughly ten times faster, a huge amount of processing power is available, compared to only a few years ago.
With clock speeds in the 100-200MHz range, it's now perfectly possible to host an interpreted language on the microcontroller, and have it run at speeds only previously available through the compiled language route.
SIMPL consists of an interpreter running within a loop. The interpreter is written in about 300 lines of standard C, and additionally includes several I/O and memory functions, which are tailored to the particular microcontroller, to create a standardised machine model.
To the Arduino user, these I/O routines will be familiar:
digitaRead Read the state of a digital input
digitalWrite Write a digital output high or low
analogRead Read the value of an ADC channel
analogWrite Write a value to an analogue PWM or DAC channel
delayMilliseconds generate a delay in mS
delayMicroseconds generate a delay in uS
printNum print an integer number to the terminal
putChar print an ASCII character to the terminal
getChar read an ASCII character from the keyboard or terminal input buffer
All microcontrollers for embedded applications should have the hardware means to execute these routines, and although setting up the I/O and peripherals may take a bit of time on an unfamiliar hardware device, once done the basic routines will be used frequently in any application that may be developed.
delayMilliseconds can simply be derived from 1000 times around the delayMicroseconds loop, or can be derived from a hardware timer, depending on the device.
Whilst putChar would normally send a character to the UART transmit buffer, it might instead be used to bit-bang an output pin, if no UART is available. Fortunately most microcontrollers have one or more UARTs available these days, so bit-banged serial comms is less of a requirement.
printNum is just a convenient means of getting integer numerical output from the microcontroller. It will use the C routine "integer to ASCII" and putChar to send an integer to the terminal.
getChar is intended to read in a character at a time either directly from the keyboard or from the terminal input buffer.
With these routines, you can now interface to a serial terminal, read and write to I/O lines, read analogue inputs and control PWM or DAC outputs. With the ability to specify accurate delays to give a sense of timing to the program flow, there is little else that the micro needs to do, except perhaps for memory operations.
Thanks for the Memory
In bygone days, when microcontrollers had very little memory, it was easy to get obsessed about the placement of code and data within memory. Memory was a precious commodity, and it was necessary to squeeze your program and your data into what little memory was available. Every byte was precious, so clever tricks were devised to pack data into as few bytes as possible.
These days, this is not so much of a problem. The STM32F407 has a 1Mbyte flash for program and storage of constant data, and 196Kbytes of SRAM, 4Kbytes of which can be battery backed and made non-volatile. Other STM32F4xx family members have 2Mbyte of flash and 256Kbytes of SRAM. This might not seem much by PC standards, but for an embedded application it is more than plenty.
To be continued.
---------------Getting along in the 21st Century with half the baggage you carried in the last.------------ /*************************Low cost electronic solutions for a low impact lifestyle.************************/
Saturday, December 28, 2013
Friday, December 27, 2013
Discovering the STM32F407 - first steps into ARM territory
Having tinkered with the Arduino and it's clones for a few years, the opportunity arose to move up to a much more powerful 32-bit ARM Cortex M4 device, which is now available cheaply.
The ARM is a somewhat more complex device than the humble 8-bit Atmel AVR so it took a little while to get things up and running to the point where I could do useful development work with it. I hope that this blog post will be a help to anyone else considering such a move.
If you read some of the historical documents describing the development of computer languages in the 1960s and early 1970s, there is a common underlying theme - the desire of the computer pioneers to make things quicker and easier and create a more comfortable programming environment.
Ken Thompson, who wrote 'B', the precursor of C had a very limited DEC PDP-7 at his disposal, and according to Dennis Ritchie in the 2003 C History paper "Thompson wanted to create a comfortable computing environment constructed according to his own design, using whatever means were available."
Similarly, Charles Moore, creator of the Forth programming language, describes in his Forth history, how he continually strove to make things simpler, so he could focus on the application and not get bogged down in the primitive tool set.
So, in true tradition, when encountering a 32-bit ARM microcontroller for the first time, I wanted to get things quickly up and running and get it within my comfort zone, and treat it like any 8 bit or 16 bit mcu, such as the AVR.
ST Microelectronics have licensed ARM cores for several years, and have encouraged newcomers to their product by way of very low cost development boards. The STM32F4 Discovery board, which is a target for the ARM Cortex M4 microcontroller is available for as little as £10, or $15 in the US.
If you have come from an Arduino background, here is a low cost board, bristling with 80 I/O lines, an accelerometer, an audio codec and a built-in programmer/debugger which runs at 168MHz. Compared to the Arduino it runs at 10.5 times the speed, has 32 times the Flash and 98 times the SRAM, all for less than the cost of a Uno.
All those I/O lines take a little getting used to, as many of them are shared between the various on-chip peripherals, and you need to do a little bit of configuration work to make sure you have access to the mix of peripheral functions needed by your application.
One approach is to arrange the I/O and peripherals into a familiar format - and it is not unsurprising that the peripherals are a good match to the Arduino resources. In one configuration we can get:
4 USART Serial ports
3 SPI interfaces
12 ADC Inputs
2 DAC Outputs
2 I2C interfaces
12 PWM channels
2 Quadrature encoder channels
Numerous digital I/O
So in terms of I/O resources, the Discovery is a good approximation to the Arduino Mega, or Due but with a good speed and memory advantage.
The downside for newcomers, is that it does not come with the Arduino IDE, but this is not altogether a bad thing, because it encourages you to broaden your horizons and finally cut the Arduino apron strings.
All of the tools needed to program and debug the Discovery board are available open source, and very quickly you can be programming your application code. However, it's always good to take a few old friends along on any voyage of discovery, so here's how to get the basics up and running for the newcomer.
First you should install the IDE from CooCox. You can download their CoIDE from here
Additionally you will need to install the GCC toolchain - which is accessible from the CoIDE page.
The Discovery board has it's own on-board programmer/debugger known as the STLink. You will also need to download the driver for this - again available from the CoIDE page.
There is now a rapid increasing number of user examples of Discovery code. A quick search will bring up several good resources e.g.
https://github.com/k-code/stm32f4-examples
Lastly, ST Microelectronics have released a standard peripherals library, and a good range of examples and application notes to support their dev kit. You might want to look through their examples here
The standard procedure for getting any microcontroller up and running, is to initialise a UART, and as a bare minimum provide the means to get serial input and output. Once this is achieved, debugging becomes a whole lot easier, and as likely as not, the final application will need serial communications - so it's not wasted effort.
The STM32F407 on the Discovery board is provided with up to six UARTS of which 4 are USARTS - meaning that they can handle both synchronous (clocked) and unsynchronous serial comms. Whichever USART is chosen, there is a certain amount of initialisation code to be executed first, and then some relatively simple code to handle character input and output.
Once the UART is up and running, you have the means to send numerical debug information to a serial terminal, and to control programs using simple serial commands.
One method I have used many times is a simple serial command interpreter based on a switch/case statement. It uses an alpha command and a numerical argument. For example, in a motor drive application, the serial command F100 could be entered to make the motor run forwards at 100rpm, and R100 would reverse it at 100rpm. These simple serial commands are easy to implement and a quick way of proving that your hardware and the various driver routines are working. Each new project I have worked on for the last few years has had some variant of this serial command interpreter programmed in as a prerequisite.
The other on chip peripherals are initialised using a similar set of functions. Most importantly is to remember to enable the clock to both the GPIO port you are using AND the peripheral you wish to use. Failure to do this is a common cause for non working peripherals.
The main.c routine posted up to Github Gist enables a number of peripherals:
USART1 and USART 2 for serial communication with a host computer.
ADC1, six 12 bit ADC channels enabled
Timer 2 and Timer 5 for 32 bit pulse counting (quadrature encoder) applications
Timer 1 for three complementary PWM channels for motor drive etc
Timer 3 is used to generate three independent PWM signals
Timer 4 is set up as a milliseconds tick timer
GPIO D is set up to have four general purpose outputs, used to drive the on board LEDs.
Further initialisation routines will follow to allow the SPI and I2C interfaces to be accessed, for SDcard and EEPROM devices. This will be covered in a later post.
The ARM is a somewhat more complex device than the humble 8-bit Atmel AVR so it took a little while to get things up and running to the point where I could do useful development work with it. I hope that this blog post will be a help to anyone else considering such a move.
If you read some of the historical documents describing the development of computer languages in the 1960s and early 1970s, there is a common underlying theme - the desire of the computer pioneers to make things quicker and easier and create a more comfortable programming environment.
Ken Thompson, who wrote 'B', the precursor of C had a very limited DEC PDP-7 at his disposal, and according to Dennis Ritchie in the 2003 C History paper "Thompson wanted to create a comfortable computing environment constructed according to his own design, using whatever means were available."
Similarly, Charles Moore, creator of the Forth programming language, describes in his Forth history, how he continually strove to make things simpler, so he could focus on the application and not get bogged down in the primitive tool set.
So, in true tradition, when encountering a 32-bit ARM microcontroller for the first time, I wanted to get things quickly up and running and get it within my comfort zone, and treat it like any 8 bit or 16 bit mcu, such as the AVR.
ST Microelectronics have licensed ARM cores for several years, and have encouraged newcomers to their product by way of very low cost development boards. The STM32F4 Discovery board, which is a target for the ARM Cortex M4 microcontroller is available for as little as £10, or $15 in the US.
If you have come from an Arduino background, here is a low cost board, bristling with 80 I/O lines, an accelerometer, an audio codec and a built-in programmer/debugger which runs at 168MHz. Compared to the Arduino it runs at 10.5 times the speed, has 32 times the Flash and 98 times the SRAM, all for less than the cost of a Uno.
All those I/O lines take a little getting used to, as many of them are shared between the various on-chip peripherals, and you need to do a little bit of configuration work to make sure you have access to the mix of peripheral functions needed by your application.
One approach is to arrange the I/O and peripherals into a familiar format - and it is not unsurprising that the peripherals are a good match to the Arduino resources. In one configuration we can get:
4 USART Serial ports
3 SPI interfaces
12 ADC Inputs
2 DAC Outputs
2 I2C interfaces
12 PWM channels
2 Quadrature encoder channels
Numerous digital I/O
So in terms of I/O resources, the Discovery is a good approximation to the Arduino Mega, or Due but with a good speed and memory advantage.
The downside for newcomers, is that it does not come with the Arduino IDE, but this is not altogether a bad thing, because it encourages you to broaden your horizons and finally cut the Arduino apron strings.
All of the tools needed to program and debug the Discovery board are available open source, and very quickly you can be programming your application code. However, it's always good to take a few old friends along on any voyage of discovery, so here's how to get the basics up and running for the newcomer.
First you should install the IDE from CooCox. You can download their CoIDE from here
Additionally you will need to install the GCC toolchain - which is accessible from the CoIDE page.
The Discovery board has it's own on-board programmer/debugger known as the STLink. You will also need to download the driver for this - again available from the CoIDE page.
There is now a rapid increasing number of user examples of Discovery code. A quick search will bring up several good resources e.g.
https://github.com/k-code/stm32f4-examples
Lastly, ST Microelectronics have released a standard peripherals library, and a good range of examples and application notes to support their dev kit. You might want to look through their examples here
The standard procedure for getting any microcontroller up and running, is to initialise a UART, and as a bare minimum provide the means to get serial input and output. Once this is achieved, debugging becomes a whole lot easier, and as likely as not, the final application will need serial communications - so it's not wasted effort.
The STM32F407 on the Discovery board is provided with up to six UARTS of which 4 are USARTS - meaning that they can handle both synchronous (clocked) and unsynchronous serial comms. Whichever USART is chosen, there is a certain amount of initialisation code to be executed first, and then some relatively simple code to handle character input and output.
Once the UART is up and running, you have the means to send numerical debug information to a serial terminal, and to control programs using simple serial commands.
One method I have used many times is a simple serial command interpreter based on a switch/case statement. It uses an alpha command and a numerical argument. For example, in a motor drive application, the serial command F100 could be entered to make the motor run forwards at 100rpm, and R100 would reverse it at 100rpm. These simple serial commands are easy to implement and a quick way of proving that your hardware and the various driver routines are working. Each new project I have worked on for the last few years has had some variant of this serial command interpreter programmed in as a prerequisite.
The other on chip peripherals are initialised using a similar set of functions. Most importantly is to remember to enable the clock to both the GPIO port you are using AND the peripheral you wish to use. Failure to do this is a common cause for non working peripherals.
The main.c routine posted up to Github Gist enables a number of peripherals:
USART1 and USART 2 for serial communication with a host computer.
ADC1, six 12 bit ADC channels enabled
Timer 2 and Timer 5 for 32 bit pulse counting (quadrature encoder) applications
Timer 1 for three complementary PWM channels for motor drive etc
Timer 3 is used to generate three independent PWM signals
Timer 4 is set up as a milliseconds tick timer
GPIO D is set up to have four general purpose outputs, used to drive the on board LEDs.
Further initialisation routines will follow to allow the SPI and I2C interfaces to be accessed, for SDcard and EEPROM devices. This will be covered in a later post.
Sunday, June 02, 2013
Extensions to SIMPL
In the last week I have been thinking about the user interfaces used on minicomputers of the 1960s, in particular the PDP-8, and wondering if a similar front LED and switch panel could be created cheaply as a nostalgic retro accessory shield for the Arduino.
I have added some LEDs to the 12 available digital I/O pins of the Arduino, so that I can recreate LED chaser and "vintage computer" style displays.
I've extended the SIMPL command set so that I can more easily address each LED in turn, or alternatively treat all twelve as a binary numerical display, to display address or data numbers in the range 0 to 4096.
The latest version of SIMPL can be found here on Github Gist:
https://gist.github.com/anonymous/facc9a262c0778aec7b6
Just download the Gist and compile it as an Arduino sketch. You can then start typing SIMPL commands using the serial monitor window at 115200 baud. Make sure that you have selected the "Both NL and CR" option for the serial monitor.
Output Commands
In order to gain more immediate access to the I/O, I have added some new commands:
a - sends an analog.Write value to a pin previously named with d
b - prints out the current value of the milliseconds counter, allowing loop timing to be calculated
c - prints out the current value of the microseconds counter
h - sets a digital pin high eg 6h
l - sets a digital pin low eg 13l
n - decodes a number up to 4095 and displays it on digital pins 2 to 13 eg 1234n
n can be thought of as a very simple binary display. It has a fast response time and allows the user a simple visible means of checking that a program is executing.
The n command can be useful to examine the characters stored in RAM. Here it is used to output 1000 characters to the LEDs, starting at RAM address 256. The characters are sent every 100mS and also printed to the terminal.
255!1000{y@rn100m}
255! Store 255in y as the starting RAM address
1000{ Perform the loop 1000 times
y Increment y each time around the loop
@ Move y into x
r read the contents of RAM into x
n Send the value to the LED display
100m 100mS delay to slow things down to a sensible speed
} End of the loop
Decision Making
SIMPL currently lacks the if, then, else decision making, or the switch case structure. This would be a useful addition and I am currently working on some ways of implementing it.
It might be possible to test the x value against certain constants and then execute one of the upper case routines if the test was equal.
Other SIMPL Commands
SIMPL instructions are a mix of lower case ASCII characters, symbols and punctuation marks. These are the primitives, which are interpreted in sequential order by a simple interpreter. The interpreter is an extension of Ward Cunningham's Txtzyme interpreter, which recognises the following:
a Send an analog write (PWM) value to a pin
b print out the current milliseconds count
c print out the current microseconds count
d define a digital port pin
e
f
g
h set pin high
i read an input
j skip next instruction
k access the loop counter
l set pin low
m define a delay in milliseconds
n display a number on a line of LEDs
o set an output
p print the x variable to the terminal
q query a block of RAM locations ( as character)
r read from RAM
s read an analogue input
t
u define a delay in microseconds
v
w write to RAM
x increment x
y increment y (as used in incrementing loop structures)
{} loop the code contained within the braces
@ copy y to x
! store x in y
? Dump the contents of RAM to show the existing words
+
-
*
/
<
>
Numbers can be typed in the range 0 to 65535 and are stored in the x variable and used to control the above instructions.
eg. 6d define digital port pin 6
100m define a delay of 100mS
10{....} go around a loop 10 times
20p Print 20 to the terminal
To these basic instructions I added a y variable, so that I could do simple maths. You can store a number in y by using the store symbol !
20! Stores the value of 20 into y (by transferring it from x)
To get the contents of y back, we use the fetch symbol @
20!@p Prints the value of 20 from y
We can do simple addition, subtraction, multiplication and division on x and y
20!5+p Adds 20 to 5 and prints result (x=x+y)
5!30-p Subtracts 5 from 30 and prints result (x=x-y)
16!8*p Multiplies 8 by 16 and prints result (x = x*y)
6!30/p Divides 30 by 6 and prints result (x=x/y)
Downloading the SIMPL sketch from Github Gist and programming it into a standard Arduino is the first step to discovering a new way to control physical computing devices.
I have added some LEDs to the 12 available digital I/O pins of the Arduino, so that I can recreate LED chaser and "vintage computer" style displays.
I've extended the SIMPL command set so that I can more easily address each LED in turn, or alternatively treat all twelve as a binary numerical display, to display address or data numbers in the range 0 to 4096.
The latest version of SIMPL can be found here on Github Gist:
https://gist.github.com/anonymous/facc9a262c0778aec7b6
Just download the Gist and compile it as an Arduino sketch. You can then start typing SIMPL commands using the serial monitor window at 115200 baud. Make sure that you have selected the "Both NL and CR" option for the serial monitor.
Output Commands
In order to gain more immediate access to the I/O, I have added some new commands:
a - sends an analog.Write value to a pin previously named with d
b - prints out the current value of the milliseconds counter, allowing loop timing to be calculated
c - prints out the current value of the microseconds counter
h - sets a digital pin high eg 6h
l - sets a digital pin low eg 13l
n - decodes a number up to 4095 and displays it on digital pins 2 to 13 eg 1234n
n can be thought of as a very simple binary display. It has a fast response time and allows the user a simple visible means of checking that a program is executing.
The n command can be useful to examine the characters stored in RAM. Here it is used to output 1000 characters to the LEDs, starting at RAM address 256. The characters are sent every 100mS and also printed to the terminal.
255!1000{y@rn100m}
255! Store 255in y as the starting RAM address
1000{ Perform the loop 1000 times
y Increment y each time around the loop
@ Move y into x
r read the contents of RAM into x
n Send the value to the LED display
100m 100mS delay to slow things down to a sensible speed
} End of the loop
Decision Making
SIMPL currently lacks the if, then, else decision making, or the switch case structure. This would be a useful addition and I am currently working on some ways of implementing it.
It might be possible to test the x value against certain constants and then execute one of the upper case routines if the test was equal.
Other SIMPL Commands
SIMPL instructions are a mix of lower case ASCII characters, symbols and punctuation marks. These are the primitives, which are interpreted in sequential order by a simple interpreter. The interpreter is an extension of Ward Cunningham's Txtzyme interpreter, which recognises the following:
a Send an analog write (PWM) value to a pin
b print out the current milliseconds count
c print out the current microseconds count
d define a digital port pin
e
f
g
h set pin high
i read an input
j skip next instruction
k access the loop counter
l set pin low
m define a delay in milliseconds
n display a number on a line of LEDs
o set an output
p print the x variable to the terminal
q query a block of RAM locations ( as character)
r read from RAM
s read an analogue input
t
u define a delay in microseconds
v
w write to RAM
x increment x
y increment y (as used in incrementing loop structures)
{} loop the code contained within the braces
@ copy y to x
! store x in y
? Dump the contents of RAM to show the existing words
+
-
*
/
<
>
Numbers can be typed in the range 0 to 65535 and are stored in the x variable and used to control the above instructions.
eg. 6d define digital port pin 6
100m define a delay of 100mS
10{....} go around a loop 10 times
20p Print 20 to the terminal
To these basic instructions I added a y variable, so that I could do simple maths. You can store a number in y by using the store symbol !
20! Stores the value of 20 into y (by transferring it from x)
To get the contents of y back, we use the fetch symbol @
20!@p Prints the value of 20 from y
We can do simple addition, subtraction, multiplication and division on x and y
20!5+p Adds 20 to 5 and prints result (x=x+y)
5!30-p Subtracts 5 from 30 and prints result (x=x-y)
16!8*p Multiplies 8 by 16 and prints result (x = x*y)
6!30/p Divides 30 by 6 and prints result (x=x/y)
Downloading the SIMPL sketch from Github Gist and programming it into a standard Arduino is the first step to discovering a new way to control physical computing devices.
Saturday, June 01, 2013
Extending SIMPL and flashing a few LEDs
I have been experimenting with SIMPL, and have added a few new commands to give it greater functionality.
I've wired Digital outputs 2 to 13 to a line of 12 LEDs, to give a very simple means of displaying numerical values. It also allows LED chaser displays to be tinkered with.
I have added a command to allow the analogWrite function to control an output pin.
Name the pin first, e.g. 6d and then the PWM value such as 127a This sets the PWM to about 50% duty cycle.
I've also been investigating how fast the commands run, so added a couple of timing commands b and c. b prints the current value of the millisecond counter millis(), so typing b before and after a list of instructions will allow you to calculate how many milliseconds it took to execute. c does the same, but uses the microseconds counter micros().
By timing 10000 cycles of a loop, I can show that SIMPL will add two 16 bit integers in about 6 microseconds.
I have added some commands for easier control of the I/O. h and l are now used to set a port pin high or low eg. typing 6h and 5l will immediately set those pins high and low.
After my experiments with LED chaser displays, I also wanted a way to immediately write an 8 bit number to 8 consecutive LEDS. So the "n" command displays a number on a row of LEDs.
Typing 255n will turn all the LEDs on Digital 2 to Digital 9.
To make incrementing loops easier, the command "x" now increments x and "y" increments y.
0!10{y@p}
This prints out the numbers from 1 to 10. 0! sets y to zero, y increments the y variable.
The q, r and w commands have been used to access the RAM.
300r will print the character stored at address 300.
SIMPL instructions are a mix of lower case ASCII characters, symbols and punctuation marks. These are the primitives, which are interpreted in sequential order by a simple interpreter. The interpreter is an extension of Ward Cunningham's Txtzyme interpreter. SIMPL now recognises the following lower case instructions:
a Send an analog write (PWM) value to a pin
b print out the current milliseconds count
c print out the current microseconds count
d define a digital port pin
e
f
g
h set pin high
i read an input
j skip next instruction
k access the loop counter
l set pin low
m define a delay in milliseconds
n display a number on a line of LEDs
o set an output
p print the x variable to the terminal
q query a block of RAM locations ( as character)
r read from RAM
s read an analogue input
t
u define a delay in microseconds
v
w write to RAM
x increment x
y increment y (as used in loop structures)
{} loop the code contained within the braces
@ copy y to x
! store x in y
? Dump the contents of RAM to show the existing words
+ Add x and y
- Subtract x and y
* Multiply x and y
/ Divide x and y
< Is y < x
> Is y > x
I've wired Digital outputs 2 to 13 to a line of 12 LEDs, to give a very simple means of displaying numerical values. It also allows LED chaser displays to be tinkered with.
I have added a command to allow the analogWrite function to control an output pin.
Name the pin first, e.g. 6d and then the PWM value such as 127a This sets the PWM to about 50% duty cycle.
I've also been investigating how fast the commands run, so added a couple of timing commands b and c. b prints the current value of the millisecond counter millis(), so typing b before and after a list of instructions will allow you to calculate how many milliseconds it took to execute. c does the same, but uses the microseconds counter micros().
By timing 10000 cycles of a loop, I can show that SIMPL will add two 16 bit integers in about 6 microseconds.
I have added some commands for easier control of the I/O. h and l are now used to set a port pin high or low eg. typing 6h and 5l will immediately set those pins high and low.
After my experiments with LED chaser displays, I also wanted a way to immediately write an 8 bit number to 8 consecutive LEDS. So the "n" command displays a number on a row of LEDs.
Typing 255n will turn all the LEDs on Digital 2 to Digital 9.
To make incrementing loops easier, the command "x" now increments x and "y" increments y.
0!10{y@p}
This prints out the numbers from 1 to 10. 0! sets y to zero, y increments the y variable.
The q, r and w commands have been used to access the RAM.
300r will print the character stored at address 300.
SIMPL instructions are a mix of lower case ASCII characters, symbols and punctuation marks. These are the primitives, which are interpreted in sequential order by a simple interpreter. The interpreter is an extension of Ward Cunningham's Txtzyme interpreter. SIMPL now recognises the following lower case instructions:
a Send an analog write (PWM) value to a pin
b print out the current milliseconds count
c print out the current microseconds count
d define a digital port pin
e
f
g
h set pin high
i read an input
j skip next instruction
k access the loop counter
l set pin low
m define a delay in milliseconds
n display a number on a line of LEDs
o set an output
p print the x variable to the terminal
q query a block of RAM locations ( as character)
r read from RAM
s read an analogue input
t
u define a delay in microseconds
v
w write to RAM
x increment x
y increment y (as used in loop structures)
{} loop the code contained within the braces
@ copy y to x
! store x in y
? Dump the contents of RAM to show the existing words
+ Add x and y
- Subtract x and y
* Multiply x and y
/ Divide x and y
< Is y < x
> Is y > x
A Little Nostalgia
In the decade that spanned the 1960s, the cost of computers fell by about two orders of magnitude, and with volume manufacture possible, they found their way into general scientific engineering and industrial use.
One area of science that particularly benefited from more widely available computing power, was that of biomedical research. Two computer designs, in particular, spurred on this advancement, the LINC of 1962, and the PDP-8 of 1965.
About 50 LINC machines were built, and a few survive today. This video shows a restored LINC in use.
http://www.youtube.com/watch?v=atJUnQN65dE
These were the first "benchtop" designs, and set the trend in design for the machines that were to be known as minicomputers. In 1965 the PDP-8 cost $18,000, still a huge amount of money, but cheap enough to be built in volume and satisfy the needs of university laboratories.
Both the LINC and the PDP-8, owed their design to the general purpose digital modules, that were manufactured by DEC from the late 1950s onwards. Each machine was a pared down 12 bit design, cost engineered for efficiency at every level, offering a machine capable of real work for a modest price.
Over the next 20 years, the PDP-8 architecture was to be revisited many times, as advancements in logic ICs and memory allowed significant cost savings to be made. The original PDP-8 was the size of a small fridge, within 10 years it was housed in a single 19" rack. The very last PDP-8 machines used a microprocessor (Intersil/Harris 6120) to implement the CPU.
By the mid 1970s, microprocessors were starting to appear, which led to the era of 8-bit microcomputers. Some of these, such as the MITS Altair 8800 paid homage to the style of the PDP-8 with a front panel of many LEDs and programming switches. The simple LED indicators allowed the user to see precisely what the registers were holding, and the switches allowed simple programs to be "toggled" directly into memory.
These machines are now approaching 50 year old , yet there are many enthusiasts who started their scientific or engineering careers programming such computers. The National Museum of Computing at Bletchley Park owns an early PDP-8, which they have restored to working order. They have made a series of short videos depicting its operation.
Here's how a short program is loaded into the machine from the front panel switches.
http://www.youtube.com/watch?v=DPioENtAHuY
Notice how much noise was present in a typical computer room. Fans, printers and teletypes produces a near constant din.
The machines were relatively slow and simple by today's comparison, capable of some 300,000 instructions per second. Nevertheless, they were capable of real work, despite their limitations in speed and memory.
In the mid 1960s, the standard user interface was a teletype printer with paper tape punch and reader. Programs would be loaded into the memory from paper tape, but often only after a simple tape loader had been manually toggled into the machine from the front panel switches.
The second of the NMOC videos shows how program on the the paper tape was loaded into memory.
http://www.youtube.com/watch?v=SOOFHFnB0D8
Application programs had to fit within the 4K memory limitation. This video shows a Chess program, and the user interaction using the ASR33 Teletype, that was supplied with every PDP-8.
http://www.youtube.com/watch?v=OyDufWHsNVE
Contemporary to the LINC and the PDP-8 was a low cost magnetic tape drive, commercialised by DEC as the DECtape. The last of the NMOC videos, shows the DECtape in use
http://www.youtube.com/watch?v=TWTpYUTbW8s
One area of science that particularly benefited from more widely available computing power, was that of biomedical research. Two computer designs, in particular, spurred on this advancement, the LINC of 1962, and the PDP-8 of 1965.
About 50 LINC machines were built, and a few survive today. This video shows a restored LINC in use.
http://www.youtube.com/watch?v=atJUnQN65dE
These were the first "benchtop" designs, and set the trend in design for the machines that were to be known as minicomputers. In 1965 the PDP-8 cost $18,000, still a huge amount of money, but cheap enough to be built in volume and satisfy the needs of university laboratories.
Both the LINC and the PDP-8, owed their design to the general purpose digital modules, that were manufactured by DEC from the late 1950s onwards. Each machine was a pared down 12 bit design, cost engineered for efficiency at every level, offering a machine capable of real work for a modest price.
Over the next 20 years, the PDP-8 architecture was to be revisited many times, as advancements in logic ICs and memory allowed significant cost savings to be made. The original PDP-8 was the size of a small fridge, within 10 years it was housed in a single 19" rack. The very last PDP-8 machines used a microprocessor (Intersil/Harris 6120) to implement the CPU.
By the mid 1970s, microprocessors were starting to appear, which led to the era of 8-bit microcomputers. Some of these, such as the MITS Altair 8800 paid homage to the style of the PDP-8 with a front panel of many LEDs and programming switches. The simple LED indicators allowed the user to see precisely what the registers were holding, and the switches allowed simple programs to be "toggled" directly into memory.
These machines are now approaching 50 year old , yet there are many enthusiasts who started their scientific or engineering careers programming such computers. The National Museum of Computing at Bletchley Park owns an early PDP-8, which they have restored to working order. They have made a series of short videos depicting its operation.
Here's how a short program is loaded into the machine from the front panel switches.
http://www.youtube.com/watch?v=DPioENtAHuY
Notice how much noise was present in a typical computer room. Fans, printers and teletypes produces a near constant din.
The machines were relatively slow and simple by today's comparison, capable of some 300,000 instructions per second. Nevertheless, they were capable of real work, despite their limitations in speed and memory.
In the mid 1960s, the standard user interface was a teletype printer with paper tape punch and reader. Programs would be loaded into the memory from paper tape, but often only after a simple tape loader had been manually toggled into the machine from the front panel switches.
The second of the NMOC videos shows how program on the the paper tape was loaded into memory.
http://www.youtube.com/watch?v=SOOFHFnB0D8
Application programs had to fit within the 4K memory limitation. This video shows a Chess program, and the user interaction using the ASR33 Teletype, that was supplied with every PDP-8.
http://www.youtube.com/watch?v=OyDufWHsNVE
Contemporary to the LINC and the PDP-8 was a low cost magnetic tape drive, commercialised by DEC as the DECtape. The last of the NMOC videos, shows the DECtape in use
http://www.youtube.com/watch?v=TWTpYUTbW8s
Monday, May 27, 2013
A LED Chaser Display using SIMPL
My last post described how a LED chaser display was one of my first forays into physical computing about 30 years ago.
My recent experiments with SIMPL, have shown that it is a perfect programming tool for simple interactions with physical computing devices - so I decided to recreate a simple LED chaser display, using SIMPL.
LED chaser displays require a bunch of LEDs which you can address individually. You also need to write code that provides basic loop structures and the means to control timing. SIMPL, which uses the Txtzyme interpreter is ideal for this task.
Txtzyme uses 1o to set a port pin high and 0o to set it low. The port pin has to be pre-specified using the d command. This all becomes a little unwieldy, so lets define a couple of new words to make it easier to type.
We will use H and L to set the port pins high and low respectively. LEDs are currently fitted to digital pins 2 to 9.
Now the definitions:
:Hd1o - sets the defined pin high
:Ld0o - sets the defined pin low
So typing 2H will turn on the LED on pin 2, and 2L will turn it off again. This simplifies the control of outputs to two very memorable commands H and L.
Now we need to generate a loop which turns all the LEDs on in sequence. Because of the way the loop counter works in SIMPL, descending loops are easier as the loop counter k can be accessed to control the loop.
This performs a down count
10{kd1o100mkd0o}
10 - perform the loop 10 times
kd1o - move the loop count k into d to select the pin and set it high
100m - wait 100mS
kd0o - move the loop count k into d to select the pin and set it low
We could now substitute H for d1o and L for d0o giving the construct
10{kH100mkL}
To make an upward counting loop is a little harder and it uses the l instruction (l as in little L).
l increments the y variable each time it is executed, and the word @ allows us to move y into x so that we can print it out.
So to make a loop that counts up from 1 to 10 we first have to set y to zero using 0! (store 0 in y)
0!10{l@p} will print out the numbers from 1 to 10.
The construct l@p increments y, moves y into x and prints it out. To turn this into a LED chaser we need to add the H and L words to control the LEDs and a short delay to control the speed:
We start with the loop - load y with a count of 1. The loop will start at 2, and run to 9
1!9{l@pd1o100m@d0o}
We can now replace d1o and d0o with H and L
1!9{l@H100m@L}
Remember that @ gets the current value of the increasing loop count y and puts it into x.
My recent experiments with SIMPL, have shown that it is a perfect programming tool for simple interactions with physical computing devices - so I decided to recreate a simple LED chaser display, using SIMPL.
LED chaser displays require a bunch of LEDs which you can address individually. You also need to write code that provides basic loop structures and the means to control timing. SIMPL, which uses the Txtzyme interpreter is ideal for this task.
Txtzyme uses 1o to set a port pin high and 0o to set it low. The port pin has to be pre-specified using the d command. This all becomes a little unwieldy, so lets define a couple of new words to make it easier to type.
We will use H and L to set the port pins high and low respectively. LEDs are currently fitted to digital pins 2 to 9.
Now the definitions:
:Hd1o - sets the defined pin high
:Ld0o - sets the defined pin low
So typing 2H will turn on the LED on pin 2, and 2L will turn it off again. This simplifies the control of outputs to two very memorable commands H and L.
Now we need to generate a loop which turns all the LEDs on in sequence. Because of the way the loop counter works in SIMPL, descending loops are easier as the loop counter k can be accessed to control the loop.
This performs a down count
10{kd1o100mkd0o}
10 - perform the loop 10 times
kd1o - move the loop count k into d to select the pin and set it high
100m - wait 100mS
kd0o - move the loop count k into d to select the pin and set it low
We could now substitute H for d1o and L for d0o giving the construct
10{kH100mkL}
To make an upward counting loop is a little harder and it uses the l instruction (l as in little L).
l increments the y variable each time it is executed, and the word @ allows us to move y into x so that we can print it out.
So to make a loop that counts up from 1 to 10 we first have to set y to zero using 0! (store 0 in y)
0!10{l@p} will print out the numbers from 1 to 10.
The construct l@p increments y, moves y into x and prints it out. To turn this into a LED chaser we need to add the H and L words to control the LEDs and a short delay to control the speed:
We start with the loop - load y with a count of 1. The loop will start at 2, and run to 9
1!9{l@pd1o100m@d0o}
We can now replace d1o and d0o with H and L
1!9{l@H100m@L}
Remember that @ gets the current value of the increasing loop count y and puts it into x.
Sunday, May 26, 2013
Not Enough Flashing Lights or Switches
Growing up in the 1970s, a common depiction of computers, at least by Hollywood film-makers, was a room full of wardrobe sized cabinets, with innumerable flashing lights and switches and spinning tape drives. Frequently, the plot of the movie was centred on the computer malfunctioning in some malevolent way, and chaos breaking out. The Italian Job, Westworld and 2001 A Space Odyssey all relied on computer failures to spice up the plot.
The reality was that throughout the 1960s, computer hardware was large and cumbersome, covered in lights and switches, and you only had to point a camera at any mainframe of that era, and you had the perfect cheap shot to enhance any sci-fi movie.
By the early 1980s, computers had entered homes and schools, and teenagers, such as myself at that time, were spending countless hours typing BASIC program listings from computer magazines, into low spec home computers, with dubious keyboards and scungy TV displays. In just 5 years, the first micros of the mid 1970s had evolved from homebrew rack systems with lights and switches, to mass produced machines on sale in every high street. In homage to the early micros, the classic example of that era, was the MITS Altair 8800, which had a role in the 1983 film "War Games".
At about the same time that Matthew Broderick was pretending to program the Altair 8800, I had invested in an 8 bit input output card for my ZX81. At about £20, and solder it yourself, it had cost me several weeks pocket money. Here for the first time, for me, was the means to connect to the real world and make the computer do something under program control. The first thing was to connect 8 LEDs to the pins of the output port and with some simple BASIC programs, create a whole load of different "Knight Rider" LED chaser display effects.
Fast forward 30 years, and technology has developed by several orders of magnitude. The average Smartphone now has 1 million times as much RAM as my first ZX81 and is clocked at 1000 times the speed. Not to mention that it has four 32 bit ARM processors acting as a quad array, plus a specialist graphics processor unit. This type of processing power and memory storage capacity in your pocket was inconceivable just a few years ago.
However, just because millions carry around this sort of processing capability in their pockets or bags, does not mean that we have become a population of computer scientists. In fact, the average citizen has no more inkling today of how a computer works, than 30 or 40 years ago, watching computers malfunction on Hollywood movies.
Fortunately, in recent years there has been an active and vocal campaign to help educate a tiny percentage of the population into the workings of computer technology. The $20 Arduino and it's spin offs, has done more for teaching computing science, hardware, firmware and programming skills than any other device in the last 30 years.
So, in homage to those early homebrew computers with their flashing LED displays, I have connected a dozen LEDs to the pins of an Arduino, and recreated some of my light chaser memories from 30 years ago.
I have a new toy to play with, and a programming language SIMPL that lends itself to simple interactive physical computing. A few lines of SIMPL and I have a LED chaser display that demonstrates the benefits of having an interactive programming environment.
The reality was that throughout the 1960s, computer hardware was large and cumbersome, covered in lights and switches, and you only had to point a camera at any mainframe of that era, and you had the perfect cheap shot to enhance any sci-fi movie.
By the early 1980s, computers had entered homes and schools, and teenagers, such as myself at that time, were spending countless hours typing BASIC program listings from computer magazines, into low spec home computers, with dubious keyboards and scungy TV displays. In just 5 years, the first micros of the mid 1970s had evolved from homebrew rack systems with lights and switches, to mass produced machines on sale in every high street. In homage to the early micros, the classic example of that era, was the MITS Altair 8800, which had a role in the 1983 film "War Games".
At about the same time that Matthew Broderick was pretending to program the Altair 8800, I had invested in an 8 bit input output card for my ZX81. At about £20, and solder it yourself, it had cost me several weeks pocket money. Here for the first time, for me, was the means to connect to the real world and make the computer do something under program control. The first thing was to connect 8 LEDs to the pins of the output port and with some simple BASIC programs, create a whole load of different "Knight Rider" LED chaser display effects.
Fast forward 30 years, and technology has developed by several orders of magnitude. The average Smartphone now has 1 million times as much RAM as my first ZX81 and is clocked at 1000 times the speed. Not to mention that it has four 32 bit ARM processors acting as a quad array, plus a specialist graphics processor unit. This type of processing power and memory storage capacity in your pocket was inconceivable just a few years ago.
However, just because millions carry around this sort of processing capability in their pockets or bags, does not mean that we have become a population of computer scientists. In fact, the average citizen has no more inkling today of how a computer works, than 30 or 40 years ago, watching computers malfunction on Hollywood movies.
Fortunately, in recent years there has been an active and vocal campaign to help educate a tiny percentage of the population into the workings of computer technology. The $20 Arduino and it's spin offs, has done more for teaching computing science, hardware, firmware and programming skills than any other device in the last 30 years.
So, in homage to those early homebrew computers with their flashing LED displays, I have connected a dozen LEDs to the pins of an Arduino, and recreated some of my light chaser memories from 30 years ago.
I have a new toy to play with, and a programming language SIMPL that lends itself to simple interactive physical computing. A few lines of SIMPL and I have a LED chaser display that demonstrates the benefits of having an interactive programming environment.
Wednesday, May 22, 2013
SIMPL - A simple programming language based on Txtzyme
SIMPL - A simple programming language based on Txtzyme
Last weekend I played around with Ward Cunningham's Txtzyme - a minimalist programming language, with an interpreter written in C so that it can be easily ported to many microcontrollers.
Txtzyme contains all the elements necessary to enable a microcontroller to interpret and execute a series of typed commands, and is an ideal example to learn the techniques employed by more sophisticated interpretive languages.
During the past week, I have written some extensions to Txtzyme and tried out a few ideas to make Txtzyme more versatile and easier to use.
This blog post is a tutorial in Txtzyme, and it's new extensions to create more of a useful language - which I am calling SIMPL - A Serial Interpreted Minimal Programming Language.
SIMPL runs in under 6K on the standard Arduino.
A Brief Description of Txtzyme.
Txtzyme consists of an interpreter contained within a loop. The interpreter, intended to be very simple, decodes individual ASCII characters, and executes a block of C code associated with that character. This is similar, in principle to how Forth scans through a series of Forth words and executes the code associated with them, but Txtzyme treats each ASCII character as a word, greatly simplifying the scanning process.
The interpreter steps through a string of ASCII characters, executing the associated code blocks in turn. This may be slow in speed in comparison to assembly language execution, but the user does not need to know about machine code, assembly language or even C to make the microcontroller perform simple tasks.
Numbers and Maths
Txtzyme enumerates numbers and assigns them to an integer variable x. Typing 123p into the serial terminal will set x to 123, and then print that value out when the p command is executed.
I extended Txtzyme with the use of another integer variable y. A number can be stored in y by using the ! character. This again being borrowed from Forth.
456! will initially assign 456 to x, and then copy it into y.
The use of the second variable allows simple maths operations to be performed. Taking the simple interpreter, I added some maths operations + - * and / .
456!123+p will set y to 456, then set x to 123, add x and y, leaving the result in x and then print out the answer 579.
I/O Commands
Txtzyme was designed to perform simple I/O operations on the pins of the microcontroller, with each operation being initiated by a serial command. This allows ports to be set, inputs to be read and analogue inputs to be read and printed to the serial terminal. The keywords that perform these operations are generally only single ascii characters, chosen to make the commands surprisingly human readable.
First you have to state which I/O pin you wish to use. This is done with the d command.
For example 6d will select digital pin 6
You may then set this selected pin to high using 1o (where o = output) or to low using 0o.
To read an input pin, first you have to define it eg. 8d will define digital 8. Then you use i, for input to read it's state into x. p will then print out the value.
To read the value on one of the ADC pins, you use the s command, which means analogue sample.
0sp will read the value on ADC 0 into x and print it out.
Loops
Txtzyme uses a simple loop structure, allowing commands to be executed repeatedly. It also uses the native delay functions present on the Arduino to provide simple timing functions - ideal for flashing LEDs and generating musical tones from output pins. Txtzyme can toggle output pins at up to 47kHz, a speed that is only limited by the Arduino digitalWrite function.
The loop function will execute any command contained within braces {}. It uses x to initialise the loop counter, k to a starting value, from whence k will be decremented to zero and terminate the loop.
For example to print out ten readings from analogue pin 0
10{0sp}
To see the loop count variable k decrementing
10{kp} will print out the numbers from 9 decrementing to 0
Txtzyme does not yet have the ability to do complete FOR/NEXT loops. This would be a very useful addition, the means to perform a loop such as
for i = x to y step z
I have added primitives @ l y and z
y allows direct access to the variable y so typing 10y is equivalent to y=10
@ was intended to be the equivalent of Forth's fetch, but in SIMPL it copies the value stored in y to x.
l is a loop counter. It increments y by 1 every time
The construct l@p increments y by 1, copies it to x and prints it out.
To print an ascending series of numbers from 1 to 10 uses this construct
0y10{l@p}
When combined with the read primitive r (see below) this can be used to read and print consecutive RAM addresses.
I/O with Loops and Timing
Loops can be used to flash LEDs or generate tones, and can be combined with the millisecond and microsecond delay functions to generate appropriate timed behaviour.
To flash a LED on pin 13 ten times, on for 500mS and off for 500mS
13d10{1o500m0o500m}
To turn this into an audible note to sound a small speaker on pin 6, we shorten the delay to say 500uS, and generate say 1000 cycles (1000 times around the loop).
6d1000{1o500u0o500u}
Creating New Definitions
The simple Txtzyme interpreter readily executes a program contained in the characters in the input buffer, but wouldn't it be great if you could store these mini programs in RAM so you could use them time over?
The mechanism to execute a program from RAM, is to point the interpreter at the location of the starting character and let it execute the characters in turn until it finds a return '\r' or newline '\n' character that marks the end of the string.
Here we have to start borrowing ideas from Forth, the concept of the "word" that signifies the start address of a block of code to execute, and the "colon definition" - a mechanism to write new words into memory.
To keep things simple, our new words will be assigned only the capital letters, allowing up to 26 new words to be defined, namely A to Z.
Additionally, to simplify the addressing of these words, and to keep the RAM usage within the limitations of the ATmega328 ( as used on the Arduino), we will allocate each word just 48 bytes of memory, with each consecutive word starting on the 48 byte address boundary. This allows us to easily decode the ASCII value of the character, find the starting address of the associated code, and execute the word.
To create a new word, and to tell the interpreter to copy the input character string into the correct position of RAM we use the "colon definition".
We type a colon followed by the capital letter of the word we wish to create. Suppose we liked the tone example from above and want to assign it to the letter T, we type
:T6d1000{1o500u0o500u}
The colon definition code will detect the leading : and then decode the T to 84 in decimal. It then creates an address by multiplying 84 by the allocated permissible word length of 48 bytes, and adds this to the start address of the array assigned to hold the definitions. I have restricted the length of the definitions to 48 bytes, because on the Arduino we are short of RAM - only having 2K to play with. Having fixed blocks of 48 characters for each definition is wasteful, but it greatly simplifies and speeds up the instruction decoding and addressing process.
This character based addressing process happens automatically and we don't have to concern ourselves about the exact address that holds T, however whenever the interpreter encounters a T, it will jump to the correct address and execute the code it finds there.
Once stored in RAM, the interpreter prints out T, to say it has been defined, and then executes the new word twice. This is a quirk of the interpreter. So we hear the tone twice as long.
Now whenever we type T, we will get the tone.
In order to keep track of what we are doing, I have added a ? command. This prints out the entire definition RAM, showing the commands A to Z and the code that is associated with them. This allows a definition to be edited, by cut and paste operations from the ? listing into the input buffer, and changing what ever parameter is to be edited. The edited definition is then automatically stored back into RAM, when you press return.
Some Prestored Definitions
Just for fun, I decided to hard code some "musical notes" into the definitions. Characters A to G play a short musical note, roughly tuned to A = 440Hz , so it's possible to play tunes just by typing the notes. Having "musical debug" is also a great way of determining whether the program is doing what was intended.
The SIMPL strings for properly tuned notes are as follows, and are pasted into the RAM array when the sketch is first compiled. They can be written over at anytime.
// 40{1o1106u0o1106u} // A 440 Hz
// 45{1o986u0o986u} // B 493.88 Hz
// 51{1o929u0o929u} // C 523.25 Hz
// 57{1o825u0o825u} // D 587.33 Hz
// 64{1o733u0o733u} // E 659.26 Hz
// 72{1o690u0o691u} // F 698.46 Hz
// 81{1o613u0o613u} // G 783.99 HZ
Building Up Programs
The real power behind the colon definition is that new and more complex words can be assembled from existing definitions, and then executed as singe commands. For example, suppose we have defined three tone generating words A B and C.
We can type ABC - which will play the three tones in succession
Alternatively 5{ABC} will play the 3 tone sequence 5 times over
We could then define a new word I as
:I5{ABC}
Whenever we type I, we get ABC played 5 times.
So from very simple definitions, quite complex operations can be performed.
This is an incredibly versatile technique. It allows you to write your own routines, assembled from other routines and then be able to use names that you can remember.
For example, you can define a word H to set the port pin high, and L to set it low. If you have a LED connected to pin 6, 6H will turn it on, whilst 5L will set pin 5 to logic low. It becomes very easy to toggle any output pin - just with a couple of memorable keystrokes.
This ability to form new definitions is one of the fundamental and most powerful aspects of Forth - so very worthwhile to borrow it to make it adaptable to the minimal programming environment of SIMPL.
Some Other Additions
The Txtzyme interpreter is readily modified to include new functions. This is a work in progress and I have added some simple extensions.
I now have comparison operators < and > to test whether x is less than y or greater than y. These operations will set x to 1 if true or 0 if false.
10!5< translates to "is 5 less than 10 ?". This is true so x is set to 1.
10!5> translates to "is 5 greater than 10 ?". This is false so x is set to 0.
To make use of these comparisons I have introduced the jump command j. If x = 1 the next command is skipped, otherwise it is executed as normal.
Memory Operations.
I wanted a means to directly edit the contents of an address in RAM and read it. These are equivalent to PEEK and POKE.
The y variable is used to hold the address - so 723! will set the address up as 723.
The x variable is used to hold the data
To write to RAM we use w and to read we use r
So 723!65w will write the character ASCII 65 into address 723. You can then type ? to see that it's there. It pokes an "A" into the first location of the word defined by J.
To read a location,
723!r will read the contents of location 723 and print it as an ASCII character. You get your "A" back.
As this character has been poked into a definition, it has modified that definition. In this case it will cause definition J to play the tone associated with A.
Finally, I needed a means to look at a block of memory. The q command does this by printing out the desired number of characters starting at the address stored into y.
As an example, address 627 holds the start address of the H command
Typing 627!48q will print out 48 consecutive characters, which in our case is the start-up message
_Hello World, and welcome to SIMPL_
With the loop primitive l we can also read and print successive memory locations
627y48{l@r}
This sets the address in y to 627 and reads and prints 48 consecutive locations using the r primitive.
Using the colon definition, the construct l@r could be assigned to R, as in :Rl@r
So to read and print 33 characters from address 627 we use
627y33{L}
A Work in Progress
SIMPL and it's underlying Txtzyme interpreter is constantly evolving as new commands are added to try new ideas.
It is unlikely that it will ever be a serious language, but a novel experiment and a means to understand how an interpreter can be manipulated to execute a series of simple commands.
Many of the ideas have been borrowed from and inspired by Charles Moore's Forth as it evolved from a set of ideas into a proper language during the 1960s.
You can download a recent version of SIMPL from github gist - but be aware that it is a work in progress.
https://gist.github.com/anonymous/5648871
I hope others will get as much enjoyment as I have from tinkering with SIMPL and Txtzyme.
Last weekend I played around with Ward Cunningham's Txtzyme - a minimalist programming language, with an interpreter written in C so that it can be easily ported to many microcontrollers.
Txtzyme contains all the elements necessary to enable a microcontroller to interpret and execute a series of typed commands, and is an ideal example to learn the techniques employed by more sophisticated interpretive languages.
During the past week, I have written some extensions to Txtzyme and tried out a few ideas to make Txtzyme more versatile and easier to use.
This blog post is a tutorial in Txtzyme, and it's new extensions to create more of a useful language - which I am calling SIMPL - A Serial Interpreted Minimal Programming Language.
SIMPL runs in under 6K on the standard Arduino.
A Brief Description of Txtzyme.
Txtzyme consists of an interpreter contained within a loop. The interpreter, intended to be very simple, decodes individual ASCII characters, and executes a block of C code associated with that character. This is similar, in principle to how Forth scans through a series of Forth words and executes the code associated with them, but Txtzyme treats each ASCII character as a word, greatly simplifying the scanning process.
The interpreter steps through a string of ASCII characters, executing the associated code blocks in turn. This may be slow in speed in comparison to assembly language execution, but the user does not need to know about machine code, assembly language or even C to make the microcontroller perform simple tasks.
Numbers and Maths
Txtzyme enumerates numbers and assigns them to an integer variable x. Typing 123p into the serial terminal will set x to 123, and then print that value out when the p command is executed.
I extended Txtzyme with the use of another integer variable y. A number can be stored in y by using the ! character. This again being borrowed from Forth.
456! will initially assign 456 to x, and then copy it into y.
The use of the second variable allows simple maths operations to be performed. Taking the simple interpreter, I added some maths operations + - * and / .
456!123+p will set y to 456, then set x to 123, add x and y, leaving the result in x and then print out the answer 579.
I/O Commands
Txtzyme was designed to perform simple I/O operations on the pins of the microcontroller, with each operation being initiated by a serial command. This allows ports to be set, inputs to be read and analogue inputs to be read and printed to the serial terminal. The keywords that perform these operations are generally only single ascii characters, chosen to make the commands surprisingly human readable.
First you have to state which I/O pin you wish to use. This is done with the d command.
For example 6d will select digital pin 6
You may then set this selected pin to high using 1o (where o = output) or to low using 0o.
To read an input pin, first you have to define it eg. 8d will define digital 8. Then you use i, for input to read it's state into x. p will then print out the value.
To read the value on one of the ADC pins, you use the s command, which means analogue sample.
0sp will read the value on ADC 0 into x and print it out.
Loops
Txtzyme uses a simple loop structure, allowing commands to be executed repeatedly. It also uses the native delay functions present on the Arduino to provide simple timing functions - ideal for flashing LEDs and generating musical tones from output pins. Txtzyme can toggle output pins at up to 47kHz, a speed that is only limited by the Arduino digitalWrite function.
The loop function will execute any command contained within braces {}. It uses x to initialise the loop counter, k to a starting value, from whence k will be decremented to zero and terminate the loop.
For example to print out ten readings from analogue pin 0
10{0sp}
To see the loop count variable k decrementing
10{kp} will print out the numbers from 9 decrementing to 0
Txtzyme does not yet have the ability to do complete FOR/NEXT loops. This would be a very useful addition, the means to perform a loop such as
for i = x to y step z
I have added primitives @ l y and z
y allows direct access to the variable y so typing 10y is equivalent to y=10
@ was intended to be the equivalent of Forth's fetch, but in SIMPL it copies the value stored in y to x.
l is a loop counter. It increments y by 1 every time
The construct l@p increments y by 1, copies it to x and prints it out.
To print an ascending series of numbers from 1 to 10 uses this construct
0y10{l@p}
When combined with the read primitive r (see below) this can be used to read and print consecutive RAM addresses.
I/O with Loops and Timing
Loops can be used to flash LEDs or generate tones, and can be combined with the millisecond and microsecond delay functions to generate appropriate timed behaviour.
To flash a LED on pin 13 ten times, on for 500mS and off for 500mS
13d10{1o500m0o500m}
To turn this into an audible note to sound a small speaker on pin 6, we shorten the delay to say 500uS, and generate say 1000 cycles (1000 times around the loop).
6d1000{1o500u0o500u}
Creating New Definitions
The simple Txtzyme interpreter readily executes a program contained in the characters in the input buffer, but wouldn't it be great if you could store these mini programs in RAM so you could use them time over?
The mechanism to execute a program from RAM, is to point the interpreter at the location of the starting character and let it execute the characters in turn until it finds a return '\r' or newline '\n' character that marks the end of the string.
Here we have to start borrowing ideas from Forth, the concept of the "word" that signifies the start address of a block of code to execute, and the "colon definition" - a mechanism to write new words into memory.
To keep things simple, our new words will be assigned only the capital letters, allowing up to 26 new words to be defined, namely A to Z.
Additionally, to simplify the addressing of these words, and to keep the RAM usage within the limitations of the ATmega328 ( as used on the Arduino), we will allocate each word just 48 bytes of memory, with each consecutive word starting on the 48 byte address boundary. This allows us to easily decode the ASCII value of the character, find the starting address of the associated code, and execute the word.
To create a new word, and to tell the interpreter to copy the input character string into the correct position of RAM we use the "colon definition".
We type a colon followed by the capital letter of the word we wish to create. Suppose we liked the tone example from above and want to assign it to the letter T, we type
:T6d1000{1o500u0o500u}
The colon definition code will detect the leading : and then decode the T to 84 in decimal. It then creates an address by multiplying 84 by the allocated permissible word length of 48 bytes, and adds this to the start address of the array assigned to hold the definitions. I have restricted the length of the definitions to 48 bytes, because on the Arduino we are short of RAM - only having 2K to play with. Having fixed blocks of 48 characters for each definition is wasteful, but it greatly simplifies and speeds up the instruction decoding and addressing process.
This character based addressing process happens automatically and we don't have to concern ourselves about the exact address that holds T, however whenever the interpreter encounters a T, it will jump to the correct address and execute the code it finds there.
Once stored in RAM, the interpreter prints out T, to say it has been defined, and then executes the new word twice. This is a quirk of the interpreter. So we hear the tone twice as long.
Now whenever we type T, we will get the tone.
In order to keep track of what we are doing, I have added a ? command. This prints out the entire definition RAM, showing the commands A to Z and the code that is associated with them. This allows a definition to be edited, by cut and paste operations from the ? listing into the input buffer, and changing what ever parameter is to be edited. The edited definition is then automatically stored back into RAM, when you press return.
Some Prestored Definitions
Just for fun, I decided to hard code some "musical notes" into the definitions. Characters A to G play a short musical note, roughly tuned to A = 440Hz , so it's possible to play tunes just by typing the notes. Having "musical debug" is also a great way of determining whether the program is doing what was intended.
The SIMPL strings for properly tuned notes are as follows, and are pasted into the RAM array when the sketch is first compiled. They can be written over at anytime.
// 40{1o1106u0o1106u} // A 440 Hz
// 45{1o986u0o986u} // B 493.88 Hz
// 51{1o929u0o929u} // C 523.25 Hz
// 57{1o825u0o825u} // D 587.33 Hz
// 64{1o733u0o733u} // E 659.26 Hz
// 72{1o690u0o691u} // F 698.46 Hz
// 81{1o613u0o613u} // G 783.99 HZ
Building Up Programs
The real power behind the colon definition is that new and more complex words can be assembled from existing definitions, and then executed as singe commands. For example, suppose we have defined three tone generating words A B and C.
We can type ABC - which will play the three tones in succession
Alternatively 5{ABC} will play the 3 tone sequence 5 times over
We could then define a new word I as
:I5{ABC}
Whenever we type I, we get ABC played 5 times.
So from very simple definitions, quite complex operations can be performed.
This is an incredibly versatile technique. It allows you to write your own routines, assembled from other routines and then be able to use names that you can remember.
For example, you can define a word H to set the port pin high, and L to set it low. If you have a LED connected to pin 6, 6H will turn it on, whilst 5L will set pin 5 to logic low. It becomes very easy to toggle any output pin - just with a couple of memorable keystrokes.
This ability to form new definitions is one of the fundamental and most powerful aspects of Forth - so very worthwhile to borrow it to make it adaptable to the minimal programming environment of SIMPL.
Some Other Additions
The Txtzyme interpreter is readily modified to include new functions. This is a work in progress and I have added some simple extensions.
I now have comparison operators < and > to test whether x is less than y or greater than y. These operations will set x to 1 if true or 0 if false.
10!5< translates to "is 5 less than 10 ?". This is true so x is set to 1.
10!5> translates to "is 5 greater than 10 ?". This is false so x is set to 0.
To make use of these comparisons I have introduced the jump command j. If x = 1 the next command is skipped, otherwise it is executed as normal.
Memory Operations.
I wanted a means to directly edit the contents of an address in RAM and read it. These are equivalent to PEEK and POKE.
The y variable is used to hold the address - so 723! will set the address up as 723.
The x variable is used to hold the data
To write to RAM we use w and to read we use r
So 723!65w will write the character ASCII 65 into address 723. You can then type ? to see that it's there. It pokes an "A" into the first location of the word defined by J.
To read a location,
723!r will read the contents of location 723 and print it as an ASCII character. You get your "A" back.
As this character has been poked into a definition, it has modified that definition. In this case it will cause definition J to play the tone associated with A.
Finally, I needed a means to look at a block of memory. The q command does this by printing out the desired number of characters starting at the address stored into y.
As an example, address 627 holds the start address of the H command
Typing 627!48q will print out 48 consecutive characters, which in our case is the start-up message
_Hello World, and welcome to SIMPL_
With the loop primitive l we can also read and print successive memory locations
627y48{l@r}
This sets the address in y to 627 and reads and prints 48 consecutive locations using the r primitive.
Using the colon definition, the construct l@r could be assigned to R, as in :Rl@r
So to read and print 33 characters from address 627 we use
627y33{L}
A Work in Progress
SIMPL and it's underlying Txtzyme interpreter is constantly evolving as new commands are added to try new ideas.
It is unlikely that it will ever be a serious language, but a novel experiment and a means to understand how an interpreter can be manipulated to execute a series of simple commands.
Many of the ideas have been borrowed from and inspired by Charles Moore's Forth as it evolved from a set of ideas into a proper language during the 1960s.
You can download a recent version of SIMPL from github gist - but be aware that it is a work in progress.
https://gist.github.com/anonymous/5648871
I hope others will get as much enjoyment as I have from tinkering with SIMPL and Txtzyme.
Sunday, May 19, 2013
More Thoughts on Txtzyme - and a musical interlude
In the last post I discussed the simple interpreted language Txtzyme and offered some ideas on how the language could be extended.
Ward Cunningham, the creator of txtzyme describes it as text that "catalyses action". I think this is a fair description.
In summary, Txtzyme uses some very simple methods to produce an executable program and interface with the Arduino hardware. It uses the following Arduino functions to enable the interpreter to implement a simple serial interface and access the digital and analogue I/O:
Serial.read
Serial.print
digitalWrite
digitalRead
analogRead
delay
delayMicroseconds
Much of the simplicity is that a single ASCII character is interpreted to produce an action, and by stringing ASCII characters together the interpreter will handle them in turn and execute each action in order.
The interpreter allows the use of a simple loop structure, by repeating the actions enclosed within braces (curly brackets) {.......}
Numerical characters are decoded into a decimal number and assigned to a single numerical variable x which is used as a parameter to control some of the actions. For example, time is handled using the two native Arduino functions delay (mS) and delayMicroseconds.
These are given the characters m and u respectively, such that
1000m is a delay of 1000 milliseconds
500u is a delay of 500 microseconds
These are useful to slow down program operation, such as when reading ports or ADCs and printing of for creating accurate timing loops for generating frequencies.
Extending the Ideas
My first foray into txtzyme was to enhance the simple interpreter such that it could execute a series of user routines invoked by typing their uppercase ASCII character name. The use of uppercase differentiates them from what I will call txtzyme primitive functions which are represented by lowercase characters.
I fitted a small loudspeaker to digital 6 and from it I was able to produce a series of beeps and tones, however it soon got tedious having to retype the txtzyme strings into the input buffer each time I wanted to try a new tone. This inspired me onto the next level of extension, the means to code each txtzyme string into a named array in memory, and execute the string just by typing its name. This is an idea heavily borrowed from the idea of Forth words, but simplified to use just a single uppercase character (A-Z) as the name.
For the demonstration, I defined six user routines called A-F, each of which caused a short musical tone to be output from pin 6 of the Arduino. The code to do this is on my github gist
https://gist.github.com/anonymous/5604829
Each uppercase character defines a txtzyme array of characters which can be interpreted as though it was typed into the serial terminal buffer. For example, a musical note is defined by the following characters stored in the A array and will be invoked whenever the text interpreter encounters the character A. 6d selects digital port pin 6, and produces 75 cycles of tone. The port pin is low for 708 microseconds and then high for 708 microseconds.
char A[64] = "6d75{1o708u0o708u}";
The A array has a total of 64 characters reserved for it although only 17 are used. This is not very efficient on RAM usage, but since there are only 26 user routines, less than 1700 bytes of RAM are allocated for this storage.
I then proceeded to write similar strings for the "notes" B through to F. Once compiled, these notes could be played just by typing ABC, or any other sequence into the serial terminal.
I then defined G by the array
char G[64] = "ABCDEFFEDCBA";
To my delight, and surprise it played the sequence of 12 notes perfectly. Using musical tones to debug program flow is a neat trick, and a lot easier and quicker than counting flashes on a LED!
Another though was what happens if a word calls itself - using this example
char H[64] = "GH";
Typing H produced an infinite loop of tone sequence - not unsurprisingly.
Finally I tried an example that reads and prints the adc0 and plays a tune each time
char I[64] = "{0spABC}";
Notice how this is just a loop structure with no controlling parameter. This means that the number of times the loop is executed can be specified by typing that number before the I,
5I - perform the I sequence 5 times.
Colon Definitions
The Colon Definition is a construct borrowed unashamedly from Forth. It is the method by which new words (actions) can be defined and stored into memory. This has the advantage of not having to keep typing new stings repeatedly just to try them out, but also provides a simple means to write new code, test it and edit it until it works.
The above demonstration bypassed the need for the colon definition, by using a hard coded array of characters defined in the C code. Now it is time to bite the bullet and extend the interpreter to handle the colon definition.
The example above written as a colon definition would be written
:A6d75{1o708u0o708u};
As txtzyme ignores whitespace, this could be rewritten with spaces to make it more legible
: A 6d 75{1o 708u 0o 708u};
To handle the colon definition we need a routine that on seeing the colon, gets the next character (capital A) as the name and copies the next n characters to an array called by that name. This process ends when the interpreter encounters the semicolon.
Unfortunately, I'm not really a C programmer, so the clever use of pointers and the reference and dereference operators tends to fox me somewhat, but after an hour of some kludgy coding, I had a function that would perform the colon definition task, and assemble the definition into a named array.
In theory the name of the definition eg A, should just be an address in memory, and on typing A, the interpreter starts processing the characters that appear at that address until the newline character is encountered.
Viewing and Editing txtzyme definitions.
I also decided that the ? character would be a good way of examining the code contained within a definition, allowing cut and paste editing from the serial terminal.
So ?A prints out the entire definition of A to the terminal
:A6d75{1o708u0o708u};
To be continued.
Ward Cunningham, the creator of txtzyme describes it as text that "catalyses action". I think this is a fair description.
In summary, Txtzyme uses some very simple methods to produce an executable program and interface with the Arduino hardware. It uses the following Arduino functions to enable the interpreter to implement a simple serial interface and access the digital and analogue I/O:
Serial.read
Serial.print
digitalWrite
digitalRead
analogRead
delay
delayMicroseconds
Much of the simplicity is that a single ASCII character is interpreted to produce an action, and by stringing ASCII characters together the interpreter will handle them in turn and execute each action in order.
The interpreter allows the use of a simple loop structure, by repeating the actions enclosed within braces (curly brackets) {.......}
Numerical characters are decoded into a decimal number and assigned to a single numerical variable x which is used as a parameter to control some of the actions. For example, time is handled using the two native Arduino functions delay (mS) and delayMicroseconds.
These are given the characters m and u respectively, such that
1000m is a delay of 1000 milliseconds
500u is a delay of 500 microseconds
These are useful to slow down program operation, such as when reading ports or ADCs and printing of for creating accurate timing loops for generating frequencies.
Extending the Ideas
My first foray into txtzyme was to enhance the simple interpreter such that it could execute a series of user routines invoked by typing their uppercase ASCII character name. The use of uppercase differentiates them from what I will call txtzyme primitive functions which are represented by lowercase characters.
I fitted a small loudspeaker to digital 6 and from it I was able to produce a series of beeps and tones, however it soon got tedious having to retype the txtzyme strings into the input buffer each time I wanted to try a new tone. This inspired me onto the next level of extension, the means to code each txtzyme string into a named array in memory, and execute the string just by typing its name. This is an idea heavily borrowed from the idea of Forth words, but simplified to use just a single uppercase character (A-Z) as the name.
For the demonstration, I defined six user routines called A-F, each of which caused a short musical tone to be output from pin 6 of the Arduino. The code to do this is on my github gist
https://gist.github.com/anonymous/5604829
Each uppercase character defines a txtzyme array of characters which can be interpreted as though it was typed into the serial terminal buffer. For example, a musical note is defined by the following characters stored in the A array and will be invoked whenever the text interpreter encounters the character A. 6d selects digital port pin 6, and produces 75 cycles of tone. The port pin is low for 708 microseconds and then high for 708 microseconds.
char A[64] = "6d75{1o708u0o708u}";
The A array has a total of 64 characters reserved for it although only 17 are used. This is not very efficient on RAM usage, but since there are only 26 user routines, less than 1700 bytes of RAM are allocated for this storage.
I then proceeded to write similar strings for the "notes" B through to F. Once compiled, these notes could be played just by typing ABC, or any other sequence into the serial terminal.
I then defined G by the array
char G[64] = "ABCDEFFEDCBA";
To my delight, and surprise it played the sequence of 12 notes perfectly. Using musical tones to debug program flow is a neat trick, and a lot easier and quicker than counting flashes on a LED!
Another though was what happens if a word calls itself - using this example
char H[64] = "GH";
Typing H produced an infinite loop of tone sequence - not unsurprisingly.
Finally I tried an example that reads and prints the adc0 and plays a tune each time
char I[64] = "{0spABC}";
Notice how this is just a loop structure with no controlling parameter. This means that the number of times the loop is executed can be specified by typing that number before the I,
5I - perform the I sequence 5 times.
Colon Definitions
The Colon Definition is a construct borrowed unashamedly from Forth. It is the method by which new words (actions) can be defined and stored into memory. This has the advantage of not having to keep typing new stings repeatedly just to try them out, but also provides a simple means to write new code, test it and edit it until it works.
The above demonstration bypassed the need for the colon definition, by using a hard coded array of characters defined in the C code. Now it is time to bite the bullet and extend the interpreter to handle the colon definition.
The example above written as a colon definition would be written
:A6d75{1o708u0o708u};
As txtzyme ignores whitespace, this could be rewritten with spaces to make it more legible
: A 6d 75{1o 708u 0o 708u};
To handle the colon definition we need a routine that on seeing the colon, gets the next character (capital A) as the name and copies the next n characters to an array called by that name. This process ends when the interpreter encounters the semicolon.
Unfortunately, I'm not really a C programmer, so the clever use of pointers and the reference and dereference operators tends to fox me somewhat, but after an hour of some kludgy coding, I had a function that would perform the colon definition task, and assemble the definition into a named array.
In theory the name of the definition eg A, should just be an address in memory, and on typing A, the interpreter starts processing the characters that appear at that address until the newline character is encountered.
Viewing and Editing txtzyme definitions.
I also decided that the ? character would be a good way of examining the code contained within a definition, allowing cut and paste editing from the serial terminal.
So ?A prints out the entire definition of A to the terminal
:A6d75{1o708u0o708u};
To be continued.
Saturday, May 18, 2013
Txtzyme - A minimal interpretive language and thoughts on simple extensions
Imagine a very simple programming language which could run on any microcontroller with the minimum of on chip resources. A language that could invoke complex instructions and one that could be used to exercise the basic I/O functions of the microcontroller with a simple serial command interface.
I have always been a proponent of minimalist programming languages and so it was nice to encounter something new this week. A language that consists of commands invoked by single ASCII characters which allows complex procedures to be assembled from simple arrays of characters.
It reminded me of the tiny Basics and tiny Forths that were written in the late 1970s for resource limited microcontrollers.
On Thursday evening, I attended the regular OSHUG meeting (Open Source Hardware Users Group) which is held each month at C4CC near Kings Cross.
The third speaker was Romilly Cocking, who presented a report on his quick2link project - a very simple, extensible protocol for controlling sensor/actuator networks. quick2link provided the means to control an Arduino as the I/O subsystem of a Raspberry Pi project.
The Pi is limited in its I/O capabilities and so adding an Arduino to handle the I/O seems a sensible idea. To allow the Pi to control the Arduino a very simple protocol is needed, and since the Arduino is essentially a microcontroller with a serial interface, a serial command interpreter seems appropriate.
Txtzyme
quick2link was inspired by the work by Ward Cunningham (creator of the first wiki) and his minimalist txtzyme command interpreter, for controlling the I/O of simple microcontrollers.
I was intrigued by txtzyme and its simplicity and having downloaded the txtzyme interpreter for the Arduino, decided to have a play. As a simple command interpreter written in C, it compiles to just 3.6k, a very low overhead for even the smallest of today's microcontrollers.
Txtzyme allows the control of the Arduino I/O, using a simple interpreted language.
The commands are reduced to single lower case ASCII characters such as i for input and o for output. Each command can be given a single numerical parameter, limited to 65535 by the unsigned integer of the C interpreter.
The interpreter, a mere 90 lines of C code, parses a serial string, evaluating numerical characters and executing the alpha character commands.
Only a few commands are implemented, leaving a lot of scope for language extensions.
0-9 enter number
p print number
a-f select pin
i input
o output
m msec delay
u usec delay
{} repeat
k loop count
_ _ print words
s analog sample
v print version
h print help
t pulse width
Whilst appearing limited, this simple command set is essentially all that is needed to get a microcontroller project up and running.
The interpreter makes use of the Arduino functions, including Serial.read, digitalWrite, digitalRead, Serial.Println, delay, delayMicroseconds and analogRead. With these simple functions the interpreter can execute a string of commands, manipulate I/O and print results to the terminal emulator.
The hello world of the Arduino is to flash the LED. The following txtzyme string implements this efficiently:
10{1o1000m0o1000m}
This will flash the LED ten times for 1000mS on and 1000mS off.
Change the parameters a little and you can produce an audible tone to a speaker connected to an output pin.
1000{1o1m0o1m}
A quick play with the command set showed that as well as simple port manipulation, txtzyme could toggle port lines at up to 47kHz, read and display ADC channels, create tones on a piezo speaker and perform simple time delays.
txtzyme uses a compact syntax, but is nevertheless quite human-readable. The following command produces a short beep to a speaker connected to an output port
400{1o200u0o200u}
400 is the loop counter - so perform the instructions enclosed between the {..} 400 times
1o - set the designated port pin high
200u wait 200 microseconds
0o - set the designated port pin low
200u wait 200 microseconds
Extensibility
I then started thinking about how txtzyme could be extended, to include new functions, and soon had simple integer arithmetical operations working using + - * and /. There are roughly 32 printable punctuation characters in ASCII, all of which could be utilised by adding a new case statement to the interpreter and writing the code to handle each function.
The lower case characters i o m u p k s are already used in the core interpreter - so it might be sensible to reserve all lower case characters for future extensions to the core interpreter. This would leave the upper case characters to be used for User defined functions.
Txtzyme is still a rather limited language, capable of concatenating blocks of code together and performing multiple loops through code blocks. There needs to be a simple mechanism to pass numerical parameters to the code blocks and also build the if...then construct. This will clearly need some further thought in creating useful language structures whilst keeping the syntax very simple.
What txtzyme lacks is the ability to store and retrieve these simple routines. Once you have typed return at the end of the terminal text buffer the input characters are lost forever - unless you copy them to the clipboard first. For the language to be extensible, there needs to be an easy way to manage the storage and retrieval of these text strings.
One solution might be to borrow from the Forth community, and create a "colon definition" - giving each routine a single upper case alpha character name. That would allow for 26 unique code snippets and an easy way to manage/execute them - solely by typing their name.
Let's call the routine above "Beep" and assign it capital B as it's name. We could use the : ; structure to define the body of the routine in the same way a Forth word is defined. So the beep word definition becomes:
:B400{1o200u0o200u};
txtzyme allocates 64 bytes of RAM to its input buffer. A very simple addressing scheme could use the ASCII value of B, to assign a start address to the RAM segment holding the body of the code.
On encountering the first colon : the interpreter needs to switch to a colon definition compiler mode, which interprets the next character B as the start address of the buffer to hold the colon definition. It then starts storing the characters into this buffer until it encounters the closing semi-colon ;
Once this colon definition has been stored in RAM, any occurrence of the letter B is interpreted as a pointer to the buffer, from where to start executing the commands.
Whilst wasteful of unused RAM locations, this scheme would be easy to implement and allow simple routines to be stored . Regular used routines could be stored in flash as "primitives".
After a little head-scratching, I realised that I could store the txtzyme characters that perform a function in an array, and give the array a name: For example this produces a low note on a speaker connected to digital pin 6. (50 cycles of 2mS on, 2mS off)
char A[64] = "6d50{1o2m0o2m}";
In order to execute the function, I just had to pass the pointer of the array i.e. A to the txtEval function and include this case statement within the routine that evaluates the serial input buffer.
case 'A':
txtEval(A);
break;
I then wrote a couple of txts which produce a medium tone and a high tone, and assigned them to B and C.
char B[64] = "6d100{1om0o1m}"; // A medium tone beep
char C[64] = "6d100{1o500u0o500u}"; // A high tone beep
And then included their "names" in the case statements of the interpreter
case 'B':
txtEval(B);
break;
case 'C':
txtEval(C);
break;
Now it is possible to type any combination of A B and C into the serial input buffer and have the tones played in order.
These capital characters also can be inserted into loops - so to play the sequence A B C ten times, all you need is
10{ABC}
I have created txt arrays to generate 6 musical notes A - F - see my Github Gist for the code
https://gist.github.com/anonymous/5604829
In the same way that the native Arduino function calls are used to exercise the basic I/O, further library functions could be accessed and called by a single alpha character. For example S for servo control and P for pwm could be invoked with a simple numerical parameter:
160S moves the servo, connected to the nominated port pin, to 160 degrees.
128P outputs a 50% duty cycle PWM waveform on the nominated port pin.
To be continued.
I have always been a proponent of minimalist programming languages and so it was nice to encounter something new this week. A language that consists of commands invoked by single ASCII characters which allows complex procedures to be assembled from simple arrays of characters.
It reminded me of the tiny Basics and tiny Forths that were written in the late 1970s for resource limited microcontrollers.
On Thursday evening, I attended the regular OSHUG meeting (Open Source Hardware Users Group) which is held each month at C4CC near Kings Cross.
The third speaker was Romilly Cocking, who presented a report on his quick2link project - a very simple, extensible protocol for controlling sensor/actuator networks. quick2link provided the means to control an Arduino as the I/O subsystem of a Raspberry Pi project.
The Pi is limited in its I/O capabilities and so adding an Arduino to handle the I/O seems a sensible idea. To allow the Pi to control the Arduino a very simple protocol is needed, and since the Arduino is essentially a microcontroller with a serial interface, a serial command interpreter seems appropriate.
Txtzyme
I was intrigued by txtzyme and its simplicity and having downloaded the txtzyme interpreter for the Arduino, decided to have a play. As a simple command interpreter written in C, it compiles to just 3.6k, a very low overhead for even the smallest of today's microcontrollers.
Txtzyme allows the control of the Arduino I/O, using a simple interpreted language.
The commands are reduced to single lower case ASCII characters such as i for input and o for output. Each command can be given a single numerical parameter, limited to 65535 by the unsigned integer of the C interpreter.
The interpreter, a mere 90 lines of C code, parses a serial string, evaluating numerical characters and executing the alpha character commands.
Only a few commands are implemented, leaving a lot of scope for language extensions.
0-9 enter number
p print number
a-f select pin
i input
o output
m msec delay
u usec delay
{} repeat
k loop count
_ _ print words
s analog sample
v print version
h print help
t pulse width
Whilst appearing limited, this simple command set is essentially all that is needed to get a microcontroller project up and running.
The interpreter makes use of the Arduino functions, including Serial.read, digitalWrite, digitalRead, Serial.Println, delay, delayMicroseconds and analogRead. With these simple functions the interpreter can execute a string of commands, manipulate I/O and print results to the terminal emulator.
The hello world of the Arduino is to flash the LED. The following txtzyme string implements this efficiently:
10{1o1000m0o1000m}
This will flash the LED ten times for 1000mS on and 1000mS off.
Change the parameters a little and you can produce an audible tone to a speaker connected to an output pin.
1000{1o1m0o1m}
A quick play with the command set showed that as well as simple port manipulation, txtzyme could toggle port lines at up to 47kHz, read and display ADC channels, create tones on a piezo speaker and perform simple time delays.
txtzyme uses a compact syntax, but is nevertheless quite human-readable. The following command produces a short beep to a speaker connected to an output port
400{1o200u0o200u}
400 is the loop counter - so perform the instructions enclosed between the {..} 400 times
1o - set the designated port pin high
200u wait 200 microseconds
0o - set the designated port pin low
200u wait 200 microseconds
Extensibility
I then started thinking about how txtzyme could be extended, to include new functions, and soon had simple integer arithmetical operations working using + - * and /. There are roughly 32 printable punctuation characters in ASCII, all of which could be utilised by adding a new case statement to the interpreter and writing the code to handle each function.
The lower case characters i o m u p k s are already used in the core interpreter - so it might be sensible to reserve all lower case characters for future extensions to the core interpreter. This would leave the upper case characters to be used for User defined functions.
Txtzyme is still a rather limited language, capable of concatenating blocks of code together and performing multiple loops through code blocks. There needs to be a simple mechanism to pass numerical parameters to the code blocks and also build the if...then construct. This will clearly need some further thought in creating useful language structures whilst keeping the syntax very simple.
What txtzyme lacks is the ability to store and retrieve these simple routines. Once you have typed return at the end of the terminal text buffer the input characters are lost forever - unless you copy them to the clipboard first. For the language to be extensible, there needs to be an easy way to manage the storage and retrieval of these text strings.
One solution might be to borrow from the Forth community, and create a "colon definition" - giving each routine a single upper case alpha character name. That would allow for 26 unique code snippets and an easy way to manage/execute them - solely by typing their name.
Let's call the routine above "Beep" and assign it capital B as it's name. We could use the : ; structure to define the body of the routine in the same way a Forth word is defined. So the beep word definition becomes:
:B400{1o200u0o200u};
txtzyme allocates 64 bytes of RAM to its input buffer. A very simple addressing scheme could use the ASCII value of B, to assign a start address to the RAM segment holding the body of the code.
On encountering the first colon : the interpreter needs to switch to a colon definition compiler mode, which interprets the next character B as the start address of the buffer to hold the colon definition. It then starts storing the characters into this buffer until it encounters the closing semi-colon ;
Once this colon definition has been stored in RAM, any occurrence of the letter B is interpreted as a pointer to the buffer, from where to start executing the commands.
Whilst wasteful of unused RAM locations, this scheme would be easy to implement and allow simple routines to be stored . Regular used routines could be stored in flash as "primitives".
After a little head-scratching, I realised that I could store the txtzyme characters that perform a function in an array, and give the array a name: For example this produces a low note on a speaker connected to digital pin 6. (50 cycles of 2mS on, 2mS off)
char A[64] = "6d50{1o2m0o2m}";
In order to execute the function, I just had to pass the pointer of the array i.e. A to the txtEval function and include this case statement within the routine that evaluates the serial input buffer.
case 'A':
txtEval(A);
break;
I then wrote a couple of txts which produce a medium tone and a high tone, and assigned them to B and C.
char B[64] = "6d100{1om0o1m}"; // A medium tone beep
char C[64] = "6d100{1o500u0o500u}"; // A high tone beep
And then included their "names" in the case statements of the interpreter
case 'B':
txtEval(B);
break;
case 'C':
txtEval(C);
break;
Now it is possible to type any combination of A B and C into the serial input buffer and have the tones played in order.
These capital characters also can be inserted into loops - so to play the sequence A B C ten times, all you need is
10{ABC}
I have created txt arrays to generate 6 musical notes A - F - see my Github Gist for the code
https://gist.github.com/anonymous/5604829
In the same way that the native Arduino function calls are used to exercise the basic I/O, further library functions could be accessed and called by a single alpha character. For example S for servo control and P for pwm could be invoked with a simple numerical parameter:
160S moves the servo, connected to the nominated port pin, to 160 degrees.
128P outputs a 50% duty cycle PWM waveform on the nominated port pin.
To be continued.
Sunday, October 28, 2012
A Brief History of Nanode
The first Nanode on a prototyping board controls an RGB lamp
Nanode was conceived back in the summer of 2010, when I returned from a trip to Shenzhen, China. I was between jobs, and had a bit of time on my hands for tinkering with some new product ideas.
Nanode arose out of the need to find a cheaper way of connecting simple open source hardware, such as Arduino to the internet, so that Arduino could be used for a range of sensing and control applications.
The combination of an Arduino and a low cost ethernet shield came to approximately £35, and from a quick glance at the Arduino and the ethershield showed that not only could the circuit design be produced on one pcb, but produced at considerably lower cost. So with the breadboarded prototype working, I set about producing a pcb version, which using conventional through-hole components and DIL ICs, could be sold as a kit and assembled by anyone with basic soldering skills.
It was anticipated that the kits could be sold for about £20, and so ten prototypes were made to test out the pcb layout. These first ten Nanode prototype pcbs were produced and sent out to friends and enthusiasts for beta testing and application development.
A pair of Nanode Prototypes - April 2011
From the outset, Nanode was offered as a DIY kit consisting of the pcb, the ICs and some 50 other components. Assembly was fairly straightforward - and an online pictorial build guide was produced to make the assembly process as simple as possible - even for those who had had little or no previous soldering experience.
During the summer months of 2011, 550 Nanode kits were produced in the UK on green pcbs and sold out by the end of August. In September, 500 new red pcbs arrived from China changing the appearance of Nanode somewhat.
The popular Nanode 5 on a red pcb. September 2011
Following a review of the design in the Autumn of 2011, it was clear that the addition of a wireless transceiver link would considerably enhance the capabilities of the device. With a RF module onboard, Nanode could "talk" to other hardware devices such as smart sensors, extending the control and monitoring range to several tens of metres from the ethernet router. RF range tests showed a useful range of better than 125m.
The pcb was updated at the end of October 2011, so that Nanode could benefit from an RFM12 RF transceiver, and thus be compatible with JeeNodes from Jeelabs. In addition to the RF module, an extra 3V3 regulator, a miniUSB socket for power and an extra green LED were added. There were spare locations on the board to which a 32K SRAM, a real time clock and a microSD card could be added to the underside of the pcb.
Nanode RF on an early prototype green pcb.
Following the success of the first prototype above 500 Nanode RF units were produced in China on a distinctive blue pcb.
The last of these Nanode RF kits sold out at the end of October 2012. So from the humble kit beginnings and just 18 months, almost 2000 Nanodes have been produced so far, with production and kitting happening in the UK, USA and China.
500 Nanode RF kits were produced on blue pcb.
Clearly a replacement to the Nanode RF was needed, and this is where our friends at Wicked Device of Ithaca NY, stepped in.
Wicked Device had become Nanode distributors in the USA, and in 2011 had produced their own versions of the kit and pcb.
Following the requirement for a low cost ethernet gateway product for the Air Quality Egg project, Dirk Swart and Vic Aprea at Wicked Device redesigned the Nanode RF so that it utilised surface mount components, and could be mass produced on a pick and place machine. So it's my pleasure to introduce the new Nanode Gateway, the first of the Nanode SMT units, which is being produced at Wicked Device's premises in upstate New York. These units will be available through the Nanode Shop from early November.
Nanode was conceived back in the summer of 2010, when I returned from a trip to Shenzhen, China. I was between jobs, and had a bit of time on my hands for tinkering with some new product ideas.
Nanode arose out of the need to find a cheaper way of connecting simple open source hardware, such as Arduino to the internet, so that Arduino could be used for a range of sensing and control applications.
The combination of an Arduino and a low cost ethernet shield came to approximately £35, and from a quick glance at the Arduino and the ethershield showed that not only could the circuit design be produced on one pcb, but produced at considerably lower cost. So with the breadboarded prototype working, I set about producing a pcb version, which using conventional through-hole components and DIL ICs, could be sold as a kit and assembled by anyone with basic soldering skills.
It was anticipated that the kits could be sold for about £20, and so ten prototypes were made to test out the pcb layout. These first ten Nanode prototype pcbs were produced and sent out to friends and enthusiasts for beta testing and application development.
A pair of Nanode Prototypes - April 2011
From the outset, Nanode was offered as a DIY kit consisting of the pcb, the ICs and some 50 other components. Assembly was fairly straightforward - and an online pictorial build guide was produced to make the assembly process as simple as possible - even for those who had had little or no previous soldering experience.
During the summer months of 2011, 550 Nanode kits were produced in the UK on green pcbs and sold out by the end of August. In September, 500 new red pcbs arrived from China changing the appearance of Nanode somewhat.
The popular Nanode 5 on a red pcb. September 2011
Following a review of the design in the Autumn of 2011, it was clear that the addition of a wireless transceiver link would considerably enhance the capabilities of the device. With a RF module onboard, Nanode could "talk" to other hardware devices such as smart sensors, extending the control and monitoring range to several tens of metres from the ethernet router. RF range tests showed a useful range of better than 125m.
The pcb was updated at the end of October 2011, so that Nanode could benefit from an RFM12 RF transceiver, and thus be compatible with JeeNodes from Jeelabs. In addition to the RF module, an extra 3V3 regulator, a miniUSB socket for power and an extra green LED were added. There were spare locations on the board to which a 32K SRAM, a real time clock and a microSD card could be added to the underside of the pcb.
Nanode RF on an early prototype green pcb.
Following the success of the first prototype above 500 Nanode RF units were produced in China on a distinctive blue pcb.
The last of these Nanode RF kits sold out at the end of October 2012. So from the humble kit beginnings and just 18 months, almost 2000 Nanodes have been produced so far, with production and kitting happening in the UK, USA and China.
500 Nanode RF kits were produced on blue pcb.
Clearly a replacement to the Nanode RF was needed, and this is where our friends at Wicked Device of Ithaca NY, stepped in.
Wicked Device had become Nanode distributors in the USA, and in 2011 had produced their own versions of the kit and pcb.
Following the requirement for a low cost ethernet gateway product for the Air Quality Egg project, Dirk Swart and Vic Aprea at Wicked Device redesigned the Nanode RF so that it utilised surface mount components, and could be mass produced on a pick and place machine. So it's my pleasure to introduce the new Nanode Gateway, the first of the Nanode SMT units, which is being produced at Wicked Device's premises in upstate New York. These units will be available through the Nanode Shop from early November.
The new Nanode Gateway produced by Wicked Device provides a platform for the creative development of web connected devices, and with the use of low power RF, extends this connectivity well beyond the reach of normal WiFi devices.
Nanode Gateway uses low power 433MHz or 868MHz wireless to form a bidirectional link between the internet and remote sensors. Within the home and garden environment the Gateway has a range exceeding 100m. It is available with or without a radio module, which can easily be added later.
The Nanode Gateway allows you to connect sensor networks – for example environmental or weather sensors, to the internet for web based data logging and visualisation. The bidirectional wireless link allows the remote control of devices using relays or actuators providing the means for web controlled home automation.
Now it is possible to connect sensors all around your home and garden back to the internet, and control external devices using a web browser interface.
- Combines Ethernet and low power 433MHz or 868MHz wireless connectivity on an Arduino compatible platform.
- Provides a gateway for low power wireless devices to connect to the internet – with a range exceeding 100m.
- Wireless link allows monitoring and control of remote sensors and devices
- Open Source Hardware and Open Wireless Protocol used throughout.
- ATmega328 microcontroller programmed using Arduino IDE
- Supports up to 30 slave sensors or devices
- Low cost, and expandable using Arduino like shields
- Used in the Air Quality Egg and Open Energy Monitor Projects
- A building block of the Internet of Things
- Manufactured in the USA by Wicked Device.
Friday, October 26, 2012
Nanode on a breadboard - an exercise in minimalism
Nanode on a breadboard
The original Nanode was conceived as an exercise in minimalism, starting with the question "What is the least hardware needed to allow an electronic device to interact with the internet".
In the summer of 2010, I experimented with a simple design built onto a prototyping breadboard, and a few months later, in the spring of 2011, this crude prototype matured into the first pcb version of Nanode.
Yesterday, I had a bit of a tidy up around my work room, and I came across the original breadboard Nanode, so for a bit of a challenge, and some hindsight, I wondered if I could make the design even simpler.
At a very basic level, the Nanode consists of an Atmel AVR microcontroller and a Microchip ethernet controller. This combination was originally selected because they are both available in DIL packages and are thus easy to prototype with on a breadboard. Added to these ICs are the ethernet connector or magjack, a couple of crystals and a handful of passive components.
The ENC28J60 ethernet controller is a 3V3 device, and by running the micro at 3V3, the design can be significantly simplified. With the micro running at 16MHz, the design draws about 165mA at 3V3.
Four connections are needed between the ENC28J60, which make up the SPI bus. These are the MOSI and MISO data lines, the serial clock SCK and a chip select line. Additionally the ENC28J60 should be reset from a common reset line shared with the microcontroller.
With this connection between the microcontroller and the ethernet controller, the micro has 6 analogue input lines and 8 digital I/O lines available for the user's application.
The ATmega328, ENC28J60 and ethernet magjack breakout board are all available from CoolComponents if you wish to build something similar at minimum cost.
Software Functionality
The key to the functionality of the Nanode is it's ability to operate as a simple web client, connected via the internet and communicate with a cloud based server.
As a bare minimum, the Nanode should be able to post a packet of data to the server application, and request a packet of data back. The outward going packet would usually contain data from analogue sensors and the return packet often contains command and control data.
In this context the server application is likened to a mailbox, where mail between two parties can be transferred via a suitable secure box, maintained by a third party.
In the case of Nanode, we are using a server application provides by the likes of emonCMS or Cosm, where in addition to simple handling of data, the server also runs data visualisation, arithmetical processing and data manipulation applications. Having all this processing grunt available in the server, means that the code running on the microcontroller can be minimal.
As a simple example, I have the Nanode measuring outside and room temperatures using low cost thermistors connected to the analogue input channels. These temperature readings are posted up to emonCMS where the data can be graphed and visualised.
The digital output lines are connected to six LEDs, four of which also have a simple R-2R resistor ladder network connected, which makes a simple digital to analogue converter. This could be used for driving an analogue output - such as varying the brightness of an LED lamp.
The original Nanode was conceived as an exercise in minimalism, starting with the question "What is the least hardware needed to allow an electronic device to interact with the internet".
In the summer of 2010, I experimented with a simple design built onto a prototyping breadboard, and a few months later, in the spring of 2011, this crude prototype matured into the first pcb version of Nanode.
Yesterday, I had a bit of a tidy up around my work room, and I came across the original breadboard Nanode, so for a bit of a challenge, and some hindsight, I wondered if I could make the design even simpler.
At a very basic level, the Nanode consists of an Atmel AVR microcontroller and a Microchip ethernet controller. This combination was originally selected because they are both available in DIL packages and are thus easy to prototype with on a breadboard. Added to these ICs are the ethernet connector or magjack, a couple of crystals and a handful of passive components.
The ENC28J60 ethernet controller is a 3V3 device, and by running the micro at 3V3, the design can be significantly simplified. With the micro running at 16MHz, the design draws about 165mA at 3V3.
Four connections are needed between the ENC28J60, which make up the SPI bus. These are the MOSI and MISO data lines, the serial clock SCK and a chip select line. Additionally the ENC28J60 should be reset from a common reset line shared with the microcontroller.
With this connection between the microcontroller and the ethernet controller, the micro has 6 analogue input lines and 8 digital I/O lines available for the user's application.
The ATmega328, ENC28J60 and ethernet magjack breakout board are all available from CoolComponents if you wish to build something similar at minimum cost.
Software Functionality
The key to the functionality of the Nanode is it's ability to operate as a simple web client, connected via the internet and communicate with a cloud based server.
As a bare minimum, the Nanode should be able to post a packet of data to the server application, and request a packet of data back. The outward going packet would usually contain data from analogue sensors and the return packet often contains command and control data.
In this context the server application is likened to a mailbox, where mail between two parties can be transferred via a suitable secure box, maintained by a third party.
In the case of Nanode, we are using a server application provides by the likes of emonCMS or Cosm, where in addition to simple handling of data, the server also runs data visualisation, arithmetical processing and data manipulation applications. Having all this processing grunt available in the server, means that the code running on the microcontroller can be minimal.
As a simple example, I have the Nanode measuring outside and room temperatures using low cost thermistors connected to the analogue input channels. These temperature readings are posted up to emonCMS where the data can be graphed and visualised.
The digital output lines are connected to six LEDs, four of which also have a simple R-2R resistor ladder network connected, which makes a simple digital to analogue converter. This could be used for driving an analogue output - such as varying the brightness of an LED lamp.
Saturday, October 06, 2012
Upgrading a Nanode to a ATmega1284 microcontroller
One of the problems encountered with Nanode, or Arduino is that sooner or later you come up against the physical limitations of the ATmega328.
With 32K of flash and 2K of RAM, the '328 is great for small projects - but when you start to do anything that uses a lot of RAM - such as lots of string handling, the 2K limit is quickly exhausted - and strange things start to happen in your code.
So this week, my challenge was to familiarise myself with the ATmega1284, and assess whether it might be a suitable upgrade for some of my projects.
Earlier in the week, I looked at using the real time clock and SD card on the Nanode RF to make a 4 channel real time datalogger, and it was whilst developing this code, that the RAM limitations of the '328 really started to cause problems.
Fortunately, there is a fairly simple upgrade to the '328, and this is the ATmega1284P. In a 40 pin DIP package it makes prototyping on breadboard easy, and with 16K of RAM, and 128K of flash it gives plenty of space for developing larger applications.
In addition to the extra RAM and Flash, it also has two more analogue input lines, a second UART, an extra INT pin, an option for a 32KHz crystal and 8 more I/O lines.
The I/O ports are arranged almost symmetrically around the 40 pin DIP, making the circuit layout very straightforward. For reference, the ATmega1284P summary datasheet is here.
An ATmega1284 on a breadboard
The first thing to do was to build a minimum system on a breadboard consisting of the microcontroller, the 16MHz crystal, the reset circuit and a FTDI programming connector.
Above is the simple breadboard layout, with the crystal, 22pF capacitors and reset circuit at the bottom centre of the picture and the FTDI compatible programming connector at the top right of the breadboard. This is the simplest possible circuit configuration (using 16MHz external crystal and remote RESET), and it leaves all the other remaining pins as I/O.
To begin to use this microcontroller, it first has to be bootloaded with an Arduino IDE compatible bootloader, and the files which describe it's registers and physical pinout have to be incorporated into the Arduino IDE. To do this, I followed Maniacbug's excellent tutorial, and it wasn't long before I was up and running simply Blinky code on the ATmega1284.
The almost symmetrical layout of the I/O ports makes of a logical arrangement of functions. There are four 8-bit ports Port A, Port B, Port C, and Port D. Unlike the ATmega328, there is no need to devote port pins to the 16MHz crystal or reset pin - so all 32 lines are available - compared to just 20 on the '328. Additionally, there are 8 analogue input pins on Port A, and these do not share the I2C functions - as on the '328, so if you need more analogue inputs and I2C, the '1284 offers an extra bonus.
To make the '1284 compatible with the Arduino IDE, it needs to have it's physical port pins mapped to the Arduino pin numbering system. There are many unique ways in which this could be done, but I personally would prefer to have a pin-mapping that is similar to the Arduino '328 - so the likes of RX, TX, INT0, INT1 are given their familiar Dig 0, Dig 1, Dig 2 Dig 3 numbering, and the SPI bus appears on the familiar Dig 10 - Dig 13 pins. This way you can remember what is where - without having to tie your mind in mental knots trying to port sketches and libraries from the '328 to the '1284.
The Ports
Port A is the analogue input port. It appears on pins 40 down to 33 on the IC, with the related (and useful) AREF, GND and AVCC on the adjacent pins 32,31 and 30. It makes sense to bring all of these analogue pins out to a common connector. The order of A0 - A7 may appear in reverse to the Arduino user. This is not a problem as the pin mapping file can be used to reverse the order in which these pins are named. Unline the 10-bit ADC in the '328 - this ADC has an input stage with selectable gain of x1, x10 and x200, and can be used both single- ended or differentially. The high gain stage makes direct reading of thermocouples a possibility.
Pins 1 to 8 of the package are home to Port B, the upper half B4 - B7 has the hardware SPI lines present. As Nanode uses three SPI connected devices on board, it would be neat to cluster the chip select lines for these devices on the same port - so provisionally allocating Port B0 - Port B5 as CS lines seems sensible.
Port D is located on pins 14 to 21 of the package. It has our familiar pin functions like RX, TX INT0 and INT1, as well as four consecutive PWM pins on Port D4 - Port D7. If six pwm lines are required - for example driving 3 phase bridge circuits, there are a further pair of pwm channels on Port B3 and B4. There is a second UART available on Port D2 and Port D3 - if the INT0 and INT1 functions are not needed.
Port C runs along pins 22 to 29. First are the I2C pins SCL and SDA on package pins 22 and 23. These are useful for reading devices such as the real time clock on the Nanode. The ATmega1284P is also provided with a JTAG port on pins 24 to 27. If JTAG programming/debug is not needed, then these form a useful additional 4 general purpose I/O lines - but if you need JTAG, be careful what hardware you connect to them, which may interfere with the JTAG operation. You may have to disable the JTAG function in the fuse settings if you want these lines for general use.
The ATmega1284P has a second on chip oscillator - designed to work with a 32768Hz watch crystal - or other 32KHz input. These crystal pins are on pins 28 and 29. If you use a watch crystal to implement an RTC - it is possible to wake the microcontroller from sleep at regular intervals, whilst otherwise keeping it in low power mode.
In addition to the rich peripheral set accessed by the ports, the ATmega1284P also has an additional 16 bit timer, and 4K of E2 non-volatile memory.
Connecting it up to a Nanode.
Having made up the simple breadboard, it was time to connect it up to a Nanode.
Most of the Nanode ICs are connected to the microcontroller using the SPI bus, and so the MOSI, MISO, SCK and any chip select lines would be needed. The RTC clock/calendar IC on the Nanode uses the I2C bus, so SCL and SDA would be needed too. Finally the Nanode board would need to be powered, and provide a reset so +5V, 0V and RESET were wired back to the breadboard.
During tests it was found that the ATmega1284 would run at 3V3, but not program successfully at 3V3. It was therefore decided to run the '1284 at 5V, and use potential divider resistors on all the output lines between the '1284 and the Nanode RF board where almost all of the hardware runs on a 3V3 supply i.e. the ENC28J60, the RFM12 and the SDcard.
Dividers were thus needed on MOSI, SCK, and the three chip selects ENC28J60_CS, RFM12_CS and SDcard_CS. The RTC connected to the I2C bus is 5V tolerant and so no divider was needed.
In the top photograph, the lower breadboard made from clear plastic has these potential divider resistors - and some diagnostic LEDs. The Nanode Rf with the '328 microcontroller removed is on the right.
The next blog post in this series will have links to code developed to run the Nanode RF using the ATmega1284.
Subscribe to:
Posts (Atom)








