Welcome to the Wilcox Family weB LOG, your source for the latest Wilcox news, anecdotes, and rants; and, as Jack Benny quipped on his first radio show (March 29, 1932), “There will be a slight pause while you say, ‘Who cares?’â€â€
For the moment, there is far less chaos than a lifetime of apocalyptic and postapocalyptic fiction have led me to expect. This is a good thing. Sort of. I am disappointed that another trope has been shattered. No cities were surrounded by the military, sterilized with nuclear weapons, or set on fire.
It’s not all good, of course. There has been the inevitable dismissal of all we are doing to slow the spread of COVID-19, keep our health care systems from being overwhelmed, and save the lives of our seniors as nothing more than overreaction or a media frenzy. There was new terminology to learn, like presumptivepositive, which refers to a test sample that has tested positive by a state health service lab, but not yet been confirmed by the CDC itself. There was also the overlooked state of testing, which led to a false sense of security: Almost no one was being tested, even if they had been exposed to COVID-19 and exhibited every symptom perfectly, the lack of available test kits meant many such people were rejected from testing, and continue to be rejected even now. (I know it’s shocking and unprecedented, but President Trump is lyingto you.)
On Thursday evening we got ready to hunker down. Market basket, at the nearly-empty time Naomi and I normally go—Thursday evening at 8:00 pm—was Saturday-morning crowded. Toilet paper and bananas had disappeared. But the staffing had been ramped up, and people were amused and polite, as is typical for our neck of the woods. When I got home I ordered some devices to be used instead of toilet paper.
Friday was a prearranged work-from-home day, while Veracode tested an “all-employees-working-from-home” scenario. There were few problems. On Sunday night, we received notice that mandatory working from home would be in effect for the next two weeks.
Humor is a typical fallback. I’ve remarked several times to David, whose severe anxiety keeps him inside at home almost all the time, “Look! We’re all David, now.” My kids have repeatedly quoted, “Oh, so now you’re interested in what introverts do for fun.”
Tonight we’re trying a long-distance game of Pandemic.
This is the final version of a literacy narrative, originally written for UMass Lowell (online) College Writing I, Sec. 031, Professor Richard Keating, October 15, 2018. (Note to plagiarists: This has been submitted to the TurnItIn database, <sarcasm>so, by all means, copy away</sarcasm>.)
Douglas Wilcox Richard Keating UML College Writing I, Sec. 031 October 15, 2018
The same year Star Wars was released, I met my first real computer: a Digital Equipment Corporation (DEC) PDP-8, at my town’s high school. Each terminal connected to this computer was a repurposed teletype machine. There was no screen display, only a nearly-endlessly spooling roll of paper. Each keystroke from the operator or each character output from the PDP was accompanied by a wonderfully complex sound of motors and servos moving the print element and its carriage across the platen, and hammering the right letter onto the paper (262LongRunner).
I was in love.
Through another school program, I got to play on a PDP-40, a massive device that would have made the PDP-8 weep with inferiority, had it been sentient. There I discovered the text adventure “Dungeon†(nee Zork) (Anderson, Kidder).
Creating my own text adventure game became my obsession. I had grand visions. I spent hours creating maps, and working to figure out subroutines that would be able to interpret user input, track inventory, handle world descriptions and actions, and even inject some humor while tracking hunger and thirst—“You would kill for a baloney-and-cheese sandwich.†There was no way for me to do a program this large on the DEC, but the Apple IIs that the junior high had would be perfect. They even had floppy drives, so I could store this creation on my own 5¼” diskette.
Not owning my own computer, I had to work offline—truly offline. I worked in notebooks, keeping the program flow in my head, and writing the code in longhand for later entry and debugging. I had the inspiration and functional model from other, better-written software, and a clear idea of what I wanted to do. I just had to figure out how.
A text adventure needs to provide a description of each location or room, and anything that might be portable in that room. The program needs to track the player’s location, and allow the player to move through the game world. My solution for handling this was effective, but contraindicated by speed and memory limitations at the time. The key was arrays—the computer equivalent of a numbered stack of index cards. I used an array of alphanumeric variables as a container, storing the description for each of the game’s locations by element number in the array. So, if the player moved to “location 104,†the description could be displayed by returning the description in “card†104.That system was great for things which stayed in place, but what about portable items? For that I had to push further, but was still able to use an array structure. I invented a design where each portable item would be assigned to an item number in an array, and the data for that item would be stored in a predetermined portion of a text variable that contained, among other things, the item’s description. In the metaphor of the index cards, we might imagine that specific lines on each card record a specific kind of data, such as consistently having a title on the first line of every card.
Player movement could be controlled by setting the player’s location to a particular number corresponding to the description array and item locations. Switching the location was just a matter of coding which direction’s movement would take one to which location number and using that number to access the description and item arrays.
When I finally got enough of the modules coded and debugged, I ran it. It worked! It was slow—but it worked.
Now I work full time as a programmer, as I have for more than 15 years, and every part of my workday involves applying digital literacy directly to solving programming problems. I use my store of those skills and a variety software tools to accomplish this. The problems I solve are far more complicated—although they often still involve arrays—but they apply all the digital skills and literacy that began when I was smitten by the PDP-8, in all its teletype-driven glory.
Phase 2: Analysis
The rapid development of digital technologies in the digital era presents individuals in the emerging information society with situations that require them to employ a growing assortment of cognitive skills in order to perform and solve problems in digital environments. These skills are often referred to as “digital literacy†(Gilster, 1997; Inoue et al., 1997; Lanham, 1995; Pool, 1997), which is presented as a special kind of mindset that enables users to perform intuitively in digital environments, and to easily and effectively access the wide range of knowledge embedded in these environments (Gilster, 1997; Tapscott, 1998; EshetAlkalai, 2004; 2005) (Aviram and EshetAlkalai 1, emphasis mine).
The experience described in this narrative pertains to the phrase: “to perform and solve problems.†Problem-solving is the aspect of digital literacy that is most important in my life and career.
My first digital literacy skills were not very impressive, and many are now accessible by toddlers in today’s world of icons and GUIs: reading a directory, loading a program, running that program, and interacting with its prompts and output. Looking back over my computer literacy from childhood through the early days of my computer career, it is clear that my very meanest skills were a foundation of understanding that lasted for decades.
I worked in notebooks, keeping the program flow in my head, and writing the code in longhand for later entry and debugging.
Although the problems I solve are now more complex, the instant availability of explanations, sample code, and often complete example projects available online can make the level of problem solving significantly different. Given my skill level at the time, my limited access to computers, the nonexistence of the Internet, and a lack of established patterns, there was more room for innovation at a basic level. Innovation is still significant, but it tends to occur
I spent hours creating maps, and working to figure out subroutines that would be able to interpret user input, track inventory, handle world descriptions and actions, and even inject some humor while tracking hunger and thirst….
It was somewhat surprising to explore this time period, and to renew my awareness of just how exhilarating computer tasks were. I was able to continually improve programming concepts and problem-solving by my sometimes weak attempts to replicate things I had seen. Writing my own text adventure was a wonderfully motivating force for improving my programming and the problem-solving that went along with it. I still advise those who want to learn a new platform on language to think of something that they really want to build as a first project.
That system was great for things which stayed in place, but what about portable items? For that I had to push further.
Although it is true that I knew far less, I was also working with a programming language that was more limited in its abilities, and accomplishing what I wanted often required a finer-grained ingenuity.
The “growing assortment of cognitive skills†(Aviram and EshetAlkalai) is particularly evident in the development of problem-solving. Like any cognitive skill practice, problem-solving begets even more refined problem-solving, leading to gains in the complexity of problems that can be solved, and the ease with which they can be solved.
Kidder, Tracy. The Soul of a New Machine. Little, Brown and Company, 2000. Print.
Feedback
Professor Keating’s Final Response:
Hi Doug,
As I read the final version of this exceptionally well revised essay, I reflect on how the vast majority of my students see digital literacy in terms of language, or a lexicon of terms common to a discipline. You see it in terms of a numerical logic, a binary code of understanding. That’s just as applicable, different cognition, same result!
This was a relatively early draft and analysis of a literacy narrative, originally written for UMass Lowell (online) College Writing I, Sec. 031, Professor Richard Keating, September 30, 2018. The more concise version will be published separately. (Note to plagiarists: This has been submitted to the TurnItIn database, <sarcasm>so, by all means, copy away</sarcasm>.)
I loved writing this essay, but desperately needed to cut it down to a much smaller size and intense focus. (That was the hardest part of the work.) Still, this history of my first exposure to computers is something I wanted to publish. The final version of this essay is here: Romancing the Code: The Literacy Narrative I Did Write.
Computers in Digital Literacy: Problem-Solvers versus
Problem-Solving
Phase 1: Literacy Narrative
When I was nine years old, the world of science fiction changed
with the release of Star Wars. The
film is, of course, merely space opera, and more fitting of the term science fantasy than science fiction, but it was remarkable
for its technical presentation and fully realized worldbuilding, rather than
for its originality or brilliance of story. (See Campbell, 2008.)
In much of twentieth century science fiction, computers are
autonomous problem-solvers. They are almost never programmed by humans. A query
is made, and the computer—via punched paper, data cards, audible output, or
screen display—provides the answer to an enormously complex problem. The idea
of a computer as a tool is reduced to its metanarrative: The computer is
godlike—omniscient and often omnipresent—and not necessarily benign. Star Wars avoided this trope, turning
sentient, autonomous computers into a digital underclass—droids—while
presenting computers with which “humans†would directly interact in a way that
was more akin to our current state of the art. The Star Wars world includes custom-purposed computer appliances, such
as a “navicomputer†(Wookiepedia), as well as networked data storage and
retrieval devices that would not be out of place in our own world. Although we
use computers to solve a vast number of problems in everyday life, even
commonly as our own navicomputer devices, it is the act of programming itself
which provides me the greatest problem-solving experience.
The same year Star Wars was released, I met my first real computer: a Digital Equipment Corporation (DEC) PDP-8 (Fig. 1) at my town’s high school. Each terminal connected to this computer was a repurposed teletype machine (Fig. 2). There was no screen display, only a nearly-endlessly spooling roll of paper. Each keystroke from the operator or each character output from the PDP was accompanied by a wonderfully complex sound of motors and servos moving the print element and its carriage across the platen, and hammering the right letter onto the paper (262LongRunner). This sound was so iconic that we continue to associate it with the background noises of the era’s television newsrooms.
At age nine, with no previous experience with computers, I was incapable of using them for anything beyond running simple math programs written by high school students. It is difficult to appreciate now, but in a world where pocket calculators were relatively rare, having a computer prompt for two numbers and then displaying their product or dividend was a marvel.
Beyond such number-crunching, computers immediately proved
to be greatly entertaining. I ran student-written programs such as “Guess,†in
which the user would enter a number between 1 and 100, and the computer would
respond with, “Too high,†or “Too low.†I printed text-based art, my favorite
being a cartoon of Snoopy, shaking his fist and saying, “Curse you, Red Baron!â€
(Fig. 3). One could print banners of words where each letter in the banner’s
text was composed of many smaller letters. I printed calendars for the current
year, my birth year, and the unbelievably far-off year 2000.
I was in love.
This elementary-school experience did nothing to assuage my longing to use computers. Through another school program I got to play on a PDP-40 at a nearby enterprise, a massive device that would have made the PDP-8 weep with inferiority, had it been sentient. There I discovered the text adventure “Dungeon†(later and more commonly known as Zork) (Anderson, Kidder). I was enthralled with text adventures. I was determined to program my own.
In my junior high years, we had access to Apple II computers repackaged by Bell & Howell to be nearly indestructible. We also secured access to the PDP-8 at the high school. By this time the teletype machines were gone, replaced mostly by dot-matrix printers from DEC, and supplemented by three glorious CRT terminals, VT05s (Fig. 4). DEC had donated these CRTs to my junior high school’s HAL (High Ability Learner) program, but I was the first to negotiate access to them. I stayed after school until 5:00 every day I could, just to get time on these. I began to learn BASIC, back in the ancient times when it still required line numbers.
Not having a computer of my own presented a problem that
might seem odd today. I had to work offline—truly offline—without even a search
engine, and then try to code what I had done in the time I could get access to
the computer. So, I worked in notebooks, keeping the program flow in my head,
and writing the code in longhand that I would hope to later enter and perfect.
I tried my hand at a number of different programs, but creating
my own text adventure game became my obsession. My first attempt at a text
adventure was quite limited. It offered nothing more than multiple-choice prompts
to make action choices, a far cry from the verb-object command-parsing that
Zork could do. My program was shameful, borrowing scenes and catch phrases from
Tom Baker’s incarnation of Dr. Who, and not much more complex than a
choose-your-own-adventure book. One-quarter of the way through, I ran the
program, and the computer spit out an inexplicable error. It was not the usual
problem of a missing parenthesis or a syntax error, but something I could not
diagnose.
“Doc†(Donald Harrison), the high school’s computer science
teacher, helped me out. Although my program was tiny, it was too big for the
execution space on the PDP-8. He taught me how to link multiple programs so I
could jump to one from another, and I was able to complete my first adventure.
It did teach me the basics of programming, even though what I wrote was not
much more than a pile of print and goto statements, hooked together with the
occasional numeric input. Even so, knowledge of programming meant
problem-solving.
I had grander visions. My next adventure was more original.
I spent hours creating maps, this time avoiding established fandom, and more
time figuring out subroutines that would be able to interpret input, track
inventory, handle world descriptions and actions, and even inject some humor
while tracking hunger and thirst—“You would kill for a baloney-and-cheese
sandwich.†There was no way for me to do a program this large on the DEC, but the
Apple IIs that the junior high had would be perfect (Fig. 5). They even had
floppy drives, so I could store my creations on my own 5¼” diskette.
Innovation was exhilarating.
There were no obvious patterns to follow, and the BASIC language itself was somewhat limited. There were no premade frameworks. I had books, which were very limited, and often inapplicable to a particular system just when I needed to learn something advanced. (The deeper one went, the less universal computer languages with the same name became—radically different from today’s write-once-deploy-everywhere languages like Java.) I had the inspiration and functional model from other, better-written software, and a clear idea of what I wanted to do. I just did not know how.
In a text adventure, one of the most important things is providing a description of each location or room, and anything that might be movable in that room. In that context, the program needs to track the player’s location, and allow the player to move in a specific direction, such as “move north.†My solution may have been clever, if contraindicated by speed or memory limitations at the time. I used an array (something like a deck of cards) of alphanumeric variables as a container, storing the location description for each “room†by element number in the array. So, if the player moved to “location 104,†the description could be displayed by accessing a function that would return the description in “card†104.That system was great for things which stayed in place, but what about portable items? For that I had to push further, and I invented a design which was not dissimilar to what is now called a bitmap. Each portable item would have an item number, but the data for that item would be stored in a predetermined part of a text variable that contained, among other things, the item’s description. In a simple example, the first three characters of the text variable might contain the location number, which could even be a number showing it to be in the player’s own inventory. The description of the item would then be the fourth character in the text to the end of it. Now we use object-oriented languages to create models of such things, in a way that often mimics the real world. A car is often used to illustrate this. A car is a generalized object, and has properties such as color, model, size, number of passengers, make, year of manufacture, or VIN.
Player movement could be controlled by setting the player’s
location to a particular number, and the same location number could be used to
get the description of the location and then display any portable items that
were there. Switching the location was just a matter of coding which direction’s
movement would take one to which location number.
When I finally got enough of the modules coded and debugged,
I ran it. It worked! There was one last problem: speed. Between entering a
command and waiting for the program to do something was a pause of 5 or 10
seconds. But it worked.
More than a decade later, I encountered the published source
code of Zork (and even got it to run in a Windows FORTRAN environment). I was
blown away by the simplicity of Zork’s code. The huge, complicated processing
modules I had created were not used. Zork had a simple data structure, with a
number of pointers, in some ways similar to my array-storage design, but
infinitely more elegant.
Now I work full time as a programmer, as I have for more
than 15 years, and every part of my workday involves applying digital literacy
directly to solving programming problems, ensuring our software is secure, and giving
our customers new or better experiences. I use a dizzying array of software
tools to accomplish this. The problems I solve are far more complicated, but
they apply all the digital skills and literacy that began when I was smitten by
the PDP-8, in all its teletype-driven glory.
Someday, we may indeed interact with our computers like much
of our science fiction predicted. When that day arrives, however, it will
surely include its own tangle of media literacy problems to be solved.
Phase 2: Analysis
The rapid development of digital technologies in the digital era presents individuals in the emerging information society with situations that require them to employ a growing assortment of cognitive skills in order to perform and solve problems in digital environments. These skills are often referred to as “digital literacy†(Gilster, 1997; Inoue et al., 1997; Lanham, 1995; Pool, 1997), which is presented as a special kind of mindset that enables users to perform intuitively in digital environments, and to easily and effectively access the wide range of knowledge embedded in these environments (Gilster, 1997; Tapscott, 1998; EshetAlkalai, 2004; 2005). (Aviram and EshetAlkalai, 2006, emphasis mine)
My experience, described in this narrative, tends to present
two foci: “a
growing assortment of cognitive skills†and “to perform and solve problems.â€
Although the two are intrinsically linked, problem-solving is the one that is
most unique to my own narrative., and the one that is most important in my life
and career.
So, I worked in notebooks, keeping the program flow in my head, and writing the code in longhand that I would hope to later enter and perfect.
My first skills were not very impressive, and are now
accessible by toddlers in today’s world of icons and GUIs: reading a directory,
loading a program, running that program, and then interacting with its prompts
and output. Tracing computer literacy from childhood through the early days of
my computer career, it is clear that my very meanest skills were a foundation
of understanding that lasted for decades. (RUNH
was the command used to launch a program, and I only recently learned that that
it was used to launch a FORTRAN module on the PDP.)
I spent hours creating maps, this time avoiding established fandom, and more time figuring out subroutines that would be able to interpret input, track inventory, handle world descriptions and actions, and even inject some humor while tracking hunger and thirst….
It was somewhat surprising to explore this time period, and
to renew my awareness of just how exhilarating computer tasks were. Computers
were often about games. I was able to continually improve programming concepts
and problem-solving by my somewhat weak attempts to replicate things I had
seen. Writing my own text adventure was a motivating force for improving my
programming and the problem-solving that went along with it.
There were no obvious patterns to follow, and the BASIC language itself was somewhat limited. There were no premade frameworks. I had books, which were very limited, and often inapplicable to a particular system just when I needed to learn something advanced.
Although the problems I solve are now more complex, the
instant availability of explanations, sample code, and often complete example
projects can make the level of problem solving significantly different.
Although it is true that I knew far less, I was also working with a programming
language that was more limited in its abilities, and accomplishing what I
wanted often required a finer grained ingenuity.
Back at one of Veracode’s Hackathons, I published the video below.
My Original Weasley Clock
The New and Improved Weasley Clock(s)
(Original post is here.) I was determined to update the code to use WiFi, and make some other improvements, so finally rewrote it. Here’s the first major revision:
#include
#include "Adafruit_IO_Client.h"
#include
/**
* https://www.amazon.com/gp/product/B015RQ97W8/ref=oh_aui_search_detailpage?ie=UTF8&psc=1
* 5-wire unipolar steppers with controller
* Longruner 5x Geared Stepper Motor 28byj 48 Uln2003 5v Stepper Motor Uln2003 Driver
* Board for arduino LK67
*
* AWESOME details on these motors/controllers:
* https://arduino-info.wikispaces.com/SmallSteppers
*
* Much Better than standard stepper library: AccelStepper
* http://www.airspayce.com/mikem/arduino/AccelStepper/classAccelStepper.html
*
* Weasley Clock
* -------------
*
* Created by Doug "LegoDoug" Wilcox for Veracode Hackathon IX.
*
* Video of the completed project is at https://www.youtube.com/embed/oRUViFnxKsg.
*
* "Share and enjoy."
*/
/************************* WiFi Access Point *********************************/
#define WLAN_SSID "DefinitelyNotMySSID" // "...your SSID..." Amusingly, the cannot contains spaces or hyphens.
#define WLAN_PASS "TotallyNotTheRealPassword" // "...your password..."
/************************* Adafruit.io Setup *********************************/
#define AIO_SERVER "io.adafruit.com"
#define AIO_SERVERPORT 1883 // use 8883 for SSL, otherwise use 1883
#define AIO_USERNAME "TotallyNotMyAdaFruitIOUser" // "...your AIO username (see https://accounts.adafruit.com)..."
#define AIO_KEY "TotallyNotMyAdafruitIOKey" // "...your AIO key..."
#define AIO_FEED_PATH "/feeds/"
#define AIO_PUBLISH_FEED "weasleyclockposition"
#define AIO_SUBSCRIBE_FEED "weasleyclockstatus"
// Motor pin definitions
#define motorPin1 14 // IN1 on the ULN2003 driver 1
#define motorPin2 12 // IN2 on the ULN2003 driver 1
#define motorPin3 13 // IN3 on the ULN2003 driver 1
#define motorPin4 15 // IN4 on the ULN2003 driver 1
#define DELAY 1
#define HALFSTEP 8
/************ Global State (you don't need to change this!) ******************/
// Create an ESP8266 WiFiClient class to connect to the WiFi network.
WiFiClient client;
// or... use WiFiFlientSecure for SSL
// WiFiClientSecure client;
// Create an Adafruit IO Client instance. Notice that this needs to take a
// WiFiClient object as the first parameter, and as the second parameter a
// default Adafruit IO key to use when accessing feeds (however each feed can
// override this default key value if required, see further below).
Adafruit_IO_Client aio = Adafruit_IO_Client(client, AIO_KEY);
// Alternatively to access a feed with a specific key:
Adafruit_IO_Feed clockFeed = aio.getFeed(AIO_SUBSCRIBE_FEED, AIO_KEY);
// States
const String LD_HOME = "ld_na";
const String LD_TRAVELING = "ld_tr";
const String LD_VERACODE = "ld_of";
const String LD_CHURCH = "ld_ch";
const String LD_MORTAL_PERIL = "ld_mp";
const String LD_GLOUCESTER = "ld_gl";
const String PLUS_ONE = "plus_1";
const String MINUS_ONE = "minus_1";
const String PLUS_FIVE = "plus_5";
const String MINUS_FIVE = "minus_5";
const String NO_MOVEMENT = "none";
// Steps
const int STEPS_HOME = 0;
const int STEPS_TRAVELING = 600;
const int STEPS_VERACODE = 1250;
const int STEPS_CHURCH = 1900;
const int STEPS_MORTAL_PERIL = 2600;
const int STEPS_GLOUCESTER = 3450;
const int STEPS_ONE = 32;
const int STEPS_FIVE = 5 * 32;
String fValue = "";
const unsigned long requestInterval = 5000L; // delay between updates, in milliseconds
void stepBySteps(int newPosition, boolean resetWhenDone = false);
AccelStepper clockStepper(HALFSTEP, motorPin1, motorPin3, motorPin2, motorPin4);
void setup() {
Serial.begin(115200);
delay(10);
// Connect to WiFi access point.
Serial.println(); Serial.println();
Serial.print("Connecting to ");
Serial.println(WLAN_SSID);
WiFi.begin(WLAN_SSID, WLAN_PASS);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println();
Serial.println("WiFi connected");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
clockStepper.setMaxSpeed(1000.0);
clockStepper.setAcceleration(100.0);
clockStepper.setSpeed(200);
clockStepper.setCurrentPosition(0);
}
void loop() {
// Wait for a bit and read the current feed value.
Serial.println(F("Waiting ..."));
delay(requestInterval);
// To read the latest feed value call the receive function on the feed.
// The returned object will be a FeedData instance and you can check if it's
// valid (i.e. was successfully read) by calling isValid(), and then get the
// value either as a text value, or converted to an int, float, etc.
Serial.println(F("Checking feed ..."));
FeedData latest = clockFeed.receive();
if (latest.isValid()) {
Serial.print(F("Received value from feed: ")); Serial.println(latest);
// By default the received feed data item has a string value, however you
// can use the following functions to attempt to convert it to a numeric
// value like an int or float. Each function returns a boolean that indicates
// if the conversion succeeded, and takes as a parameter by reference the
// output value. Also, beware. There seems to be a limit on how long the
// feed value can be. I had trouble when "minus_five" was used, which makes
// me think the limit is 8 characters.
// Want some fun? Learng about "conversion from 'FeedData' to non-scalar type 'String' requested" the hard way.
fValue = latest;
if(fValue == LD_HOME) {
Serial.println("Nashua");
stepBySteps(STEPS_HOME);
}
if(fValue == LD_TRAVELING) {
Serial.println("Traveling");
stepBySteps(STEPS_TRAVELING);
}
if(fValue == LD_VERACODE) {
Serial.println("Veracode");
stepBySteps(STEPS_VERACODE);
}
if(fValue == LD_CHURCH) {
Serial.println("Church");
stepBySteps(STEPS_CHURCH);
}
if(fValue == LD_MORTAL_PERIL) {
Serial.println("Mortal Peril!");
stepBySteps(STEPS_MORTAL_PERIL);
}
if(fValue == LD_GLOUCESTER) {
Serial.println("Glostah");
stepBySteps(STEPS_GLOUCESTER);
}
if(fValue == PLUS_ONE) {
Serial.println("Forward one.");
stepBySteps(clockStepper.currentPosition() + STEPS_ONE, true);
}
if(fValue == MINUS_ONE) {
Serial.println("Back one.");
stepBySteps(clockStepper.currentPosition() - STEPS_ONE, true);
}
if(fValue == PLUS_FIVE) {
Serial.println("Forward five.");
stepBySteps(clockStepper.currentPosition() + STEPS_FIVE, true);
}
if(fValue == MINUS_FIVE) {
Serial.println("Back five.");
stepBySteps(clockStepper.currentPosition() - STEPS_FIVE, true);
}
if(fValue == NO_MOVEMENT || fValue == "") {
Serial.println("Not moving.");
}
} else {
Serial.print(F("Failed to receive the latest feed value!"));
}
}
void stepBySteps(int newPosition, boolean resetWhenDone) {
clockStepper.enableOutputs();
clockStepper.moveTo(newPosition);
while (clockStepper.isRunning()) {
clockStepper.run();
delay(DELAY);
}
clockStepper.disableOutputs();
if (resetWhenDone) {
clockStepper.setCurrentPosition(0);
}
}
Still to come, if I ever get around to it:
Alternative methodologies for reading the feed (publish/subscribe).
Secure WiFi communication.
Adjustment (such as after power disconnect) via an induction sensor.
One of the best parts of the March for Science Sarah and I attended on April 22, 2017, in Washington, D.C., was the nearly endless creativity the marchers put into their signs. Not too many were repeated, and few would have been considered offensive. The preview image here is my sign, cribbed from “Stand back! I’m going to try science!” of XKCD origin.
All the signs we photographed:
[Best_Wordpress_Gallery id=”1″ gal_title=”Signs of Science”]
The TramBot—When my nephew Dave Matheson (a veterinary grad student at Prince Edward Island) stopped in for a day-long visit, we constructed a TramBot that ran on a string stretched across an upstairs room with a light-activated set of “grabsâ€â€”perfect for bombing runs. This was inspired by the “Bomber Fly†seen in assorted Lego media.
Yes, I Always Over-Design
If you’ve seen the Bomber Fly in the Lego publications, then you will immediately notice that my creation is much bigger, and probably heavier. I developed a fear of minimalism after my very first RIS creation quite literally shook itself to pieces in under 10 seconds.
Features and Innovation Details
The forward-reverse pulleys are driven by a belt drive, although a geared drive would have been fine in this case.
There are bumpers connected to touch sensors on each end that reverse the drive pulley motor when triggered. Because the string is at about a 45º angle to the wall, we added the tires to keep the bumper rods from slipping. (Before this was done, the bumpers would sometimes just glance off the wall without triggering the touch sensors, as the robot tried to keep moving.)
We solved the problem of timing on the “grabs†(the name alludes to Gerry Anderson’s Supermarionation Thunderbirds program—see https://www.gis.net/~fm/) by using a belt drive, and setting the motor run time to one second longer than the absolute maximum necessary. This allowed the grabs to automatically re-synchronize, be movable by hand, and grip objects of various sizes.
The grabs are light-triggered. We used the Lego light sensor, and programmed it so that a flashlight beamed on it would trigger the grabs’ open or close sequence. This allowed for precise payload delivery.
My sons Isaac and John, my Nephew Dave, and I perform some final adjustments and testing.
At three years old, my son Isaac might have been the youngest person ever to construct a Lego MindStorms project. Although he calls it a robot, it is more of a contraption than a real robot … but I cannot help but be impressed.
Isaac built this entirely without help—he even connected the RCX to the motor properly on his own. The design is entirely his; I never built anything similar.
Isaac grins as he contemplates his world conquest.
This contraption, which he calls a “punching robot,†uses an assortment of Lego axles that rest within a 40t gear, that is directly mounted on the motor. Attached to several of the outer axles are the shock absorber pieces. These shock absorber pieces extend outward from the central gear when the motor is activated, and will repeatedly punch whatever the robot is placed near.
Back at Veracode’s last Hackathon, I published the video below. People have started discovering this and asking questions about it, so here is the code for it:
/*
Weasley Clock
-------------
Created by Doug "LegoDoug" Wilcox for Veracode Hackathon IX.
Video of the completed project is at https://www.youtube.com/embed/oRUViFnxKsg.
"Share and enjoy."
*/
// Arduino SPI (Serial Peripheral Interface) library - https://www.arduino.cc/en/Reference/SPI
#include <SPI.h>
// Arduino Ethernet library - https://www.arduino.cc/en/Reference/Ethernet
#include <Ethernet.h>
// Arduino Stepper library - https://www.arduino.cc/en/Reference/Stepper
#include <Stepper.h>
// Adafruit REST IO library - https://learn.adafruit.com/adafruit-io/arduino
// See also https://www.arduino.cc/en/Tutorial/WebClientRepeating
#include "Adafruit_IO_Client.h"
// assign a MAC address for the ethernet controller.
byte mac[] = {
0x8C, 0xDC, 0xD4, 0x4A, 0xC9, 0xC2
};
// initialize the library instance:
EthernetClient client;
// last time the Arduino connected to the server, in milliseconds
unsigned long lastConnectionTime = 0;
// delay between retrieving updates, in milliseconds
const unsigned long requestInterval = 5000L;
// Configure Adafruit IO access. You will need to create your own
// Adafruit IO account (free), and set up a feed, and provide your
// feed and AIO key in the code below.
#define AIO_FEED "weasleyclockstatus"
#define AIO_KEY "XXXXXXXXXXXXXXXXXXXXXXXXXXX"
// Create an Adafruit IO Client instance. Notice that this needs to take a
// WiFiClient object as the first parameter, and as the second parameter a
// default Adafruit IO key to use when accessing feeds (however each feed can
// override this default key value if required, see further below).
Adafruit_IO_Client aio = Adafruit_IO_Client(client, AIO_KEY);
// Alternatively to access a feed with a specific key:
Adafruit_IO_Feed clockFeed = aio.getFeed(AIO_FEED, AIO_KEY);
// States - These are the codes that correspond to specific clock positions.
const String LD_HOME = "ld_na";
const String LD_TRAVELING = "ld_tr";
const String LD_VERACODE = "ld_of";
const String LD_CHURCH = "ld_ch";
const String LD_MORTAL_PERIL = "ld_mp";
const String LD_GLOUCESTER = "ld_gl";
// Steps - How many steps the motor needs to move to point to a specific position
// on the clock.
const int STEPS_HOME = 0;
const int STEPS_TRAVELING = 750;
const int STEPS_VERACODE = 1600;
const int STEPS_CHURCH = 2450;
const int STEPS_MORTAL_PERIL = 3350;
const int STEPS_GLOUCESTER = 4350;
// Someday, I will determine what this actually does. (I don't think, functionally,
// it has any affect.)
const int stepsPerRevolution = 200;
long motorPosition = 0L; // Number of steps the motor has taken.
String fValue = ""; // Feed value.
Stepper clockStepper(stepsPerRevolution, 7, 6, 5, 4, 8);
void setup() {
// start serial port:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native
// USB port only, on certain Arduino models.
}
// give the ethernet module time to boot up:
delay(1000);
// start the Ethernet connection using a fixed IP address and DNS server:
//Ethernet.begin(mac, ip, myDns);
// Or, just start it with dynamic DNS by giving it a MAC address.
Ethernet.begin(mac);
// print the Ethernet board/shield's IP address:
Serial.print("My IP address: ");
Serial.println(Ethernet.localIP());
clockStepper.setSpeed(20);
}
void loop() {
// Wait for a bit and read the current feed value.
Serial.println(F("Waiting ..."));
delay(requestInterval);
// To read the latest feed value call the receive function on the feed.
// The returned object will be a FeedData instance and you can check if it's
// valid (i.e. was successfully read) by calling isValid(), and then get the
// value either as a text value, or converted to an int, float, etc.
FeedData latest = clockFeed.receive();
if (latest.isValid()) {
Serial.print(F("Received value from feed: ")); Serial.println(latest);
// By default the received feed data item has a string value, however you
// can use the following functions to attempt to convert it to a numeric
// value like an int or float. Each function returns a boolean that indicates
// if the conversion succeeded, and takes as a parameter by reference the
// output value.
// Want some fun? Learning about "conversion from 'FeedData' to non-scalar
// type 'String' requested" the hard way.
//
// If I remember correctly, it was a casting error caused by trying to use
// the 'latest' variable as a String, directly.
// The following line casts 'latest' to a string and lets us use it as 'fValue'.
fValue = latest;
if(fValue == LD_HOME) {
Serial.println("Nashua");
stepBySteps(STEPS_HOME);
}
if(fValue == LD_TRAVELING) {
Serial.println("Traveling");
stepBySteps(STEPS_TRAVELING);
}
if(fValue == LD_VERACODE) {
Serial.println("Veracode");
stepBySteps(STEPS_VERACODE);
}
if(fValue == LD_CHURCH) {
Serial.println("Church");
stepBySteps(STEPS_CHURCH);
}
if(fValue == LD_MORTAL_PERIL) {
Serial.println("Mortal Peril!");
stepBySteps(STEPS_MORTAL_PERIL);
}
if(fValue == LD_GLOUCESTER) {
Serial.println("Glostah");
stepBySteps(STEPS_GLOUCESTER);
}
} else {
Serial.print(F("Failed to receive the latest feed value!"));
}
}
void stepBySteps(int newPosition) {
if(motorPosition == newPosition) {
Serial.println("No movement required.");
return;
}
long steps = newPosition - motorPosition;
clockStepper.step(steps);
motorPosition = newPosition;
Serial.print("position should now be:" );
Serial.println(motorPosition);
}
Remember Scotty’s remark about his nephew in Star Trek II: The Wrath of Khan? (No, of course you don’t.) Scotty explains to Kirk, after an inappropriately emotional response by Midshipman Preston: “My sister’s youngest, Admiral. Crazy to get to space.”
“Come on, R2, we’re going.”
Although I never pursued a career as an astronaut, I certainly remain, “Crazy to get to space,” and the description from Khan still resonates with me. I may yet get there, in my lifetime, especially with companies like SpaceX competing to make the cost of getting to orbit as low as possible.
For now, I’m going to have to settle for a proxy. Eliszabeth* MacDougal, one of the human family members I inherited when I married Sarah Latimer, has a friend, Cian Branco, who offered her the chance to send something small up on the Terrior Improved Orion rocket as part of the RockSat-C program. Eliszabeth realized this would be thrilling to me, and passed along her opportunity.
I ordered a new Lego R2-D2 minifigure, and a few parts to complete another mini-me as an astronaut, and shipped them off to Eliszabeth. They will be going up on Thursday, June 23, 2016, somewhere between 6:00 and 10:00 am, from the NASA facility at Wallops Island, Virginia. (My son, David, and I stood on our roof in the cold in October, 2014, to watch a night launch from Wallops.)
Update: (June 24, 2016) I got up early to watch the launch today! In my mind, I was thinking, Saturn V. Long, slow acceleration. This is, uh, quite a bit smaller, and it zoomed upward so quickly I missed the rocket itself in the launch video screen capture. (The video will be posted soon by NASA/Wallops, anyway.) The crew was worried about missing the launch window due to weather, and debated skipping the camera alignment step. In addition to the pad camera, there was a UAV (drone) flying around, as some of the pictures below show.
The rocket got to its apogee of 119.08 km (74.0 miles) almost immediately. The payload detached successfully, and hit splashdown in the Atlantic, where it would be recovered, only 8 or 9 minutes later.
Update: (June 24, 2016, 16:05) Just got the official word from Cian: “Hey Doug, will send pics a bit later, currently wrecked. Your minis all went up and returned fine. I have pics of reintegration. Cheers!”