carlynorama

the blog

Intel Galileo and Bee Mail Part 4: Working with Libraries

by Carlyn Maw on March 3, 2014, 4 comments

This is Part 4 of creating the BeeMail project. Previously I got the Galileo up and running, designed the Bees themselves and built the motor circuits. See the Table of Contents for this series at the bottom of the post.

“All” that was left was to rework the code in the example project to suit my own purposes. Sadly copying and pasting the code as written caused all. sorts. of. error. messages. None of which I understood yet.  Since the project has many intermeshed systems, most of which were new to me, Jim Lindblom’s work became a todo list / starting guide. Troubleshooting is all about isolating variables.

My ToDo list looked something like this:

  • Is the WiFi Working?
    • Is the WiFi hardware recognized?
    • Is the Wifi Connected to the network?
    • Can the Galileo get out to the internet?
  • Can I see the SD card?
    • Does the SD card initialize?
    • Can the Arduino sketch create files?
    • Can the Arduino sketch add content to files?
    • Can the Arduino sketch read files?
    • Can the Arduino delete files?
  • Does the Python Work?
    • Does Python run at all?
    • Can the shell see the internet / is my mail server available to it?
    • Does my Python script work on the Galileo?
    • What does the output look like of the Python script and where is it putting it?
    • Is the sketch calling the Python script successfully?
    • How is the Arduino sketch interpreting the output file?
  • Add in the bees.

The first to sections are covered in this post with a lot of long code includes, so I’m putting them after a break.

WiFi

The way to use WiFi on the Intel Galileo is NOT the WiFi shield. On the bottom of the Intel Galileo is a Mini PCI slot which should be used instead. PCI stands for Peripheral Component Interconnect. PCI cards are a standardized way to extend a computer’s hardware functionality. Mini just means PCI’s designed for small computers. There are actually 3 sizes of Mini PCI: traditional, full height and half-height.  The Galileo has a full height slot which means the half-height WiFi cards will need an adapter, but those are easy to find. While it is possible to extend Intel Galileo projects relatively cheaply with the many different types of PCI cards out there, keep in mind the specification is not opensource. However, PCI cards remain a viable option especially because not all Arduino shields are compatible with the Galileo board. Intel has posted a list of compatible shields that will hopefully stay maintained.

Shopping List

Galileo Board with  WiFi Card & Attenae Attached

Galileo Board with WiFi Card & Attenae Attached

Using the WiFi Library

The example code from the Arduino WiFi library functioned on first compile, a completely pleasant experience that worked as expected with both an open network and a WPA secured network connection.  I broke both of those example cases out into an file that I could use to add WiFi to future projects by dropping it into the same folder as my Arduino sketch.

Arduino window with WiFi as tab

Arduino window with WiFi as tab

WiFi Library Full Test Sketch

This script is for testing WiFi functionality completely as a stand alone sketch. It prints out everything to know about the card and its local connection as well as makes a test call to a plain text page on the Arduino website. If that page ever goes down there is a secondary test funtion that connects to google.com and returns the search results page for “Arduino.”


/*
// This code is to test WiFi function on Arduino Boards
// It was complied from various examples which can be found:
//
// http://arduino.cc/en/Tutorial/ConnectNoEncryption
// http://arduino.cc/en/Tutorial/ConnectWithWPA
// http://arduino.cc/en/Tutorial/WiFiWebClientRepeating
// http://arduino.cc/en/Reference/WiFiClientConnect
//
// Carlyn Maw 2014
// www.carlynorama.com
// This code is released to the public domain
*/
#include <WiFi.h>
char ssid[] = "CHANGE_TO_YOUR_NETWORK_NAME"; // your network SSID (name)
char pass[] = "CHANGE_TO_YOUR_NETWORK_PASSWORD"; // your network password
int status = WL_IDLE_STATUS; // the Wifi radio's status
// ————————————————————- setup()
void setup() {
//Delay start so serial communication and sketch updating
//dont intrfere with each other on the Intel Galileo board
delay(5000);
//Intialize serial
Serial.begin(9600);
//Both of the below functions connect to the wifi card
//and verify that a connection to the local network
//has been made.
wifiNotEncrypted();
//wifiEncrypted();
connectToTestPage();
}
// ——————————————————— END setup()
// ————————————————————– loop()
void loop() {
// put your main code here, to run repeatedly:
}
// ———————————————————- END loop()
// ————————————————– wifiNotEncrypted()
void wifiNotEncrypted() {
// check for the presence of the shield:
if (WiFi.status() == WL_NO_SHIELD) {
Serial.println("WiFi shield not present");
// don't continue:
while(true);
}
String fv = WiFi.firmwareVersion();
if( fv != "1.1.0" )
Serial.println("Please upgrade the firmware");
// attempt to connect to Wifi network:
while ( status != WL_CONNECTED) {
Serial.print("Attempting to connect to open SSID: ");
Serial.println(ssid);
status = WiFi.begin(ssid);
// wait 10 seconds for connection:
delay(10000);
}
// you're connected now, so print out the data:
Serial.print("You're connected to the network\n");
printCurrentNet();
printWifiData();
}
// ———————————————- END wifiNotEncrypted()
//—————————————————— wifiEncrypted()
void wifiEncrypted() {
// check for the presence of the shield:
if (WiFi.status() == WL_NO_SHIELD) {
Serial.println("WiFi shield not present");
// don't continue:
while(true);
}
String fv = WiFi.firmwareVersion();
if( fv != "1.1.0" )
Serial.println("Please upgrade the firmware");
// attempt to connect to Wifi network:
while ( status != WL_CONNECTED) {
Serial.print("Attempting to connect to WPA SSID: ");
Serial.println(ssid);
// Connect to WPA/WPA2 network:
status = WiFi.begin(ssid, pass);
// wait 10 seconds for connection:
delay(10000);
}
// you're connected now, so print out the data:
Serial.print("You're connected to the network\n");
printCurrentNet();
printWifiData();
}
//————————————————– END wifiEncrypted()
//—————————————————— printWifiData()
void printWifiData() {
// print your WiFi shield's IP address:
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);
// print your MAC address:
byte mac[6];
WiFi.macAddress(mac);
Serial.print("MAC address: ");
Serial.print(mac[5],HEX);
Serial.print(":");
Serial.print(mac[4],HEX);
Serial.print(":");
Serial.print(mac[3],HEX);
Serial.print(":");
Serial.print(mac[2],HEX);
Serial.print(":");
Serial.print(mac[1],HEX);
Serial.print(":");
Serial.println(mac[0],HEX);
}
//————————————————– END printWifiData()
//—————————————————- printCurrentNet()
void printCurrentNet() {
// print the SSID of the network you're attached to:
Serial.print("SSID: ");
Serial.println(WiFi.SSID());
// print the MAC address of the router you're attached to:
byte bssid[6];
WiFi.BSSID(bssid);
Serial.print("BSSID: ");
Serial.print(bssid[5],HEX);
Serial.print(":");
Serial.print(bssid[4],HEX);
Serial.print(":");
Serial.print(bssid[3],HEX);
Serial.print(":");
Serial.print(bssid[2],HEX);
Serial.print(":");
Serial.print(bssid[1],HEX);
Serial.print(":");
Serial.println(bssid[0],HEX);
// print the received signal strength:
long rssi = WiFi.RSSI();
Serial.print("signal strength (RSSI):");
Serial.println(rssi);
// print the encryption type:
byte encryption = WiFi.encryptionType();
Serial.print("Encryption Type:");
Serial.println(encryption,HEX);
Serial.println();
}
//———————————————— END printCurrentNet()
//————————————————– connectToTestPage()
void connectToTestPage() {
char server[] = "www.arduino.cc";
WiFiClient client;
// if there's a successful connection:
if (client.connect(server, 80)) {
Serial.println("connecting…");
// send the HTTP PUT request:
client.println("GET /latest.txt HTTP/1.1");
client.println("Host: www.arduino.cc");
client.println("User-Agent: ArduinoWiFi/1.1");
client.println("Connection: close");
client.println();
while (client.available()) {
char c = client.read();
Serial.write(c);
}
}
else {
// if you couldn't make a connection:
Serial.println("connection failed");
}
if (!client.connected()) {
Serial.println();
Serial.println("disconnecting from server.");
client.stop();
}
}
//———————————————- END connectToTestPage()
//—————————————————- connectToGoogle()
void connectToGoogle() {
char server[] = "www.google.com";
WiFiClient client;
Serial.println("\nStarting connection to server…");
// if you get a connection, report back via serial:
if (client.connect(server, 80)) {
Serial.println("connected to server");
// Make a HTTP request:
client.println("GET /search?q=arduino HTTP/1.1");
client.println("Host: www.google.com");
client.println("Connection: close");
client.println();
while (client.available()) {
char c = client.read();
Serial.write(c);
}
}
else {
// if you couldn't make a connection:
Serial.println("connection failed");
}
// if the server's disconnected, stop the client:
if (!client.connected()) {
Serial.println();
Serial.println("disconnecting from server.");
client.stop();
}
}
//———————————————— END connectToGoogle()

view raw

WiFiChecker.ino

hosted with ❤ by GitHub

SD Card

Fixing the SD card errors was not actually what I did after confirming the WiFi worked. I troubleshot the Python, actually, to ascertain whether I was getting data to work with at all.  A giant topic in and of itself, that process will be getting its own post. Fixing the Python didn’t make the code work, however.  So I turned my attention to the SD Card behavior.

Fix the ability to load the SD library on MacOS.

Sadly there is a flaw in the MacOS Intel Galileo developed Arduino IDE. The IDE can’t find some of Libraries even though they are installed. I’m not entirely clear on what causes the Yocto / gcc snafu mentioned, but this article on Yocto and the Intel Galileo from linux.com looks like where I’ll start reading to understand the bug better. In the mean time, to fix it, open Terminal, navigate to the Java folder, add the sym link.

cd /Applications/ArduiG.app/Contents/Resources/Java
ln -s . hardware/tools/x86/i586-poky-linux-uclibc/usr/include/c++/4.2.1

Even after fixing the embed libraries problem, the in the Arduino Intel Galileo IDE v1.5.3 the SD library include statement does not highlight the keywords.

Screen capture of the unhighlighted txt

The SD card library does not highlight.

Ignore that for now.  The library does compile and the code will run.

Break down SD functionality into smaller chunks, get stymied at Step Two

A worse consequence of the symlink workaround is that the SD Card Library example files do not show up in the examples folder. They can be found in the SD Card Reference section on the Arduino website.

As per my ToDo list, I used the example files to try answering the following questions in order:

  • Does the SD card initialize?
  • Can the Arduino sketch create files?
  • Can the Arduino sketch add content to files?
  • Can the Arduino sketch read files?
  • Can the Arduino delete files?

The card initialization code worked just fine, but there was a barrier right on Step 2 that the SparkFun tutorial code neatly avoids with system() call. A bug, not in the Intel Galileo SD library but in the underlying C fopen command, causes any attempt to create a file via Arduino commands to fail. Then attempting to write data to a nonexistent file causes the Arduino process to crash, leading to reboot. If the serial window is open at the time a “**B0100000063f694” message will appear.  In my own testing I skipped dealing with file creation troubles by establishing a serial connection via a dongle to the Linux console and manually creating files.  That I will cover more in the next post. Going through that step taught me that test files can also be created on a computer and dropped into the SD card’s home directory.

Intel Galileo SD card home directory

Intel Galileo SD card home directory with sample files created

Other than creating files, the other need functions needed work just like the examples.

SD Library Full Test Sketch

I did locate a workaround for creating files which I’ve incorporated into a sketch that others can use for testing.

Keep in mind that the SD library and system commands are required to be C Strings  or (lower case s string in Arduino documentation) not the flexible more java-like String Object, String(), that Arduino has also implemented. Much of the crazy in the code below is dealing with translations between the two and creating useful error messages.


/*
// This code is to test SD Card function on an Intel Galileo Board
// It was complied from various examples which can be found:
//
// https://communities.intel.com/thread/46635
// https://communities.intel.com/message/229074
// http://arduino.cc/en/Reference/SD
// http://forum.arduino.cc/index.php?topic=57460.0
//
// Carlyn Maw 2014
// This code is released to the public domain
// Updated March 31, 2014 with information from thread
// https://communities.intel.com/message/229074
*/
#include <SD.h>
// change this to match your SD shield or module;
// Arduino Ethernet shield: pin 4
// Adafruit SD shields and modules: pin 10
// Sparkfun SD shield: pin 8
// Intel Galileo Board: NOT REQUIRED
const int CS_PIN = 4;
// Note that even if it's not used as the CS pin, the hardware SS pin
// (10 on most Arduino boards, 53 on the Mega) must be left as an output
// or the SD library functions will not work.
// NOT REQUIRED on the Galileo
const int HSS_PIN = 10;
void setup() {
//delay so that there will be no interference with the uploading
//of new sketches
delay(5000);
Serial.begin(9600);
//Does the SD card initialized?
initSDCard();
//can I make a file?
galileoCreateFile("i_exist.txt");
//can I append data to an existing file?
addFileContent("i_exist.txt", "celebrate good times!");
//add a little more?
addFileContent("i_exist.txt", "celebrate good times… again!");
//can I look at that data later?
printFileContent("i_exist.txt");
//can I delete a datafile?
deleteFile("i_exist.txt");
}
void loop() {
// nothing happens after setup.
}
//———————————————————– initSDCard()
void initSDCard() {
Serial.print("Initializing SD card…");
//Not necessary for Galileo Board
pinMode(HSS_PIN, OUTPUT);
// try if (!SD.begin()) { if on the Galileo, does not need a pin
// to initialize correctly
if (!SD.begin(CS_PIN)) {
Serial.println("initialization failed!");
return;
}
Serial.println("initialization done.");
}
//—————————————————— END initSDCard()
//———————————————————- deleteFile()
void deleteFile(String fileName) {
Serial.println("\n*****Removal started.*****");
String status_message = String();
status_message = fileName;
char charFileName[fileName.length() + 1];
fileName.toCharArray(charFileName, sizeof(charFileName));
if (SD.exists(charFileName)) {
status_message += " was found.";
Serial.println(status_message);
SD.remove(charFileName);
if (SD.exists(charFileName)) {
status_message += " Removal failed.";
}
else {
status_message += " Removal a success.";
}
}
else {
status_message += " already doesn't exist. Perhaps you meant a different file?";
}
Serial.println(status_message);
}
//—————————————————– END deleteFile()
//————————————————— printFileContent()
void printFileContent(String fileName) {
Serial.println("\n*****Printing Started*****");
String status_message = String();
status_message = fileName;
char charFileName[fileName.length() + 1];
fileName.toCharArray(charFileName, sizeof(charFileName));
if (SD.exists(charFileName)) {
File myFile = SD.open(charFileName);
if (myFile) {
status_message += " found… hold for content: \n\n";
while (myFile.available()) {
status_message += (char)myFile.read();
}
status_message += "\nDone printing.";
myFile.close();
}
else {
status_message += " found, error with content";
}
}
else {
status_message += " does not exist.";
}
Serial.println(status_message);
}
//———————————————– END printFileContent()
//—————————————————– addFileContent()
//SD.open retrieves the file in append more.
void addFileContent(String fileName, String content) {
Serial.println("\n*****Add Started*****");
String status_message = String();
status_message = fileName;
char charFileName[fileName.length() + 1];
fileName.toCharArray(charFileName, sizeof(charFileName));
if (SD.exists(charFileName)) {
status_message += " was found.";
File targetFile = SD.open(charFileName, FILE_WRITE);
targetFile.println(content);
targetFile.close();
status_message += "\n\nFile now reads:\n\n";
File readFile = SD.open(charFileName);
while (readFile.available()) {
status_message += (char)readFile.read();
}
status_message += "\nDone printing.";
readFile.close();
}
else {
status_message += " does not exist. Perhaps you meant to add the information somewhere else.";
}
Serial.println(status_message);
}
//————————————————- END addFileContent()
//——————————————————— createFile()
//—————- DOES NOT WORK ON GALILEO BOARD ———————-
void createFile(String fileName) {
Serial.println("\n*****Creation Started*****");
String status_message = String();
status_message = fileName;
char charFileName[fileName.length() + 1];
fileName.toCharArray(charFileName, sizeof(charFileName));
if (SD.exists(charFileName)) {
status_message += " exists already.";
}
else {
File newFile = SD.open(charFileName, FILE_WRITE);
newFile.close();
if (SD.exists(charFileName)) {
status_message += " created.";
}
else {
status_message += " creation tried and failed.";
}
}
Serial.println(status_message);
}
//—————————————————– END createFile()
//————————————————– galileoCreateFile()
//There appears to ba a bug with fopen() in the C standard library stio.h on
// the Galileo board. The Galileo SD Library calls fopen correctly, but it
// butfopen does not behave as expected. This function works around that.
void galileoCreateFile(String fileName) {
Serial.println("\n*****Creation Started*****");
String status_message = String();
status_message = fileName;
char charFileName[fileName.length() + 1];
fileName.toCharArray(charFileName, sizeof(charFileName));
if (SD.exists(charFileName)) {
status_message += " exists already.";
}
else {
char system_message[256];
char directory[] = "/media/realroot";
sprintf(system_message, "touch %s/%s", directory, charFileName);
system(system_message);
if (SD.exists(charFileName)) {
status_message += " created.";
}
else {
status_message += " creation tried and failed.";
}
}
Serial.println(status_message);
}
//———————————————- END galileoCreateFile()

In this series

  • Part 1
    • Overview
  • Part 2
    • From Zero to Blink.
    • Creating an SD card image and getting a sketch to persist on the Galileo
    • UPDATE: Blink on an external LED
  • Part 3
    • Creating the bees and getting them to work on an Arduino UNO
  • Part 4 (This Post)
    • Setting up Wifi (very easy, library examples worked immediately)
    • Getting the SD card read & write to work (a missing libraries/symlink problem)
  • Part 5
    • Serial Communication to the Linux Core
    • Troubleshooting Python on the Galileo
  • Part 6
    • Revising the example String to Int code (lack of Null Termination problems)
    • Moving the motors over to the Galileo