August 11, 2011

Family reunion: JeeNode and JeeLink get to talk

So as I said before leaving for vacation, I did receive the jeeLink and JeeNode from ModernDervice. It took a good half hour to solder the jeeNode together.

First Impressions
Hardware:
  The jeeNode PCB has lots of really good little things showing that jcw has an unusual attention to detail. The shape profile of the components is actually printed on the PCB to help position those that are polarized in the correct way. I also dreaded soldering the RF12 and it all went very smoothly, so don't get to worked up like I did, it's a piece of cake. The instructions on the jeelabs site to assemble the jeenode are good but I didn't like the order in which it tells you to solder the components. It should be from lowest to highest profile so can push the components down as much as you can against the PCB. The instructions do say that but then one of the capacitors from modern device actually had a higher profile than the port connectors which made it a little tricky to solder the ports correctly so be warned: the cap should go last.

Software:
  Being Arduino, I went straight to download the Arduino IDE. As much as I hate eclipse, I must say that they sure made it simple and straightforward for Arduino first time users! Once you have the IDE running, simply select the COM port your hardware is on and its model and you're in business! Sweet!
OK, not quite, you still need to get the libraries. So, for the JeeNode, you will need 2 core libraries, the rf12 and the ports libraries. You can get them there:
svn://svn.jeelabs.org/jeelabs/trunk/libraries/Ports
svn://svn.jeelabs.org/jeelabs/trunk/libraries/RF12

Do check them both out in the arduino "libraries" folder. That is IT!
Having never ever dealt with anything Arduino, I did not know anything about it and certainly did not know what to expect but I somewhat had an expectation of greater complexity.

Making it work: Hello World?
Though I sometimes like the obligatory hello world tutorial, it usually doesn't actually DO anything, which makes it kind of moot unless the environment itself is what you need to get used to. In this case, I think something a little meatier was in order so, since I had a DS18B20 on hand, I decided the better example would actually be to have the jeeNode send the temperature readings from that sensor to the jeeLink attached to my laptop. Maybe later I can make something useful with those wireless readings but at the moment, the intent is mostly to check that a) I did all the soldering right and b) I can wrap my head around the jeeLabs and Arduino goodness.

Libraries:
  I did need help from Google to figure it out but basically, you can find libraries to make your life easier for a lot of common components. That indeed include the Dallas 18B20 I was planning to use. It's a 1-wire component and guess what, there's a OneWire library. And lo and behold, there is even a DallasTemperature library that thinly wraps around the one wire to provide convenience functions around the temperature sensor.

Setting it all up:
 First I had to set the jeeLink up, that means I simply had to give it a node number. You do that by opening a terminal to your jeeLink COM port and simply type '1n'. This set my jeeLink as node 1.
Pretty simple eh? That's because the jeeLink comes loaded with a sketch called rf12demo and it allows for this dynamic configuration.

First test:
 ok so now the jeelink is listening, I will try to load a sketch on to the jeenode and have the jeenode send the temperature readings. The DS18B20 is plugged on to port 4 on the jeeNode but there is a little trick: Port on the jeeNode is like port 3 on the arduino, consequently, when we code to the jeenode, since we do it from an arduino software perspective, our port 4 will really be port 7 in the arduino lingo. Unless you know this, it actually is weird, once you do, well, whatever. So, here's a sketch that sends the temperature:

#include
#include
#include
#include

// Data wire is plugged into port 4 on the JeeNode, since port
// 1 of the jeeNode is really port 3 on the arduino, port 4 on
// jeeNode is port 7 in arduino lingo
#define ONE_WIRE_BUS 7

// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire ds18b20 (7);
OneWire oneWire(ds18b20);
char payload[10];
float temperature;

// Pass our oneWire reference to Dallas Temperature. 
DallasTemperature sensors(&oneWire);

void setup(void)
{
  // start serial port
  Serial.begin(57600);
  Serial.println("Remote Temperature Sensor v0.1a Starting...");

  // Start up the library
  sensors.begin();
  rf12_initialize(2,RF12_915MHZ,212);
}

void loop(void)
  // call sensors.requestTemperatures() to issue a global temperature 
  // request to all devices on the bus
  rf12_recvDone();  
  sensors.requestTemperatures(); // Send the command to get temperatures
  temperature = sensors.getTempCByIndex(0);
  Serial.print("Temperature: ");
  Serial.print(temperature);
  Serial.println(" C");
  sprintf(payload,"%d", int(temperature));
  Serial.print("Sending temperature: ");
  Serial.println(payload);
  if ( trySending(payload)){
    Serial.println("Succesfully sent.");
  } else {
    Serial.println("Sending failed 3 times in a row");
  }
  delay(10000);
}

boolean trySending(char message[]){
  boolean result = false;
  if (rf12_canSend()){
    rf12_sendStart(1,message,sizeof message);
    result=true;
  }  
  return result;
}

And guess what, we do get the temperature on the jeeLink: yeeehaaaw

Oh no!
 the problem with this sketch is that if rf12_canSend() returns false (which it does every now and then) then nothing gets sent until the next loop, meaning we can lose readings

Second Try
 the solution I found, at least for now, is to implement a retry mechanism like so:

boolean trySendingHarder(char message[], int retries){
  boolean result = false;
  int i = 0;
  while ((i++
    delay(50);
  }
  if ( i < retries ){
    result=true;
  }
  return result;
}

All I have to change now is the call to trySending(payload) to trySendingHarder(payload,3) and it will do the retry 3 times. It has now been running 24 hours and hasn't missed a beat!

I hope this will help someone out there getting started with jeestuff.

August 10, 2011

Sync speed ... part 1

I've been surprised a number of times now with the expectation from people we introduced to our Sync technology. Let's jog back up a bit.


UnboundID offers a synchronization technology that has the particularity of doing near-real-time synchronization of two end-points, A and B. It does it by building an "object" from data gathered at both end points, comparing the two objects and applying the minimum changes to the destination so that the destination matches the source. The way we do bi-directional sync is to set up one pipe from A to B, and one pipe from B to A, taking care of ignoring changes applied by the synchronization engine itself to avoid infinite loops.


When we offer this to solve some tough business problems, we're often asked about the performance of Sync. Will it be as fast as my current ?
Most likely? Yes. I just wrote a couple of mock end-points simulating "ideal" end points to see how fast the sync engine is at processing the changes. I don't have hard numbers to share mainly because I tested on my laptop and I still need to iron out some of the wrinkles in my code to make it nicer but I just want to point out that:

  1. the sync core is really efficient. It could probably be improved slightly here and there but as it stands, it's pretty lean already.
  2. in the unlikely event that you have some mythical database outpacing Sync, we could scale out by using Sync on multiple machines, each sync managing its own subset of the data.
  3. More than likely, either or both your end-points are the issue.
The extensions are running inside Sync so it also nulls out the network latency. In a later version, I plan to add the ability to simulate network latency too in order to better determine the impact of the network on the system as a whole.
Stay tuned...