Android Lollipop 5.0 built from scratch

My Nexus 5 died. (Bad phone. BAD!) And its time to rebuild the Android baseline from scratch anyway so here it is. Lollipop 5.0 from scratch. Flashed on my backup Nexus 4.

Android Lillipop "About Screen" screenshot

Android Lillipop “About Screen” screenshot

Nothing like a fresh rebuild with the latest and a successful flash. (Cracks knuckles) Nice!

Advertisements
Posted in Android AOSP | Leave a comment

Android Kit Kat 4.4.2 built from scratch

I develop on a Mac and I recently did an update to my Ubuntu Virtual Machine and … of course it hanged on reboot. (sigh) So, nuked it, reinstalled Ubuntu 12.04, install the latest patches, install the android toolchain etc etc. Downloaded the Kit Kat android-sdk-4.4.2_r1 branch, install the Nexus 4 vendor binaries, build and behold, success!

Android Kit Kat 4.4.2 built from scratch

Android Kit Kat 4.4.2 built from scratch

Posted in Android AOSP | Leave a comment

XBee and Sensor Printed Circuit Board

After finishing the Building Wireless Sensor Networks book, I have to look at the output of the circuits and realize that you cant deploy a solder-less breadboard. (Laugh) It doesn’t look very professional to ship someone a rats nest of wiring. So I bought a copy of Eagle CAD PCB Design Software and created a printed circuit board(PCB). Check it out:

Uploaded this design to OSH Park PCB Manufacturer. As you can see from the pictures, they use a distinctive purple solder mask. At about $5 a square inch, three copies of this board cost ~$45 dollars and about two weeks to get the boards back.

There are four PCB’s on this one board. Three temperature sensor PCB’s and one main PCB holding a 3.3V Voltage Regulator and an XBee. On the main PCB I pulled out the RSSI and ON pins through LED’s that can be enabled by a jumper. Pulled out the RX/TX and CTS/RTS wires for future expansion. And provided VCC and 3.3V pins for testing and for powering the board if needed without using a wall plug.

My plan is to have this one XBee board read three temperature sensors.  This will replace the three XBee boards each reading a single temperature sensor that I currently have. I’m rewriting the BWSN Chapter 8 “More to Love” Processing sketch to read these three analog values and upload to Xively.

So what went right:

* (MAJOR) Wrestled with Eagle CAD to create my first PCB.

* (MINOR) Ordered the correct matching Molex male/female and crimps to have a polarized connectors for the voltage and data pins from the XBee board to the Temperature sensor. You may not think this is important but having a connector that only allows a certain orientation to be plugged in saves time and effort in troubleshooting.

What went wrong:

* (MAJOR ISSUE) Used the wrong Voltage regulator part in Eagle CAD. The one I originally used on this board was center grounded:

Pin 1(VOUT) Pin 2(GND) Pin 3(VIN)

But the LD1117V33 voltage regulator in To-220 package I’m using is Pin 1 grounded:

Pin 1(GND) Pin 2(VOUT) Pin 3(VIN)

Dang. So a small hardware mod when connecting this to the board and its all fixed! But it’s kind of frustrating to solder the part onto the board, test and find that you aren’t getting 3.3v out.

Overlooked Label* (MINOR) Forgot to add (Plus)+ and (Gnd)- text on the PCB silkscren pins for the VCC and 3.3V taps I placed on the board.

Crowded Text* (MINOR) Need to move the 3.3V-GND-DATA labels on the PCB silkscreen out from the pins so that the Molex connector doesn’t completely obscure the text.

Posted in BWSN, PCB Awesome | Leave a comment

Android Jelly Bean 4.3 built from scratch

Created a new Ubuntu 12.04 virtual machine last night, reinstalled the android tool chain. Downloaded and built android-4.3_r1.1 for my Galaxy Nexus test phone. Flashed without any issues. Check it:

android-4.3_r1.1 Info Screen

android-4.3_r1.1 Info Screen

The hardest part was figuring out how to get the VMWare tools to compile and install on Ubuntu. (Shrug)

EDIT: Wrongly identified this as ICS (Ice Cream Sandwich) but the Android 4.3 branch is code named Jelly Bean. Changed the title to correct this error.

Posted in Android AOSP | Leave a comment

BWSN Uploading to Xively

Here is the video for Chapter 8 “More to Love”.

I was hoping to get the processing sketch to upload a week or two of sensor data until I made a post about it, but I kept running into issues. (Laugh)

You can see my Xively device page here. This show’s my XBee temperature sensor network at room, fridge and freezer temperatures.

So the original source code for this project can be found on the author’s website here. Unfortunately this code is not up to date. The book and the downloaded code upload to Pachube. BUT Pachube changed its name twice since this book was writtien, first to Cosm then to Xively.

In light of these changes, I’ve fixed the processing sketch to upload to Xively using the EEML library. So step by step:
1) Login to Xively and create an account. Once you have a free developer account/login, create a device. The device page will give you a FeedID and an API Key which will need to be placed in the Processing sketch.
2) Download the code from the author’s website here.
3) Download the EEML(Extended Environments Markup Language) jar library from here and place it in the “code” directory of the Processing sketch.
4) Replace the Processing sketch provided by the author’s website and use this sketch instead. Replace the FeedID and apiKey with the ones provided by your Xively device webpage:

/*
 * Draws a set of thermometers for incoming XBee Sensor data
 * by Rob Faludi http://faludi.com
 *
 * Oct 2013 - Updated to use EEML, upload to Xively and display both Celsius and
 *   Fahrenheit display numbers.
 */

// Using EEML for Xively connection http://xively.com/
// EEML Processing.org library available at http://www.eeml.org/library/
import eeml.*;

// used for communication via xbee api
import processing.serial.*; 

// xbee api libraries available at http://code.google.com/p/xbee-api/
// Download the zip file, extract it, and copy the xbee-api jar file 
// and the log4j.jar file (located in the lib folder) inside a "code" 
// folder under this Processing sketch’s folder (save this sketch, then 
// click the Sketch menu and choose Show Sketch Folder).
import com.rapplogic.xbee.api.ApiId;
import com.rapplogic.xbee.api.PacketListener;
import com.rapplogic.xbee.api.XBee;
import com.rapplogic.xbee.api.XBeeResponse;
import com.rapplogic.xbee.api.zigbee.ZNetRxIoSampleResponse;

String version = "1.10";

//  *** Replace with the Serial Port (Com Port) Number for your local Xbee *** 
int SerialPortNumber = 1;


// *** REPLACE WITH YOUR OWN PACHUBE API KEY AND FEED ID ***
String XivelyBaseURL="https://api.xively.com/v2/feeds/";
String apiKey="ADD_THE_XIVELY_APP_KEY_FOR_YOUR_DEVICE_HERE";
String feedID="ADD_THE_XIVELY_FEEDID_FOR_YOUR_DEVICE_HERE" + ".xml";

DataOut dOut;  // Data object used to upload to Xively

// create and initialize a new xbee object
XBee xbee = new XBee();

int error=0;

// Defines the thermometer ID starting at zero and incrementing.
// Used to differentiate streams on Xively
int thermID = 0;  

// used to record time of last data post
float lastUpdate;

// make an array list of thermometer objects for display
ArrayList thermometers = new ArrayList();
// create a font for display
PFont font;

void setup() {
  size(800, 600); // screen size
  smooth(); // anti-aliasing for graphic display


  // You’ll need to generate a font before you can run this sketch.
  // Click the Tools menu and choose Create Font. Click Sans Serif,
  // choose a size of 10, and click OK.
  font =  loadFont("SansSerif-10.vlw");
  textFont(font); // use the font for text

  // The log4j.properties file is required by the xbee api library, and 
  // needs to be in your data folder. You can find this file in the xbee
  // api library you downloaded earlier
  PropertyConfigurator.configure(dataPath("")+"log4j.properties"); 
  // Print a list in case the selected one doesn't work out
  println("Available serial ports:");
  println(Serial.list());
  try {
    // opens your serial port defined above, at 9600 baud
    xbee.open(Serial.list()[SerialPortNumber], 9600);
  }
  catch (XBeeException e) {
    println("** Error opening XBee port: " + e + " **");
    println("Is your XBee plugged in to your computer?");
    println(
      "Did you set your COM port in the code near line 27?");
    error=1;
  }
  
  // Create the XivelyURL and setup
  String FeedURL = XivelyBaseURL + feedID;
  dOut = new DataOut(this, FeedURL, apiKey); 
}


// draw loop executes continuously
void draw() {
  background(224); // draw a light gray background
  // report any serial port problems in the main window
  if (error == 1) {
    fill(0);
    text("** Error opening XBee port: **\n"+
      "Is your XBee plugged in to your computer?\n" +
      "Did you set your COM port in the code near line 20?", width/3, height/2);
  }
  SensorData data = new SensorData(); // create a data object
  data = getData(); // put data into the data object
  //data = getSimulatedData(); // uncomment this to use random data for testing

  // check that actual data came in:
  if (data.value >=0 && data.address != null) { 

    // check to see if a thermometer object already exists for this sensor
    int i;
    boolean foundIt = false;
    for (i=0; i <thermometers.size(); i++) {
      if ( ((Thermometer) thermometers.get(i)).address.equals(data.address) ) {
        foundIt = true;
        break;
      }
    }

    // *** ENABLE THIS CODE FOR LM335 temperature sensor ****
    // process the data value into a Celsius temperature reading for
    // LM335 with a 1/3 voltage divider
    //   (value as a ratio of 1023 times max ADC voltage times 
    //    3 (voltage divider value) divided by 10mV per degree
    //    minus zero Celsius in Kevin)
    // float temperatureCelsius = (data.value/1023.0*1.2*3.0*100)-273.15;

    //    // *** ENABLE THIS CODE FOR TMP36 temperature sensor ****
    //    // process the data value into a Celsius temperature reading for
    //    // TMP36 with no voltage divider
    //    //   (value as a ratio of 1023 times max ADC voltage times 
    //    //    minus 500 mV reading at zero Celsius
    //    //    times 100 to scale for 10mv per degree C)
    float temperatureCelsius = ((data.value/1023.0*1.25 - .5) *100); 
    
    println(" temp: " + round(temperatureCelsius) + "˚C");

    // update the thermometer if it exists, otherwise create a new one
    if (foundIt) {
      ((Thermometer) thermometers.get(i)).temp = temperatureCelsius;
    }
    else if (thermometers.size() < 10) {
      thermometers.add(new Thermometer(data.address,35,450,
      (thermometers.size()) * 75 + 40, 20, data.numericAddr, thermID++));
      ((Thermometer) thermometers.get(i)).temp = temperatureCelsius;
      
      int thermometerFeedID = ((Thermometer) thermometers.get(i)).thermometerID;
      println("Init thermometerFeedID: " + thermometerFeedID);
      
      // Init Xively here for each Temp Bar
      dOut.addData(thermometerFeedID,
                       "TempSensor_" + thermometerFeedID ,
                      (float)40.0, (float)-10.0);
      dOut.setUnits(thermometerFeedID, "Celsius","C","basicSI");
    }

    // draw the thermometers on the screen
    for (int j =0; j<thermometers.size(); j++) {
      ((Thermometer) thermometers.get(j)).render();
    }
    // post data to Xively every minute
    if ((millis() - lastUpdate) > 60000) {
      for (int j =0; j<thermometers.size(); j++) {
        ((Thermometer) thermometers.get(j)).dataPost();
      }
      lastUpdate = millis();
    }
  }
} // end of draw loop


// defines the data object
class SensorData {
  int value;
  String address;
  long numericAddr;
}


// defines the thermometer objects
class Thermometer {
  int sizeX, sizeY, posX, posY;
  float maxTemp = 40; // max of scale in degrees Celsius
  float minTemp = -10; // min of scale in degress Celsius
  float temp; // stores the temperature locally
  String address; // stores the address locally
  long numAddr; // stores the numeric version of the address
  int thermometerID;  // Feed ID of this object
  float temp_f;  // temp in F


  Thermometer(String _address, int _sizeX, int _sizeY, 
  int _posX, int _posY, long _numAddr, int _ID) { // initialize thermometer object
    address = _address;
    sizeX = _sizeX;
    sizeY = _sizeY;
    posX = _posX;
    posY = _posY;
    numAddr = _numAddr;
    thermometerID = _ID;
  }

  void dataPost() {
    // add and tag a datastream
    int thermometerFeedID = thermometerID;
    println("thermometerFeedID: " + thermometerFeedID);
    
    
    //Update Xively feed objects
    dOut.update(thermometerFeedID, (float) temp);
    println("posting to Xively...");
    int response = dOut.updatePachube(); // update the datastream
    println(response);  // Should be 200 OK success

  }

  void render() { // draw thermometer on screen
    noStroke(); // remove shape edges
    ellipseMode(CENTER); // center bulb
    float bulbSize = sizeX + (sizeX * 0.5); // determine bulb size
    int stemSize = 30; // stem augments fixed red bulb 
    // to help separate it from moving mercury
    // limit display to range
    float displayTemp = round( temp);
    if (temp > maxTemp) {
      displayTemp = maxTemp + 1;
    }
    if ((int)temp < minTemp) {
      displayTemp = minTemp;
    }
    // size for variable red area:
    float mercury = ( 1 - ( (displayTemp-minTemp) / (maxTemp-minTemp) ));
    // draw edges of objects in black
    fill(0); 
    rect(posX-3,posY-3,sizeX+5,sizeY+5); 
    ellipse(posX+sizeX/2,posY+sizeY+stemSize, bulbSize+4,bulbSize+4);
    rect(posX-3, posY+sizeY, sizeX+5,stemSize+5);
    // draw grey mercury background
    fill(64); 
    rect(posX,posY,sizeX,sizeY);
    // draw red areas
    fill(255,16,16);

    // draw mercury area:
    rect(posX,posY+(sizeY * mercury), 
    sizeX, sizeY-(sizeY * mercury));

    // draw stem area:
    rect(posX, posY+sizeY, sizeX,stemSize); 

    // draw red bulb:
    ellipse(posX+sizeX/2,posY+sizeY + stemSize, bulbSize,bulbSize); 

    // show text
    textAlign(LEFT);
    fill(0);
    textSize(10);

    // show sensor address:
    text(address, posX-10, posY + sizeY + bulbSize + stemSize + 4, 65, 40);

    // show maximum temperature: 
    temp_f = maxTemp * 9/5 + 32;
    text(temp_f + "˚F", posX+sizeX + 5, posY); 
    text(" " + maxTemp + "˚C", posX+sizeX + 5, posY + 10); 

    // show minimum temperature:
    temp_f = minTemp * 9/5 + 32;
    text(" " +temp_f + "˚F", posX+sizeX + 5, posY + sizeY);
    text(minTemp + "˚C", posX+sizeX + 5, posY + sizeY + 10);
    
    // Conver the temp to F before display
    temp_f = temp * 9/5 + 32;

    // show temperature:
    text(round(temp_f) + "˚F", posX+2,posY+(sizeY * mercury+ 14));
    text(round(temp)   + "˚C", posX+2,posY+(sizeY * mercury+ 24));
  }
}

// used only if getSimulatedData is uncommented in draw loop
//
SensorData getSimulatedData() {
  SensorData data = new SensorData();
  int value = int(random(650,670));
  String address = "00:13:A2:00:12:34:AB:C" + str( round(random(0,2)) );
  data.value = value;
  data.address = address;
  data.numericAddr = unhex(data.address.replaceAll(":", ""));
  delay(200);
  return data;
}

// queries the XBee for incoming I/O data frames 
// and parses them into a data object
SensorData getData() {

  SensorData data = new SensorData();
  int value = -1;      // returns an impossible value if there's an error
  String address = ""; // returns a null value if there's an error

  try {
    // we wait here until a packet is received.
    XBeeResponse response = xbee.getResponse();
    // uncomment next line for additional debugging information
    //println("Received response " + response.toString()); 

    // check that this frame is a valid I/O sample, then parse it as such
    if (response.getApiId() == ApiId.ZNET_IO_SAMPLE_RESPONSE 
      && !response.isError()) {
      ZNetRxIoSampleResponse ioSample = 
        (ZNetRxIoSampleResponse)(XBeeResponse) response;

      // get the sender's 64-bit address
      int[] addressArray = ioSample.getRemoteAddress64().getAddress();
      // parse the address int array into a formatted string
      String[] hexAddress = new String[addressArray.length];
      for (int i=0; i<addressArray.length;i++) {
        // format each address byte with leading zeros:
        hexAddress[i] = String.format("%02x", addressArray[i]);
      }
      // join the array together for a numeric address:
      long numericAddress = unhex(join(hexAddress,""));
      data.numericAddr = numericAddress;
      print("numeric address: " + numericAddress);
      // join the array together with colons for readability:
      String senderAddress = join(hexAddress, ":"); 
      print("  sender address: " + senderAddress);
      data.address = senderAddress;
      // get the value of the first input pin
      value = ioSample.getAnalog0();
      print("  analog value: " + value ); 
      data.value = value;
    }
    else if (!response.isError()) {
      println("Got error in data frame");
    }
    else {
      println("Got non-i/o data frame");
    }
  }
  catch (XBeeException e) {
    println("Error receiving response: " + e);
  }
  return data; // sends the data back to the calling function
}

This Processing sketch will automatically create a thermometer when a new XBee address is found. It will then automatically create a device channel and begin uploading the last data sample it got from the Xbee device once a minute.

Some advice:
a) The XBee nodes are based on the Chapter 5 thermometer TMP36 remote sensor nodes.
b) The Processing sketch can be tested without hardware to verify that it uploads to Xively successfully. To do this comment in the “data = getSimulatedData();” line in the sketch. It will create three fake thermometers and fill them with random test data.
c) Be careful when restarting the Processing sketch. It will upload to channel one, two, three etc based on which XBee address appears first. So turn off the XBee’s before restarting the Processing sketch and power them on in the order you want them to appear on the website. First XBee sample found will thereafter be uploaded to channel one, second on channel two, etc. If your not careful, this can mess up your channel data.

Some issues:
i) I don’t know if I trust the temperature sample data coming out of the XBee’s. Looking at my Xively webpage and comparing the data provided to my other test devices, I can see that the room temperature given is warmer than it actually is in the room. Reads high 70’s when my weather station temperature reads low 70’s. The fridge temperature should be higher than zero because I don’t find any frozen water or juice when I pull them out of the fridge. And the freezer seems about 10 or so degree’s colder than I expect it to be. I don’t know what’s the issue with these readings. I’ll have to investigate that.
ii) The Processing sketch has died on me in two different ways.
1) The sketch kept running and uploading the last data sample to Xively but the console read “Unable to read start byte”. This tells me I need to update the text processing in the sketch to be more robust.
2) The sketch will stop processing sample data. I believe this is an issue with my USB drivers which I will have to look into.
iii) Be careful when restarting the Processing sketch. Sample data will be uploaded to Xively based on what XBee address appears first. This is something I will have to address in my future XBee software projects.

Last but not least, I really don’t need to use a Processing sketch to capture this sample data. If I have sample data appearing on a website, I won’t need to look at the thermometer graphs. I should be using the Connect port to push this data to Xively.

And thats a wrap! Chapter 8 “More to Love” was the last chapter in the “Building Wireless Sensor Networks” book. I have to say over the last two months where I worked through the projects that it has been a learning experience. Hope you enjoyed these posts.

Posted in BWSN | 2 Comments

BWSN Twitter Reader Demo

Video covering “Chapter 7 – Over the Borders” featuring a twitter reader and a mailbox web application:

The XIG Internet Gateway software is a very powerful tool.  With the help of the ConnectPort x2 it bridges the gap between the XBee nodes and the wider internet.  This allows items on the XBee network to upload data (using GET) and fetch from the internet.  Robert Faludi includes API info, arduino sketch and PHP examples on his website here.

Some comments on this project:

  • The twitter reader code has been updated from the book and the latest version (v1.06 seen in the video above) is available on the author’s website here.
  • The internet gateway software XIG python scripts loaded on the ConnectPort X2 can be downloaded from here.  I’m using the Ver1.5.1b19 beta software in the video demo.
  • The website demo I wrote uses two PHP files.  One is the main page where the user can submit a msg to be stored in the SQL database and another that the arduino fetches that pulls from the SQL database to be displayed on the LCD.
  • I didn’t find much information on how to connect the 10K trimpot but after some experimenting I realized that Pin 3 of the LCD should be attached to the middle pin and VCC to one outer pin and GND to the other outer pin.
Posted in BWSN | Leave a comment

BWSN Powerswitch Tail Demo

New video, this covers “Chapter 6 – Sleeping, Then Changing the World” with Powerswitch Tails:

This project was relatively easy. It built on the sensor boards constructed from “Chapter 5 – API and a Sensor Network”. The only change is to remove the temperature sensor and in its place put a NPN Transistor. I’m using the 2N3904 from SparkFun as provided in the BWSN Basic Kit.  This project uses the two Powerswitch Tail II’s provided in the BWSN Advanced Kit.  In the video above, I show the use of two PST2 and one PST1 which I had left over from another project.  The connections are the same.

Some helpful advice:

  • You can test your circuit without having to plug the PST into a wall socket.  If you have connected the NPN to the XBee correctly and used the Processing program provided, the light on the PST will light up.  The PST1  will also give an audible thunk as it engages the relay.
  • The PST2 will not engage the relay if it is not connected to power.  I.E. if it’s not connected to a lamp or other electrical appliance, it will not make a noise as it will not enable the relay.  BUT if under a load, it will engage the relay and make the noise.  Clear as mud?  Good.
  • The processing sketch used in this example can be downloaded from Robert Faludi’s BWSN site.  Download the “Simple_Actuator_Network.zip”
  • If you are using the latest Processing, the examples in the book won’t work exactly right. They changed the way the com ports get setup. Instead of setting the “mySerialPort” string, you have to choose the correct COM port from the “Serial.list()” array. See the code example below.
try {
// opens your serial port defined above, at 9600 baud
// ## (2013-Aug-27) Updated Processing, now have to
// ## select the serial port from the "serial.list" array.
// ## IE "serial.list()[X]" where X is the COM port
// ## in the array.
xbee.open(Serial.list()[2], 9600);
}
  • There aren’t many explanations for wire the hookup’s for the PST.  After looking at the schematic’s I connected Pin 1 “+in” to the 9v input of the battery and connected Pin 2  “-in” to the collector of the NPN transistor and left Pin 3 “Ground” floating.
Posted in BWSN | Leave a comment