![](/media/cache/profiles/53420bd6e6798761679772a7dd012674.50x50_q85.jpg)
Read data from an ADIS16355 IMU and write it to the USB port.
Revision 0:c6ee363ac724, committed 2011-08-10
- Comitter:
- yahugh
- Date:
- Wed Aug 10 21:50:36 2011 +0000
- Commit message:
- initial release, still has some problems but might be of interest to others regardless
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/imu-spi.cpp Wed Aug 10 21:50:36 2011 +0000 @@ -0,0 +1,98 @@ +// +// imu-spi.cpp +// +// copyright 2010 Hugh Shane +// +#include "mbed.h" +#include "imu-spi.h" + +ImuSpi::ImuSpi(void) : + spi(p5, p6, p7), // mosi, miso, sclk + cs(p8), // IMU chip select + reset(p8), // IMU reset. CAUTION! This also resets the altimeter. + diag(p21), // diagnostic output + imuDataReady(p11) // interrupt on IMU data-ready +{ + // Setup the spi for 16 bit data, high steady state clock, + // second edge capture, with a 1 MHz clock rate + spi.format(16,3); + spi.frequency(1000000); + + // init the pingpong buffer + pingpong = 0; + + // init the interrupt semaphore + dataReady = false; + + // interrupt on the falling edge of the IMU data-ready signal + diag = 0; + imuDataReady.fall(this, &ImuSpi::DataReadyISR); + + // init the IMU + InitImu(); + +} + +void ImuSpi::reinitInterrupts(void) { + imuDataReady.fall(this, &ImuSpi::DataReadyISR); +} + +// initialize the IMU +void ImuSpi::InitImu(void) { + // deselect the IMU + cs = 1; + reset = 1; + // perform a hard reset + reset = 0; wait(.1); reset = 1; + // send initialization commands + Write(0x34, 0x04); // enable active low data ready on DIO1 + Write(0x38, 0x00); // Set the FIR filter to its widest possible bandwidth +} + +// read the IMU accelerometer and gyro registers into the pingpong buffer +void ImuSpi::BurstRead(void) { + static int16_t imuRegs[] = {0x04,0x06,0x08,0x0A,0x0C,0x0E,0x3C}; + int16_t* wp = GetBufferWritePtr(); + Read(imuRegs[0]); // set up the first register read operation + wait(0.000024); // required to meet IMU t(datarate) spec + + // send register read commands & read the registers + for (int i = 1; i <= 6; i++) { + *wp++ = Read(imuRegs[i]); + wait(0.000024); + } + *wp = Read(0); // read the last register output +} + +int16_t ImuSpi::Read(char adr) { + int16_t cmd = 0x3f00 & (adr << 8); + int16_t response; + cs = 0; + response = spi.write(cmd); + cs = 1; + return response; +} + + +void ImuSpi::Write(char adr, char data) { + int16_t cmd = 0x8000 | (adr << 8) | data; + cs = 0; + spi.write(cmd); + cs = 1; +} + +bool ImuSpi::IsDataReady(void) { + if (dataReady == true) { + dataReady = false; + return true; + } else { + return false; + } +} + +void ImuSpi::DataReadyISR(void) { +diag = 1; + TogglePingpong(); + dataReady = true; +diag = 0; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/imu-spi.h Wed Aug 10 21:50:36 2011 +0000 @@ -0,0 +1,31 @@ +// +// imu-spi.h +// +// copyright 2010 Hugh Shane +// + +class ImuSpi { +private: + const static int bufferSize = 7; + int16_t buffer[2][bufferSize]; // ping-pong IMU data buffer + unsigned pingpong; + bool dataReady; + SPI spi; + DigitalOut cs; + DigitalOut reset; + DigitalOut diag; + InterruptIn imuDataReady; + void InitImu(void); + void DataReadyISR(void); + int16_t Read(char); + void Write(char, char); + void TogglePingpong() {pingpong = (~pingpong) & 1U;}; + int16_t* GetBufferWritePtr() {return buffer[pingpong & 1U];}; +public: + ImuSpi(void); + void BurstRead(void); + int16_t* GetBufferReadPtr() {return buffer[(~pingpong) & 1U];}; + bool IsDataReady(void); + int GetBufferSize(void) {return bufferSize*sizeof(int16_t);}; + void reinitInterrupts(void); +}; \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Wed Aug 10 21:50:36 2011 +0000 @@ -0,0 +1,51 @@ +// +// main.cpp +// +// Container class for mbed-based ADIS16355 IMU data acquisition system +// +// copyright 2010 Hugh Shane +// +#include "mbed.h" +#include "imu-spi.h" +#include "usb-serial.h" + +int main() { + DigitalOut diag_led(LED1); + ImuSpi imu; + usb_serial_init(); + char* imubuffer; + bool overflow; + Timer timer; + timer.start(); + int now, last = 0, elapsed; + int nbytes = 12; + + while (1) { + + // acquire the IMU data + while (!imu.IsDataReady()) {} // wait for the IMU data-ready signal + now = timer.read_us(); // grab the elapsed time in microseconds + elapsed = now - last; + last = now; + imu.BurstRead(); // read the IMU output data registers + imubuffer = (char*)imu.GetBufferReadPtr(); // get a pointer to the IMU output data + + // transmit a data packet on the USB serial port + overflow = usb_serial_putc(0x55); // start of packet + overflow = usb_serial_putc((uint8_t)elapsed); // time marker, just the lower bits + + for (int i = 0; i < nbytes; i++) { + overflow = usb_serial_putc(*imubuffer++); // IMU data + } + + overflow = usb_serial_putc(0xAA); // end of packet + + // diagnostic LED + if (overflow) + diag_led = 1; + else + diag_led = 0; + + } + +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Wed Aug 10 21:50:36 2011 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/e2ac27c8e93e
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usb-serial.cpp Wed Aug 10 21:50:36 2011 +0000 @@ -0,0 +1,65 @@ +#include "mbed.h" +#include "usb-serial.h" + +volatile unsigned wp, rp; +static const int outbuf_size = 128; +static const unsigned pointer_mask = 0x007fU; +char usb_outbuf[outbuf_size]; +static bool overflow; +DigitalOut mydiag(p22);; + +extern "C" static void txReadyISR() __irq { + + mydiag = 1; + // If the output buffer has data, copy the head to the UART + if (rp != wp) { + LPC_UART0->THR = usb_outbuf[rp]; + rp = (rp+1) & pointer_mask; + } + + // If the output buffer is empty, disable the transmit buffer empty + // interrupt + if (rp == wp) + LPC_UART0->IER = 0; + + + mydiag = 0; +} + +void usb_serial_init(void) { + + // init the output FIFO + wp = 0; rp = 0; + overflow = false; + + // init the serial port + Serial usb_serial(USBTX, USBRX); + usb_serial.baud(/*115200*/230400); + usb_serial.format(8, Serial::None, 1); + LPC_UART0->FCR = 7UL; + NVIC_SetVector(UART0_IRQn, (uint32_t)txReadyISR); + NVIC_EnableIRQ(UART0_IRQn); + LPC_UART0->THR = 0; // this is required to start the interrupts, don't understand why +} + +bool usb_serial_putc(char c) { + + if (overflow == false) { + usb_outbuf[wp] = c; + LPC_UART0->IER = 0; // ---- critical + wp = (wp+1) & pointer_mask; + + if (wp == rp) + overflow = true; + else + overflow = false; + + LPC_UART0->IER = 2UL; // ---- \critical + } else { + // reinit the output FIFO + wp = 0; rp = 0; + overflow = false; + } + + return overflow; +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usb-serial.h Wed Aug 10 21:50:36 2011 +0000 @@ -0,0 +1,2 @@ +void usb_serial_init(void); +bool usb_serial_putc(char); \ No newline at end of file