Thursday, February 23, 2017

Andy's Ham V20 Virtual Machine Update

When last we left Andy's Ham, in this post, I had Andy's linux ham radio distribution installed in a virtual machine running on a Windows 10 host under Virtualbox. The installation was successful, but I still had to run some software.

The first step was to get the virtual machine to recognize my my Signalink USB. After starting up the VM, in Virtualbox, I went to "Settings/USB" and found "Burr-Brown from TI USB Audio Codec." I ticked that, and for a couple of weeks I could not get the VM to do anything but freeze up.  I was pretty sure that that was the Signalink, so I scoured the interwebs for information, to no avail. In desperation, In installed AndysHam on a different physical machine and plugged in the Signalink. The same option appeared in USB settings, and it worked. This time I notice the options for USB controller: 1.0, 2.0, and 3.0.  In both cases I had ticked 2.0.  However, the computer with the VM has some USB 3.0 ports (see this post on my upgrade). I had not noticed that I had plugged the Signalink into a 3.0 port (I just reached around to the back of the computer and plugged it in where I could). I went back and ticked 3.0 and all was well. The VM did not freeze and the Signalink showed up as an option in the software (fldigi and WSJT-X).
VirtualBox USB settings for Signalink (be sure to enable the correct USB controller)

If I have WSJT-X (e.g.) running on the host, the guest grabs the USB port for the Signalink and holds it until the VM is shut down. So, I can run the software on the guest, but not the host. On the host, the Signalink is not an option for sound card until the guest is shut down. It may be necessary to redesignate the sound card every time--however, if you plan to use the Signalink in the guest only, this is not an issue.

So, I got AndysHam to work in two environments--on a stand-alone machine and as a guest machine under Virtualbox.  There are a couple of things I need to get used to. First, JTAlert does not run on linux.  I have been enjoying the features, so I'm not sure I want to give that up. Second, I find the set up a little inflexible.  I'm sure I can do what I want to do, but it's been set up to provide most things, and for under-powered computers--which mine is not.  

I'll work with it some more, and if I have anything useful to say in the future I will post it here.

Wednesday, January 25, 2017

Andy's Ham Version 20 VM Installation

I have recently made progress with digital modes.  On 2 Meters, I have been successful with packet on my Alinco DR-135. I am considering a Tigertronics Signalink as sound card interface for my Ten Tec Jupiter.

Meanwhile, I need software.  I could pursue commercial options like Ham Radio Deluxe, but I decided to explore some free options.  I discovered KB1OIQ - Andy's Ham Radio Linux .  The advantage is that it includes a variety of free packages, including logging, rig control, satellite tracking, and a variety of others.

I had 3 options for installation:
  1. Turn my Windows 10 system into a dual boot, and boot into linux when I want to play radio and Windows for other applications
  2. Install Andy's Ham on a separate matching dedicated to playing radio
  3. Install Andy's Ham as a virtual machine (VM), running under Windows
I chose option 3, because dual booting can be a pain and a separate computer can add complexity. Running a VM allows both Windows and linux to be available at the same time. To do that, I needed virtualization software. I chose VirtualBox because I have used it before at work and home.  Installation on Windows is simple: download the correct version at the link just provided, and run the .exe.  It makes sense to download the Extension Pack and install it, too (honestly, I don't know why that's an option--just always install it).

Once VirtualBox is installed:
  1. run it and create a VM (follow the prompts--consult the user documentation at the download link if you need to). The only change I needed to make from defaults was disk size--it defaults to 8G but I gave it 20G--Ubuntu says it needs ~20. 
  2. download Andy's Ham (link in the second paragraph above)
  3. in VirtualBox, click settings, then storage for the machine you created. Next to Optical Drive on the right, click on the CD image and point it to the downloaded Andy's Ham .iso file.
    Installing Andy's Ham in a VM
    1. Start the VM--follow the current instructions. For me I chose the "live" option when prompted. When asked for a user id gave it "ubuntu" and presses enter on password (no Password). Once the VM comes up, you can play with the installation, but nothing is permanent until you install to the VN's hard drive. To do that, click on "Debian"  at the lower left, an in the menu that pops up click "System" then "Install to Hard Disk."  This will take a while, but cannot run unattended because you need to respond to some prompts along the way.
    2. Restart the VM (click on machine/ACPI shutdown, then double click the machine name), and you're done.  One of the prompts you responded to created a user and password--use those to log in to your new machine.
    This is a nice remix of Ubuntu if all you want to do is play radio.  I'm going to have to play to see how to add back some Ubuntu features that I'm used to.  I will post again after I've had a chance to play/learn.

    Install Andys Ham to hard drive after starting with "live" option

    Example of how to navigate to some of the features

    Monday, December 26, 2016

    I upgraded my computer--including stupid technician tricks

    System Information (from Control Panel/System)


    The last two times I was on +Adafruit Industries #showandtell, my video was unacceptable.  That's a minor irritation for me, but the second time I had my seven-year-old-granddaughter on. She was able to get through it, but it was a struggle.  Show and and Tell is a Google Hangout, and the minimum requirements include a quad-core processor.  I had been getting by with an AMD Athlon X2 dual-core processor and ASUS Motherboard for the 3 years I've been participating by shutting everything else down and running just one tab on Chrome for the hangout, but I guess Google's "enhancements" have rendered my computer obsolete.

    The computer was an 8-year old home-build, and has served me well, but I decided that I needed to get my granddaughter on again in fine style, so I bought an AMD 8-core processor and ASUS motherboard. Actually I bought an ASRock motherboard first, but I had some issues with the build (see below) and I read reports of this mobo bursting into flames, so I returned it and ordered the ASUS. I will report here after I try Show and Tell again, but so far it's great.

    Additions

    I also ordered a new graphics card.  I'm not very happy with it. First, the description, the invoice, and the parts list all say it supports DirectX 12.  What Newegg sent me supports DirectX 11.2, according to the box. I returned it for replacement, expecting them to fix their error right away.  It turns out that they refused to replace it until the receive the one they sent in error.  So, I changed it to refund and ordered a new one.  I got the new one 5 days before they received the return. To my surprise, it was the same version. Newegg has been good in the past, but this is not good.  Over 2 weeks later I still do not have a refund.  

    In addition, I got this card because Microsoft says that the Windows 10 video capture tool works with AMD Radeon R7 and later. However, it's still telling me that my video card is not good enough for them. More research.

    The motherboard has an  M.2 slot for what is essentially and SSD stick.  When I get around to it, I will add a 250GB SSD using this new, smaller, faster technology.

    The motherboard also has COM header for a serial port, Since my ham radios are able to work digital modes through a serial port I ordered one from China and will hook that up to enable me to experiment with digital modes. More learning and excitement!

    Since the 650W power supply I had in the machine had failed recently, I had replaced it with a 800W supply.  Underpowering a system is an invitation to frustration, so if you're upgrading, don't forget to be sure that you have a power supply that will meet all the requirements of your new system.

    Stupid Technician Tricks

    I won't go into detail on the big one (it's embarrassing and I know better), but here are some suggestions for installing an AMD CPU on a motherboard:
    1. lift up the lever next to the pad on the motherboard
    2. align the arrow in one corner of the CPU with the arrow on the motherboard pad (also check the pattern of the CPU pins to be sure they align with the pattern on the pad
    3. only after the CPU is seated properly, push the lever down
    4. check that everything is secure BEFORE adding the heatsink/fan assembly
    Enough said, except that the overarching recommendation is "Take your time!"  

    The only other problem I had was minor:  the hard drive light was not lighting. Obviously, I connected it wrong.  Lesson: double check your connections before you plug in the unit, and check that everything works before putting the case all back together.

    Activation

    Initially, I thought I may need to buy a new copy of Windows, but I read up on Microsoft's digital license policy and made sure that I was all set up.  I had Windows 10 Pro, installed as part of Microsoft's free upgrade program. Since I had purchased Windows 8.1 Pro, it upgraded me to Windows 10 Pro.  After I fired up the  machine I was not asked to activate Windows (although Office 2010 did ask to be activated--quick and easy).  I did get a message "you need to fix your Microsoft Account."  Google revealed that I needed to update a user. When I went in to do that I was told I couldn't because Windows wasn't activated.  I went through the activation process--which tells you you need to buy a new copy but has a non-prominent link "I recently upgraded my hardware."  I clicked that, and after a couple of "our servers are down" messages, I was able to activate.  Done,

    I use Norton Security provided as part of my subscription to Comcast.  Norton said it had expired.  I couldn't convince it that it hadn't, and Comcast help was typically useless, so I uninstalled it and reinstalled and all was forgiven.

    Summary

    I have a fast new machine that should work with the Adafruit Show and Tell Google Hangout. Everything is activated.  I have and upgrade path to an SSD and will have a serial port to use for ham radio digital modes as soon as it arrives.  Overall I'm happy with the build.

    The only issue is the video card.  I read on the interwebs that others with this card have had the problem Windows 10 video capture.  I'm working on it.

    Saturday, December 10, 2016

    I am an Extra Class Operator


    In 1958, my friend Freddy and I studied Morse Code with the intention of becoming licensed Ham Radio operators. Then Junior High School happened, along with the 60's and other decades of distraction, so I never got licensed.  About 3 years ago, I became interested in hobby electronics. In the process I built a crystal radio, and all the ham interest came back. A little over a year ago, I decided to investigate the local ham community.  I found an active, vibrant community so I decided to get licensed. I passed my first exam in January of this year.

    As of about 9:45 AM EST 10 December 2016, I am an Amateur Extra Class Radio Operator. I passed the test with a 100% score. I have now taken all 3 Ham Radio license exams this year. I scored 100% on the Technician, got 1 wrong on the General (although when they asked me the question after the test I got it right), and 100% on the Extra.

    So, now I have to go learn what the questions really mean--but I am proud and happy, and I have made two QSOs (contacts) so far with my new privileges.


    Friday, November 25, 2016

    Generator House Upgrades

    Upgraded house, showing new roof, exhaust system, and PVC carrying wires to/from the residence.

    The generator house (see this post) did a great job.  However, we needed some upgrades.

    First, we needed to get the exhaust fumes out.  The extra heat and the flammable gasses were a potential problem. So, with some black iron pipe and some welding (again, my brother-in-law has skills), we fashioned the exhaust system and connected it to the generator.

    Next, in order to power the house, we had to run a cable from the generator to the transfer switch--every time.  I bought a new transfer switch with more circuits and more suitable for my house.  We ran 10/4 wire from the transfer switch, and 14/2 from an existing circuit, to a junction box, then out through the wall, where the wires ran through PVC down the outside wall, underground, and into the back of the generator house.  The 10/4 goes to a junction box, where it connects to a cable that plugs into the generator. Now we don't have to mess with the heavy cable every time we want to power the house.  The 14/2 supplies 2 boxes:  one with a switch that goes to a light plus 2 unswitched  receptacles and the other to a switch that controls 2 receptacles--the fan is plugged into one and the battery charger to the other. These will always be powered, except in the time between house power going out and running the generator.

    Third, the quick roofing job was not sufficient, so we took off the old shingles, put down tar paper, added metal drip guard around the edges, re-shingled, and added lead flashing at the top.

    Now we have something!  When we have a power outage, all we need to do is flip the switches on the transfer switch to off, start the generator, let it run for a few minutes, then flip the transfer switches to generator, and we have power.  The whole house, except air conditioning and the stave and dryer can run off the generator.

    BTW, when I say "we" with respect to any work I mean my brother-in-law under my expert supervision (which is mostly me saying "that' looks good").

    See the video.

    Wednesday, November 9, 2016

    Halloween Candy Cauldron V3.1

    V3.1 in the enclosure. Ignore the external speaker--it's a vestige. Ready to tidy up for V4.
    As I said in my last post on this project, all that was left to do was tidy up the connections and enclose the electronics. I decided that the enclosure I was using was too big. The reason it was too big was that I had the project on a breadboard instead of soldering the components to a PCB. I have always wondered why places like Radio Shack that sell enclosures and PCBs don't sell PCBs that fit in the enclosures--with mounting holes and screws.  So, I went looking and found this enclosure with matching PCB and a battery compartment. A little pricey, but good quality and they have a variety of sizes and features. (I'm using the term PCB to include proto boards here.) Follow-up note: I found that the soldering pads on the pcb were insufficient.  I'll accept blame for my soldering technique, but I had more trouble with this than any other I've worked with.

    Since the new enclosure was a little smaller, I decided to use an  +Arduino Pro Mini (actually an Arducam clone) instead of the +Adafruit Industries Pro Trinket.  It's a little smaller, and I had a few in inventory. It needs an FTDI to serial module to program, but I was using one anyway for the Trinket to be able to use the serial monitor.

    The code compiled with no changes.  (See link to last post in opening sentence to see code.) In order to upload to the board, the IDE required some changes (to point to the right board--Nano, not mini), and the USB Port needed a tweak in Windows Device Manager (I'm on Windows 10). Arduino.cc has a clear and concise getting started article describing this better than I can.

    Interrupt

    Note that the interrupt code also works as-is.  I need to work on the program to make the sleep more useful. As you can see in the video (the blue LED is on when it's sleeping), it doesn't sleep much, I'm using the Echo pin on the HC-SR04 sensor to wake it up. I put it to sleep at the top of the loop, then wait for Echo to go LOW or HIGH. It works the same either way, at least to the naked eye.

    I used LOW because IDLE is the only mode that can be woken from anything other than LOW, and I wanted to be able to play with other modes. I'm thinking about using an inverter so I can set the interrupt on LOW, but have the pin go LOW when the Echo pin goes HIGH. +Home DIY Electronics has a good article on interrupts and the HC-SR04.

    Since the sensor is ranging constantly, it wakes up pretty quickly. If I try to put it in power down mode, it does not wake up (maybe because the sensor shuts down?):  The LED indicating sleep stays on and no gesture will wake it up. There are 5 sleep modes and these are only the 2 extremes. I will play with some of the intermediate modes--next year, or the next time I'm playing with interrupts on an AVR board.

    Construction
    1. Test the mini
      Since I changed boards, I needed to upload the code, wire the circuit on a breadboard, and test. As described above, all was well.
    2. Prep the enclosure
      In this design, the speaker and the battery are now inside the enclosure, I only need holes to bring in wires from the switch and from the HC-SR04. I also drilled 7 holes to let the sound out, places where I planned to put the speaker.
    3. Design the board layout
      I needed to mount the Pro Mini, then find room for the amplifier and Micro SD Reader.  This required some planning, so I simulated with header pins on the PCB and marked where I would place the components.  All the components had male headers attached, because I originally set set this up for a breadboard, so I soldered the headers to the printed side of the board.
    4. Wire the busses
      I created power and ground busses on the inside edge of the board, next to the battery, using tinned copper bus wire. The board has pairs of adjacent rows of connected holes, so I used two of these pairs (one row for each bus, each adjacent row for connections to the circuit).  The power rail is supplied from the voltage regulator circuit 5V output, and the ground from the 9V battery's negative lead. The positive lead from the battery goes to a 2-wire JST connector, which mates to another connector with leads going to a toggle switch. The other lead from the case (with the + from the battery) is the 9V input to the voltage regulator.
    5. Test the Voltage Regulator Circuit
      Since I have habit of messing up connections, and power is a key part of this, I wanted to be sure that I was getting 5V out of this part of the circuit before completing the soldering. When I got it right (after some stupid soldering tricks), I was ready to move on.
    6. Mount the components
      All the components had male headers attached, because I originally set set this up for a breadboard, so I soldered the headers to the printed side of the board. I also added an LED and resistor for visual representation of the sleep mode (the code for this was already included, so what the heck).
    7. Test the circuit
      Before fastening the circuit board to the enclosure, make sure everything works.  Here's where I ran into trouble.  I worked the continuity function of my multi-meter extensively. I thought I had everything in order, but it failed. I went back to a version of the sketch that had serial commands for testing in it, and saw that the SD board was not initializing.  I rechecked the connections, checked the SD card to see if it could be read, and then got drastic:  clipped the jumpers from the mini to the SD reader, and connected them via alligator leads to another reader.  Still not initializing, so I was pretty sure it was my connections.  One more continuity test revealed a problem with one of the jumpers. I re-soldered, put it back together, and it worked. Stupid soldering tricks, indeed!
      Working circuit, mounted. Clockwise from upper left: Adafruit Class D Mono Amp (wires to speaker), voltage regulator circuit, indicator LED and resistor, Pro Mini, Micro SD Card Reader. Yellow and green wires go to HC-SR04, red and black wires on right are power to HC-SR04 (red and black) and from 9V battery and switch (black and gray). 
    8. Put it in the box
      See photo at the top of this post.  Enclosing was a matter of adding screws in the prepared holes to secure the PCB, then passing the 4 wires to the HC-SR04 through one hole and the battery connection through another, position the speaker under the holes, and closing the box.
    9. Video
      Available on Youtube (my channel)



    Wednesday, October 19, 2016

    Halloween Candy Cauldron V3

    Cauldron V3 in-process.
    The large speaker will be removed--replaced by the small green on in the enclosure.
    The red FTDI Friend and USB cable are there for programming.
    We'll shorten the wires, neaten it up, and put the cover on the enclosure.
    The red LED is for testing--turned on before sleeping, turned off on waking.

    When last we looked a this (last Halloween), I was having trouble making the electronics small. To recap, I started out with an +Arduino Uno, an SD card shield, +Adafruit Industries class D mono amp, and an HC-SR04 Ultrasonic Sensor.  Then someone reaches in to grab a piece of candy, the sensor reacts, code on the arduino then chooses one of nine sounds to play, via the amp and an 8 Ohm speaker.

    Objective

    The big issue is that the electronics are loose in the bottom of the cauldron, so I wanted to use a smaller board and smaller SD breakout (like a MicroSD), and put the whole thing in an enclosure. I tried the Adafruit Pro Trinket 5V last year and ran out of time before I could get it to work.

    Turns out this was a stupid wiring trick. The circuit is powered by a 9V battery, run through a 7805 5V Voltage Regulator circuit.  The dumb thing I did last year was connect the BAT pin on the Trinket to the battery.  I'm not sure what, if anything, else I did wrong (I may have also connected that same pin to the 5V rail), but this year I connected the BAT pin to the 5V rail. Last year I got only static, this year it works. In both cases I powered the peripherals from the 5V rail (output of the VR circuit), to provide enough current, since the Trinket's 5V pin provides 150mA max.

    Further, I wanted to put the Trinket to sleep while waiting for trick-or-treaters to save battery.

    Video

    Interrupts

    Sleep mode turned out to be simple, but required some learning.  As described in this post on interrupts on the M0, I just completed my first successful Arduino project using interrupts.  So, I started with a __WFI(); instruction to wait for an interrupt. It turns out that different processors use different instructions, since interrupts are so hardware dependent, so this did not compile.

    My main source of information was here. The avr\sleep.h library (which does not work with the M0), was the key, since the main differences between the 2 processor families is how you put the processor to sleep, and the sleep modes. On the M0, the top of loop tested to see if one of our interrupts had been fired, and if not issued a wfi--back to sleep.  If so, go on to process In the case of the Trinket, also at the top of loop, we attached the interrupt, enabled sleep, went to sleep, and on waking, disabled sleep and detached the interrupt. The code:
    //*****sleep**************************
        digitalWrite(ledPin, HIGH);  //turn on the LED (testing)
        attachInterrupt(digitalPinToInterrupt(echoPin), echoISR, HIGH); //attach interrupt
        sleep_enable();          // enables the sleep bit in the mcucr register
        sleep_mode();            // here the device is actually put to sleep!!
    //***********************************/

    //wait here for echoPin interrupt--ignore all others
    //*****wake up************************
        sleep_disable();         // first thing after waking from sleep: disable sleep...
        detachInterrupt(digitalPinToInterrupt(echoPin));      // disables interrupt because pin stays high
    //***********************************/

    echoPin is Trinket pin 3, the only one that sees interrupts
    echoISR just sets a volatile boolean, handIn
    The next code tests handIn to see if it was set, meaning that we woke up because of the interrupt we care about, then goes on to reset the boolean and process.

    In set up, we enabled interrupts ("interrupts();") and set the sleep mode ("set_sleep_mode(SLEEP_MODE_IDLE);"). According to the article cited above, IDLE is the only mode that can be awakened by a mode other than LOW, and I thought since we want to be interrupted when echoPin goes HIGH, we're stuck with it, even though it saves the least power of all modes.

    However, some experimentation yielded that LOW works similarly to HIGH on the attachInterrupt.  I tried SLEEP_MODE_PWR_DOWN, AND it seemed to sleep a little more, but the board hung with regularity, so I went back to IDLE.

    I'm sure there are more and better ways to do this, but this is working for me.

    Other Enhancements

    I was never happy with how the code looked, There's a lot of function-specific processing that made the loop long. So, I broke out the code to calculate the distance based on the sensor pin values and the code to choose which sound to play and put them in functions.  Not rocket science, but good programming practice.

    I replaced the 3.5" speaker with a 1.5". That allowed me to enclosed the speaker in the box, reducing wires. I also made it a little quieter--young trick-or-treaters don't like the loud version. Yes I know I can control the volume on the amp, but this works well.

    Fritzing Diagram


    Code

    /*2014-10-05 Virgil Machine Halloween Candy Dish: Play random sound when kid (or greedy adult) reaches into bowl

    2016-10-18 V3 VM  never got Trinket to work last year, this week I did (stupid wiring trick)
     also replaced external speaker with a 1.5" that dit in the enclosure
     Added interrupt  handling to put it to sleep to save battery (thanks to http://playground.arduino.cc/Learning/ArduinoSleepCode)
     had  to change echoPin to #3--only pin on Trinket that is interruptable; changed trigPin to 4 to be
    side-by-side for wiring, added ledPin for testing
    Also, put the song selection/playing and distance calculation code in functions to make loop more readable.

    2015-10-14 V2 VM change to Pro Trinket from Uno to put the circuit in an enclosure
     Echo to 6 (Pro Trinket does not have pin 7)

    2014-10-05 VM HC_SR04 Distance sensor code added
    Neeed to modify pins for Halloween (13&12 used by SPI)

    2014-04-26 VM Downloaded from Instructables
     HC-SR04 Ping distance sensor]
     VCC to arduino 5v GND to arduino GND
     Echo to Arduino pin 13 Trig to Arduino pin 12 (used 8&7 instead--need SPI pins for SD reader)
    */

    /******* see virgilmachine.blogspot.com*****/

    /*includes*/
    #include    //SPI library
    #include     //SD card library
    #include //library for playing sound
    #include  //sleep functions
    #include  //interrupt functions

    /*constants*/
    #define SD_ChipSelectPin 10
    #define echoPin 3 //so we can have an interrupt (D3 is the only one)
    #define trigPin 4 //to be next to echo for wiring
    #define ledPin  5

    /*variables*/
    int song = 0;   // song number for random function
    volatile boolean handIn = false; //variables in ISR need to be volatile
    /*objects*/
    TMRpcm speaker;   // create an object for use in this sketch


    void echoISR() //ISR for distrance sensor
    {
        handIn = true;  //someone put his or her hand in
    }

    void setup(){
      randomSeed(analogRead(0));  //initialize random (A0 unconected)
      pinMode(trigPin, OUTPUT);   //pins for distance sensor
      pinMode(echoPin, INPUT);
      pinMode(ledPin, OUTPUT);   //LED fot testing
      digitalWrite(ledPin, LOW);  //default to off
      speaker.speakerPin = 9; //output to amp
      speaker.loop(0); //2014-10-05 do not play repeatedly
    //  Serial.begin(9600); //Serial is for testing--comment to reduce time/power consumption
      if (!SD.begin(SD_ChipSelectPin))
         {  // see if the card is present and can be initialized:
    //Serial.println("SD not initialized");
          return;   // don't do anything more if not
          }
    //   else
    //      {
    //       Serial.println("SD initialized");
         //
    //     }  
      speaker.volume(1);
    //  speaker.setVolume(7);   //attempt to increase volume

    interrupts(); //enable interrupts (should not need to do this, but just for drill...)
    set_sleep_mode(SLEEP_MODE_IDLE);   // sleep mode is set here
    //set_sleep_mode(SLEEP_MODE_PWR_DOWN);   // PWR_DOWN hangs periodically
    }

    void loop() {

    //*****sleep**************************
        digitalWrite(ledPin, HIGH);  //turn on the LED (testing)
        attachInterrupt(digitalPinToInterrupt(echoPin), echoISR, LOW); //attach interrupt
        sleep_enable();          // enables the sleep bit in the mcucr register
        sleep_mode();            // here the device is actually put to sleep!!
    //***********************************/

    //wait here for echoPin interrupt--ignore all others
    //*****wake up************************
        sleep_disable();         // first thing after waking from sleep: disable sleep...
        detachInterrupt(digitalPinToInterrupt(echoPin));      // disables interrupt because pin stays high
    //***********************************/
      while (handIn) {   //someone wants candy, hcsr04 interrupted
        digitalWrite(ledPin, LOW);  //turn off LED (testing)
        handIn=(!handIn); //reset the boolean
    //2014-10-05 If distance is <8in cm="" hand="" his="" in="" nbsp="" p="" put="" someone="">//2016-10-18 (the getDistance function calculates that)
        if (getDistance() < 20)
        {
          playSong(); //function to select and play a random song
        } //distance
          delay(2500);  //give the song a chance to play
      } //while

    } //loop

    void playSong() {
            song = random(1,10); //get random number from 1 to 9
    //      Serial.print("song: "); //for testing
    //      Serial.println(song); //for testing
          switch (song) {
            case 1:
              speaker.play("1.wav");
              break;
            case 2:
              speaker.play("2.wav");
              break;
            case 3:
              speaker.play("3.wav");
              break;
            case 4:
              speaker.play("4.wav");
              break;
            case 5:
              speaker.play("5.wav");
              break;
            case 6:
              speaker.play("6.wav");
              break;
            case 7:
              speaker.play("7.wav");
              break;
            case 8:
              speaker.play("8.wav");
              break;
            case 9:
              speaker.play("9.wav");
              break;
          } //switch/case
    } //playSong

    long getDistance() {
      long duration, distance;
      digitalWrite(trigPin, LOW);
      delayMicroseconds(2);
      digitalWrite(trigPin, HIGH);
    //trigPin must me high for 10 microsecs to do ranging
      delayMicroseconds(10);
      digitalWrite(trigPin, LOW);
    //duration is the time between pings of the sensor  in microseconds as returned on echoPin
      duration = pulseIn(echoPin, HIGH);
    //duration is a round-trip, so divide by 2; speed of sound is 29.1 cm/microsec, so distance is in cm
      distance = (duration/2) / 29.1;
      return distance;
    } //getDistance