<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Gaugette</title>
    <link>//guy.carpenter.id.au/gaugette/categories/arduino/index.xml</link>
    <description>Recent content on Gaugette</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <atom:link href="//guy.carpenter.id.au/gaugette/categories/arduino/index.xml" rel="self" type="application/rss+xml" />
    
    <item>
      <title>SwitecX25 Quad Driver Tests</title>
      <link>//guy.carpenter.id.au/gaugette/2017/04/29/switecx25-quad-driver-tests/</link>
      <pubDate>Sat, 29 Apr 2017 14:16:00 +1000</pubDate>
      
      <guid>//guy.carpenter.id.au/gaugette/2017/04/29/switecx25-quad-driver-tests/</guid>
      <description>&lt;img src=&#34;//guy.carpenter.id.au/gaugette/resources/2017-04-29/AX1201728SG-closeup.jpg&#34;  class=&#34;right&#34;   alt=&#34;AX1201728SG&#34;  /&gt;


&lt;p&gt;This article demonstrates a modification of the Arduino SwitecX25 driver library
to use a AX1201728SG quad driver chip (equivalent to the X12.017 or VID6606).
This chip offers some significant advantages over driving the motor directly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;it uses microstepping to provide smoother positioning - 12 steps per degree rather than 3.&lt;/li&gt;
&lt;li&gt;it requires only two GPIO pins per motor (plus one global reset pin)&lt;/li&gt;
&lt;li&gt;it protects the microprocessor from the inductive effects of the motor coils&lt;/li&gt;
&lt;li&gt;it places lower current requirements on the microprocessor&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;In the past I&amp;rsquo;ve been unable to find a low-volume supplier for the &lt;a href=&#34;//guy.carpenter.id.au/gaugette/gaugette/2012/01/19/x12-quad-driver-chip/&#34;&gt;X12.017 Quad Driver Chip&lt;/a&gt;,
or any of the functionally identical chips from other manufacturers.  These are the ones I know about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The VID VID6606 Quad Driver &lt;a href=&#34;//guy.carpenter.id.au/gaugette/resources/vid/2009111391612_VID6606%20manual%20060927.pdf&#34;/&gt;(datasheet)&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;The &lt;a href=&#34;http://www.nostm.com&#34; target=&#34;_blank&#34;&gt;NOST Microelectronics&lt;/a&gt; BY8920 Quad Driver &lt;a href=&#34;//guy.carpenter.id.au/gaugette/resources/nost/1428412011616by8290datasheet.pdf&#34;/&gt;(datasheet, in Chinese)&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;The AX1201728SG (by EmMicroe maybe?)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Recently both the AX1201728SG and VID6606 have become readily available in small quantities.&lt;/p&gt;

&lt;h2 id=&#34;the-ax1201728sg&#34;&gt;The AX1201728SG&lt;/h2&gt;

&lt;p&gt;The AX1201728SG is available in single quantities from ebay for a few dollars apiece.
 The one complication is that they are SOP28 surface mount packages, which are
 a little harder to prototype with than DIP packages.
 I bought some drivers, and some SOP28 to DIP28 adaptors so I could mount the drivers on a breadboard
 for testing.&lt;/p&gt;

&lt;img src=&#34;//guy.carpenter.id.au/gaugette/resources/2017-04-29/SOP28-components.jpg&#34;   alt=&#34;AX1201728SG SOP28 Components&#34;  /&gt;


&lt;h2 id=&#34;mounting&#34;&gt;Mounting&lt;/h2&gt;

&lt;p&gt;I haven&amp;rsquo;t worked with SMD chips before, so I had a friend help me mount them.
We used tweezers to apply the paste, and a regular household oven for reflowing.
Very basic, but it worked fine.&lt;/p&gt;

&lt;img src=&#34;//guy.carpenter.id.au/gaugette/resources/2017-04-29/SOP28-mounting.jpg&#34;   alt=&#34;AX1201728SG SOP28 Mounting&#34;  /&gt;


&lt;img src=&#34;//guy.carpenter.id.au/gaugette/resources/2017-04-29/AX1201728SG-pinout.png&#34;  class=&#34;right&#34;   /&gt;


&lt;h2 id=&#34;wiring-it-up&#34;&gt;Wiring It Up&lt;/h2&gt;

&lt;p&gt;Initially I&amp;rsquo;m testing with a single motor on output A.  The wiring is as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;VSS (chip pin 12) to GND&lt;/li&gt;
&lt;li&gt;VDD (chip pins 1 and 15) to 5V&lt;/li&gt;
&lt;li&gt;RESET (chip pin 26) to Arduino pin 10&lt;/li&gt;
&lt;li&gt;CW/CCW A (chip pin 27) to Arduino pin 9&lt;/li&gt;
&lt;li&gt;f(scx) A (chip pin 28) to Arduino pin 8&lt;/li&gt;
&lt;/ul&gt;

&lt;img src=&#34;//guy.carpenter.id.au/gaugette/resources/2017-04-29/AX1201728SG_bb.png&#34;   alt=&#34;breadboard&#34;  /&gt;


&lt;p&gt;&lt;img src=&#34;//guy.carpenter.id.au/gaugette/resources/2017-04-29/X27.168-rear-contacts.png&#34;  class=&#34;right&#34;   /&gt;

The motor connections are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;OUT1A (chip pin 7) to Motor pin 1&lt;/li&gt;
&lt;li&gt;OUT2A (chip pin 6) to Motor pin 2&lt;/li&gt;
&lt;li&gt;OUT3A (chip pin 4) to Motor pin 3&lt;/li&gt;
&lt;li&gt;OUT4A (chip pin 5) to Motor pin 4&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;software&#34;&gt;Software&lt;/h2&gt;

&lt;p&gt;I started with a basic hello-world program to run the motor forward and backwards
so I could work out any setup issues before switching to the more complicated driver software.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;/*
  X12.017 Quad Driver Test
  Drive the motor forward and backwards through 270 degrees
  at constant speed.
 */

const int LED = 13;
const int DIR_A = 9; // pin for CW/CCW
const int STEP_A = 8; // pin for f(scx)
const int RESET = 10; // pin for RESET
const int DELAY = 250; // μs between steps
const int ANGLE = 270; // of 315 available
const int RANGE = ANGLE * 3 * 4;
int steps = 0;
bool forward = true;

// pull RESET low to reset, high for normal operation.

void setup() {
  pinMode(DIR_A, OUTPUT);
  pinMode(STEP_A, OUTPUT);
  pinMode(LED, OUTPUT);
  pinMode(RESET, OUTPUT);

  digitalWrite(RESET, LOW);
  digitalWrite(LED, HIGH);
  digitalWrite(STEP_A, LOW);
  digitalWrite(DIR_A, HIGH);
  delay(1);  // keep reset low min 1ms
  digitalWrite(RESET, HIGH);
}

// The motor steps on rising edge of STEP
// The step line must be held low for at least 450ns
// which is so fast we probably don&#39;t need a delay,
// put in a short delay for good measure.

void loop() {
  digitalWrite(STEP_A, LOW);
  delayMicroseconds(1);  // not required

  steps++;
  if (steps &amp;gt; RANGE) {
    forward = !forward;
    steps = 0;
    digitalWrite(DIR_A, forward ? LOW : HIGH);
    digitalWrite(LED, forward ? HIGH : LOW);
  }

  digitalWrite(STEP_A, HIGH);
  delayMicroseconds(DELAY);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This worked, mostly.  If I leave the motor running for a while I notice that
the needle position drifts, which indicates either missed steps, or
a counting problem.  Increasing the inter-step delay from 250ms to 500ms
resolved that problem, so most likely I&amp;rsquo;m exceeding the (low) torque limit
during the turnaround.  I&amp;rsquo;m not worried about that - once I port the SwitecX25
library I can find a safe set of acceleration parameters to keep it from dropping
steps.&lt;/p&gt;

&lt;h2 id=&#34;adapting-the-switecx25-library&#34;&gt;Adapting the SwitecX25 Library&lt;/h2&gt;

&lt;p&gt;The SwitecX25 library provides an acceleration/deceleration model,
and some higher-level control abstractions.  Importantly, it is asynchronous.
The caller sets a desired step position and then calls the &lt;code&gt;update()&lt;/code&gt; method
as frequently as possible and the library manages the scheduling of the steps.&lt;/p&gt;

&lt;p&gt;One concern I have about supporting the quad driver is the being able to
service the pin transitions quickly enough.
When driving the motor directly we need to update 4
outputs once per step.  With the quad driver we need to pulse the f(scx) line low then high
once per micro-step, which equates to 8 transitions per full step.  It may
turn out to be difficult hit all of the timing deadlines to drive 4 motors at full speed simultaneously.&lt;/p&gt;

&lt;p&gt;My first cut at this is to create an entirely new class &lt;a href=&#34;https://github.com/clearwater/SwitecX25/blob/X12/SwitecX12.h&#34; target=&#34;_blank&#34;&gt;SwitecX12&lt;/a&gt;
which duplicates the key timing code from SwitecX25, with new output logic
and an adjusted acceleration curve.&lt;/p&gt;

&lt;p&gt;The code below zeroes the needle, moves the needle to the centre of the sweep, then
cycles between &amp;frac14; range and &amp;frac34; range.&lt;/p&gt;


&lt;div style=&#34;position: relative; padding-bottom: 56.25%; padding-top: 30px; height: 0; overflow: hidden;&#34;&gt;
  &lt;iframe src=&#34;//www.youtube.com/embed/ygrRIWR8rmY&#34; style=&#34;position: absolute; top: 0; left: 0; width: 100%; height: 100%;&#34; allowfullscreen frameborder=&#34;0&#34;&gt;&lt;/iframe&gt;
 &lt;/div&gt;


&lt;pre&gt;&lt;code&gt;#include &amp;lt;SwitecX12.h&amp;gt;

const int STEPS = 315 * 12;
const int A_STEP = 8;
const int A_DIR = 9;
const int RESET = 10;

SwitecX12 motor1(STEPS, A_STEP, A_DIR);


void setup() {
  digitalWrite(RESET, HIGH);
  Serial.begin(9600);
  motor1.zero();
  motor1.setPosition(STEPS/2);
}

void loop() {
  static bool forward = true;
  static int position1 = STEPS * 3/4;
  static int position2 = STEPS * 1/4;
  if (motor1.stopped) {
    motor1.setPosition(forward ? position1 : position2);
    forward = !forward;
  }
  motor1.update();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;The AX1201728SG looks very promising.  It&amp;rsquo;s a bit of a nuisance to
deal with surface mount devices if you aren&amp;rsquo;t set up for it, but not insurmountable.&lt;/p&gt;

&lt;p&gt;The microstepping is really smooth. Below is a video showing how smooth.
I used a very exaggerated acceleration
table to keep the needle in the slow range for longer.&lt;/p&gt;


&lt;div style=&#34;position: relative; padding-bottom: 56.25%; padding-top: 30px; height: 0; overflow: hidden;&#34;&gt;
  &lt;iframe src=&#34;//www.youtube.com/embed/YJIwiru_kk4&#34; style=&#34;position: absolute; top: 0; left: 0; width: 100%; height: 100%;&#34; allowfullscreen frameborder=&#34;0&#34;&gt;&lt;/iframe&gt;
 &lt;/div&gt;</description>
    </item>
    
    <item>
      <title>Resources</title>
      <link>//guy.carpenter.id.au/gaugette/resources/</link>
      <pubDate>Tue, 01 Nov 2016 14:39:00 +1000</pubDate>
      
      <guid>//guy.carpenter.id.au/gaugette/resources/</guid>
      <description>

&lt;h2 id=&#34;source-code&#34;&gt;Source Code&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/clearwater/SwitecX25&#34; target=&#34;_blank&#34;&gt;SwitecX25 Driver Library for Arduino&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/clearwater/gaugette&#34; target=&#34;_blank&#34;&gt;Gaugette Source for Arduino&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;switec-x25-series-stepper-motors&#34;&gt;Switec X25 Series Stepper Motors&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;//guy.carpenter.id.au/gaugette/gaugette/resources/switec/X25_xxx_01_SP_E-1.pdf&#34;&gt;Switec X25 Series Data Sheet&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;//guy.carpenter.id.au/gaugette/gaugette/resources/switec/ISM_Buyers_Guide.pdf&#34;&gt;Switec X25 Series Buyers Guide&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;vid29-series-motors&#34;&gt;VID29 Series Motors&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;//guy.carpenter.id.au/gaugette/gaugette/resources/vid/20091026113525_VID29_manual_EN-080606.pdf&#34;&gt;VID29 Series Data Sheet&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;//guy.carpenter.id.au/gaugette/gaugette/resources/vid/20090905105401VID29.pdf&#34;&gt;VID29 Mechanical Drawings&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;//guy.carpenter.id.au/gaugette/gaugette/resources/vid/2009111395111_Acceleration_&amp;amp;_reset_calculation_example.pdf&#34;&gt;VID29 Acceleration and Reset Calculation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;//guy.carpenter.id.au/gaugette/gaugette/resources/vid/2009111395409_VID29_Precaution_of_Pointer_Assembly.pdf&#34;&gt;VID29 Pointer Assembly Precautions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;//guy.carpenter.id.au/gaugette/gaugette/resources/vid/2009111395504_VID29_reset_pulse_general_description.pdf&#34;&gt;VID29 Power-On Reset Procedure&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;//guy.carpenter.id.au/gaugette/gaugette/resources/vid/2009111395537_VID29Electrical_and_Mechanical_Characteristic1.pdf&#34;&gt;VID29 Electrical and Mechanical Characteristics&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;vid23-series-motors&#34;&gt;VID23 Series Motors&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;//guy.carpenter.id.au/gaugette/gaugette/resources/vid/2009111390052_VID23 manual EN-081210.pdf&#34;&gt;VID23 Transparent Shaft Motor&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;mcr-motor-mr1107-mr1108&#34;&gt;MCR Motor MR1107/MR1108&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;//guy.carpenter.id.au/gaugette/gaugette/resources/mcr/2010410104720473.pdf&#34;&gt;MCR Motor MR1107/MR1108 Data Sheet&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;//guy.carpenter.id.au/gaugette/gaugette/resources/mcr/2009212115216347.pdf&#34;&gt;MCR Motor Mechanical Drawings&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;//guy.carpenter.id.au/gaugette/gaugette/resources/mcr/201041010510949.pdf&#34;&gt;MCR PWM Driving Mode&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;//guy.carpenter.id.au/gaugette/gaugette/resources/mcr/2010410104915847.pdf&#34;&gt;MCR Acceleration Curve&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;driver-chips&#34;&gt;Driver Chips&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;//guy.carpenter.id.au/gaugette/gaugette/resources/switec/X12_017.pdf&#34;&gt;X12.017 Quad Driver Chip Data Sheet&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;//guy.carpenter.id.au/gaugette/gaugette/resources/nost/1428412011616by8290datasheet.pdf&#34;&gt;BY8290 Quad Driver Chip Data Sheet (in Chinese)&lt;/a&gt;, and here’s a link to a Google-generated &lt;a href=&#34;http://translate.google.com.au/translate?hl=en&amp;amp;sl=zh-CN&amp;amp;tl=en&amp;amp;u=http%3A%2F%2Fguy.carpenter.id.au%2Fgaugette%2Fresources%2Fnost%2F1428412011616by8290datasheet.pdf&#34; target=&#34;_blank&#34;&gt;English translation of the data sheet&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;//guy.carpenter.id.au/gaugette/gaugette/resources/vid/2009111391612_VID6606%20manual%20060927.pdf&#34;&gt;VID6606 Quad Driver Chip Data Sheet&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    <item>
      <title>Gauge Build Number One</title>
      <link>//guy.carpenter.id.au/gaugette/2012/01/28/gauge-build-number-one/</link>
      <pubDate>Sat, 28 Jan 2012 15:56:00 +1000</pubDate>
      
      <guid>//guy.carpenter.id.au/gaugette/2012/01/28/gauge-build-number-one/</guid>
      <description>&lt;p&gt;&lt;img src=&#34;//guy.carpenter.id.au/gaugette/resources/thermo_original.jpg&#34;  class=&#34;left&#34;   alt=&#34;$5 Hygrometer&#34;  /&gt;

This weekend I opened up one of the cheap-but-funky thermometers/hygrometers
from &lt;a href=&#34;http://www.letsmaketime.com.au&#34; target=&#34;_blank&#34;&gt;Lets Make Time&lt;/a&gt;
and replaced the thermometer mechanism with the
Arduino-controlled Switec X25.168 stepper.

The thermometer and hygrometer are installed
in identical one-part plastic housings with no screws
or seams, so it wasn&amp;rsquo;t clear how to crack them open.
&lt;img src=&#34;//guy.carpenter.id.au/gaugette/resources/thermo_back.jpg&#34;  class=&#34;right&#34;   alt=&#34;back removed&#34;  /&gt;

I used a Dremel to cut away the back panel giving access to the
thermometer mechanism, but to my surprise the dial face was still firmly
locked in place.  After a bit
of poking around I discovered that I could push the whole assembly out
forward - in fact the plastic lens is only held in by friction, and
the dial and mechanism are held in by the lens.  No cutting was
required.  #LFMF&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;//guy.carpenter.id.au/gaugette/resources/thermo_disassembly.jpg&#34;  class=&#34;left&#34;   alt=&#34;thermometer disassembly&#34;  /&gt;

This turned out to be important because after careful measurement I realized
that the motor would have to be mounted snugly against the the back of the housing to
leave the drive shaft protruding enough to attach a needle.  The plastic panel I cut away
would have been ideal to screw the motor to.
Starting again with an undamaged housing, I gently pried out the plastic lens, removed the face and mechanism.
This time I only cut away enough plastic on the back to allow the drive shaft to pass through.&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;//guy.carpenter.id.au/gaugette/resources/thermo_mount.jpg&#34;  class=&#34;right&#34;   alt=&#34;mechanism removal&#34;  /&gt;

The needle and the bi-metal thermometer coil came off the face easily enough, but the mounting for the coil
is a crafty two-piece deal that mounts through the centre of the dial.  It appeared to be
assembled a bit like a rivet, and a couple of solid blows from the back with a punch
released it cleanly from the dial face.&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;//guy.carpenter.id.au/gaugette/resources/thermo_glued.jpg&#34;  class=&#34;left&#34;   alt=&#34;hot glue to the rescue&#34;  /&gt;

I originally intended to use screws to secure the stepper to the back of the housing, but
there isn&amp;rsquo;t much tolerance for positional
error, which made me nervous.  Instead I used the conical rivet-thingy to precisely align the motor drive shaft in hole in the dial and held it all in place while I hot-glued it to the back of the case.  Alignment was spot-on the the motor seems to be solidly secured.  So far so good.&lt;/p&gt;

&lt;p&gt;Next I wired up the Arduino and zeroed the motor against the low stop and put the needle on.
There were some unexpected complications at this point.
The motor has a sweep of 315 degrees, but this dial only
allows about 230 degrees of needle movement.  I modified the library to support a
soft range limit to avoid exceeding 230 degrees, while still running through a full 315
degrees during reset.&lt;/p&gt;

&lt;p&gt;While trying to calibrate the dial I found the needle slipping at times, especially under
vibration caused by the power-on reset or slow stepping.  With the needle slipping calibration
was impossible. I tried applying the smallest drop of hot glue I could manage to the back of the needle.  That really didn&amp;rsquo;t work - the tiny irregular mass between the needle and the dial face would sometimes
bind against the dial face, causing more problems.&lt;/p&gt;

&lt;p&gt;I believe the needle hole is dished a little, so I removed the needle, cleaned the glue away,
and smacked it with a hammer to flatten out the dish and close up the hole.  That worked
a little too well and I had to ream the hole out a bit with a thumb tack.  Now the needle
is nice and snug, no slippage.&lt;/p&gt;


&lt;div style=&#34;position: relative; padding-bottom: 56.25%; padding-top: 30px; height: 0; overflow: hidden;&#34;&gt;
  &lt;iframe src=&#34;//www.youtube.com/embed/UJKaaRR9W6g&#34; style=&#34;position: absolute; top: 0; left: 0; width: 100%; height: 100%;&#34; allowfullscreen frameborder=&#34;0&#34;&gt;&lt;/iframe&gt;
 &lt;/div&gt;


&lt;p&gt;So here&amp;rsquo;s how it looks assembled.  Calibration is slightly out, but I&amp;rsquo;m going to make
a new dial face anyway, so no need to sweat about that.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>A Simplified Acceleration Model</title>
      <link>//guy.carpenter.id.au/gaugette/2012/01/26/simplified-acceleration-model/</link>
      <pubDate>Thu, 26 Jan 2012 09:42:00 +1000</pubDate>
      
      <guid>//guy.carpenter.id.au/gaugette/2012/01/26/simplified-acceleration-model/</guid>
      <description>&lt;p&gt;The logic in the &lt;code&gt;advance()&lt;/code&gt; function of the
&lt;a href=&#34;https://github.com/clearwater/SwitecX25&#34; target=&#34;_blank&#34;&gt;Switec X25 library&lt;/a&gt;
steps the motor forward or backward one step, then computes the delay in
microseconds until the next step is due.  This logic determines the acceleration curve and
maximum speed of the needle.  My first cut at this
code used floating point arithmetic to model this as time/accel/velocity problem.  The
motion was nice and smooth, but it was overkill, and consumes too many precious Arduino
compute cycles.  When driving multiple motors, this will create an artificial ceiling on the
maximum motor speed.

I&amp;rsquo;ve rewritten that logic to use a simple lookup table instead.
This is a fairly obvious approach, but it was
reassuring to see similar approaches recommended in both the
&lt;a href=&#34;//guy.carpenter.id.au/gaugette/resources/vid/2009111395111_Acceleration_&amp;amp;_reset_calculation_example.pdf&#34;/&gt;VID 29 documentation&lt;/a&gt;

and the &lt;a href=&#34;//guy.carpenter.id.au/gaugette/resources/mcr/2010410104915847.pdf&#34;/&gt;MCR MR1107 data sheet&lt;/a&gt;
.&lt;/p&gt;

&lt;p&gt;The acceleration curve is defined as pairs of vel,delay values:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;unsigned short accelTable[][2] = {
  {   10, 5000},
  {   30, 1500},
  {  100, 1000},
  {  150,  800},
  {  300,  600}
};
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We maintain a variable &lt;code&gt;vel&lt;/code&gt; (which isn&amp;rsquo;t actually velocity,
but is a surrogate for velocity) that increments
each step under acceleration, and decrements each step under deceleration.
When stationary, &lt;code&gt;vel&lt;/code&gt; is zero.  After 1 step of acceleration it is 1.
For simplicity I&amp;rsquo;ve made the acceleration and deceleration curves identical
so they can share the same lookup table.&lt;/p&gt;

&lt;p&gt;To determine the inter-step delay at any given value of &lt;code&gt;vel&lt;/code&gt;, we find
the first table entry such that &lt;code&gt;accelTable[i][0] &amp;lt; vel&lt;/code&gt;.  In practice this means that the
motor will step at 5000 &amp;micro;S intervals for 9 steps, then 1500 &amp;micro;S
steps for the next 30 steps, 1000 &amp;micro;S for the next 100 steps, and so on.
The peak speed with a delay of 600 &amp;micro;S equates to 1666 Hz step rate
or about 500 degrees per second.&lt;/p&gt;

&lt;p&gt;The motion control logic first determines if the motor is subject to acceleration,
at full speed, or deceleration and adjusts &lt;code&gt;vel&lt;/code&gt; accordingly.  Using
steps as the unit for &lt;code&gt;vel&lt;/code&gt; makes it very
easy to determine when to declerate: when &lt;code&gt;vel&lt;/code&gt; is greater than or equal to the number of steps
to reach our destination, we need to start decelerating.&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;//guy.carpenter.id.au/gaugette/resources/VID29_accel.png&#34;  class=&#34;right&#34;   alt=&#34;From the VID29 Tech Note&#34;  /&gt;

The new logic also ensures that if the motor is moving at
speed in one direction and is directed to a new position in the opposite direction it will
decelerate to a stop before accelerating in the opposite direction.&lt;/p&gt;

&lt;p&gt;The constants that make up the acceleration table are constrained by the
the inertia of the needle attached to the motor.  The
&lt;a href=&#34;//guy.carpenter.id.au/gaugette/resources/vid/2009111395111_Acceleration_&amp;amp;_reset_calculation_example.pdf&#34;/&gt;VID 29 documentation&lt;/a&gt;

gives some recommendations for calculating these values, but I actually
didn&amp;rsquo;t use that.  I experimented until I
found values that were within operational limits and look nice to me.&lt;/p&gt;

&lt;p&gt;I tested this code driving 3 motors simultaneously with an Arduino Uno.
All good.  New code is in the &lt;a href=&#34;https://github.com/clearwater/SwitecX25&#34; target=&#34;_blank&#34;&gt;library on Github&lt;/a&gt;.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Two Motors, One Arduino</title>
      <link>//guy.carpenter.id.au/gaugette/2012/01/23/two-motors-one-arduino/</link>
      <pubDate>Mon, 23 Jan 2012 14:39:00 +1000</pubDate>
      
      <guid>//guy.carpenter.id.au/gaugette/2012/01/23/two-motors-one-arduino/</guid>
      <description>&lt;p&gt;Last night I built a pair of improved wiring harnesses so I could
connect two motors to the Arduino.  Once concern
I have is that the control logic that manages the acceleration and
deceleration could be so slow that it will interfere with the motor
drive signaling when trying to control more than one motor.  I have in mind to replace the
floating point logic with a lookup table, but for now I like being
able to easily fiddle with the motion parameters.&lt;/p&gt;

&lt;p&gt;It turns out that two motors work pretty well with only minor tweaks to the existing
code.&lt;/p&gt;


&lt;div style=&#34;position: relative; padding-bottom: 56.25%; padding-top: 30px; height: 0; overflow: hidden;&#34;&gt;
  &lt;iframe src=&#34;//www.youtube.com/embed/Z-f4m18n48I&#34; style=&#34;position: absolute; top: 0; left: 0; width: 100%; height: 100%;&#34; allowfullscreen frameborder=&#34;0&#34;&gt;&lt;/iframe&gt;
 &lt;/div&gt;

</description>
    </item>
    
    <item>
      <title>Motor Acceleration and Deceleration</title>
      <link>//guy.carpenter.id.au/gaugette/2012/01/15/motor-acceleration-and-deceleration/</link>
      <pubDate>Sun, 15 Jan 2012 19:38:00 +1000</pubDate>
      
      <guid>//guy.carpenter.id.au/gaugette/2012/01/15/motor-acceleration-and-deceleration/</guid>
      <description>&lt;p&gt;My first cut at the &lt;a href=&#34;https://github.com/clearwater/gaugette&#34; target=&#34;_blank&#34;&gt;Switec X25 library&lt;/a&gt;
stepped the needle at a constant speed.  You can see the constant speed
motion in the &lt;a href=&#34;http://www.youtube.com/watch?v=vwAxRk_5oXA&#34; target=&#34;_blank&#34;&gt;original video&lt;/a&gt;.


&lt;div style=&#34;position: relative; padding-bottom: 56.25%; padding-top: 30px; height: 0; overflow: hidden;&#34;&gt;
  &lt;iframe src=&#34;//www.youtube.com/embed/uNLySm71OBc&#34; style=&#34;position: absolute; top: 0; left: 0; width: 100%; height: 100%;&#34; allowfullscreen frameborder=&#34;0&#34;&gt;&lt;/iframe&gt;
 &lt;/div&gt;
&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;ve updated the library to support acceleration and deceleration, partly because
it seems more aesthetically pleasing, and partly because I have a notion that
I should be able to reach faster peak speeds by ramping the speed up.  Motion is
now specified by 4 parameters: minimum speed, maximum speed, acceleration, deceleration.&lt;/p&gt;

&lt;p&gt;For now I&amp;rsquo;ve used floating point calculations to compute each step period
standard Newtonian velocity/distance/time
calculations.  This works okay, but is unnecessarily compute-intensive.&lt;/p&gt;

&lt;p&gt;The Switec X25 library supports multiple motors
and no doubt this computation will become a factor when I try to drive more than
one motor, so I&amp;rsquo;ll have to address that at some point.&lt;/p&gt;

&lt;p&gt;One interesting aspect of the control logic is that the calculations are done at the start
of each step, in distance-domain rather than in time domain like most simulations.
This means the calculations must be done more frequently at higher needle
speeds.  This is going to set an upper bound on maximum step rate.&lt;/p&gt;

&lt;p&gt;When it does become an issue,
I think I could replace the entire floating point calculation with a small table of pre-computed
(step-count, step-period) pairs with little perceptible difference.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Initial Results</title>
      <link>//guy.carpenter.id.au/gaugette/2012/01/09/initial-results/</link>
      <pubDate>Mon, 09 Jan 2012 14:16:00 +1000</pubDate>
      
      <guid>//guy.carpenter.id.au/gaugette/2012/01/09/initial-results/</guid>
      <description>&lt;h2 id=&#34;wiring-it-up&#34;&gt;Wiring It Up&lt;/h2&gt;

&lt;p&gt;Given the comments by &lt;a href=&#34;http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1260978962&#34; target=&#34;_blank&#34;&gt;Toby Catlin&lt;/a&gt;
about cooking the motors while soldering, I opted to make up a harness with a connector rather than
soldering directly to the motor.
The pins on each winding exactly match the spacing of the first and fourth pins
of a standard 0.1&amp;rdquo; connector.  JST RE connectors are the right pitch, but the pins on the motor are
too short and too narrow to engage with the connectors.  For my first harness I cut up
a floppy disk cable connector into two 4-hole sections and soldered wire to the first and fourth
pins.  It worked fine but it is pretty bulky, and the metal contacts in the connector did not solder
very easily.  For now I just pushed the tinned ends of the wires directly into the Arduino connectors.

I wrote some code for the Arduino to step the motor using the IO pattern established
in &lt;a href=&#34;http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1260978962&#34; target=&#34;_blank&#34;&gt;this post&lt;/a&gt;
and a quick ruby script to query my pfSense firewall to get some live data to test with.&lt;/p&gt;

&lt;p&gt;Add some duct tape for a gauge, and behold the simplest analog bandwidth meter ever:&lt;/p&gt;


&lt;div style=&#34;position: relative; padding-bottom: 56.25%; padding-top: 30px; height: 0; overflow: hidden;&#34;&gt;
  &lt;iframe src=&#34;//www.youtube.com/embed/vwAxRk_5oXA&#34; style=&#34;position: absolute; top: 0; left: 0; width: 100%; height: 100%;&#34; allowfullscreen frameborder=&#34;0&#34;&gt;&lt;/iframe&gt;
 &lt;/div&gt;</description>
    </item>
    
    <item>
      <title>What is Gaugette?</title>
      <link>//guy.carpenter.id.au/gaugette/2012/01/05/what-is-gaugette/</link>
      <pubDate>Thu, 05 Jan 2012 13:11:00 +1000</pubDate>
      
      <guid>//guy.carpenter.id.au/gaugette/2012/01/05/what-is-gaugette/</guid>
      <description>&lt;p&gt;Gaugette is a project detailing the construction of custom analog gauges using
an Arduino microcontroller and Switec X25.168 stepper motors.
Each motor requires 4 digital I/O pins,
and a single Arduino can drive three motors.  The limit
is purely due to Aruidno limit of 14 digital I/O lines.


&lt;div style=&#34;position: relative; padding-bottom: 56.25%; padding-top: 30px; height: 0; overflow: hidden;&#34;&gt;
  &lt;iframe src=&#34;//www.youtube.com/embed/Z-f4m18n48I&#34; style=&#34;position: absolute; top: 0; left: 0; width: 100%; height: 100%;&#34; allowfullscreen frameborder=&#34;0&#34;&gt;&lt;/iframe&gt;
 &lt;/div&gt;
&lt;/p&gt;

&lt;p&gt;Source code for the project is available on
&lt;a href=&#34;https://github.com/clearwater/gaugette&#34; target=&#34;_blank&#34;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&#34;motivation&#34;&gt;Motivation&lt;/h2&gt;

&lt;p&gt;After playing with the
&lt;a href=&#34;http://www.adafruit.com/products/171&#34; target=&#34;_blank&#34;&gt;motor shield party pack&lt;/a&gt; from Adafruit,
I started thinking it would be fun to have a couple of analog gauges
mounted on the wall somewhere to show system health indication; maybe network bandwidth or
web traffic?
&lt;img src=&#34;http://blog.skytee.com/wp-content/uploads/2010/11/B-300x277.jpg&#34;  class=&#34;right&#34;   alt=&#34;TorrentMeter by Skytee&#34;  /&gt;

Of course I&amp;rsquo;ve seen the very beautiful
&lt;a href=&#34;http://blog.skytee.com/2010/11/torrentmeter-a-steampunk-bandwidth-meter/&#34; target=&#34;_blank&#34;&gt;TorrentMeter by Skytee&lt;/a&gt;
which is so pretty it makes me weep, but beautiful brass antique voltmeters are in short supply
around here.&lt;/p&gt;

&lt;p&gt;The servos and steppers in the Adafruit pack aren&amp;rsquo;t ideal for driving gauges.  The little stepper they
include runs really hot.  The servo seemed
like possibility and it is driven by PWM, so I wouldn&amp;rsquo;t even need the motor shield.
But it is quite bulky and noisy, so I started looking for something better.&lt;/p&gt;

&lt;h2 id=&#34;the-switec-x25-stepper-motor&#34;&gt;The Switec X25 Stepper Motor&lt;/h2&gt;

&lt;p&gt;&lt;img src=&#34;//guy.carpenter.id.au/gaugette/resources/Switec_X25_168.jpg&#34;  class=&#34;right&#34;   alt=&#34;Switec X26.168 Stepper Motor&#34;  /&gt;

I noticed a lot of sellers on eBay selling tiny Switec X25
motors as replacements for GM auto instrument clusters.  They were developed
by the technology arm of Swatch, so I figured they should be low power and
pretty quiet.  Certainly they are cheap; under $5 each!&lt;/p&gt;

&lt;p&gt;The X25 motors have 6 steps per revolution, and a 180:1 gearbox, giving a
resolution of 1/3 degree.
The &lt;a href=&#34;//guy.carpenter.id.au/gaugette/resources/switec/X25_xxx_01_SP_E-1.pdf&#34;/&gt;data sheet&lt;/a&gt;

indicates they draw no more than 20mA per winding, which is low enough to source directly from the 5V
Arduino data pins, raising the possibility of driving these without an intermediate controller chip. Yes, I
understand the risks associated with wiring inductive loads directly to the microcontroller.  Arduinos are
cheap, why not try it?&lt;/p&gt;

&lt;p&gt;On the net I found an excellent
&lt;a href=&#34;http://www.mycockpit.org/forums/content.php/355-An-Easy-Approach-to-an-Analog-Gauge&#34; target=&#34;_blank&#34;&gt;overview of the Switec X25 by Mike Powell&lt;/a&gt;.
Mike expresses concerns about driving inductive loads directly from the microcontroller and uses
an external L293D driver.  There is an intriguing
&lt;a href=&#34;http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1260978962&#34; target=&#34;_blank&#34;&gt;thread by Toby Catlin&lt;/a&gt;
which approaches the issue of driving these without a controller, but the thread ends abruptly at the point
where he sees the first signs of success.  What happens next?  Blue smoke?&lt;/p&gt;

&lt;p&gt;At the price I figured it was worth a shot driving these directly,
so I ordered 6 from  &lt;a href=&#34;http://stores.ebay.com.au/partsangel&#34; target=&#34;_blank&#34;&gt;one of many&lt;/a&gt;
eBay stores selling them.  Apparently a complete GM instrument cluster has 6 motors, so 6 is a popular quantity.
In all it cost about $25 including postage from the US to Australia.
At the time of writing they carry both the X25.168
with rear contacts, and the X25.589 with front contacts and a longer indicator shaft.
Both have internal stops.  See the &lt;a href=&#34;//guy.carpenter.id.au/gaugette/resources/switec/ISM_Buyers_Guide.pdf&#34;/&gt;buyers guide&lt;/a&gt;
 for details
on the different models.&lt;/p&gt;</description>
    </item>
    
  </channel>
</rss>