Contact Us Curdridge Observatory channel on youtube google plus

Source code sketch Arduino example for reading the FGM-3h magnetometer

This is some very simple source code to read out data from the FGM-3h fluxgate magnetometer using the Arduino. The pulses from the FGM-3 are counted using an external counter source in the Arduino Mega and the output sent to the serial port. An clock counter overflow ISR is used to help calculate the total number of pulses coming from the FGM in the sample period. The sample period used here is about 5 seconds but could be anything you like.

First we setup some includes and defines at the top of the program

#include "avr\io.h"
#define SAMPLE_DELAY 5 // number of seconds between samples
#define SAMPLE_DURATION 5 // number of seconds to sample for.
volatile int mult=0;
static uint32_t timer=0;
float GetData();

Next we do the setup() function to get the serial port up and running.

void setup()
 Serial.println("Hello world");

And here is the Arduino loop function. This causes a reading to be made every 5 seconds and sends the result up the serial port.

void loop()
  if (millis() > timer) {
   timer = millis() + (SAMPLE_DELAY*1000); //only run every 5 seconds or whatever
   float FGMreading;
   FGMreading = GetData();
   Serial.print("FGM Reading. Period = ");
   Serial.println(" microseconds");

Next we setup the timer overflow interrupt. The square wave output from the FGM is connected directly to pin 47 of the Mega. This pin is wired to the counter on clock 5 of the atmel processor. This is done using the lower level timer clock commands. When the interrupt is enabled it will increase the variable "mult" to count the number of timer overflows.

 //Interrrupt service routine for clock counter - each time it reaches 65k, reset and increase mult
 //mult*65k is then added to the count at the end in GetData()
 if (TIFR5 & 1) { // if Timer/Counter 1 overflow flag
   mult++; // count number of Counter1 overflows
   TIFR5 =(1<<TOV5); // clear Timer/Counter 1 overflow flag

Now the meat of the program. Loop() will call the GetData function at intervals. The GetData() function first zeros the mult counter. It resets the timer count and enables the interrupt service routine. The timer counter will count the number of pulses coming from the FGM, and the ISR will increase mult++ each time the timer overflows. We can then get the total number of ticks at the end of the period by adding the timer counter value to the multi*65k.

Then some long winded high accuracy maths is done to convert the tick count into a period of seconds in microseconds. The period should be in the order of 9-15 microseconds.

  unsigned long count;
 unsigned long Frequency;

  TCCR5A=0; // reset timer/counter control register A
 TIMSK5 |=(1<<OCIE5A); //enable interrupt service routine

 //start counting
 bitSet(TCCR5B ,CS12); // Counter Clock source is external pin 47 of mega 2560
  bitSet(TCCR5B ,CS11); // Clock on rising edge
  delay(SAMPLE_DURATION*1000); //wait for sample duration and count the clicks
  //stop counting
 TCCR5B = 0;
 count = TCNT5;
  TCNT5 = 0;

 count+=0x10000 * mult; // the counter is 16 bit, so total count is count + mult*65k
 Frequency = count/SAMPLE_DURATION; //frequency in Hz

  unsigned long long oneSecond = 1000;
  unsigned long long Period;
 Period = oneSecond / (unsigned long long) Frequency;

  float usPeriod;
 usPeriod = float (Period) / 100000;

 return usPeriod;

Possible improvements to this code