button_collage

Push Button RF Data Transmitter

Background

So a friend of mine who works in, let’s say, the sciences, approached me about a simple application, but one that a hardware company was charging an inordinate amount of money for. In the physical sciences equipment business, this is very common: overcharging for a very simple feature, because it’s convenient and it just works. The fact of the matter is that scientists simply don’t have the time to homebrew solutions, they don’t get accolades for making simple instruments work well and cheaply, and taking the time to do so takes them away from their real jobs — doing science. This is where consultants and outsourcing really make sense, even when at first it might seem a bit expensive. Regardless, this doesn’t mean that buying a receipt printer attached to a button to print out data from a device should cost $1000, or a dead-simple temperature controller in a box with a couple relays should cost $2k. but this is the twisted norm.

We are moving away from a time where a tiny handful of people were able to design things that once seemed very complicated, like a microcontroller IO device, to an era where these things are available for dirt cheap and are everywhere. The markets are therefore just waiting to be taken over or at least challenged and/or adjusted by the talents and creativity of the makers around us.

The Project

The device I was approached about was a laboratory instrument that has an RS232 interface. You can send it a couple characters and it sends back the data. What we envisioned was a single button: you press the button, it acquires data and sends it off to a sensor gateway, where the data is databased and stored for later processing, addition of metadata, etc. It’s a pretty general thing. To summarize:

basicmodel

Now the idea of a single button is pretty romantic, in a way. It is the absolute reduction of input to the simplest unit of data transfer: the binary digit. The ultimate in simplicity. As it turns out, it’s not a unique one, either. The Staples big red button has been around forever, and if you do some googling you can find a couple companies that make, essentially, big red networked buttons that do one thing. There are legion applications where you just need one thing to happen. Call an elevator, a taxi, turn on a light, disable an appliance … so many user interfaces can be created with one or three binary elements. Anyway, the imagination runs wild. But let’s get onto the simple nuts and bolts of how to make our little button here.

The Hardware

We’ll construct this unit exactly like our Enhanced Remote, which we wrote about previously. We’ll use the same enclosure, and just attach a button to the top, and run two cables out of one side. This will negate the IP rating of the cable entry, but make it so all of our cables come out of one side. This is a key feature for presentation and accessibility. As a result, however, we need to size up our cable entry to PG9, which really doesn’t fit on the side of the enclosure, despite the appearance. Next time we do this, we’ll get a single cable with enough conductors so we can use a smaller PG7 entry as on the standard remote.

Components for our RF button remote.
Components for our RF button remote.

What we SHOULD have done here was document the button insertion process and what the bare button looks like. It’s one of these guys at right.

Our button's product picture before we seal it up on the enclosure lid.
Our button’s product picture before we seal it up on the enclosure lid.

Strangely, the top bezel on this thing is really narrow, so you need to get the hole size just right. Let’s just say our set of bits didn’t prove up to getting it close enough. So we ended up using a grommet in the hole opening, which had the added benefit of keeping the top sealed. It also gives the button a little spring, and a totally secure feeling. To get it in there just right, we had to cut the grommet in half and use one half on each side. Not a very interesting story.

Wiring

Aside from the step putting this thing together we covered previously, we need to do our wiring to the outside and connect our button. From the outside, everything will be on one USB cable: 5V power, GND, and two data lines. The two data lines will be passed out on the second USB, and our data source can use them as they see fit. For an RS232 source, for example, we’ll use them as RX/TX, after level conversion if necessary. This will make using a Y USB cable possible in the future. Here’s a simple layout:

Simple wiring diagram of our button and RF sender unit. All the external connections go on a single USB bus.
Simple wiring diagram of our button and RF sender unit. All the external connections go on a single USB bus.

The button is pretty straightforward – two pins for the contact and two for the LED. One button contact will go to ground, with the other connected to the IO1, which we’ll configure as INPUT_PULLUP on the Arduino. Not coincidentally, this pin has a hardware interrupt (pin 3) on the Moteino/Arduino. When our button is pressed, the input will change from it’s normal state of 1 to a state of 0. We can set an interrupt on RISING or FALLING and we’ll be good to go.

For the button LED, we’ll need a current-limiting resistor. 330 ohms turns out to be about right, using the 5V input from our USB power input. We attach this to the positive LED terminal, and connect the negative terminal to IO1, which we’ll use as an open-drain output. The IO4 terminal is connected to the drain of the MOSFET footprint, into which we’ve soldered a 2N7000 NPN. IO4 on our mote is io7 internally, and corresponds to pin A2. Once we enable the output, it will be set each cycle, so we don’t /need/ a pulldown, but we’ll configure one anyway.

Construction

Now we need to physically get everything into the box. Not to complicated. First, we solder our button wire. I am personally so tired of soldering crappy stranded wire, such as that in ribbon cable, that I went with some solid core hookup wire. It’s not as pretty and tidy, and makes closing up the box a bit of a pain, but it’s much more robust and cuts down on the short/bad connection sleuthing endemic to stranded wire, especially when you are moving connections around a lot. It also makes screw terminal insertion (especially difficult with the space constraints here) a breeze. Totally worth it in this application.

Getting everything into a box. Pulling cable in and wiring our button.
Getting everything into a box. Pulling cable in and wiring our button.

Once we do some wire coiling and screw terminal insertions, we’re ready to close ‘er up (and then open it up again to program it).

All done! Time to play.
All done! Time to play.

Micro Programming

Programming this thing is pretty basic. You can find the sketch here. We’ll mention a couple things we did that were perhaps noteworthy. The rest has all been covered in our UniMote programming. We decided to slightly modify our interrupt programming. We have noticed that there are issues with running any serial print debug on a function run by an interrupt. This can be quite annoying, especially if you are calling a function that is designed to provide output, such as debug accompanied by our RF send functions, for example. To mitigate this, we used our interrupt to do nothing except set a loop routine to run:

pinMode (3,INPUT_PULLUP);
attachInterrupt (1,setDoButton,RISING);

...

void setDoButton() {
  runDoButton = 1;
}

Then, inside our loop:

if (runDoButton) {
  doButton();
}

The only requirement here is that the loop time is short enough that feedback is fast. Because we’re not really doing much, as long as we make sure our LOOPPERIOD is sufficiently short, we’re good to go.

Finally, sending our value is as simple as wrapping up our standard SendWithSerialNotify function with something that retrieves our data, and sends a specially formatted message. In this case, we’re using the identifiers ‘scalepin’ and ‘scalevalue’. This will allow our gateway to interpret the data accordingly. This is shown below, with dummy data for testing. You can see here that we manually turn the LED output on and off again when the function enters and exits, respectively.

void doButton() {
  if (millis() - lastbutton > debounce && iovalue[7] == 0){
    Serial.println("Button Pressed");
    iovalue[7]=1;
    
    // manually turn on output
    digitalWrite(16,1);
    
    float scalevalue = 9999.9999;
    sendScaleMessage(iopins[7], scalevalue);
    lastbutton = millis();
  }
  runDoButton = 0;
}
void sendScaleMessage(byte pin, float value) {
  int wholePart = value;
  long fractPart = (value - wholePart) * 10000;
  int sendlength = 35; 
  char sendstring[sendlength];
  sprintf(sendstring, "scalepin:%02d,scalevalue:%05d.%05d", pin, wholePart, fractPart);
  sendWithSerialNotify(GATEWAYID, sendstring, sendlength); 
  Serial.println("Waiting, hang on");
  delay(1000); //  This is for visual feedback
  Serial.println("Done");
  iovalue[7]=0;
  digitalWrite(16,0); // turn off light manually
}

Gateway Programming

On the gateway, all we need to do is include a handler for our special message with data fields of ‘scalepin’ and ‘scalevalue’. Pretty easy stuff. We’ll fancy it up later, but for now it’s just as simple as an additional line or two in our serialhandler.py:

elif 'scalevalue' in datadict:
            querylist.append('create table if not exists scalevalues (value float, time string)')
            querylist.append(pilib.makesqliteinsert('scalevalues',[datadict['scalevalue'], pilib.gettimestring()],['value','time']))
            pilib.sqlitemultquery(pilib.logdatabase, querylist)

A couple presses of the button later, and sure enough, we have a table with some values!

Button press dummy data, as viewed in phpliteadmin. Yay data!
Button press dummy data, as viewed in phpliteadmin. Yay data!

We’ll spend some time getting this into a proper page for export and addition of metadata shortly. Oh yeah, and getting real data!

Reference

The above makes use of the open source libraries available on github:

Explanation and installation here:

Leave a Reply

Your email address will not be published. Required fields are marked *