Morse Code Tao Te Ching Flashing on the Arduino 
Saturday, August 31, 2019, 14:44
Posted by Administrator


This year I have been experimenting quite a bit with the Arduino platform. I love how Arduino clones are much cheaper than Raspberry Pi’s and only cost me around 2 dollars each from China. Arduinos also consume very little power and run for many days on my rechargeable external battery packs.

Long ago I created a blinking morse code light on a Raspberry Pi which slowly flashed the Tao Te Ching. It was a relatively straightforward process as there is far more than enough storage available on virtually any Micro Sd card to hold even the largest of books. 
 
My first true Arduino project was to remake my morse code Tao Te Ching light. Getting the Arduino to flash morse code was straightforward and lots of people have worked up examples that got me started. I made many modifications to some code I found online, and eventually got the Litany Against Fear from Dune to flash out on a small white LED:

// Message
byte m[] = "I MUST NOT FEAR. FEAR IS THE MIND-KILLER. FEAR IS THE LITTLE-DEATH THAT BRINGS TOTAL OBLITERATION. I WILL FACE MY FEAR. I WILL PERMIT IT TO PASS OVER ME AND THROUGH ME. AND WHEN IT HAS GONE PAST I WILL TURN THE INNER EYE TO SEE ITS PATH. WHERE THE FEAR HAS GONE THERE WILL BE NOTHING. ONLY I WILL REMAIN.";

// Pin to flash
int pin = 13;

// Tempo
// 240 ~5wpm
// 120 ~10wpm
// 80 ~15wpm
int t = 240;

// Setup the output pin
void setup () {
pinMode(pin, OUTPUT);
}

// Perform the dits
void d() {
digitalWrite(pin, HIGH);
delay(1 * t);
digitalWrite(pin, LOW);
delay(1 * t);
}

// Perform the das
void da() {
digitalWrite(pin, HIGH);
delay(3 * t);
digitalWrite(pin, LOW);
delay(1 * t);
}

// Define the pattern of dits and das for each letter
void morse(byte l) {
if (l == 'A' or l == 'a') {d(); da();}
else if (l == 'B' or l == 'b') {da(); d(); d(); d();}
else if (l == 'C' or l == 'c') {da(); d(); da(); d();}
else if (l == 'D' or l == 'd') {da(); d(); d();}
else if (l == 'E' or l == 'e') {d();}
else if (l == 'F' or l == 'f') {d(); d(); da(); d();}
else if (l == 'G' or l == 'g') {da(); da(); d();}
else if (l == 'H' or l == 'h') {d(); d(); d(); d();}
else if (l == 'I' or l == 'i') {d(); d();}
else if (l == 'J' or l == 'j') {d(); da(); da(); da();}
else if (l == 'K' or l == 'k') {da(); d(); da();}
else if (l == 'L' or l == 'l') {d(); da(); d(); d();}
else if (l == 'M' or l == 'm') {da(); da();}
else if (l == 'N' or l == 'n') {da(); d();}
else if (l == 'O' or l == 'o') {da(); da(); da();}
else if (l == 'P' or l == 'p') {d(); da(); da(); d();}
else if (l == 'Q' or l == 'q') {da(); da(); d(); da();}
else if (l == 'R' or l == 'r') {d(); da(); d();}
else if (l == 'S' or l == 's') {d(); d(); d();}
else if (l == 'T' or l == 't') {da();}
else if (l == 'U' or l == 'u') {d(); d(); da();}
else if (l == 'V' or l == 'v') {d(); d(); d(); da();}
else if (l == 'W' or l == 'w') {d(); da(); da();}
else if (l == 'X' or l == 'x') {da(); d(); d(); da();}
else if (l == 'Y' or l == 'y') {da(); d(); da(); da();}
else if (l == 'Z' or l == 'z') {da(); da(); d(); d();}
else if (l == '1') {d(); da(); da(); da(); da();}
else if (l == '2') {d(); d(); da(); da(); da();}
else if (l == '3') {d(); d(); d(); da(); da();}
else if (l == '4') {d(); d(); d(); d(); da();}
else if (l == '5') {d(); d(); d(); d(); d();}
else if (l == '6') {da(); d(); d(); d(); d();}
else if (l == '7') {da(); da(); d(); d(); d();}
else if (l == '8') {da(); da(); da(); d(); d();}
else if (l == '9') {da(); da(); da(); da(); d();}
else if (l == '0') {da(); da(); da(); da(); da();}
else if (l == '.') {d(); da(); d(); da(); d(); da();}
else if (l == ',') {da(); da(); d(); d(); da(); da();}
else if (l == '?') {d(); d(); da(); da(); d(); d();}
else if (l == '\'') {d(); da(); da(); da(); da(); d();}
else if (l == '!') {da(); d(); da(); d(); da(); da();}
else if (l == '/') {da(); d(); d(); da(); d();}
else if (l == '(') {da(); d(); da(); da(); d();}
else if (l == ')') {da(); d(); da(); da(); d(); da();}
else if (l == '&') {d(); da(); d(); d(); d();}
else if (l == ':') {da(); da(); da(); d(); d();d();}
else if (l == ';') {da(); d(); da(); d(); da(); d();}
else if (l == '=') {da(); d(); d(); d(); da();}
else if (l == '+') {d(); da(); d(); da(); d();}
else if (l == '-') {da(); d(); d(); d(); d(); da();}
else if (l == '_') {d(); d(); da(); da(); d(); da();}
else if (l == '"') {d(); da(); d(); d(); da(); d();}
else if (l == '$') {d(); d(); d(); da(); d(); d(); da();}
else if (l == '@') {d(); da(); da(); d(); da(); d();}

// Plus the two below equals a delay of 7 tempos for a space
if (l == ' ') {delay(5 * t);}

// Delay of 3 tempos, 2, plus the delay after a character
delay(2 * t);

}

// Loop through the message
void loop () {

// For each character in the message
for (int g = 0; g < sizeof(m); g++) {

// Flash the morse equivalent for this letter
morse(m[g]);

}

}

The real challenge was in getting an entire book to fit on an Arduino. Most standard Arduino’s such as the Arduino Nano clones that I’m using have roughly 32K of storage space for holding programs. You get even less than this in reality since a typical bootloader for the Arduino takes .5K – 2K of the space before you even load your code on there. Even though the morse code flashing instructions I put together are relatively small, there was still not nearly enough space left to hold my favorite copy of the Tao Te Ching translated by Stephen Mitchell.

His translation is around 37.32K and my original hope was that if I removed all the line breaks, and most of of the punctuation that I could get it to fit somehow. However, after adding in the additional code for flashing the LED and the bootloader, it became apparent that there was just no way this was going to work. I then pondered over it all for a couple of days.

Compression is the natural solution to this problem. I was able to find a wonderfully up to date text compression utility called Shox96. It is a hybrid entropy and dictionary encoder and the author has put together a great white paper on the design which is well worth reading. It also has a version which works great at compressing short strings into the Arduino program memory.

After compressing Stephen Mitchell’s translation of the Tao Te Ching with Shox96 and then decompressing one chunk at a time and feeding that into my morse code flashing program it all worked perfectly. I had the entire book flashing before my eyes. 
 
There was even plenty of free space left over. So I decided to make things a lot harder and use this public domain translation of the Tao Te Ching by John H. McDonald which is ~45.70K in size when not compressed. After compressing it… it did not fit on the Arduino anymore.

I continued to poke at it and eventually realized that Shox96 encoding is more efficient when the lines of text are long. I then went through the full text manually and increased the line sizes to mostly be full sentences. Compressing this version got it all plenty small enough and I finally considered the project to be finished.

I left the light blinking for many weeks running off of the USB port on the side of my office monitor. At the slow speed I set it at it takes longer than a day to run through the entire book, at this point it loops and starts from the beginning. I left serial debugging on, so if you monitor the serial output of the device you can watch it print each character to the screen as it flashes. This looked especially nice when paired with outputting to a CRT television. I ran it this way for many days as well. 
 
This project helped me get quite a bit more familiar with Arduino’s and making use of additional libraries when working on sketches. The final flashing art piece also got me much better at sight-reading morse code which was a nice bonus.
 
The full code for this project is available here. Let me know if you can think of any other great books that would benefit from this sort of harassment.
add comment ( 2577 views )   |  permalink   |  $star_image$star_image$star_image$star_image$star_image ( 3 / 3193 )
Javascript Flasher Clock 
Sunday, March 25, 2018, 08:12
Posted by Administrator
I have been using my minimalistic Pi Zero W flasher clock for a while now and have found it to be an exceptionally soothing way to check on the current time. I recently ported the code over to work on the Pi 3 B+ and have edited my previous post about it to include both versions.

The only trouble with this clock has been that the code for it is very specifically for a Raspberry Pi, and I have found myself wanting to have a flashing clock indicator like this on other devices like phones, televisions, etc. Clearly, the flasher clock I designed was in need of another port, so set of to re-create it in Javascript.

It was a much more interesting challenge to get this working in Javascript than I expected it to be since Javascript is non-blocking and there is no built-in way to pause execution and sleep as you can with bash scripting. However, with some new features that most modern browsers take advantage of, Javascript is now capable of handling asynchronous functions natively and can use the async/await keywords to sort of hold off on execution until a promise for the await returns.

With async/await and promises, I was able to create a helper function to simulate a similar sleep behavior that my original script had without having to re-design everything to work as a weird sort of state machine using setTimeouts. This new code could have certainly be re-written to not use async/await but I believe it would be a lot less straightforward to make sense of that way. I was also able to take advantage of another ES6 addition, arrow functions, to streamline this custom wait function into the following one-liner:

var wait = t => new Promise(resolve => setTimeout(() => resolve(), t));

This function, wait, takes a variable t which is the time in milliseconds that the setTimeout should wait until returning a promise. With this component in place I had everything I needed to finish up converting my original design into something that could run in any modern browser:

<html>
<head>
<title>Javascript Flasher Clock</title>

<script>

// Set up our colors array
const colors = [
'#FFFFFF',
'#FF0000',
'#FF8000',
'#FFFF00',
'#80FF00',
'#00FF00',
'#00FF80',
'#00FFFF',
'#0080FF',
'#0000FF',
'#7F00FF',
'#FF00FF',
'#FF007F'
];

// Set up our default color index
var c = 0;

// Set up our base wait time
var w = 50;

// Define the wait function, a promise that waits for a setTimeout of length t before returning
var wait = t => new Promise(resolve => setTimeout(() => resolve(), t));

// A function to change the color
function changeColor() {

// If we are at the end of the colors array set c back to the first value
if ( c === colors.length - 1) {

// Set c back to the first color
c = 0;

}

// Else we just need to increment our color value c
else {

// Increment c
c++;

}

}

// Define our clock function using async so that we can use await
async function clock() {

// Set the default background color to black at the beginning of each cycle
document.body.style.background = '#000000';

// Wait for a long while so that we separate our flasher clock cycles
await wait(w * 40);

// Get the current date
let date = new Date();

// Get the current number of hours
let hours = ((date.getHours() + 11) % 12 + 1);

// Get the current number of tens digits
let tensDigits = (date.getMinutes() < 10 ? '0' : '' + date.getMinutes()).substring(1,0);

// Flash the current number of hours
for (let h = 0; h < hours; h++) {

// Wait a while
await wait(w*8);

// Set the screen to the colors c value
document.body.style.background = colors[c];

// Wait another while
await wait(w*8);

// Set the screen back to black
document.body.style.background = '#000000';

}

// Wait a medium while between the hours and tens digits flashes
await wait(w*20);

// Flash for the current number of tens digits
for (let t = 0; t < tensDigits; t++) {

// Wait a little while
await wait(w*5);

// Set the screen to the colors c value
document.body.style.background = colors[c];

// Wait another little while
await wait(w*5);

// Set the screen back to black
document.body.style.background = '#000000';

}

// Call this clock function again to start a new cycle
clock();

}
</script>

</head>
<body onload='clock()' onclick='changeColor()'>
</body>
</html>

I also added the capability to click anywhere on the screen to cycle through many different color codes so that the one can switch up the display color of the flash easily even if using a phone.

As with the original design, the clock flashes for the current number of hours ( in 12-hour format ) and then flashes a little more quickly once for every current tens digit of minutes. For example, if the time is 6:38 the clock will flash 6 times somewhat slowly, and then three times somewhat faster. I decided that the clock should be in 12-hour format in order to cut down on the number of flashes one would potentially have to watch in each cycle. Similarly, I have foregone the full number of minutes to cut down on the number of flashes one would have to count. Staying within ten minutes of accuracy seems like a good compromise between the time necessary to read the clock and precision to me.

The Javascript Flasher Clock can be experienced here.

I'm very happy with the results. It was great to finally make use some of the newest additions to Javascript. These new features made it possible for me to rewrite my original script much more easily than I had originally imagined.

My plan is to shine a phone running this clock at a wall so that the whole wall is a time indicator, but I'm also interested in lighting up translucent objects so that the object itself can be the time indicator. A milk jug should work great for that, although it may look classier inside of a paper lantern.

-- Addendum, March 26 2018

I have found a nice opaque white container that diffuses a phones display well and have placed it in the middle of my indoor sand garden. The phone is able to remain charged by keeping it plugged in with a hole for the cord I made in the back of the container. It then struck me that I had no way to change the light color or intensity once everything was assembled in the jar, but this was easily solved by adding Teamviewer Host to the phone and the remotely controlling phone from another device to change the display brightness or cycle through color options.
add comment ( 2388 views )   |  permalink   |  $star_image$star_image$star_image$star_image$star_image ( 2.8 / 3744 )
Easy Raspberry Pi GPIO Pin Control with Bash 
Saturday, July 8, 2017, 13:37
Posted by Administrator
I have been experimenting a bit with home automation lately by hooking up some small electrical relays to my Raspberry Pis. So far I have my bedroom fan and a small lamp fully under remote control and connected to my home network. I even have them under voice control now by using an app called Tasker on Android, as well as two helper plugin apps for Tasker called Autovoice and an associated SSH Plugin. I feel an undeniable sense of power whenever I verbally tell my phone to turn my lamp or fan on or off, and it has quickly become a much more natural and pleasant feature of my bedroom over the last few days.

In the past, I have always used Python and a GPIO control library to control the output pins on a Raspberry Pi. This method requires installing both Python and the pin control library on a fresh Raspbian or Retropie install, which can be a bit of a nuisance.

Since the release of the first Raspberry Pi I've been wanting a simple solution to just turn Raspberry Pi pins on or off without having to install any additional software or remember any commands. I've also loved bash scripting for a long time now, and while putting together my last minimal Pi Zero clock project I realized that a pi's output pins can be fully controlled by writing to system files without the need of installing Python or anything else. For example, to turn on pin 26 on a Raspberry Pi one can simply enter these three short commands:

sudo echo "26" > /sys/class/gpio/export
sudo echo "out" > /sys/class/gpio/gpio26/direction
sudo echo "1" > /sys/class/gpio/gpio26/value

Turning the pin off is as easy as echoing a value of 0 to the pin's value in the same location as the last line.

I first created a number of small scripts to turn certain pins on, and another script to turn the same pin off and was using that with my home automation system. After a couple of days, I decided that I'd like to have a script to toggle the state of any arbitrary pin. This is so that I can issue the same command to turn my lamp on or off without having to be specific about what I want when I yell at the phone. I also wanted this script to be able to specifically turn a pin on or off in the case that I'm not at home and want to make sure something is turned on or off even if I don't recall whether I left it on or not. I quickly came up with the following bash code that accomplishes just that:

#!/bin/bash
# A utility script to toggle a raspberry pi gpio pin on or off
# Spike Snell - July 2017

# If there are command line options to use
if [ $# != 0 ]
then

# Set up our argument variables
arg1="$1"
arg2="$2"

# If the gpio pin was not previously set up
if [ ! -e /sys/class/gpio/gpio"$arg1" ];
then
# Make sure that gpio pin $arg1 is initialized
echo "Initializing gpio pin" $arg1
echo "$arg1" > /sys/class/gpio/export
echo "out" > /sys/class/gpio/gpio"$arg1"/direction
fi

# Check to see if there was a second command line argument
if [ -z "$2" ]
# Argument 2 for the on/off value was not set
# We should just toggle the current state of gpio pin $arg1
then
# If the current value is 1 set it to 0 and vice versa
if grep -q 1 /sys/class/gpio/gpio$arg1/value
then
echo "Toggling gpio pin" $arg1 "to 0"
echo "0" > /sys/class/gpio/gpio"$arg1"/value
else
echo "Toggling gpio pin" $arg1 "to 1"
echo "1" > /sys/class/gpio/gpio"$arg1"/value
fi
# Argument 2 for the on/off value was set
# We should set gpio pin $arg1 to the value of $arg2
else
echo "Setting gpio pin" $arg1 "to" $arg2
echo "$arg2" > /sys/class/gpio/gpio"$arg1"/value
fi

# Else there were no options passed in, let the user know about them
else
echo "Please enter what pin to toggle, ex: sudo ./pin.sh 11"
echo "Optionally enter if the pin should be 1 or 0, ex: sudo ./pin.sh 11 0"
echo " * Make sure to run as super user "
fi

I included some helpful information near the bottom that gets displayed if the script is called without any parameters. To use it the script should be saved as pin.sh and set to be executable with the command sudo chmod +x pin.sh.

I plan to use this script quite a lot in the future and this seems a good place to keep a copy of it. Hopefully this can be helpful to others as well. Feel free to leave any comments or suggestions that you may have.
add comment ( 3275 views )   |  permalink   |  $star_image$star_image$star_image$star_image$star_image ( 3 / 538 )

<Back | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Next> Last>>