Friday, July 5, 2013

Unboxing SmartMaker's Tinkerer and Starter Kits

I just received a package from SmartMaker today.

That took some time and unfortunate strong arming that this post will not focus on. I am not associated with smARtDUINO in any way. In fact I may be on their bad side for a while but enough of that. Instead I'll show that the modules work and what was in the package using some high-res pictures. I had been excited about a small open modular Arduino-type system for a long time but had given up, yet here it was on my door step.

Unboxing

The package contained one Starter Kit, one Tinkerer Kit, and a few more Breakout Boards and SmartPower units. It also had a yellow T-shirt and some stickers (thank you).

        


Hello LED

I quickly wanted to see if the modules actually worked.  The movie below shows the Arduino version of "hello, world" i.e. the Blink sketch modified to use LED#3 and not #13.  The setup is powered over USB and as programmed using the normal Arduino 1.5.2 IDE over a COM port.


High-Res Pictures of Modules

I was curious about the quality of the soldering since the pitch of the Hirose connector is quite small.  I was also wondering about the placement of the connectors for a long time so I thought I'd make it easier for anybody else wondering about female/male connectors and if they even included them on the backside of some modules.

The pictures below try to focus on the joints using a Sony NEX-5N and a 10x macro adapter to get even closer to the board.  One picture says more than a thousand words to here they are:

SmartCORE U

This module showed up as a normal Arduino Uno on a COM port after plugging it in.  I think it had a morse code message starting with the number '3' pre-programmed to blink LED13  but I could be wrong.






SmartCORE L

This is an Arduino Leonardo module.  I had to manually install drivers for it from the Arduino folders but thankfully it reported in with a proper name in the device manager.  It's curious that this CORE is only available as part of the StarterKit and not as a standalone module.  It may just be a glitch on the website.




SmartHOST Breakout

I ordered quite a few of these since they will connect to actual sensors and actuators in my projects.  Plus I can use them in pinch with the ARM Cortex-M3 CoAction Hero board that uses the same physical Hirose connector but unfortunately not the same signals.



SmartHOST for Arduino

Much like a normal Arduino board with power but allows you to swap out any SmartCORE as its brain.





SmartHOST Breadboard

Much like the SmartHOST fror Arduino but without the power connector so cheaper.



SmartBUS AB Riser

Simple spacer passing through all signals.



SmartBUS Basic Double

For building wider objects instead of stacking tall.  This one keeps the two AB connector pairs aligned while the SmartBUS Mirror rotates the connectors.  Basic meaning only AB and not AB+CD.



SmartBUS Basic Mirror

Much like SmartBUS basic Double but with the second AB pair rotated.



Final Words

Pretty excited about everything working and with some good looking manufacturing.  I'll definitely order some more modules when things cool down.  Until then I'll still head over to the project's KickStarter comment section, open a bag of popcorn, and keep reading the posts...  Although the official forum might be a better source of info, just not as entertaining.

Tuesday, May 21, 2013

Debugging an Xbee UART using a USB Logic Analyzer

I've been having trouble communicating with my Xbees last week and I thought the problem was bad connections.  In the end it was due to the Xbees configured as end-points and their sleep values set too aggressively.  Sleep settings are worthy of a whole blog entry by itself but this short page will focus on an easy way to debug both ASCII and binary XBee API calls.

USB Setup

The analyzer I used was a USBee-AX that plugs onto the USB port.  At first I thought the unit was defective but you only need two connections to debug the UART's TX/RX.  No need for GND or VCC connections:



Software Setup

The other missing piece was dialling in the baud rate correctly.  I run my XBees at 115200 and 2 stop bits for various reasons and the USBee-AX needed to be configured the same before data was intercepted by double clicking on the UART section for this dialog box:



The last piece was designating the TX line to be the trigger to start sampling.  You can see that in the final image as the rising edge next in the blue TX box.

Binary Output and Frame Decoding

I was very surprised to see actual binary bytes after designating line 6+7 as UART.  The section to the right shows the UART communication in-view and syncs such that it always shows the same data as the main window but in more readable form.




This data is actual serial communication at 155200 baud intercepted over a few milliseconds.  As you can
see both the 7E 08 AT commands show up along with their corresponding 7E 88 AT response.

Decoded by the Digi API frame maker we can see this is in the middle of asking for the whole Xbee state and this is the ATNT command/response.  Compare the Packet bytes below with the blue bytes above.




A great tool to debug protocol over physical wires and makes hardware tinkering more debuggable.  The setup showed me right away that there was nothing wrong with my serial transmission which led me down the road to find out the module was just sleeping.

Tuesday, May 7, 2013

Cheap Pyroelectric Infrared PIR Motion Sensor on 3.3v

My current project is focusing on a pure 3.3v setup, both MPU and sensors.  I've been experimenting with various cheap sensors from both SparkFun and eBay sellers from China to fill the various sensor "slots" my final module should have.

One of them is Motion Sensing.

The PIR Motion Sensor from SparkFun looked good at first but I was concerned with the problems it seemed to have running at 3.3v.



All the other PIR Sensors on eBay seemed to have the same setup with some onboard voltage regulator.  1.7v Voltage Dropout on these regulators prevent an already regulated 3.3v source from powering it out-of-the-box.  Or so I thought...

The even more expensive sensor from Parallax looked fine but at $11 it was going to add up with a lot of my sensors.  I felt a little more comfortable tinkering with a cheap sensor from China than the others so I ordered two sensors from two different eBay merchants at around $3.


Unreliable at 3.3v

Hooking these sensors up to my Programmable XBee with a did not go as well as I had hoped.  The sensor simply didn't work with a 3.3v VCC source just like the SparkFun sensor.  The signal was wildly erratic as if someone was moving randomly in front of the sensor:

#3064 TMP102=22.19 Door=CLOSED Motion=NO
#3068 TMP102=22.19 Door=CLOSED Motion=NO
ALARM: Motion
#3072 TMP102=22.19 Door=CLOSED Motion=NO
#3076 TMP102=22.19 Door=CLOSED Motion=YES
ALARM: Motion
#3080 TMP102=22.19 Door=CLOSED Motion=NO
ALARM: Motion
#3084 TMP102=22.25 Door=CLOSED Motion=YES
#3088 TMP102=22.25 Door=CLOSED Motion=YES
ALARM: Motion
#3092 TMP102=22.25 Door=CLOSED Motion=YES
#3096 TMP102=22.19 Door=CLOSED Motion=YES

Reliable but useless at 5v

Connecting it to a 5v source fixed the problem just like others:

#3872 TMP102=22.19 Door=CLOSED Motion=NO
#3876 TMP102=22.19 Door=CLOSED Motion=NO
#3880 TMP102=22.19 Door=CLOSED Motion=NO
ALARM: Motion
#3884 TMP102=22.19 Door=CLOSED Motion=YES
#3888 TMP102=22.19 Door=CLOSED Motion=NO
#3892 TMP102=22.19 Door=CLOSED Motion=NO
#3896 TMP102=22.19 Door=CLOSED Motion=NO
#3900 TMP102=22.19 Door=CLOSED Motion=NO
#3904 TMP102=22.25 Door=CLOSED Motion=NO

However this makes it a borderline unusable sensor since I won't have 5v on my final module.  Fortunately I stumbled on an interesting hack that most likely will work fine at 3.3v permanently.

Knowing enough to cause damage

I'm actually just getting back to hardware tinkering after a 15 year hiatus doing software.  This reminds me of learning how to code by just messing with source and seeing what happens.

After probing the voltage regulator I confirmed that the sensor had a 7133-1 regulator which does have a 1.7v Voltage Dropout.  That's sad since I was hoping to be lucky with something closer to Parallax's design that can take input down to about 3v.


Probing around with the multimeter I confirmed the 5v in and 3.3v out on the 7133 regulator.  I also found a pure 3.3v at the lower right capacity's outer leg which rings right with what I just read about voltage regulators and noise in SparkFun's Beginning Embedded Electronics.  It looked like that capacitor would be an easier point to inject my already clean 3.3v power into the sensor than shorting out the regulator.

Easier 3.3v access?

Looking at the backside of the circuit board I could see a small trace from the newly discovered 3.3v capacitor's positive pin crossing over to... the H-pin?  After another attempt at tracking down a schematic I found something similar over at openimpulse.com.

Their schematic looked showed the sensor's 3-pin was connected directly to V-out from the regulator and the whole rest of the 3.3v trunk!  Its main purpose is to bring the BISS0001's A-line either high or low but let's use it as a 3.3v VCC instead.


Final 3.3v Hack and No Damage

Probing the three pins I found one of them being exactly 3.3v.  After moving over the gray cable over from a 5v to a 3.3v source, I plugged the other end into pin-3.  The sensor worked perfectly and reliably, just as when it was powered by 5v!

3.3v motion detecting PIR sensor done without any soldering.



Sunday, May 5, 2013

Remote Temperature Sensor using 434MHz RF Link and Arduinos

As another quick experiment to after my ElectricImp project, I decided to go the full opposite of the Imp's highlevel programming and automatic WiFi connectivity and use a low-tech 434MHz RF transmitter/receiver pair powered by Arduinos.

Hardware

The ElectricImp's WiFi connection and programming is wonderfully simple but price, power requirements, and its closed source aspect made me not invest more time here.  Instead I tried an old-school RF pair to transmit Temperature data between two Arduinos.

Transmitter

Since I'd like to keep using 3.3v sensors such as the TMP102, I got a low power 3.3v 8MHz Arduino Mini Pro to read the sensor and transmit the data to the RF Link Transmitter.  This way I don't have to translate the signals between 5v and 3.3v as i would have had to do with a regular 5v Arduino.  The soldering was a quick and dirty job where I connected the power and I2C link directly to the Arduino:



As you can see above I simply hardwired a signal line from the Arduino over to the RF transmitter using a white cable.  The connection to the TMP102 sensor is done over I2C using A4/A5 with connectors protruding from the back of the Arduino and looping back over the the sensor.

The main focus is the transmitter since the receiver will most likely be a single AC powered device.  Therefore I dug out my old Uno and a ProtoShield to hack together the receiver side.  I really just wanted to print the information on the screen but I also had to experiment with some error checking code in the end.  RF transmissions are NOT reliable as I found out.

Receiver

The final receiver unit ended up using not much more than the Uno, a ProtoShield, and an RF Link Receiver:


The code uses the VirtualWire Arduino library and was amazingly simple to use and setup.  With no antenna to speak of, I ended up with about a 100ft range which is not bad since I was feeding the transmitter a paltry 3.3v.  The RF Link specsheet says a range of 1.5 to 12v so I was planning to do some range experimentation, figuring out how supply voltage would affect range but ended up moving on to the next project that uses XBee radios instead.

Software

The code below is for both the receiver and transmitter with a simple #ifdef statements redirecting the Arduino compiler to build each sketch.  The LED usage made it easy to debug and do some manual range checking by just watching for blinks every second a GOOD reading was received.  Removing the checksum code allows you to see the corrupted messages as distance and interference increased.

Fun little project but I won't be going in this direction since I don't want to deal with cross talk interference with  10+ sensor nodes and the re-transmission protocols required.  I was also not happy with having to add an Arduino Pro Mini to each node even at $10 per node although eBay sells them for $6 now which is getting very tempting...


#include <Wire.h>
#include <VirtualWire.h>

static int tmp102Address = 0x48;
static byte kID = 0;
byte gCounter = 0;


void encode(byte ioBuffer[8], byte inTemp1, byte inTemp2)
{
  ioBuffer[0] = 't';
  ioBuffer[1] = 'e';
  ioBuffer[2] = 'm';
  ioBuffer[3] = 'p';
  ioBuffer[4] = gCounter++;
  ioBuffer[5] = kID;;
  ioBuffer[6] = inTemp1;
  ioBuffer[7] = inTemp2;
}

bool decode(byte ioBuffer[8], byte outTemp[2])
{
  Serial.print((char)ioBuffer[0]);
  Serial.print((char)ioBuffer[1]);
  Serial.print((char)ioBuffer[2]);
  Serial.print((char)ioBuffer[3]);

  Serial.print(" #");
  Serial.print((int)ioBuffer[4]);

  Serial.print(" id-");
  Serial.print((int)ioBuffer[5]);

  Serial.print(" [");
  Serial.print((int)ioBuffer[6]);
  Serial.print(',');
  Serial.print((int)ioBuffer[7]);
  Serial.print("] ");

  outTemp[0] = ioBuffer[6];
  outTemp[1] = ioBuffer[7];

  return ioBuffer[0] == 't' && ioBuffer[1] == 'e' && ioBuffer[2] == 'm' && ioBuffer[3] == 'p';
}

#define transmitter

#ifdef transmitter
void setup()
{
  Serial.begin(9600);
  Serial.println("Transmitter");
  Wire.begin();

  // Initialise the IO and ISR
  vw_set_ptt_inverted(true); // Required for DR3100
  vw_setup(2000); // Bits per sec
  vw_set_tx_pin(3);
}

void loop()
{
  byte message[8];

  Wire.requestFrom(tmp102Address, 2);  
  encode(message, Wire.read(), Wire.read());

  digitalWrite(13, true); // Flash a light to show transmitting
  vw_send(message, 8);
  vw_wait_tx(); // Wait until the whole message is gone
  digitalWrite(13, false);
  Serial.println(gCounter);

  delay(1000); // Send a temperature sample every second
}

#else // receiver
void setup()
{
  Serial.begin(9600);
  Serial.println("Receiver");

  // Initialize the IO and ISR
  vw_set_ptt_inverted(true); 
  vw_set_rx_pin(3);
  vw_setup(2000);  // Bits per sec

  vw_rx_start();       // Start the receiver PLL running
}

void loop()
{
  uint8_t buf[VW_MAX_MESSAGE_LEN];
  uint8_t buflen = VW_MAX_MESSAGE_LEN;

  if (vw_get_message(buf, &buflen)) // Non-blocking
  {
    digitalWrite(13, true); // Flash a light to show received good message

    byte id;
    byte counter;
    byte temp[2];
    decode(buf, temp);
   
    // 12bit int so using two's compliment for negative
    int TemperatureSum = ((temp[0] << 8) | temp[1]) >> 4;
    float celsius = TemperatureSum * 0.0625;
    Serial.print(celsius);
    Serial.print("C ");
    Serial.print(celsius * 9 / 5 + 32);
    Serial.println("F");
     
    delay(100);
    digitalWrite(13, false);
  }
}
#endif


Sunday, April 14, 2013

Temperature Graph using Electric Imp and TMP102 over I2C

Hey I have a blog I forgot about...

Why another temperature monitor?

My main purpose was to just get started with creating wireless embedded low-power devices.  I hadn't used a soldering iron in over a decade and I needed something easy and fun.

So let's show my boss that my brain overheats at over 75 degrees Fahrenheit.

I quickly needed a way to track temperature.  Ideally the device should be wireless and low power to liberate myself from the desktop.  I had bought an Arduino Uno R3 a while ago but I didn't like that it needed a serial connection.  So I decided to try the Electric Imp even though it's a closed system.  

The prototype uses a TMP102 temperature sensor since I wanted a cheap high resolution sensor on a breakout board.  I also wanted to learn I2C since the digital bus design is very appealing for future devices with many sensors.  Spark Fun Electronics here in Boulder Colorado has some wonderful things that got me started.

Hardware

The wiring ending up very simple, with the sensor intentionally wired up almost directly to the Imp Breakout board.  You could potentially solder them onto each other but I'd like to save the Impee for future quick work.


The line-up between the Imp and the TMP102 worked out because the way I soldered the pins.  As you can see in the code below I configured pin 1+2 to be the I2C connection.

TMP102: SCL and SDA?

However, the I2C connection has a clock (SCL) and data (SDA) and I had to head over to a forum to learn that SCL is pin1 and SDA is pin 2.  That should be easy info on the Imp documentation wiki.  The next pin over is pin 5 which lines up with VCC on the TMP102.  They are both 3.3v ICs and I hoped that the Imp could drive a low-power sensor.  I was right but I really should check the amp requirements.

TMP102: ADD0

I thought I could leave the ADD0 pin on the TMP102 alone but it does need to be grounded.  TMP102 allows two sensors on the I2C bus and grounding it is the way to lock it to the lower address 0x48.

Blinking LED

The project had to have a blinking LED.  All projects do...  This one was my debugging tool.  The black bar you can see is the 330 resistor bank since... it looks nicer than a resistor...  The wires make the LED connected to pin 7 and the code blinks the LED every time it takes a temperature reading.

Software

Electric Imp is a strange beast.  The SD card form factor makes you think you can program it using a computer with and SD reader.  You can't.  It won't hurt it inserting into an SD reader but it won't even power up.  Instead you need a breakout board that supply power and an ID chip that uniquely identifies your Impee.

The Imp is connected to the internet over WiFi.  This is also how you program it. Yep.  No sketches or uploading over USB.  You program on their webpage and upload to the Imp.  It's strange programming with the Imp next to you, even "connected" with USB but just for power

When you hit "Run Code" it actually uploads the new code over the web back to your Imp over your home WiFi.  Debugging is the same strange thing.  I see serial output on the Web page but those strings are actually transmitted over the web by the Imp and then BACK to my computer.  That's a lot of travelling for embedded debugging.

Imp: Planner

The main screen allows you to see all your Imps and visually associate debug input and outputs using dragging of connectors.  The screen below is the currently running temperature monitor:


The blue box represents the Imp along with its current show message using:
server.show(format("%3.1f%c (%dv)", temperature, unit, volt));

The green boxes are output that allow easy display of output values or just counting the number of updates the Imp has provided.  It's a push architecture displayed above.  The "Cosm 200" green boxes will be dealt with at the end. They are the bridges to graphing the temperature.

Imp: Code

Programming is done by clicking the edit link in the blue box which brings us to the "code" tab:


The Log tab is showing output in real-time when you use server.log() such as:
server.log(format("[%d,%d] %d %dv", degrees, data[1], steps, volt));

TMP102: Negative temperature

The only tricky part was reading negative temperatures correctly.  The imp sat in my freezer for an hour at least...  I'm serious.

The TMP102 returns temperature as two bytes.  The first byte is the Two's Complement of the temperature in Celsius  This byte is probably enough for most people but it required a little tinkering to compute the rest of the temperature without my full C++ toolbox.  I'm sure there is a better way of doing it in the Imp's Squirrel language but I ran out of time and it works.

TMP102: 12 bits of temperature?

The sensor is rated for 0.5°C accuracy and the second byte carries this extra data.  The sensor actually returns 12-bit aka 0.0625°C resolution but doesn't promise that accuracy.  However looking at page 4 on the full TMP102 spec sheet it shows the following graph:


This means most of the data at room temperature is MUCH more accurate than 0.5°C.  It looks like most readings are +- 0.05°C and many are probably even more accurate.

BTW, The TMP102 has a lot of cool capabilities such as continuous temperature reading, sleep modes, high and low thresholds and more.

Graphs

The purpose was to show management that development was overheating so we needed fancy graphs and historical records.  Fortunately Cosm is a great resource for this and Electric Imp has a direct bridge over to Cosm.


Connecting out Imp temperature data feed over to Cosm is simply a matter of adding a Cosm node and configuring it with the correct Cosm API key and feed number.  I did add two feeds from the Imp for fun and practice over at https://cosm.com/feeds/123369


Fun project and management is already working on installing blinds and fixing the AC system, three days after the graph became visible.  let me know if there are any correction needed above.

Next project will be a cheaper version of wireless temperature using Arduino and a 434Mhz transmitter.



Code for the Imp below:

/** Temperature monitor using TMP102 chip over I2C */
// Temperature Sensor Class for TMP102
class TemperatureSensor
{
    i2cPort = null;
    i2cAddress = null;
    constructor(port, add0)
    {
        if (port == I2C_12)
        {
            // Configure I2C bus on pins 1 & 2
            hardware.configure(I2C_12);
            i2cPort = hardware.i2c12;
        }
        else if (port == I2C_89)
        {
            // Configure I2C bus on pins 8 & 9
            hardware.configure(I2C_89);
            i2cPort = hardware.i2c89;
        }
        else
        {
            server.log("Invalid I2C port specified.");
        }
        i2cPort.configure(CLOCK_SPEED_100_KHZ);
        i2cAddress = (add0 ? 0x49 : 0x48) << 1;
        server.log(format("i2cAddress=%x", i2cAddress));
        // Start continuous conversion
        i2cPort.write(i2cAddress, "");
        i2cPort.write(i2cAddress, "0");
        imp.sleep(0.05);
    }
    // Retrieve temperature (from local sensor) in deg F
    function getTemperature(unit)
    {
        local data = i2cPort.read(i2cAddress, "\x00", 2);
        if (data == null)
        {
            server.show("Error reading TMP102");
            return null;
        }

        // Remove two's complement if negative temperature
        local degrees = data[0];
        if (degrees & 0x80)
            degrees = -((degrees - 1) ^ 0xFF);
            
        // Calculate no of steps. Each step is 0.0625 degrees centigrades
        local steps = degrees * 16 + (data[1] >> 4);
        
        local temperature = steps * 0.0625;
        if (unit == 'F')
            temperature = temperature * 9 / 5 + 32;
        
        local volt = hardware.voltage();
        server.log(format("[%d,%d] %d %dv", degrees, data[1], steps, volt));
        server.show(format("%3.1f%c (%dv)", temperature, unit, volt));
        return temperature;
    }
}

// Instantiate the sensor
local sensor = TemperatureSensor(I2C_12, false);
// Output port to send temperature readings
local output = OutputPort("Temperature", "number");
local iq = OutputPort("IQ", "number");
local power = OutputPort("volt", "number");

// Temperature unit
local unit = 'F';
// Capture and log a temperature reading every 5s
function capture()
{
     // Blink LED
    hardware.pin7.configure(DIGITAL_OUT);
    hardware.pin7.write(1);
    imp.sleep(0.1);
    hardware.pin7.write(0);
    
    // Set timer for the next capture
    imp.wakeup(60.0, capture);
    // Output the temperature in F
    local temp = sensor.getTemperature(unit);
    if (temp != null)
    {
        output.set(math.floor(temp*10.0)/10.0);
        iq.set(math.floor(100.0 + 20.0 * math.atan(40.0-temp/2.0)));
        power.set(hardware.voltage());
    }
}
// Register with the server
imp.configure(format("Temperature Logger (%c)", unit), [], [output,iq,power]);


// Configure and turn on temperature chip
hardware.pin5.configure(DIGITAL_OUT);
hardware.pin5.write(1);

// Start capturing temperature
capture();
// End of code.