Skip to content

SIKIO C6: Analog In & Data Logging

Jordan McConnell edited this page Jan 8, 2014 · 16 revisions

In this circuit we'll be reading in values from a photocell, and saving the values to a text file stored on your phone. We'll also do a simple little real-time graph of the photocell values.

##Circuit Diagram

C6

Code Walkthrough

Let's start with our IOIO tab. As before, we need to set up variables for type of pin, the pin number, and the value coming in.

  AnalogInput photo; // Our photocell is an AnalogInput
  int photoPin = 39; // The pin for our potentiometer
  float photoVal; // Input analog values ranging from 0 to 1

In our ioioSetup() method, we need to open our Pin:

   photo = ioio.openAnalogInput(photoPin);

And in our ioioLoop() method, we need to read in the value from the photocell into our photoVal variable:

   photoVal = photo.read();

Back in our main tab, our primary job is to take the value we're getting from our photocell, display it, and if we press a button, write the photocell values collected over a short period of time to text file stored locally on our phone. You can retrieve the text file by plugging your phone in to your computer and enabling USB storage. The file should be in a folder called Sikio within the root directory. The file will be called sensorValues.txt.

Our first step is to check whether we can access and write to the external storage on our Android device. We're going to need some String variables to display two boolean variables that display the results of a checkStorage() method. These go at the top of your main tab, above the setup() method.

// These variables hold the state of storage device's availability, write access, and logging status. 
String storageAvailable, storageWritable, logStatus;

Inside our setup() method, we need to call our checkStorage() method, which will let us know if we've got the proper access to create and write to a text file on our device. We also create our "log" button and set logStatus to "ready".

  //Method that checks whether local storage is accessible and writable
  checkStorage();
  
  // Create a our widget container and place our log button.
  widgetContainer = new APWidgetContainer(this);
  logButton = new APButton(10, 150, "Log Data");
  widgetContainer.addWidget(logButton);
  
  logStatus = "ready"; // Log status is in ready state until button is pressed, purely for display.

Down below, after our draw() loop, we have the actual code for the checkStorage() method. This function checks to see if the removable storage is available and if we can write to it.

public void checkStorage() {

  // Get the readable/writable state of our media storage
  String state = Environment.getExternalStorageState();

  if (Environment.MEDIA_MOUNTED.equals(state)) 
  {
    // We can read and write to files.
    storageAvailable = storageWritable = "true";
  } 
  else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) 
  {
    // We can only read files.
    storageAvailable = "true";
    storageWritable = "false";
  } 
  else 
  {
    // Something else is wrong. We can neither read nor write to a file.
    storageAvailable = storageWritable = "false";
  }
}

In our draw() loop, we're going to display a graph corresponding to the current photocell reading, display a button that triggers the recording of sensor values, and display text that corresponds to the values we're getting from our photocell as well as our logging status.

  background(0); // Clear background.
  
  // Draw a verticle bar graph to show sensor reading.
  stroke(255, 0, 0); // Set line color to red.
  strokeWeight(30); // Set width of line in pixels.
  // Now draw a line that corresponds to our current sensor reading.
  line(width/2, height, width/2, height - (photoVal * 1000));

  // Print the photocell sensor input as well as SD card logging status.
  text("Analog Value: " + photoVal, 10, 50);
  text("Log Status: " + logStatus, 10, 100);

We're using an APWidgets button to control the start of our data logging, so all the action is in our onClickWidget() function. Basically, when the button is pressed, we get the root directory of our device, create a folder called "Sikio", open up a file on it, write our sensor values to it over a brief period of time, and close the file when we're done.

// This function is called when the log button is pressed. 
void onClickWidget(APWidget widget) 
{
  // Checks if logButton was pressed
  if (widget == logButton) 
  {
    logStatus = "got button press"; // logStatus reflects that button was pressed

    try 
    {
      // Update status to indicate we are recording sensor values to a file
      logStatus = "recording";
      
      // Create a Sikio folder if it's not present
      File folder = new File("/sdcard/Sikio/");
      folder.mkdirs();
       
      // Get the external storage directory. 
      File root = Environment.getExternalStorageDirectory();
      
      // If we can write to our storage, create a text file, and fire up a BufferedWriter to write to it
      if (root.canWrite()) 
      {
        File sensorValues = new File(root, "/Sikio/sensorValues.txt");
        FileWriter writer = new FileWriter(sensorValues);
        BufferedWriter out = new BufferedWriter(writer);
        
       // We just want to take a few seconds worth of data when we hit the button. 
       for (int i = 0; i < 1000000; i++) 
       {
         // Take 1 of every 1000, don't need too many values too quickly
         if (i % 1000 == 0) 
         {
           // Write values to our text file
           out.write((i / 1000) + "\t" + photoVal + "\r\n");
         }
       }
        
       // Close our BufferedWriter.
       out.close();
       
       // Update the Android's file system so that the file will be shown 
       // when the Android is plugged back into the computer (without restarting the device)
       sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://" + root + "/Sikio/")));

       // We're done! Update status so user is aware that the file logging has finished.
       logStatus = "done";
      }
    } 
    catch (IOException e) 
    {
      // Let us know if we couldn't log for some reason.
      logStatus = "exception";
    }
  }
}

At the end of the previous function, we use sendBroadcast() method to tell the Android that the files in that directory have been updated so they can be seen when you plug your Android back into your computer.

If everything worked correctly, you should be able to plug in your device, enable USB storage, and find a sensorValues.txt file that contains a bunch of readings from your photocell in the Sikio folder. If for some reason you can't see the file, try restarting your phone and plugging it back in to the computer.

For a bonus challenge, try programming a stop button to halt the recording of sensor values instead of using the given for loop.

Continue to C7 - Camera.