Tutorial #10 - Serial Communication

copyright, Peter H. Anderson, Baltimore, MD, Jan, '98

Introduction.

This tutorial deals with serial communication between the Stamp and other devices. The discussion presents some basics and illustrates how to interface the Stamp with a PC or other terminal device and how to interface with such serial devices as a serial LCD and our popular 8-channel temperature measurement unit.

In addition to the SERIN and SEROUT commands, the COUNT and LOOKDOWN commands are presented.

Throughout the discussion, I have attempted to weave in a number of weather related applications.

Serial communication is a very large subject and this tutorial doesn't begin to scratch the surface. Rather I have tried to concentrate on straight forward applications while bringing out some points which are not obvious.

Some Basics. (See Figure #1).

In the idle state the serial transmit line is at a logic one. In sending a character, the line is brought to a logic zero for one bit time. This is referred to as the start bit. The 8-bit ASCII representation of the character is then sent beginning with the least significant bit, followed by the stop bit which is a logic one. Note the state of the stop bit is the same as that for the idle condition.

For example; consider the character "S" which is $51 or 0101 0001;

     1 1 1 1 0 1 0 0 0 1 0 1 1 1 1 1
     ^ idle  ^ ^             ^ ^ again idle
             | |             | stop bit
             | 8 - bit ASCII beginning with least significant bit
             | start bit

Many PC terminal emulators permit you to specify whether you desire one or two stop bits. In interfacing with the Stamp, it may be set to either. Note that the stop bit state is the same as the idle and thus one might think of the stop bit designation as being the minimum time to idle between sending characters. If your program is waiting for a user to enter a character from the keyboard, the TX line is idle (at a logic one).

A bit time is the inverse of the baud rate. For example, at 9600 baud, each bit is 1/9600 or 104 usecs.

Logic Levels. (See Figure #2).

With TTL, a logic zero is defined as being near ground and a logic one as being near +5V.

However, the RS232 standard provides for sending the data using EIA levels where a logic zero is greater than +3 VDC and a logic one as being less than -3 VDC. Note the apparent backwards nature which is a carry over from the days of early mechanical teletype communication.

This TTL to RS232 level conversion is commonly performed in a PC using such integrated circuits as the Motorola MC1488 quad line driver and the RS232 to TTL conversion using a MC1489 quad line receiver. (This tutorial discusses the MAX232).

Thus, the RS232 logic one idle state is less than -3 VDC and more typically between -10 and -12 VDC. The start bit (logic zero) causes the TX line to go to greater than +3 VDC and more typically to +10 to + 12 VDC

Note that on the TTL side, a logic zero and logic one are indeed, near ground and near +5 VDC. With a TTL zero into an EIA transmitter, the level at the output of the transmitter is greater than +3 VDC. However, the EIA receiver converts this to a TTL logic zero.

See Figure #3.

In interfacing with some peripherals such as a serial LCD display an RS232 receiver is replaced with a series limiting resistor so as to protect the PIC in the peripheral from the RS232 potentials. Note that in such cases, an RS232 logic zero (greater than +3 VDC) is seen by the TTL logic in the interfacing PIC as a logic one, and similarly, an RS232 logic one (less than -3.0 VDC) is seen by the TTL as a logic zero. In such cases, the PIC performs the inversion in software and such peripherals are referred to as "inverting". This is discussed in greater detail when discussing the interfacing of a Stamp with a serial LCD.

Stamp to PC Interface. (See Figure #4).

Any of the 16 I/O terminals P0 through P15 may be used as either a serial output or serial input. However, these are all TTL logic levels.

In addition, the Stamp terminals normally associated with downloading and debugging programs may be used and this is particularly important as the TTL to RS232 and RS232 to TTL level conversion circuitry is already provided.

The Stamp uses the circuitry shown in Figure #4 to download and debug programs. It is noteworthy as the circuitry "borrows" the less than -3.0 VDC potential required for an EIA logic one from the PC or other terminal device.

Parallax's Stamp 2 development program uses the PC's data terminal ready lead (DTR) to momentarily bring the PIC's reset lead low, thus resetting the Stamp prior to downloading the file. Normally the PC's DTR lead is at a logic one, less than -3.0 V, and thus transistor Q1 is off and the PIC's reset lead is high. In downloading a program, the Stamp 2 program causes DTR to momentarily go to a logic zero (greater than +3 Volts), thus turning on transistor Q1 and resetting the Stamp.

Note that on the Stamp data receive side, the PC's TX lead is normally at a logic one (greater than +3.0 VDC) which turns on NPN transistor Q2, causing a TTL logic zero to appear on the RX terminal of the PIC. An EIA logic one (less than -3V) causes the transistor to turn off, and thus a TTL logic one appears on the RX terminal of the PIC (+5 VDC through 4.7K).

Now, looking at the other side, when the Stamp's PIC TX terminal is at a TTL logic zero, PNP transistor Q3 is on, and +5 VDC appears on the PC's receive lead. Note that this meets the greater than +3 volt requirement for an EIA logic zero. When the Stamp's PIC TX terminal is at a logic one, transistor Q3 is turned off and the voltage appearing on the PC's transmit lead is gated to it's receive lead. Of course, when idle, the PC not transmitting and this is less than -3.0 V (logic one). Thus, Q3 is either gating +5 VDC or the potential on the PC's transmit lead.

This is particularly important. If the application calls for the Stamp to only send to the PC terminal, one might be tempted to connect only the RX_D lead from the PC (and of course, ground). However, the TX_D lead must also be connected so as to provide the negative voltage source.

Figure #5 illustrates how the PC - Stamp interface normally used for downloading and debugging may be simply modified so as to use the PC as a serial terminal device. Note that in the download mode, the Stamp 2 development program uses an unconventional loop back of request to send (RTS) to data set ready (DSR) and uses the DTR lead to reset the Stamp. In the terminal mode, RTS is looped back on clear to send (CTS) and DTR is looped back to DSR. However, if your terminal program does not require hardware flow control, these loop backs may be omitted and thus the interface consists simply of the two data lines and the common ground.

Use of the SEROUT Command.

The format of the SEROUT command;

     SEROUT 16, 84, 10, ["Hello", DEC VAL, CR]
where the first number is the pin number, 0 through 15, and in addition 16 which is used to indicate the terminal normally used for communicating with the PC in the development mode.

The second number (84) designates the baud rate. This is the bit time in usecs less 20 usecs. For example, for 9600 baud, one bit is 1/9600 or 104 usecs. Subtracting 20 usecs yields the value of 84. For 2400 baud, one bit is 416 usecs. Thus 416 - 20 or 396 would be used to specify the baud rate.

The third number is the time delay in msecs between transmitting characters.

The balance in brackets [ ] is in the same format as the DEBUG command.

In fact, the DEBUG command uses 9600 baud and thus the above is precisely the same as;

     DEBUG "Hello", DEC VAL, CR
That is, if your operational terminal is operating at 9600 baud, you can simply use the DEBUG command.

PC Terminal Program.

Two common terminal emulation packages that I use are PromCom Plus for DOS and the Hyperterm program supplied with Windows95. Configure as a direct connection to the appropriate com port at 9600 baud, 8 N 1 with no hand shaking.

Working with serial during the development process is a bit awkward as you are downloading your program using the Stamp 2 development program and then running the terminal emulation package. Of course, nothing ever works the first time, and I find I am constantly switching between the two. In frustration I found an old Compaq "portable" to use as the terminal, reserving my main PC for Stamp development and downloading.

You might first load the Stamp with some simple program and then configure your PC as a terminal and verify that you can indeed read data from the Stamp.

For example;

     N VAR BYTE
TOP:
     FOR N = 0 TO 100
        SEROUT 16, 84, 10, ["N = ", DEC N, CR]
        DEBUG DEC ? N    ' this is the same thing
        PAUSE 500
     NEXT
     GOTO TOP
Inputting Data to the Stamp.

In the development mode, there is no provision for you to communicate with the Stamp. However, there are instances when you may desire to do so when in the operational mode. Examples which come to mind are menu driven programs where the user is prompted and the Stamp acts on the input from the PC and in entering calibration data to be stored in EEPROM.

The SERIN command is of the form;

     SERIN 16, 84, 10000, TOP, [DEC CHOICE]
Where 16 refers to the I/O pin which is usually 0 through 15. 16 refers to the terminals associated with the PC interface.

The second number refers to the baud rate.

The third refers to the amount of time to wait and if nothing is received, the program is to advance to the label in the next field. In this case, the Stamp is to wait for 10,000 ms and if nothing is received, to go to TOP. This is a big improvement over the Basic Stamp 1, where the program will "hang" if no data is received.

The material in the brackets identifies the format of the input and the variables and Parallax has done a very nice job in thinking out just about any format one will need including signed and unsigned binary, decimal and hexadecimal, characters, strings of a specified length and null terminated strings of an unspecified length. In addition, provision is made for skipping a specified number of bytes, and waiting for a specified string or value. One could write many many pages on simply this one command, but I encourage you to read the manual to appreciate what can be done and when the actual application arises, tinker with the various format specifiers to implement the desired code.

Program SER_1.BS2.

In program SER_1.BS2, the user is prompted to enter a number and the
number is then read into CHOICE.  The program then forks to an appropriate
place depending on the value.

' SER_1.BS2
'
' Prompts user for a number and branches to a specific point depending
' on the value.  
'
' Intended to illustrate SERIN and use of the LOOKDOWN command
'
' Towanda Malone, Jan 9, '98

CHOICE    VAR BYTE
INDEX          VAR BYTE

     DIRS = $00FF
     
TOP:
     SEROUT 16, 84, 10, ["Enter a number which is less than 100", CR, 10]
     SERIN 16, 84, 10000, TOP, [DEC CHOICE]
     PAUSE 500
     LOOKDOWN CHOICE, <= [25, 30, 75, 150], INDEX
     BRANCH INDEX, [PL_1, PL_2, PL_3, PL_4]

PL_1:
     SEROUT 16, 84, 10, ["Place 1", " ", DEC CHOICE," ", DEC INDEX, CR,
10]
     PAUSE 500
     GOTO TOP  
    
PL_2:
     SEROUT 16, 84, 10, ["Place 2", " ", DEC CHOICE, " ",DEC INDEX, CR,
10]
     PAUSE 500
     GOTO TOP  
    
PL_3:
     SEROUT 16, 84, 10, ["Place 3", " ", DEC CHOICE, " ", DEC INDEX, CR,
10]
     PAUSE 500
     GOTO TOP  
    
PL_4:
     SEROUT 16, 84, 10, ["Place 4", " ", DEC CHOICE, " ", DEC INDEX, CR,
10]
     PAUSE 500
     GOTO TOP  
Discussion.

This is a somewhat foolish program as it really doesn't do anything very interesting.

The reason I developed it was in addition to illustrating the SERIN command to illustrate the LOOKDOWN command which is usually used in conjunction with the BRANCH command to implement what is termed a "switch" in the C programming language.

Recall that the BRANCH command takes an argument in the range of 0 to N and redirects program flow to the nth label. The function of the LOOKDOWN command is to take a number and map it into a number in the range of 0 to N.

The form of the LOOKDOWN command;

     LOOKDOWN CHOICE, <= [25, 30, 75, 150], INDEX
CHOICE is the value and the next field is the relational test. For example, if CHOICE is 33, the condition that CHOICE is <= to 25 is false, as is <= 30. However, <= 75 is true and the INDEX takes on the value of 2.

This is particularly useful in menu type programs where the user enters a character which directs program flow to a particular task as illustrated in the following snippet which reads a character and forces it to upper case and then branches to an appropriate point.

     SERIN 16, 84, 10000, TOP, [LETTER]
     IF (LETTER >= "A") & (LETTER <= "Z") THEN SKIP    ' it's upper case
     LETTER = LETER - "a" + "A"         ' make it an uppercase letter
SKIP:
     LOOKDOWN LETTER, = ["M", "C", "X", "T"], INDEX
     BRANCH INDEX, [PL_1, PL_2, PL_3, PL_4]
Note that there is no qualifier in the above SERIN command and thus LETTER takes on the ASCII value of the character which is received. For example the character "A" is $41.

The IF statement then tests if the character is an upper case character. That is, in the range of the characters "A" to "Z". Note that the Stamp 2 development software converts the quoted characters to their ASCII values. That is, the following is the same statement;

     IF (LETTER >= $41) & (LETTER <= $5A) THEN SKIP
If not, I assume it is a lower case character and convert it to an upper case character;
     LETTER = LETER - "a" + "A"

or   LETTER = LETTER - $21 + $41
The value of LETTER is then mapped into an index using the LOOKDOWN command and the BRANCH command then directs program to the appropriate place.

(Note that in the above I forced the character to upper case to show how it is done. Of course, my snippet is lacking in that there is not additional error checking to assure the character is in fact a letter and that the letter is one of the valid selections.)

Relative Humidity.

The following presents a technique for measuring relative humidity using a Philips 2322 691 90001 Humidity Sensor. A data sheet in .PDF format for this device is available from http://www.philips.com. Search on "humidity". The device is available from Newark Electronics (http://www.newark.com). Search on "2322". It is about $15.00.

This is a capacitor which varies as a function of humidity. At 43 percent relative humidity the capacitance is 122 pFd. The sensitivity over the range of 15 to 75 percent relative humidity is 0.4 pFd / percent relative humidity.

From this data an equation is developed for calculating relative humidity as a function of capacitance.

(1)  RH = 1/0.4e-12 * (C - 122e-12) + 43
where RH is the humidity in percent and C is the sensor's capacitance in pico Farads.

Figure #6 illustrates the use of the in the familiar 555 multivibrator mode.

Recall that;

(2)   T_555 = (R1 + 2*R2) * C * ln(2)
Substituting for R1 = R2 = 100K and rearranging;
(3)  C = T_555/(300K * ln(2)
Substituting (3) into (2);
(4)  RH = 12e6 * T_555 - 262
Thus, one technique for measuring relative humidity would be to measure the period using the PULSIN command to determine the high and low times and then use equation (4).

However, the above may be expressed as;

(5)  RH = 12e6/COUNT_SEC - 262
where COUNT_SEC is the number of positive transitions of the 555 over one second.

However, 12e6 is a hard number to work with using the Stamp. Dividing the numerator and denominator by 200;

(6)  RH = 60,000 / COUNT_5_MSEC - 262
Thus the idea is to measure the number of counts from the 555 over a five millisecond period and then use equation (6).

Of course, all of this assumes the device is actually 122 pico Farads at 43 percent humidity. Equation (7) allows for a calibration constant;

(7)  RH = 60,000 / COUNT_5_MSEC - 262 + CAL_CONST
For example, assume a user knows the actual relative humidity is 60 percent, but equation (6) evaluates to 45 percent. The calibration constant is then 15 decimal or %0000 1111. However, if the actual humidity was 30 and equation (6) evaluates to 45, the calibration constant is -15 or %1111 0001.

In program HUMID.BS2, the calibration constant in EEPROM is initialized to zero when downloading.

The user is prompted as to whether they wish to make a measurement or perform a calibration. If a measurement, the count over a five msec time is made using the COUNT command. Equation (7) is then used with the calibration constant being fetched from EEPROM. If the user select calibration, they are prompted for the actual relative humidity and then a measurement is performed using equation (6) and the difference is saved to EEPROM.

' HUMID.BS2
'
' Measures relative humidity using Philips capacitive sensor.  See text.
'
' User is prompted as to whether to perform a measurement or a
' calibration.
'
' If a measurement, the number of counts from a 555 over a 5 msec period
' is determined using the COUNT command and the relative humidity is 
' calculated.
'
' If a calibration, the user is prompted to enter the actual RH.  The 
' program then performs a measurement and saves the difference between 
' the actual and the measured to EEPROM.  This difference is then used in 
' later measurements.
'
' Towanda Malone, Jan 9, '98

CAL            DATA $00  ' initialize calibration correction
ADR_TABLE      DATA CAL  ' address of CAL

INDEX          VAR BYTE
CAL_CONST      VAR BYTE  ' correction
COUNT_5_MSEC   VAR WORD  ' number of 555 counts over 5 msecs
RH             VAR BYTE  ' measured relative humidity
ACTUAL_RH      VAR BYTE  ' relative humidity entered by the user

PTR            VAR WORD  ' used to read and write to EEPROM

     DIRS = $00FF
     
TOP:
    SEROUT 16, 84, 10, ["Enter 0 to read humidity or 1 to calibrate", CR,
10]
     SERIN 16, 84, 10000, TOP, [DEC INDEX]   ' read response
     BRANCH INDEX, [MEAS, CALIBRATE]         ' branch to appropriate place

MEAS:    
     COUNT 8, 5, COUNT_5_MSEC                ' number of 555 counts 
               
     READ ADR_TABLE, PTR.BYTE0               ' fetch the pointer to CAL
     READ ADR_TABLE+1, PTR.BYTE1
     READ PTR, CAL_CONST                ' fetch the calibration
     BRANCH CAL_CONST.BIT7, [POSITIVE, NEGATIVE]
     ' test to see if it is positive or negative
POSITIVE:
     RH = (60000/COUNT_5_MSEC) - 262 + CAL_CONST  
     GOTO MEAS_2

NEGATIVE:
     CAL_CONST = (~CAL_CONST)+1              ' take two's compliment
     RH = (60000/COUNT_5_MSEC) - 262 - CAL_CONST
     GOTO MEAS_2

MEAS_2:
     PAUSE 500
     SEROUT 16, 84, 10, ["RH = ", DEC RH, " ", DEC INDEX, CR, 10]
     PAUSE 500
     GOTO TOP

CALIBRATE:
     PAUSE 500
     SEROUT 16, 84, 10, ["Enter Calibration RH:", CR, 10]
     SERIN 16, 84, 60000, CALIBRATE, [DEC ACTUAL_RH]   ' fetch actual RH
     COUNT 8, 5, COUNT_5_MSEC           ' now perform a measurement
     
     RH = (60000/COUNT_5_MSEC) - 262    ' and calculate the result
     CAL_CONST = ACTUAL_RH -RH          ' calculate the difference
     READ ADR_TABLE, PTR.BYTE0          ' and save to EEPROM
     READ ADR_TABLE, PTR.BYTE1
     WRITE PTR, CAL_CONST
     PAUSE 500
     SEROUT 16, 84, 10, [DEC ACTUAL_RH, "!", DEC CAL_CONST, CR, 10]
     GOTO TOP       
Discussion.

The format of the COUNT command;

     COUNT pin, time, variable
Where pin may be any of the 16 I/O pins. Note that it must have been previously defined as an input. Time is the number of msecs to count (maximum of 65,535 msecs or a bit over one minute) and variable is a word which may accommodate up to 65,535 counts.

Note that CAL_CONST is saved in two's compliment format. That is, 15 is saved as %0000 1111, and minus 15 as %1111 0001. Unfortunately, when fetching this value from memory and adding it to 60000/COUNT_5_MSEC - 262, the quantity is treated as a 16 bit word and thus minus 15 will be evaluated as +241.

Thus, when fetching the calibration constant from EEPROM, the sign is checked by determining the state of the most significant bit and the cases of a positive and negative calibration constant are handled differently. If positive, the constant is simply added, but, if negative, the two's compliment is performed and the result is then subtracted from 60000/COUNT_5_MSEC - 262.

The very important point in this program is the ability to have the user provide a reference point so as to perform a single point calibration. Although this was presented in the context of relative humidity, it is applicable to virtually any measurement process. One of the great powers of the Stamp is the combination of the ease in interfacing with a PC terminal and EEPROM to store this calibration constant.

Use of a MAX232. (See Figure #7).

All of the above discussion relates to interfacing the Basic Stamp with a PC terminal using the Stamp's on-board circuitry to provide the RS232 to TTL and TTL to RS232 level conversion.

When using I/O leads P0 through P15 to interface with periperals, recall that these are TTL levels. TTL levels may be suitable in interfacing with such devices as another Basic Stamp, a serial LCD, our serial temperature measurement kit and such devices from Solutions Cubed as the Watch real time clock, their motor controller and their RAM.

However, if the peripheral is located more than a few feet from the Stamp, you may wish to use a pair of MAX232 devices. Note that the MAX232 requires only a source of +5VDC. Internal charge pumps generate the RS232 potentials, typically plus and minus 10 VDC.

Note that each MAX232 provides tow RS232 transmitters and two receivers.

Just how far one can reliably extend the distance using the RS232 interface is subject to debate. At the time the RS232 standard was developed, the specification was 75 feet, but if you are in a hobby situation where failure has no severe consequences, go as far as you can which is probably more than 1000 feet.

Stamp to Stamp Communication.

Consider an application using more than one Stamp. An application which comes to mind is a weather application where a master Stamp periodically performs the following;

Temperature. We have discussed several techniques including a thermistor in a 555 circuit and the DS1624 on an I2C bus.

Barometric Pressure. This was discussed in the context of interfacing with an ADC0831.

Relative Humidity. An implementation using a Philips humidity sensor in a 555 circuit was discussed above.

Wind Speed. Although this has not been discussed, the concept is simple. As the spinner on the anemometer turns, a magnet passes by either a Hall effect device or a reed switch which sends a pulse to the Stamp. Thus, measuring wind speed is nothing more than opening a counter using the COUNT command for a second or even ten seconds and then applying some expression to the resulting number of counts to calculate wind speed.

Wind Direction. This is often implemented using a 360 degree potentiometer and can be measured using either the period of a 555, using the POT command or by using an analog to digital converter.

Rainfall. All the instrumentation that I have seen sends a pulse for each 0.01 inch of rainfall and one might be tempted to dismiss this as a trivial application of the COUNT command.

However, unlike the use of the COUNT command in the above measurements, a missed 0.01 inch of rainfall is lost forever. Wind speed can be measured at any time and common sense suggests that a wind speed measurement performed for ten seconds every ten minutes (or 1/60 of the time) is a good enough picture. That is, it is not necessary to spend 99.9 percent of the time measuring wind speed. On the other hand, a good cloud burst could well occur during the 59/60 of the time one is not monitoring rainfall.

This type of phenomenon that requires near continuous "camp-on" might be solved by dedicating an entire Stamp to do nothing more. Certainly, you may reject rainfall as being important enough, but it is an example which is readily understandable.

Thus a slave BS2 might do nothing more than open a 10 second window using the COUNT command and add any counts to the accumulated rainfall and then spend a few milliseconds checking to see if the master BS2 desires this information.

Refer to Figure #8.

Here again, Parallax has done an outstanding job in simplifying the task by providing for "flow control".

The Master might spend its time making temperature, wind speed and direction, barometric pressure and relative humidity measurements, but every 15 minutes it desires to know the accumulated rainfall and it executes the following command;

     SERIN 8\7, 84, 11000, FAILURE, [DEC RAIN]
Note the addition of the \7 which designates P7 as the flow control pin. This causes P7 to go to a logic zero signaling the Slave that a measurement result is desired. Note the timeout is 11 seconds.

The Slave is continually "camping" on a lead to count the rainfall as shown in the following snippet.

AGN:
     COUNT 9, 10000, RAIN
     ACCUM = ACCUM + RAIN
     SEROUT 7\8, 84, 1, AGN, [DEC ACCUM]
     ACCUM = 0           ' reset ACCUM once result has been transmitted
After adding any additional rainfall to the accumulated value, the Slave executes the SEROUT command. Here again, note the designation of a pin for flow control, but also note the additional timeout parameter, which has been set to 1 ms.

The Slave checks the flow control pin (P8) and if it is high, it waits for one ms and then branches to AGN without sending the data. Thus, the Slave spends 99.99 percent of the time camped on the terminal from the rainfall detector.

If the Slave finds the flow control pin low, it sends the serial data and then resets ACCUM back to 0.

Thus every ten seconds, the Slave is testing to see if the Master desires the information. Note that the Master will keep the flow control pin low for 11 seconds assuring that the Slave will execute the SEROUT command within that time.

Interfacing with a Serial LCD.

See Figure #9.

In many applications it is desirable to display text and a serial LCD is considerably more portable and less expensive than a laptop PC.

There are a number of such arrangements available ranging from our $9.95 kit which includes everything other than the LCD itself to units costing five or ten times that from Parallax.

There is a considerable amount of information on my home page, including a number of sample Basic Stamp programs. The following is a good example as it conveys many points.

' LCD_1.BS2
'
' Illustrates how to display four quantities at different places on a
' 2-line display.
'
' P0 (term 5) -------------------------- To RX on LCD
'
' Towanda Malone, Morgan State University, 7 July, '97

     Q1   VAR WORD  ' some dummy quantities
     Q2   VAR WORD
     Q3   VAR WORD
     Q4   VAR WORD
     
     N    VAR BYTE

     DIR0=1         ' define serial output to LCD

MAIN:
     SEROUT 0, $4000+396, 10, [$FE, $01]     ' clear LCD


     ' display Q1=  Q2=
     '         Q3=   Q4=

     SEROUT 0, $4000+396, 10, [$FE, $80, "Q1="]    ' line 1, pos 0
     SEROUT 0, $4000+396, 10, [$FE, $80+(8-1), "Q2="] ' line 1, pos 7
     SEROUT 0, $4000+396, 10, [$FE, $80+$40, "Q1="]'  ' line 2, pos 0
     SEROUT 0, $4000+396, 10, [$FE, $80+$40+(8-1), "Q2="]' line 2, pos 7

     FOR N=0 to $FF
        Q1=N        ' give quantities some varying values
        Q2=100+N
        Q3=200+N
        Q4=300-N
          
        SEROUT 0, $4000+396, 10, [$FE, $80+3, dec Q1]
        SEROUT 0, $4000+396, 10, [$FE, $80+(8-1)+3, dec Q2]
        SEROUT 0, $4000+396, 10, [$FE, $80+$40+3, dec Q3]
        SEROUT 0, $4000+396, 10, [$FE, $80+$40+(8-1)+3, dec Q4]

        PAUSE 300
     NEXT
     STOP
Discussion.

Consider;

     SEROUT 0, $4000+396, 10, [$FE, $01]     ' clear LCD
At the beginning of this tutorial, it was noted that serial LCDs typically do not use an RS232 receiver, but rather a series limiting resistor. Thus, an RS232 logic one (< -3.0 VDC) is a TTL logic zero. However, the PIC associated with the LCD controller inverts this to interpret the TTL logic zero as being a "one" state. Similarly, a RS232 logic zero (> 3.0 VDC) is a TTL logic one, but the PIC interprets this as a "zero" state. Thus, the term "inverted".

Now, assume there is no RS232 transmitter. In the idle state the Stamp output would normally be at a logic one. The start bit would be a logic zero. However, the serial LCD is interpreting these as being the opposite state which is unworkable.

The solution is to send the data "inverted" as well. Life does indeed get complex.

Here again Parallax did a good job. Parallax uses a 16 bit word to specify the characteristics of the serial transmission. The lower 14 bits are used to define the bit time

Recall that the bit time is expressed as 1/BAUD in usecs less 20 usecs. The bit time for some common Baud rates;

     Baud      Bit Time (usecs)    Bit Time - 20

      300      3333           	      3313
     1200       832            	       812
     2400       416            	       396
     9600       104              	84
Note that 14 bits (0 through 13) are required to provide for 300 Baud.

Bit 14 is used to define whether the data is to be sent in true (bit set to zero) or inverted (bit set to one) form. Thus, in the above program, we desire the data be sent in inverted form and thus the quantity $4000 (%0100 0000 0000 0000) is added to the bit time specifier

(In passing, bit 15 is used to define whether or not the data is to be sent using no parity or with even parity. When bit 15 is set to 0, data is sent as eight bits with no parity. When set to 1, data is sent as 7 bits with even parity. Setting the bit is accomplished by adding $8000 (%1000 0000 0000 0000). I have never used this capability).

Thus far, I have only explained the $4000 + 396.

     SEROUT 0, $4000+396, 10, [$FE, $01]     ' clear LCD
Note that the first character which is sent is ASCII $FE. This character is not used in normal text and is used by the LCD controller as a flag that what follows is a control command. The command $01 clears the LCD.

Consider;

     SEROUT 0, $4000+396, 10, [$FE, $80, "Q1="]    ' line 1, pos 0
     SEROUT 0, $4000+396, 10, [$FE, $80+(8-1), "Q2="] ' line 1, pos 7
Here again, the $FE signifies that what follows is to be interpreted as a control command.

A Control Command having a one in the most significant bit are interpreted as "position the cursor at this location on the LCD".

Thus $80 or %1000 0000 is interpreted as "position the cursor at address 0". That is, in the upper left. Similarly, $FE, $87 positions the cursor at address 7.

The address of the beginning of the second line is defined as address $40 as shown in the following two lines.

     SEROUT 0, $4000+396, 10, [$FE, $80+$40, "Q1="]'  ' line 2, pos 0
     SEROUT 0, $4000+396, 10, [$FE, $80+$40+(8-1), "Q2="]' line 2, pos 7
Consider;
        SEROUT 0, $4000+396, 10, [$FE, $80+3, dec Q1]
        SEROUT 0, $4000+396, 10, [$FE, $80+(8-1)+3, dec Q2]
        SEROUT 0, $4000+396, 10, [$FE, $80+$40+3, dec Q3]
        SEROUT 0, $4000+396, 10, [$FE, $80+$40+(8-1)+3, dec Q4]
In each case, the control command is limited to one byte. The, the $FE is a flag that the next byte specifies a control command, in this case a positioning of the cursor. After that, the LCD interprets the transmission as text. In this case, the decimal values of Q1, Q2, Q3 and Q4 are displayed at various positions on the LCD.

As with most things, this may appear far more complex than it actually is. Once you get an LCD display functioning you tend to learn quickly.

Interfacing with our 8 channel Temperature Measurement Systems.

See Figure #10.

The temperature measurement system is idle when input MEAS is low and input /MEAS is high.

A measurement sequence is initiated by bringing MEAS low. The PIC processor associated with the A measurement sequence is initiated by bringing MEAS low. The processor then proceeds to make measurements, beginning with Channel 0, sending each measurement at 2400 Baud as it is completed. The time required for each measurement is nominally one second.

It is recommended that the temperature measurement system be configured in the multiline format when interfacing with the Stamp. (Ground on input 1_LINE).

The data is then returned in the following format.

     0 20.34
     1 20.56
     2 -0.34
     3 -21.15
     4 -99.99
     5 23.12
     6 -99.99
     7 -99.99
The first number is the channel and the second is the temperature in degrees C. Note that minus 99.99 indicates the channel is not equipped with a Dallas 1-wire temperature device.

The serial data is sent to the Stamp via the MAX232. Note that the serial temperature measurement system sends 2400 baud non inverted. That is, the idle condition is a TTL logic one. The START bit is a TTL logic zero, the eight data bits are sent, followed by the STOP bit which is a TTL logic one. However, the MAX232 converts a TTL logic one and zero to less than -3V and greater than +3V respectively.

On the Stamp side, there is no similar conversion from EIA levels to TTL levels. Thus, a logic one (less than -3V) is read by the Stamp as a TTL logic zero, and a logic zero (greater than +3V) is read as a TTL logic one. This inversion is acceptable if one configures the Stamp to receive 2400 Inverted.

Note that a 22K series limiting resistor is provided to protect the Stamp from the +10V and -10V signals seen at the output of the MAX232.

Program T_MEAS.BS2.

This program simply initiates a measurement sequence and then reads the results of each of the eight measurements. The characters are converted to decimal and then displayed using the DEBUG command.

The intent is to simply demonstrate the operation. Once you have read the temperatures, you might desire to compare one or more against either a high or low threshold or both and use the Stamp to turn on fans, air conditioning, heat or simply to sound an alarm. You might desire to log the T_C and fraction to a serial EEPROM for later uploading to a PC. The number of possibilities are endless.

A measurement sequence is initiated by bringing output P1 low for 100 msecs.

The first measurement is then read using the SERIN command;

     SERIN 0, BAUDMODE, 5000, TIMEOUT, [DEC1 CHANNEL, SKIP 1, SDEC T_C, 
                                        SKIP 1, DEC2 FRACTION, SKIP 2]
Note that this must all be on one line. I found it necessary to split the line for this discussion.

Recall that the format of the data is;

     0 -12.7
Followed by a return (ASCII 0DH) and linefeed (ASCII 0AH).

A literal translation of the above SERIN command is, "receive the serial bit stream (2400 inverted) on pin P0. If more than 5000 msecs elapses, jump to location TIMEOUT. Strip off the first received character, convert it to decimal and save in variable CHANNEL. Skip the next character (a space). Convert the next to a signed decimal and save in T_C. Skip the decimal point. Convert the next two digits to a decimal value and save in variable FRACTION. Finally, skip the return and linefeed characters.

The serial temperature system provides a one second delay before sending the next value. This provides the user with a period of time to display the data, save it to EEPROM or compare it with alarm thresholds. However, it is important to get back to read the next value within the one second or portions of the serial string will be lost.

Note that T_C is defined to be a signed byte and if a quantity is negative, the Stamp saves the quantity in two's complement form and is thus capable of storing values in the range of 0 to 127 and -1 to -128 degrees. In the example, 12 is;

     0 0 0 0  1 1 0 0 
The two's complement is;
     1 1 1 1  0 0 1 1 + 0 0 0 0 0 0 0 1 

or      1 1 1 1  0 1 0 0
or 244 unsigned decimal.

A simple test as to whether a quantity is negative is to test the most significant bit as to whether it is a one, or if the quantity is 128 or greater. In this routine, if the quantity is >= 128, a minus sign is displayed followed by the two's complement of the value. For example;

      1 1 1 1  0 1 0 0

   	0 0 0 0  1 0 1 1 + 0 0 0 0  0 0 0 1

or   	0 0 0 0  1 1 0 0
or 12 decimal.

Don't worry too much if you are confused. My students are always confused with two's complement and my best advice is to take it on faith. It works. Keep tinkering with it, and one beauty of the Stamp is that it permits you to tinker, and over time, you will grasp it.

'T_MEAS.BS2
'
' This is a simple routine to initiate a measurement sequence and then
' read each of eight measurements from the serial temperature system.
'
' The result of each measurement is displayed using the debug command.
'
' Continual loop with 10 second delay after receipt of the last
' measurement.
'
' Copyright, Peter H. Anderson, August 18, '97


BAUDMODE  CON      396 + $4000      '2400 Inverted

CHANNEL   VAR      BYTE
T_C       VAR      BYTE
FRACTION  VAR      BYTE
N         VAR      BYTE

 
     DIR0 = 0  ' serial input
     DIR1 = 1  ' output.  A logic zero initiates initiates a 
               ' measurement sequence.


TOP:
     OUT1=0         ' bring low to start measurement sequence
     PAUSE 100
     OUT1=1
     FOR N=1 TO 8
        'Note.  The following statement must all be on a single line
        SERIN 0, BAUDMODE, 5000, TIMEOUT, [DEC1 CHANNEL, SKIP 1, 
                    SDEC T_C, SKIP 1, DEC2 FRACTION, SKIP 2]

        DEBUG DEC CHANNEL
        DEBUG " "
        IF T_C<128; THEN AROUND       ' if its negative
           T_C = T_C^$FF +1             ' take 2's complement
           DEBUG "-"
AROUND:
        DEBUG DEC T_C
        DEBUG "."
        DEBUG DEC FRACTION
        DEBUG 13                        ' return character
     NEXT 
     SLEEP 10
     GOTO TOP

TIMEOUT:
     DEBUG "TIMEOUT"
     DEBUG 13
     GOTO TOP
Summary.

This tutorial has been particulary difficult to write as there are so many details associated with serial communication. If you are confused, don't worry too much. Rather cut and paste as required for your application.

Some general recommendations are offered.

1. Reserve the use of the terminals normally associated with downloading and debugging programs for interfacing with a PC or similar terminal device.

2. Use the other terminals (P0 through P15) when interfacing with other peripherals. These include the serial to LCD, our serial to parallel printer and temperature measurement kits and the Solutions Cubed RAM, Motor Mind and Watch.

3. If these peripherals require a negative potential for an EIA logic one, you will need an EIA level converter. If the distance between the Stamp and the peripheral is greater than a few feet, use an EIA converter. The MAX232 is an excellent choice.

4. If the distance is less than a few feet and the peripheral does not require EIA levels, go direct with no EIA converter. However, remember to use the inverted mode to compensate for the missing EIA inversion as necessary.