Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Demonstrating MM3 usage with interrupts for convert and reading.
- Loading branch information
1 parent
b6a6807
commit 3b8d911
Showing
1 changed file
with
174 additions
and
0 deletions.
There are no files selected for viewing
174 changes: 174 additions & 0 deletions
174
examples/MicroMagConvGetResInt/MicroMagConvGetResInt.ino
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,174 @@ | ||
/* | ||
* MicroMagConvGetRes.ino | ||
* Author: Steve Marple | ||
* License: GNU Lesser General Public License, version 2.1 | ||
* | ||
* Example sketch to demonstrate reading from a MicroMag2 or MicroMag3 | ||
* module using the convert() and getResult() functions. The initial | ||
* convert is started from a match interrupt generated by | ||
* timer/counter2. | ||
* | ||
* Requirements: | ||
* Arduino >= 1.0 | ||
* Calunium (standard Arduino cannot access the DRDY pin and the | ||
* Arduino Mega(2560) doesn't have timer/counter2 connected to the | ||
* shield headers. | ||
* MicroMag library, see https://github.com/stevemarple/MicroMag | ||
* MicroMag2 or MicroMag3 module | ||
* | ||
* Calunium configuration: | ||
* RTC (DS1307 or similar) fitted, with battery | ||
* RTC square wave routed to D15 (JP1 fitted) | ||
*/ | ||
|
||
#include <Wire.h> | ||
#include <RealTimeClockDS1307.h> | ||
|
||
#include <SPI.h> | ||
#include <MicroMag.h> | ||
|
||
#include <util/atomic.h> | ||
|
||
// Adjust these pin definitions to suit your hardware. They are chosen | ||
// to match the RN-XV and SD shield with the MicroMag3 module option | ||
// on Calunium. Ensure the correct interrupt service routine is | ||
// defined for the DRDY pin. | ||
#define DRDY_PIN 14 | ||
const uint8_t mmResetPin = A3; | ||
const uint8_t mmDrdyPin = DRDY_PIN; | ||
const uint8_t mmSsPin = A0; // This is the chip select pin on the MM3 | ||
|
||
// Change this to suit your version. | ||
const uint8_t model = 3; | ||
|
||
// The sampling period | ||
uint8_t period = MM_PERIOD_4096; | ||
|
||
// Create a MicroMag object | ||
MicroMag MM = MicroMag::MicroMag3(mmSsPin, mmDrdyPin, mmResetPin); | ||
|
||
// Use an 8-bit variable to obtain atomic read/write access. Disabling | ||
// interrupts is therefore not needed. | ||
/// volatile uint8_t dataReady = false; | ||
|
||
// The 2 or 3 samples are taken in different invocations of loop() so | ||
// use static variables to hold the results until all 2 or 3 have been | ||
// taken and can be printed. | ||
volatile uint8_t axis = 0; | ||
volatile uint8_t sampleInProgess = false; | ||
volatile int16_t data[model]; | ||
volatile unsigned long timestamps[model] = {0}; | ||
|
||
|
||
// This ISR is called when the state has *changed*. Act only when the | ||
// current state is high (data is ready) | ||
ISR(PCINT2_vect){ | ||
ATOMIC_BLOCK(ATOMIC_FORCEON) { | ||
if (!digitalRead(DRDY_PIN)) | ||
return; // Data not ready (new sample started?) | ||
|
||
data[axis] = MM.getResult(); | ||
++axis; | ||
if (axis == model) | ||
sampleInProgess = false; | ||
else { | ||
timestamps[axis] = millis(); | ||
MM.convert(axis, period); // Start sampling next axis | ||
} | ||
return; | ||
} | ||
} | ||
|
||
void setupPinChangeInterrupts(void) | ||
{ | ||
*(digitalPinToPCMSK(DRDY_PIN)) |= _BV(digitalPinToPCMSKbit(DRDY_PIN)); | ||
*(digitalPinToPCIR(DRDY_PIN)) |= _BV(digitalPinToPCICRbit(DRDY_PIN)); | ||
} | ||
|
||
// When the counter matches sample X | ||
ISR(TIMER2_COMPA_vect) | ||
{ | ||
ATOMIC_BLOCK(ATOMIC_FORCEON) { | ||
if (sampleInProgess) | ||
return; | ||
sampleInProgess = true; | ||
axis = 0; | ||
timestamps[axis] = millis(); | ||
MM.convert(axis, period); | ||
return; | ||
} | ||
} | ||
|
||
// Configure counter/timer2 in asynchronous mode, counting the rising | ||
// edge of signals on TOSC1. This always triggers on the rising edge; | ||
// if connecting SQW from a DS1307 then this means the ticks occur | ||
// halfway through the second. | ||
void setupTimer2(void) | ||
{ | ||
noInterrupts(); | ||
ASSR = (_BV(EXCLK) | _BV(AS2)); | ||
TCCR2A = 0; | ||
TCCR2B = 0; | ||
TCNT2 = 0; | ||
OCR2A = 3; // Have the ISR called every 10th (n+1) tick | ||
TCCR2A |= _BV(WGM21); // CTC mode | ||
TCCR2B |= _BV(CS20); | ||
TIMSK2 |= _BV(OCIE2A); | ||
interrupts(); | ||
} | ||
|
||
|
||
void setup() | ||
{ | ||
pinMode(SS, OUTPUT); // Prevent SPI slave mode from happening | ||
Wire.begin(); | ||
Serial.begin(9600); | ||
|
||
// For calunium: enable inputs on pin 6 in case JP4 is fitted and | ||
// routing SQW there also | ||
pinMode(6, INPUT); | ||
|
||
// On Calunium timer/counter2 is connected to digital pin 15. | ||
pinMode(15, INPUT); | ||
setupTimer2(); | ||
|
||
if (MM.begin() != 0) { | ||
Serial.println("Could not initialise MicroMag"); | ||
while (1) | ||
; // no point in continuing | ||
} | ||
setupPinChangeInterrupts(); | ||
|
||
// Set up the RTC output | ||
RTC.sqwEnable(RealTimeClockDS1307::SQW_1Hz); | ||
} | ||
|
||
unsigned long lastDisplayed = 0; | ||
void loop() | ||
{ | ||
// Check if new data is ready | ||
if (!sampleInProgess && axis == model && timestamps[0] != lastDisplayed) { | ||
lastDisplayed = timestamps[0]; | ||
double total = 0.0; | ||
|
||
// Display the results | ||
for (uint8_t i = 0; i < model; ++i) { | ||
if (i) | ||
Serial.print(" "); | ||
Serial.print(char('X' + i)); | ||
Serial.print(" = "); | ||
Serial.print(data[i]); | ||
total += sqrt(double(data[i]) * data[i]); | ||
} | ||
Serial.print(" Total = "); | ||
Serial.println(total); | ||
|
||
for (uint8_t i = 0; i < model; ++i) { | ||
if (i) | ||
Serial.print(" "); | ||
Serial.print(timestamps[i]); | ||
} | ||
Serial.println(); | ||
} | ||
|
||
} |