Cleanup in aisle four…

I have just spent far too much time going back and editing all the posts to this site which include source code. WordPress has done a wonderful job mangling them, but I think I finally have a solution in place, moving forward, that should prevent it. The ALLRAM BBS conversion project has also been updated to the latest version.

Also, you will notice the theme has been changed. I was having some issues with the other terminal-looking theme, and it didn’t support all of the things I liked having (like the horizontal menu bar at the top of each page). When I find time, I will learn how to customize WordPress and try to make this theme look more retro and less generic.

Greetings from the Sub-Etha!

Don’t Panic!

You have been diverted.

Welcome to the new home of…

---------|---------|---------|---------|---------|---------|---------|---------|
       _______              __             _______             __
      / _____/\            / /\           / _____/\           / /\
     / /\____\/           / / /          / /\____\/  __      / / /     ______
    / /_/__    __  __    / /_/_   ___   / /_/     __/ /_    / /_/_    /___  /\
   /____  /\  / /\/ /\  / ___ /\ /__/\ / ___/\   /_  __/\  / __  /\  _\__/ / /
   \___/ / / / / / / / / /\/ / / \__\// /\__\/   \/ /\_\/ / /\/ / / / __  / /
 _____/ / / / /_/ / / / /_/ / /      / /_/__     / /_/   / / / / / / /_/ / /
/______/ / /_____/ / /_____/ /      /______/\   /___/\  /_/ /_/ / /_____/ /
\______\/  \_____\/  \_____\/       \______\/   \___\/  \_\/\_\/  \_____\/
 =======    ======    ======   ===   =======   ======    ======    ======
                                S O F T W A R E
                               Established 1990.

      "In Support of the CoCo and OS-9" ... and Perl, and Arduino, and...

---------|---------|---------|---------|---------|---------|---------|---------|

In 1990, Sub-Etha Software was formed in Lufkin, Texas. You can read all about it, if you are curious. Since then, much has changed. It’s hard to believe that was almost 25 years ago!

Although Sub-Etha hasn’t done much for years, for the past few months, I have been posting on my Apple site, www.appleause.com, about my exploits with the Arduino platform. I haven’t done this much recreational programming since my days using the Radio Shack Color Computer. This has made me decide to dust off my old software company, Sub-Etha Software, and set up this website. Although I have had the domain for many years, it was just a subsection of one of my personal sites… until tonight.

I have now migrated all my programming-related posts from the Appleause site over to this one. I think they will fit in better here, and it finally gave me an excuse to do something with this domain.

So here it is – the all-new Sub-Etha Software website. Here you will find historical information about the original Sub-Etha, which started back in 1990 to offer products for the Radio Shack Color Computer and Microware OS-9 operating system. There is even a page which will eventually document the items we made for the Interactive Media Systems MM/1 computer, which ran OS-9/68000 (“OSK”). I may even make a page covering some of the items we sold after I took a job with Microware and had to shut down Sub-Etha. (Hint: Sub-Etha SoftWEAR didn’t sell software…)

Around 2001, I learned a bit of Perl programing and created a few simple scripts which I made available free under the Sub-Etha Software name, so Perl gets a page here, too. And lastly, some of my recent development efforts on the Arduino and related devices like the Teensy 2.0. I may even through in some BASIC Stamp talk at some point if I ever dig out my old hardware.

But since Sub-Etha started with the CoCo, it remains with the CoCo. There will be discussions about new CoCo related projects, and a listing of some of CoCo websites I think all CoCoists should check out.

Stay tuned…

Part 3: Debouncing digital inputs.

See also: Part 1, Part 1b, Part 2, and Part 3.

It seems I completely forgot the story I started telling awhile ago. If you did, too, you can go back and read about how I got started with Arduino, along with a few more notes, and finally, the one where I started dissecting my first sketch which read inputs from a haunted house pressure mat and turned them in to serial signals some software could read.

Back in February, I was discussing a problem I noticed with my first Arduino project. When switches would connect, and generate the serial strings for on/off like I wanted, I would often see the data stutter, toggling back and forth quickly before resting at on or off. I recognized this problem from learning about how the TRS-80 Color Computer’s keyboard matrix worked, and I knew the solution would be to add some debounce code to my sketch.

There actually is a Debounce library available to the Arduino, but I chose to write my own since it was a good opportunity to learn. Plus, the Bounce library seemed to provide much more capability than I needed. You can find this library here:

http://playground.arduino.cc//Code/Bounce

It seems very easy to use, but instead, I chose to apply some of the information I read on another section of the Arduino site. My debounce code would look like this:

/* For I/O pin status and debounce. */
unsigned int pinStatus[DI_PIN_COUNT];    // Last set PIN mode.
unsigned long pinDebounce[DI_PIN_COUNT]; // Debounce time.
unsigned int debounceRate = DEBOUNCE_MS; // Debounce rate.

I would create arrays to hold the last known pin status, and a time value for that pin. The time value would be used to mark debounce time. The debounce rate variable would be used for how long the debounce should be.

First, notice I was using “unsigned int” for the pin status. On the Arduino, and int is a 16-bit value, and takes up 2-bytes of RAM. The pin count could easily be represented with byte variable instead, saving a byte for each instance. It’s not a big deal wasting a few bytes for a small sketch, but for big projects, every last byte can matter. SO, don’t code like that. Use a byte. Or if you are really in a crunch, remember that a byte is made up of eight bits, so one byte could actually be used to track the status of eight different pins. So, my original version would take 16 bytes of RAM to track eight pins, but I could have done that using only one byte. That’s quite a savings. I can discuss using bits in a future article.

Okay, so those were my variables. The actual code that did all the work looks like this. First, I defined the pins I would be using for the project:

/* TX/RX pins are needed to USB/serial. */
#define DI_PIN_START  2
#define DI_PIN_END    12
#define DI_PIN_COUNT  (DI_PIN_END-DI_PIN_START+1)

The different Arduinos and Teensys and such have different I/O pin numbers. I decided I would just use a range of pins, so I specify the starting pin and ending pin. In this example, I skipped pin 0 and 1 since those are used by the serail port. Pin 13 is connected to an LED I wanted to blink (letting me know the board was alive and processing), so I could use pins 2-12 and get eleven pins to wire up to the pressure mats in the haunted house.

Inside setup(), I did a loop through these pins to put them in INPUT mode (using the pull-up resistor so I didn’t need extra wiring), and to initialize my arrays. You will notice I have something commented out. Originally, I read the current state of all the pins so I could mark them as changing later. So, if a pressure mat was “on” when it started, it would do nothing until the mat was released. This sounded like a good idea, but it meant there would be no way for the software to know things needed to go “now” on power up, so instead I set the status to HIGH (meaning off), thus if a mat were depressed when the program started, it would immediately see that as a change to LOW and send out the serial data.

  // Initialize the pins and pinStatus array.
  for (int thisPin=0; thisPin < DI_PIN_COUNT; thisPin++ )
  {
    // Set pin to be digital input using pullup resistor.
    pinMode(thisPin+DI_PIN_START, INPUT_PULLUP);
    // Read and save the current pin status.
    pinStatus[thisPin] = HIGH; //digitalRead(thisPin+DI_PIN_START);
    // Clear debounce time.
    pinDebounce[thisPin] = 0;
  }

Inside the main loop(), I would once again loop through all the pins and check their status:

  // Loop through each Digital Input pin.
  for (int thisPin=0; thisPin < DI_PIN_COUNT; thisPin++ )
  {
    // Read the pin's current status.
    int status = digitalRead(thisPin+DI_PIN_START);

Next, I would compare the current status to the one stored in the array and see if it had changed. No need to do anything for a pin that reads HIGH if it previously read HIGH. We only care about changes in status, so someone standing on a pressure mat wouldn’t trigger it dozens of times before they stepped off.

    // In pin status has changed from our last toggle...
    if (status != pinStatus[thisPin])
    {

And now it gets fun. The pinDebounce[] array is used to hold a time value, or 0 if there is nothing going on with that pin. If it has a number in it, that means we are in the process of counting down a debounce value. If it is 0, we need to start a debounce counter. The way we do that is by looking at the current time using millis(), and adding the debounce time to it, and storing that. So if millis() is 1200 when a pressure mat is triggered, and we are using a debounce rate of 1 second (1000 millis), we would store 1200+1000=2200 in that variable:

      // Remember when it changed, starting debounce mode.
      // If not currently in debounce mode,
      if (pinDebounce[thisPin]==0)
      {
        // Set when we can accept this as valid (debounce is considered
        // done if the time gets to this point with the status still the same).
        pinDebounce[thisPin] = millis()+debounceRate;
      }

Next, we check the pin to see if it’s non-zero. If it is, it indicates this pin is in debounce mode, and we need to see if the current time in millis() is greater than the pin’s pinDebounce[] time that was set earlier. If it is, we have seen the status hold long enough to believe it is a real trigger, and emit either “on” or “off” messages depending on which way the pin just toggled:

      // Check to see if we are in debounce detect mode.
      if (pinDebounce[thisPin]>0)
      {
        // Yes we are. Have we delayed long enough yet?
        if ( (long)(millis()-pinDebounce[thisPin]) >= 0 )
        {
            // Yes, so consider it switched.
            // If pin is Active LOW,
            if (status==LOW)
            {
              // Emit UPPERCASE "On" character.
              Serial.println(char(65+thisPin));
            } else {
              // Emit lowercase "Off" character.
              Serial.println(char(97+thisPin));
              if (pinsOn>0) pinsOn--;
              if (pinsOn==0) digitalWrite(LED_PIN, LOW);
            }

Then we remember this new status, and reset the debounce counter for that pin back to zero.

            // Remember current (last set) status for this pin.
            pinStatus[thisPin] = status;
            // Reset debounce time (disable, not looking any more).
            pinDebounce[thisPin] = 0;
        } // End of if ( (long)(millis()-pinDebounce[thisPin]) >= 0 )

      } // End of if (pinDebounce[thisPin]>0)
    }
    else // No change? Flag no change.
    {
      // If we were debouncing, we are no longer debouncing.
      pinDebounce[thisPin] = 0;
    }
  } // End of for()

At the very end, we have a condition that is met only if the pin’s status has not changed since the last time.

Does this look correct to you? If the pin hasn’t changed, I am resetting the debounce back to 0. But what if the pin were in a debounce mode? Wouldn’t we want to keep counting? It looked weird to me as I put the code here, but it is correct. If the pin has not changed, we are not interested in debouncing. If the pin is HIGH, it just resets to zero over and over (useless), but if it changes from HIGH to LOW, we enter the code and start the debounce. Note that the pinStatus[] variable has not been updated yet, so it remains HIGH.

The next loop through, the status of the pin is read again. If it is still LOW, we enter the code again because it is still different than the last pinStatus[], which is still HIGH. We do more debounce checks. And this continues.

The reason the reset to 0 is correct is because of this. We are not comparing the status to the last time we read, but to the last time we considered it switched after a debounce. As we continue the example, at some point, the pin has held its status long enough to be considered debounced, and we toggle it and update pinStatus[] to now be LOW, and the debounce counter is reset.

Clear as mud? Because we have not really change the status, we keep setting it to 0. But as long as the current pin status is different than the previously saved pinStatus[], we will keep entering that loop and checking, never getting to the reset 0. In fact, the only time we get to the reset 0 if current pinStatus is the same as the last pinStatus[]. So, a switch not switching will just reset 0 all the time, but once the switch has changed, it will fall in to the code to check debounce and never touch the reset 0 code. This is what resets the debounce timer if the switch goes from ON to OFF (which should trigger, but not yet), then pops back to ON quickly… resetting the counter… Then if it pops to OFF again, it starts the counter fresh.

I hope that makes sense.

Here’s the full script. Remember, it was the first thing I ever wrote for the Arduino, and I have done more to it since then. You will also see I have a part that checks the serial input for “?” to be typed, then prints out the current pin status. A nice thing for debugging.

Hope this helps… The next version will add Analog inputs (for reading laser tag light sensors), and then this code morphs in to an Atari joystick converter.

Until then…

/*-----------------------------------------------------------------------------

Arduino Digital Input

Monitor digital inputs, then emit a serial character depending on the pin
status. The character will be uppercase for pin connected (N.O. button push)
and lowercase for pin disconnected (N.O. button released). It will begin with
"A" for the first I/O pin, "B" for the next, and so on. Currently, with pins
0 and 1 used for serial TX/RF, this leaves pins 2-12 available (10), with pin
13 reserved for blinking the onboard LED as a heartbeat "we are alive"
indicator.

This software was written to allow an Arduino act as a cheap input/trigger
interface to software such as VenueMagic. As I do not own a copy of this
software, I could only test it under the 15 day trial. There may be other
issues...

2012-10-09 0.0 allenh - Initial version.
2012-10-11 0.1 allenh - Updated debounce to work with timing rollover, via:
                        http://www.arduino.cc/playground/Code/TimingRollover
                        Fixed bug where last DI pin was not being used.

-----------------------------------------------------------------------------*/
//#include
#include

/* TX/RX pins are needed to USB/serial. */
#define DI_PIN_START  2
#define DI_PIN_END    12
#define DI_PIN_COUNT  (DI_PIN_END-DI_PIN_START+1)

#define LED_PIN 13
#define LEDBLINK_MS 1000
#define DEBOUNCE_MS 100 // 100ms (1/10th second)

/*---------------------------------------------------------------------------*/
/*
 * Some sanity checks to make sure the #defines are reasonable.
 */
#if (DI_PIN_END >= LED_PIN)
#error PIN CONFLICT: PIN END goes past LED pin.
#endif

#if (DI_PIN_START < 2)
#error PIN CONFLICT: PIN START covers 0-TX and 1-RX pins.
#endif

#if (DI_PIN_START > DI_PIN_END)
#error PIN CONFLICT: PIN START and END should be a range.
#endif
/*---------------------------------------------------------------------------*/

/* For I/O pin status and debounce. */
unsigned int  pinStatus[DI_PIN_COUNT];      // Last set PIN mode.
unsigned long pinDebounce[DI_PIN_COUNT];    // Debounce time.
unsigned int  debounceRate = DEBOUNCE_MS;   // Debounce rate.
unsigned long pinCounter[DI_PIN_COUNT];

/* For the blinking LED (heartbeat). */
unsigned int  ledStatus = LOW;             // Last set LED mode.
unsigned long ledBlinkTime = 0;            // LED blink time.
unsigned int  ledBlinkRate = LEDBLINK_MS;  // LED blink rate.

unsigned int pinsOn = 0;

/*---------------------------------------------------------------------------*/

void setup()
{
  // Just in case it was left on...
  wdt_disable();
  // Initialize watchdog timer for 2 seconds.
  wdt_enable(WDTO_4S);

  // Initialize the pins and pinStatus array.
  for (int thisPin=0; thisPin < DI_PIN_COUNT; thisPin++ )
  {
    // Set pin to be digital input using pullup resistor.
    pinMode(thisPin+DI_PIN_START, INPUT_PULLUP);
    // Read and save the current pin status.
    pinStatus[thisPin] = HIGH; //digitalRead(thisPin+DI_PIN_START);
    // Clear debounce time.
    pinDebounce[thisPin] = 0;

    pinCounter[thisPin] = 0;
  }

  // Set pin 13 to output, since it has an LED we can use.
  pinMode(LED_PIN, OUTPUT);

  // Initialize the serial port.
  Serial.begin(9600);

  // Docs say this isn't necessary for Uno.
  while(!Serial) {
    ;
  }

  // Emit some startup stuff to the serial port.
  Serial.println("ArduinoDI by Allen C. Huffman (alsplace@pobox.com)");
  Serial.print("Configured for: ");
  Serial.print(debounceRate);
  Serial.print("ms Debounce, ");
  Serial.print(DI_PIN_COUNT);
  Serial.print(" DI Pins (");
  Serial.print(DI_PIN_START);
  Serial.print("-");
  Serial.print(DI_PIN_END);
  Serial.println(").");
  Serial.println("(Nathaniel is a jerk.)");
}

/*---------------------------------------------------------------------------*/

void loop()
{
  // Tell the watchdog timer we are still alive.
  wdt_reset();

  // LED blinking heartbeat. Yes, we are alive.
  if ( (long)(millis()-ledBlinkTime) >= 0 )
  {
    // Toggle LED.
    if (ledStatus==LOW)  // If LED is LOW...
    {
      ledStatus = HIGH;  // ...make it HIGH.
    } else {
      ledStatus = LOW;   // ...else, make it LOW.
    }
    // Set LED pin status.
    if (pinsOn==0) digitalWrite(LED_PIN, ledStatus);
    // Reset "next time to toggle" time.
    ledBlinkTime = millis()+ledBlinkRate;
  }

  // Check for serial data.
  if (Serial.available() > 0) {
    // If data ready, read a byte.
    int incomingByte = Serial.read();
    // Parse the byte we read.
    switch(incomingByte)
    {
      case '?':
        showStatus();
        break;
      default:
        break;
    }
  }

  // Loop through each Digital Input pin.
  for (int thisPin=0; thisPin < DI_PIN_COUNT; thisPin++ )
  {
    // Read the pin's current status.
    int status = digitalRead(thisPin+DI_PIN_START);

    // In pin status has changed from our last toggle...
    if (status != pinStatus[thisPin])
    {
      // Remember when it changed, starting debounce mode.
      // If not currently in debounce mode,
      if (pinDebounce[thisPin]==0)
      {
        // Set when we can accept this as valid (debounce is considered
        // done if the time gets to this point with the status still the same).
        pinDebounce[thisPin] = millis()+debounceRate;
      }

      // Check to see if we are in debounce detect mode.
      if (pinDebounce[thisPin]>0)
      {
        // Yes we are. Have we delayed long enough yet?
        if ( (long)(millis()-pinDebounce[thisPin]) >= 0 )
        {
            // Yes, so consider it switched.
            // If pin is Active LOW,
            if (status==LOW)
            {
              // Emit UPPERCASE "On" character.
              Serial.println(char(65+thisPin));
              pinCounter[thisPin]++;
              pinsOn++;
              digitalWrite(LED_PIN, HIGH);
            } else {
              // Emit lowercase "Off" character.
              Serial.println(char(97+thisPin));
              if (pinsOn>0) pinsOn--;
              if (pinsOn==0) digitalWrite(LED_PIN, LOW);
            }
            // Remember current (last set) status for this pin.
            pinStatus[thisPin] = status;
            // Reset debounce time (disable, not looking any more).
            pinDebounce[thisPin] = 0;
        } // End of if ( (long)(millis()-pinDebounce[thisPin]) >= 0 )

      } // End of if (pinDebounce[thisPin]>0)
    }
    else // No change? Flag no change. if (status != pinStatus[thisPin])
    {
      // If we were debouncing, we are no longer debouncing.
      pinDebounce[thisPin] = 0;
    }
  } // End of for()
}

void showStatus()
{
  int status = 0;

  Serial.print("DI: ");

  for (int thisPin=0; thisPin < DI_PIN_COUNT; thisPin++ )
  {
    // Read the pin's current status.
    int status = digitalRead(thisPin+DI_PIN_START);
    Serial.print(thisPin+DI_PIN_START);
    Serial.print("=");
    Serial.print(digitalRead(thisPin+DI_PIN_START));
    Serial.print(" ");
  }
  Serial.println("");

  for (int thisPin=0; thisPin < DI_PIN_COUNT; thisPin++ )
  {
    Serial.print(thisPin+DI_PIN_START);
    Serial.print(":");
    Serial.print(pinCounter[thisPin]);
    Serial.print(" ");
  }
  Serial.println("");

  //Serial.print("millis() = ");
  //Serial.println(millis());
}
/*---------------------------------------------------------------------------*/
// End of file.

P.S. – Don’t mind my rude comment to Nathaniel in the status display. He’s the effects designer out at the Sleepy Hollow Haunted Scream Park I was doing this project for, and I only kid him because he’s such a great guy. He’s really not a jerk. Honest.

CoCo appears on TWiT

Curtis Boyle, a long time TRS-80 Color Computer developer, donated some Radio Shack CoCo stuff to Leo Laporte’s TWiT TV studio museum. (If you don’t know what that is, don’t worry. I would have no idea myself if it weren’t for working at a place that sold satellite TV systems back around 2002, where I watched him on a show at the defunct cable channel Tech TV.) Anyway, Curtis wrote a demo program that drew the TWiT logo and flashed colors, and it was shown on the live stream between recording some of their shows.

Screen shots follow. Good job, Curtis!

TRS-80 Color Computer items on Leo's desk.
TRS-80 Color Computer items on Leo’s desk.
Curtis Boyle's demo program, shown on TWiT between shows
Curtis Boyle’s demo program, shown on TWiT between shows

4/19/2013 Update: Curtis shared his source code on the CoCo mailing list today.


10 PALETTE 8,63:PALETTE 0,0:WIDTH40:CLS1
20 ON BRK GOTO 410
30 'TWIT logo CC3 program by L. Curtis Boyle
40 POKE65497,0:INPUT "<R>GB OR <C>OMPOSITE MONITOR (TV):";MN$
50 PALETTE 0,0:PALETTE 3,63
60 IF MN$<>"R" AND MN$<>"r" THEN 80
70 PALETTE 1,36:PALETTE 2,25:BC=0:GOTO 90
75 'Depending on your TV/Composite monitor settings, you may need to adjust these
80 PALETTE 1,8:PALETTE 2,31:BC=0
90 PALETTE 4,BC:HSCREEN2:HCLS4:POKE 65434,BC
100 HCIRCLE(70,96),70,2
110 HPAINT(70,96),2,2
130 HCIRCLE(70,96),56,0,1,.5,1
140 HCIRCLE(70,96),44,0,1,.51,.99
150 HCOLOR0:HLINE(15,92)-(125,104),PSET,BF
160 HPAINT(18,87),0,0
170 HLINE(50,70)-(62,134),PSET,BF
180 HLINE(78,96)-(90,134),PSET,BF
190 HCIRCLE(84,76),7,1:HPAINT(84,76),1,1
200 HCOLOR3:HPRINT(18,19),"Netcasts you love from"
210 HPRINT(21,20),"people you trust"
215 'Start of "TWiT"
220 HCOLOR3:HLINE(149,65)-(191,75),PSET,BF
230 HLINE(165,75)-(175,117),PSET,BF
240 HLINE(191,75)-(200,117),PSET:HLINE-(210,117),PSET
250 HLINE-(217,91),PSET:HLINE-(224,117),PSET:HLINE-(234,117),PSET
260 HLINE-(246,65),PSET:HLINE-(236,65),PSET:HLINE-(229,91),PSET:HLINE-(222,65),PSET
270 HLINE-(212,65),PSET:HLINE-(205,91),PSET:HLINE-(198,65),PSET:HLINE-(191,65),PSET
280 HPAINT(194,66),3,3
290 HLINE(254,75)-(264,117),PSET,BF:HCIRCLE(259,65),7,1:HPAINT(259,65),1,1
300 HLINE(272,65)-(314,75),PSET,BF:HLINE(288,75)-(298,117),PSET,BF
310 FORT=1 TO 4000:NEXT T
320 ST=1:EN=15
330 FOR TC=ST TO EN
340 IF INKEY$="" THEN 380
350 IF ST<>1 THEN 370
360 ST=BC:EN=BC:GOTO 330
370 ST=1:EN=15:GOTO330
380 PALETTE4,TC:POKE65434,TC:FORT=1TO100:NEXTT
390 NEXTTC:GOTO330
400 GOTO 400
410 POKE65496,0:END

A cheap way to get an Arduino on WiFi

Update 3/8/2014: There is an Arduino WiFi shield for around $40 now sold by Adafruit Industries (but you have to solder on the connectors). That shield costs about as much as the TP-Link router I mention in this article, and a $20 Ethernet shield. However, with clone Ethernet shields now around $9 from China, it’s still cheaper to hack something together. (Another advantage of the TP-Link device is you can have it set up to connect and publish the connection via Ethernet, and plug it in to anything that needs it — an Arduino, an OUYA, TiVo, etc.)

To test my Arduino Ethernet code, I needed a way to get my Arduino on my home network. Unfortunately, my router is somewhere else, and I was not able to run a long ethernet cable to it. I initially experimented with making my old MacBook act as a gateway using Apple’s Internet Sharing. I was going to have it share my home WiFi internet out the ethernet port, and hook that port up to the Arduino. Unfortunately, again, it seems there is some problem with the current version of Mac OS X and Internet Sharing and I was unable to get it to work. So, I turned to a free bit of software called Ice Floor which is a GUI front end for the Unix firewall running on Mac OS X. With a bit of Googling I was able to configure Ice Floor to let my Arduino hook to the MacBook, then reach out to the Internet.

I won’t be writing about that. It was easy, once I figured it out, but I spent all night trying.

What I really wanted was a way to get my Arduino on my home WiFi.

With Arduino ethernet interfaces being real cheap if your order from China, or slightly less cheap if your order from the USA, it puzzled me that WiFi shields were so much more. Well, if you don’t need everything to fit inside a small Arduino case, you can just get one of the cheap Ethernet shields and then use one of these things:

This $23 TP-LINK WR702N WiFi router is really teeny tiny (about 2″x2″ and .5″ tall), and comes with a short ethernet cable, USB cable, and USB power supply. It has several modes of operation, including the one you would expect — plugging up to an Ethernet jack and broadcasting it as a WiFi signal. But, it also has a Client mode, so you can plug it up via Ethernet to the Arduino and then use it as a WiFi card.

Configuration was a bit tricky because I didn’t know what I was doing, but basically, you plug it up to power (USB or power adapter), and configure it via your computer and an Ethernet cable. If your computer is already on a network that is 192.186.0.x (like mine was, from my home DSL router), you will need to disable that from your computer (turn off WiFi, or unplug the Ethernet cable). The instructions (on the website) tell you to change your computer’s IP address to 192.168.0.10, and then in your web browser you go to 192.168.0.254 (which is the router’s default IP address). Up loads an admin web page.

Type in the password (admin/admin), then click the easy setup button and select Client. It will then give you a screen where you can browse to the WiFi network you wish to join, and enter the password (if it’s a protected network) and encryption method used (again, if it’s a protected network).

Once you do that, the little box will reboot and then try to connect to that WiFi hotspot, and then get an IP address from it and link the Ethernet port to the WiFi… So, configure it, then unplug it from the computer and plug it to the Arduino and… your Arduino’s Ethernet code now talks out WiFi.

So, if you ever try to telnet in to my home Arduino, that is how the connection will be getting there.

Just passing information along. Hope it helps someone.

Telnet is pretty cool.

Now processing most of the Telnet protocol!
Now processing most of the Telnet protocol!

A few evenings ago, I noticed a bunch of garbage coming on from an Ethernet connection on the Arduino when a new connection was made to the example server code. This garbage turns out to be part of the Telnet protocol. There are various escape sequences (some of which are quite large) that flow across the connection, and must be handled else they pollute the data stream.

I began writing some code to do this, and like many tangents I get on, it has led me down quite the rabbit hole of discovery. My first stop was this very helpful web page that explained a bit about how Telnet works:

http://www.softpanorama.net/Net/Application_layer/telnet.shtml

I then proceeded to read the RFC documents about Telnet, and learn more details:

http://www.faqs.org/rfcs/rfc854.html

RFC 854 covers the Telnet protocol. This document is from 1983, which is the year I was writing my *ALL RAM* BBS system which I recently ported to the Arduino. There are other RFCs that cover specific aspects of Telnet, such as all the various Options that can be set.

Initially, I created something very simple that just “ate” all the Telnet escape codes. This is small code, and should be used on any Arduino sketch that expects someone to be able to Telnet in to the device. I will finish it and post it here, or as a sample on the Arduino webpage in the Playground area.

I soon learned there were even more codes than what I first learned, so I went and found more complete references:

http://www.tcpipguide.com/free/t_TelnetOptionsandOptionNegotiation-2.htm

Even after that, I still have a few others I can generate (from the PuTTY terminal program) and see but I haven’t found good documentation on them yet. (I just know it has an option in PuTTY to send special sequences, and I went through all of them to make sure I was handling them correctly.) I have learned quite a bit about Telnet in the past few days. It’s pretty neat.

So, I am now working on two things. One is a simple EthernetServer filter that will take care of the most simple bits of Telnet. I will make it so that can be compiled out, so it’s just a “eat all the Telnet escape sequences” thing, for sketches that are very tight on space.

The bigger project is the seTelnetServer. It’s a klunky name, but it follows that naming conventions I used back when I was coding 6809 assembly language utilities for the OS-9 operating system. seTelnetServer is going to be a more complete Telnet implementation, with (conditionally compiled out) the ability to emit all the protocol debug information on the console (for those curious). I am planning on supporting some of the basic features I see various Telnet clients try to set — line versus character mode, echo and things like that. It will have hooks in the code where you can modify it and handle more if you need to. For instance, do you want to do something with the BRK sequence? Or Suspend?

I am packaging this together in to a very simple-to-use server sketch that might be as easy to use as this:

void setup()
{
telnetInit(23); // Initialize, listening on port 23
}

void loop()
{
Serial.print("Waiting for connection:");
while(!done)
{
telnetInput(buffer, 80); // Read up to 80 characters.
// do stuff...
telnetPrint("Hello, user!");
}
}

The “telnetInput()” routine would take care of listening for a new connection, if there wasn’t one, and then read input from the user (handling Telnet protocol). If they disconnect, it would return a code that could be used to detect that and reset.

I have a rough version of this working. I even added the ability (with my Ethernet library fixes) for it to receive other connections while it is handling the first one and inform them that “The system is in use. Please try back later.” And, there is even an “offline” mode, so if the operator decides to log in via serial console, it will disable the Ethernet (again, giving those who connect a “System is offline” message) while the operator is using it.

Sounds like fun. And when I am done, I plan to end up writing some Telnet software for the CoCo as well (though that has already been done for the DriveWire project).

More to come…

Multiple source files in an Arduino project

The Arduino IDE does an amazing job of hiding all the technical details of what it’s doing. This allows the some of the easiest creation of programs I have seen since the days of BASIC. From the looks of many of the forum questions over at the main Arduino website, it seems there are certainly a bunch of new programmers doing just this.

As an experience embedded programmer, much of what the Arduino IDE does seems to be magic to me. How can I just type a function without a prototype? How does it know what libraries to include when I don’t specify them? How is this able to work at all?

Over the past week, I have learned a bit more about what is going on behind the scenes. Apparently, the IDE has a preprocessor that converts the Arduino “Sketch” in to C++ code, generating prototypes and such automatically. I have already ran in to one problem with this.

Many other things remain a mystery, but at least one more has been explained today. I was very curious how one could split up a larger project in to multiple files. As it turns out, the Arduino IDE makes this super simple… Just make a new tab in the existing project.

In the Arduino 1.0.4 (current released version) editor, I noticed a square icon with a down arrow in it on the right side of the window, under the magnifying glass “search” button. I had seen this before, with “New Tab” and other options in it. I had assumed this was so you could switch between multiple projects in the same window, but now I understand this is how you have multiple files in the same project. Just create a tab, and put your code in it.

So, if I have my setup() and loop() in the main tab, and create a second tab with doSomething(), I can then call doSomething() from setup() or loop(). More magic.

I will be splitting up my various code snippets in to separate files for easy including in future projects.

I post this because I expect maybe I am not the only “experienced embedded programmer” who doesn’t read the manual.

A real Arduino Telnet server?

  • 2014/03/16 Update: The source code to this is now on GitHub. Check the Arduino link at the top of each page of this site.
This sketch tries to process Telnet protocol mesages.
This sketch tries to process Telnet protocol mesages.

The example code for the Ethernet library has some things that try to act like Telnet servers, but really all they do is open up a port and listen for data. When someone connects with a Telnet client, that client will send Telnet protocol messages trying to negotiate the connection. The Arduino examples I have found posted around do not deal with this, which means whatever “garbage” comes in could have unexpected results if the program isn’t properly ignoring invalid data.

Tonight, I began working on a more complete Telnet server for the Arduino. I am sure many of them exist, but what better way to learn than to reinvent the wheel?

I am doing a “fuller” version that would support many of the Telnet protocol options, then a dumber one that would just get rid of the protocol from the stream and ignore pretty much everything.

And, I will wrap that with a simple to use bit of code for making connections without all the tedious setup.

Comment if this project is of interest, as I have several others I may work on first.

Arduino compiler problem with #ifdefs solved.

In C, “#ifdef” or “#if defined()” are used to hide or include portions of code only if certain conditions are met. For example, my recent *ALL RAM* BBS experiment contains code for using the SD card library as well as the Ethernet library. I used #ifdef around specific blocks of code so I could compile versions with or without either of those libraries. But all is not well in Arduino land. Consider this following, simple example:

#if defined(FOO)
byte mac[] = { 0x2A, 0xA0, 0xD8, 0xFC, 0x8B, 0xEE };
#endif

void setup()
{
Serial.begin(9600);
while(!Serial);
Serial.println("Test...");
}

void loop()
{
}

This is supposed to only include the “byte mac[] =” line if “FOO” is defined, such as with:

#define FOO

However, on the current Arduino IDE (1.0.4), this simple code will fail with:

ifdef.ino: In function ‘void setup()’:
ifdef:18: error: ‘Serial’ was not declared in this scope

What? Suddenly “Serial.println()” won’t work? Moving the byte declaration outside of the #if def make it work. Very weird.

I also found a similar example, where I tried to comment out a function that used SD library variable types:

void setup()
{
Serial.begin(9600);
while(!Serial);
Serial.println("Test...");
}

void loop()
{
}

#ifdef FOO
byte fileReadln(File myFile, char *buffer, byte count)
{
}
#endif

In this example, I did not want the fileReadln() function to be included unless I had defined FOO. But, compiling this produces:

ifdef:15: error: ‘File’ was not declared in this scope
ifdef:15: error: expected primary-expression before ‘char’
ifdef:15: error: expected primary-expression before ‘count’
ifdef:15: error: initializer expression list treated as compound expression

Unhelpful. And after wasting some time on this, I started a topic in the Arduino.cc forums to ask if others were experiencing the same thing. And they were. A helpful post from parajew pointed me to this site which helped explain the problem, and offered a workaround:

http://www.a-control.de/arduino-fehler/?lang=en

The pre-processor does some stuff behind the scenes, creating prototypes and including header files where needed, and it just does it wrong. The A-Control site figured out a simple workaround, which I trimmed a bit to just adding this at the top of my scripts:

// BOF preprocessor bug prevent - insert me on top of your arduino-code
// From: http://www.a-control.de/arduino-fehler/?lang=en
#if 1
__asm volatile ("nop");
#endif

…and now either of my examples will compile as intended. Thank you, parajew and A-Control! I can now move on to my next problem…

Hope it helps you, too.