Sunday, 15 September 2013

All servo's mounted...

So as per my last post, I've finally mounted and calibrated all servo motors for my Points. These motors have been mounted using Franc Carter's 3D printed servo brackets.

You can see them in the photo below:




Now, to complete the software for the point controller. Then the real work begins - proper circuit layout and wiring.

I'll also have to wire in the lights, motor controllers and sensors for the main rail network and the tram.

In the video below you can see one of the points in motion.

Pololu Micro Serial Servo Controller

I've finally got all my Points bolted in place and I'm now driving them from a Pololu Micro Serial Servo Controller. Take a look at the Pololu web page here.

These are really nice pieces of hardware - they can drive up to 8 servos from a single tiny board.

I'm using the software serial library to communicate with the Pololu. I've found that you have to explicitly control the reset on the device otherwise it's unpredictable and often bombs out on power up.

This simple circuit drives a single servo based on reading an input from a potentiometer. I'm restricting the angle quite narrowly because the sweep between 2 n-scale rails is only 9mm or so.

Here's my rough prototype board:



And here's the source code...

//
// Pololu micro serial servo controller modes
//
// Software Serial from Arduino example by Tom Igoe
//
// Pololu code borrowed from Mike Crist...
//   put() (now position_absolute) & set_speed() functions found on pololu forums & modified
//   mike crist 2009-01-03

#include <SoftwareSerial.h>

#define  ServoRxPin     2
#define  ServoTxPin     3
#define  ServoResetPin  4

// Pins for later use ;-)
#define  CmdRxPin       5
#define  CmdTxPin       6

int  old_d;

// set up a new serial port
SoftwareSerial softSerial =  SoftwareSerial(ServoRxPin, ServoTxPin);

void setup()
{
  int  i;
  
  // set the data rate for the hardware serial port
  Serial.begin(9600);

  pinMode(ServoResetPin, OUTPUT);
  digitalWrite(ServoResetPin, LOW);
  delay(20);
  digitalWrite(ServoResetPin, HIGH);
  

  pinMode(ServoRxPin, INPUT);

  digitalWrite(ServoTxPin, HIGH);

  pinMode(ServoTxPin, OUTPUT);

  // set the data rate for the SoftwareSerial port
  softSerial.begin(38400);
  
  for (i = 0 ; i < 8 ; i++ )
  {
    set_speed(i, 3);
    //delay(100);
    set_neutral(i, 3000);
    //delay(100);
    set_servo_parameters(i, 15);
    //delay(100);
      
  }
  
  old_d = 0;
}



void loop()
{
  int  v,d;

/*  Here's the bit reading the pot - commented out for now...
  v = analogRead(0);
  d = map(v,0,1023,70,110);

  if( d != old_d )
  {
    old_d = d;
    
    position_8bit(1,(byte)map(d,0,179,0,255));
  
    Serial.print(v);
    Serial.print(" , ");
    Serial.println(d);
  }
  delay(10);
*/
//
// I'm driving a single point repeatedly now to hammer it!!
//
    position_8bit(1,(byte)map(94,0,179,0,255));
    delay(5000);
    position_8bit(1,(byte)map(85,0,179,0,255));
    delay(5000);
    

}

void set_servo_parameters(byte servo, byte rangeVal)
{
   //this function uses pololu mode command 0 to set servo parameters
   //servo is the servo number (typically 0-7)
   //rangeVal of 15 gives 180 deg in 8-bit, 90 deg in 7 bit
   
   byte temp;
   byte parameters;
   
   temp = 1 << 6;                     //set first two bits of parameters (on = 1, forward = 0)
   temp = temp + (rangeVal & 0x1f);   //put first five bits of rangeVal into temp
   parameters = temp & 0x7f;          //take only bottom 7 bits
      
   //Send a Pololu Protocol command
   softSerial.write(0x80);       //start byte
   softSerial.write(0x01);       //device id
   softSerial.write((byte)0x00);       //command number
   softSerial.write(servo);      //servo number
   softSerial.write(parameters); //parameters
   
}

void set_speed(byte servo, byte speedVal)
{
   //this function uses pololu mode command 1 to set speed
   //servo is the servo number (typically 0-7)
   //speedVal is servo speed (1=slowest, 127=fastest, 0=full)
   //set speedVal to zero to turn off speed limiting
   
   speedVal = speedVal & 0x7f; //take only lower 7 bits of the speed
   
   //Send a Pololu Protocol command
   softSerial.write(0x80);     //start byte
   softSerial.write(0x01);     //device id
   softSerial.write(0x01);     //command number
   softSerial.write(servo);    //servo number
   softSerial.write(speedVal); //speed

}

void position_7bit(byte servo, byte posValue)
{
  //this function uses pololu mode command 2 to set position  
  //servo is the servo number (typically 0-7)
  //posValue * range (set with command 0) adjusted by neutral (set with command 5)
  //determines servo position

   byte pos = posValue & 0x7f;     //get lower 7 bits of position

   //Send a Pololu Protocol command
   softSerial.write(0x80);     //start byte
   softSerial.write(0x01);     //device id
   softSerial.write(0x02);     //command number
   softSerial.write(servo);    //servo number
   softSerial.write(pos);     //position
}

void position_8bit(byte servo, byte posValue)
{
  //this function uses pololu mode command 3 to set position  
  //servo is the servo number (typically 0-7)
  //posValue * range (set with command 0) adjusted by neutral (set with command 5)
  //determines servo position

   byte temp;
   byte pos_hi,pos_low;
   
   temp = posValue & 0x80;      //get bit 8 of position
   pos_hi = temp >> 7;            //shift bit 8 by 7
   pos_low = posValue & 0x7f;     //get lower 7 bits of position

   //Send a Pololu Protocol command
   softSerial.write(0x80);     //start byte
   softSerial.write(0x01);     //device id
   softSerial.write(0x03);     //command number
   softSerial.write(servo);    //servo number
   softSerial.write(pos_hi);  //bits 8 thru 13
   softSerial.write(pos_low); //bottom 7 bits
}

void position_absolute(byte servo, int angle)
{
  //this function uses pololu mode command 4 to set absolute position  
  //servo is the servo number (typically 0-7)
  //angle is the absolute position from 500 to 5500

   unsigned int temp;
   byte pos_hi,pos_low;
   
   temp = angle & 0x1f80;  //get bits 8 thru 13 of position
   pos_hi = temp >> 7;     //shift bits 8 thru 13 by 7
   pos_low = angle & 0x7f; //get lower 7 bits of position

   //Send a Pololu Protocol command
   softSerial.write(0x80);    //start byte
   softSerial.write(0x01);    //device id
   softSerial.write(0x04);    //command number
   softSerial.write(servo);   //servo number
   softSerial.write(pos_hi);  //bits 8 thru 13
   softSerial.write(pos_low); //bottom 7 bits
}

void set_neutral(byte servo, int angle)
{
  //this function uses pololu mode command 5 to set neutral position  
  //servo is the servo number (typically 0-7)
  //angle is the absolute position from 500 to 5500

   unsigned int temp;
   byte pos_hi,pos_low;
   
   temp = angle & 0x1f80;  //get bits 8 thru 13 of position
   pos_hi = temp >> 7;     //shift bits 8 thru 13 by 7
   pos_low = angle & 0x7f; //get lower 7 bits of position

   //Send a Pololu Protocol command
   softSerial.write(0x80);    //start byte
   softSerial.write(0x01);    //device id
   softSerial.write(0x05);    //command number
   softSerial.write(servo);   //servo number
   softSerial.write(pos_hi);  //bits 8 thru 13
   softSerial.write(pos_low); //bottom 7 bits
}

Monday, 1 April 2013

The Canberra branch

Chris made the mistake sometime back of allowing other weirdos enthusiasts to post to his blog. I expect this to be fixed very shortly but till then... This permission includes Canberra-based Marklin HO enthusiasts trying to return to their childhood by resurrecting (and over-ebaying) an old, large, analogue collection of bits and pieces. It might even stretch to a house renovation that includes a 60sqm basement and planning approval from the family for a model railway there (shared with the snooker table, table-tennis table and sundry games). That story will have to wait for another day, and perhaps a separate blog. Actually, I can point house-renovation enthusiasts to our (hibernating) renovation blog.

For now though, readers of the Mendes blog may be interested to know of two major model railway exhibitions that are held just down the road, in Canberra. One is held at Malkara Special School the first weekend of August. The other is the Canberra Model Railway Club's annual Expo, held around the end of March. This year is it's 25th anniversary. Both attract modellers and vendors from across the eastern seaboard. Having lived in Canberra for twenty years, I've been to nearly a dozen of the Malkara shows, but missed every one of the CMRCI shows. Not this year. This year, with a herculean effort, I made it to the last twenty five minutes of a two-day extravaganza! (Next year, must do better.)

First impressions. It's big. The information guide stretches to nearly forty pages. There are about twenty-five+ layouts of every level of maturity and scale (N to O, plus Lego), plus about thirty vendors. Secondly, it's railways and nothing else. Malkara includes a small number of RC cars and some extremely impressive RC boats and RC submarines, as well as doll houses and other modellers. Thirdly, don't get there late on the last day. The packing up starts an hour before the end. You can do the maths...

Photos, photos, photos...


Bathley Creek is a cool 3-bay layout with some gorgeous visual and auditory features. Kept folks amused for ages.

Crestwood is the CMRCI club layout for general tinkering, and an eclectic mix of locos and rolling stocks (whoever rocks up with stuff can run on it)


Many of their buildings are scratch builds, factories came more from kits.

Then there was Arakoola, an O-scale layout. Needed a bit of space...



For those interested, there's an O-Scale Modellers forum on the 6th of April in Sydney.


Stuuuuufffffff...... so much stuff...... One of about thirty vendors.


The dirty secret behind every layout - but you can't hide in this hall.

These guys were selling neon lighting - the photo doesn't do it any justice.

I loved the welder in the shed at front. The blue led would flicker a while, then go off, replaced with a nice orange glow led. It's the details...

This layout is an amazing N-scale replica of Central. Everything here is scratch built including all the cars, trucks, trams and buses. The photo does not do it credit. It took over six years to build, following four years of surveying and measuring... everything.



Anybody recognise the location above? The building at the top right is a hint. It's Sydney Central, around 1876. Actually, the notes say Redfern, though I'm a little lost as to how the old mortuary station is on that side then. Did the tracks change that much? For the trivia buffs, there was a second mortuary station, same design, out at Rookwood Cemetery. It got taken brick by brick to Canberra, and with some minor changes became the All Saints church in Ainslie. 


Enough of the Australian nostalgia. I didn't know it, but I wanted a brightly-lit faux-Japanese layout, and I found one! Lots of bright leds, as you'd expect.




Nakele Junction is a really cool idea. The CMRCI has partnered with the hosting high school to offer an extra-curricular (but during class-time!) activity on model-railway construction. So all of this layout has been done by year 7-10 students.

How little space you need for a layout, if you have a vivid imagination...


Ok, and here come the CLUG - not the Canberra Linux Users Group, but the Canberra Lego Users Group. Sadly they had already taken down about a third when I arrived. But - fear not - they have an annual show around the second weekend of August (Hellenic Club, Woden) where they set up their full layout. Tickets are only sold online. Last year they sold out, over 10,000 tickets. Get in quick. Note the beautiful bridgework, and the funicular monorail.




And finally for the N-scale enthusiasts, below is the layout of the Canberra Monaro N-scale group. One of the joys of N-scale is what you can fit in a small space - that turntable and shed is just amazing. However, when talking to these guys, don't mention HO scale. Religion doesn't even begin to describe it...




Thank you for reading this far. Now we'll see whether Chris will exercise his editorial powers and kick me off, and whether Chris paid for the storage quota for all the photos...

Cheers,
Markus