NerdKits - electronics education for a digital generation

You are not logged in. [log in]

NEW: Learning electronics? Ask your questions on the new Electronics Questions & Answers site hosted by CircuitLab.

Sensors, Actuators, and Robotics » Memsic 2125 Dual-Axis Accelerometer (#28017)

June 24, 2010
by Ralphxyz
Ralphxyz's Avatar

Anyone have code to use this device with the NerdKit?

Communication: TTL/CMOS compatible 100 Hz PWM output signal with duty cycle proportional to acceleration

I am just starting to look at PWM going out of the NerdKit now how do i monitor it coming back in?

I see in the forum that this or similar devices have been used for projects.

Ralph

June 26, 2010
by Ralphxyz
Ralphxyz's Avatar

So here is a good document from ATmel discussing PWM capture.

www.atmel.com/dyn/resources/prod_documents/doc8014.pdf.

It appears to be aimed at a engineering student and explains the principles of what is required for PWM capture,it does not go into detail but just discusses PWM in general. It depends on "source code" to do the in depth explanation.

That's all well and good except there is no link to the source code!!

Any one familiar with the ATmel web site know where I might find the related source code?

Ralph

July 03, 2010
by esoderberg
esoderberg's Avatar

Ralph,

I used the code below to read the PW from a Memsic 28017. Should work as well for the 2125. Works nice, much less noisy when compared to analog accel inputs read via ADC I tried earlier.

Summary: Accel input read from PB4. Clock code from Nerdkits tutorial. Mark time at front end of pulse, then at back end, and take difference for PW.

Eric S.

// Clock set up

void realtimeclock_setup()

{ // setup Timer0: // CTC (Clear Timer on Compare Match mode) // TOP set by OCR0A register

TCCR0A |= (1<<WGM01);

// clocked from CLK/ // which is 16000000/64, or 250000 increments per second

TCCR0B = 0;

TCCR0B |= (1<<CS01) | (1<<CS00);

// set TOP to 4 // because it counts 0, 1, 2,3,4, 0, 1, 2 ... // so 0 through 4 equals 5 events

OCR0A = 4;

// enable interrupt on compare event // (250000 / 5 = 50000 per second)

TIMSK0 |= (1<<OCIE0A); }

// the_time will store the elapsed time // (50000 = 1 second)

// This variable is marked "volatile" because it is modified // by an interrupt handler. // // With "volatile", it will always read it from memory // instead of making that assumption.

volatile int32_t time;

volatile int32_t t1;

volatile int32_t t2;

SIGNAL(SIG_OUTPUT_COMPARE0A) {

// when Timer0 gets to its Output Compare value, // elapsed time (0.0002 seconds per count).

time++; }

// Below is what gets executed on interrupt; measures PW of accelerometer input to PC4

ISR(PCINT1_vect){

if(PINC & (1<<PC4)) {t1 = time;} // if change in PC4 plus high --- ie start of pulse then mark start time t1

else {t2 = time; //if change in PC4 plus low -- IE end of pulse, mark time at end t2 --- t2 - t1 = pulse width

// t2-t1 = Pulse width from accelerometer.

Ax = (250 - (t2-t1));}

// 250 is the zero g point for the 2801, 2125 may be different

init_accelerometer(){

//make PC4 input pin

DDRC &= ~(1<<PC4);

//Enable PIN Change Interrupt 1 - This enables interrupts on pins //PCINT14...8 see p70 of datasheet

PCICR |= (1<<PCIE1);

//Set the mask on Pin change interrupt 1 so that only PCINT12 (PC4) triggers //the interrupt. see p71 of datasheet

PCMSK1 |= (1<<PCINT12); }

int main() { realtimeclock_setup();

t1 = 0;

t2 = 0;

init_accelerometer();

// turn on interrupt handler sei();

}

July 03, 2010
by esoderberg
esoderberg's Avatar

Ralph,

I'm actually using the 2125 as well and didn't even realize it while writing the above post.  28017 is just the kit # for the 2125.  Short of it is, the above code works for the 2125.

Eric S.

July 04, 2010
by Ralphxyz
Ralphxyz's Avatar

Eric, that is fantastic thank you!!

re: "analog accel inputs read via ADC I tried earlier" what was your analog device?

I was thinking of using a inverted joystick read via ADC, is that similar to what you were trying?

What you using to display the X & Y data on the LCD or sent to a PC?

Is there a G axis also, what do you get when you drop it?

Thanks again,

Ralph

July 04, 2010
by esoderberg
esoderberg's Avatar

Ralph,

I'm using the accelerometer data to keep a tilting three wheeled vehicle in a balanced condition (with lateral acceleration near zero) so the PWM/accel reading isn't displayed at all, it's used to drive a PWM output to servos which are attached to a steering mechanism; I only need to measure one axis of acceleration for this feature, so that's all I'm using from the 2125. I'm also using the ADC to read a joystick, but that is pretty well functionally separated from the code above for readying the PWM accel input. Drop testing isn't in the works for my setup, so no answer for you there.

Eric S.

July 05, 2010
by Ralphxyz
Ralphxyz's Avatar

Oooh let me see, let me see.

My future plans are for a balance bot, have you posted a video yet?

Are you using acceleration to achieve balance or using a counter weight or gyro.

Here is a very stable two wheel balance-bot that uses a couple of ATmega processors and a gyro.

I'd sure like to see their code.

http://www.youtube.com/watch?v=3hJyiDPR9Gw

Your code looks great I cannot wait to try it out, thanks again.

Ralph

August 05, 2010
by BoloBit64
BoloBit64's Avatar

I am a bit confused by the code as to what connectins your making. It is a pw pin(pc4) is what it looks like you are using which i understand, but what input are you using on the accelerometer. You mentioned the tilt input but then also talked about acceleration input. Please explain what input you are using and if you have a code with all inputs set up i would like to see it. It would be very helpful to me.

August 05, 2010
by esoderberg
esoderberg's Avatar

Bolo,

There is only one input involved with the code above - the lateral acceleration, however the lateral acceleration in my physical setup is proportional to the second derivative of the tilt angle of my vehicle. For static 1 g conditions vice the dynamic setup I've got, tilt angle will be proportional to the measured lateral acceleration(at least for small angles), I've commingled the terms a little because for my project they're all related.

So, for the code above, there is only one input, which is coming from a MEMSIC 2125 accelerometer attached to my vehicle with the acceleration measured along an arc about the vehicles longitudinal axis (ie lateral roll). The output of the accelerometer is a pulse width. I'm reading that pulse on PC4. When PC4 goes high, I start to time(t1), when it goes low again, I stop the clock (t2), with accel being proportional to the Pulse width as per the equation given for Ax.

There was one potential gotcha in the NK portion of the code above. I updated to a 328 and the interrupt vector given above for the clock, SIGNAL(SIG_OUTPUT_COMPARE0A), was outdated and did not work like it did with the standard NK168. I replaced that part of the code with the updated version from the AVR interrupt library ISR(TIMER0_COMPA_vect) and all is good.

EricS.

August 05, 2010
by esoderberg
esoderberg's Avatar

Bolo,

After that long winded explanation, I think I just saw what might have actually confused you and there is a much shorter, better answer, where I wrote accel read from PB4, I meant to type PC4. PB4 not involved at all.

August 08, 2010
by BoloBit64
BoloBit64's Avatar

Thank you for the explaination, and even though long i understood it.

August 13, 2010
by BoloBit64
BoloBit64's Avatar

For those who would like to program for both X an Y axis take a look at this code. It is a good starting base for it. With the code provided from Eric S.(thank you) I then took it and added another pin for the x axis. PLEASE CHECK CODE!!!!! If this is not correct post something on what's wrong as i am not an avid programmer, but thanks to nerdkits and everyone else i am learning quickly! Enjoy, Bolo

//Pin Definition: // Pin 27: PC4(PCINT12) // Pin 28: PC5(PCINT13) //Memsic 2125 Pin Def: // Pin 2: Yout (connected to PC4) // Pin 5: Xout (connected to PC5) // It is also possible to recieve the temp. from the Memsic through T out(pin 1) //and connect it like you did the temp sensor through the adc converter.

// Clock set up

void realtimeclock_setup()

{ // setup Timer0: // CTC (Clear Timer on Compare Match mode (14.6 on datasheet)) // TOP set by OCR0A register

TCCR0A |= (1<<WGM01);

// clocked from CLK/ // which is 16000000/64, or 250000 increments per second

TCCR0B = 0;

TCCR0B |= (1<<CS01) | (1<<CS00);

// set TOP to 4 // because it counts 0, 1, 2,3,4, 0, 1, 2 ... // so 0 through 4 equals 5 events

OCR0A = 4;

// enable interrupt on compare event // (250000 / 5 = 50000 per second)

TIMSK0 |= (1<<OCIE0A); }

// the_time will store the elapsed time // (50000 = 1 second)

// This variable is marked "volatile" because it is modified // by an interrupt handler. // // With "volatile", it will always read it from memory // instead of making that assumption.

volatile int32_t time;

volatile int32_t t1;

volatile int32_t t2;

SIGNAL(SIG_OUTPUT_COMPARE0A) {

// when Timer0 gets to its Output Compare value, // elapsed time (0.0002 seconds per count).

time++; }

// Below is what gets executed on interrupt; measures PW of accelerometer input to PC4 and PC5

ISR(PCINT1_vect){

if(PINC & (1<<PC4) & (1<<PC5)) {t1 = time;} // if change in PC4 or pc5 plus high --- ie start of pulse then mark start time t1

else {t2 = time; //if change in PC4 or pc5 plus low -- IE end of pulse, mark time at end t2 --- t2 - t1 = pulse width

// t2-t1 = Pulse width from accelerometer.

Ax = (250 - (t2-t1));}

// 250 is the zero g point for the 2801, 2125 may be different

init_accelerometer(){

//make PC4 and pc5 input pin

DDRC &= ~(1<<PC4) ~(1<<PC5);

//Enable PIN Change Interrupt 1 - This enables interrupts on pins //PCINT14...8 see p70 of datasheet

PCICR |= (1<<PCIE1);

//Set the mask on Pin change interrupt 1 so that PCINT12 (PC4) and PCINT13 (pc5) are the only ones that trigger //the interrupt. see p71 of datasheet

PCMSK1 |= (1<<PCINT12) (1<<PCINT13); }

int main() { realtimeclock_setup();

t1 = 0;

t2 = 0;

init_accelerometer();

// turn on interrupt handler sei();

}

August 13, 2010
by esoderberg
esoderberg's Avatar

Bolo,

I don't think the modification you made is going to work like you want it to. If you want to read both accel channels from the MEMSIC you'll need to distinguish between channels when you start/stop your clock; I don't see where the changes you posted above do that. Would recommend having a t1x,t2x and a t1y,t2y. Mark t1x at start of pulse from x channel, t2x for the end of pulse from x channel. Do the same for y with t1y and t2y. Then Ax = 250 - (t2x-t1x) and Ay = 250 - (t2y-t1y)

Eric

August 16, 2010
by BoloBit64
BoloBit64's Avatar

Thanks I will try it.

August 21, 2010
by Ralphxyz
Ralphxyz's Avatar

BoloBit64, so what is happening? Did you get it to work?

I sure would appreciate it if you would post your code.

Ralph

July 24, 2011
by Ralphxyz
Ralphxyz's Avatar

Any videos of a device using the 2125 accelerometer and the Nerdkit?

Of course actual working code would be nice also.

Ralph

July 24, 2011
by Ralphxyz
Ralphxyz's Avatar

Any videos of a device using the 2125 accelerometer and the Nerdkit?

Of course actual working code would be nice also.

Ralph

August 08, 2011
by nightfall
nightfall's Avatar

Hello, I'm new to nerd kits and I'm trying to use an accelerometer for a group project. I have read this post but i am still confused. I know i need to get more familiar with coding in C and the data sheets. I plan on working with the other projects suggested by nerd kits, to enhance my understand as a whole, however i was wondering if there was a good beginner project with accelerometers. I've looked at other websites and i understand the purpose of accelerometer but haven't found any solid tutorials. I was hoping you could point me in the right direction. Sorry if has been answered before.

Thanks in advance!

Post a Reply

Please log in to post a reply.

Did you know that hobby servos are controlled through a particular kind of PWM (Pulse Width Modulation) signal? Learn more...