Hard Iron Calibration of a Magnetometer Using a CSV Data File

image

I recently worked with a client to explore hard-iron calibration of a magnetometer’s output.  I found some really helpful information from Freescale in their application notes AN4246, AN4247, and AN4248.  These all relate to tilt compensation of an eCompass.  These application notes are directed toward a cell phone application.

[Read more…]

Thermistor and Thermocouple Temperature Logger Part 2

temp_logger_thermistor_test

 

This week in the epic adventure I like to call Thermistor and Thermocouple Temperature Logger Part 2, I took a look at the thermistor portion of my circuit.

[Read more…]

Thermistor and Thermocouple Temperature Logger

max31855_spi

(Image: scope capture of three T type thermocouples being read with SPI and the MAX31855 ICs)

We’ve been developing a barbecue controller as part of an R&D project.  My portion of the project is interfacing the temperature sensors to the overall system.  I’ve decided to include both thermistors and thermocouple sensors, as well as battery backup and data logging functions.  In the end the project won’t need all of that but  I wanted to come up with something “stand-alone” I could develop.

Thus far I’ve designed the schematic and first revision circuit board.  I’ve been able to test the temperature sensors, but not much else.  I did want to share the MAX31855 interface, which I found pretty cool and a definite time saver.  The Maxim Integrated Circuits’ MAX31855 (datasheet) is a cold-junction compensated thermocouple interface.  It provides a 14-bit signed digital value that is temperature in 0.25 degree C increments with +/-2 degree C accuracy.  You buy a chip specific to the thermocouple you’re using.  In our case I placed 4 of these ICs on the board and selected “T” type thermocouples.  The device uses an SPI interface, although it only outputs data.  You can see a partial schematic below (click to enlarge).

temp_logger_max31855_schematic

 

For the microcontroller interface I used the PIC16F1789, a Microchip product.  This part has 12-bit analog to digital converters and operates between 2.5V-5.5V, which works well with the battery powered system I’ve envisioned,

Configuring the SPI interface is pretty straightforward, and here is the code I used to do this.

/******************************************************************************/
/* Configure_SPIPort:
   Configures registers used to send and receive using the SPI hardware       */
/******************************************************************************/
void Configure_SPIPort(void)
{
    SSPSTATbits.SMP = 0;  // Input data sampled at middle of data output time
    SSPSTATbits.CKE = 0;   // Transmit occurs on transition from Idle to active clock state

    SSPCONbits.CKP = 0; //  Idle state for clock is a low level
    SSPCONbits.SSPM = 2; //SPI Master mode, clock = FOSC/64
    SSPCONbits.SSPEN = 1; // Enables serial port and configures SCK, SDO, SDI and SS as the source of the serial port pins

    SSPCON2 = 0;
    SSPCON3 = 0;
}

I’m running the SPI at 500KHz, which is a little fast for some SPI ICs, but the MAX31855 is spec’ed at 5MHz max speed.  The actual communication with a MAX31855 is shown in the code below.  The code is repeated for each thermocouple (with different variables).…

/******************************************************************************/
/* Read_Thermocouples:
 Reads temperature signals from MAX31855 using the SPI interface.  
 /******************************************************************************/
void Read_Thermocouples(void)
{  
    _CS_TEMP1 = 0;  // select the first MAX31855
    SSPBUF = 0xAA;          // doesn't matter what we write but H'AA' easy to see on scope
    while(SSPSTATbits.BF == 0); // wait for 8 bits to clock in
    MyTemp.B[1] = SSPBUF; // save data
    SSPBUF = 0xF0; // doesn't matter what we write but H'F0' easy to see on scope differs / from H'AA'
    while(SSPSTATbits.BF == 0); // wait for 8 bits to clock in
    MyTemp.B[0] = SSPBUF; // save data
    NV.Ints.Thermocouple1 = MyTemp.W[0]; // use union to combine bytes in 16 bit value, stick in reg
    _CS_TEMP1 = 1;   // de-select the MAX31855

    INDICATOR.Bits.THERMO1 = 0; // clear my fault flag
    if (NV.Ints.Thermocouple1 & 0x1 == 1) // check to see if an fault flag was set by MAX31855
        INDICATOR.Bits.THERMO1 = 1; // if so, then set flag in my structure
    NV.Ints.Thermocouple1 = NV.Ints.Thermocouple1>>2; // shift temperature data two to the right
    NV.Ints.Thermocouple1 = NV.Ints.Thermocouple1 & 0x3fff; // make sure upper 2 bits are clear
    if ((NV.Ints.Thermocouple1 & 0x2000) != 0 ) // check sign bit
        NV.Ints.Thermocouple1 += 0xc000; // if sign bit is set then extend sign to all 16 bits
    if (NV.Ints.Thermocouple1 == 0x1fff) // check to see if thermocouple is attached
        INDICATOR.Bits.THERMO1 = 1; // if not then set flag

The code deserves some decryption.  Here are some descriptions of the variables used above.
_CS_TEMP1: A constant that refers to the chip select pin.
INDICATOR.Bits.THERMO1: A variable structure that maintains fault conditions and other flags in the firmware.
NV.Ints.Thermocouple1: A variable structure of integers that can be stored in EEPROM and accessed via a serial UART, this is where the temperature data is stored.
MyTemp: This variable can be a little confusing in this context. It is not related to temperature.  MyTemp is a variable union that I often use as a temporary register to quickly break apart or assemble other variables.  For example, I can read two bytes from the SPI port and place them in byte sized members of the union and then use an integer sized member of the union to copy the bytes as a single 16-bit value.

union LongUnion
    {
    long LW;
    unsigned long uLW;
    int W[2];
    unsigned int uW[2];
    char B[4];
    unsigned char uB[4];
    };
union LongUnion
MyTemp;

In my firmware I select the MAX31855 by asserting the chip select pin and then sending hexadecimal 0xAA and 0xF0.  The data I send doesn’t matter, but the PIC16F1789 needs to have the SSBUF register written to in order to begin clocking data out and reading data in.  The SSPSTATbits.BF variable is defined by Microchip in this part’s header file, and will be set when the SPI receive buffer is full.  After 16 bits of data are read the chip is de-selected.  The image at the head of this blog entry shows a scope capture of this process.

Once I’ve read 16 bits I need to convert the data to a temperature value.  Not all of the bits relate to temperature so I need to adjust the values I read somewhat.  Bit 0 is a fault flag (set if there is a fault) and bit 1 is reserved (read as 0).  Additionally, bit 15 is the sign bit (using two’s compliment format this bit is set if the value is negative).  In the firmware I check the fault flag (bit 0) and then shift the 16-bits I read from the MAX31855 two places to the right.  This leaves the sign flag in the 13th bit location.  I clear the upper two bits of the register which is kind of an old school operation.  In assembly code when you shift data the carry bit can be shifted into a register.  In C I’ve never seen a “1” get shifted in, but I’ve been doing this for so many years I just can’t stop.   I then check the sign bit and if it is set I set the two highest bits of the temperature data to maintain the two’s compliment formatting.

This diagram shows the process more visually.

max31855_data

There are some additional points related to the MAX31855 that deserve mention.

First, if the thermocouple is disconnected the datasheet states that the MAX31855 will respond with a cleared sign bit and all other temperature data bits set (0x1FFF in hexadecimal).  I didn’t see that, but also didn’t delve into why it didn’t happen.

There are an additional 16-bits of data that can be read from the MAX31855.  You would read this data by clocking in 16 more bits before setting the chip select pin.   This additional data includes the 12-bit internal temperature of the IC and more details on the nature of any fault that occurs.

Lastly, the MAX31855 calculates temperature when the chip is not selected for SPI communication.  It also requires a maximum of 100mS to take the measurements.  Therefore, the fastest you can sample a thermocouple using this IC is 10Hz.

Dual Axis Solar Panel Tracker / Controller Part 5

damc_rev1

The saga of the dual axis solar panel controller continues.  As an R&D project I couldn’t put a lot of time into this design this week.  Here is what I did get accomplished.

[Read more…]

Dual Axis Solar Panel Tracker / Controller Part 4

DUAL_MC_PCB_1

I finally received the PCB for this design.  And in general it turned out okay.  There were a couple of shortcoming in my design that will force me to to re-spin the PCB, so it’ll be a while before I can finish everything up.  But having the PCB gives me the ability to debug my firmware and test the overall concept for this solar panel tracker.

[Read more…]

Simple and Low Cost Temperature and Humidity Sensor: Part 2

temp_humidity_pcb

Above you can see the primary circuitry for the simple temperature and humidity sensor I described last week.  The board shown above is part of a client’s design, so there is quite a bit more circuitry than is required for the sensor I described last week.

[Read more…]

Simple and Low Cost Temperature and Humidity Sensor

image

Here’s a simple and low cost temperature and humidity sensor.  I’ve been developing a control system for an industrial application for one of our clients.  As part of that system we have a microcontroller located in a box with some other equipment, and thought it would be good to include some environmental monitoring.  Mostly we want to know if the things get too hot, or if they start to get wet due to maintenance people spraying down the outside of the equipment boxes (which are supposed to be water proof).

[Read more…]

Dual Axis Solar Panel Controller / Tracker Part 2

SST_SMT

Last week I discussed my latest project, an accelerometer based dual axis solar tracker (that blog is here).  When starting a project its easy to get lost in the details.  For example, this project has a whole host of possible control functions and interfaces.  I’ve always found it useful to start my work on the schematic and hardware.  So that’s what I did.

Since this is an R&D project I decided to use some components I haven’t used before.  This design will control a 24VDC brushed motor, and a 12VDC brushed motor.  I’m going to use two St Microelectronics PN:  VNH3SP30-E.  They’re rated for 40V and 30A (although there’s no way they can handle 30A without melting off the PCB).  One feature I like about these controllers is that they only need a single PWM channel for proportional control.  Two other digital channels are used to provide direction.  Here’s a section of the schematic that shows the connections between a PIC16F1789 and two of the motor controllers (click the image for a better view).

image

In the end, this control system will be used to control our dual axis controller that uses a worm gear for horizontal movement, and a linear actuator for vertical movement.  Here’s a photo of the assembly in front of the old college text books we could never bring ourselves to throw away.  Both the worm gear and linear actual came with feedback.  The worm gear was very expensive and has an encoder on the motor.  the linear actuator was pretty cheap and came with a potentiometer that failed in about a month.  That was one catalyst for attempting that has the position feedback on the control board via an accelerometer.

dual_axis_panel

So for this first run at this design I generated a schematic (here’s a PDF), bill-of-materials (and another PDF), and a circuit board layout.

The circuit board ended up being about 2.5” x 3.5”.  Here’s what the top copper layer looks like.  The 6 dots on the upper and lower right-hand side of the board are for mounting automotive style blade fuses.

TOP
Finally, I ran though the list of components I selected to see if any were not able to operate over the industrial temperature range of –40C to 85C (or -40F to 185F).

Here is the column from my bill-of-materials.

TEMP_COLUMN

There are a couple of interesting findings.  First, I have an 8MHz oscillator on the design that has the smallest range of operation (-20C to 70C).  I’m actually going to use the internal oscillator available in the microcontroller, and I don’t see clock timing to be an incredibly important issue in this design.  I added the oscillator part to the schematic as kind of a back-up plan but don’t plan on using it.  So I’ll ignore that problem for now.

The next lowest temp. range part is the PDV-P7002, a photocell I will be using to detect daylight.  For a part like this, whose resistance changes with light, I would guess that it goes “out-of-specification” outside of its operating range.  I doubt it quits working.  I’ll have to research that some more, but since I’m using the photocell as a yes/no type input I can accommodate a wide resistance variance.

That leaves me with some ceramic caps that don’t meet my operating temperature range, and I can certainly select a similar part with an extended temperature range, so I’m probably good there.

I guess there was one other issue.  The small metal buttons I have on this design (E-Switch parts) had no temperature rating.  I thought that was interesting.  These are not the kind of buttons you would use in an outdoor design, but no temperature rating?

And now for a sanity check.  Am I really going to run this design between –40C and 85C.  Nope.  This is R&D, it’ll spend its life in my office.  If this were a consulting contract we would design for this temperature but suggest our clients place test fixtures in the intended environment to collect operating data and/or make use of a temperature chamber for extended temperature testing.

That’s as far as I was able to get this week.  I’ll try to take some time over Christmas break to order the circuit board.  I need to panelize it with some other designs so it doesn’t cost an arm and a leg.  Hopefully I can begin writing code in January.

Detecting Taps with an Accelerometer: Disco Bike Light part 4

Tap Control of the Disco Bike Light

In last week’s blog I talked about looking into using an accelerometer output as a user interface for the Disco Bike Light design.  This week I took the next step of actually implementing a method of detecting taps with an accelerometer and using them as an on-off signal.

For a quick refresher, the Disco Bike Light is a design where I’ve decided to replace the guts of a Schwinn bike light with my own electronics. I wanted more color and more brightness.  I put some constraints on myself for the design.  One was that I couldn’t destroy the existing bike light in the process of making my new one.  For on/off/color control I was left with few options…

[Read more…]

Accelerometer as User Input Signal: Disco Bike Light Part 3

dbl_all_layers

Welcome to another edition of “Disco Bike Light: adventures in electronic design”.  In last week’s blog I talked a little about the printed-circuit-board (PCB) design and the Lithium battery charging circuit.  This week I’ll touch more on the circuit board, and a little bit on the user interface.

[Read more…]