Monday, January 16, 2017

Raspberry Pi 3 Setup 101

In order to support a number of upcoming projects, I've finally decided to take a step outside of the old/comfortable Arduino space, and do some work with the Pi.  The most immediate use will be to get OctoPi up and running on our new Lulzbot Mini (more on that on a future post).  But before I can do that, I need to get a Pi workspace up and running.

There are a bajillion setup guides for the Pi 3, so I will not attempt to recreate one here.  Below are my notes on the basics, so that when I forget all of this and need to do it again, I only have one place to look for my answers.

HARDWARE:


A quick trip to Amazon has everything you need: board, case/power, memory card:

Raspberry Pi 3 Model B
Smraza Starter Kit
SanDisk 32GB MicroSD card

The kit went together easy, but the screws for the case were awfully small - guess I'm showing my age, but I decided to pull out the Donegan Optivisor rather than accidentally scratch the board during assembly...



OS SETUP:


After the board was assembled, it was time for prepping the SD card.  Instructions were found at the Raspberry Pi site:

Downloading and installing the Raspberry Pi Software

I skipped the NOOBS option, and downloaded Raspbian directly, and burned it to the MicroSD card using etcher.io.  All worked as expected, and the Pi booted up without issue.

Basic Pi Configuration:


After booting for the first time, some basic house-cleaning was performed.

From a terminal window:

sudo apt-get update
sudo apt-get upgrade
sudo apt-get clean

From the Raspberry Pi configuration:


Localization:
Changed everything to US/English options, and the appropriate timezone.

System:
Changed the hostname and password, as well as choosing to expand the filesystem.

Finally the Pi was rebooted and WiFi connected via the toolbar app.  After a quick browser check to ensure everything was properly connected to the internet, victory was declared.

In a future post I'll list my notes on installation of xrdp, and getting the Pi to run in a headless manner (already tired of switching my cables, would prefer to remote into the device)...

Sunday, January 1, 2017

Assembling a Lionel Covered Bridge (6-24117)

What a pain in the #!*&.  I've assembled a number of things over the years, but this one really caught me by surprise, primarily by the time and frustration factor...

The bridge in question is the Lionel 6-24117 Covered Bridge for O-scale trains.  I am not a huge "train person", but we do have one we use during the holidays with the kids.  The manual starts off claiming the kit is "easy to assemble";  That may be true if you have the hands of a child, or patience of a saint, but for the rest of us, it took a little more effort than advertised.

The assembly kit comes with 32 screws.  Really, its not the quantity that is bad, its the size and quality of the washer screws.  They are small, but not so small that a precision screwdriver can be used.  So instead, you need to dig through your toolbox and find the smallest non-precision screwdriver, and use that one with great patience.  Why patience?  Well - none of the screw holes are pre-tapped, and the screw heads strip very easily.  And fully knowing this issue, how many extra screws were included by the vendor - thats right, zero, thanks Lionel.

Your mileage may vary, but after stripping the first screw trying to assemble everything up front, this is what worked for me. Use one new screw, and pre-tap all the holes in the kit.  I did this by twisting the screw in a few turns at a time, then backing it out.  Lather-Rinse-Repeat for 32 holes in the product.  After that, follow the directions, using painters tape to keep the pieces steady while the parts are connected.

If you take your time, the kit can be assembled with good results.  See below for a few photos.






One final note: To power the lights, this 12VAC power supply was used instead of a Lionel accessory power kit.  Just cut off the female plug and solder the wires directly to the bridge leads, finishing the connection off with some heat shrink tubing.

Sunday, February 28, 2016

Arduino WiFi Weather Web Server Prototype

Building on previous work, the Arduino WiFi 101 Shield will now be configured to broadcast weather information, using a slow but effective temperature/humidity sensor, the DHT-22.

Connecting the device was accomplished with a slightly modified set of procedures from the original example found on AdaFruit. Most notably the use of 3.3V vs 5V to support the different levels on the Arduino Zero.  Note that a 10K pull-up resistor is also used on pin 2.




After compiling and downloading the sketch below, the temperature/humidity was successfully obtained and published/visible on the network via Chrome.



The source code used to implement the WiFi Weather Web Server is seen below.

 #include <SPI.h>  
 #include <WiFi101.h>  
 #include "DHT.h"  
   
 char ssid[] = "mynetwork";     // your network SSID (name)   
 char pass[] = "mypassword"; // your network password  
 int status = WL_IDLE_STATUS;  // the Wifi radio's status  
 WiFiServer server(80);  
   
 #define DHTPIN 2      // what digital pin we're connected to  
 #define DHTTYPE DHT22   // DHT 22 (AM2302), AM2321, RHT03  
 DHT dht(DHTPIN, DHTTYPE); // Initialize DHT sensor.  
   
 void setup()   
 {  
  // initialize serial:  
  Serial.begin(9600);  
  while (!Serial)  
  {  
   ; // wait for serial port to connect. Needed for native USB port only  
  }  
   
  dht.begin();  
    
  if (WiFi.status() == WL_NO_SHIELD)  
  {  
   Serial.println("WiFi shield not present");  
   // don't continue:  
   while (true);  
  }   
   
  // attempt to connect to Wifi network:  
  while ( status != WL_CONNECTED)  
  {  
   // attempt to connect using WPA2 encryption:  
   Serial.println("");  
   Serial.println("Attempting to connect to WPA2 network...");  
   status = WiFi.begin(ssid, pass);  
   
   if (status != WL_CONNECTED)  
   {   
    // if you're not connected, stop here:  
    Serial.println("Network unavailable, trying again in 10 seconds...");  
    // wait 10 seconds for connection:  
    delay(10000);  
   }  
  }  
    
  server.begin();  
   
  Serial.println("Connected to network");  
  printWifiStatus();  
 }  
   
 void loop()  
 {  
  // listen for incoming clients  
  WiFiClient client = server.available();  
  if (client)  
  {  
   Serial.println("new client...");  
   
   // Wait a few seconds between measurements.  
   delay(2000);  
     
   // Reading temperature or humidity takes about 250 milliseconds!  
   // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)  
   float h = dht.readHumidity();  
   // Read temperature as Celsius (the default)  
   float t = dht.readTemperature();  
   // Read temperature as Fahrenheit (isFahrenheit = true)  
   float f = dht.readTemperature(true);  
   
   // Check if any reads failed and exit early (to try again).  
   if (isnan(h) || isnan(t) || isnan(f)) {  
    Serial.println("Failed to read from DHT sensor!");  
    f = 0;  
    h = 0;  
    t = 0;  
   }    
   
   // Compute heat index in Fahrenheit (the default)  
   float hif = dht.computeHeatIndex(f, h);  
   // Compute heat index in Celsius (isFahreheit = false)  
   float hic = dht.computeHeatIndex(t, h, false);  
    
   // an http request ends with a blank line  
   boolean currentLineIsBlank = true;  
   while (client.connected())  
   {  
    if (client.available())  
    {  
     char c = client.read();  
     Serial.write(c);  
     // if you've gotten to the end of the line (received a newline  
     // character) and the line is blank, the http request has ended,  
     // so you can send a reply  
     if (c == '\n' && currentLineIsBlank)  
     {  
      // send a standard http response header  
      client.println("HTTP/1.1 200 OK");  
      client.println("Content-Type: text/html");  
      client.println("Connection: close"); // the connection will be closed after completion of the response  
      //client.println("Refresh: 5"); // refresh the page automatically every 5 sec  
      client.println();  
      client.println("<!DOCTYPE HTML>");  
      client.println("<html>");  
      client.println("<head><title>Arduino Web Server</title></head>");  
      client.println("<body>");  
        
      client.print("Humidity is ");  
      client.print(h);  
      client.println("<br />");  
   
      client.print("Temperature is ");  
      client.print(t);  
      client.println(" (C) <br />");       
        
      client.print("Temperature is ");  
      client.print(f);  
      client.println(" (F) <br />");       
   
      client.print("Heat Index is ");  
      client.print(hic);  
      client.println(" (C) <br />");       
   
      client.print("Heat Index is ");  
      client.print(hif);  
      client.println(" (F) <br />");       
   
      client.println("</body>");  
      client.println("</html>");  
      break;  
     }  
       
     if (c == '\n')  
     {  
      // you're starting a new line  
      currentLineIsBlank = true;  
     }  
     else if (c != '\r')  
     {  
      // you've gotten a character on the current line  
      currentLineIsBlank = false;  
     }  
    }  
   }  
   // give the web browser time to receive the data  
   delay(1);  
   
   // close the connection:  
   client.stop();  
   Serial.println("client disonnected...");  
  }  
 }  
   
 void printWifiStatus()   
 {  
  // print the SSID of the network you're attached to:  
  Serial.print("SSID: ");  
  Serial.println(WiFi.SSID());  
   
  // print your WiFi shield's IP address:  
  IPAddress ip = WiFi.localIP();  
  Serial.print("IP Address: ");  
  Serial.println(ip);  
   
  // print your gateway address:  
  IPAddress gateway = WiFi.gatewayIP();  
  Serial.print("Gateway: ");  
  Serial.println(gateway);  
    
  // print the received signal strength:  
  long rssi = WiFi.RSSI();  
  Serial.print("signal strength (RSSI):");  
  Serial.print(rssi);  
  Serial.println(" dBm");  
 }  
   

Saturday, February 27, 2016

Arduino WiFi Shield 101 Web Server Basics

Without much fuss, the earlier code example was modified per Arduino instructions for a WiFi Web Server.   No additional code libraries were needed, and the application worked without issue.  Here is a snapshot of the page being served by the Arduino after opening the IP address in Chrome.


The code is documented below:

 #include <SPI.h>  
 #include <WiFi101.h>  
   
 char ssid[] = "mynetwork";   // your network SSID (name)   
 char pass[] = "mypassword!";  // your network password  
 int status = WL_IDLE_STATUS;   // the Wifi radio's status  
 WiFiServer server(80);  

 void setup()   
 {  
  // initialize serial:  
  Serial.begin(9600);  
  while (!Serial)  
  {  
   ; // wait for serial port to connect. Needed for native USB port only  
  }  
   
  if (WiFi.status() == WL_NO_SHIELD)  
  {  
   Serial.println("WiFi shield not present");  
   // don't continue:  
   while (true);  
  }   
   
  // attempt to connect to Wifi network:  
  while ( status != WL_CONNECTED)  
  {  
   // attempt to connect using WPA2 encryption:  
   Serial.println("");  
   Serial.println("Attempting to connect to WPA2 network...");  
   status = WiFi.begin(ssid, pass);  
   
   if (status != WL_CONNECTED)  
   {   
    // if you're not connected, stop here:  
    Serial.println("Network unavailable, trying again in 10 seconds...");  
    // wait 10 seconds for connection:  
    delay(10000);  
   }  
  }  
    
  server.begin();  
   
  Serial.println("Connected to network");  
  printWifiStatus();  
 }  
   
 void loop()  
 {  
  // listen for incoming clients  
  WiFiClient client = server.available();  
  if (client)  
  {  
   Serial.println("new client...");  
   // an http request ends with a blank line  
   boolean currentLineIsBlank = true;  
   while (client.connected())  
   {  
    if (client.available())  
    {  
     char c = client.read();  
     Serial.write(c);  
     // if you've gotten to the end of the line (received a newline  
     // character) and the line is blank, the http request has ended,  
     // so you can send a reply  
     if (c == '\n' && currentLineIsBlank)  
     {  
      // send a standard http response header  
      client.println("HTTP/1.1 200 OK");  
      client.println("Content-Type: text/html");  
      client.println("Connection: close"); // the connection will be closed after completion of the response  
      client.println("Refresh: 5"); // refresh the page automatically every 5 sec  
      client.println();  
      client.println("<!DOCTYPE HTML>");  
      client.println("<html>");  
      client.println("<head><title>Arduino Web Server</title></head>");  
      client.println("<body>");  
      // output the value of each analog input pin  
      for (int analogChannel = 0; analogChannel < 6; analogChannel++)  
      {  
       int sensorReading = analogRead(analogChannel);  
       client.print("analog input channel ");  
       client.print(analogChannel);  
       client.print(" is ");  
       client.print(sensorReading);  
       client.println("<br />");  
      }  
      client.println("</body>");  
      client.println("</html>");  
      break;  
     }  
       
     if (c == '\n')  
     {  
      // you're starting a new line  
      currentLineIsBlank = true;  
     }  
     else if (c != '\r')  
     {  
      // you've gotten a character on the current line  
      currentLineIsBlank = false;  
     }  
    }  
   }  
   // give the web browser time to receive the data  
   delay(1);  
   
   // close the connection:  
   client.stop();  
   Serial.println("client disonnected...");  
  }  
 }  
   
 void printWifiStatus()   
 {  
  // print the SSID of the network you're attached to:  
  Serial.print("SSID: ");  
  Serial.println(WiFi.SSID());  
   
  // print your WiFi shield's IP address:  
  IPAddress ip = WiFi.localIP();  
  Serial.print("IP Address: ");  
  Serial.println(ip);  
   
  // print your gateway address:  
  IPAddress gateway = WiFi.gatewayIP();  
  Serial.print("Gateway: ");  
  Serial.println(gateway);  
    
  // print the received signal strength:  
  long rssi = WiFi.RSSI();  
  Serial.print("signal strength (RSSI):");  
  Serial.print(rssi);  
  Serial.println(" dBm");  
 }  
   

The data itself is not very interesting (as it is just pulling values from floating pins), however that will be remedied in the next post.

Saturday, February 20, 2016

Getting Started with the Arduino WiFi Shield 101

After verifying the Arduino Zero was functional (previous blog entry), the WiFi Shield 101 was connected (via stacking headers) and tested out.  Again, there is not too much to be added to the basic documentation on the Arduino site, this just documents the links for later:

Arduino WiFi Shield 101
Arduino WiFi Shield 101 Getting Started
Arduino WiFi 101 Software Library


The shield requires a software library, which is first downloaded via the Library Manager (Sketch | Include Library | Manage Libraries...):


After installing the library, the sample code for Scan for available networks was compiled/uploaded and successfully listed my local network.  I then combined a few sample code snippets into the following, and was able to connect to the local network with WPA2:

 #include <SPI.h>  
 #include <WiFi101.h>  
   
 char ssid[] = "mynetwork";   // your network SSID (name)   
 char pass[] = "mypassword";  // your network password  
 int status = WL_IDLE_STATUS;   // the Wifi radio's status  
   
 void setup()   
 {  
  // initialize serial:  
  Serial.begin(9600);  
   
  if (WiFi.status() == WL_NO_SHIELD)  
  {  
   Serial.println("WiFi shield not present");  
   // don't continue:  
   while (true);  
  }  
    
  // attempt to connect using WPA2 encryption:  
  Serial.println("");  
  Serial.println("Attempting to connect to WPA network...");  
  status = WiFi.begin(ssid, pass);  
   
  if (status != WL_CONNECTED)  
  {   
   // if you're not connected, stop here:  
   Serial.println("Couldn't get a wifi connection");  
   while(true);  
  }   
  else  
  {  
   // if you are connected, print out info about the connection:  
   Serial.println("Connected to network");  
   printWifiStatus();  
  }  
 }  
   
 void loop()  
 {  
  // do nothing  
 }  
   
 void printWifiStatus()   
 {  
  // print the SSID of the network you're attached to:  
  Serial.print("SSID: ");  
  Serial.println(WiFi.SSID());  
   
  // print your WiFi shield's IP address:  
  IPAddress ip = WiFi.localIP();  
  Serial.print("IP Address: ");  
  Serial.println(ip);  
   
  // print your gateway address:  
  IPAddress gateway = WiFi.gatewayIP();  
  Serial.print("Gateway: ");  
  Serial.println(gateway);  
    
  // print the received signal strength:  
  long rssi = WiFi.RSSI();  
  Serial.print("signal strength (RSSI):");  
  Serial.print(rssi);  
  Serial.println(" dBm");  
 }  
   

The sketch worked as designed, and the Arduino was visible on my routers list of connected devices.  Unfortunately I can find no way to set the device name for the WiFi shield, but that is a minor complaint when so much functionality worked "out of the box".


Next up will be to work with the onboard real-time clock (RTC), set the RTC automatically via an NTP call, and perform some basics to serve a webpage on the local network.



Thursday, February 18, 2016

Getting Started with the Arduino Zero

There is not too much to be added to the documentation on the Arduino site, this just documents the links for later:

Getting Started with the Arduino Zero

First install the latest software, which as of February 2016 is the following:


Make sure to perform the step of installing the SAMD core like this, then select the appropriate Board and Serial Port from the Tools menu.  As an initial test, the Blink application was installed and observed to be functioning normally.



Next step will be to connect up the WiFi 101 board...

Sunday, October 18, 2015

Using Symbolic Links for Modules in Node.js

To avoid the relative directory nightmare in Node.js, a simple operating system hack can be used to bypass the problem. Rather than referencing your module as:

 var mymodule = require('../../../mymodule')  

a simple trick with symbolic links can be used to reference your module as:

 var mymodule = require('_/mymodule')  

from anywhere within your project.

First create a library directory (lib) within your project, and move your module within this directory. To create a symbolic link, perform the following process from a command window:

Linux and Mac:

 cd /myproject/node_modules
 ln -s ../lib _

Windows:

 cd /myproject/node_modules
 mklink /D _ ..\lib

There is nothing magical about the underscore character;  Any name could be used to reference your directory, however, picking something innocuous will help prevent name collisions with other modules imported into your project.