Memsic 2125 Accelerometer with interrupts

Hi everyone, I have a working sketch that reads the memsic 2125 accelerometer using pulsein. I am trying to convert it to using interrupts but I am getting bizarre behavior. Here is the working example:

byte xPin = 2;
byte yPin = 3;
byte value = 0;

int count = 0;
int pulse = 0;

void setup() {
  beginSerial(57600);
  for (int i = 2; i <= 8; i++) {
    pinMode(i, INPUT);
  }
}

void loop() {
  readTiltPulse(xPin);
  readTiltPulse(yPin);
} 

void readTiltPulse(int axe) {
  value = digitalRead(axe);
  while (value == HIGH) { // Loop until pin reads a low
    value = digitalRead(axe);
  }
  pulse = pulseIn(axe, HIGH);
  
  if (axe == xPin) {
    Serial.print("X ");
    Serial.print(pulse);
    Serial.print("\t");
  } else {
    Serial.print("Y ");
    Serial.println(pulse);
  }  
}

With this I get smooth, consistent output like this (with the unit lying nearly flat):

X 4948      Y 4914
X 4947      Y 4916
X 4948      Y 4913
X 4949      Y 4913
X 4948      Y 4916
X 4944      Y 4916
... plenty more

Here is my sketch with interrupts (only X-axis so far).

volatile unsigned long currentTicksValueX = 0;
volatile unsigned long currentTicksValueY = 0;
volatile unsigned long lastStartX = 0;
volatile unsigned long lastStartY = 0;
volatile unsigned long dutyCycleX = 0;
volatile unsigned long dutyCycleY = 0;

void setup (void) {
  Serial.begin(57600);
  for (int i = 2; i <= 13; i++) {
    pinMode(i, INPUT);
  }
  attachInterrupt(0, onChangeX, CHANGE);
  //attachInterrupt(1, onChangeY, CHANGE);
}

void loop (void) {
  /*Serial.print("X: ");
  Serial.print(dutyCycleX);
  Serial.print("\t");
  Serial.print("Y: ");
  Serial.println(dutyCycleY);
  delay(500);*/
}

void onChangeX() {
  currentTicksValueX = (millis() << 8) + TCNT0;
  if (digitalRead(2) == HIGH) {
    lastStartX = currentTicksValueX;
  } else {
    dutyCycleX = currentTicksValueX - lastStartX;
  }
  Serial.println(dutyCycleX);
  
}

This yields output like so:

1250
1250
1250
1250
1250
1505
1505
1249
1249
1249
... more

Notice the jump from 1250 to 1500 for no apparent reason (unit was resting). If I comment the serial print in the onChangeX function and enable the serial print in the loop function but comment out the delay I get something like this:

X: 1249      Y: 0
X: 1249      Y: 0
X: 1250      Y: 0
X: 33889976320      Y: 0
X: 1249      Y: 0
X: 1249      Y: 0
X: 1249      Y: 0
X: 1506      Y: 0
X: 1506      Y: 0
X: 1506      Y: 0
X: 1506      Y: 0
X: 1250      Y: 0
X: 1250      Y: 0
X: 1250      Y: 0
X: 1250      Y: 0
X: 1249      Y: 0
X: 1249      Y: 0
X: 1249      Y: 0
X: 1249      Y: 0
X: 49739776249      Y: 0
X: 1249      Y: 0
X: 1249      Y: 0
X: 1249      Y: 21102222012220102001
X: 1503      Y: 0
X: 1503      Y: 0
X: 1249      Y: 0
X: 1249      Y: 0
X: 1249      Y: 0
X: 1249      Y: 0
X: 66152249      Y: 0
X: 1249      Y: 0
X: 1249      Y: 0
X: 1249      Y: 0
X: 1250      Y: 0
X: 1250      Y: 0
X: 1250      Y: 0
X: 1250      Y: 0
X: 2730491904250      Y: 0
X: 1250      Y: 0
X: 1250      Y: 0
...more

If I enable the delay(500) I get something like this:

X: 0      Y: 0
X: 462      Y: 0
X: 462      Y: 0
X: 1250      Y: 0
X: 1250      Y: 0
X: 1249      Y: 0
X: 1249      Y: 0
X: 1249      Y: 0
X: 1249      Y: 0
X: 1249      Y: 0
X: 1249      Y: 0
X: 1250      Y: 0
X: 1250      Y: 0
X: 1249      Y: 0
X: 1249      Y: 0

What's interesting is that this is ALL the output. It stops altogether while the other examples go on forever.

Can anybody spot some trouble that would cause this?
Thanks.

I'm using Arduino 12.

/Daryl

I ran the last case (with the delay(500) enabled) in Arduino 10 and it does not cease to output as it does with 12, though the numbers still jump around.

/Daryl

Ok, I've figured it out. Many of you are probably familiar with this sub-millisecond timer:

unsigned long hpticks(void) {
    return (timer0_overflow_count << 8) + TCNT0;
}

This does not work in Arduino 12. I read that millis() should be used as part of the formula, though I can't find it now. Obviously I didn't get it right. Using the above hpticks with my interrupt routine works fine. I'll open a new thread on timer issues.

/Daryl

Hi!!

Im interfacing with the 2125, i want to obtain and inclination angle, does anyone have done it? i test some code i found in internet, but so far, no luck....

10x!!!

An accelerometer measures acceleration, of course, including gravity. When the unit is flat (it's a 2 axis unit), it is measuring 0g. When it is tilted 90 degrees it is measuring 1g (or -1g). So take whatever numbers you get from reading it (microseconds, clock ticks, loop counts, whatever) and use the map function to convert to degrees.

/Daryl