My contribution to the open-source community http://www.opensourcelab.salazarserrano.com A blog by Luis Jose Salazar-Serrano: physicist, engineer and open-source enthusiast Mon, 12 Sep 2016 19:23:33 +0000 en-US hourly 1 https://wordpress.org/?v=4.7.6 Automatic Beam Blocker http://www.opensourcelab.salazarserrano.com/automatic-beam-blocker/ Mon, 12 Sep 2016 19:23:33 +0000 http://www.opensourcelab.salazarserrano.com/?p=159 Read More »]]> A beam blocker (BB), also known as "beam shutter", is a device used to block / unblock a light beam while the source power stays on.

In this post, I will present how to implement an extremely cheap and simple Automatic Beam Blocker (ABB) that can be used to block a low power laser beam. The beam blocker is composed of a shutter that is open or closed by pressing a push button connected to an Arduino Uno board.

automatic_beam_blocker_002

Materials

  • 3D printed beam blocker (STL files available on Thingiverse repository)
  • Servo motor (Tower Pro SG90 9G Mini servo)
  • Push-button
  • 1 Kohm resistor
  • Connection cables
  • Arduino UNO board

To build the beam blocker, first download the zip file automatic_beam_blocker.zip, extract and print the STL files (automatic_beam_blocker_1of2.STL) and (automatic_beam_blocker_2of2.STL). Afterwards, mount the pieces according to the following steps show in the figure. Notice that in the zip file there is also provided a STL file that contains both components for a single print session (full_automatic_beam_blocker.STL).

automatic_beam_blocker_gif

In principle the Automatic Beam Blocker requires only a 1/2" optical post to be mounted on any experiment. In addition, the device is compatible with Thorlabs cage system. In the zip file I also provide a SCAD file (automatic_beam_blocker.SCAD) that allows to change certain parameters in order to make the ABB compatible with cage systems from other manufacturers.

Once the beam blocker is assembled, mount the circuit, upload file beam_blocker.ino in the Arduino UNO, and start using the Automatic Beam Blocker in your experiment!

3D printed Beam Blocker

The beam blocker is composed of two parts. The main part (automatic_beam_blocker_1of2.STL) is used to couple the shutter to a 1/2" post or to a cage system and to fix the servo that moves the shutter.

The second component, the shutter (automatic_beam_blocker_2of2.STL), is aimed at blocking the light beam. The height of the shutter can be changed in the first line of the module beam_shutter() of the openSCAD file. By default the height is set to 2 mm (see line height = 2;).

Control circuit

The beam blocker is controlled by a push button that opens or close the shutter depending on its previous state.

beam_block_003

The shutter moves by means of a Tower Pro SG90 9G Mini servo that is set to move between the positions 0º (closed) and 90º (open). The angles are specified in lines 56 and 61 in the Arduino code shown below.

/*

beam_blocker.ino

Program that controls a 3D printed beam blocker that uses a servo as actuator

The circuit:
* Push-button connected to pin digital pin 6
* Servo motor connected to pin 9

Usage:
When the push button is pressed, the beam blocker opens or close depending on its previous state.

Additional information:
3D printed model can be downloaded from Thingiverse  

Created 08/Sept/2016
By Luis Jose Salazar-Serrano
totesalaz@gmail.com
http://opensourcelab.salazarserrano.com

*/

#include 

Servo servo1;

int ledPin = 13;                
int key_s6 = 6; // pin for push button

int index = 0;
boolean flag1 = false;

void setup()
{
  pinMode(ledPin, OUTPUT);      // Set Pin13 to output mode
  pinMode(key_s6, INPUT);       // Set Pin2 to input mode
  
  servo1.attach(9);             // Attach servo to digital port 9
  servo1.write(0);              // initialize servo position
  digitalWrite(ledPin, LOW);
}
void loop()
{
      
   // if button S6 is pressed...
   if(digitalRead(key_s6) == LOW && flag1 == false){        
    index++;
    flag1 = true;
   }

   // if button is NOT pressed...
   if(digitalRead(key_s6) == HIGH && flag1 == true){    
   
      if(index%2 == 1){
        servo1.write(90); // open beam block
        digitalWrite(ledPin, HIGH);
      }

      if(index%2 == 0){
        servo1.write(0);  // close beam block
        digitalWrite(ledPin, LOW);
      }
      
      flag1 = false;
   }
           
}

Additional resources

  • The ABB circuit can be viewed and tested online (for free!) using the platform Autodesk circuits that allows to simulate the Arduino based scheme shown above. The scheme can be found on the following link.

  • The STL files ready for 3D printing are available on the following link on Thingiverse. For more components useful for the optics laboratory visit the things that I have implemented so far.

]]>
Product Theorem for Gaussian Functions http://www.opensourcelab.salazarserrano.com/product-theorem-for-gaussian-functions/ Sun, 27 Mar 2016 11:00:57 +0000 http://www.opensourcelab.salazarserrano.com/?p=107 Read More »]]> It is a well known fact in mathematics that the product of two Gaussian functions is also a Gaussian function. In this post I want to present this result for future reference for me and for anyone who might find it useful.

The product theorem for Gaussian functions states that the product of two overlapping Gaussian functions is also a Gaussian function and determines the center and width of the resulting function in terms of the parameters of the two original functions.

To illustrate the identity, consider a Gaussian function of the form G_i(x)=A_i\exp[-(x-\mu_i)^2/2\sigma_i^2], where \mu_i, \sigma_i and A_i, correspond to its center, width and amplitude, respectively. The result of the product of two Gaussian functions G_1(x) and G_2(x) with different amplitudes, widths and central positions, G_3(x) = G_1(x)G_2(x), is equal to

G_3(x) = A_1 A_2\exp\left(-\frac{(\mu_1-\mu_2)^2}{2(\sigma_1^2+\sigma_2^2)}\right)\exp\left(-\frac{(x-\tilde{\mu})^2}{2\tilde{\sigma}^2}\right)\,,


where the centroid is given by

\tilde{\mu} = \frac{\mu_1\sigma_2^2+\mu_2\sigma_1^2}{\sigma_1^2+\sigma_2^2}\,,


and the width by

\tilde{\sigma}^2=\frac{\sigma_1^2\sigma_2^2}{\sigma_1^2+\sigma_2^2}\,.


The theorem shows that the result of the product of two Gaussian functions is a new Gaussian function of width \tilde{\sigma}, centered in the position \tilde{\mu}, whose amplitude strongly depends on the factor \exp\left(-(\mu_1-\mu_2)^2/2(\sigma_1^2+\sigma_2^2)\right). In addition, the resulting function is narrower than either of the two original Gaussian functions, and its center lies within the interval (\mu_1,\mu_2). Notice that the above result can be further simplified if we consider the scenario where the Gaussian functions are centered in different positions but have the same width. If we define \sigma_1 = \sigma_2 = \sigma, the centroid simplies to \tilde{\mu}= (\mu_1+\mu_2)/2, whereas the width is given by \tilde{\sigma}^2 = \sigma^2/2.

Examples

The next figures show two representative cases where two different Gaussian functions with different and equal widths are multiplied. In both cases the result is a Gaussian function narrower than the original functions centered in between the two original centroids, \mu_1 and \mu_2.

ProductTheoremForGaussianFunctions_001

ProductTheoremForGaussianFunctions_002

Additional information

  • E. Wolf, J. T. Foley and F. Gori, "Frequency shifts of spectral lines produced by scattering from spatially random media," J. Opt. Soc. Am. A, 7, 173, (1990)
]]>
How to connect (successfully) a reprap discount full graphic smart controller to a 3Drag 3D printer http://www.opensourcelab.salazarserrano.com/how-to-connect-successfully-a-reprap-discount-full-graphic-smart-controller-to-a-3drag-3d-printer/ http://www.opensourcelab.salazarserrano.com/how-to-connect-successfully-a-reprap-discount-full-graphic-smart-controller-to-a-3drag-3d-printer/#comments Sat, 19 Mar 2016 16:21:57 +0000 http://www.opensourcelab.salazarserrano.com/?p=73 Read More »]]> After spending some hours reading hundreds of posts, comments and blogs, finally I have been able to connect a reprap discount full graphic smart controller to my 3Drag printer.

According to my experience, there is no clear information on how to connect the controller to that specific printer model. For that reason, I decided to write this post in order to show the problems that I have encountered during the process and above all the successful result.

To start, you should have the following components.

Materials

  • 3Drag 3D printer (board version 1.2)
  • RAMPS1.4 12864 LCD Display Controller Kit For 3D Printer (I bought this in bangood.com)
  • 4 x 10 pin Dupont connector (for instance this on aliexpress)
  • 20 x F-F jumper wire connector (for instance this on aliexpress)
  • PC with Arduino IDE version 1.0.5 installed

Since the LCD Display Controller Kit For 3D Printer provides a connetor that is not compatible with the 3Drag pins, you have to build your own cable according to the following table that indicates the pin correspondence between the two devices.

pin_table

I have to thank the Velleman K8200 support forum, in particular to the user mpoor who strongly believes on the open source principle. Without his contribution on Jan 10, 2014, it would have been impossible for me to build the cable.

There are different ways to make the cable. A first approach is to buy a commercial one; unfortunately, in open-electronics.org they sell the full kit with the adapter for 3Drag not assembled . The next easiest (and more elegant) alternative is to adapt Dupont individual wire connectors to 10 pin connectors. You could use individual cables, but I didn't like the fact that the cables may disconnect eventually.

To build the cable, remove the individual connectors in each F-F jumper cables and use the 10 pin connectors, one for each EXT terminal and two for the 3Drag circuit board. When finished, the cable should look like this

cable_connected

Ok. Once we have the cable, let's proceed to upload the firmware to the 3Drag board. The steps are the following:

  1. Download the Marlin firmware for 3Drag version V1.1 from the webpage and unzip the file.

  2. Open the file Marlin.ino using Arduino IDE version 1.0.5. Attention! I recommend to use this specific version. I have spent a few hours trying to upload the firmware using a newer version of the Arduino IDE without success.

  3. Select card Mega2560 or Mega ADK in Arduino IDE.
    ArduinoIDE_Card_selection

  4. Select the config.h file and make sure that the TEMP_SENSOR lines have the following values

#define TEMP_SENSOR_0 5
#define TEMP_SENSOR_1 0
#define TEMP_SENSOR_2 0
#define TEMP_SENSOR_BED 5

  1. Comment line 343

#define ULTIMAKERCONTROLLER //as available from the ultimaker online store.

  1. Uncomment line 358

//#define REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER

  1. At this point you can save and Verify the code. If you have an error message, you are in the right track. The error message indicates that the library u8glib used to control the graphic controller is required and has not been added.

  2. Go to the webpage and download the u8glib library. I have used the 1.18. version which was released very recently.

  3. Import the library, u8glib_arduino_v1.18.1.zip , in Arduino IDE
    ArduinoIDE_Add_library_u8glib

  4. Add #include <U8glib.h> at the beginning of the file config.h
    ArduinoIDE_Include_u8glib

  5. Verify code. At this point you should have no errors after compilation.

  6. Short the JPROG pins together with a jumper.

  7. (optional) By default, the controller language is Italian. If you want to change it, go to the file tab language.h and change the last digit in the line:

#define LANGUAGE_CHOICE 7  // Pick your language from the list above

According to the following table:

Language Code
English 1
Polish 2
French 3 (awaiting translation!)
German 4
Spanish 5
Russian 6
Italian 7
Portuguese 8
Finnish 9
  1. Upload code to board.

  2. Disconnect JPROG jumper.

  3. Power off printer.

  4. Connect LCD controller to 3Drag using the cable built previously.

  5. Turn on printer. Happy printing!!!

What can go wrong?

I had a hard time uploading the firmware. At some point, after double-checking the cable, I had the following image displayed on the LCD screen.
LCD_problem

"It has to be a software rather than a harware problem", I thought. Fortunately, after using an older version of the Arduino IDE, everything worked.

My advice is, avoid using the latest version of the Arduino IDE to upload the firmware, and use an older one; for example version 1.0.5.

Additional information

The following resources where very helpful:
* Gilles Simon blog Velleman k8200 Usage / Upgrade / Hacking
* Velleman K8200 support forum. Topic: LCD help

]]>
http://www.opensourcelab.salazarserrano.com/how-to-connect-successfully-a-reprap-discount-full-graphic-smart-controller-to-a-3drag-3d-printer/feed/ 4
How to communicate with Arduino using a command table http://www.opensourcelab.salazarserrano.com/how-to-communicate-with-arduino-using-a-command-table/ Tue, 06 Oct 2015 17:49:27 +0000 http://www.opensourcelab.salazarserrano.com/?p=7 Read More »]]> There are thousands of examples in the web showing how easy is to communicate with an Arduino board using the serial port. In this post, I would like to go one step forward and show how to communicate using a command table which is a method used by many commercial devices that allow communicating effectively and efficiently using the serial port.

A command table is a dictionary of instructions that can be divided into two categories: commands and queries. The first category corresponds to a direct order such as "move servo motor connected to pin 3, half-turn". The second type of command is used to ask information to the device about its status; for example the state of a digital variable, the value of an ADC or the identification string that contains relevant information about the device and its manufacturer.

In the next sections, I will show how to control the Arduino UNO digital pins using a command table composed of N commands. The code presented here can be easily extended to other Arduino functions that allow to control servo motors, stepper motors and to retrieve information from ADCs, among others.

Commands

In general, a command has the following structure:
Command:subCommand1:subCommand2...subCommandN:Value
Note that the command is composed of a set of substrings separated by the character ":". The principal instruction, Command, can be followed by any number of subCommands. The combination of strings Command:subCommand1:subCommand2...subCommandN is unique and corresponds to a very specific order that can control only a single degree of freedom of the device every time is sent. The value of the variable to control is specified in the last string: Value.

Examples:

  • SERVO:POSITION:120 (move servo to position 120º)
  • SERVO:SPEED:5 (set servo speed to 5)
  • SERVO:PORT1:OFF (turn off servo connected to port 1)

In some occasions, a single command may contain more than one variable so that the command string is Command:subCommand1:value1:subCommand2...subCommandN:valueN.

The instruction:

  • SERVO:PORT:1:POSITION:135 (move servo in PORT 1 to position 135º) is an example where is specified the SERVO channel (1) and its position (135º).

From my experience, a dictionary composed of two subCommand commands is more than enough to implement a large variety of functions in your device.

Queries

A query has the following structure:

Command:subCommand1:subCommand2...subCommandN?

The instruction is similar to a command; however, it has a question mark at the end to indicate that we are asking for information. From the query is returned the value that was previously specified for the instruction Command:subCommand1:subCommand2...subCommandN:Value (or its default value). As in the command case, a query may also contain more than one variable.

Examples:

  • SERVO:POSITION? (what is the position of the servo?) >> 358
  • SERVO:PORT1? (is the servo in port 1 active?) >> FALSE

A query command can be used also to retrieve information of the device such as its manufacturer, model, version among others. In may commercial devices the string "*IDN?" is reserved to retrieve this type of information.

  • *IDN? >> Servo control from command table - totesalaz@gmail.comnLuis Jose Salazar S. - 2015

Since the PC will receive an answer from the device to the command "*IDN?" only if the connection is successful, this query is typically sent to test if the communication is established correctly.

How to control an Arduino using a command table

The following code allows turning on/off any of the digital pins (0 to 13) using a command sent through the serial port. If you don't have any circuit to test the different ports, just used the built-in LED in port 13. In this example the dictionary is composed of three, not case-sensitive, instructions:

Instruction Task
pin:n:state:[0|1] sets pin n to the state [HIGH|LOW]
pin:n:state? queries the state of pin n
*idn? retrieve device information

The next code is based on the example SerialEvent that can be found on the Arduino web page. The function SerialEvent is called every time data is available in the serial port buffer. To start, open a new file and write the following lines to initialize the required variables

String commandString = ""; // a string to hold incoming data
boolean stringComplete = false; // whether the string is complete
int commandSeparator[] = {0,0,0};
String commandSplitted[] = {"","","",""};
boolean pinStatus[] = {0,0,0,0,0,0,0,0,0,0,0,0,0};
int ledPins[] = {13,8,9,10};
String pinState[] = {"LOW","HIGH"};

The commandString variable stores the incoming data from the serial port, whereas stringComplete changes to true every time string sent is complete.

The next two variables, commandSeparator and commandSplitted, are used to store the position of the separation character ":" within commandString and from this information the commandString is separated into substrings that are stored in the commandSplitted array.

The array pinStatus is used to determine the status of each pin. In this particular example, four pins can be controlled. By default, each pin is initialized to zero (LOW state).

After defining the global variables, copy the following lines corresponding to setup() and loop() functions.

void setup() {

// Open serial communications and wait for port to open:
Serial.begin(9600);
// reserve 200 bytes for the inputString:
commandString.reserve(20);
pinMode(13, OUTPUT);
Serial.println(">>");

} //End setup

void loop() {

if(stringComplete){

// Serial.println("Command received: " + commandString);

commandSeparator[0] = commandString.indexOf(":");
commandSeparator[1] = commandString.indexOf(":", commandSeparator[0]+1);
commandSeparator[2] = commandString.indexOf(":", commandSeparator[1]+1);

commandSplitted[0] = commandString.substring(0,commandSeparator[0]);
commandSplitted[1] = commandString.substring(commandSeparator[0]+1,commandSeparator[1]);
commandSplitted[2] = commandString.substring(commandSeparator[1]+1,commandSeparator[2]);
commandSplitted[3] = commandString.substring(commandSeparator[2]+1);

//pin:[pin number]:STATE:[0|1]
if(commandSplitted[0]=="PIN"){
if(commandSplitted[2]=="STATE"){
pinStatus[commandSplitted[1].toInt()] = commandSplitted[3].toInt();
//digitalWrite(ledPins[commandSplitted[1].toInt()],commandSplitted[3].toInt());
digitalWrite(commandSplitted[1].toInt(),commandSplitted[3].toInt());
Serial.println(">> Pin "+commandSplitted[1]+" set to "+pinState[commandSplitted[3].toInt()]);
}
if(commandSplitted[2]=="STATE?"){
Serial.println(commandString+"\n>> "+pinState[pinStatus[commandSplitted[1].toInt()]]);
}
}

if(commandSplitted[0]=="*IDN?"){
Serial.println(commandString+"\n>> Control Arduino using command table\nLuis Jose Salazar S. - 2015\ntotesalaz@gmail.com");
}

commandString = "";
stringComplete = false;

}

} //end main
/*
SerialEvent occurs whenever a new data comes in the
hardware serial RX. This routine is run between each
time loop() runs, so using delay inside loop can delay
response. Multiple bytes of data may be available.

Function taken from:
https://www.arduino.cc/en/Tutorial/SerialEvent
*/

void serialEvent() {

while (Serial.available()) {
// get the new byte:
char inChar = (char)Serial.read();

// add it to the inputString:
if (inChar != '\n')
commandString += inChar;
// if the incoming character is a newline, set a flag
// so the main loop can do something about it:
if (inChar == '\n')
stringComplete = true;
}

commandString.toUpperCase();

}//END serialEvent

Usage example

Open the serial monitor in the Arduino IDE (Ctrl+Shift+m) and used the commands pin:13:state:1 and pin:13:state? to turn on the LED on pin 13 and to retrieve information about its status. The serial monitor should look like the following image.

commandSequence

The code presented has been tested on an Arduino UNO board and on a DFRobot Romeo V1.0 board.

]]>