Posts

Showing posts from 2018

Android app for block assembly

Image
Collaboration with a local company paved the way to the development of an Android app to represent 3D models that are built by joining a set of 3D blocks. Each block is made of a set of layers of parts machined by a 3-axis CNC machine out of foam sheets.  The manufacturing process is more or less outlined in this video:


The problem here was for work workers to have an easy way to know the assembly of the parts without the need of having a computer screen. Given each one of them happens to have a smartphone that seemed the obvious choice. And that is the result (portrait video warning):


As you can see in the video each block has a red number hovering it. And the low polygon count of the 3D mesh is just to ease on the amount of data transmitted and not a limitation of the program itself.

I wanted to make this tool useful for other users, so the file format is a regular ZIP file with .mim extension that contains three different elements: one binary STL file for each block, first one name…

Speeding up nesting calculations

Image
Algorithms for free-form nesting has a cost that depends on the complexity of the polygons that represent the parts to be placed. The more complex (the more points) these polygons are, the longer the computing time.

One might accept a slight waste of material if that can speed up the nesting significantly. The obvious idea is to simplify the polygons and for that task, there is a considerable amount of algorithms available.

However, there is a bit of a catch in our case: If the simplification process renders a new polygon that is slightly smaller than the original one, this could be a problem as the actual part will not fit in the space allocated for it by the nesting software.


The simplification performed by the red arrow creates a new polygon that, while it has fewer points, it cannot contain the original polygon inside and so it would be a bad idea to use the new for nesting purposes. On the other hand, the green arrow simplification does create a new polygon with fewer points that…

Another stepper motor

Image
I was looking for a simple mock-up to be used to explain the operation of a stepper motor to my students. This is what I came up with:
Just four coils on the edges of a plus-sign shape, where the two horizontal coils are connected in serial in a way that they create opposite polarity fields. Same arrangement for the two vertical coils. So we end up with a vertical and a horizontal coil. Once this is set, we use a pill-shaped magnet that will align with the vertical or horizontal magnetic field created by the coils.


What is even better, current is ramped-up on one axis while it is ramped-down on the other, a smoother movement can be achieved (aka micro-stepping).

Of course, that pill-shaped magnet will look familiar to you if you ever have been to a chemistry lab as they are used for magnetic stirrers.

So for powering this "motor", I have used a stepper motor driver A4988 and as you can see, if field changes are fast enough, the rotor can spin and even stir a liquid.

Cleaning a Java Area object

Image
To determine the projection of a given 3D part, I am slicing the parts in a sequence of cuts at different heights. Each cut creates one or more perimeters or rings. The approximated desired projection is obtained by performing the union of each cut.   The image above represents the output perimeter in red color, and the number tells me there is just one. Each perimeter start is marked by a circle and its end by a square. The image below, however, does have two different output perimeters, that is, the vertical projection can be decomposed in two different disconnected areas.
 I am coding in Java and using the Area class from java.awt. The main reason is that the class does include a method to do the union of areas.  However, after some weird results and some debugging, I realized the output of such a union method is not always clean. Sometimes the output is polluted with some additional paths that are not really useful or valid. In my case, I was getting some paths consisting in just…

When the top of a cut is not that simple

Image
In the previous entry, I discussed how the silhouette of a cut, which would be a closed polygonal line, could be turned into a triangulated surface so these triangles could form a closed lid for the sliced triangular mesh.

But there are many cases when that surface is not that simple as a closed polygonal line. So the general case is a little bit more challenging. Let us see some sample cases in the image below:
So the simple case I talked about would be the circle label with the number 1. But the rest of the cases 2,3, and 4 are a bit trickier.

Case 2: We have a hole inside the exterior cut. That would be the result of cutting a tube-like shape. Here we do not want to cover the whole circle as in case number 1, but we want to keep the hole uncovered. Luckily, the Earcut library handles the cases where the external polygonal line encloses an area with one or more holes. But we still need to tell the library which points delimit the external perimeter and which ones are the perimeter of…

Closing the hole after cutting a triangular mesh

Image
Once a triangular mesh is cut by an intersecting plane, the resulting halves are no longer a water-tight mesh, because some holes are created by the cutting action of the plane.

In the image here, the volume of a [solid] hat was cut by a vertical plane, splitting it in two. In order for this half to be back a 2-manifold triangular mesh, all the triangles with black edges have been added to create a flat surface that covers what the cut plane would otherwise reveal (the inside of the hat).

The problem is how given a certain polygon, like the red polygonal line here, a collection of triangles can be created to cover entirely all the area delimited by such a perimeter (aka polygon triangulation).

The problem gets even more interesting once we consider that some meshes can present holes inside these perimeters obtained after cutting the mesh with a plane.

Fortunately, there are different algorithms to solve that problem, and I will settle with the so-called Ear clipping. Fortunately, the…

Cutting a triangular mesh and keeping the pieces

Image
When we use a plane to cut a triangular mesh, several cases can be considered. If there is a non-null intersection between the plane and a given triangle, there are mostly five different cases:


The plane contains one vertex of the triangle: not very useful for cutting purposes if the rest of the triangle lays above the cutting plane and we want to keep all that is below.The plane contains two vertices of the triangle, then the intersection is a line segment but we will only keep that triangle if the other vertex is below the cutting plane.The plane contains three vertices of the triangle: that is a keeper.The plane does not contain any vertices of the triangle, but there is an intersection with two of the edges: this is what we will talk about today here.A fifth case can be considered when the plane contains one vertex but the two other are on opposite sides of the plane, and it can easily be incorporated to the previous case. The following picture shows us a couple of triangles of a m…

Enterprise WPA and ESP32

Image
I recently gave Adafruit's IO service a try. You can get a few data sensor feeds recorded and graphed on the web. They have a somehow limited version for free and a more complete offering for paying customers.

A current project required to record a few sensor samples per minute and Adafruit's free service seemed to fit the bill. I was using ESP32 with BME280 sensor to gather humidity, temperature, and atmospheric pressure and to store it somewhere in the cloud.

I was testing this on campus, where we have a corporate wifi network that uses a Radius server for PEAP authentication. I assumed ESP32 could only use WPA with a pre-shared key but I was wrong. I googled around and found that some people were using it with Eduroam. Eduroam is a European-wide Academic wifi network and it is present in our campus too, so what harm was in trying?

I found this code that might work so I tried it out, and it did work at the first try! Brilliant!


But there were a couple of details that did not…

Improving dcservo accuracy

Image
Not being an expert in motor control, I created dcservo project to make a basic platform to create cheap servomotors that could replace stepper motors on certain systems, like 3D printers. I chose to implement a full PID controller but that might have been a bit overkill.

I was talking today to a more knowledgeable colleague who asked me why I needed a PID. My answer was that without the integral action I was getting a significant position error in the steady state, and the derivative action, though a really small value, was needed to keep the system from overshooting. However, he suggested me to focus only on a simpler, proportional controller with a twist: most of my position error is coming from the fact that there is a dead zone where motor does not respond to control action.

It is true, though the motor will move faster the higher the PWM value it is applied to the motor drive, it is also true that low values (between 1 and 50 in my test system) do not cause the motor to move.

I …

Marlin's Bézier vs sinusoidal speed profile

Image
Bugfix-1.1 branch of Marlin firmware does include a fifth-degree (quintic) Bézier polynomial for the speed profile. If you want to use it enable S_CURVE_ACCELERATION define. You can have a look at the source code, luckily well commented so we can understand where it is coming from.

I was curious to check how different that curve was from the sinusoidal speed profile I mentioned in a previous entry. Although the source code comments are very thorough on how they reach their expression, in layman's terms is something the speed along a move is

s(t)= (6*t5-15*t4+10*t3)*|v1-v0|+v0
where v1 is the final speed, v0 is the initial speed and t varies from 0 to 1 to trace the motion.

I was surprised on how it looked quite similar to the sinusoidal case, so I went on and did a comparison with the sinusoidal s-curve:

And the result is that there is not much of a difference so I don't expect much different behavior when using one or the other. 

Too much pressure

Image
A local company built a ram extruder for us. Not very different from a syringe extruder but massive in terms of size and pressure.

Our assumption was that parts had been sized properly, so we did not question the 8.7Nm NEMA34 stepper, nor the 5mm-thick acrylic tube with a 60mm internal diameter. After all, it was not the first time they have built a similar contraption to be used with clay.

Unfortunately, though we try to be very gentle on the extrusion test, we manage to break the tube in a few minutes. Luckily for us, it cracked without sending debris around. We did not expect that at all and when we contacted the seller all sorts of questions were asked, questions we did not have an answer for, like "what was the operating pressure?". I did not have a clue as I was just trying to get the stepper rotating very slowly. Their diagnose was we did it wrong as we set the nominal current (6A) for the stepper driver.

From torque to pressure So I was determined to figure out how …

One table to run them all

Image
In previous entries, I have delved into the idea of using different shapes for the speed pattern for a motion using steppers and have presented how the timing can be based on a look-up table. Such a table would be pre-calculated and flashed with the firmware. But a single table provides a pattern for a given max speed, acceleration, number of steps and speed shape.


You can use that for timing the steps of the motor and it will accelerate properly as many steps as entries on your table. But it won't be practical if we want to change any of these parameters for other movements.
The idea I am not yet sure this works as expected, but first tests look ok, finally, as it took me a while to figure this out.
I have created a lookup table as the graph above, where each entry contains the delay needed for each step, for a movement of 1000 steps total, where speed will increase to 2Π while time goes till 2Π too. Maximum speed for each different motion pattern will be different though, but th…

More experiments with motion curves for steppers

Image
Though I have been experimenting with Arduino, I realize that as soon as the computing requirements grow a bit the results quickly show the processor is actually slowing down my results. So now I am using a DOIT Espduino featuring an ESP32 processor that makes that sensitivity go away.

It was a bit of a challenge to get this board to work with CNCshield v3. The culprit was resistor R1 (enable pin) that would affect the booting capability of the ESP32. Once R1 was removed (brutally destroyed with a wire cutter in my case) the problem was gone and I could upload and run code with the Arduino IDE.

I created a simple program that uses some pre-calculated delays to perform the motion using different expressions for the acceleration. Four have been used and shown in the video below:

Uniform acceleration a=kSinusoidal acceleration a=1-cos(t)Exponential a=(e^(cos(t/2)-1)*sin(t/2))/2Exponential2 a=(e^(-(t-sin(t))/pi)*(1-cos(t)))/pi The expectation from a former entry was that adding the exponen…

Stepper motor step signal timing calculation

Image
While we use stepper motors in many devices, the timing of the step signals is not always well understood. Most of us can see how a fixed speed is a bad idea unless the speed of motion is really slow, but it is fixed speed what is really to generate with simple code. You just can use the Arduino Blink example to send a fixed frequency of pulses to a stepper motor driver. If too slow, just reduce the delay value.

But for most real-life applications variable speed controls will perform better. These systems will speed up the motor to a given maximum speed and it will slow it down to stop at the desired step count. But understanding the math behind this process is sometimes not obvious.

Let us start with the simple case of the so-called trapezoidal speed motion profile. Here motion takes place in three phases: acceleration, constant speed (cruising) and deceleration. But the point is how can our code create such a behavior.

Stepper motor drivers usually accept two signals to control moto…

A better stepper drive s-curve?

Image
One of the not so desirable features of stepper motors is the fact that output torque falls quickly with shaft speed. This is one of the reasons these motors cannot reach high speeds.

So I was thinking that when we use a s-curve to drive them, instead of choosing a symmetric one, where acceleration is is max in the middle of the acceleration section (as speed raises), I could try one where higher accelerations happen to lower speeds. However, in order to still keep the s-curve shape instead of a sawtooth, I would use the following expression: 1-e^(cos(t/2)-1)and it is shown in blue in the graph.

This will produce a s-curve shape, but modulated with the exponential behavior. Resulting signal will grow faster as the beginning (where more torque is available) and more slowly at the end (where faster speeds are reached and less torque is available).

A first test shows me that, for a bare motor, a faster move can be achieved, more reliably (no missed steps), using this pattern instead of …

How to get sinusoidal s-curve for a stepper motor

Image
After some experimentation, and delving a bit into the math of motion, I realized there can be a significant difference on the motion of a machine by just making small changes.

A common and popular approach to smooth one axis of motion is to use a trapezoidal speed pattern, where acceleration and deceleration are uniformly accelerated movements (aka constant acceleration motion) separated by a portion happening at cruising speed.

The problem comes with the fact that, while that approach is simple to understand and to code, it does contain sudden changes in the acceleration, that show as spikes on the acceleration derivative, called jerk. These sudden changes in the acceleration translate into undesired vibration in our machines.

Most of that can be eliminated by selecting a motion pattern that does not contain sudden changes of acceleration. If we chose a mathematical function for our speed whose second derivative is continuous, then we reduce system vibration quite a lot. One may thi…

Moving code from ESP8266 to ESP32

Image
A while ago I made a mashup of Dan Royer's code CNC 2 Axis Demo with my own code for trapezoidal motion stepper and servo control for ESP8266.

I assumed porting the code to the ESP32 would be trivial, and that was true for the most part: changes like library name being Wifi.h instead of Wifi8266.h were not a problem. UDP now does not like multicharacter writes but you can use print instead. So far so good.

However, when it came to the interrupt code I was stuck with the stepper interrupt causing an exception sometimes. And to make things weirder, the servo interrupt worked flawlessly (both of them had the IRAM_ATTR directive if you ask me).

Going little by little, I could narrow down the culprit to a floating point operation during the interrupt, that would cause problems sometimes but not always. Browsing around I found this post. Where the solution was simple: do not use floats within the interrupt routines but doubles. The reason was the float calculation would be performed by…

Servo control on ESP32

Image
One of the things that do not work the Arduino way in the ESP32 so far is the PWM generation using analogWrite() command. There is, however, a library to handle PWM signals using timers, so up to 16 PWM signals can be handled.  You can find fine examples like this one.

However, I wanted to use timers in my project and I wanted to have a clearer view of what was going on, so I decided to handle the PWM timing myself. Here you have an example of how to handle a single servo using a timer. Same timer and routine could be extended to handle more output pins in a similar fashion, but I just needed one here.


It is just a simple sketch that moves the servo back and forth using a sin function to get this motion easily, ranging the signal pulse width from 600 to 2200 microseconds.
This is the end result:


All in all, I am impressed with the simplicity and power of the ESP32 and the great Arduino-esp32 code. Kudos to Espressif.

ESP-32 in UNO format

Image
A few years ago, the IC manufacturer Expressif surprised many of us with their ESP8266 SoC.  A 32- bit processor, running at 80 or 160 MHz with built-in wifi support. It proved to be a very interesting proposal and, eventually, a versión with the same form-factor as the Arduino UNO was made available (which opened compatibility with many available shields).

The same manufacturer developed the next versión, a new and improved SoC this time with Bluetooth and Wifi support, more I/O pins and low-power modes.

I almost forgot, the main reason these chips got successful in the DIY world was that the price was right and a powerful SDK was made available, that eventually led to a group of enthusiasts to create an Arduino-compatible library that made possible to use Arduino code and Arduino IDE to develop with these chips.

A few weeks ago I was contacted to see if a wifi-enabled stepper motor controller board could be done with an ESP. As that is something I had already done the obvious answer…

Testing sinusoidal S-curves

Image
My main goal here was to keep a simple mechanism to be easy to calculate and able to be included into 8-bit firmware like Marlin. Which by the way already has support for s-curves for quite a while (at least on this mod for Ultimaker).

So the goal is to have a function f(t) that will map the speed at each given moment but in a way that the maximum speed will be reached at the same time as it would using a uniform acceleration, so the rest of the math and motion planning is not affected. In doing so, the peak acceleration is going to be higher than that when using uniform acceleration. However, if that is a problem it is ok to reduce the maximum acceleration so the system can work flawlessly.

I have tested a couple of functions, both based on sinusoidal functions, the former is:
f(t)=V*(1-cos(PI*(t/t1))/2 (where V is max speed and t1 marks the end of the S-curve ramping up). It is the dotted-green curve below. The shape of the acceleration for this speed pattern is the dotted-pink curv…

Sinusoidal functions for s-curve motion

Image
While trapezoidal speed motion pattern is good and well. It is well known that the sudden changes in acceleration it requires, also known as jerk (jerk being the time derivative of the acceleration) is the cause of trouble in many machines.


That first model can be improved with another acceleration shape that will remove the sudden changes, thus improving the system performance.

However, will there are no sharp edges on the acceleration values, there is still a couple of points where there is a not so smooth change. So the next idea, while still within the use of a sinusoidal acceleration profiles is to change to this other acceleration profile:
This new curve has smoother transitions from zero to any other value, thus no more problems with the jerk. However, we still can think of a combination of this latter case and the initial one, where corners are smoothed out using a sinusoidal: That is what they suggest in this paper
While I was not eager to use any complex math in my dcservo

Speeding up my CAM

Image
A while ago, I created from scratch a CAM software. It has been consistently working ok with a minor problem of occasional wounds in some parts, which I narrowed down to a bad condition.

But solving the math was only part of the problem. A problem my students found too difficult to crack. So I have to provide them a solution (this was for a ball end mill).


The computing time of the algorithm depends on how many calculations are done. And the brute-force approach of checking every single point, edge and triangle for each sample point is just too slow (but works flawlessly).

I have used a dual approach to speed up the code. On one hand, I am selecting only a few elements to be checked for each vertical scan line, that reduces significantly the number of checks to those that are relevant for the current scan line. The second idea is to write multi-threaded code that can handle different scan lines using a different thread, that in turn will run in a different core of the processor if I d…

I bought a Prusa MK3 too

Image
first layer adjustment). I have been testing each new version of Josef Prusa printers and I am glad at how good and predictable the build process is turning, and documentation is getting better at each new release.

Prusa i3 MK3 is addressing quite a few shortcomings of these type of printers with a good dose of innovation and ingenuity.

I ordered my printers in October 2017 and got it here last Monday. I knew there was a significant waiting time but I was not in a hurry at the time. And it seems to wait has played in my favor as I have received some improvements over the original release (mine are definitely hardened rods). But I  will yet have to wait for a PEI laminated steel sheet.

This time I built the printer by myself: it is more entertained when you have a helper that can double-check the manual, but version 3.0 of the manual is already very good. My only complaint on that front is that although it is clear Prusa Research is doing an effort with a full-color manual in a large …

More SAMD21 M0 weirdness

Image
My assumption was that using Arduino IDE was the quickest and simplest way to venture into the world of 32 bit ARM processors, but I am starting to think otherwise. This post is the second about things not working as expected and time used to figure out what's wrong.

For a motor-controller project, I was testing Allegro's A4950 h-bridge when I realized that while varying motor speed using a PWM signal, sudden torque spikes were happening.

My first idea was that the power supply was to blame, so I replaced it, to obtain exactly the same result.

The code I was running was very simple and on close inspection, I could not find any reason for the observed glitch, that somehow had a periodic nature: one acceleration and deceleration period would work ok and the next one will show three or four torque spikes.

As I was using an Arduino-form M0 board (SAMD21-based) I decided to bring back my trusted Arduino UNO and to run exactly the same code. This time all worked nicely, no sudden ac…