uCurrent (from EEVblog) current upgrade

April 4th, 2013

2013-04-04 18.11.33I  have been having a lot of issues as of late using my HP 34401A DMM to measure current.  The DMM measures current by passing the current through a resistor to rectify the current into a voltage based on the relationship V=IR.  It then measures the voltage across the resistor to determine the current.  I used a secondary DMM to measure the resistance to 5.5Ohms

This is quite typical.  However, the size of the resistor is somewhat large (5.5Ohms), and causes a drop in voltage across that resistor (also based on V=IR).  The more current you measure, the larger the drop in voltage.  A 1A current will cause a 5.5V drop!

As my WiFi module was powering up, it would require a larger draw of current due to large inrush, this would cause a sudden spike in current which would cause the a drop in voltage across the current sense resistor which would cause things to break.  Took me a full day to figure out that this was the culprit to my problems.  Very annoying. 

So I ordered a precision current measurement device by the EEVblog author (http://www.adafruit.com/products/882) which works in the exact same way as my DMM, but it passes the current through a much smaller resistor (in the mA setting, it passes the current through a 0.01 Ohm .5% resistor – R1 in http://alternatezone.com/electronics/ucurrent/uCurrent%20Schematic.png).  Thus, for a 1A current, we expect only a voltage drop of .01 * 1 = 10mV!  Much better. 

2013-04-04 15.51.14However, I want to measure at least up to 1A, and the documentation states it only works up to 300mA.  If you look at the circuit, it sets up a virtual ground at 1.5V (given a 3V supply), take the voltage difference across the current sense resistor and amplifies it 100x using U1.  Thus a 1A current should result in 10mV * 100 = 1V.  This should easily be within the output capability of U1.  So I posted to the authors forum, and asked.  It seems the 300mA limit is because of the switch SW1’s limit.  Doh.  So I added some solder blobs to force it into mA mode and capable of supporting much higher currents (see photo – 2 solder blobs directly below the LED (D1). 

So it works fine, but I am getting an unusual amount of noise out of the system given the precision components and the quality opamp.  In looking at the circuit, I would wager that it’s from R2.  It is always in there, parallel with either R8 or R1.  It’s so much larger than R1 or R8, that it doesn’t really alter the measurement, however, it does add Johnson noise  which is amplified as well.  The amplifier has a GBW of 6.5Mhz, and no additional filtering is provided, so we can approximate the bandwidth as 6.5Mhz/100=65kHz (not exactly, but close enough).  We can use this to calculate the noise from R2 to be 3.2uV (from http://www.sengpielaudio.com/calculator-noise.htm) * 100 = 320uV noise.  At 1mA/mV (the output of the device), that’s equal to 320uA of background noise.  I’ll take out the resistor at some point to see how it improves the signal, but it’s a bit annoying that it’s there.  He could have easily hooked R2 to the 1st terminal of SW1 to avoid this source of error..

image

Electronics

How to handle JSON data using the electric imp.

January 7th, 2013

I’ve had more requests for examples of accessing JSON data using an electric imp.  I use it to collect weather information from weather underground. Here’s some skeleton code to highlight what you need..

 

local astronomy = OutputPort("Astronomy","number");
function getAstronomyData() {
    astronomy.set(1); //initiates outbound connection to retreive astronomy data
}

function dumptable(p, t) {
    foreach(key, value in t) {
        if (typeof value == "table") {
            dumptable(p+"."+key, value);
        }
        else server.log(p+"."+key + " = " + value);
    }
}

//this class receives the json data
class Astronomy extends InputPort {
    function set(payload) {
        //to figure out json structure uncomment the following and check the log output
        //dumptable("",payload);
       
        //all the data is considered a string, so convert to integer or whatever as necessary 
        local variable = payload.moon_phase.sunset.hour.tointeger(); 
        doSomethingWith(variable);
       
        //schedule another update in 1 minute
        imp.wakeup(60, getAstronomyData);
    }
}

function boot() {
    //invoke a call to get the astronomy data here
    getAstronomyData(); // or use imp.wakeup() to specify a time to invoke
}

imp.configure("Outdoor Automation", [Astronomy("astronomy","string") ], [astronomy]);

 

In the planner, setup an HTTP request which sends the request in the form of a GET request specifying the url (which, in the case of weather underground, includes the api key).  Set the content type to json.

 

image

 

Connected an arrow from your application to the HTTP request and one from the HTTP request back to the application.

 

The way it works is that when you write to the HTTP request, the URL is called.  When data is returned, it will invoke Astronomy.set() (defined in imp.configure(), which you need to provide) which then parses the data. 

A dumptable function is provided in order to help you figure out the structure of the json data the first time to know how to extract it.

Hope this helps.

Electronics

Electric Imp & SHTxx sensors

December 17th, 2012

There have been a couple people requesting the code to drive an SHT temp/humidity sensor from an electric imp, so I’ll post it below.  No warrantee implied..  Also, it’s ugly as someone else wrote it for some other microprocessor and I just tweaked it; I would never write such aesthetically displeasing code.    Obviously, I’m big banging pins 8 and 9; adjust to suite your needs.  Don’t forget the pullup resistor on one of those lines.  This is also written for the SHT71, tweak for whichever unit you are using.

 

class SHT {
       
    function delay_us(x) {imp.sleep(0.000001 * x);}

     noACK =0;
     ACK=1;
                                //adr  command  r/w
     STATUS_REG_W =0×06;   //000   0011    0
     STATUS_REG_R =0×07;   //000   0011    1
     MEASURE_TEMP =0×03;   //000   0001    1
     MEASURE_HUMI =0×05;   //000   0010    1
     RESET        =0x1e;   //000   1111    0
    
    data_output = true;
   
    function constructor() {
        hardware.pin8.configure(DIGITAL_OUT);
        hardware.pin9.configure(DIGITAL_OUT);
        s_softreset( );
    }
   
   
   
    function sck_set(x) {
        hardware.pin8.write(x);
       
    }
    function data_set(x) {
        if (!data_output) {
            hardware.pin9.configure(DIGITAL_OUT); 
            data_output = true;
        }
        hardware.pin9.write(x);
       
    }
   
    function data_get() {
        if (data_output) {
            hardware.pin9.configure(DIGITAL_IN);
            data_output = false;
            }
        return hardware.pin9.read();
    }
   
   
    function SCK( val) {
        if (val) {
            sck_set(1);
        } else {
            sck_set(0);
        }
    }
   
    function DATA( val) {
        if (val) {
            //input w/ pullup resistor
            data_get();
        } else  {
            //output – gnd
            data_set(0);
        }
    }           
   
   
    function sht_init() {
        s_write_statusreg(0, 0×00); //8/12 bit resolution
    }
   
   
       
   
   
    //———————————————————————————-
    function s_write_byte( value) {
    //———————————————————————————-
    // writes a byte on the Sensibus and checks the acknowledge
      local error=0; 
   
      for (local i=0×80; i>0; i=i/2)             //shift bit for masking
      {
          if (i & value) DATA( 1);          //masking value with i , write to SENSI-BUS
          else DATA(0);                       
            delay_us(5);
          SCK( 1);                          //clk for SENSI-BUS
          delay_us(5);        //pulswith approx. 5 us     
          SCK( 0);
      }
      delay_us(5);
      DATA( 1);                           //release DATA-line
      SCK( 1);                            //clk #9 for ack
    
      error=data_get();                       //check ack (DATA will be pulled down by SHT11)
      SCK( 0);  
      return error;                     //error=1 in case of no acknowledge
    }
   
    //———————————————————————————-
    function s_read_byte( ack)
    //———————————————————————————-
    // reads a byte form the Sensibus and gives an acknowledge in case of "ack=1"
    {
      local val=0;
      DATA( 1);                     //release DATA-line
      for (local i=0×80; i>0 ; i = i>>1)  {           //shift bit for masking
       SCK( 1);                    //clk for SENSI-BUS
        if (data_get()) val=(val | i);        //read bit 
        SCK( 0);                      
      }
      if (ack) {
          DATA(0);
      } else {
          DATA(1);
      }
     
      SCK( 1);                      //clk #9 for ack
      delay_us(5);          //pulswith approx. 5 us
      SCK( 0);                           
      DATA( 1);                     //release DATA-line
      return val;
    }
   
    //———————————————————————————-
    function s_transstart( )
    //———————————————————————————-
    // generates a transmission start
    //       _____         ________
    // DATA:      |_______|
    //           ___     ___
    // SCK : ___|   |___|   |______
    { 
       DATA( 1);
       SCK( 0);//Initial state
       delay_us(2);
       SCK( 1);
       delay_us(2);
       DATA( 0);
       delay_us(2);
       SCK( 0); 
       delay_us(6);
       SCK( 1);
       delay_us(2);
       DATA( 1);          
       delay_us(2);
       SCK( 0);          
    }
   
    //———————————————————————————-
    function s_connectionreset( )
    //———————————————————————————-
    // communication reset: DATA-line=1 and at least 9 SCK cycles followed by transstart
    //       _____________________________________________________         ________
    // DATA:                                                      |_______|
    //          _    _    _    _    _    _    _    _    _        ___     ___
    // SCK : __| |__| |__| |__| |__| |__| |__| |__| |__| |______|   |___|   |______
    { 
      server.log("connectionreset()");
      DATA( 1);
      SCK( 0);                    //Initial state
      for(local i=0;i<9;i++)                  //9 SCK cycle
      {
          SCK( 1); delay_us(1);
        SCK( 0); delay_us(1);
      }
      s_transstart();                   //transmission start
    }
   
    //———————————————————————————-
    function s_softreset( )
    //———————————————————————————-
    // resets the sensor by a softreset
    {
      local error=0; 
      s_connectionreset();              //reset communication
      error = s_write_byte( RESET);       //send RESET-command to sensor
      return error;                     //error=1 in case of no response form the sensor
    }
   
    //———————————————————————————-
    function  s_read_statusreg() {
    //———————————————————————————-
    // reads the status register with checksum (8-bit)
      local error=0;
      local ret = {};
      s_transstart();                   //transmission start
      error=s_write_byte(STATUS_REG_R); //send command to sensor
      ret.value <- s_read_byte(ACK);
      ret.checksum <- s_read_byte(noACK);
      ret.error <- error;
     
      return ret;                     //error=1 in case of no response form the sensor
    }
   
    //———————————————————————————-
    function s_write_statusreg( p_value)
    //———————————————————————————-
    // writes the status register with checksum (8-bit)
    {
      local error=0;
      s_transstart();                   //transmission start
      error= error+s_write_byte( STATUS_REG_W);//send command to sensor
      error= error+s_write_byte( p_value);    //send value of status register
      return error;                     //error>=1 in case of no response form the sensor
    }
                                   
   
    function s_getHumidity( ) {
        local timer=0.0;
        local data=0.0;
        local a;
        local b;
        local crc;
        local result=0;
        local errorString="";
   
        s_transstart();
        if (s_write_byte( MEASURE_HUMI)) {
            server.log("s_getHumidity:writing data error");
            return 0;
        }
       
        // wait up until 2 seconds for DATA to go low
        while (timer < 2 && data_get()) {
            imp.sleep(0.01);
            timer = timer + 0.01;
        }
        // see if an error occured (data_get is still high) 
        if (data_get()) {
            server.log("s_getHumidity:no response");
            return 0;
        }
       
   
        a = s_read_byte( ACK); //MSB
        b = s_read_byte( ACK); //LSB
     
        crc = s_read_byte( noACK); //checksum
        result = a<<8 | b;
       
    //    data = -4.0 + (result * 0.0405) – (0.0000028 *result * result); 
   
        return result;
    //    return data;
    }
   
    function s_getTemperature( ) {
        local timer=0.0;
        local data=0.0;
        local a;
        local b;
        local crc;
        local result=0;
        local errorString="";
   
        s_transstart();
        if (s_write_byte( MEASURE_TEMP)) {
            server.log("s_getTemperature:writing data error");
            return 0;
        }
       
        // wait up until 2 seconds for DATA to go low
        while (timer < 2) {
            if (data_get() == 0) break;
            imp.sleep(0.01);
            timer = timer + 0.01;
        }
        // see if an error occured (data_get is still high) 
        if (data_get()) {
            server.log("s_getTemperature:no response");
            return 0;
        }
   
        a = s_read_byte( ACK); //MSB
        b = s_read_byte( ACK); //LSB
        crc = s_read_byte( noACK); //checksum
        result = a<<8 | b;
   
    //    data = -40.2 + ( .018 * result );
    //    return data;
        return result;
    }
   
    //—————————————————————————————-
    function get()
    //—————————————————————————————-
    // calculates temperature [°C] and humidity [%RH]
    // input :  humi [Ticks] (12 bit)
    //          temp [Ticks] (14 bit)
    // output:  humi [%RH]
    //          temp [°C]
    { local C1=-4.0;              // for 12 Bit
      local C2=0.0405;           // for 12 Bit
      local C3=-0.0000028;        // for 12 Bit
      local T1=0.01;             // for 14 Bit @ 5V
      local T2=0.00008;           // for 14 Bit @ 5V   
      local rh_lin;                     // rh_lin:  Humidity linear
      local rh_true;                    // rh_true: Temperature compensated humidity
      local t_C;                        // t_C   :  Temperature [°C]
   
    //  s_connectionreset();
    // imp.sleep(1);
         
      local hum_data=s_getHumidity();             // rh:      Humidity [Ticks] 12 Bit
      local temp_data=s_getTemperature();           // t:       Temperature [Ticks] 14 Bit
   
   
      t_C=temp_data*0.01 – 40;                  //calc. temperature from ticks to [°C]
      rh_lin=C3*hum_data*hum_data + C2*hum_data + C1;     //calc. humidity from ticks to [%RH]
      rh_true=(t_C-25)*(T1+T2*hum_data)+rh_lin;   //calc. temperature compensated humidity [%RH]
      if(rh_true>100)rh_true=100;       //cut if the value is outside of
      if(rh_true<0.1)rh_true=0.1;       //the physical possible range
     
      local t_F = t_C * 9 / 5 + 32;
     
      local ret = {};
      ret.temp <- t_F;
      ret.humidity <- rh_true;
     
      return ret;
    }
}

 

sht <- SHT(); //instantiate class only once

local tempHum = sht.get(); //call as often as you want
server.log("temp="+tempHum.temp+" hum="+tempHum.humidity);

Electronics ,

Outdoor Automation Controller Installed

November 18th, 2012

2012-11-18 20.55.08I ordered an enclosure from Amazon, but in the meantime, I gutted my sprinkler control box and stuck my control module in there.  It’s connected to the two sprinkler zones, and the 120V side of my low-voltage outdoor light system (less current on the 120V side). 

2012-11-17 21.02.50In the process, I must have shorted the output of the 24VAC power supply for my irrigation system, as it stopped working.  Using a hack saw, chisel and mallet, I managed to open the power supply and only found a large transformer.  The photo is of the primary windings.  You’ll notice three wires sticking up, the black wires (120VAC) connect to two of them.  On the right, it connects to the primary winding.  On the left, it connects to a silver wire that goes into the coil and out again in the middle, which also connects to the winding.  It seems as if they decided to a fuse in the middle of the toroid to make it impossible to access.   And given the multimeter shows a short between the left and middle terminal, the fuse must be blown.   Talk about designing in obsolescence. 

I could short out these terminals or put a fuse inline to make the transformer work, but I was able to find a 16VAC (measured @ 19VAC with the multimeter) rated at like 1/3rd the current but it is still capable of powering the sprinkler solenoids so I decided to just use that. 

2012-11-18 20.55.42In any case, the device is collecting data just fine and posting it to COSM here.  The rain sensor is attached and is configured to trigger when it gets 1/8” of rain.  I’m not sure how long it will stay activated after triggered.  I also forgot to order a phototransistor to use as my light intensity sensor.  I’ll order one and add it at some time in the future.

I’m trying to figure out how squirrel parses json data (I’m just seeing it as a table blob and not sure how to access it) so I can get sunrise/sunset info to control the lights.  I’m also not sure how best to control the sprinklers given the rain data, but that shouldn’t be too bad.

I threw together a really really quick web interface to be imageable to manually turn the lights/spinklers on/off. It works fine as is very responsive, and will be made to look nice and I’ll probably add a configuration page for my sprinkler control. 

So far, I’ve been pleased with the outcome of this project.  Next up, I need to write some android widgets to display data and do some home automation, and add some business logic. 

I’ve got another Electric Imp module, not sure where it will end up.  I’m thinking monitoring power consumption for each circuit in my house, or modifying my dryer to allow me to turn it on/off and get an SMS notification when it is done with the cycle rather than buzzing loudly and repeatedly.  It might also be interesting to track the temperature and humidity of the out-gas, though I’m concerned with fouling my gas sensor with lint..

Electronics

Taking a break from the EEG work.. Outdoor Automation

November 9th, 2012

2012-11-09 18.00.05I’ve always wanted to implement some home automation system.  My first attempt at implementing an X10 based system worked for a time, then it failed.  Lights would turn on randomly, switches stopped working.  Ultimately, the lesson I learned was that you get what you pay for.  With the X10 system: cheap shit.

I’ve since implemented a couple systems, they work for a time, but nothing robust.  I was happy to find the Electric Imp which is an inexpensive WiFi module with a cloud based backend.  I wanted to test it out, and thought automating my backyard low voltage lights and sprinkler system would be a good first application.  Luckily, most of the work was initially done by their developers in their implementation of the ‘Jane’ platform.  I asked, and was given access to their source files (since posted on their site).  I modified it to my liking:

  • Only 3 relays, not 4 to reduce PCB size cost
  • Swapped their temp sensor for an SHT71 temp/humidity sensor.  Overkill, for this application, but I have a number of extra ones from a previous project
  • Replaced their shift register with an I2C I/O expander (I need more I/O pins)
  • Used a full bridge rectifier to allow more power to supply the caps.  I also like the way full bridge rectifiers look. 
  • Added support for an external NPN based light sensor.
  • Added support for an external rain sensor.

I need to test/debug the hardware, write code in some language named after a rodent, get a box to mount the electronics – and then I’ll be all set. 

 

For the UI, I will be putting a framed Nexus 7 permanently in the wall.  It will serve as a frontend to a number of applications I want to make.

I think I’m going to make a number of visualization widgets to plot things like power consumption, temp, etc, and have a webserver running on the hardware that will serve html pages to do the configuration (when the sprinklers work, etc).  I plan on using it to control music in the house.  Let see how far I get along this project before being sidetracked.

Electronics

Website Migration from 1and1.com to Amazon’s EC2

October 31st, 2012

It was a bit of work to get everything setup, but I finally migrated my websites from 1and1.com (horrible horrible company) to amazon’s EC2 service.  Wow, performance is great, I pay for what I use only  (way cheaper) – and the first year is pretty much free for you to try out.  If you know anything about setting up a linux box with apache and mysql – it’s trivial. 

The EC2 management console took a bit of playing with to figure it out.  You can add disks, make backup snapshots, configure the firewall, increate the ram, add CPUs, etc.. Very slick.

In any case, the migration is still in progress and I need to fix a few more things.  But after the migration, I hope to be updating this site more frequently.

Electronics

Thermostat Replacement For Kegorator

February 26th, 2012

IMG_1226

I had experimented for some time with a peltier based heat exchanger to cool beer from my kegs (home brewing), but after a few iterations, I felt the system would not be as compact as I hoped, and the peltier was eating up too much current (80W).  Here’s the unit  – heatsink, peltier, and big block of metal that would be placed in a water bath.  I have 16ft of stainless steel tubing that wraps around the block for the beer to flow through.  I had the unit in a bucket surrounded by expanding foam for insulation.   Ultimately, it was ugly.

I finally gave in, and decided to buy a dedicated fridge for the kegs instead.  I found a neighbor selling one of the right size across the street (very convenient).  He was the nth owner, and it was a commercial unit with a nice stainless steel exterior.  However, after getting it home, it seemed apparent that the thermostat was useless.  It would turn on randomly and off randomly.  I figured I could fix this, but my goal was to spend no money.  Also, the thermostat has this meal tube that goes into the wall of the fridge – and it seems permanently attached, so I wasn’t sure how feasible it would be to replace the thermostat if I had to take the entire thing apart to replace that tube.

launchpad01

After looking through my pile of PCBs that I could repurpose, I came across my Texas Instruments LauchPad that I picked up at ESC.

The thing that makes this unit amazing as compared to the arduino is that it costs $4.30.  The thing that sucks is that the target MCU is a POS and really didn’t have enough ram/flash for my liking.  However, after looking at the schematic, the IC at the top left of the picture caught my eye.  It’s a MSP430F1612, and it is used as a programming interface for the target IC.  Unlike the target MCU, it’s very nice and had all the features I wanted.  It’s powered off USB (5V) but has a 3.6V regulator onboard.  This surprised me a bit as this is the max voltage the MSP430s run at, with 3.3V being more logical, and what I would have expected.  Additionally, the header exposed 4 of the I/O lines which are used to interface (program) the target MCU.  This was the minimum I needed to implement a temperature sensor, a display, and to control a relay to switch on the refrigerator compressor.

I love how appliances have wiring schematics on them these days (though I had to remove the condenser coils to access it).

IMG_1208

Both neutral and line voltage (120VAC) are present at the location of the thermostat, and a simple relay is sufficient to drive it.   Oddly enough, the lamp switch was present but unused in the fridge (so it was always on – was probably a design mistake as the door never made contact with the lamp switch anyhow).   Not surprisingly, the bulb was burnt out.

IMG_1209

The relay replaced the thermostat (pins 3,4 in the photo).  And a wall adaptor for my old cell phone which presented a 5V USB interface was used to provide power.  It was connected to the BLU wire and the WHT wires in place of the lamp.

imageThe schematic for the lauchpad is provided by TI, which was nice.  The header I interfaced was J3. If you look, you’ll find that pins 5.1, 5.2, 4.7, and 4.2 are all connected through R5 to SBWTDIO.  Setting all but one pin as an input, and using the output pin worked fine.  Additinally, pin 5.3 connectes to SBWTCK (with a pulldown resistor which we can ignore if we are driving the pin).  Finally, we have the a serial interface on pins 3.7 and 3.6.

The header on the top left (you need to add pins) provide the programming header for the MSP430F1612.  There might be some way to program it from the USB port, but as I had the programmer, it was fairly easy.

The interface I  built was super simple, but looked ugly as it was a mass of wires handing all over.  Here’s the schematic.

photo-001

Starting from the top, an IO is used to switch a darlington which turns on the relay.  Again, I just used what I had lying around, and it was able to switch the relay at 2V, which was good.

I have a number of SHT75 temperature and humidity sensors lying around that require a clock and data line to interface.  Additionally, the data line requires a pullup resistor, but the MSP430F1612 doesn’t have any so an external one was added.  They have some horrible example code that I ported over and after a few tweaks I was able to get it to work.  One tricky bit is that the data line should never be driven high – when the code wants it to go high, set it as an input so that the pullup resistor pulls it up.  For some of the messaging, you need to watch that line and see when the SHT75 module pulls it low.

Finally, I got lucky and had an LCD with the SerLCD module from sparkfun mounted.     It lets you use a serial line to drive a serial interface, dropping the I/O line requirements from something like 8 to 1.

I recently got an Ultimaker which is cool, but the documentation sucks sucks sucks sucks for a commercial product.  I need to spend the rest of the day today taking apart the print head and which is encased in melted plastic to add some teflon tape to prevent the plastic from oozing everywhere.   In any case, I was able to print out an enclosure for the device, and for the most part, it works fine.  Not having any additional input lines, I have no way to adjust the temperature setpoint without pulling the board out and reprogramming it.  It’s currently set to turn on at 45 deg F and off at 40 deg F, which seems a reasonable temperature range for beer.  Here are some photos of the unit operating.

IMG_1223

The temperature probe is taped to the back of the fridge.

IMG_1224

Yes, humidity is pointless in this application, but I had enough space on the LCD.

IMG_1225

It’s still a mess, and I would like to remake the enclosure so it’s a bit nicer and it fully hides all the wires.  Feel free to contact me if you want a copy of the firmware.

Electronics ,

Android Intents, registerReceiver, BroadcastReceiver, updating GUI elements from threads

August 12th, 2011

First, let me make one thing clear.  I have Java.  I think that there is something wrong with the way people who code java think.  It’s like they have to make things as complicated as possible, as verbose as possible, and as convoluted as possible for no reason.

I had a simple goal, and that was to have a background thread receive some data and update a text field in an “Activity”.  There were plenty of webpages that attempted to describe how to do it, referring to explicit intents, to modifying the Manifest.xml file, and all sorts of other jargon – but no clear examples.  I came across dozens of posts from people trying to do the same thing I wanted to do, but no answers.  I spent about 4 hours trying to piece together a method that worked. 

Hopefully, this simple explanation will help someone..

If you want to send data from one thread to another you can do it through a messaging protocol, and encapsulate data in that message if needed.  One big complication is that the messaging can occur across applications, it can be directed at a specific target if you know it exists, or it can be ambiguous and you figure something will deal with it.  The messages can also invoke an application (“Activity”) to do something.

What I’m going to describe is how to send a message from one part of an application to another – with the typical goal being to send data to the active “activity” to display data or somesuch.

 

1. In the activity where you want to receive messages, you need to create a class within the activity class (I have no idea what the java developers were smoking to come with this idea) that extends BroadcastReceiver().  You then want to override onReceive() to contain the business logic.

 

public class ActivityClass extends Activity {

  private BroadcastReceiver mReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if (action.equals("net.reza.SET_BATT")) {
            setBattery(intent.getIntExtra("value", 0));
        }        
    }
  };

  /* rest of your code */

}

In this example, I’m creating  mReceiver which is a BroadcastReceiver but I am modifying the onReceive() method.  In the method, I’m checking to see if the activity string is equal to “net.reza.SET_BATT”.  This can be anything.  There are some standards that are meaningless.  Use whatever you want.  I think it’s called an intent or intent-filter.  I’m going to call it a ‘tag’ for clarity.

2. You need to register that mReceiver is capable of handing the “net.reza.SET_BATT” tag.  There are a bunch of places to do this in your code.  I stuck it in the onCreate() method for the Activity class.

 

@Override

public void onCreate(Bundle savedInstanceState) {
  IntentFilter ifilt = new IntentFilter("net.reza.SET_BATT");
  registerReceiver(mReceiver, ifilt);

  /* more code */

 

A lot of the documentation said you need to modify the Manifest.xml file and stick it in there, but that was a mess and not obvious how to make it work.  Defining it this way is /much/ easier, and in my mind, much more manageable.  Why do java people love XML so much? 

And I have no idea why they call these tags “intent-filters” but they do.  Based on my code, you don’t need to bother with the action.equals() line, as the only time it will be called is if that tag is registered with registerReceiver(), and I’ve only registered that one tag.   But if you register multiple tags with the same BroadcastReceiver then you should check to see which one is being called.

 

3. You need to invoke that tag.  This can be done anywhere, as far as I know.  Even from another application.  In my case, it’s from a background thread that monitors the battery voltage by polling a device over bluetooth. 

public class BatteryMonitor extends Thread{

Context context;

public BatteryMonitor(Context y) {

  this.context = y;

}

 

public void run() {

  /* some code */

  Intent i = new Intent("net.reza.SET_BATT");
  i.putExtra("value", bat);
  this.context.sendBroadcast(i);

  /* more code */

}

 

Couple things here.  First, I still have no clue what a context is, who owns it, and how to use it properly.   I kept trying different things till it worked.  I passed the output of getBaseContext() to the constructor of the background thread, and that seemed to work.  I think some other options are getContext() and getApplicationContext(), so try those too.  Please post a comment if you know what’s going on.  

So we create an Intent with the same tag.  We can then stick extra data in there – in my case, I add an int. And then you call the sendBroadcast() method from the context object to make it go. 

 

I now need to go write some more code in C to cleanse my mind from all this gibberish…

Electronics

Skunkworks Project–Modern Art PCB

July 10th, 2011

Been busy the past month with a secret project.  Still in stealth mode, but the layout looked like modern art, so I thought I would share…

 

image

Electronics

Bluetooth enabled multifrequency bioimpedance spectrometer for hydration monitoring.

June 5th, 2011

P1040489

I finally had a chance to assemble this PCB.  Alas, I ordered an SO8 package for a part accidentally and had to stick it on a daughterboard.  Will replace with the right part.  Designed to scan complex bioimpedance from 1k-100kHz and communicate with a handheld tablet over bluetooth.  I’ve moved away from the CSR ICs to using these packages as the BlueCore 3 that we were using became more expensive than these modules, and the modules are a lot simpler to solder.  I’m planning on moving to the BlueCore5 for future designs – can get power consumption down to <10mA (if you believe the datasheet) at 115kbps.

Electronics