April 24, 2015

MSP430 BSL Rocket EMF Detector

A few months ago I received the MSP430-BSL Rocket from Texas Instruments Europe, as a prize for a Facebook contest. The Rocket is a low-cost programmer for MSP430 devices but since it has its own microcontroller, I thought it would be fun to use it for another application: an EMF detector!
Since it has a rocket shape, I had the idea to build a custom flame shaped PCB for the output LEDs, which I could plug through the 2x5 pins BSL connector.
The board itself is open source hardware and has an MSP430F5510 microcontroller, where most of the pins are available through 2 rows of pads. It also comes with a mini USB port, 2 buttons for reset and bootloader mode, and 2 LEDs connected to GPIOs:
I plugged the board to my PC and the LEDs blinked, but it is a BSL Loader and I want to turn it into an EMF detector so it was time to start modifying the firmware. The best way to get started with the rocket is by checking its info on the Texas Instruments Wiki
Now to program the board there are a few options, but one of the easiest ways is probably by using the "MSP430 USB Firmware Upgrade Example", which is part of the MSP430 USB Developers Package. This is a program with a very simple GUI that allows you to download your code to the board, and even comes with a built in blink LED application, ready to be sent.
Once installed, confirm the license agreement. To try it out first I chose the blink LED example, but before upgrading the firmware, the board must be detected, and for that it needs to start in Bootloader mode. That can be done either by powering the board or pressing the reset switch, while holding the Bootloader button (USB_BSL). After that, the program should detect the device and the "Upgrade Firmware" option will become available.
After downloading the blink LED example the board started working:
Now that I tested downloading something to the board, it's time to start thinking about the EMF detector. A few years ago I had seen an Arduino EMF detector on Make, originally made by Aaron ALAI. So I thought about doing something similar. First thing I'm going to need is an analog input, so by checking the MSP430F5510 datasheet, I see that the PT package, which is the one used on the rocket, has 6 external ADCs, where 4 of them are in the pins P6.0 to P6.3. According to the rocket schematic, these pins are free and available on the pads, so I'm going to use one of them for my antenna.
More specifically, I'll be using pin P6.2 which corresponds to the ADC A2. Using a 3 MΩ pull-down resistor and a piece of wire for the antenna:
I wanted the output LEDs to be connected through the BSL connector so that I could "plug" the addon PCB easily to the rocket, but for that I needed to make sure that there are some GPIOs available on there. Going back on the rocket schematic again,we can see that 7 out of 10 pins actually connect to GPIOs, passing through 100Ω resistors, which is not a problem at all:
That only leaves behind V3.3, GND and TVCC_SENSE. This last one just goes to a normal pad on the rocket, but the power pins gave me an idea. I could mount a battery pack behind the flame PCB and power the entire rocket with it, this way it could be a portable EMF detector, which is exactly what it should be.
Having figured out the pins that I was going to need, I moved on to the actual application. For that I'll be using Code Composer Studio from Texas Instruments. It has a few different licensing options, but for this project, the free license it's all you need.
After selecting the workspace, you're greeted with the Getting Started page, which has a few interesting options, like training, videos and examples, which are particularly useful if you're using CCS for the first time.
I started by browsing the examples, there you can select the family of microcontrollers and then choose the examples you want, each one demonstrates the usage of a different peripheral, like GPIOs, ADCs, Timers, Comparators, UART and SPI Communications, among others. Since my idea for the EMF detector was to "read the environment" through an ADC pin and light up the LEDs forming some kind of a bar effect, the ADC and GPIO examples should come in handy.
Before moving on to the actual EMF application, let's start off by compiling the Toggle LED example, which is the first one on the resource explorer list, and try uploading it to the board. This application configures pin P1.0 as an output and toggles its state through a software loop.
By checking the MSP430-BSL Rocket schematic, we can verify that this pin is actually being used for the green LED on the board (which is why the earlier blink LED example also worked!). So it should do just fine without any changes to the code. However, the MSP430 Firmware Upgrade Example application, uses a specific format to upload the code to the board, which is the TI TXT format. To have that file, first we need to tell CCS to generate that specific output file format when building the project. To do so, on the project explorer section, right click on the desired project and select properties. Then navigate to "CCS Build > MSP430 Hex Utility" and select the checkbox "Enable MSP430 Hex Utility", a few more options will appear bellow. Now on the navigation tree, go to "CCS Build > MSP430 Hex Utility > Output Format Options" and then select the Output Format: "Output TI-TXT hex format (--ti_txt)".
I'm using CCS version 6.0.1, so the procedure might be slightly different for other versions. After doing this, every time you build the project, in the main directory, inside the Debug folder, there will be also a TXT file, which is the TI TXT hex format file, and this is the one you'll upload to the board if you are using the MSP430 Firmware Upgrade Example. There, you'll have the option to download your custom firmware, select the generated TXT file and click on "Upgrade Firmware".
And we can see that it works:
Now I'm ready to finally move on to the EMF application. I started by connecting all the 7 GPIOs from the BSL connector to LEDs on a breadboard using a few wires:
Then I developed a simple application to light up all the outputs, one at a time, to check that all of them were working properly:
From studying the GPIO, ADC and Timer examples, I was able to develop the basic structure of the EMF Detector. I thought it would be cool to make the rocket's green and orange LEDs toggle every 0.2 seconds, to let me know that the detector was working, even when the EMF measurement is not enough to light the first flame LED, besides it would be a great opportunity to use timers and interrupts. But first some basic bitwise operations. For this, Ray Wisman has a good and simple explanation on his MSP430 Getting Started guide:
Now for the code, first comes the main configurations like defining the ADC channel, the auxiliary functions, initializing the ports and some variables:

#include "msp430f5510.h"

#define ADC_Channel ADC10INCH_2  // ADC PIN P6.2

float ADC_Result;  // ADC Value
_Bool ADC_Ready;   // ADC Done flag


_Bool Timer_Ready = 0;   // Variable to toggle the LEDs with a timer

void measure(unsigned int);
void initTimer(float);

void main(void)
{

  WDTCTL = WDTPW+WDTHOLD;   // Stop WDT
  P1DIR |= BIT0;   // Set P1.0/Green LED to output direction
  P1DIR |= BIT1;   // Set P1.1/Orange LED to output direction
  PJDIR |= 0x0F;   // Set PJ.0 to PJ.3 to output direction
  P4DIR |= 0xFF;   // Set P4 to output direction

  P1OUT |= BIT0;   // Set P1.0 to 1
  P1OUT &= ~BIT1;  // Set P1.1 to 0
  ADC_Ready = 0;   // Variable to indicate ADC is ready
  initTimer(0.2);  // Start the timer clock - receives seconds

The main loop will check if either the timer or ADC interrupts are ready and react accordingly. If the timer has run out, the Rocket LEDs will toggle their state, if the ADC conversion is ready, then the output flame LEDs should turn on accordingly with the voltage level:

for (;;)
  {
    __delay_cycles(100);  // default is 5000
    measure(ADC_Channel);
    __bis_SR_register(CPUOFF + GIE);// LPM0, ADC10_ISR will force exit

    if (Timer_Ready)  // Timer runs out
    {
      Timer_Ready = 0;
      P1OUT ^= BIT0;  // Toggle LED - XOR
      P1OUT ^= BIT1;  // Toggle LED - XOR
    }
    if (ADC_Ready)  // ADC conversion is ready
    {
      ADC_Ready=0;
      ADC_Result=ADC_Result*3.3/1023; // Convert into Volts

      if (ADC_Result < 0.665) // All off
      {
        PJOUT = 0x00;
        P4OUT = 0x00;
      }
      else if (ADC_Result < 0.67)  // P4_4 on
      {
        PJOUT = 0x00;
        P4OUT = 0x10;
      }
      else if (ADC_Result < 0.69)  // and P4_5
      {
        PJOUT = 0x00;
        P4OUT = 0x30;
      } 
      else if (ADC_Result < 0.73)  // and PJ_2
      { 
        PJOUT = 0x04; 
        P4OUT = 0x30;
      }
      else if (ADC_Result < 0.79)  // and P4_0 
      {
        PJOUT = 0x04;
        P4OUT = 0x31; 
      }
      else if (ADC_Result < 0.85)  // and PJ_1
      {
        PJOUT = 0x06;
        P4OUT = 0x31;
      }
      else if (ADC_Result < 0.98)  // and PJ_3
      {
        PJOUT = 0x0e;
        P4OUT = 0x31;
      } 
      else         // and P4_3
      {
        PJOUT = 0x0e;
        P4OUT = 0x39;
      }
    }
  }
}

The auxiliary functions are responsible for configuring the timer and the ADC:

// Initialize Timer - see from page 474 slau208n
void initTimer(float time)
{
  // Configure Timer
  TA0CCR0 = 32768*time;          // Value for timer to compare
  TA0CTL = TASSEL_1+MC_1+TACLR;  // ACLK, count to CCR0, clear TAR
  TA0CCTL0 = CCIE;               // Gen interrupt when rollover
}

// ADC configuration - see from page 711 slau208n
void measure(unsigned int channel)
{
  // Configure ADC
  ADC10CTL0 |= ADC10SHT_2 + ADC10ON;  // ADC10ON, S&H=16 ADC clks
  ADC10CTL1 |= ADC10SHP;              // ADCCLK = MODOSC sampling timer
  ADC10CTL2 |= ADC10RES;              // 10-bit conversion results
  ADC10MCTL0 |= channel;              // A3 ADC input select; Vref=AVCC
  ADC10IE |= ADC10IE0;                // Enable ADC conv complete int.
  ADC10CTL0 |= ADC10ENC + ADC10SC;    // Sampling and conversion start
}

And then their respective interrupt service routines:

// ADC10 interrupt service routine
#pragma vector=ADC10_VECTOR
__interrupt void ADC10_ISR (void)
{
  ADC_Result = ADC10MEM0;           // Saves measured value.
  ADC_Ready = 1;                    // Sets flag for main loop.
  __bic_SR_register_on_exit(CPUOFF);// Enable CPU so main loop continue
}

// Timer0 A0 interrupt service routine.
#pragma vector=TIMER0_A0_VECTOR
__interrupt void TIMER0_A0_ISR (void)
{
  Timer_Ready = 1;                    // Time to update
  __bic_SR_register_on_exit(LPM3_bits);   // Exit LPM
}

After building the project with CCS and downloading the application to the rocket with the MSP430 Firmware Upgrader, it was time to test it out. I pulled out an extension cord near to the antenna of the EMF detector and there it was, the LEDs started shining:
Having tested the general concept I could move on to the actual flame PCB. So I opened up KiCad and started drawing the schematic:

I decided to use an extra connector for the battery pack to power the entire detector, and a 10 pin IDC10S/PCB Male connector to plug in the flame directly to the MSP Rocket. Then it was time to start drawing the PCB itself. First I tried to visually design the rocket as realistic as I could, to be able to have a good visual reference of how large the flame should be. Then I sketched the flame and added the LEDs and connectors:

Since the MSP Rocket already has 100Ω resistors on the BSL connector, and the board is going to work on 3.3V or less, I concluded it wasn't necessary to add any more. After the design was ready, I moved on to the etching phase:
I used the Toner transfer method to pass the circuit onto the PCB and then used a solution of acid and hydrogen peroxide for the corrosion part. After that the double sided PCB was ready:
Unfortunately the PCB that I used was a bit old and oxidated so it didn't turn out quite perfect, but still it didn't have any major problems (at least on the tracks):
Then I protected the connector pads and painted the PCB yellow. Now it's becoming more like a flame:
I painted some contours with a black pen, giving the flame a cartoony look and soldered the LEDs and connectors into place:
Then I added the battery pack on the back of the PCB. Fortunately, the MSP430 is a very low power microcontroller, which makes it one of the best to use in battery powered applications. This way 2xAAA batteries should be more than enough to power the EMF detector for a good while. I guess this is sort of a booster pack:
Now it's time to test it! I tried mostly everything I could remember, like lamps:
And of course fluorescent lamps with a magnetic ballast. Here was kind of surprising, even with the detector far away, it still detected a lot of radiation, specially on the instant when the light was turned on:
Microwave:
An induction oven:
A normal power outlet:
And here is a short video of the detector near some devices at the lab:

Now obviously the calibration is a bit messy and it's kind of hard to make it work as well in strong electromagnetic fields as in weak fields. Besides, the proximity of the antenna wire to the USB port on the rocket also has an influence, because it's ground shielded. Either way it was a fun project, and even though it's not the most precise thing there is, it still allows for some really interesting discoveries around the house or the lab.

I have uploaded the application code and PCB files to my Github.

By the way, if you want to restore the original MSP430 BSL Rocket firmware, you can find it here.

So thanks again for this prize Texas Instruments Europe!

No comments:

Post a Comment