HOME - - - - - - - - - Other material for programmers - - - - - - - - - Pascalite Tutorial Table of Contents

Pascal Tutorial: What has that hamster been up to?

This tutorial covers some more important ground regarding the use of simple variables. It also tells you a little more about binary numbers, but the binary number stuff is optional! The program will be something inspired by a post in the internet newsletter generated by enthusiasts for the Dallas (aka Dalsemi, aka Maxim) 1-Wire / iButton / MicroLan product as applied to weather monitoring. He wired his children's hamster's exercise wheel to a computer so that the family could see a graph of how active Spike was, 24x7. Spike, like all of his species, was a night owl, busy the night, which the children had not known.

Most of the tutorials in this series come in versions for Pascalite users, and for users with the FPC or TP Pascal compilers. This tutorial, sadly, cannot be converted for the non-Pascalite compilers. But keep reading through the end of this paragraph! The Pascalite has some built in hardware which isn't routinely available on the PCs used by the other compilers. Users of those compilers should still read through this tutorial. There sill be some stuff that you can be a little relaxed about, but the important stuff should be obvious. Comments specifically for those users are presented in the style you see in this paragraph.

"Why can't non-Pascalite programmers do what is in this tutorial?", I hear you cry.

Well... you could. But you either have to interface a counter to your PC, or you could use one of the "fire" inputs on the joystick interface, and de-bounce it and count pulses in software. Neither are really for the beginner, the likely reader of this tutorial. If you are not a beginner, and are happy to work in a higher language, e.g. Delphi or Java, then the way to go would be to attach a 1-Wire counter.

With a Pascalite, all it took was a reed switch (not complicated). Effectively, each time the wheel went 'round, a switch was turned on for a moment, and then off again. If you have a real Pascalite, you can wire a doorbell-type switch to b0, but the virtual Pascalite will work fine, too... you'll just have the minor annoyance of having to turn the switch on AND THEN OFF again to simulate each turn of the wheel. (For advanced readers: Yes, the Pascalite does have a counter, it might be a better way to monitor a stream of pulses. Remember this tutorial is introductory!)

Previously, I've just given you the final code for a program. This time, I'm going to take you through the steps I would use in writing something. Notice how, for example, when I type a "begin", I immediately type the corresponding "end", and THEN I go back and fill in what goes in between. Pascal's design makes it easy to work like this, and doing so helps you keep track of what you're up to. This will be a little strange for you, because you don't know where I'm going... but after you've been through the exercise and grasp where we've arrived, go back, look at the development sequence again, and I think you'll see why I went from nothing to finished program via the route I took. At each stage below, I'll mark which lines are newly added. After each stage, you should be able to "run" the program without errors. I've put "run" in quotes because the program won't actually do very much, but you should at least get not complaints when you try to run it. this is another advantage of building the program up as I am demonstrating.... you can keep it "working" right from the start, and if you re-"run" it after each phase of the building process, if there are errors, you've only added a little new stuff since the last time the program was running, so the problems only have a small area in which to hide. Start by entering the following:

program Spike;
Declare the variables we need...
program Spike;
var boItIs, boItWas: boolean; {new}
Initialize a few things and put in the loop to make the main part of the program continue indefinitely. Previous Pascalite tutorials explained that the def_out line simply alters settings in the Pascalite's electronics so that the specified pins can be used for output. The line bTurns:=0 should be read "bTurns becomes zero". In other words, the effect of that line is to store the number zero in the variable named bTurns. Eventually, we will have the number of turns the wheel has made stored in bTurns.
program Spike;
var boItIs, boItWas: boolean;
def_out(d0,d1,d2,d3,d4,d5,d6,d6,d7); {new}
bTurns:=0; {new}
boItWas:=b0; {new}
repeat {new}
until 4=5; {new}
Add an if... then... that will watch to see if the switch attached to b0 is in the off position. (There is no "else..." part this time.)(This is a LITTLE different from the similar thing we did in an earlier tutorial. We're going to mostly ignore the change from on to off, only counting off to ons... but we need to keep boItWas up to date. Remember: b0 will "boil down to" false if the switch attached to b0 is in the off position.)
program Spike;
var boItIs, boItWas: boolean;
if not(b0) then boItWas:=false;{new}
until 4=5;
Now add something so that when b0 goes to true, the LED on d0 flashes briefly. We won't have this "flash briefly" in the final version of the program, but we're writing it in at this stage as a little test of what we think we've achieved.
program Spike;
var boItWas: boolean;
if not(b0) then boItWas:=false;
if not(boItWas) and b0 then begin{this.... and partner below:FIRST new}
     pulse(d0,80);{later new}
     boItWas:=true;{later new}
     end;{this.... and partner above:FIRST new}
until 4=5;
Think about what boItWas is being used for. We don't want a flash on d0 every time we go through the loop and find b0 true... just on the first time through the loop when we find it true when PREVIOUSLY it was false.

(By the way... if you put something like this together with a real Pascalite, you may encounter a problem arising from something called switch bounce. Don't worry that something is wrong with your hardware or your program if your system's count of wheel turns is too high. If you use a reed switch to sense the wheel's turning, the problem will probably go away, and if it doesn't try adding "delay(10);" just after the boItWas:=true; and if that doesn't fix things email me!)

So! By now we (should!) have something that runs, and which flashes the LED on d0 whenever b0 goes from off to on. Not quite what we were supposed to have, but we ARE getting there!

REPLACE the "pulse(d0,80);" with...
We need to digress to talk about arithmetic with variables. It is perfectly okay to say something like bTurns:=4+3; (although that would be of no use to us in counting hamster wheel turns) If you said bTurns:=4+3, you would be saying bTurns becomes 7, i.e., put the number 7 in the variable called bTurns. 4+3 "boils down" to 7.

Pascalite does have a few limitations. For one thing, it isn't very clever about arithmetic, but that's fine... I'm all in favor of keeping things simple as long as they don't stop me getting where I want to go. In any case, while talking about the way 'round a problem, I can cover a vital concept.

In most Pascals, you could say something like..
Once you know that the asterisk means multiply, I hope you can see that the above would store 35 in bTurns?

In Pascalite, you have to do things as follows:
(FPC and TP are not as "stupid". They both handle bTurns:=(4+3)*5; just fine.)

I hope you're remembering to think of ":=" as "becomes", because if you're looking at the line above and seeing "bTurns equals bTurns times 5" you're going to be confused!! How can anything equal itself times 5 ?!?!? (Of course, infinity times five does equal infinity, but that is a rather special exception.)

No. "bTurns:=...." means that you want the number stored in bTurns to change to a new number. When we said bTurns:=0, I hope you were happy? What we're doing now isn't a lot more complicated.... though it is at the heart of that lesson Per Ranhoff gave so long ago. We are saying with the "....bTurns*5" (right hand side of expression) is, "Look in the variable called bTurns. What number do you find there? Multiply that number times 5." So- if bTurns previously held seven then "bTurns times five" boils down to 35. Keep the "boils down to" number in your head for just a moment. Forget where it came from. Look again at the first part of "bTurns:=...". That says "the contents of the variable bTurns BECOMES..."... so- the number stored in bTurns changes to whatever number the right hand side of the statement boiled down to.

Returning ("At last...", did someone say?) to our hamster wheel monitor: Look again at
Right at the start of the program, with "bTurns:=0;" we said "put zero in the variable called bTurns. the first time the program does "bTurns:=bTurns+1;", what's in bTurns will be changed to 1. When the program has been running for a while, you'll reach a time when bTurns holds 15. At that stage, "bTurns+1" will boil down to 16, and the number in bTurns will become 16. And so on.

Don't forget: the "bTurns:=bTurns+1;" is part of the stuff that only happens "if boItWas=false and b0= true.... ", so don't be thinking bTurns will be made one bigger every time the program goes thought the repeat... until loop!

If you run the program now, you will no longer see flashes, but the number of turns will be recorded in bTurns. There's just one "slight difficulty": You can't SEE the number in bTurns!

Just after boItWas:=true; add:
(On a Pascalite, what we've just seen would turn some of LEDs connected to the microcontroller on or off. Users of FPC and TP who really, really don't care about binary numbers can stop reading here.)

Now anyone who knows about simple binary numbers can see how many times the switch has been switched on by looking at the LEDs of port B. If no LEDs are on, it hasn't been switched on once... we're going to say "there have been no counts" to say that. If just the right hand LED is on, there has been one count. In the following, "1" means the LED is on, "0" means the LED is off. For the moment, ignore the right hand column

                   What the pattern
   LEDs  / Count / stands for...

00000000     0
00000001     1
00000010     2
00000011     3     2+1
00000100     4
00000101     5     4+1
00000110     6     4+2
00000111     7     4+2+1
00001000     8
00001001     9     8+1
00001010    10     8+2
00001011    11     8+2+1
00001100    12     8+4
00001101    13     8+4+1
00001110    14     8+4+2
00001111    15     8+4+2+1
00001000    16
00001001    17    16+1
00001010    18     16+2
... and so on.....
There is a pattern to the codes for 0,1,2,3,4....

You can convert any code, let's take 00001011 once you realize that each column in the code is worth a specific amount. Starting at the RIGHT hand side: The first column is worth 1, the second worth 2, the third worth 4, the fourth worth 8, and so on... the worth doubles each time you go left one column. You ignore the column's worth if there's a 0 in the column, you add in the column's worth if there's a 1 in the column. So, working from the right of 00001011, that is worth 1+2+8, it is worth 11. Now look again at the third column of information in the table above... see what it is saying? N.B. This is just ONE OF the binary codes that have been invented. It is SIMPLE binary numbers. We'll look at other ways of using 1's and 0's to say things later on. (Anything that says something with only two characters, e.g. 1 and 0, is a binary code. It is overly simplistic to speak of "binary" as if there's only one way of showing things with 1's and 0's.)

Find all of that just too tedious? How about a different system of showing on the LEDs how many counts there have been?

Replace the write(portd,bTurns); line with....
write(portd,0);{Turns all the LEDs off}

if bTurns>4  then write(portd,128);
if bTurns>9  then write(portd,192);{128+64}
if bTurns>14 then write(portd,224);{128+64+32}
if bTurns>19 then write(portd,240);{128+64+32+16}
if bTurns>24 then write(portd,248);{128+64+32+16+8}
... etc
In this version of the program, you'll get no LEDs on until there have been 5 turns, the left hand one on after 10 turns, the left 2 on after 15 turns, etc. This isn't the most elegant way to do the job, but it is pretty clear, I hope. (Admittedly, getting the right number for the write(portb... statement is a bit hard, but you could always write out a full table of numbers vs codes if you had to. Many Pascals, maybe even Pascalite, have ways to let you write a number in binary, in which case the numbers for the lines above would have been 10000000, 11000000, 11100000, 11110000, 11111000, etc)

My Sheepdog Guides site.
My Arunet site.

Go to the sites above, and use their search buttons if you want to search them.
To search this site....

Search this site or the web powered by FreeFind

Site search Web search
*    Spell them properly.

You can also search this site without using forms.
Click here to visit editor's freeware, shareware page.



Editor's Main Homepage
How to email or write this page's editor, Tom Boyd
