Category Archives: Arduino

Arduino programming, tips and research.

Sir Sound prototype, version 2.

Now working without the crystal. This is using a Teensy and one of the pins to generate a 4mhz signal. I will post a video in coming days, hopefully, as soon as I have some CoCo BASIC code talking to it.

The green and black wires running off of it wold go to a headphone jack that the cassette cable sold plug in to so you could feed Sound back to the CoCo without needing to use an external speaker. AUDIO ON!

Introducing the Sir Sound CoCo Sound Card

NEW “PRODUCT” ANNOUNCEMENT

The team that brought you* the CoCoPilot DriveWire Server is proud to announce their latest innovation:

“Sir Sound”

Sir Sound is a solid-state multi-voice audio synthesizer that operates over a serial transport mechanism**. It provides arcade-quality*** sound with up to three independent tonal voices plus one white noise channel all in an external module that doesn’t require voiding your warranty to install. In fact, you won’t even need tools!

Pricing is to be announced but hopefully it will be around $50. Or maybe $30. Or cheaper. Or less if you build it yourself. Heck, we’ll probably just make kit versions available since we don’t really like to solder.

Sir Sound Configurations

  • Turnkey – This is a “plug and go” version where you just plug it in and go. No special drivers are needed, as they are already built in to both BASIC and OS-9.****
  • BYOE – The bring-your-own-everything edition is shipped as a set of simple instructions containing a parts list and how to run wires between the parts.
  • Custom – Also planned to be available are various custom configurations, like what color of case it comes in.

Pricing

We estimate the thing is gonna cost us, like, ten or so bucks to make using off-the-shelf parts ordered in small quantities from China. But, to make it a product, we really should have an integrated circuit board and a case made, which will run the costs up dramatically. Rest assured, we’ll pass those unsavings along to you!

Availability

The first prototype is in the process of being tested. Quit rushing us. We’ll let you know when it’s done.

Specs

Basically it’s a Texas Instruments SN76489 sound chip hooked to a tiny Arduino micro-controller with a TTL-to-RS232 adapter. Here’s the prototype John Strong of StrongWare sent me:

SN76849 sound chip hooked to an Arduino Nano on a neat 3-D printed platform from StrongWare.

You kinda have to use some micro-controller since the sound chip turns on and starts making sound. Something has to issue the “shut up” instruction to it. If you just had hardware to translate a serial byte in to the command, and made the CoCo do all the work, the CoCo would have to load and run a program to shut the thing up every time you powered up. Fortunately, a custom-built Arduino that handles this can be done for like $5. There are cheaper PIC chips that could do it for less.

Then, you add a MAX232 type chip that goes from the TTL signal levels of the Arduino to RS232 signal levels, or using one of these $3 (or less) boards that’s already wired:

TTL-to-RS232 adapter.

Lastly, add a CoCo serial cable (4-pin DIN to DB9), and you are set.

Prototype “Sir Sound” sound module for the CoCo (or anything with a serial port, actually).

A small program on the Arduino will monitor the serial port for bytes and then relay them to the sound chip.

By doing some POKEs in BASIC to set the baud rate, you could make music by doing things like this:

REM PLAY MIDDLE C
PRINT #-2,CHR$(&H8E);CHR$(&H1D);CHR$(&H90);

FOR A=1 TO 1000:NEXT A

REM VOLUME OFF
PRINT #-2,CHR$(&H9F);

The notes always play, so you shut them off by setting volume off. There are different channel values for each of the four channels.

I envision having a “raw” mode where the device just translates the bytes from serial to the sound chip, and a “smart” mode where you could use an API and just send note values (like 1-88 of a piano keyboard, or MIDI note values).

“Smart” mode could simplify the control so it might look like this:

REM ALL DATA: PLAY CHANNEL 0, NOTE 10, AT VOLUME 15
PRINT #-2,CHR$(&H00);CHR$(&HA);CHR$(&HF);

REM NOTE ONLY: PLAY CHANNEL 0, NOTE 10
PRINT #-2,CHR$(&H01);CHR$(&HA);

REM NOTE ONLY: PLAY CHANNEL 1, NOTE 10
PRINT #-2,CHR$(&H11);CHR$(&HA);

REM VOLUME ONLY: CHANNEL 0, VOLUME 5
PRINT #-2,CHR$(&H20);CHR$(&H5);

And, I could also add a “super smart” mode where it could parse PLAY command-style strings, then spool them in the background while you do other things:

REM PLAY COMMAND, CHANNEL 0
PRINT #-2,CHR$(&H30);"CDEFGAB";

And, a “super super smart” mode could let it store string sequences, and play them by triggering with a simple byte:

REM STORE NOTE SEQUENCE 0
PRINT #-2,CHR$(&H40);"CCDCECFECCDCECFE";CHR$(0);

REM PLAY NOTE SEQUENCE 0
PRINT #-2,CHR$(&H50);

REM PLAY NOTE SEQUENCE 0 FIVE TIMES
PRINT #-2,CHR$(&H55);

…or whatever. You could sequence them together, like MIDI sequencers do, and have complex patterns that could play in the background while the program does other things.

There are lots of possibilities. We could even see about using the Carrier Detect line as a way to tell if the sound card was still playing something (rather than needing routines to read data back from the device, which would be doable but not from BASIC without assembly language code).

If this “sounds” fun to you, leave a comment…

Until then…


Notes:

* If you call making a blog post “bringing it” to you.

** It plugs in to the Serial I/O port. “Sir” sounds like “Ser”, get it? Marketing thought SerSound wasn’t friendly enough.

*** This part is true. The same sound hardware is used in the arcade mega-hits Congo Bongo and Mr. Do, among others.

**** PRINT#-2, yo.

Arduino and the Texas Instruments SN76489

You may have never heard of the Texas Instruments SN76489, but if you are reading this article, there’s a good chance you have heard it.

The SN76489 is a sound chip which, according to the Wikipedia entry, was used in systems such as:

…and in arcade games such as:

…and many more. I am just naming the machines and games I have heard of or seen/played.

Side Note: The Wikipedia entry also claims the Sega Genesis used one, but it had far fancier sound. A quick search shows the Genesis did not use this chip, so other systems may also be incorrect. Ah, Wikipedia…)

This chip is able to produce three tones and one white noise at a time, which sounds an awful lot like the audio capabilities of my first computer, the VIC-20.

The chip has none of the fancy synthesizer features found in other chips, such as the famous Commodore 64 SID chip. The only thing you can do is adjust the volume level of each channel of sound. Clever software uses this to produce bell sounds and other effects. (If Congo Bongo is really using this chip, it’s doing some fancy things to make those bongo sounds!)

Thanks to StrongWare‘s John Strong, I now have one of these chips to experiment with. It is wired up to an Arduino Nano clone. (NOTE: I had issues getting this clone recognized on my Mac, due to it using a different serial chip. I found the solution, and wrote about it earlier this week.)

SN76849 sound chip hooked to an Arduino Nano on a neat 3-D printed platform from StrongWare.

John pointed me to this short tutorial on how to use the chip:

http://danceswithferrets.org/geekblog/?p=93

Using sample code there, I was able to get the device making tones, and then expanded it to play a sequence of tones to make a tune.

The next day I added more code so it could do a multitrack sequence.

I thought it might be fun to share what I have learned the first two days of playing with the device, and share the code I have come up with.

I will do a full article on the chip and how it works (summarizing some overly complex explanations I have been reading), but until then, here is my sample project:

https://github.com/allenhuffman/MusicSequencerTest

It contains routines to poke bytes to the SN76489, plus a work-in-progress multitrack music sequence that currently plays the 2-voice intro music to Pac-Man :)

I’ve been fixing up the comments and squashing some bugs, so check back for the latest. I still have to add real/better support for the “noise” channel, but it works right now for playing simple tunes.

More to come…

Arduino Nano serial port not recognized on Mac 10.12

John Strong of StrongWare sent me an Arduino Nano to experiment with, and I was puzzled when it would not appear as a Port in the Arduino IDE. All I could select was “dev/cu.Bluetooth-Incoming-Port”.

I never had to install special drivers for Arduino on Mac before (but do on a PC) but I did some searching and decided to try the FTDI drivers (most recent release from 2015). No luck.

I then decided to try my UNO. I couldn’t find it, and had to open a brand new one up. It was also not recognized.

After some searching, I found out that many clone Arduino are using a different USB-to-Serial chip, and need special drivers. The “official” ones (from a Chinese website!) cause a kernel panic due to a bug in the current release.

I found this:

https://github.com/adrianmihalko/ch340g-ch34g-ch34x-mac-os-x-driver

These drivers work and I now can use this clone Arduino Nano:

Arduino Nano visible using replacement CH serial drivers.

I hope this helps someone else not waste an hour like I had to tonight to find this ;-)

sizeof() matters

Updates:

  • 2016/02/29 – Per a comment by James, I corrected my statement that sizeof() is a macro. It is not. It is a keyword. My bad.

In C, the sizeof() macro can be used to determine the size of a variable type or structure. For instance, if you need to know the size of an “int” on your system, you can use sizeof(int). If you have a variable like “int i;” or “long i;”, you can also use sizeof(i).

On the Arduino, an int is 16-bits:

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  Serial.print("sizeof(int) is ");
  Serial.println(sizeof(int));
}

void loop() {
  // put your main code here, to run repeatedly:
}

On the Arduino, that produces:

sizeof(int) is 2

On a Windows system, an int is 32-bits:

int main()
{
  printf("sizeof(int) is %d\n", sizeof(int));

  return EXIT_SUCCESS;
}

That displays:

sizeof(int) is 4

Note: sizeof() is not a library function. It is a macro C keyword that is handled by the C preprocessor during compile time. It will be replaced with the number representing the size the same way a #define replaces the define in the source code. At least, I think that’s what it does.

You should avoid making any assumptions about the size of data types beyond what the C standard tells you. For example, an “int” should be “at least 16-bit”. Thus, even a PC compiler could have chosen to make an “int” be 16-bits instead of 32.

A better way to use data types was added in the C99 specification, where you can include stdint.h and then request specific types of variables:

uint8_t unsignedByte;

uint16_t unsignedWord;

int32_t signed32bit;

But I digress.

The point of this article was to mention that you can also use sizeof() on strings IF they are known to the compiler at compile time. You can, of course, get the size of a pointer:

char *ptr;

printf("sizeof(ptr) is %d\n", sizeof(ptr));

Depending on the size of a pointer on your system  (16-bits on the Arduino, 32 on the PC), you will get back 2 or 4 (or 8 if it’s a 64-bit pointer, I suppose).

And the pointer is still the same size regardless of what it points to. You still get the same size even if you had something like this:

char *msgPtr = "This is my message.";

printf("sizeof(msgPtr) is %d\n", sizeof(msgPtr));

But, if you had declared that string as an array of characters, rather than a pointer to a character, you get something different because the compiler knows a bit about what you are pointing to:

char msgArray[] = "This is my message.";

printf("sizeof(msgArray) is %d\n", sizeof(msgArray));

There, you see the compiler actually substitutes the size of the array of characters:

sizeof(msgArray) is 20

This is an instance where using “char *ptr =” is different than “char ptr[] = ” even though, ultimately, they both are pointers to some memory location where those characters exist.

At work, I ran across a bunch of test code that did this:

const char    PROMPT[] = "Shell: ";
const uint8_t PROMPT_LEN = 7;

const char    LOGIN[] = "Login: ";
const uint8_t LOGIN_LEN = 7;

Those strings would be used elsewhere, and the length needed to be known by some write()-type function. Counting bytes in a quotes string and keeping that number updated sounds like work, so instead they could have used the sizeof() macro. Since it returns the size of the array (including the NIL zero byte at the end), they’d need to subtract one like this:

const char    PROMPT[] = "Shell: ";
const uint8_t PROMPT_LEN = sizeof(PROMPT)-1;

const char    LOGIN[] = "Login: ";
const uint8_t LOGIN_LEN = sizeof(LOGIN)-1;

At compile time, the size of the character array is known, and the compiler substitutes that length where the “sizeof()” macro is. If the string is changed, that value also changes (at compile time).

Of course, since we are using NIL terminated strings, you could also just use the strlen() function. But, that is more for strings of unknown length, and it runs code that counts every character until the NIL zero, which is wasted CPU use and code space if you don’t actually need to do that.

My optimization tip for today is: If you are using hard coded constant strings, and you need to know the size of them, declare them as C arrays (not a pointer to the string) and use the sizeof() macro as a constant. Use strlen() only for times when the compiler cannot know the size of the character array (dynamic strings or things being passed in to a function from the outside).

Speaking of that … as long as the compiler can “see” where the array is declared, sizeof() will work. But if you had something like this:

void showSize(char *ptr)
{
  printf("showSize - sizeof(ptr) = %d\n", sizeof(ptr));
}

int main()
{
  const char    LOGIN[] = "Login: ";

  showSize(LOGIN);

  return EXIT_SUCCESS;
}

…that will not work. By the time you pass in just a “pointer to” the array, all the compiler sees (inside that showSize function) is a pointer, and thus can only tell you the size of the pointer, and not what it points to.

As you see, this tip is of limited use, but I think it is still neat and a potential way to save some CPU cycles and program space bytes from time to time. Since I have worked on a number of Arduino Sketches that have gotten too big to fit (also on some TI MSP430 projects), small tricks like this can make a very big difference in getting something to fit or not fit.

sizeof() can matter :-)

C strcat, strcpy and armageddon, part 3

See also: part 1 and part 2.

Previously, I discussed a way to make string copies safer by using strncpy(). I mentioned there would be a bit of extra overhead and I’d like to discuss that. This made me wonder: how much overhead? I decided to try and find out.

First, I created a very simple test program that copied a string using strcpy(), or strncpy() (with the extra null added).

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define BUFSIZE 20

//#define SMALL

int main()
{
 char buffer[BUFSIZE];

#ifdef SMALL
 // Smaller and faster, but less safe.
 strcpy(buffer, "Hello");
#else
 // Larger and slower, but more safe.
 strncpy(buffer, "Hello", BUFSIZE-1);
 buffer[BUFSIZE-1] = '\0';
#endif

 // If you don't use 'buffer', it may be optimized out.
 puts(buffer);

 return EXIT_SUCCESS;
}

Since I am lazy, I didn’t want to make two separate test programs. Instead, I used a #define to conditionally compile which version of the string copy code I would use.

When I built this using GCC for Windows (using the excellent Code::Blocks editor/IDE), I found that each version produced a .exe that was 17920 bytes. I expect the code size difference might start showing up after using a bunch of these calls, so this test program was not good on a Windows compiler.

Instead, I turned to the Arduino IDE (currently version 1.6.7). It still uses GCC, but since it targets a smaller 16-bit AVR processor, it creates much smaller code and lets me see size differences easier. I modified the code to run inside the setup() function of an Arduino sketch:

#define BUFSIZE 10
#define SMALL

void setup() {
 // volatile to prevent optimizer from removing it.
 volatile char buffer[BUFSIZE];
 
#ifdef SMALL
 // Smaller and faster, but less safe.
 strcpy((char*)buffer, "Hello");
#else
 // Larger and slower, but more safe.
 strncpy((char*)buffer, "Hello", BUFSIZE-1);
 buffer[BUFSIZE-1] = '\0';
#endif
}

void loop() {
 // put your main code here, to run repeatedly:
}

Then I selected Sketch Verify/Compile (Ctrl-R, or the checkmark button). Here are the results:

  • SMALL (strcpy) – 540 bytes
  • LARGE (strncpy) – 562 bytes

It seems moving from strcpy() to strncpy() would add only 22 extra bytes to my sketch. (Without the “buffer[BUFSIZE-1] = ‘\0’;” line, it was 560 bytes.)

Now, this does not mean that every use of strncpy() is going to add 20 bytes to your program. When the compiler links in that library code, only one copy of the strncpy() function will exist, so this is more of a “one time” penalty. To better demonstrate this, I created a program that would always link in both strcpy() and strncpy() so I could then test the overhead of the actual call:

#define BUFSIZE 10
#define SMALL

void setup() {
 // volatile to prevent optimizer from removing it.
 volatile char buffer[BUFSIZE];

 // For inclusion of both strcpy() and strncpy()
 strcpy((char*)buffer, "Test");
 strncpy((char*)buffer, "Test", BUFSIZE);

#ifdef SMALL
 // Smaller and faster, but less safe.
 strcpy((char*)buffer, "Hello");
#else
 // Larger and slower, but more safe.
 strncpy((char*)buffer, "Hello", BUFSIZE-1);
 //buffer[BUFSIZE-1] = '\0';
#endif
}

void loop() {
 // put your main code here, to run repeatedly:
}

Now, with both calls used (and trying to make sure the optimizer didn’t remove them), the sketch compiles to 604 bytes for SMALL, or 610 bytes for the larger strncpy() version. (Again, without the “buffer[BUFSIZE-1] = ‘\0’;” line it would be 608 bytes.)

Conclusions:

  1. The strncpy() library function is larger than strcpy(). On this Arduino, it appeared to add 20 bytes to the program size. This is a one-time cost just to include that library function.
  2. Making a call to strncpy() is larger than a call to strcpy() because it has to deal with an extra parameter. On this Arduino, each use would be 4 bytes larger.
  3. Adding the null obviously adds extra code. On this Arduino, that seems to be 2 bytes. (The optimizer is probably doing something. Surely it takes more than two bytes to store a 0 in a buffer at an offset.)

Since the overhead of each use is only a few bytes, there’s not much of an impact to switch to doing string copies this safer way. (Assuming you can spare the extra 20 bytes to include the library function.)

Now we have a general idea about code space overhead, but what about CPU overhead? strncpy() should be slower since it is doing more work during the copy (checking for the max number of characters to copy, and possibly padding with null bytes).

To test this, I once again used the Arduino and it’s timing function, millis(). I created a sample program that would do 100,000 string copies and then print how long it took.

#define BUFSIZE 10
//#define SMALL

void setup() {
 // volatile to prevent optimizer from removing it.
 volatile char buffer[BUFSIZE];
 unsigned long startTime, endTime;

 Serial.begin(115200); // So we can print stuff.

 // For inclusion of both strcpy() and strncpy()
 strcpy((char*)buffer, "Test");
 strncpy((char*)buffer, "Test", BUFSIZE);

 // Let's do this a bunch of times to test.
 startTime = millis();

 Serial.print("Start time: ");
 Serial.println(startTime);

 for (unsigned long i = 0; i < 100000; i++)
 {
#ifdef SMALL
 // Smaller and faster, but less safe.
 strcpy((char*)buffer, "Hello");
#else
 // Larger and slower, but more safe.
 strncpy((char*)buffer, "Hello", BUFSIZE - 1);
 buffer[BUFSIZE - 1] = '\0';
#endif
 }
 endTime = millis();

 Serial.print("End time  : ");
 Serial.println(endTime);

 Serial.print("Time taken: ");
 Serial.println(endTime - startTime);
}

void loop() {
 // put your main code here, to run repeatedly:
}

When I ran this using SMALL strcpy(), it reports taking 396 milliseconds. When I run it using strncpy() with the null added, it reports 678 milliseconds. strcpy() appears to take about 60% of the time strncpy() does, at least for this test. (Maybe. Math is hard.)

Now, this is a short string that requires strncpy() to pad out the rest of the buffer. If I change it to use a 9 character string (leaving one byte for the null terminator):

#ifdef SMALL
    // Smaller and faster, but less safe.
    strcpy(buffer, "123456789");
#else
    // Larger and slower, but more safe.
    strncpy(buffer, "123456789", BUFSIZE - 1);
    buffer[BUFSIZE-1] = '\0';
#endif

…no padding will be done. Without padding, the SMALL version takes 572 and the strncpy()/null version takes… 478!?!

Huh? How can this be? How did the “small” version suddenly get SLOWER? Well, before, strcpy() only had to copy the five characters of “Hello” plus a null then it was done, while strncpy() had to copy “Hello” then pad out five nulls to fill the buffer. Once both had to do the same amount of work (copying nine bytes and a null), it appears that strncpy() is actually faster! (Your mileage may vary. Different compilers targeting different processors may generate code in vastly different ways.)

Perhaps there is just some optimization going on when the destination buffer size is know. (Note to self: Look in to the GCC strncpy source code and see what it does versus strcpy.)

Conclusion:

  • strncpy() isn’t necessarily going to be slower (at least on this Arduino)!
  • strncpy() might be significantly slower if you copy a very short string (“Hi”) in to a very long buffer (char buffer[80];).

Buyer Programmer beware!

I am sure glad we (didn’t) clear that up. In the next part, I’ll get back to talking about appending strings using strcat() and how to make that safer.

To be continued…

ESP8266 $5 WiFi for Arduino?

This evening, I saw a reference to something called an ESP8266. A quick web search revealed it was a $5 WiFi chip that was mentioned last August 2014 on Hackaday:

http://hackaday.com/2014/08/26/new-chip-alert-the-esp8266-wifi-module-its-5/

As of this writing it has only been about six months since the discovery. At the time, little was known about it beyond some documents in Chinese and some early attempts to write code to use it. Today, however, you can find this part on Amazon for $7.99 with Prime shipping, or much cheaper on e-Bay with slow shipping from China:

http://www.amazon.com/s/ref=nb_sb_noss_1?url=search-alias%3Daps&field-keywords=ESP8266

http://www.ebay.com/itm/ESP8266-Serial-WIFI-Wireless-TransceiveR-Module-Send-Receive-LWIP-AP-STA-SY-/221619180149?pt=LH_DefaultDomain_0&hash=item3399885275

The chip can been hooked up to a UART (transmit and receive), or via SPI. This means, with a cheap TTL-to-RS232 adapter and a power supply, you could WiFi enable anything with an RS232 port with a bit of communications software.

The next time I have a few spare bucks, I plan to order one and see how easy it is to work with. It could be a fun way to WiFi-enable a CoCo or Arduino :)

And for those curious, here is a tutorial on using it I found:

http://www.instructables.com/id/Using-the-ESP8266-module/

Please leave a comment if you have worked with this chipset. It seems it might not take much to make a C library for Arduino that mirrored the official Arduino WiFi shield API, but used this inexpensive part.

CoCo/Tandy 1000 joystick adapter project

Last year, I designed an adapter that would let me use original CoCo (or Tandy 1000) analog joysticks on a modern computer via USB. I also designed an opposite adapter, which would let a modern USB controller be used on an old CoCo or Tandy 1000.

I ordered all the parts for a prototype, and did some quick tests to prove that it worked… And then promptly moved on to other things.

Eventually I found some time and I dug out all of these parts and began wiring things up again. My hope was to have a few things available to sell at the Chicago CoCoFEST this past April 25 and 26, 2015. (Money is very tight here, so any thing I can do to generate some extra income is a good thing.) I was unable to go, so did no more work on the project.

Rather than collect dust, I thought I’d share my work so far in this article I originally started working on last February.

The hardware components I have will allow several things:

For the CoCo

  • Use modern USB joysticks/gamepads on the CoCo
  • Use modem Bluetooth wireless joysticks/gamepads on the CoCo
  • Use modern USB keyboards on the CoCo
  • Use modern Bluetooth wireless keyboards on the CoCo

For Mac/Linux/Windows

  • Use an original CoCo/Tandy 1000 joystick as a USB input device
  • Use an original CoCo/Tandy 1000 joystick as a wireless Bluetooth input device
  • Use an original CoCo keyboard as a USB keyboard
  • Use an original CoCo keyboard as a Bluetooth wireless keyboard

As you can see, there are two main goals (use modern stuff on a CoCo, or use old CoCo stuff on a modern computer), with a focus on USB or wireless Bluetooth. All of these are possible, with the cost of doing Bluetooth about the same (or maybe a few dollars less) than USB.

My current prototype reads a PC USB joystick and turns that in to a CoCo-readable analog joystick. I also wired up CoCo joysticks to use on my Mac (very direct and easy).

The keyboard stuff also interests me. I plan to order the Bluetooth part I need so I can embed it inside my CoCo, hooked to the keyboard connector, and use an external battery powered Bluetooth keyboard on my CoCo.

The other combinations are not high on my project list since I do not even own a wireless Bluetooth gamepad or controller (unless my OUYA console controller can be used). However, when I get to that point, I may be able to find someone I can borrow one from for testing.

My eyesight took a hit last year, and now I can no longer focus on things more than a few feet away so I probably won’t do much until I can afford a new set of glasses ;-) Mid-40s is trying to make me think I’m no longer in my mid-20s!

To be continued…

Configuring the TP-LINK TL-WR702N nano router for Arduino

2015-02-07 Update: Added default WiFi password.

The two most-viewed pages on this site are often the following to Arduino articles:

The first one deals with a bug (?) I found in in the Arduino Ethernet library that prevented it from properly handling multiple incoming connections to the same port. The second was sharing my discovery of the $20 TP-LINK TL-WR702N nano router. It seems I am not the only one not happy that Arduino WiFi shields can be as much as $90, while cheap ethernet shields can be found for around $10.

The TP-LINK can be configured to connect to a WiFi network and then plug in to an Ethernet-only device and link it to the WiFi. Folks use them to get Ethernet printers on WiFi (such as the Lexmark printer I have — the official Ethernet module for it is $50, but I can use this TP-Link and be wireless printing for $20). I use one to get my Arduino on WiFi. Note that the Arduino will not have any control over the WiFi connection and won’t be able to select WiFi

This article is a quick guide to getting the TP-LINK set up for use with the Arduino.

TP-LINK TL-WR702N nano router box.

TP-LINK TL-WR702N nano router box, pictured next to a pen for scale.

1. Buy the TP-LINK WR702N. I got mine from Amazon for $19.99. It comes in a tiny box and is packed almost as nicely as an Apple product.

Inside the box you will find the tiny router (about 2″x2″x.5″), a micro USB cable, an Ethernet cable, and a USB power supply. There is also a mini-CD and a few small quick start guides. The guides are put together very well and have plenty of photos.

On the back of the TP-LINK unit will be the MAC address, but unless you have multiple units, you won’t need to know this.

2. Power up the TP-LINK by either plugging it up with the USB micro cable to a USB port (on your computer or a hub), or via the power supply.

3. The unit will boot up and after a few moments a new wireless network will appear that starts with “TP-LINK_xxxxxx” with the last part being the end of the MAC address of the router. Connect your computer to it. You will be prompted for a WiFi password, which you will find under the tiny barcode on the back of the unit. (It will be the last 8 HEX digits of the Mac address.) Give it a few more moments to connect and get an IP address. (Make sure you aren’t getting an internet connection some other way, like Ethernet. There are also ways to configure this router via Ethernet, but you’ll have to check TL-LINK guides for that.)

4. Open a web browser and go to: tplinklogin.net  It should prompt you for a username and password. You will find these on the back of the router, but they should be admin and admin.

TP-LINK WR702N login

Enter “admin” for the username and “admin” for the password.

5. You should see an admin webpage that is coming from your router. The first thing we need to do is configure the router to connect to your WiFi access point and connect to the internet. Click on Quick Setup under Basic Settings and click Next.

TP-LINK WR702N quick setup

Select Quick Setup.

6. The first screen is to select the Working Mode. We want Client, so choose it then click Next.

TP-LINK WR702N working mode

Select Client mode.

6. Next we will do Wireless Client setup and choose which WiFi network this nano should connect to. You can manually type it all in, but it’s easier to just click the Survey button so it scans for networks that are available. From that list, select your own WiFi network and then you will have an easy spot to enter your WiFi network password.

TP-LINK WR702N wireless client

Click the Survey button to obtain a list of available WiFi networks.

TP-LINK WR702N survey

Select your WiFi network from the list.

TP-LINK WR702N wifi password

Enter the password to your WiFi network.

7. The unit will then reboot and attempt to connect to your WiFi network. When it does, it will begin passing the WiFi connection out to the Ethernet port. To test this, turn off WiFi on your computer, and plug it up to the TP-LINK nano router via the included Ethernet cable. You will need to configure your computer’s Ethernet connection for DHCP. If it is working, after a few moments you will get an IP address assigned to your computer by the nano. Once the connection is made, you can test by going to Google.com or a known-working site.

8. Once you know it’s working, you should update the firmware on the nano to the latest. You can download the firmware here:

http://www.tp-link.us/support/download/?model=TL-WR702N&version=V1

Look for the latest version. It should look something like this:

TP-LINK WR702N firmware

Look for the latest version of the firmware for the TP-LINK TL-WR702N on the TP-LINK website.

Download this .zip file, then extract it somewhere you will be able to find it. It will create a folder with a few files inside, including a “.bin” which is the actual firmware update.

Log back in to tplinklogin.net and go to System Tools and Firmware then browse to the .bin file you just downloaded.

TP-LINK WR702N update

Browse to the .bin file you downloaded and update the firmware.

After it updates, the nano will reboot once again. On mine, this reset all the router settings, and I had to log back in and set it up again. There is probably a better set of steps to do this, but this is how I went through it and took screen shots so that is what I am sharing.

Once this is done, you can unplug and switch your computer back to normal internet connection. Now the TP-LINK can be plugged to power and the Arduino Ethernet shield and you can use the Ethernet library to make connections via your WiFi network.

NOTE: Since the nano requires using a computer and web browser to select which WiFi it connects to, this is not a portable solution. You cannot choose what WiFi to connect with (or the password or anything) from the Arduino. If you wanted to take your Arduino somewhere else and get it online, you would have to have a computer available to connect to the TP-LINK nano and reprogram which WiFi network it connects to. If you have a real WiFi shield for the Arduino, you can do this in software.

I hope these quick notes help…

Splitting a 16-bit value to two 8-bit values in C

Recently in my day job, I came across some C code that just felt inefficient. It was code that appeared to take a 16-bit integer and split the high and low bytes in to two 8-bit integers. In all my years of C coding, I had never seen it done this way, so obviously it must be wrong.

NOTE: In this example, I am using modern C99 definitions for 8-bit and 16-bit unsigned values. “int” may be different on different systems (it only has to be “at least” 16-bits per the C standard. On the Arduino it is 16-bits, and on my PC it is 32-bits).

uint8_t  bytes[2];
uint16_t value;

value = 0x1234;

bytes[0] = *((uint8_t*)&(value)+1); //high byte (0x12)
bytes[1] = *((uint8_t*)&(value)+0); //low byte  (0x34)

This code just felt bad to me because I had previously seen how much larger a program becomes when you are accessing structure elements like “foo.a” repeatedly in code. Each access was a bit larger, so it you used it more than a few times in a block of code you were better off to put it in a temporary variable like “temp = foo.a” and use “temp” over and over. Surely all this “address of” and math (+1) would be generating something like that, right?

Traditionally, the way I always see this done is using bit shifting and logical AND:

uint8_t  bytes[2];
uint16_t value;

value = 0x1234;

bytes[0] = value >> 8;     // high byte (0x12)
bytes[1] = value & 0x00FF; // low byte (0x34)

Above, bytes[0] starts out with the 16-bit value and shifts it right 8 bits. That turns 0x1234 in to 0x0012 (the 0x34 falls off the end) so you can set bytes[0] to 0x12.

bytes[1] uses logical AND to get only the right 8-bits, turning 0x1234 in to 0x0034.

I did a quick test on an Arduino, and was surprised to see that the first example compiled in to 512 bytes, and the second (using bit shift) was 516. I had expected a simple AND and bitshift to be smaller, but apparently, on this processor/compiler, getting a byte from an address was smaller. (I did not tests to see which one used more clock cycles, and did no experiments with compiler optimizations.)

On a Windows PC under GNU-C, the first compiled to 784 bytes, and the second to 800. Interesting.

I ran across this code in a project targeting the Texas Instruments MSP430 processor. The MSP430 Launchpad is very Arduino-like, and previous developers had to do many tricks to get the most out of the limited RAM, flash and CPU cycles of these small devices.

I do not know if I can get in the habit of doing my integer splits this way, but perhaps I should retrain myself since this does appear incrementally better.

Update: Timing tests (using millis() on Arduino, and clock() on PC) show that it is also faster.

Here is my full Arduino test program. Note the use of “volatile” variable types. This prevents the compiler from optimizing them out (since they are never used unless you uncomment the prints to display them).

#define OURWAY

void setup() {
  volatile char bytes[2];
  volatile uint16_t  value;

  //Serial.begin(9600);
  
  value = 0x1234;

#ifdef OURWAY  
  // 512 bytes:
  bytes[0] =  *((uint8_t*)&(value)+1); //high byte (0x12)
  bytes[1] =  *((uint8_t*)&(value)+0); //low byte  (0x34)
#else  
  // 516 bytes:
  bytes[0] = value >> 8;     // high byte (0x12)
  bytes[1] = value & 0x00FF; // low byte  (0x34)
#endif

  //Serial.println(bytes[0], HEX); // 0x12
  //Serial.println(bytes[1], HEX); // 0x34
}

void loop() {

  // put your main code here, to run repeatedly: 
  
}