Arduino Yun SD card problem and webpage problem

I’m currently working on a project to have a Yun read in voltages from a pressure sensor. The Yun then translates the voltages to pressures, prints the pressures to a webpage and records them to a text file on an SD card.

My code is written and compiles, but is still not doing what I want. I’m spent the last few days asking around and searching the internet for solutions, but I’m finally at a loss as to what to do. I’ve hacked together the code from previous projects which I’ve done and a few example codes provided, including that included here (http://blog.arduino.cc/2013/09/05/hands-on-the-arduino-yuns-bridge/) to print data to a webpage, and this one (http://arduino.cc/en/Tutorial/YunDatalogger) to record the data to a file on the SD card. Like I said, my final code compiles with no errors, but when I open up the serial monitor I get the message “error opening datalog.txt”. I believe this problem has to do with the SD card, but I’m not sure exactly what the problem is or how to fix it.

The webpage also wont load. The problem is probably that I simply don’t know where to go to find the page. I’ve tried searching it with the IP address of my Yun, but the webpage either doesn’t load or it takes me to the page where I can configure my Yun’s Wifi and Ethernet settings. The page where I got the example code from provides addresses to go to to see my data, but those wont load either.

This is my first project with a Yun, so I’m still fairly inexperienced with the board. I have, however, used an Uno to read in temperatures and print them to a webpage, and to work with a GUI to control a motor and print out the motor’s position to a webpage.

If anyone knows why I’m getting the message “error opening datalog.txt” and why this webpage wont load, please let me know. From what I’ve heard and been reading, this is actually a mechanical problem, but, if it is in my case, I don’t know what the actual problem is or how to fix it.

My code is below. If you’re reading through it, ignore the “Briannatempfactor” part. That will be replaced by the correct conversion for voltage to pressure. Although this compiles, I’m sure there’s still something wrong with this.

#include <FileIO.h>
#include <SPI.h>
#include <Ethernet.h>
#include <Bridge.h>
#include <YunServer.h>
#include <YunClient.h>

YunServer server;
String startString;
long hits = 0;

int pin = 0; // analog pin
int pressureT1 = 0; // pressure variables
int samples[8]; // variables to make a better precision
int maxiT1 = -100,miniT1 = 100; // to start max/min pressure
int i;

void setup() {
  // Initialize the Bridge and the Serial
  Serial.begin(9600);
  
  //Bridge startup
  FileSystem.begin();
  digitalWrite(13, LOW);
  Bridge.begin();
  digitalWrite(13, HIGH);
  
  // using A0 and A2 as vcc and gnd for the TMP36 sensor:
  pinMode(A0, OUTPUT);
  pinMode(A2, OUTPUT);
  digitalWrite(A0, HIGH);
  digitalWrite(A2, LOW);

  while(!Serial);  // wait for Serial port to connect.
  Serial.println("Filesystem datalogger\n");
  
  server.listenOnLocalhost();
    server.begin();
    
  // get the time that this sketch started:
  Process startTime;
  startTime.runShellCommand("date");
  while(startTime.available()) {
    char c = startTime.read();
    startString += c;
  }

}


void loop () 
{
  // make a string that start with a timestamp for assembling the data to log:
  String dataString;
  dataString += getTimeStamp();
  dataString += " = ";

  // read three sensors and append to the string:
  for (i = 0; i < 7; i++) {
     float briannaTempFactor = 30.0/74.5;
     //Device specific calibration from pin voltage to temperature with our handy dandy briannaTempFactor
     samples[i] = ( briannaTempFactor*5.0 * analogRead(pin) * 100.0) / 1024.0; //need to change to pressure
     pressureT1 = pressureT1 + samples[i];
     int sensor = analogRead(i);
     dataString += String(sensor);
     if (i < 7) {
       dataString += ",";  // separate the values with a comma
    }
     delay(100);
  }
    pressureT1 = pressureT1/8.0; // Obtain average value
      
   if(pressureT1 > maxiT1) {maxiT1 = pressureT1;} // set max pressure
   if(pressureT1 < miniT1) {miniT1 = pressureT1;} // set min pressure

   Serial.print(pressureT1,DEC);
   Serial.print(" PSI ");
   Serial.print(maxiT1,DEC);
   Serial.print(" Max, ");
   Serial.print(miniT1,DEC);
   Serial.println(" Min");
 
  //finished the pressure readout   
 
 //WEBSERVER STUFF
   YunClient client = server.accept();
   
   if (client) {
    // read the command
    String command = client.readString();
    command.trim();        //kill whitespace
    Serial.println(command);
    // is "pressuret1" command?
    if (command == "pressureT1") {
 
      // get the time from the server:
      Process time;
      time.runShellCommand("date");
      String timeString = "";
      while(time.available()) {
        char c = time.read();
        timeString += c;

   }
   
   Serial.println(timeString);
      int sensorValue = analogRead(A1);
      // convert the reading to millivolts:
      float voltage = sensorValue *  (5000/ 1024); 
      // convert the millivolts to temperature celsius: NEED TO CONVERT TO PRESSURE INSTEAD
      float pressureT1 = (voltage - 500)/10;
      // print the voltage:
      client.print("Current time on the Yún: ");
      client.println(timeString);
      client.print("
Current pressure: ");
      client.print(pressureT1);
      client.print(" PSI");
      client.print("
This sketch has been running since ");
      client.print(startString);
      client.print("
Hits so far: ");
      client.print(hits);
    }
 
    // Close connection and free resources.
    client.stop();
    hits++;
  }


  // open the file. note that only one file can be open at a time,
  // so you have to close this one before opening another.
  // The FileSystem card is mounted at the following "/mnt/FileSystema1"
  File dataFile = FileSystem.open("/mnt/sd/datalog.txt", FILE_APPEND);

  // if the file is available, write to it:
  if (dataFile) {
    dataFile.println(dataString);
    dataFile.close();
    // print to the serial port too:
    Serial.println(dataString);
  }  
  // if the file isn't open, pop up an error:
  else {
    Serial.println("error opening datalog.txt");
  }

  delay(1500);
}
// This function return a string with the time stamp
String getTimeStamp() {
  String result;
  Process time;
  // date is a command line utility to get the date and the time
  // in different formats depending on the additional parameter
  time.begin("date");
  time.addParameter("+%D-%T");  // parameters: D for the complete date mm/dd/yy
                                //             T for the time hh:mm:ss    
  time.run();  // run the command

  // read the output of the command
  while(time.available()>0) {
    char c = time.read();
    if(c != '\n')
      result += c;
  }
  return result;
}

May not apply to a Yun, but below is the way the Ethernet shield and SD card are initialized on an arduino so they play well together.

//zoomkat 12/26/12
//SD server test code
//open serial monitor to see what the arduino receives
//address will look like http://192.168.1.102:84 when submited
//for use with W5100 based ethernet shields

#include <SD.h>
#include <SPI.h>
#include <Ethernet.h>

byte mac[] = { 
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; //physical mac address
byte ip[] = { 
  192, 168, 1, 102 }; // ip in lan
byte gateway[] = { 
  192, 168, 1, 1 }; // internet access via router
byte subnet[] = { 
  255, 255, 255, 0 }; //subnet mask
EthernetServer server(84); //server port
String readString; 

//////////////////////

void setup(){

  Serial.begin(9600);

  // disable w5100 while setting up SD
  pinMode(10,OUTPUT);
  digitalWrite(10,HIGH);
  Serial.print("Starting SD..");
  if(!SD.begin(4)) Serial.println("failed");
  else Serial.println("ok");

  Ethernet.begin(mac, ip, gateway, gateway, subnet);
  //delay(2000);
  server.begin();
  Serial.println("Ready");
}

void loop(){
  // Create a client connection
  EthernetClient client = server.available();
  if (client) {
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();

        //read char by char HTTP request
        if (readString.length() < 100) {
          //store characters to string 
          readString += c; 
          //Serial.print(c);
        } 
        //if HTTP request has ended
        if (c == '\n') {

          ///////////////
          Serial.println(readString); //print to serial monitor for debuging 

            client.println("HTTP/1.1 200 OK"); //send new page
          //client.println("Content-Type: text/html");
          client.println("Content-Type: image/jpeg");
          //client.println("Content-Type: image/gif");
          //client.println("Content-Type: application/x-javascript");
          //client.println("Content-Type: text");

          client.println();

          //File myFile = SD.open("boom.htm");
          File myFile = SD.open("HYPNO.JPG");
          //File myFile = SD.open("BLUEH_SL.GIF");
          //File myFile = SD.open("SERVOSLD.HTM");

          if (myFile) {

            byte clientBuf[64];
            int clientCount = 0;

            while(myFile.available())
            {
              clientBuf[clientCount] = myFile.read();
              clientCount++;

              if(clientCount > 63)
              {
                // Serial.println("Packet");
                client.write(clientBuf,64);
                clientCount = 0;
              }
            }
            //final <64 byte cleanup packet
            if(clientCount > 0) client.write(clientBuf,clientCount);            
            // close the file:
            myFile.close();
          }
          delay(1);
          //stopping client
          client.stop();
          readString="";
        }
      }
    }
  } 
}

Thanks for the advice. I've used a similar code to the one you posted for my projects with the Uno. My first instinct was to try to tweak it a bit for the Yun, but from what I've seen and tried, the Yun is pretty different from the Uno when it comes to posting to a webpage.

I'm going to continue looking over my code so that I can be sure this is actually a mechanical problem and not something I'm doing wrong. If anyone has experienced this problem before and knows how to solve it, I would really appreciate your advice.

I have tried this with three other Yun's (using the same SD card for each) and the same error message ("error opening datalog.txt") continues to pop up in the serial monitor. I've tried both my own code and the SD DataLogger code for each board. I also get this same message if no SD card is in. This makes me think that the problem is not with the board or the code (although the one I wrote might still be faulty in different areas) but with the card itself.

I wonder if there is a limit to the size of the card. The card I'm using is a 64 GB micro. Most of the other places on the internet talking about using SD cards with Yun's use significantly smaller cards. I'm not sure if this is actually a problem, but I'll try with a card around 8 GB to be sure.

As I mentioned before, if anyone has any experience with this problem, your advice would be tremendously helpful.

Alright, I’ve the code works now. Since there doesn’t seem to be much information about my problem, I’m going to post the final code here.

#include <FileIO.h>
#include <SPI.h>
#include <Ethernet.h>
#include <Bridge.h>
#include <YunServer.h>
#include <YunClient.h>

YunServer server;

int pin = 0; // analog pin
int pressureT1 = 0; // pressure variables
int samples[8]; // variables to make a better precision
int maxiT1 = -100,miniT1 = 100; // to start max/min pressure
int i;

void setup() {
  // Initialize the Bridge and the Serial
  Serial.begin(9600);
  
  //Bridge startup
  FileSystem.begin();
  digitalWrite(13, LOW);
  Bridge.begin();
  digitalWrite(13, HIGH);
  
  while(!Serial);  // wait for Serial port to connect.
  Serial.println("Filesystem datalogger\n");
  
  server.listenOnLocalhost();
  server.begin();
}


void loop () 
{
  // make a string that start with a timestamp for assembling the data to log:
  String dataString;
  dataString += getTimeStamp();
  dataString += " = ";

  // read three sensors and append to the string:
  for (i = 0; i < 7; i++) {
     float briannaTempFactor = 30.0/74.5;
     //Device specific calibration from pin voltage to temperature with our handy dandy briannaTempFactor
     samples[i] = ( briannaTempFactor*5.0 * analogRead(pin) * 100.0) / 1024.0; //need to change to pressure
     pressureT1 = pressureT1 + samples[i];

     int sensor = analogRead(i);
     dataString += String(sensor);
     if (i < 7) {
       dataString += ",";  // separate the values with a comma
    }
     delay(100);
  }
    
   pressureT1 = pressureT1/8.0; // Obtain average value
      
   if(pressureT1 > maxiT1) {maxiT1 = pressureT1;} // set max pressure
   if(pressureT1 < miniT1) {miniT1 = pressureT1;} // set min pressure

   Serial.print(pressureT1,DEC);
   Serial.print(" PSI ");
   Serial.print(maxiT1,DEC);
   Serial.print(" Max, ");
   Serial.print(miniT1,DEC);
   Serial.println(" Min");
  //finished the pressure readout  
 
  // open the file. note that only one file can be open at a time,
  // so you have to close this one before opening another.
  // The FileSystem card is mounted at the following "/mnt/FileSystema1"
  File dataFile = FileSystem.open("/mnt/sd/datalog.txt", FILE_APPEND);

  // if the file is available, write to it:
  if (dataFile) {
    dataFile.println(dataString);
    dataFile.close();
    // print to the serial port too:
    Serial.println(dataString);
  }  
  // if the file isn't open, pop up an error:
  else {
    Serial.println("error opening datalog.txt");
  } 
 
 //WEBSERVER STUFF
     // Get clients coming from server
  YunClient client = server.accept();
  // There is a new client?
  if (client) {
    //process(client);
    Serial.println("new client");
    boolean currentLineIsBlank = true;
    while (client.connected()){
      if (client.available()) {
        char c = client.read();
        Serial.write(c);
        if (c == '\n') {
           client.println("Status: 200");
           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><meta http-equiv=\"refresh\"content=\"10\"></head>");
           for (int analogChannel = 0; analogChannel < 1; analogChannel++) {
             int sensorReading = analogRead(analogChannel);
             client.print("Current pressure of T1 is ");
             client.print(pressureT1);
             client.print(" PSI ");
           }
             client.println("</html>");
             break;
  }
  if (c == '\n') {
    currentLineIsBlank = true;
  }
  else if (c != '\r') {
    currentLineIsBlank = false;
  }
    }
    }
   delay(10); 
   client.stop();
   Serial.println("client disonnected");
}
delay(1500); 
}

// This function return a string with the time stamp
String getTimeStamp() {
  String result;
  Process time;
  // date is a command line utility to get the date and the time
  // in different formats depending on the additional parameter
  time.begin("date");
  time.addParameter("+%D-%T");  // parameters: D for the complete date mm/dd/yy
                                //             T for the time hh:mm:ss    
  time.run();  // run the command

  // read the output of the command
  while(time.available()>0) {
    char c = time.read();
    if(c != '\n')
      result += c;     
  }
  return result;
}

To see the pressure readings, go to http://192.168.240.1/arduino/analog/0 (replace my Yun’s address with yours, though). I’m still awaiting my new SD card, but this code should work. The webpage displays pressure values and refreshes every ten seconds.

some meta refresh code that might be of interest.

/ zoomkat's meta refresh data frame test page 5/25/13
// use http://192.168.1.102:84 in your brouser for main page
// http://192.168.1.102:84/data static data page
// http://192.168.1.102:84/datastart meta refresh data page
// for use with W5100 based ethernet shields
// set the refresh rate to 0 for fastest update
// use STOP for single data updates

#include <SPI.h>
#include <Ethernet.h>

const int analogInPin0 = A0;
const int analogInPin1 = A1;
const int analogInPin2 = A2;
const int analogInPin3 = A3;
const int analogInPin4 = A4;
const int analogInPin5 = A5;

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; //physical mac address
byte ip[] = { 192, 168, 1, 102 }; // arduino ip in lan
byte gateway[] = { 192, 168, 1, 1 }; // internet access via router
byte subnet[] = { 255, 255, 255, 0 }; //subnet mask
EthernetServer server(84); //server port
unsigned long int x=0; //set refresh counter to 0
String readString; 

//////////////////////

void setup(){
  Serial.begin(9600);
    // disable SD SPI if memory card in the uSD slot
  pinMode(4,OUTPUT);
  digitalWrite(4,HIGH);

  Ethernet.begin(mac, ip, gateway, gateway, subnet);
  server.begin();
  Serial.println("meta refresh data frame test 5/25/13"); // so I can keep track of what is loaded
}

void loop(){
  EthernetClient client = server.available();
  if (client) {
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
         if (readString.length() < 100) {
          readString += c; 
         } 
        //check if HTTP request has ended
        if (c == '\n') {

          //check get atring received
          Serial.println(readString);

          //output HTML data header
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println();

          //generate data page
          if(readString.indexOf("data") >0) {  //checks for "data" page
            x=x+1; //page upload counter
            client.print("<HTML><HEAD>");
            //meta-refresh page every 1 seconds if "datastart" page
            if(readString.indexOf("datastart") >0) client.print("<meta http-equiv='refresh' content='1'>"); 
            //meta-refresh 0 for fast data
            if(readString.indexOf("datafast") >0) client.print("<meta http-equiv='refresh' content='0'>"); 
            client.print("<title>Zoomkat's meta-refresh test</title></head><BODY>
");
            client.print("page refresh number: ");
            client.print(x); //current refresh count
            client.print("

");
            
              //output the value of each analog input pin
            client.print("analog input0 is: ");
            client.print(analogRead(analogInPin0));
            
            client.print("
analog input1 is: ");
            client.print(analogRead(analogInPin1));
                        
            client.print("
analog input2 is: ");
            client.print(analogRead(analogInPin2));
            
            client.print("
analog input3 is: ");
            client.print(analogRead(analogInPin3));
                                    
            client.print("
analog input4 is: ");
            client.print(analogRead(analogInPin4));
            
            client.print("
analog input5 is: ");
            client.print(analogRead(analogInPin5));
            client.println("
</BODY></HTML>");
           }
          //generate main page with iframe
          else
          {
            client.print("<HTML><HEAD><TITLE>Zoomkat's frame refresh test</TITLE></HEAD>");
            client.print("Zoomkat's Arduino frame meta refresh test 5/25/13");
            client.print("

Arduino analog input data frame:
");
            client.print("&nbsp;&nbsp;<a href='/datastart' target='DataBox' title=''yy''>META-REFRESH</a>");
            client.print("&nbsp;&nbsp;&nbsp;&nbsp;<a href='/data' target='DataBox' title=''xx''>SINGLE-STOP</a>");
            client.print("&nbsp;&nbsp;&nbsp;&nbsp;<a href='/datafast' target='DataBox' title=''zz''>FAST-DATA</a>
");
            client.print("<iframe src='/data' width='350' height='250' name='DataBox'>");
            client.print("</iframe>
</HTML>");
          }
          delay(1);
          //stopping client
          client.stop();
          //clearing string for next read
          readString="";
        }
      }
    }
  }
}