/Users/eayars/Documents/Research/Chaotic_Rotor/SinDrive/SinDrive.ino
/*
SinDrive.ino
Eric Ayars
6/5/13
Uses an Arduino and MCP4725 DAC to drive the Helmholtz coils on my
chaotic rotor, and to report position and phase information.
*/
#include <Wire.h>
#include <Adafruit_MCP4725.h>
#define FPIN 0 // Frequency adjust knob, analog input 0
#define ZERO 11 // Zero-position button
#define PHASELED 12 // Indicator LED
#define ROTORLED 13 // Indicator LED
#define TMIN 500 // Minimum T for adjustment knob
#define TMAX 2500 // Maximum T for adjustment knob
// Define the DAC
Adafruit_MCP4725 DAC;
// Drive-related variables
unsigned long T; // Note: if T is int, calculation of dt fails.
int dt; // time step, microseconds.
int residual = 0; // residual microseconds to add in for each step
unsigned long M; // micros
unsigned long lM; // last micros
int dM; // change in micros
// Position variable
volatile int position = 0;
// Counter variable
byte j; // Byte so it wraps correctly with 8-bit LUT.
// Look-Up Table (LUT) for the sine wave.
// MCP4725 is 12-bit DAC, so maximum is 0x0FFF=4095.
PROGMEM uint16_t DACLookup_FullSine_8Bit[256] =
{
2048, 2098, 2148, 2198, 2248, 2298, 2348, 2398,
2447, 2496, 2545, 2594, 2642, 2690, 2737, 2784,
2831, 2877, 2923, 2968, 3013, 3057, 3100, 3143,
3185, 3226, 3267, 3307, 3346, 3385, 3423, 3459,
3495, 3530, 3565, 3598, 3630, 3662, 3692, 3722,
3750, 3777, 3804, 3829, 3853, 3876, 3898, 3919,
3939, 3958, 3975, 3992, 4007, 4021, 4034, 4045,
4056, 4065, 4073, 4080, 4085, 4089, 4093, 4094,
4095, 4094, 4093, 4089, 4085, 4080, 4073, 4065,
4056, 4045, 4034, 4021, 4007, 3992, 3975, 3958,
3939, 3919, 3898, 3876, 3853, 3829, 3804, 3777,
3750, 3722, 3692, 3662, 3630, 3598, 3565, 3530,
3495, 3459, 3423, 3385, 3346, 3307, 3267, 3226,
3185, 3143, 3100, 3057, 3013, 2968, 2923, 2877,
2831, 2784, 2737, 2690, 2642, 2594, 2545, 2496,
2447, 2398, 2348, 2298, 2248, 2198, 2148, 2098,
2048, 1997, 1947, 1897, 1847, 1797, 1747, 1697,
1648, 1599, 1550, 1501, 1453, 1405, 1358, 1311,
1264, 1218, 1172, 1127, 1082, 1038, 995, 952,
910, 869, 828, 788, 749, 710, 672, 636,
600, 565, 530, 497, 465, 433, 403, 373,
345, 318, 291, 266, 242, 219, 197, 176,
156, 137, 120, 103, 88, 74, 61, 50,
39, 30, 22, 15, 10, 6, 2, 1,
0, 1, 2, 6, 10, 15, 22, 30,
39, 50, 61, 74, 88, 103, 120, 137,
156, 176, 197, 219, 242, 266, 291, 318,
345, 373, 403, 433, 465, 497, 530, 565,
600, 636, 672, 710, 749, 788, 828, 869,
910, 952, 995, 1038, 1082, 1127, 1172, 1218,
1264, 1311, 1358, 1405, 1453, 1501, 1550, 1599,
1648, 1697, 1747, 1797, 1847, 1897, 1947, 1997
};
void positionUp() {
position++;
}
void positionDown() {
position--;
}
void setup() {
// set up DAC
DAC.begin(0x62);
// initialize variables
j=0;
lM = micros();
// set up buttons and LEDs
pinMode(ZERO, INPUT);
digitalWrite(ZERO, HIGH);
pinMode(PHASELED, OUTPUT);
pinMode(ROTORLED, OUTPUT);
// Start serial
Serial.begin(115200);
while (!Serial) {
;
}
// Attach counter interrupts
attachInterrupt(0,positionUp,RISING);
attachInterrupt(1,positionDown,RISING);
}
void loop() {
// Start by read the frequency knob and updating T:
T = map(analogRead(FPIN),0,1023,TMIN,TMAX);
dt = T*1000/256;
// Now check the time and adjust output accordingly
M = micros();
dM = M - lM + residual;
if (dM > dt) {
// we just crossed a drive cycle time step, so...
// adjust output.
j = j + dM/dt; // step forward requisite number of steps.
DAC.setVoltage(pgm_read_word(&(DACLookup_FullSine_8Bit[j])), false);
residual = dM % dt; // save "unused" microseconds for next dM.
lM = M;
// Check how position is doing
if (!digitalRead(ZERO)) position = 0;
// zero button has been pressed
if (position > 359) position -= 360;
// wrap backwards
if (position < 0) position += 360;
// wrap forwards
// Update position indicator light
if (position==0) digitalWrite(ROTORLED, HIGH);
else digitalWrite(ROTORLED, LOW);
// Update phase indicator light
if (j==0) digitalWrite(PHASELED, HIGH);
else digitalWrite(PHASELED, LOW);
// Send information to the computer
Serial.print(M, DEC); // microseconds
Serial.print(" ");
Serial.print(j, DEC); // phase angle (0-255)
Serial.print(" ");
Serial.print(position, DEC); // position (degrees)
Serial.print(" ");
Serial.println(T, DEC); // Drive period (ms)
}
}
Generated by GNU enscript 1.6.4.