Project Monday: Laser Monitoring with Sy...

Solar botics
March 10, 2014

I'm Dilan, a relatively new hire here at Solarbotics, and I am in charge of product development and R&D support. I've got tons of experience with many things, and have seen Arduino as a staple in many projects here at Solarbotics. With its ease of use, powerful programming language, and vast online community, it has been the go-to platform whenever a quick solution is needed. But when I needed some wireless communication, I'd choose a system like Xbee/Zigbee or even simple 433MHz modules, where the communication interface was still treated as a dumb serial link between the two systems. With Solarbotics' use of Synapse, I needed to project to get to know a more advanced wireless system.

Solarbotics has been playing with Synapse SNAP modules, and have featured these modules in various projects in the past, like our our wireless Brutusbot and with a tutorial on how to get started with Synapse. This system has potential, and it was time to bend it to my will!

Why Synapse?

Some quick details about Synapse, and why to consider them for your project:

  1. Instant mesh-networking. Unlike similar XBee/Zigbee devices, these simply talk to each other. And if you need more range, just plop another unit in between. Done!
  2. Fast and powerful. Even the cheapest unit can do 450M (1500'), up to 2Mbps. Let's see a cheap 433MHz unit do that!
  3. Built-in microcontroller. Although it's Arduino-friendly, there's no need for it for simpler applications. 7 A/D ports, 6 PWM outputs, and 9 interrupt-capable pins, plus I2C and 2 Uarts on the least expensive RF200P81 model. That's lots to work with.
  4. Cost. The least expensive model is only $19.95. They're all compatible; it's just what feature set and range what determines what model you want.

Development

After breadboarding up one of the RF100 SNAP modules with the use of our breakout board, I started in on the above tutorial and instantly fell in love with the amount of functionality that these modules provide. While there is a small hurdle of learning the syntax of Python, any experienced Arduino user can be fully up to speed in a few days hacking with SnapPy (Synapse' version of Python).

The amazing part about these modules is their ability to mesh network by default. You can use a single SNAP module to communicate with a huge number other modules by just specifying the target's address. Being mesh-networked means talking with a remote module is straightforward as long as long as you have other modules in-between.

However I'm going to try to stay out of the details of my intimate love affair with Synapse just in case my wife is reading this article. What I want to focus on today is the practical application of how I used these modules to solve a long standing problem here at Solarbotics.

We produce a lot of acrylic parts. Sales of Useless Boxes often means our team of lasers is running non-stop. A production problem we often hit is notification of a laser's "Job Complete" signal, which is a soft "beep", and is often missed in the loud lasering room. Although the lasers are continually monitored, they can easily sit overlooked for 20-30 minutes while waiting for an unload by the production team. By the end of the week these delays add up and that's something we don't want.

This is where the use of Synapse comes in. We want to have a SNAP module monitor each laser's "job complete" beep signal, and send the status via the mesh network to the Master node that will pester the production team with a "HEY! Change me!" signal. Less time wasted, less power used, and a more efficient production team!

Sensing Laser Beams

I started by fleshing out how to interface a Synapse module to our biggest laser, aptly named "Papa" (the most powerful and somewhat… the least smart one of the three in the laser family here at Solarbotics). I was happy to see that in a previous project we had already brought out the "Laser Firing" signal to our custom air assist  circuit, which turns off the compressed air line when the laser is not cutting. A high (5V) signal indicates laser is cutting and low (0V) when the job is finished (image below). On turn-on, the "Laser Firing" signal goes high until the file is loaded, then acts as a traditional "5V for on", "0V for off" signal. Yay for traditional 5V logic!

But as SNAP modules are 3.3V logic, I a simple voltage divider to bring the signal down to safe levels. With this signal, I'm able to detect job completion, and trigger the LED indicator of the Master module.

Finished Module:

 

As we were stealing the signal for the air assist valve, we merged the control circuitry with our laser monitor board.  We used BPS protoboards and a prototype "Circuit Sammich" protective acrylic to mount the screw-down connectors, voltage regulation, air-assist relay and Synapse module. We're using the SMA antenna version of the RF100 module so we can optionally move the antenna off the laser for best signal quality.

Since SNAP modules can be programmed with Python, I was able to completely drop the use of an Arduino. This decreased the overall size of the device while increasing the wireless functionality - a win/win in my books. No need to code twice - the event-driven embedded python in the SNAP module was more than adequate for this application.

The Code

Download

Python is great, but due to hardware restrictions, there are some limitations to note when working with the Synapse' SNAPpy python:

  1. No For/Next loops are not supported. This was a bit aggravating. You can use do/while instead but it can be cumbersome and ugly. I'm not sure why it's not supported, but alas, that is how it is. This quirk is also followed by
  2. No float, long, lists (arrays), and classes. These are all annoyances to the way most of us are used to coding, but the usefulness Synapse provides is compensates for these shortcomings.

Synapse uses the event driven programming model. Instead of running a continuous loop like Arduino, Synapse will only execute code when an interrupt is triggered. This interrupt can be one of many things, but for this code I only utilize interrupts from input pins as well as a timer that triggers an interrupt every second.

While I'm not going to go into a huge amount of detail about the code (I've made sure to include extensive commenting), I feeling like a brief description of how it functions is required.

@setHook(HOOK_GPIN)

def togglePin(pinNum, isSet):  #Passes the pin number that toggled Interrupt and if a high or low signal

global lStatus, lFlag  #Use global variables instead of making locals

if isSet == True:  #If the signal is high (3.3V)

if pinNum == lStatus:  #If the pin was the lStatus pin
lFlag = False	 #Set the flag to false

elif isSet == False:  #If the signal is low (0V)
if pinNum == lStatus:  #If the pin was the lStatus pin
lFlag = True  #Set the flag to true

The main function of this device is to monitor the laser firing signal to sense when it has finished a job. To do this we use the @setHook(HOOK_GPIN) interruptThis will sense when any monitored pin which transitions between high (above 2.31V) or low(below 1.16V). It will then execute the togglePin(pinNum, isSet) function that will set a flag to indicate if the laser has finished cutting or not.

@setHook(HOOK_1S)

def updateFSM(tick):

global lCount, lTimeout, lFlag, dFlag

if lCount < 10 and lFlag == True:  #If the laser has finished and it has been less than 10	#seconds.

lCount += 1  #Increment the counter by 1
print(lCount);

elif lCount >= 10 and dFlag == False:  #If it has been 10 seconds or greater, and the done flag                                                                                #hasn't been set.

rpc(masterAddress, 'laserFinish', "papa")  #Tell the master node that the job has been completed.

print("RPC Called");
dFlag = True  #Set the done Flag to True so that the master 
		#node isn't poled again.

elif lFlag == False:  #If laser has not finished a job or else not started a job
lCount = 0  #Reset the counter
lFlag = False  #Set the flag to false
dFlag = False

If it has sensed a high signal, it will set a flag to say that the laser has finished. After 10 seconds of the done flag being set high, the module will execute the function rpc(masterAddress, 'laserFinish', "papa"). This is where Synapse really starts to shine. The function rpc() will allow you to execute a function on another module. You can specify the address, function, and parameters you will pass. In this case, we are specifying an address of masterAddress, and will execute the function laserFinish which takes the argument of "papa". This will in turn tell the Master module that the papa laser has finished a job and that it should turn on the indicator LED.

Flashing LEDs

Now that the laser monitoring device had been completed, the next step is to build the LED indicator. Below is an image of the three lights that represent the three different lasers we have in the warehouse. It originally contained 3 incandescent bulbs that ran at 12V which I didn't like. So instead, I ripped them out and replaced them each with a high power 2.8 watt white LED (Ooooo shiny!).  This allowed me to use one of our Star Controllers to control each LED with the default 3.3V of the Synapse module.

The control box features a Synapse RF100 module with the integrated chip antenna. Another SMA model would have been preferred, but the larger antenna would have been in the way (and this is all we had in R&D at the time!).

 

On the bottom we have the round Star Controller circuit board, which interfaces low voltage/low current microcontroller pins with high voltage/high current LEDs. Each channel of the Star Controller (usually used to control an RGB LED) drives 350mA into each white LED in the light tower, which we've found is quite adequate to illuminate the indicator nicely.

On the left are the three pushbuttons. We use these buttons to turn off the indicator once the laser has been restarted. The buttons are wired to pull the Synapse lines from 3.3V to 0V. A 10K ohm pullup is used to provide a known state. As before, the electronics have been soldered to another BPS protoboard and then enclosed within a prototype "Circuit Sammich".

The Code

Download

The LED indicator station simply displays the completion status for each laser. When a laser has finished, its monitoring device will execute a function on the Master module (inside the LED indicator) which sets a flag stating that the indicator LED for that laser should be turned on.

def laserFinish(laserName):

global rFlag, gFlag, bFlag  #Use the global variables instead of making locals

if laserName == "baby":  #If the laser that called the function passed the string "baby" 

rFlag = True  #Turn on the baby LED indicator by setting the flag to True

elif laserName == "mama":  #If the laser that called the function passed the string "mama"

gFlag = True  #Turn on the mama LED indicator by setting the flag to True

elif laserName == "papa":  #If the laser that called the function passed the string "papa" 

bFlag = True  #Turn on the papa LED indicator by setting the flag to False

Above we have a code snippet of the function that handles setting the flag for each laser. When the laser monitor calls the function rpc(masterAddress, 'laserFinish', "papa" ), it will set laserName to "papa". Since this meets the condition of the second elif statement, bflag is set which will make the Synapse module blink the b-channel of the Star Controller which represents the "papa" laser LED.

@setHook(HOOK_GPIN)

def togglePin(pinNum, isSet):

global rFlag, gFlag, bFlag  #Use the global variables instead of making locals

if isSet == False:  #If the interrupt was triggered by a high signal
if pinNum == bInput:  #If the pin being triggered is the baby laser reset button
rFlag = False  #Turn off the baby LED by setting the flag to false

elif pinNum == mInput:  #If the pin being triggered is the mama laser reset button
gFlag = False  #Turn off the mama LED by setting the flag to false  

elif pinNum == pInput:  #If the pin being triggered is the papa laser reset button
bFlag = False  #Turn off the papa LED by setting the flag to false

If a flag has been set by a laser and the LED is being flashed, it can only be turned off by pressing one of the reset buttons. When a button has been pressed, it will toggle the @setHook(HOOK_GPIN) interrupt which will then set a flag false depending on which button triggered it.

Note that HOOK_GPIN passes two variables to the function that is executed by the interrupt; pinNum (contains the pin number of which pin triggered the interrupt) and isSet (states whether the interrupt was a high or low signal). In the code above, we will only reset a flag if the interrupt was a low signal and the pin was one of which that were assigned to each laser.

@setHook(HOOK_1S)
def updateFSM(tick):

global rFlag, gFlag, bFlag  #Use the global variables instead of making locals

if rFlag == True:  #If the baby laser flag has been set to true

pulsePin(rPinLED, 500, True)  #Turn on the baby laser LED indicator for 0.5 seconds

if bFlag == True:  #If the mama laser flag has been set to true

pulsePin(gPinLED, 500, True)  #Turn on the mama laser LED indicator for 0.5 seconds

if gFlag == True:  #If the papa laser flag has been set to true

pulsePin(bPinLED, 500, True)  #Turn on the papa laser LED indicator for 0.5 seconds

Every second, the @setHook(HOOK_1S) is triggered and will execute the above function which will turn on the LEDs for the corresponding lasers. The function pulsePin() is extremely helpful since it will pulse a pin either high or low for a specified duration. In our case, I pulse the pin for each LED high for 500mS. Since the updateFSM() function runs every second, each LED is effectively on for 0.5 seconds and off for 0.5 seconds if it's flag is set to True.

Although not as cheap as "keyfob" type transceivers, these inexpensive Synapse units offer considerable utility, especially considering it has an inbuilt microcontroller available for your use. While there may be a bit of a learning curve for python, I can personally say that the investment in time was  very well worth it.

Solarbotics Synapse Tutorial

Synapse Forums

Python Documentation Index

Synapse Ref. Manual

MORE POSTS

January 20, 2014
TechBurlesque Fundraiser on January 17

As a worthy conclusion for the last workweek on Friday night we attended TechBurlesque show, which was a fundraiser for the upcoming 2014 Make Fashion Gala & Fashion Show. It was hosted by Endeavor Arts Gallery located in the downtown Calgary. In preparation to the show we have donated a bunch of electronics and glowy […]

October 2, 2007
Tah-DAAAA! Welcome to the new digs!

...And by "digs" I mean website! Thanks to all of you who've dropped in for a looky-loo while the paint dries. We're still (metaphorically) moving the furniture in, but everything is ready to roll. Stay tuned while we finish tweaking and installing new content! Thanks, Dave

July 12, 2013
Friday New Product: Synapse, OpenBeam an...

Lets contabulate! And that means, as I recently learned, to cover with boards, which in our case are - breadboards. Today's breadboard coverage is only partial, as we have other stuff to show off too: Synapse "Getting Started" Transmitter Bundle $49.99 Add a Wii Nunchuck and battery to this bundle and you'll have a simple […]

April 13, 2006
Question: If a rabbit laid an egg, would...

Answer: If it was a chocolately Easter Egg, yes! Yes, quite possibly that was the worst segue of the season, but moving on... Solarbotics will be closed on Friday April 14, 2006 for the Easter long weekend. We will be open on Monday, April 17, 2006 and all will be business as usual.

Solarbotics Ltd Logo
Solarbotics has been operating for more than 25 years, bringing electronics know-how and supplies to both the electronics professional and hobbyist. We'll be happy to help you too!

Solarbotics, Ltd. is not responsible for misprints or errors on product prices or information. For more information, please see our Terms and Conditions.

Warning: This product contains chemicals known to the State of California to cause cancer and birth defects or other reproductive harm.
Please visit www.P65Warnings.ca.gov for more information. This item was manufactured prior to August 31, 2018.