To format for printing, click here.
Handy Cricket Programming Reference
The Handy Cricket is programmed in a language called Cricket Logo, which is a simplified version of the powerful yet easy-to-learn Logo language.
Cricket Logo has the following features:
Cricket Logo Screen
The Cricket Logo screen is shown above.
The text area in the lower left is the Command Center. Statements typed into this window are immediately transmitted to the Cricket and then executed. In the screen image, the primitive beep is shown. This command causes the Cricket to emit a short chirp.
The text area on the right is for programs, and is labeled Cricket Logo Programs. In Cricket Logo, individual procedures are defined using to and end syntax. In the example screen above, the procedure demo turns on motor A for two seconds, beeps, and then reverses the motor direction (for the next time its turned on).
The one-line text area at the top left of the window is the Run This line. When programs are downloaded, any statement typed into this area will be run when the Crickets Run/Stop button is pressed. You would normally put the name of the procedure you want to run here.
To download your programs, click the Download button. This causes all procedures written in the procedures area to be downloaded to the Cricket.
Then, run the program by pressing the Run/Stop button on the Cricket. In this example, the demo procedure would then be run.
After downloading, you can also run a program by typing its name into the Command Center. Hit the Return key and the Cricket will run the code on that line.
The Cricket has two motors, which are named A and B. A bi-color LED indicates the state of each motor.
Motor commands are used by first selecting the motor (using a, b, or ab,) and then telling it what to do (e.g., on, off, rd, etc.).
Timing and Sound
The timing and sound primitives are useful to cause the Cricket to do something for a length of time.
TimingWith the wait primitive, one can cause the Cricket to do nothing, thereby causing for a certain amount of time to pass by. While the Cricket is idling in this fashion, motors may be left on, so, for example:
ab, on wait 20 off
will turn the motors on for two seconds. This is equivalent to:
ab, onfor 20
There is also a free-running timer, which keeps track of elapsed time even when the Cricket is doing other things. Two primitives are available for using the timer: resett, which resets the timer to zero, and timer, which reports the current value of the timer.
The table below summarizes the wait, timer, and resett primitives.
The Cricket has a built-in piezo beeper which may be used to play simple tones. There are two primitives for making sound: beep, which generates a short beep of fixed length and pitch, and note, which takes duration and pitch inputs:
For example, note 119 5 will play a middle c for half a second.
Please note that there are two different reference values for timing: 0.1 second units, used in wait, onfor, and note, and 0.004 second units, used in timer.
The beep command is equivalent to note 63 1.
The Cricket has two sensor ports, named A and B. Various devices may be plugged into these sensor ports, including:
There are two types of primitive for reporting the value of a sensor plugged into a sensor port: switch, which reports a true-or-false reading (assuming a switch-type sensor), and sensor, which reports a numerical reading (from 0 to 255) depending on the sensor's value:
Cricket Logo supports a small but useful set of control forms. These consist of loop structures, conditionals, a busy-wait form, and primitives for early termination of procedure execution.
The following table summarizes Cricket Logo's control structures:
The following procedure makes the motor A output flip back and forth ten times:
to flippy repeat 10 [a, onfor 10 rd] end
Here are two ways to make the motor A flip back and forth continuously:
to flippy-forever-1 loop [a, onfor 10 rd] end to flippy-forever-2 a, onfor 10 rd flippy-forever-2 end
The second method, which avoids the use of the loop form, is more efficient, because the compiler recognizes it as tail recursion and optimizes it as a goto.
The following procedure turns on motor A, waits for switch B to be pressed, and then turns off the motor:
to on-wait-off a, on waituntil [switchb] off end
The following procedure repeatedly tests the state of switch B. If it's pressed, the motor is made to go on in the thisway direction. If the switch is not pressed, the motor goes in the opposite direction:
to switch-controls-direction a, on loop [ ifelse switchb [thisway][thatway] ] end
The Cricket has a 16-bit number system. Numbers may range from -32768 to +32767.
All arithmetic operators must be separated by a space on either side. Therefore the expression 3+4 is not valid. Use 3 + 4.
Normal expression precedence rules are not used by the compiler. Instead, operators are evaluated in the order they are encountered from left to right. Thus:
3 + 4 * 5
evaluates to 35, because the compiler first acts on the 3 + 4 and then multiplies this sum by 5.
Parentheses may be liberally applied to get expressions to evaluate how you intend them. E.g.:
(3 + (4 * 5))
yields 23.The following table lists the operators provided in Cricket Logo:
Procedures, Inputs, and Outputs
A procedure is defined using the to keyword, followed by the procedure name, followed by the procedure body, followed by the end keyword. For instance, the following defines the procedure flash, which turns the motor A output on and off 10 times:
to flash repeat 10 [a, onfor 5 wait 5] end
Procedures can be defined to accept inputs, which then become local variables inside the procedure. This is done using the colon character : as shown below. In this example, the flash procedure is given one input, which is then used as the counter in the repeat loop:
to flash :n repeat :n [a, onfor 5 wait 5] end
Then one can use this procedure with (e.g.) flash 5, flash 10, flash 20, etc.
Here an example of a procedure with two inputs:
to flash :times :delay repeat :times [a, onfor :delay wait :delay] end
There is no built-in limit to how many inputs a single procedure may have.
Procedures may return values with the output primitive. In the following example, the detect procedure returns a value of 0, 1, or 2 depending on the value of sensor A:
global [temp] to detect settemp sensora if temp < 30 [output 1] if temp < 50 [output 2] output 3 end
The global variable temp is defined. In the detect, a reading of sensor A is loaded into temp. If the reading is less than 30, then a 1 is returned. If the reading not less than 30, then the next test executes, and if the reading is then less than 50, a 2 is returned. If this test fails, then a 3 is returned.
Care should be taken to ensure that if a procedure sometimes produces an output, that it always does. In a procedure that is capable of producing an output, the Cricket will crash if an execution path that does not produce an output is travelled.
Global variables are created using the global [variable-list] directive at the beginning of the procedures buffer. E.g.,
global [cats dogs]
creates two globals, named cats and dogs. Additionally, two global-setting primitives, setcats and setdogs, are instantiated. Thus, after the global directive is provided, one can say
to set the value of cats to 3, and
setcats cats + 1
to increment the value of cats.
Global variables are stored in RAM, so their contents are lost when the Cricket is turned off. To save data when the Cricket is turned off, please use the data recording and playback functions, or the global array functions. Both of these store data in the Cricket's non-volatile memory.
Global arrays are created using the array primitive at the beginning of the procedures window. For example,
array [clicks 10 clacks 15]
creates two arrays, one named clicks, which can hold 10 numbers, and another named clacks, which can hold 15 numbers.
Elements in the array are accessed using the aget primitive and written using the aset primitive:
Array indices start at 0. So, for example, aset clicks 0 17 sets the first element of clicks to have a value of 17, and send aget clicks 0 causes the value of that element of clicks to be transmitted via infrared.
There is no error-checking to prevent arrays from overrunning their boundaries. Arrays are stored consecutively in memory as the order they are defined, so (continuing the example) if did an aset clicks 10 17 you would actually be writing a 17 into the first element of clacks (since the index values for clicks should run from 0 to 9, inclusive).
Array values are stored in the Cricket's non-volatile memory, so their contents are preserved even when the Cricket is turned off.
Data Recording and Playback
There is a single global array for storing data which holds 2500 numbers.
For example the procedure take-data can be used to store data recorded by a sensor once every second:
to take-data resetdp repeat 2500 [record sensora wait 10] end
To transfer data to the PC, use the standard Cricket Logo software. In the Cricket menu, there is an option Upload Data. This will bring up a dialog box that allows you to retrieve the data from the Cricket and then save it into a text file. This text file can be imported into a spreadsheet for analysis and graphing.
Please note that there is no error checking to prevent against recording too many data points and thereby overrunning the data buffer.
Please note that recorded values are stored as 8-bit values (0 to 255); if you try to record a number greater than 255, only the lower byte (remainder when dividing by 256) will be recorded.
The Cricket supports recursionthat is, procedures that are defined in terms of themselves.
For instance, the mathematical definition of the factorial function is that the factorial of n is equal to n times the factorial of (n - 1), with the factorial of 1 being 1. This idea may be expressed in Cricket Logo as:
to fact :n if :n = 1 [output 1] output n * fact :n - 1 end
To try this out, download the procedure and then type into the Cricket's command center:
repeat fact 3 [beep wait 1]
You should hear six beeps, since the factorial of 3 is 6.
Please note that the memory for keeping track of recursive calls during execution is quite small, and limited to perhaps six calls deep. If the stack overflows, the Cricket halts and beeps five times.
Tail recursion is a special case of recursion when the very last instruction at the end of a procedure is the recursive call. The Cricket supports tail recursion, converting the recursive call into a goto statement, and avoiding the stack depth problem just mentioned.The following procedure illustrates correct use of tail recursion, creating an infinite loop:
to beep-forever beep wait 1 beep-forever end
The Cricket supports a limited form of multi-tasking. In addition to the conventional thread of execution, the Cricket can have one background task. This task repeatedly checks a condition. When this condition becomes true, the task interrupts foreground activity and processes its special action. When the background task's action finishes, execution picks up where it left off in the foreground activity.
The background task is started up using the when primitive. For example, consider the following line of code:
when [switcha] [beep] loop [a, onfor 5 rd]
In this example, the background task is looking for the condition switcha. When this becomes true (e.g., a switch plugged into sensor port A is pressed), then the action is run, and the Cricket beeps. Concurrently, the Cricket executes an infinite loop, turning motor A on for a 1/2 second and then reversing its direction.
Please note a few details about how this is happening:
Crickets can send infrared signals to each other using the send primitive and receive them using the ir primitive. The ir primitive reports the last value received. A third primitive, newir?, reports true when an IR byte has been received but not yet retrieved.
As an example, consider the following pair of procedures. The first procedure, called sender, will run on one Cricket, and generate numbers which are sent to a second Cricket. Here, the sender procedure randomly sends a 0, 1, or 2:
to sender send random % 3 beep wait 30 sender end
The expression random % 3 produces a 0, 1, or 2, using the remainder-after-division operator. This value is sent using the send primitive. Then the procedure beeps and waits 3 seconds before sending a new number.
On a second Cricket, a receiver procedure, doit, will receive these numbers and either turn on motor A, motor B, or both motors depending on the value it gets:
to doit waituntil [newir?] if ir = 0 [a, onfor 10] if ir = 1 [b, onfor 10] if ir = 2 [ab, onfor 10] doit end
Please note that the Cricket system uses values 128 through 134 for low-level operations between Crickets. So it's best to not deliberately send those values around, because Crickets that are sitting idle (turned on, but not running a program) will interpret those codes and possibly overwrite their memory.
When the Cricket is idle, pressing its pushbutton causes it to begin executing remote-start line 1 on the Cricket Logo screen.
When the Cricket is running a program, pressing the button causes it to halt.
|low-byte val||Reports the low byte of the argument; equivalent to val % 256 but significantly faster.|
|high-byte val||Reports the high byte of the argument; equivalent to val / 256 but significantly faster.|
|eb addr||Examine Byte reports the value located at memory location addr. On the Handy Cricket v1.5, memory begins at address 0 and ends at address 4095 (decimal).|
|db addr val||Deposit Byte reports the byte val into Cricket memory at location addr. Warning: it's easy to over-write Cricket program memory using this command, causing software crashes.|
|bsend val||Bus Send sends the low byte of val over the Cricket peripheral bus. If bit 8 is set, marks the communication as a command byte.|
|bsr val||Bus Send Receive sends the low byte of val over the Cricket peripheral bus and waits up to 1/4 second for reply. Reports reply value or 1 if timed out. If bit 8 of val is set, marks the outgoing communication as a command byte.|