Sunday 8 November 2015

Lab Power Supply - Transition to KiCAD and PCB

In another post I talked about learning KiCAD and converting from Altium's Circuit Maker. So now I have the Lab PSU schematic fully in KiCAD and I have created footprints for all the components. I have a PCB design and have placed an order with Seeed studio! Exciting!

I made a couple of small changes and those were :

  • I created a circuit to detect CC mode and interfaced this with the micro controller. 
  • I moved to using a 24V relay as this way I could minimize the heat losses in the regulators feeding the relay circuit.

KiCAD Schematics

First up, here is the the power circuit as drawn in KiCAD
Things to note are the 24V relay I previously mentioned, the 24V regulator that is running off the bias rectifier and the move back to a TO-220 regulator for the 5V line. I worked out that in parallel mode the voltage on the rectified is about 28V which is easily enough room for a 24V regulator. In 40V mode we have even more room. The 24V relay also has a 1.4K coil resistance so this lowers the power loss by even more.

Otherwise the circuit is as before with a transistor switching the relay and another switching the bias regulator between 24V and 40V.

Next is the pre-regulator based on the black-dog design but with the changes to minimize the voltage when the load is low.


Now I have bypassing for the comparator. The circuit that subtracts 3V from the pre-regulator got moved a little as it was easier to draw. Otherwise this is unchanged from the previous design.

The voltage and current regulator design is pretty much as before. I added resistors between the Sense+ and V+ and between Sense- and V- outputs so if the sense lines aren't hooked up the supply will still work.

The other change was the addition of the transistor circuit attached to the output of the voltage controller. The first PNP  transistor (Q8) switches off when the output goes within 0.6V of the rail. This occurs when the current limiter has kicked in and the voltage controller is driving the output to the rail to try and get the voltage up to the set point. When the PNP turns off then this turns off Q9 which will send the CCMode line low. Q9 switches the 5V line so the CCMode signal is a 5V logic signal.

Finally the digital control circuit:

As suggested by people on the EEVBlog forum, I used lines to connect signals instead of using labels. I'm not sure this makes it clearer. Otherwise the only change is that I added more bypassing as per the datasheets of the components. This meant a *lot* of additional capacitors as components like the ADUM1201 need two for each side and the micro controller has one for each power pin.

I switched back to using a crystal instead of a ceramic resonator for the ADC as the stability may effect the readings. The MCP2200 USB chip and the ATMEGA328P still use ceramic resonators as they are very convenient.

I added a ferrite to join the digital and analog power nets. This is to stop the digital noise getting back into the current sense circuit (which is also 5V).

PCB

I feel like I have been designing the PCB in my head for weeks. Every time I read a datasheet that has layout guidelines or another paper on bypassing or noise I seem more of the picture.

First I needed to pick a PCB Fab house. PCBShopper helped a lot although in the end I went with SeeedStudio as they seem well supported and popular amongst hobbiest projects. I first made sure that KiCAD was configured with the rules  which actually weren't that stringent.


The main things that drive the PCB design are:
  1. The board needs to be no more than 80 or 90mm wide so I can fit 3 of them on my heatsink side by side.
  2. The MOSFETs and regulators need to go at the back to go on the heatsink.
  3. The output needs to go at the front
  4. The analog and digital sections need to be separate. ADCs and DACs need to be at the edge.
  5. No ground plane in the analog part - star ground from the current shunt. Ground plane for the digital part.
  6. No digital lines under analog chips
  7. Fat traces for current carrying connections.
I started by placing the output MOSFET and then the pre-regulator mosfets across the back and then the LM317s. Then I put the capacitors in as they are quite large and need to be close. I figured out the best place for the input connector was in the middle but close to the back and I placed the relay and diode bridge alongside. I put the output connector at the front and all the MOVs along the front edge.

Now I have a small space at the back between the bridge and the MOSFETs for the pre-regulator and power circuits and a larger space at the front for the analog and digital control.

I router the power traces and the pre-regulator. The fat traces proved to be hard. Ideally I would have 10mm traces but 6mm was about the biggest I could really fit.

The pre-regulator was not too hard to place and route. I took the approach of starting with the main component (like a comparator or an op amp) and then starting with one of the resistors/capacitors attached to it. I placed them one at a time and choose the next one connected as I go. I try and line them up in columns (on a 0.5mm grid).

Then I placed the op amps in the analog control circuit and placed/routed the associated components. I left power and ground until last.

I switched to the digital part and after some fiddling decided to place the processor and programming header close together toward the back, then place the USB, USB controller and isolator closer to the front corner. The ADC/DAC go toward the middle (nearer to the analog part).

The digital part was very hack-and-slash compared with the analog routing. I figured out how to make a copper pour and this looked ok. I have a separate copper pour for the isolated USB part also.

The through-hole USB connector was tricky as I needed a *very* fine track to get between the pads. If I don't go between pads then the trace length difference will be too big and it could effect the reliability. This was the one spot where I had to use the minimum track size.

So I stared at it for a few days and tweaked things. In the end I placed an order. Main things I am still not sure about are 
  • If the bypass capacitors are close enough to the chips. I think this is where using smaller parts would have helped.
  • (In hindsight) if I should have put the reference in the analog section away from the digital ground plane.
  • I probably should have done a top-side AND a bottom side copper pour in the digital section.
I found this guide useful when exporting the board ready for Seeed. I had no problems getting the fab to accept the board.

Here is the board. Output MOSFET at top left, then pre-regulator MOSFETs below that. The two LM317s for 5V and VCC at bottom and the bulk cap for those nearby. The input connector, relay and diode bridge are in the middle. USB at bottom right, MOVs and ground link above that. Output connector top right. Current shunt and fuse to left of output connector.


So I have ordered the boards and the remaining parts. Now I wait!





Thursday 5 November 2015

C++ Lightweight template based encoders

I recently had to implement an encoder that could translate an ActiveMQ MapMessage into a a small number of C++ object. The traditional approach is to create a class that knows how to decode various field types and derive all the message classes from this and have them decode themselves from a MapMessage, I wanted to avoid dragging all the baggage associated with encoding/decoding into each message class object and do it another way.

A while ago I experimented with creating classes that act as a sort of template that defines the encoding format for a message. The template object is static and really just directs an encoder/decoder so it know how to populate or encode the message object. I used a simple version of this technique to solve this problem and I thought it is interesting enough to describe here in case I need it another time.

The solution I came up with looks a lot like how you would do this in Java using reflection but uses C++ and templates.

Edit: Since writing this article I went through the process of porting the code to g++ (it was originally developed using Microsoft Visual Studio 2008). Unfortunately this highlighted quite a lot of deficiencies in Visual Studio's template support so I have amended the article to cover this.

Function Pointer

The problem is how can the template object modify or read the message object contents without exposing everything (without breaking encapsulation). The answer is to use function pointers to operate the accessor functions. Say we have a class like this:

class TestMessage
{
public:
    const std::string getName() const;
    void setName( const std::string& name );
};

Then we can provide access to the name field for any instance of this class if we know what functions to call. We can use a pointer to the getName() and setName() function to provide access to the name field of any instance of a TestMessage. It's like a key you can use to unlock this field from any TestMessage. So if we define two function pointer types like this;

typedef const std::string& (TestMessage::*GetterFunc)() const;
typedef void (TestMessage::*SetterFunc(const std::string&);

Now we can get the function pointer values by doing this:

GetterFunc getter = &TestMessage::getName;
SetterFunc setter = &TestMessage::setName;

Then say we have an instance of a TestMessage, we can get or set the name field like this:

TestMessage messageInstance;

std::string nameValue = (messageInstance.*getter)();
(messageInstance.*setter)(nameValue);

Say we had a message template class that store the setter and getter function pointer for each field, we could then use these to set the message content when decoding or read the content when encoding. The template class just has to store the function pointers and can apply them to each message instance it decodes or encodes.

The tricky part is that the function pointer type varies with the message type and with the field type. We need some way of unifying this all and being able to configure a list of fields to get/set per message.

MessageTemplate template

The answer is to create a MessageTemplate base-class that is a C++ template with the message type as a parameter. Some something like this:

template<class MessageType>
class MessageTemplate
{
public:
    virtual void toFields( 
        const cms::MapMessage& mapMessage,
        MessageType&           message  const;

    virtual void fromFields(
        cms::MapMessage&       mapMessage,
        const MessageType&     message) const;

    ....
};

Now to perform these two operations, this class needs to know how to translate a message field into a message class field (a field adapter). These will vary by field type but we need a base-class for all of these so we can stuff them into a list and then iterate over them all to perform the conversion. The base FieldAdapater will looks like this:

template<class MessageType>
class FieldAdapterBase
{
public:
    FieldAdapterBase(const char *fieldName,const bool optional) 
        : m_fieldName(fieldName),m_optional(optional)
    {
    }

    virtual void toField(
        const cms::MapMessage& mapMessage, 
        MessageType& message) const=0;

    virtual void fromField(
        cms::MapMessage&       mapMessage, 
        const MessageType&     message) const=0;

protected:

     const char *m_fieldName;
     const bool m_optional;
};


In addition to the field name, the FieldAdapterBase stores if the field is optional or not. This allows for fields that don't have to always be present. The class provides a common interface for converting a single field regardless of field type.

The next step is to extend this to provide the function pointer bindings and to allow this to vary with field type. Hence we define this class:

template<class MessageType,typename FieldType>
class FieldAdapter : public FieldAdapterBase<MessageType>
{
public:
    typedef const FieldType& (MessageType::*GetterFunc)() const;
    typedef void (MessageType::*SetterFunc)(const FieldType&);

    FieldAdapter( 
        const char *fieldName,
        GetterFunc  getter,
        SetterFunc  setter,
        const bool  optional ) 
            :   FieldAdapterBase<MessageType>(fieldName,optional),
                m_getterFunc(getter),
                m_setterFunc(setter)
        {}
    
protected:

    GetterFunc  m_getterFunc;
    SetterFunc  m_setterFunc;
};

Here we define the function pointer types and we store function pointers to allow conversion. There is still no conversion going on yet. This class just provides a convenient common base for all the converters so we don't have to define the function pointer type over and over.

One problem with this class is that returning or passing const references doesn't make sense for POD types (integers etc). To make this easier we also define a POD version of the FieldAdapter:

template<class MessageType,typename FieldType>
class PODFieldAdapter : public FieldAdapterBase<MessageType>
{
public:
    typedef const FieldType (MessageType::*GetterFunc)() const;
    typedef void (MessageType::*SetterFunc)(const FieldType);

    PODFieldAdapter( 
        const char *fieldName,
        GetterFunc  getter,
        SetterFunc  setter,
        const bool  optional ) 
            :   FieldAdapterBase<MessageType>(fieldName,optional),
                m_getterFunc(getter),
                m_setterFunc(setter)
        {}
    
protected:

    GetterFunc  m_getterFunc;
    SetterFunc  m_setterFunc;
};

A FieldAdapter for encoding string types into the ActiveMQ message would then look like this:

template<class MessageType>
class StringFieldAdapter 
    : public FieldAdapter<MessageType,std::string>
{
public:
    StringFieldAdapter( 
        const char *fieldName,
        typename FieldAdapter<MessageType,std::string>::GetterFunc  getter,
        typename FieldAdapter<MessageType,std::string>::SetterFunc  setter,
        const bool  optional=false,
        const CYBERTRUST::String& defaultValue =
            CYBERTRUST::String::emptyString) 
        : FieldAdapter<MessageType,CYBERTRUST::String(
              fieldName,getter,setter,optional),
          m_defaultValue(defaultValue)
    {
    }

    virtual void toField(
        const cms::MapMessage& mapMessage, 
        MessageType& message) const
    {
        if ( this->skipOptional(mapMessage) )
        {
            return;
        }

        try
        {
            std::string value =  
                  mapMessage.getString(this->m_fieldName);
            (message.*this->m_setterFunc)(value);
        }
        catch( const cms::CMSException& e )
        {
            handleMissingFieldException(e);
        }
    }

    virtual void fromField(
        cms::MapMessage& mapMessage, 
        const MessageType& message) const
    {
        std::string value((message.*this->m_getterFunc)());

        if ( !this->m_optional || (value != m_defaultValue))
        {
            mapMessage.setString(
                 this->m_fieldName,
                 value);
        }
    }

protected:

    std::string m_defaultValue;
};

As you can see I skipped a few details like handling exceptions. The exception handling function is actually part of the base but all it does is translates the exception to something meaningful to my application.

A few other notes on this code:

  • Initially the type of the setter/getter function pointer was just GetterFunc and SetterFunc. When I compiled the code on g++ I found that I had to use the full template name AND the typename keyword to make sure the compiler knew I was talking about a type. The problem is that the compiler doesn't fully compile the templates until instantiation.
  • Whenever the code refers to an inherited data member or function I have to use the 'this->' construct as (again) the compiler doesn't fully compile the code until later.
So now we need to go back to the MessageTemplate<> class to see how to make these field adapters work. The application can sub-class a MessageTemplate and register a field adapter for each field. We need to provide a means of registering each type of field and for stuffing all the adapters in a list and processing them all. So now the MessageTemplate<> class looks like this:

template<class MessageType>
class MessageTemplate
{
public:
    virtual void toFields( 
        const cms::MapMessage& mapMessage,
        MessageType&           message  const
   {

        typename FieldAdapters::const_iterator nextFieldAdapter;

        for(    nextFieldAdapter=m_fieldAdapters.begin();
                nextFieldAdapter!=m_fieldAdapters.end();
                nextFieldAdapter++ )
        {
            (*nextFieldAdapter)->toField(mapMessage,message);
        }
   }

    virtual void fromFields(
        cms::MapMessage&       mapMessage,
        const MessageType&     message) const

    {
        typename FieldAdapters::const_iterator nextFieldAdapter;
        for(    nextFieldAdapter=m_fieldAdapters.begin();
                nextFieldAdapter!=m_fieldAdapters.end();
                nextFieldAdapter++ )
        {
            (*nextFieldAdapter)->fromField(mapMessage,message);
        }
    }

protected:


    void registerStringField(
        const char     *fieldName,
        typename StringFieldAdapter<MessageType>::GetterFunc getter,
        typename StringFieldAdapter<MessageType>::SetterFunc setter,
        const bool     optional=false,
        const std::string& defaultValue=std::string() )
    {
        m_fieldAdapters.push_back( 
            new StringFieldAdapter<MessageType>(
                fieldName,
                getter,
                setter,
                optional,
                defaultValue));
    }

    ....


    typedef std::vector< boost::shared_ptr< FieldAdapterBase<MessageType> > > FieldAdapters;

    FieldAdapters m_fieldAdapters;
};

To apply this to our TestMessage class we would define a MessageTemplate class as follows:

class TestMessageTemplate : public MessageTemplate<TestMessage>
{
public:
    TestMessageTemplate()
    {
       registerStringField(
           "Name",
            &TestMessage::getName,
            &TestMessage::setName );
    }
};

Then to use use this we do something like this:

TestMessageTemplate testMessageTemplate;

TestMessage testMessage;
// Init the testMessage contents

cms::MapMessage *mapMessage = session->createMapMessage

testMessageTemplate.fromFields(mapMessage,testMessage);

Advanved Topics

Enumerated Types

A bunch of the fields were enumerated types so I created a converter to specifically deal with these. The code is common but the enum type will vary by field.

template<class MessageType,typename EnumType>
class EnumFieldAdapter : public PODFieldAdapter<MessageType,EnumType>
{
public:
    EnumFieldAdapter( 
        const char      *fieldName,
        typename PODFieldAdapter<MessageType,EnumType>::GetterFunc      getter,
        PODFieldAdapter<MessageType,EnumType>::SetterFunc      setter,
        const bool      optional,
        const EnumType  defaultValue ) 
        :   PODFieldAdapter<MessageType,EnumType>(
                fieldName,getter,setter,optional),
            m_defaultValue(defaultValue)
    {
    }

...

};

Note that this is derived from the PODFieldAdapter as enums wouldn't normally be passed by reference. Then in MessageTemplate we define a register function like this:

    template<typename EnumType>
    void registerEnumField(
        const char *fieldName,
        typename EnumFieldAdapter<MessageType,EnumType>::GetterFunc getter,
        typename EnumFieldAdapter<MessageType,EnumType>::SetterFunc setter,
        const bool optional=false,
        const EnumType defaultValue=(EnumType)0)
    {
        m_fieldAdapters.push_back( 
            new EnumFieldAdapter<MessageType,EnumType>(
               fieldName,
               getter,
               setter,
               optional,
               defaultValue));
    }

Then say we had methods like this in out TestMessage class

enum EnumType
{
   ENUM_VALUE1,
   ENUM_VALUE2
};

const EnumType getEnumValue() const;
void setEnumValue(const EnumType value);

In our MessageTemplate class we could register this field as follows:

registerEnumField<TestMessage::EnumType>(
    "Enum_Field",
    &TestMessage::getEnumValue,
    &TestMessage::setEnumValue);

Subclasses

In my case the message types had a lot of commonality and it made sense to define base message classes and sub-classes. For example all of the response messages had common fields for the status of the operation and for returning error codes if the operation failed.

Say we had a ResponseMessage class and then another SpecialResponse that derives from this, we want the SpecialResponseMessage template to covert both the ResponseMessage fields and the SpecialResponseMessage field.

To make this work I created a class for sub-class templates as follows:

template<class ParentMessageType,class MessageType>
class MessageSubClassTemplate : public MessageTemplate<MessageType>
{
public:
    MessageSubClassTemplate( 
        const MessageTemplate<ParentMessageType>& parentTemplate ) 
            :   MessageTemplate<MessageType>(),
                m_parentTemplate(parentTemplate)
    {
    }

    void toFields(
        const cms::MapMessage& mapMessage, 
        MessageType& message) const
    {
        m_parentTemplate.toFields(mapMessage,message);
        MessageTemplate<MessageType>::toFields(mapMessage,message);
    }

    void fromFields(
        cms::MapMessage& mapMessage, 
        const MessageType& message) const
    {
        m_parentTemplate.fromFields(mapMessage,message);
        MessageTemplate<MessageType>::fromFields(
            mapMessage,
            message);
    }

protected:

    const MessageTemplate<ParentMessageType>& m_parentTemplate;
};

The basics of it are:
  • The MessageSubClassTemplate knows the MessageType has a base-type and that base type has a MessageTemplate of its own.
  • MessageSubClassTemplate derives from MessageType to implement the sub-class field conversion.
  • MessageSubClassTemplate takes as a constructor parameter a reference to the parent message class template.
  • When converting the fields, the MessageSubClassTemplate first converts the base class fields and then converts the sub-class fields (as normal).
To use this you create the base class template as before and then you create the sub-class template like this:

class SpecialResponseTemplate 
    : MessageSubClassTemplate<ResponseMessage,SpecialResponse>
{
public:
    SpecialResponseTemplate(
        const MessageTemplate<ResponseMessage>& parentTemplate )
    : MessageSubClassTemplate<ResponseMessage,SpecialResponse>(
          parentTemplate)
     {
         // register the SpecialReponse fields
     }
};

To use the SpecialResponseTemplate you construct it passing in the parent template and then use it like normal.

ResponseMessageTemplate responseMessageTemplate;
SpecialResponseTemplate specialResponseTemplate(
                           responseMessageTemplate);

SpecialResponse message;
responseMessageTemplate.toFields(mapMessage,message);

More

Other things worth doing might be to implement aggregate messages where you can have some-fields within a contained object.

At the moment you have to know what type of message to expect but it would be nice to define some factory mechanism where the system figures out what to instantiate for you and then runs the conversion. Sort of like a container for templates that does the encoding.

Anyway that's it for now but I'm sure this technique could be applied to all sorts of encoding and conversion problems.