Friday, 23 October 2015

Arduino: Read Instruction From Serial

When using Arduino, parsing serial data and converting it to something usable is way harder than it seems.


While this functionality is specially useful as it allows your computer to talk with the Arduino easily, a quick search on google will give you thousands of very different solutions. The one exposed here is just another one that is working perfectly for me.

The instruction:

The idea is to set the position of three servos by serial and also be able to change other parameters.
The instruction, then, must be composed from an instruction name and the parameters, for example, to move the three servos:

MOVE 120 23 90

And, if we also want to switch on a light, the instruction could be:

LIGHT ON

How do we get the Arduino to know that we want the servos to move and then switch on a light?

 

Arduino Read Instruction:

Code:
/*
JMG OCTOBER 2015
This script is made up from snippets found in stackoverflow and other
google results
*/

void setup()
{
  // open serial port at 115200 baud
  Serial.begin(115200);
}

String complete_instruction[4];  // will contain the decoded instruction (4 fields)
void loop()
{
  
  while(!Serial.available()) {}  // if there is nothing on serial, do nothing
  int  i = 0;
  char raw_instruction[25];
  while (Serial.available())
  {  // if something comes from serial, read it and store it in raw_instruction char array
    delay(10); // delay to allow buffer to fill
    if (Serial.available() > 0)
    {
      raw_instruction[i] = Serial.read();
      i++;
    }
  }
  if( strlen( raw_instruction ) > 0 )  // if a new raw_instruction has been read
  {
    // clean raw_instruction before decoding (overwrite non filled array positions with empty spaces)
    for( int n = i; n < 25; n++ ) { raw_instruction[n] = ' '; }
    // decode the instruction (4 fields) (iterator n = field, iterator j = character)
    int j = 0;
    for( int n = 0; n < 4; n++ )
    { 
      while( j < 25 )
      {
        if( raw_instruction[j] == ' ' )
        {
          j++;
          break;
        }
        else
        {
          complete_instruction[n] += raw_instruction[j];
        }
        j++;
      }
    }
    // print decoded instruction by serial
    for( int n = 0; n<4; n++ )
    {
      Serial.println( complete_instruction[n] );
      // clear field after using it
      complete_instruction[n]="";
    }
  }
  delay(50);
}

The summary is that you can send by serial something like "A B C D" (using space as delimiter) and the variable complete_instruction will contain {A, B, C, D}. A,B,C,D can be any kind of data of any length you want, for the instruction MOVE 120 23 90, it will return {"MOVE", "120", "23", "90"}. For the second instruction LIGHT ON, it will return {"LIGHT", "ON", "", "" }.

This way, now you just need to set several if conditions to check if the instruction says "MOVE", "LIGHT", "KILL" or whatever, and if it does, check the remaining parameters (you can use toInt() or toFloat() for numeric values).

My experience with this script is that it works as intended and does not cause memory problems. But I do not have enough knowledge about C to assure that it will not crash your script (from what I've read, String variables together with low RAM space seem to give problems.) Just take it into account if something very weird is happening. (code updated, memory problem solved?)


Bye!

Thursday, 10 September 2015

FreeCAD: Intersection Between Shapes

Hi!

This is a small script that will find intersection volumes between the selected shapes, for example, given two cubes and a sphere, this is the result:


It gives some transparency to the original shapes and also displays intersection volume at the report view.

The code is:

# JMG 2015
object_list = []
for obj in FreeCAD.Gui.Selection.getSelectionEx():
  obj = obj.Object
  object_list.append( obj )

for n in range( len(object_list) ):
  object_A = object_list[n]
  for i in range( len(object_list) ):
    if i <= n:
      pass
    
    else:
      object_B = object_list[i]
      common = object_A.Shape.common( object_B.Shape )
      if common.Volume > 0.0:
        FreeCAD.Console.PrintMessage( '-Intersection- ' + object_A.Name + ' with ' + object_B.Name + '\n')
        FreeCAD.Console.PrintMessage( 'Common volume: ' + str( common.Volume ) + '\n' + '\n' )
        
        intersection_object = FreeCAD.ActiveDocument.addObject( 'Part::Feature', 'Intersection_Volume' )
        intersection_object.Shape = common
        intersection_object.ViewObject.ShapeColor = ( 1.0,0.0,0.0,1.0 )
        object_A.ViewObject.Transparency = 80
        object_B.ViewObject.Transparency = 80

Thursday, 6 August 2015

FreeCAD: Double Slider Mechanism Animation

Since few days ago, this blog is two years old, and, also, last month it crossed the 4000 views/month barrier.
I was thinking about a way of celebrating this events, and last night I saw a .gif image about a flat mechanism at which I could be staring the whole day:


I don't know its exact name, but "double slider mechanism" seems appropriate. It belongs to the family of flat, four bar linkage mechanisms, and, possibly, there is no real use for this one. But it moves very smoothly, with the outer end of the rotating arm drawing some kind of ellipse.



The kinematics of this one are not too difficult (none of the family of four bar linkage mechanism are), and for the animation I have solved it in an analytical way.

The code:


# Javier Martinez Garcia    August 2015   GPL V2.0

from PySide import QtCore
from math import sin, cos, radians

# retrieve the objects from the document
slider_x = FreeCAD.ActiveDocument.getObject("Pad003002")
slider_y = FreeCAD.ActiveDocument.getObject("Pad003001")
arm = FreeCAD.ActiveDocument.getObject("Pad002001")


# store initial placement (needed to restore initial position)
slider_x_placement = slider_x.Placement
slider_y_placement = slider_y.Placement
arm_placement = arm.Placement

# store object placements in a new variable
r_slider_x_pl = slider_x.Placement
r_slider_y_pl = slider_y.Placement
r_arm_pl = arm.Placement


def reset():
  # function to restore initial position of the objects
  slider_x.Placement = r_slider_x_pl
  slider_y.Placement = r_slider_y_pl
  arm.Placement = r_arm_pl


# In this mechanism, "i" represents the angle of the rod in degrees
i = 0

# update function calculates object position as f(i) and increases i
def update():
  global i
  alpha = radians( i )
  x = 150.0*cos( alpha )
  y = 150.0*sin( alpha )
  slider_x.Placement = FreeCAD.Placement( slider_x_placement.Base + FreeCAD.Vector( 150-x, 0, 0 ),
                                          slider_x_placement.Rotation )
  
  slider_y.Placement = FreeCAD.Placement( slider_y_placement.Base + FreeCAD.Vector( 0, y, 0 ),
                                          slider_y_placement.Rotation )
  
  arm.Placement = FreeCAD.Placement( arm_placement.Base + FreeCAD.Vector( 0, y, 0 ),
                                     FreeCAD.Rotation( FreeCAD.Vector( 0,0,1), i))
  # update the scene
  FreeCAD.Gui.updateGui()
  # increase mechanism input position
  i += 1


# create a timer object
timer = QtCore.QTimer()
# connect timer event to function "update"
timer.timeout.connect( update )
# start the timer to trigger "update" every 10 ms
timer.start( 10 )



Download the .fcstd model and animation script here, on github.


Have fun!