Special I/O Commands Intro Edit

This chapter includes specialized input/output commands such as those for A/D conversions, generating audio tones, controlling LCD displays, stepper motors, servos, etc.

This chapter contains the following sections:

  • Special I/O Commands
    • ADin
    • Button
    • Count
    • RCTime
    • EnableHservo
    • Hservo
    • HservoWait
    • GetHservo
    • Servo
    • Mservo
    • Spmotor

Conventions Used in this Chapter Edit

{ ... } represent optional components in a command. The { } are not to be included.
[ ... ] used for lists - the [ ] are required.
( ... ) used for some arguments. The ( ) are required.

Important: Several of the commands described in this chapter specifically address hardware features of the microcontroller chip. Descriptions of these hardware features are beyond the scope of this manual.

Please refer to the H8/3664F or H8/3687F hardware manual, available at for further details.


Sets up the hardware A/D converter and stores the resulting value in a variable. The resolution is 10 bits.

Important: The ADIN command uses the microcontroller's built-in A/D hardware. A description of this hardware is beyond the scope of this manual. Please refer to the H8/3664F or H8/3687F hardware manual (see page 135).


adin pin,var
pin is a constant or variable specifying the analog pin to use for the A/D input. Available pins are:
AtomPro 24-M P0 - P3
AtomPro 28-M P0 - P3 and P16 - P19
var is a variable (word or long) that stores the returned value from the conversion (10 bit resolution).


The ADIN command converts an analog (0 - 5V) signal to a digital value from 0 - 1023. The input can be scaled by using a reference voltage (Vref).


volts var word
adin 1,volts

will convert an input voltage (0 - 5V) on pin 1 to a digital value of 0 - 1023 and store the result, right justified, in word variable "volts". The first 6 bits of "volts" will be zeros.


Processes a momentary switch contact, such as a button press. Includes debouncing and auto-repeat. The BUTTON command should be used in a program loop so that it is repeatedly accessed.

Note: Note that all timing (except debounce) for the BUTTON command is set by counting program loops, so some experimentation may be required to find the best values.


button pin, downstate, delay, rate, loopcounter, targetstate, target
pin is a variable or constant the specifies the I/O pin to be used. Pin will be set to an input automatically.
downstate is a variable or constant (value either 0 or 1) that specifies the logical state of the pin when the button is pressed. 0 = low, 1 = high. This lets you use normally open or normally closed buttons.
delay is a byte variable or constant (0 - 255) that specifies the number of program loops to execute before first entering the auto-repeat sequence.
  • If delay is set to 0 both debounce and auto-repeat are disabled.
  • If delay is set to 255 debounce is enabled, but autorepeat is disabled.
rate is a byte variable or constant (0 - 255) that specifies the number of program loops to execute before auto-repeating, after the initial delay has expired.
loopcounter is a byte variable used to store the current number of program loops. This variable must not be used for any other purpose within this program loop. If more than one BUTTON command is used in your loop, you must specify a different loopcount variable for each.
targetstate is a variable or constant (0 or 1) that determines the logical state of the button for a branch to target to occur. 0 = not pressed, 1 = pressed. (Pressed and not-pressed are defined by downstate.)
target is a label to which execution will branch if the button is in targetstate and debounce, delay and rate conditions are met.


BUTTON checks the state of an I/O pin connected to a switch and branches according to the result. BUTTON is actually just a form of conditional branch; it does not produce any numeric result or save any values.

For the following notes, assume that the BUTTON parameters have been set to see a LOW state as downstate and to branch when the button is pressed (down). BUTTON is executed within a loop.

  • Not pressed. If the button is not pressed, loopcounter is reset and control simply passes to the next program statement. After the following statements are executed, control must be returned to the start of the loop.
  • First press. If the button is pressed for the first time (i.e. the previous loop pass showed it as not pressed), BUTTON first does a debounce check.
    • If debounce fails (i.e. the button wasn't actually pressed), control passes to the next program statement as above.
    • If debounce passes (i.e. the button is really pressed) BUTTON branches to the statement defined by target. Loopcounter is also incremented for use by the auto repeat function. The sequence of commands following target must return to the start of the loop.
  • Repeat delay. If the button is still pressed the next time BUTTON is encountered (i.e. on the next pass through the loop), loopcounter is again incremented. If loopcounter has reached the value specified by delay execution will branch to target and loopcounter will be reset. If loopcounter has not reached this value, it will be incremented and execution will continue with the

following program statement.

  • Auto-repeat. If the repeat delay has expired, the sequence of steps under "Repeat delay" will be executed, but using the rate value for loopcounter, rather than the delay value. This lets you

set the initial delay and the repeat rate independently.


Mechanical buttons often close and reopen many times (sometimes hundreds of times) before stabilizing in the pressed position. This is because of mechanical vibration of the components of the button. To avoid having BUTTON see these intermittent cycles as many button presses, it has a built-in debounce feature.

When BUTTON sees a valid downstate for the first time, it delays approximately 20 ms and checks again. If the downstate is still valid, it assumes that the button is really pressed and continues processing. If downstate is no longer valid, this could be the result of a bounce so it is ignored and control passes to the next program statement.

If the button really was pressed, the next execution of the BUTTON command will show a valid downstate and processing will continue as above.


delay var byte
rate var byte
count1 var byte
count2 var byte
   button P4,0,delay,rate,count1,1,right
   button P5,0,delay,rate,count2,1,left
goto startloop
   ;code to rotate to the right
goto startloop
   ;code to rotate to the left
goto startloop

This program will check two buttons, one for right on pin 4, the other for left on pin 5. The buttons are normally open, closed when pressed, so they pull the pins LOW when pressed. Depending on which button is pressed, a stepper motor (or other device) will be caused to turn left or right.

The two BUTTON commands use different loopcount variables, count1 and count2.

Note: This program does not include code to deal with simultaneous pressing of the two buttons.


Counts the number of cycles (0 - 1 - 0) on an input pin during a specified time period. Used to determine frequency. The minimum pulse width that can be counted is 4 µs.


count pin,period,cycles
pin is a variable or constant that specifies the input pin to be used. This pin is automatically set to input mode.
period is a variable or constant that specifies the counting time in milliseconds.
cycles is the variable in which the total count will be saved. Cycles must be large enough to store the highest expected number of cycles.


total var word
count p3,10,total

Will count the total number of 0-1-0 transitions on I/O pin 3 for 10 ms, and store the result in "total". For instance, if the input frequency was 50 kHz, the count would be 500 (± 1 count).


Measures short time intervals, such as the charge/discharge time of an R/C circuit.


rctime pin,state,{timeoutlabel,timeout,}result
pin is a variable or constant that specifies the I/O pin to use. This pin will be placed into input mode and left in that mode when the instruction finishes.
state is a variable or constant (1 or 0) that specifies the state which will end the timing period.
TimeoutLabel is a program label. If the command times out before the pin state changes, execution will continue at this label. The default timeout is 65535 µs. If no TimeoutLabel is specified, program execution will continue with the next statement in the event of a timeout.
Timeout is a 32 bit value that specifies the timeout in 0.5 µs units.
ResultVariable is a variable in which the time measurement, in µs, will be stored. This variable must be large enough to store the maximum value set by TimeoutMultiplier.


Warning: For those users who are converting code from a Basic Stamp to run on the Basic Atom Pro, The semantics of the state parameter is different.

RCTIME can be used to measure the value of capacitors or resistors, as well as to make other triggered timing measurements. One common use is to measure a potentiometer setting.


Figure 20 - Measuring time with RCTIME

With a circuit similar to that shown in Figure 20 the RCTIME command is used as follows:

  1. Set the I/O pin to be an output and set it high.
  2. Wait long enough for the capacitor to fully charge. About 5 time constants (i.e. 5 x R x C) will do nicely. (The "time constant" of an R/C circuit is the time for it to charge to 63.2% of the applied voltage, or to discharge to 36.8% of the initial voltage. It is calculated using the equation T = R * C where R is in ohms and C is in farads.)
  3. Issue the RCTime command, which will switch the pin to an input and "watch" the voltage as the capacitor discharges through the variable resistor.

From the resulting time, the resistor or capacitor value can be calculated (you have to know at least one of them accurately if absolute, rather than relative, results are required).

To help in your calculations, here's some information about the BasicATOM Pro's I/O pins:

Approximate voltage to switch from low to high state on a rising input 2.05V
Approximate voltage to switch from high to low state on a falling input 0.80V

It takes about 1.83T (where T is the time constant) for the circuit to discharge enough to trigger the RCTime command. This means that the time constant = ResultVariable / 1.83. A sample calculation is shown below under Examples.

Note: It's very convenient that the time constant equation also works perfectly if time is in µs and capacitance is in µF.


This program assumes that the circuit shown in Figure 20 is used, with the variable resistor set to about the mid point of its rotation. Some scaling is done to allow integer arithmetic to be used.

dtime var word
resist var word
high P3
pause 10 ; wait for capacitor to charge
rctime P3,0,dtime
resist = (10000*dtime)/(183*2) ; see text below

The program sets P3 to output, high state, and then waits 10 ms for the capacitor to charge fully. The RCTIME command then changes P3 to an input and waits for a low state, which occurs when the capacitor discharges to about 0.8V. The time, in microseconds, is stored in dtime.

The resistance is then calculated using the formula:

resistance = dtime/(1.83 * capacitance)

However, to accommodate the integer arithmetic, the 1.83 and capacitance are each multiplied by 100 (giving 183 and 2, respectively), so the numerator must be multiplied by 10000 to compensate. These steps could be avoided by using floating point calculations, if desired, at the expense of program complexity and calculating time.

In the example, if dtime is 1830, the value of the resistance comes out to be 50000 ohms.

Important: In most cases an absolute value won't be needed, only a relative position of the variable resistor, so the resistance calculation can be simplified.


Enables the hardware servo control system and specifies its parameters of operation.




ENABLEHSERVO is a compile time directive that tells the compiler to add support for the hardware servo control system. The HSERVO system uses the TimerW (or TimerZ0 in ATOM-Pro Plus) to produce interrupt driven signals for up to 32 servos.

ENABLEHSERVO has no arguments.


Sets the position and speed of up to 32 servos. Before using this command the ENABLEHSERVO compile time directive must be included in your program.


HSERVO [Pin\Pos\Spd....PinN\PosN\SpdN]
Pin...PinN are expressions that specify the pin numbers connected to the servos whose position and speed are to be set.
Pos...PosN are expressions that specify the desired positions for each of the specified servos (range -12000 to +12000).
Spd...SpdN are optional expressions that specify the speed used to move each servo to its new position (default 255).


The HSERVO command is a background timer interrupt driven command. It allows you to set the new position and speed to move to that position of up to 32 servos at one time. Each servo set will start moving to its new position imediately after the HSERVO comand finishes.

To deactivate a servo that has been used set its Pos to -16000.


HSERVO P1\2000\100,P2\-1000\100


Waits for specified servos to reach position before continuing.


HSERVOWAIT [pin#,pin#,...]
Pin# is an expression that specifies the I/O pin number to which the servo is connected.


HSERVOWAIT pauses program execution until the specified servos have reached the postions set by the HSERVO instruction.


Get the current position of the specified servo. Optionally determine whether the servo is idle or not.


GETHSERVO pin,position{,idle}
Pin is an expression that specifies the I/O pin number on which to check servo position.
Position is a variable where GETHSERVO will store the current position (-12000 to +12000, center = 0) of the specified servo. (Most servos will not reach the maximum values shown.)
Idle is an optional variable where GETHSERVO will store the current state of the servo. A value of $FFFFFFFF means the servo is idle (at its final position).


Gethservo is used to determine the current position of a servo and whether it has finished moving to its final position.


getservo p0,pos


getservo p0,pos,idle

If the servo is at its new position "idle" will be a non-zero number. If the servo is still moving to its new position then "idle" will equal 0.


Operates a servo motor.


servo pin, rotation{, repeat}
pin is a variable or constant that specifies the I/O pin used to control the servo.
rotation is a variable or constant that specifies the position to which you want the servo to rotate. The value of rotation should fall within the limits of -2400 to +2400*, with 0 being the center position. See the Notes below for a discussion of servo motors.

Important: *Exceeding these values could damage your servo.

repeat is an optional variable or constant that specifies the number internal cycles the command runs (default = 20). This value must be high enough for the motor to reach the desired position, so higher values may be required for larger angles. Repeat allows the servo to reach the desired position before

the program continues and perhaps sets a new position.


Servo motors are controlled by a pulse width modulated signal that is applied repeatedly at 20 ms intervals as long as the motor remains under control. The pulse width varies from 0 to 3 ms (this is standard for servo motors). Values from 0 to 1.5 ms rotate the motor to the left, values from 1.5 to 3.0 ms rotate it to the right. A pulse width of 1.5 ms sets the motor to the center of its rotation. These values are set by adjusting the rotation parameter (see above). (Values of -1200 to +1200 don't actually cover the full 0 to 3 ms pulse width range. They are restrained at both ends to prevent over-rotation of the servo, which could cause damage.)

The amount of rotation varies with different motors, from about 90 degrees to 270 degrees total. You may have to determine this amount by experiment if you don't have access to data sheets.

The control signal must be continuously applied or the motor will drift from its set position (i.e. it won't generate any torque with no signal). This implies that the SERVO command should be used in a program loop.

Since servo motors take time to reach the set position, the SERVO command repeats the pulse output for a sufficient time. Depending on the individual servo motor, and the amount of rotation change required, you may have to adjust the repeat parameter for the command.

For reference, the following wire colors are used by different manufacturers:

Manufacturer Power (+5V) GND (Vss) Control
Airtronics red black brown
Futaba J red black white
KO Propo red black blue
Kyosho/Pulsar red black yellow
Japan Radio (JR) red brown orange


pos var word
   ;code to determine desired position
   servo P4,pos,50
goto setpos

This simple program controls a servo connected to P4. The desired position may be determined by any number of different input factors, depending on the application. Since the 20 ms control sequence is repeated 50 times, the position may only be changed about once per second.


Operates multiple servo motors. Similar to SERVO.


servo1{\servo2{\servo3{\servo4{\servo5{\servo6{\servo7{\servo8{\servo9{\servo10{\servo11{\servo12}}}}}}}}}}}{, repeat}
Pin is an expression that specifies the pin number controlling servo1. All other servos are controlled by the next pin (i.e. servo2, pin+1, servo3, pin+2 etc...)
Servo# is an expression that specifies the position to which you want the servo to rotate. A value from -2400 to +2400* is used with 0 being center. The maximum +2400 and minimum -2400 will vary based on the servo being used.

Important: *Exceeding these values could damage your servo.

Repeat (optional) Specifies the number of internal cycles the command runs (defaults to 20).


The MSERVO command is similar to the SERVO command except that it operates more than one servo motor. MSERVO is a foreground task.

Note: See the SERVO command (page 160) for more detail on MSERVO parameters and the operation of servo motors.


MServo p0,0,-1000,1000

Assumes three servos are attached to P0,P1 and P2. The pin argument specifies the first pin used.


Operates a stepper motor.


spmotor pin,delay,step
pin is a variable or constant specifying the lowest numbered of 4 output pins used. For example, if pin = P0, pins 0, 1, 2 and 3 will be used.
delay is a variable or constant (0 - 65535) that specifies the delay in milliseconds between steps. The delay controls the speed at which the stepper motor operates.
step is a variable or constant (-32682 to +32682) that specifies the number and direction of steps the stepper motor will execute. With correct wiring, positive values are clockwise, negative values are counterclockwise.


Stepper motors are precision devices that are used to control position or rotation in small increments. Each step moves the motor an absolute, predetermined amount (the amount varies with different stepper motors and may be determined by experiment, or by referring to the manufacturer's data sheets). Stepper motors are commonly found in XY positioning tables, graphing devices, disk drives, laser printers, etc.

Stepper motors may be unipolar or bipolar. Bipolar motors require slightly more complex control circuitry. Typically, unipolar steppers have 4 wires, bipolar have 5 wires.

Note: The SPMOTOR command supports both unipolar and bipolar stepper motors. Wiring for bipolar motors is not described in this manual.

Since the inductive load of a stepper motor may exceed the ratings of the BasicATOM Pro, it should be driven using a buffer amplifier. The most common device for this purpose is the ULN2803A Darlington array, which includes protective diodes for inductive loads.

A sample circuit using a ULN2803A is shown below. Further circuit design and determining the correct wiring of the stepper motor are beyond the scope of this manual. Experimenting to find the right connections is a bit tedious, but you won't damage the motor by doing so.


Note: Data sheets and application notes for the ULN2803A are available on the internet: a quick search will let you find many resources.


delay var word
step var sword
delay = 50
step = -60
spmotor P0, delay, step

will cause the stepper motor to make 60 counterclockwise steps at intervals of 50 ms.