Subscribe via RSS
22Aug/121

Eizan Dentetsu (Eiden) Kyoto, Japan

Was just travelling via Google Earth and decided to check out North Kyoto. The Eizan Electric Railway runs one and two-car EMUs from Demachiyanagi Station up to either Mount Kurama or Mount Hiei. I haven't travelled up to Hiei-san yet, but I do love the trains that travel up to Kurama.

Usually google maps satellite photography is taken at random hours and doesn't capture anything interesting, but it seems this time they have captured a Kirara 900 Series about to pass an 800 Series at Ninose Station.

Just thought I'd take a snapshot and record it... it's a beautiful area of Kyoto and everyone must visit at least once!

Meanwhile... here's a few old shots of my visits there including these two EMUs.

Eizan Dentetsu Kirara 900 at Iwakura Station Kirara 900 at Iwakura Station
Kirara 900 paused at Demachiyanagi Station Kirara 900 Kirara 900
Eizan Dentetsu 800 Series Eizan Dentetsu Yards Eizan Dentetsu
Kirara 900 Eizan 800 Series Eizan Dentetsu - Demachiyanagi
Eizan Dentetsu Colourful Train Eizan Dentetsu Kirara 900 Maple Orange Eizan Dentetsu Kirara 900 Maple Red_001
Eizan Dentetsu Kirara 900 Maple Red_002

I could go on about this railway forever .... go and visit it now.

15Apr/124

First CAN Node: LEDs and Sensors

Despite my layout being tiny, I've decided that my layout will need two nodes. One will do the sensing of trains + management of LEDs and the other will control the throttle, points and isolation. I've now finished the building and wiring of the first node. One note for below: I've used Frame IDs to differentiate the messages across the network; unique numbers are used to define the message type and each node will have filters applied to only receive nodes that are specifically for them.

Detecting Trains

Train sensing has been implemented via light sensors. I needed 24 sensors around the track and decided that multiplexing was the only way to read them all. 3x 4051 ICs came in handy and were configured as per the schematic below. You can find a better explanation on light sensor implementation in the article here.

LED+Sensors CAN Node

I've simplified the code for reading the sensors as I'll ensure all of them have sufficient lighting and therefore 'stable' values. The circuit waits a second after power-up to read the initial sensor values. It then marks each one as 'active' if the value is greater than 20 'points' above the initial value. If a reading comes in lower then the initially read value then that value is lowered accordingly. I've also created a special command (frame id: 0x333) to allow a reset of all sensor values (specifically if ambient light proves a problem.)

The node sends out the sensor values and then pauses 100ms. The CAN packet with sensor data has the frame ID 0x111 and then fills three bytes with the 24 sensors states. A '1' is used for occupied and a '0' for vacant. The message will be received by any node on the network with the appropriate filters set.

Controlling LEDs

To control the LEDs I've re-used the previous MAX7219 ICs that I had lying around. There's a much more in-depth article here on how to use this chip. The MAX7219 requires three wires to the Arduino... but I'd already used up all the digital pins. Fortunately you can use the Analog pins just as easily.

LEDs on new layout

LEDs on new layout

As the MAX7219 can receive bytes per row to control the LEDs I simply pass through the data from the CAN bus when appropriate. It would only take one CAN message as they contain 8 bytes of data. The Frame ID for this message is 0x222. You can see that I'm being pretty wasteful with Frame IDs but, fortunately, I don't have many specific messages to send.

Completed Sensor+LED Node

So, it was soldered and wired... quite a mess really. The CAN Controller was on-board but there was no 'direct communications' interface to the PC. This meant I had to pop the chip out (atmega328) each time I wanted to change the code... tedious and dangerous!! I managed to bend pins and confuse myself every now and then. Don't do this at home!

SENSOR+LED Node

Controller Node

I've got a third node hooked up to the computer via my trusty old Arduino Mega. This node transmits data from the CAN Bus to the PC via the standard serial-over-USB connection. A .NET application then shows the layout and allows you to interact with the LEDs and sensors accordingly. It shows the status of the sensors at any point in time and allows you to create rules in a sequence which can determine the speed and direction of the train.

The physical design of this node is simply the Arduino Mega plus the CAN schematic as seen in my previous blog post on implementing the MCP2515 controller.

  if (CAN.buffer0DataWaiting()) {
    CAN.readDATA_ff_0(&length,frame_data,&frame_id, &ext, &filter);
    Serial.write("X");
    Serial.write(frame_data[0]);
    Serial.write(frame_data[1]);
    Serial.write(frame_data[2]);
  }
  
  while (Serial.available() >= 9) {
    // read the incoming byte:
    b = Serial.read();
    if (b == 'L') {
      for (int i = 0; i < 8; i++) frame_data[i] = Serial.read();
      frame_id = 0x222;
      CAN.load_ff_0(8, &frame_id, frame_data, false);
    } else if (b == 'D') {
      for (int i = 0; i < 8; i++) frame_data[i] = Serial.read();
      frame_id = 0x666;
      CAN.load_ff_0(8, &frame_id, frame_data, false);
      //printBuf(frame_id, frame_data);
    } else if (b == 'R') {
      for (int i = 0; i < 8; i++) frame_data[i] = Serial.read();
      frame_id = 0x333;
      CAN.load_ff_0(8, &frame_id, frame_data, false);      
    } else if (b == 'P') {
      for (int i = 0; i < 8; i++) frame_data[i] = Serial.read();
      frame_id = 0x777;
      CAN.load_ff_0(8, &frame_id, frame_data, false);            
    }
  }

LED+Sensor Node Code

The sensor code consisted of an initial sensor read and then constant sensor checking. The sensors were then determined to be either 'occupied' or 'vacant' and then the data was sent. There are no 'smarts' here... the sensor data is simply hammered over the network.

The receive buffers are also checked for a Frame ID of 0x222 or 0x333. The filters are set appropriately to ensure that only these messages trigger the interrupts. The LED data is sent to the MAX7219 controller on the 0x222 message and the sensors are reset on 0x333.

void loop() {	
  send_data[0] = 0;
  send_data[1] = 0;
  send_data[2] = 0;
  for (sens = 0; sens < 8; sens++) {
    setOutputBit(sens);
    sensor_read = readInput(0);
    if (sensor_read < sensor[sens]) sensor[sens] = sensor_read;
    send_data[0] |= (((20 + sensor[sens])      <= sensor_read) << sens);
    sensor_read = readInput(1);
    if (sensor_read < sensor[sens]) sensor[sens] = sensor_read;
    send_data[1] |= (((20 + sensor[sens + 8])  <= sensor_read) << sens);
    sensor_read = readInput(2);
    if (sensor_read < sensor[sens]) sensor[sens] = sensor_read;
    send_data[2] |= (((20 + sensor[sens + 16]) <= sensor_read) << sens);
  }
  frame_id = 0x111;
  CAN.load_ff_0(3, &frame_id, send_data, false);

  frame_data[0] = 0;

  data1 = CAN.buffer0DataWaiting();
  data2 = CAN.buffer1DataWaiting();

  if (data1 || data2) {
    if (data1) CAN.readDATA_ff_0(&length, frame_data, &frame_id, &ext, &filter);
    if (data2) CAN.readDATA_ff_1(&length, frame_data, &frame_id, &ext, &filter);

    if (frame_id == 0x222) {
      for (int i = 0; i < 8; i++) lcl.setRow(0, i, frame_data[i]);
    } else if (frame_id == 0x333) {
      for (sens = 0; sens < 8; sens++) {
        setOutputBit(sens);
        sensor[sens] = readInput(0);
        sensor[sens + 8] = readInput(1);
        sensor[sens + 16] = readInput(2);
      }   
    }
 }
 delay(100);
}

Controller Node Code

The controller was the middle-man for translating PC code to the CAN bus and vice-versa. Sensor data from the CAN bus was converted to serial data with a leading 'X' byte. On the contrary LED commands were received from the PC with a leading 'L' byte. The following 8 bytes were sent as a single message onto the CAN bus once this character was seen.

    using System.IO.Ports;
    SerialPort _serialPort;

    private void SetupComPort() {
        _serialPort = new SerialPort("COM3", 9600, Parity.None, 8, StopBits.One);
        _serialPort.Handshake = Handshake.None;
        _serialPort.DataReceived += new SerialDataReceivedEventHandler(HandleData);
        _serialPort.Open();
    }

    private void cb_CheckedChanged(object sender, EventArgs e)
    {
        Byte[] bytesToSend = new Byte[9];
        bytesToSend[0] = (byte)'L';
        for (int i = 0; i < 8; i++) {
            for (int z = 0; z < 8; z++) bytesToSend[i+1] |= (byte)((LEDs[(i*8) + z].Checked ? 1 : 0) << z);
        }
        _serialPort.Write(bytesToSend, 0, 9);
    }

    private void UpdateSpeed()
    {
        Byte[] bytesToSend = new Byte[9];
        bytesToSend[0] = (byte)'D';
        bytesToSend[1] = (byte)(direction ? 1 : 0);
        bytesToSend[2] = (byte)hSpeed.Value;
        bytesToSend[3] = (byte)points[0]; //for loop? probably should.
        bytesToSend[4] = (byte)points[1];
        bytesToSend[5] = (byte)points[2];
        bytesToSend[6] = (byte)points[3];
        bytesToSend[7] = (byte)points[4];
        bytesToSend[8] = (byte)points[5];
        _serialPort.Write(bytesToSend, 0, 9);
        Console.WriteLine("Sent: D" + bytesToSend[1] + "-" + bytesToSend[2]);
    }

Notes learnt from hooking all this up

  • CAN Filters work, but you can still see messages
    On the CAN controller you can set filters to only allow specific messages through. It actually turns out that, regardless of the filter being set, if you constantly poll either buffer for a message that, if there has been a message sent, it will be available and can be received from the network. Filters simply prevent the message from triggering the 'message waiting in buffer' interrupts. So, the best bet is that you check for a message in a buffer first rather than simply constantly attempt to receive messages. Let the CAN IC tell you that a message is waiting!
  • You can easily spam a CAN network
    Sending too many messages over the network will delay or prevent transmission of other nodes' messages. One node can send too many messages over the network preventing another from successfully getting messages into a third nodes' buffers. It's all down to how quickly the third node can receive the messages. If both receiving buffers are full then the message will fly on past and not be seen.
  • Inserting and removing ICs
    PLEASE only do this when you need to and do this with care! Lever them out from both ends and DO NOT just use your fingers. Insert them evenly as well. It's too damn easy to destroy these delicate and expensive components.

...next will be a node to control the thottle, isolated blocks and point-servos.

3Mar/1274

Arduino + Controller Area Network (CAN)

Stolen from Wikipedia: The CAN (controller area network) bus is a vehicle bus standard designed to allow microcontrollers and devices to communicate with each other within a vehicle without a host computer. This bus standard includes it's own messaging protocol for communications between nodes on the network.

One of the most popular uses for this technology is in the automobile where the network provides a communication channel between the ECU, Transmission, airbags, braking systems, etc...

As you'll have noticed, I've recently been investigating OpenLCB which uses this technology for communications between its nodes on a model railway. The article below will show how the CAN bus can be incorporated with an Arduino to allow communications between different microcontrollers/nodes on your network.

Topography

The OpenLCB project dictates that the CAN bus implemented via their standards must not be in the form of a ring. When I initially saw the Railstars:io prototype I expected that a ring would be required; the prototype shows an 'in' and 'out' communications port. Little did I realise that, upon closer inspection, the io could act as a termination point for the CAN bus that it connects to. We therefore will implement a layout as follows on our railways...

can-setup

The OpenLCB project will use standard RJ45 cables (i.e. ethernet cables) due to the requirement of twisted pair technology to guarantee data transmission.

Interfacing with the Arduino via SPI

The Serial Peripheral Interface is a communication standard used to provide communications between integrated circuits. The Arduino has an SPI library and therefore allows us to easily communicate to the CAN interface.

We'll be using the MCP2515 and MCP2551 integrated circuits to transmit/receive our data from SPI onto the CAN bus. This setup has been done before in Sparkfun's CAN-BUS Shield, the CAN-CAN, the Universal CAN Library (Universelle CAN Bibliothek) and the CANduino. The CAN-CAN Schematic and Sparkfun's schematics provide a great reference point for hooking the whole lot up. Of course, you could also just grab their shield if you don't want to build everything yourself.

Schematic

The image below should be pretty self-explanatory. See the next section for the exact pins for the SPI interface. RESET and INT can go to any digital pin.

MCP2515

Building, troubleshooting and talking to one's self

I built two at the same time to be able to test node-to-node communications. There was nothing overly tricky in the construction... I just chose to use relatively tight pcb prototyping boards which didn't leave much room for error. The above schematic was followed and the devices were hooked up to my Arduino(s).

Initial board

I tried the loopback test from the canduino project and got random responses... the data going in was not the same as the data coming back. I started the debugging process after letting out a little sigh.

It turns out that, on all Arduinos, the SPI interface can only be used on specific pins:

SPI Pin Arduino Mega Smaller Arduinos (168,328)
SS/CS 53 10
MOSI 51 11
MISO 50 12
SCK 52 13

Note that the CAN library also then required a change as the pins in it are hard-coded to a 168/328 Arduino and wouldn't have ever worked with the Mega. You can find my fix for this down below.

I finally had responses after the pins were in the correct locations... but not the responses I wanted to see; I looked at the crystals next. My Arduinos all used 16.000MHZ crystals, but my local hobby shop only had 4mhz, 8mhz or 20mhz. This concerned me and I google'd and google'd to work out if, in the same circuit, multiple ICs could be driven off different oscillation rates. I decided that, since the 'SPI' interface had it's own 'bus rate' and the CAN bus also had it's own 'bus rate' that the crystals therefore did not affect these speeds. Also, the Arduino would dictate the speed of the SPI interface since it was the master (and slower.) I therefore bought 20mhz crystals for the MCP2515 chips, with my fingers crossed. Of course, this could have been the next issue.

Fortunately, from my previous attempts at barebones Arduinos, I had a 16mhz crystal on-hand. I swapped out the 2 capacitors and the 20mhz for the 16mhz and hooked it all up again. Nothing...

So, I then whipped out my Atmega328p 'barebones' Arduino and hooked it up to that. The SPI pins were different, as per above, so I made sure they were correct... and the CAN library from the canduino source had to be modified back to the required pins. After putting it all together I checked the serial output in the Arduino Serial Monitor and saw the correct response. The loop back test was working!

WTH... there was no reason that it should... except that maybe the SPI interface on my Mega was fried? I then, just because I hate caution and feed it to the wind all the time, swapped the 20mhz crystal and capacitors back in. It STILL WORKED! Good... I could keep the 16mhz for my other barebones Arduino.

So... with a known-working CAN node, I swapped it back onto the Mega. WTH... it worked. I now had my CAN nodes (by this time the other node built was also functioning thanks to it's guinea pig brother) talking to themselves. It was time to get them to talk to each other!

Talking in the CAN

Hah... there's an unwritten rule to not talk whilst in the toilet, but in our situation we'll make an exception. From the start I'd built the bus and was just itching to get the damn thing transmitting messages. The setup was simple: terminal blocks were used at junctions and standard dodgy speaker wire was the main network cable. 120ohm resistors were the terminators as per the standard CAN specification.

Terminators One node setup

The only real issues here were the source code (or my lack of knowledge of how it worked) and the usage of crystals. Yes, they came back to haunt me... it turns out that, whilst I had the loopback going, I'd left a 16mhz on one node and a 20mhz on the other. In the source code you specify the 'CAN Bus Speed' which, of course, was configured the same on both Arduinos. The actual issue was that, when the Arduino told the CAN controller to run at bus speed '1000', the CAN nodes did this but, due to their differing crystals, their calculations of what '1000' meant were incorrect! Since one was running 4mhz faster (20mhz vs. 16mhz) it must've been communicating on the bus at a different rate and therefore confusing the hell out of the other node.

The next issue was the code... I looked over it and thought that each node would take turns in transmitting and recieving... I was wrong: you had to actually set one as the sender and one as the receiver. I configured this based on the Arduino class (by #IFDEF just as the SPI pins were configured) and then had communication! My nodes were live and functional!

Communicating More communications

RX/TX LEDs

The final step was wanting RX/TX activity LEDs. It turns out that the MCP2515 supports this, but you need to do a little configuration. If you view the datasheet at microchip you'll note that the RXnBF Pins can be configured as 'nothing', 'general outputs' or 'low on RX buffer full'. I was hoping that obe would be 'high on TX buffer', but no such luck. It actually turns out that the chip has two RX buffers and therefore two RXnBF Pins. LEDs attached to these pins will, once configured as per below, illuminate once the associated RX buffer is full. If you ever see both full then you might be losing data?

RX TX LEDs

Second option: It turns out that in the MCP2515 Demo Board PDF that you can just put two LEDs on the RXCAN(1)/TXCAN(2) pins of the MCP2515.

Third option: It seems that you can also configure the INT pin to fire on TX buffer 'emptying'. You'll have to disable the pin firing on all other error situations to do this. By default, this pin is usually pulled 'high' by the MCU, so you must either disconnect that, use a resistor between the MCU and MCP2515 or just pull the pin high normally via a pullup resistor and then connect an LED in parallel with this to the INT pin. I imagine that in more complicated scenarios you'd actually want to know once the MCP2515 has generated an interrupt.

IDs: Standard or Extended?

All messages sent on the network have a 'frame id' of either (standard mode) 11-bits or (extended mode) 29-bits. It must be understood that this 'frame id' does not actually identify a node! It is simply an identifier for the actual message being transmitted. This identifier can contain any form of information you want; the bits are yours to play with.

One main use for this identifier is to record the intended recipient of the message you are sending. Depending on the amount of nodes in your network (don't forget to think of future scalability!) you can use anywhere up to 29-bits to uniquely identify them. Of course, this identifier could just be used to identify the 'class' of node and then you could put further data in the message to indicate the exact recipient. You could also go the other way and only use a portion of the identifier for the recipient code and have the rest for other uses.

The MCP2515 has in-built filtering to work on the identifier of incoming messages. If you're only using standard mode then the filters also apply to the first two bytes of the message. The filtering works inside the MCP2515 and therefore doesn't saturate your SPI link as the messages are stopped prior to being put into the RX buffer.

MCP2515 Modes

There's 5 modes that you can set the MCP2515 into. These are as follows:

Mode Description
Configuration This mode allows the developer to update settings. The following settings require this mode to be set first: CNF1,CNF2,CNF3,TXRTSCTRL,MASKS,FILTERS.
Normal Standard operating mode. RXM0 and RXM1 per buffer do not apply in this mode. All filters and Masks do apply.
Sleep Low-power mode. SPI remains active, and the MCP2515 will wake up if there is activity on the CAN bus if the WAKIE/WAKIF interrupts are enabled. After woken, the chip will be in Listen Mode.
Listen Make sure there are two or more nodes on the CAN bus. Whilst in Listen mode, the chip won't output a thing, so if another chip sends a message then the message will constantly circulate on the bus if there is no other node to 'ACK' it. Another node must be there to stop the message transmission. RXM0 and RXM1 per buffer apply in this mode and the masks/filters also do too.
Loopback All messages sent are returned via the RX buffers, filtered first. No messages are sent out over the CAN. No messages are received from the CAN.

Buffers

It needs to be noted that the MCP2515 has two receiving buffers known as Buffer 0 and Buffer 1. Messages will go to the first if it's free (and not filtered) and then the second. Filters can be set on both, but the second buffer is much more flexible with four filters.

I don't know the exact reason for the MCP2515 containing two buffers, and then why one is more flexibile than the other, but in the end it's up to the developer as to how to use them. Filters can be configured to allow specific message 'types' on each buffer. This then means that, for example, the developer could configure the second buffer to only allow emergency messages such as 'STOP THAT TRAIN' whilst the first deals with the standard communications.

Filtering CAN Messages via the MCP2515

With the base configuration, an MCP2515 controller will accept any messages sent across the network. This therefore means that your nodes need to filter each individual message coming across the bus to determine if they themselves are the intended recipient. Fortunately the MCP2515 has in-built configurable filtering to allow only messages intended for the node to be passed through its RX buffers.

The MCP2515 has 6 configurable filters with 2 masks. The first mask works in conjunction with the first two filters and applies to the first receiving buffer whereas the second mask works with the final 4 filters and works with the second receiving buffer. Filtering is enabled when any bit of a mask is '1' and disabled when the masks are completely zero'd out.

You may be wondering why both a mask and a filter are needed? As mentioned above, you may not have used the entire 'identifier' area of the sent message to indicate the recipient. Therefore, when you're checking an incoming message, you wont want to filter the entire identifier. As the identifier bits can be a '1' or '0', you need to initially specify which bits you want to check (mask) and then whether or not they are a '1' or '0' (filter).

Node 1 ('101') Node 2 ('110')
Identifier 10110 10110
Mask 00111 00110
AND'd 00110 00110
Filter 00101 00110
Match? False True

In the table above, you can see that Node 1 failed to match. The filter applied was looking for '101' (5 in decimal) but the lower 3 bits identifier (that's what the mask was looking for) was actually '110' (6 in decimal). You can see that the actual result was '110' after the mask was applied to the identifier. The second node matched as the filter is actually looking for '110'.

Now, we have to use the full registers when we apply this to the MCP2515. This means filling out 29bits of data. When in doubt, fill everything else with zeroes. Each register in the MCP2515 is 8bytes, this therefore means that you need 4 bytes per filter and 4 bytes per mask. The 6 filters and 2 masks that were mentioned above are located in the following areas:

Mask 0 Filter 0 Filter 1 Mask 1 Filter 2 Filter 3 Filter 4 Filter 5
0x20 0x00 0x04 0x24 0x08 0x10 0x14 0x18
0x21 0x01 0x05 0x25 0x09 0x11 0x15 0x19
0x22 0x02 0x06 0x26 0x0a 0x12 0x16 0x1a
0x23 0x03 0x07 0x27 0x0b 0x13 0x17 0x1b

Right, now that you know you need 4 bytes for a filter and then 4 bytes for a mask... and you know where to store them... you'll probably now need to know how to construct a mask and filter. We'll start with a mask that looks for the value 11 (decimal!) [0x0b in hex, 1011 in binary] in the standard 11-bit identifier. As you can guess, I've just provided the filter by representing the value in binary; we simply need to zero-out the bits to the left to ensure we provide the correct number. Have I provided the mask? No! Look at the truth table below if we were to use 1011 as the mask.

Node 1 ('11011') Node 2 ('01111') Node 3 ('01011')
Identifier 11111 11011 01011
Mask 01011 01011 01011
AND'd 01011 01011 01011
Filter 01011 01011 01011
Match? True True True

They all matched!?!?!? Since we were only checking the 'exact' value via the mask, we weren't actually looking to see if any of the bits around the value were set. The basic principal is that we need to know the maximum length of the value we could be looking for and then use that as the mask. For example, if you have up to '11111' (32 including '0') ids on your network, then you want to make sure that your mask is '11111' and that your filter is the exact number of the node checking if the message is theirs.

Node 1 ('01011') Node 2 ('01111') Node 3 ('11011')
Identifier 11111 11011 01011
Mask 11111 11111 11111
AND'd 11111 11011 01011
Filter 01011 01011 01011
Match? False False True

That's better! Make sure your values are correct! So, in the example below we'll use '11111' as the max value and therefore the mask. We'll then use 01011 as the value of the node we're pretending to be and we'll insert these into the correct registers (being Mask 0 and Filter 0.)

Message Acceptance Process

So, two buffers with differing filters... what happens when a message arrives? The basic idea is that a message will hit the first buffer and, if not accepted, attempt to hit the second buffer. The message is then discarded if the second buffer is also configured to not accept this message.

Note: There are also two bits (RXM0 and RXM1) in the RXBnCTRL (where n is either 0 or 1 depending on the buffer) that determine how messages are accepted. Note: My code currently has the ability to set these registers; for the life of me I cannot actually get the chip to function as per the datasheet when these registers are set. If anyone else has succeeded in using the RXM bits successfully then please leave a comment and tell how you did it!

RXM0 RXM0 Description
0 0 [Default] Enable reception of all valid messages as determined by the appropriate acceptance filters. (See the pseudo-code below as to how the masks and filters apply.)
0 1 Only accept standard messages. Filters are useless if the EXIDE bit does not match with this value.
For example, if you put an extended filter on buffer 0 but you disable extended messages to buffer zero with this configuration then that filter will never be used.
1 0 Only accept extended messages. The same rules apply that any standard filters on a buffer with this setting will not be used.
1 1 Receive ALL messages regardless of filters. Also recieve messages that have caused an error during transmission. The fragment of message received in the buffer prior to the error will be brought through. This mode should really only be used for debugging a CAN system.

So, as long as the RXM bits are both set to '0', the message buffers will then process through the following procedure to accept or deny messages.

  for EACH BUFFER b: (initially 0)
    if (MASK 'b' is ZERO) { //mask 0 for buffer 0 and mask 1 for buffer 1
      Accept new message on Buffer b
    } else {
      using FILTERs 0,1 (if b equals 0) OR FILTERs 2,3,4,5 (if b equals 1)
        if (both the message and filter are 'extended') or (both the message and filter are 'standard') then
          for each '1' in MASK as 'x', does FILTER[x] equal message[x]?
            if all match then accept message
            else check next filter as this filters bits do not match the relevant message bits.
        else check next filter as this filter type does not match this message type.
      if still not accepted then TRY BUFFER 1
    }

A mask is disabled when all its bits are '0'. As soon as a bit is '1' then that mask applies to the relevant buffer. As per the section above, the bits in the filter are then checked against the relevant message bits based on what bits the mask specifies the process to check.

On the contrary, a filter is not 'disabled' when all bits are '0'; instead you have configured two filters, on the buffer related to the mask, which will only permit standard messages where the identifier is zero. If you set the mask on a buffer to anything other than 0 and then don't touch the filters, this will prevent extended messages from coming through (as both filters have '0' as the EXIDE bit) and also prevent any standard messages that do not have an identifier of zero.

In the event that you don't want to receive a specific message type, you must put a mask on both receiving buffers and then an appropriate filter to block out the specific identifier bits. On the contrary, make sure that your masks and filters are smart enough to capture all other data required for your CAN node.

If in doubt, write an 'all-seeing' debugging application to view all traffic on your bus... it'll allow you to diagnose why messages are landing where you might not want them to. As per above, setting both RXM bits to 1 will bypass your filters; this way you don't have to muck around with your own configuration too much. Just make sure you have more than two other nodes on the bus if you want another in Listen mode. Having one node on the bus, or two with one in listen mode, will mean that any message transmitted will stay perpetually on the wire. A message must be consumed by another node for it to disappear.

Storing Masks and Filters on the MCP2515

Scroll up to see the register addresses for the masks and filters. The contents of each of these registers looks as follows:

Filter/Mask Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0
Byte 0 (RX[F|M]nSIDH)* SID10 SID09 SID08 SID07 SID06 SID05 SID04 SID03
Byte 1 (RX[F|M]nSIDL)* SID02 SID01 SID00 –– EXIDE/––** –– EID17^ EID16^
Byte 2 (RX[F|M]nEID8)* EID15 EID14 EID13 EID12 EID11 EID10 EID09 EID08
Byte 3 (RX[F|M]nEID0)* EID07 EID06 EID05 EID04 EID03 EID02 EID01 EID00
  • *: 'n' is the filter number, i.e. RXF0SIDH is the 'Standard ID High Receive Register Filter 0'.
    [F|M] means that the name is 'RXF1SIDH' for Filter 1 and 'RXM1SIDH' for Mask 1.
  • **: 'EXIDE': set this to '1' and this filter will only apply to Extended IDs, '0' means it will only apply to standard IDs.
    This byte is unimplemented for Masks. Just leave it as zero.
  • ^: These two bits are not used if you are in standard mode as you only need 16 bits to check the first two bytes of data.

Have I lost you yet? Each filter and mask needs to be able to store both the Standard ID bits and the Extended ID bits. As mentioned before, if you're in standard mode then the 'lower' two bytes (i.e. bits 16 to 0 [17,18 are ignored!]) of the extended area are for matching against the first two bytes of data. You can disable this by ensuring that the associated mask has zeroes in the extended area. On the contrary, if you wanted to check the first byte in the data for a specific value then you would pass in '001111111100000000' as the extended area of the mask with the relevant extended bits set in filter.

Somewhere up above I mentioned we'd use '11111' for the mask and '01011' for the node id. We'll now store this in the registers. We'll use Mask 0 and Filter 0 for this and we'll make sure the rest are all zeroes so they don't apply. You'll note that the first register (RXM0SIDH) starts with zeros; as per above this means that the identifier could actually contain any data in this area and, since the mask is '0' for these bits, the acceptance process wont care at all! The registers will need to be set as follows:

Register Data Register Data
RXM0SIDH [0x20] 0b00000011 RXF0SIDH [0x00] 0b00000001
RXM0SIDL [0x21] 0b11100000 RXF0SIDL [0x01] 0b01100000
RXM0EID8 [0x22] 0b00000000 RXF0EID8 [0x02] 0b00000000
RXM0EID0 [0x23] 0b00000000 RXF0EID0 [0x03] 0b00000000
Note: All other Registers in the RXF/RXM space need to be zero'd out!

So, as you can see above, we've put the mask 0b00000011111 in the 'standard id area' of Mask 0 and 0b00000001011 in the 'standard id area' of filter 0. Based on our logic above this will then only allow messages through that match the above requirements. Below is the code to actually do this on the Arduino.

#define MASK_0 0x20
#define FILTER_0 0x00
void CANClass::setMaskOrFilter(byte mask, byte b0, byte b1, byte b2, byte b3) {
	setMode(CONFIGURATION);  
	setRegister(mask, b0);
	setRegister(mask+1, b1);
	setRegister(mask+2, b2);
	setRegister(mask+3, b3);
	setMode(NORMAL);
}

//set MASK 0 for RXB0 a mask checks all bits of the standard id.
CAN.setMaskOrFilter(MASK_0,   0b11111111, 0b11100000, 0b00000000, 0b00000000);
//set Filter 0 to 0x555. Therefore only messages with frame id: 0x555 are allowed through this buffer. 
CAN.setMaskOrFilter(FILTER_0, 0b10101010, 0b10100000, 0b00000000, 0b00000000);

Note that only setting this for buffer 0 will mean that any message that doesn't match will come through on buffer 1. You'll need to also set a mask on buffer 1 to stop the messages completely. Of course, you can also only ever check buffer 0 for messages and not care if buffer 1 has anything waiting.

Filters in action: Guessing game.

Ok, who would've thought you could make microcontrollers play a game together. You know the old trick, someone else chooses a 'random' number and you get to 'randomly' guess it. Why don't we make our Arduino's play the same game?

We'll set the filter on buffer 0 to the number the receiver is thinking of. This means that the sender will only actually get a message through to the receiver if they guess the correct identifier. Both controllers will then swap roles. Just to make life easier we'll limit the range of numbers allowed, but we'll still make the guessing as 'random' as possible.

I could paste the full code here, but instead I'll just post the general idea.

Main setup
Set Mask of Buffer 0 to the 11-bit standard identifier
Set Mask of buffer 1 to the same 11-bit id
set filter 2 (first filter of buffer 1) to a specific ID for messages that aren't guesses.
Set one node to RX and one to TX
Initialise the random generator.
Receiver Role Transmitter Role
  1. Randomly set 'guess' number from known range.
  2. Set Filter 0 to guess number.
  3. Sit and wait for transmitter to guess...
    - if they send a message on buffer 1 then pass it on to the host.
    - if they get through on buffer 0 then it's their turn.
  1. Randomly choose a number to guess.
  2. Set the frame id of the message and send.
  3. Wait for response, if found then we won, swap to receiver.
  4. If no response, send guessed number to buffer 1 of receiver.
  5. Loop and guess another number if required.

Source code (including my version of the CAN Library)

The final piece of the puzzle is always the source code. I've included the guessing game example as well. Note that my code is based off the canduino and I intend to send changes upstream where possible to make life easier for everyone.

Download the library and example here.
29Feb/129

Arduino + Thermal Printers (Sparkfun, IBM 4160-TF6)

I've always wanted to print my own receipts... devious activities come to mind; but the following usage of receipt printers is nothing sinister at all. My goal is to print out activities for trains on the layout; certain locations will have a new reporting mechanism!

I'd seen a few printers on eBay, most being USB. Serial was always to be my preferred method and I had the components on hand. I then saw the Thermal Printer at Sparkfun and decided that it'd be my first guinea pig.

Sparkfun Thermal Printer

The Sparkfun themal printer is, like most of their products, targetted at the Arduino. Thanks to this there is a wealth of information on their page on how to connect and use it. After hooking up a proper power supply (they recommend 9v @ 2Amps, so use a 7809 with a heatsink!) the printer just started spewing out whatever I threw at it.

Sparkfun Thermal Printer

The easiest way to use this is via the library found here: Displaying on Paper – Thermal Printer + Arduino. bildr.org is actually a really cool site full of interesting projects for the Arduino, check it out when you can!

There's a forum for discussing the above library, in which I've already posted my praises to the developer. If you need a hand then go over and ask away... they're always open to feedback and improvements to the library too!

Note that this printer uses small rolls of 58mm paper. I found a 10-pack of these at OfficeWorks (Australia) for AUD$9.95.

IBM 4610-TF6 (on Windows)

I'd finally found a dirt cheap printer on eBay that was RS-232. It was a chunky/retro IBM thermal printer and really was just a larger, more robust version of the Sparkfun thermal printer above. It didn't come with a power supply and, after purchasing, I realised that it wanted 38v! What the hell? It seems that the 'thermal' side of it uses a lot of current to burn the paper! It also wanted 3 AMPS at 38v... where the hell would I find that?

Split open IBM SureMark 4610-TF6 Bypassing the power socket 58mm paper output!

I installed the printer drivers here on a Windows XP 32-Bit machine (DOES NOT WORK WITH 64-Bit!) and provided it 12v @ 2A. The LED came on, but the printer showed up as 'offline'. All attempted connections via Hyper-Terminal showed the port as 'already open'; the printer driver would've been the cause. I uninstalled it and rebooted, but Hyper-Terminal wasn't receiving any responses after connecting successfully.

Middle bar not printing!

Bit Switches

I then found a second 12v power supply and chained them together... Prior to this I'd re-installed the printer drivers and, upon the boost to 24v, the printer flicked to 'online' and the LED glowed slightly brighter. I could now also use the line-feed button on the top of the printer! I opened notepad, loaded a text file from the Arduino directory and, without thinking, hit print. The printer control panel window showed the job spooling up to 20 pages and then the printer started .... and kept going ... for an hour. It printed at a rate of about 1 line per 5 seconds.

Testing output

I had no idea how to cancel it... so I had to let it go.

IBM 4610-TF6 (on the Arduino)

It was now time to make this printer talk to my Arduino Mega. I hooked it all up based on how the Sparkfun printer wiring and attempted to use the same code; nothing happened. I then used the code from Tom Taylor's Microprinter blog post. Once uploaded, I had junk coming out of the printer... It occurred to me that I probably needed a MAX232 in the middle to raise the voltages to proper RS232 levels (as per everyone elses examples!)

I hooked up the MAX232 as per the schematic below and then had a functional printer from my Arduino! Determining the actual commands to send it came next.

Printer Connection to Arduino

Proper cabling Initial DB9 Connections Two RS232 cables for the Arduino

MAX232 Setup

Fonts, spacing, etc...

Right, this gets tricky... you can either put 58mm or 80mm paper in this printer. 80mm is recommended as it has better chances of staying aligned with the paper cutter (coming out diagonally is actually an issue.) I had started with the 58mm but quickly went and bought 80mm paper (AUD$12 for 4 80x80 rolls) as I also wanted the extra printing space.

You can work out how many characters per line based on the font chosen, character spacing. It is pretty much expected that you're using 80mm paper. Font A is 10x20, Font B is 12x24 and Font C is 8x16. The Cash Receipt print line is 72 mm (2.83 inches) long. There are 576 dots per line and 203 dots per inch.

The Application Guide provides the following calculations:

  • 20 CPI ⇒ 8-dot wide character + 2-dot space (Font C) ⇒ 57 characters/line
  • 17 CPI ⇒ 10-dot wide character + 2-dot space (Font A) ⇒ 48 characters/line
  • 15 CPI ⇒ 10-dot wide character + 3-dot space (Font A) ⇒ 44 characters/line
  • 12 CPI ⇒ 12-dot wide character + 5-dot space (Font B) ⇒ 33 characters/line

More test output

Printing a Barcode

In a comment below, Jonas has asked how to print a barcode from any programming language via the serial port... Here's a list of instructions to do so:

  1. Set the Font (0x00 or 0x01):
    0x1d 0x66 FONT 0x0a
  2. Set the Text Location:
    • 0x00 - None
    • 0x01 - Above
    • 0x02 - Below
    • 0x03 - Both
    0x1d 0x66 POSITION 0x0a
  3. Set Barcode Width:
    0x1d 0x68 WIDTH 0x0a
  4. Set Barcode Height:
    0x1d 0x77 HEIGHT 0x0a
  5. Print a Barcode. 'CHARS' is the list of characters to print.
    • 0x00 - UPC-A
    • 0x01 - UPC-E
    • 0x02 - JAN13 (EAN)
    • 0x03 - JAN8 (EAN)
    • 0x04 - CODE 39
    • 0x05 - ITF
    • 0x06 - CODABAR
    • 0x07 - CODE 128 (c)
    • 0x08 - CODE 93
    • 0x09 - CODE 128 (a, b)
    0x1d 0x6b BARCODE_TYPE CHARS 0x00

A 'Hello World' example of point 4 would be:

0x1d 0x6b 0x00 0x48 0x65 0x6C 0x6C 0x6F 0x20 0x57 0x6F 0x72 0x6C 0x64 0x00

IBM SureMark Thermal Printer Library for Arduino 1.0

IBM provides a great reference document for this collection of printers: Application interface specification for IBM 4610 printers. I found it to be a little hit-and-miss as to what commands are available on the TF6, but most worked well. Either way, I built the following library which provides the following functionality:

  • Text Styles: Bold, Underline, Overline, Inverted, Arbitrary Font Scaling, Double Height/Width, Rotated, Upside-down
  • Barcode Printing: UPC-A, UPC-E, JAN13 (EAN), JAN8 (EAN), CODE 39, ITF, CODABAR, CODE 128 (c), CODE 93, CODE 128 (a, b)
  • Image Printing from data stream, image storing to printer RAM and image printing from printer RAM
  • Message storing to printer RAM and printing from printer RAM
  • Beeper sounds. (Example below has 'Mary had a little lamb')
  • Paper cutting, line spacing, line feeding, etc...
Download the library and example here.

Other references

It turns out that, if I'd google'd more, I would've found a lot more help around the traps... here's a few locations to check out:

20Feb/123

Controlling points/turnouts with Servos via the Arduino

I've managed to cook many Tomix Turnouts during my tinkering with the Arduino. The main issue has been applying too much current for too long. The actual switches that come with Tomix points are momentary and, internally, the circuit is only completed very quickly via a spring mechanism. The goal, of course, is to prevent the user from holding the power to the turnout magnet for too long. Unfortunately, I've managed to (via both coding and circuitry mistakes) apply too much power in the past and it takes very little time to melt the roadbase of Tomix Finetrack.

Due to all this, and the desire to use Peco Setrack, I'd decided that instead of Peco Turnout Motors (which also require large amounts of voltage) I'd use the smallest RC servos I could find. Off to eBay I went and the following arrived not so long ago.

9g Servo 9g Servo 9g Servo

I had no idea what servos to purchase: they seem to be rated in grams as to how much they can lift? I read in a few random locations across the web that 9g would be more than enough for switching points.

Hooking up Servos to your Arduino

This could not be easier. Arduino 1.0 already comes with the Servo Library in-built. Simply include this header and then implement the following code. The basic idea is to initialise the Servo on a specific pin (they only require one pin to be controlled) and then hook up the external power source. As per usual, it's not recommended to power too many off the USB 5v.

Servo and Rotary Encoder

Mounting Servos to control Turnouts

Got some piano wire? A paperclip? Resistor legs? Any solid piece of wire/metal/rod will work to connect your turnout to a Servo. As you can see below, I've used a .55mm 'hobby wire' to connect everything up as I don't need flexibility and I want it to be robust.

Prototype Arduino + Servo controlling point

Prototype Arduino + Servo controlling point

You could also be very tricky and build a full interlocking frame to control multiple points at once. I bought a few 'hinges' (no idea what the real word should be) to allow the rodding to turn corners but thought it easier in the end to just install another Servo :).

Rotary Encoders allow you to switch the Turnout yourself...

Rotary Encoders are 'endless' switches which usually come with 5 pins + GND. You can continually turn them, allowing for applications where you want an inifinitely adjustable value. The pins are as follows: one side has two pins which are for the 'pushbutton', as the actual stem can be pushed into the base and provides a momentary switch. The other three on the other side are for the rotor location. The inside pin is 'common' and needs to go to ground; the outside pins are 'data' and need to be hooked into digital inputs somewhere on your Arduino.

Rotary Encoder

You then simply download the rotary encoder library from PJRC, drop the main Encoder.cpp and 'utils' folder into your sketch folder and include the following source lines.

#define ENCODER_DO_NOT_USE_INTERRUPTS

#include "Encoder.h"
#include <Servo.h>

Encoder myEnc(7, 8);

Servo myservo;
long position = -999;
long srv = 0;
void setup() {                
  myservo.attach(5);
}

void loop() {
  long newPos = myEnc.read();
  if (newPos != position) {
    if (newPos < position) {
      srv += 1;
      if (srv > 180) srv = 180;
    } else {
      srv -= 1;
      if (srv < 0) srv = 0;
    }
    position = newPos;
    myservo.write(srv);    
  }
}

The code above will check if the rotary encoder has moved and, if it has, then check which direction and adjust the servo accordingly. Note that the servos will hum/jam if you try to turn them past any restrictions: i.e. once hooked to a turnout, the servo's movement will be limited and you should only move them as much as required... don't try and move them past the limits of the turnout. I'm quite sure that you will ruin either the servo or the turnout if you let it hum for too long past the movement of the switch.

What to do next?

Control your points based on timing? Or even based on track occupancy detection. Computerised turnout control will allow you to automate any movement over your layout. Of course, my current goal is to build a node for the OpenLCB project to control points via servos. This will need to store data, allow max/min settings per point, etc... but more as it gets built!

17Feb/124

Persistent Data on the Arduino (EEPROM)

It's taken me a year to realise that you can actually store data at runtime on the Arduino and happily turn it off, expecting the data to still be there when you turn it on. By this, I don't mean the code you've uploaded; I mean the actual values you've created/calculated/determined whilst your code has been executing on the Arduino.

Actually, I lie... it hasn't taken a year to 'realise'... it's taken a year to actually need the ability to store information. It occurred to me, whilst looking at Don's OpenLCB railstars products, that they'd need to store everything they 'learn' as you set them up with controller nodes. All of my previous projects would've forgotten all settings once you disconnect the power!

Memory Types on the Arduino

After a little research, it turns out that Arduinos have three types of memory areas. These would be the flash, EEPROM and SRAM. The former is the location that all 'sketches' and other compiled program code go, therefore being the largest area. The EEPROM is, depending on your chip, an area around 1k to 4k in size for storing data to be persisted. Finally the SRAM is the 'running' area where data is stored during runtime of your code.

Memory Type ATMega168 ATMega328P ATmega1280 ATmega2560
Flash 16k 32k 128k 256k
SRAM 1k 2k 8k 8k
EEPROM 512 bytes 1k 4k 4k

So, as you can see, the more you pay for the microprocessor, the more space you get to play with. I have used the Arduino Mega 1280 for a while and had never used the space available in the EEPROM... what a waste. Now I'm tinkering with the Atmega328P and, as it shows, there's a lot less space available to play with. Fortunately, depending on how frugal you are with data storage, there's more than enough for creating our OpenLCB nodes.

Working with the EEPROM

Arduino 1.0 (and all previous versions) include the EEPROM Library. This library includes two calls, being read() and write(). For the Atmega328P, I'm able to store a byte in 1024 areas. This expands to 4096 areas for the Mega.

By the way, for time-critical apps, an EEPROM write takes 3.3 ms to complete.

NOTE: As the Arduino page warns, EEPROMs are only good for 100000 writes! Please only write/update your EEPROM areas sparingly and when absolutely required.

Efficient storage of Bits/Bytes

Depending on your requirements, you may want to be more efficient in the way you store certain values. We'll start with booleans: if you're lazy and wont need to store over 1024 booleans on an Atmega328p then you can simply check the boolean and store a '1' or '0' in any of the 1024 areas. Of course, if you need more, then you'd want to efficiently use the 8 bits per byte that you have available. As each of those 8 bits can be a '1' or a '0', you can then actually store 8 booleans in each byte. It's simply a matter of 'or'ing 8 booleans together and left-shifting to ensure you set the correct bit.

byte setBit(store, bit) { //bit 1 is right-most
      store |= (1 << (bit - 1)); //set bit 5 to '1'.
}

byte clearBit(store, bit) {
      store &= !(1 << (bit - 1));
}

bool getBit(store, bit) {
      byte b = (1 << (bit - 1));
      return (store & b);
}

Arduino has a good bit of information on BitMasks and BitMath for those interested.

Using PROGMEM to store 'known' data

So, as previously mentioned, the Flash area has the most space available. The Arduino comes with the PROGMEM library for storing variables in this area. Note that you cannot easily write to this at run-time (I haven't dug far enough to work out if you really can) ... the goal is to just store large data in the flash and use it from there at runtime rather than copying to your limited SRAM first.

Firstly, you need to select from a datatype below:

Data Type Description
prog_char a signed char (1 byte) -127 to 128
prog_uchar an unsigned char (1 byte) 0 to 255
prog_int16_t a signed int (2 bytes) -32,767 to 32,768
prog_uint16_t an unsigned int (2 bytes) 0 to 65,535
prog_int32_t a signed long (4 bytes) -2,147,483,648 to * 2,147,483,647.
prog_uint32_t an unsigned long (4 bytes) 0 to 4,294,967,295

Now, declare it in the PROGMEM 'space'. It seems that the Arduino devs recommended it to be stored as an array as you'd usually only use this space for large amount of data.
I've chosen the prog_uint16_t (note that this var size is a 'word'), the code below stores two of these values and then uses them during execution.

#include 
PROGMEM prog_uint16_t myValues[] = { 123, 456 };

int k; //counter? don't quite know what for.
int readValue1, readValue2;
void setup() {
      k = 0; //read the first word. 
      readValue1 = pgm_read_word_near(charSet + k);
      k = 1;
      readValue2 = pgm_read_word_near(charSet + k);
}

void loop() {
      //now you should probably do something with these values...
}

And that's it.. I hope this helps some of you to limit your SRAM requirements and also to store data for users each time your device is switched off!

14Feb/122

Building an Arduino from scratch

OK, OpenLCB is the new cool... to make 'nodes' for it, we need a skeleton Arduino to build from. This article will define how to go about this. The goal in the end is to have a prototype that can, via the Arduino IDE, have a sketch uploaded to do as you wish.

References

Firstly, a list of random links for random information on building your own Arduino:

Serial or USB?

I know the DB-9 Serial Port is archaic... needs an Interrupt Request (IRQ) assigned to it etc, etc... but there's something nostalgic about plugging in a chunky cable instead of a new USB-B connector. It's also cheaper and easier to use parts on hand and I had a few MAX232s sitting around.

To use USB you'll need an FTDI chip to convert the USB signal from your PC to the TTL protocol of which the Arduino understands. Note that there are also FTDI chips which convert USB to RS232, the serial protocol that allows devices (specifically your old dial-up modems) to communicate over serial cables. You don't want one of these as you'd then have to convert the RS232 again to TTL.

Which Microcontroller?

Good question! Your choice of microcontroller comes down to size and quantity of digital/analogue inputs and outputs. I decided on the Atmega328P as it has enough IO lines for what I need on each OpenLCB node; I'll produce more node types and have them specialise rather than one node that does everything from one board. They're cheap on eBay and they are very similar to the MCU used in the Arduino Duemilanove (5 analogue and ~13 digital IOs.)

Schematic

You'll find schematics all over the web, although none seem to agree on what components are the exact bare-minimum for an Arduino... it actually makes it quite difficult to know exactly what you need. Below is a solid basis to start your Arduino-based invention, containing everything required to program over the serial port.

BareBones

Building the prototype

There was not much out of the ordinary on the breadboarding of this project. It's actually quite simple and the standard rules of check, check and double-check your wire placement, IC pin numbers, etc... as you go is imperative. The serial cable connection on this project, due to the cable being rigid, can cause issues of dragging the board around. I'd recommend to seat connection and cable first and secure everything to your workbench... You'll then prevent your breadboard from upending when the serial cable chooses to move around.

Programming from the IDE

The MCU chosen is the Atmega328P and, as mentioned, it's closest match is the "Arduino Duemilanove w/ Atmega328". Once everything was connected I attempted to flash using this board, selected in the Arduino GUI, but it didn't work straight away. The initial error was that the chip device ID didn't match. It turns out that the Atmega328 has as a different code to the Atmega328P (something to do with Pico Power.) I had to hack the 'avrdude.conf' file buried in the arduino folder and then it just worked.

Before I knew it I had the servo library in and a mini servo from eBay controlling a Peco point on my layout.

Re-programming an Atmega MCU

I accidentally learnt how to do this... At one point I'd put the MCU in the wrong way around and expected that I'd killed it. The circuit then failed to work after numerous attempts with the TX and/or RX lights constantly lit. It wouldn't accept sketches and I therefore thought the best bet was to re-flash the bootloader + program.

It turns out that my Arduino Mega can be used as an In-Serial Programmer and so I set this up. This can be selected via the "Arduino ISP" option in the "Programmer" menu under the new Arduino 1.0 software.

ArduinoMegaISP

(Note that the capacitor from +5v to RESET is a 100n non-polarised.)

After the re-flash and a reconfigure of the MAX232 in/outs (the schematic above is the final version that now works perfectly) it all just worked again... for one of the MCUs anyway. The second simply refused to receive sketches; the RX light would not turn off. I took this as a fundamental failure in the chip (I blame my bread-boarding skills) and therefore tried something sneaky: I copied the entire code off the MCU that worked and flashed it to the 'broken' one with avrdude and it's associated avrdude-GUI [direct download link]. It turns out this worked... the chip now did what the previous one did... but in the MAX232 breadboard it still would not accept a new sketch from the Arduino GUI. I attempted to find other methods to 'completely erase/reset' an Atmega, but I couldn't get it to work and so just accepted it's fate of having to copy it's brother.

9Feb/120

OpenLCB: Controlling Your Model Railroad

It's been a while since anything remotely home-brew/electronic for model railways has appeared on this blog... but this is about to change. It's now time to try a third method of electronic control after previous attempts of controlling via DCC Boosters and then Arduino Microprocessors.

Don E. Goodman-Wilson, who you would've seen commenting on a few of my posts here regarding DCC and Arduino, has gone all-out and started production of some pretty amazing technology. He's started a company called railstars which is currently providing DCC boosters, central units and throttles. Not only are these perfectly marketed and designed, they also now incorporate a new concept known as OpenLCB.

OpenLCB

OpenLCB is an initiative by the OpenLCB team to define a network (protocol and required hardware) to control pretty much everything on your model railway. The end result is layout control and automation which is easy to install, configure and extend. As of the 9th of February 2012, there are motions for NMRA to work closely with the OpenLCB project in a venture named NMRAnet... stay tuned for more information on that!

It should be noted that the OpenLCB team is still in the early stages of design work and, although prototypes have been built and tested, there is a lot of work to do to get final products to market.

The basic concept consists of a control bus with nodes located along a network bus, terminated at each end. Each node has it's own processor that can create and respond to events. Events can be anything from controlling accessories and trains on your layout to sending informational messages to remote displays. With this, you can have a node controlling points around your layout, a node controlling trains indirectly via DCC and a final node acting as a control panel with buttons and switches configured to send specific events.

In case you were wondering, the OpenLCB venture has no intention to interact with DCC. Other parties, such as Don with his railstars products, are currently bringing DCC in as an option, but do not intend to outright replace it! Don's efforts with railstars OpenLCB components will allow DCC commands to be transmitted over the OpenLCB protocol allowing each node on the network to respond appropriately. A lot of opportunities will open up with this as you will then be able to use the OpenLCB network to transmit DCC information, allowing completely separate DCC blocks on your layout.

You can find a lot more information about OpenLCB here at their 'First Look' page.

I want to control my DC Layout?

There are currently no nodes designed for use as standard DC throttles; fortunately, controlling DC layouts via the OpenLCB bus should be completely feasible! As per my previous articles on Arduino control of model railways, a simple PWM motor controller is all that is required to supply a model railway with the appropriate power levels. Since OpenLCB is also very compatible with Arduino, it would also therefore be quite practical to transform an Arduino+Motor Controller into an OpenLCB 'node'. This would mean that any 'controller node' could then send 'events' to the 'pwm node' which would then act accordingly... be that 'supply 50% throttle'.

I'd spoken to Don on this concept and he indicated that the OpenLCB key concept was to control 'Trains' rather than 'Blocks'. This is the same as DCC... as you supply the same power+data to all rails on your layout and the locomotives respond only when called. The issue then with DC control is that trains, sitting in blocks, will respond as soon as you apply power. One answer would be to have detection circuits around the layout which would follow movement and assume where each train was. Another would be to have the 'pwm nodes' act simply as 'accessories' that supply power to each block. This concept is still under discussion.

What's Next...

I really do want to get into development and testing of the OpenLCB system. Fortunately the whole lot is open source and one can even use standard Arduinos as 'nodes' based on the code available in the OpenLCB repository. Once I have enough components I'll be building and connecting a few nodes to test the communications functionality. After that I'll go ahead and design a block-controller and pwm node. At the least this will allow me to prototype some ideas whilst controlling my latest n-scale-in-a-table layout.

The OpenLCB project will also shortly be offering a 'dev kit' to parties interested in developing for the OpenLCB project. It will have enough components to create a local network able to control a layout. You can find out more information on the Japanese Modelling & Japan Rail Enthusiasts Forum.

I intend on keeping everyone updated as I tackle the concept of DC in the newly formed OpenLCB realm.

10Nov/112

Lima HO NS Koploper

I purchased one of these from Schaal Treinen Huis in Amsterdam after travelling on one to Groningen. The Koploper reminds me a lot of the JR West Thunderbird (683 Series).

The review? It runs like a dog due to it only having a single motorised end carriage (fortunately with all-wheel pickup) and the lighting shines brightly though the shell.

Lima HO NS Koploper Lima HO NS Koploper Lima HO NS Koploper

Lima HO NS Koploper Lima HO NS Koploper Lima HO NS Koploper Lima HO NS Koploper

As you can see, the train I bought included an add-on carriage and all packaging. The price tag was on-par with what I'm seeing on eBay nowadays. The train was in a glass cabinet on display when I bought it and I didn't realise that the base package only contained one coach. I have since found and purchased another coach from eBay and will attempt to extend this set. You can also see in the comparison shot of the two passenger cars that they are slightly differing in colour. Unfortunately, this is just a side-effect from purchasing second-hand; I have no idea what their story is and if the main set was left in the sun too long...

Lima HO NS Koploper Lima HO NS Koploper Lima HO NS Koploper Lima HO NS Koploper

Either way, it's a great looking train set.

7Nov/110

The Southern Spirit – November 2011

Right, it's that time of year again... The Southern Spirit was tabled to come back through Melbourne from Adelaide on the 5th and 6th of November. What better excuse for a drive out west to see what had been happening...

Of course, there's always concerns that driving 400kms might be a complete waste of time and this TAA on occupations near Great Western should have probably received more of my attention. Just in case you're wondering... an 'occupation' is where the Australian Rail Track Corporation has requested complete manual control of a section of track. In this case it was the area between Pyrenees Loop – Great Western Loop and Great Western Loop – Deep Lead Loop... they were to do ballast cleaning!? ... this might actually be worth the trek for!

Planning

As per usual, I perused through ARTC's Train Alteration Advice and determined items which might have applied to the 5th of November; fortunately there was nothing apart from the above ballast cleaning. I therefore recorded the times on ARTC's timetables for the area into a diamond diagram and, from this, worked out where I should have been when. I, this time, wanted to check out places I hadn't been to yet and therefore started working out what train I could see where.

Diamond diagram for chasing the SS

How to read the above? The vertical axis shows the time-of-day and the horizontal the location. Each location has an arrival and departure time... so if you see a flat horizontal line for any service then it means that train has not stopped. Therefore, the train with the flat line will be moving whilst the diagonal will be waiting in a loop when you see two lines intersecting.

From the above you can see where all the regularly scheduled trains cross. I had errands to run on Saturday morning and, based on google maps estimates, could only just get to Tatyoon Loop by 11:00am. This would just be enough to see 6AM3 pass The Overland. The goal was then to wait for the Mineral Sands from Portland and follow it through to Murtoa. I would then wait for the Horsham container train, arriving in time to see the Southern Spirit arrive. 4PM6 would then be following and I'd choose a point along the way back to see this again.

Tatyoon

No, not Tatooine... there's no pod racing here. This was meant to be a loop for a pass, but it didn't seem anywhere near long enough. There was a seemingly-abandoned grain silo with a definitely unused siding for it. The poor old station platform didn't even have a station sign on it anymore... I imagine the last passenger service here would've been steam-hauled?

Tatyoon Station Silos at Tatyoon Silos at Tatyoon
Silos at Tatyoon Tatyoon Station Silos at Tatyoon Silos at Tatyoon Water tanks at Tatyoon

I waited up until the time 6AM3 was meant to arrive but realised that I was lying to myself and it wasn't coming. The lighting at Tatyoon wasn't the best for The Overland, so I bolted to Maroona and waited for it there. At the western-end of the loop was a great view with the railway sweeping to the left... it would've been perfect in the morning sun for a Melbourne-bound freighter!

Tatyoon - Looking towards Maroona Tatyoon - Looking towards Maroona Tatyoon - Looking towards Tatyoon

Maroona

Yes, Ma-roo-na. Not to be confused with: Mooroopna, Moorooduc, Maroondah, Maroota, Mooralla, etc...
This township is located due-south of Ararat (not do be confused with Ballarat) and ... there isn't much to it. Fortunately, there's a junction here to Portland which means the railway infrastructure was slightly interesting. The roads in the yard had been used recently and it seems that the trains to Portland must arrive into the yard and then depart, crossing the main.

Maroona Station Maroona Station Maroona Station
Maroona Station Maroona Station Old point levers at Maroona
Maroona Yard Maroona Station Line to Portland Maroona Station Maroona Station

The Overland, running 25 minutes late, arrived from the East and proceeded at a slower-than-usual pace through the station. This was the first and last time I was to see it.

Overland approaching Maroona Overland approaching Maroona Overland passing Maroona

I then waited for the Mineral Sands train... but realised it was never going to turn up. I therefore decided the better option was to bypass Ararat and head to Murtoa.

Murtoa

I'd never been here either... It's a large detour from the highway and it's the reason why I previously beat The Overland to Horsham as, although it can do 115km/h, the path via Murtoa adds quite a few more kilometres. Of course, it also meant I wouldn't see The Overland at Murtoa as I was never going to catch up to it on the country roads. Murtoa is the junction for the branch North to Hopetoun... the rails were quite shiny, so something must've run that way recently, but the Mineral Sands train wasn't to run this day.

Murtoa Yard Line to Warracknabeal/Hopetoun Looking towards Murtoa Station

I decided that I'd wait here for the Horsham freight. There was no reason it wasn't running, but as The Overland was 25mins late, this train would probably also be late.

Grain infrastructure at Murtoa Murtoa Station Murtoa Station

After dealing with wildlife (brown snakes, etc..) the train came through fast.

8030+GML10 on Horsham freight

8030+GML10 on Horsham freight

I then jumped in the car to Horsham... expecting to see the tail of this train, but it had a headstart on me and there was no chance.

Horsham

Last time we saw C501 and T386 doing the Horsham freight, this time it was 8030 and GML10. Other than that, not much as changed... same colourful characters on the platform watching the trains go by. Actually, there is now a rail tractor LOK001 doing the shunting/splitting of the container train instead of the actual locos that brought it in.

Rail Tractor used for shunting Rail tractor at Horsham 8030+GML10 at Horhsam
GML10 at Horsham 8030+7334 at Horsham LOK001+8030+GML10 at Horsham

NR85 brought the Southern Spirit in around 20mins late. The consist was as long as usual.

NR85 on Southern Spirit at Horsham Horsham Station Southern Spirit at Horsham

NR85 on Southern Spirit at Horsham

Southern Spirit at Horsham Southern Spirit at Horsham Southern Spirit at Horsham

And then 4PM6 came through on time based on its amended running.

4PM6 passes Southern Spirit at Horsham

4PM6 passes Southern Spirit at Horsham

And that was it... the day had turned dim and the freighter was running with the light for the rest of the trip... I chose to return home.

Ararat

So, the initial TAA I mentioned had something about ballast cleaning in it? I forgot to tell you that I actually saw the track gang in the first loop directly after Ararat. It had to be a loop (was a fair distance from the highway) as The Overland had already bolted through. I was hoping they'd be in a location closer to a road on the way back, but they'd already packed up and were in Ararat yard.

Track machines at Ararat

Track machines at Ararat

The next day...

The Southern Spirit spend the night in Maroona. It proceeded east via Melbourne but was to only stop at Broadmeadows briefly. Fortunately it was to pass the large standard gauge viaducts as per usual and I decided to catch it at the one closest to Jacana. The up V/Line SG Albury service was running around 30 minutes late, but the Southern Spirit then got the green and bolted past.

N470 on late up Albury at Jacana NR85 heads to BMS NR85 heads to BMS

NR85 heads to BMS

And that was it... this train returns via Melbourne on the 14th of November. It will actually pass via Southern Cross Station, after a pause up in Somerton. We'll see what happens...