示例#1
0
int main(void)
{
    /* initialize the core clock and the systick timer */
    InitClock();
    InitSysTick();

    /* initialize the RGB led */
    LED_Init();

    /* Initialize UART0 */
    InitUart0();

    /* double rainbow all across the sky */
    DoubleFlash();

    /* initialize the I2C bus */
    I2C_Init();

#if DATA_FUSE_MODE

    /* signaling for fusion */
    FusionSignal_Init();

#endif // DATA_FUSE_MODE

    /* initialize UART fifos */
    RingBuffer_Init(&uartInputFifo, &uartInputData, UART_RX_BUFFER_SIZE);
    RingBuffer_Init(&uartOutputFifo, &uartOutputData, UART_TX_BUFFER_SIZE);

    /* initialize UART0 interrupts */
    Uart0_InitializeIrq(&uartInputFifo, &uartOutputFifo);
    Uart0_EnableReceiveIrq();

    /* initialize I2C arbiter */
    InitI2CArbiter();

    /* initialize the IMUs */
    InitHMC5883L();
    InitMPU6050();
//    InitMPU6050();

#if ENABLE_MMA8451Q
    InitMMA8451Q();
#endif

    /* Wait for the config messages to get flushed */
    //TrafficLight();
    DoubleFlash();
    RingBuffer_BlockWhileNotEmpty(&uartOutputFifo);

#if ENABLE_MMA8451Q
    /* initialize the MMA8451Q data structure for accelerometer data fetching */
    mma8451q_acc_t acc;
    MMA8451Q_InitializeData(&acc);
#endif

    /* initialize the MPU6050 data structure */
    mpu6050_sensor_t accgyrotemp, previous_accgyrotemp;
    MPU6050_InitializeData(&accgyrotemp);
    MPU6050_InitializeData(&previous_accgyrotemp);

    /* initialize the HMC5883L data structure */
    hmc5883l_data_t compass, previous_compass;
    HMC5883L_InitializeData(&compass);
    HMC5883L_InitializeData(&previous_compass);

    /* initialize HMC5883L reading */
    uint32_t lastHMCRead = 0;
    const uint32_t readHMCEvery = 1000 / 75; /* at 75Hz, data come every (1000/75Hz) ms. */

    /************************************************************************/
    /* Fetch scaler values                                                  */
    /************************************************************************/

#if DATA_FUSE_MODE

    const fix16_t mpu6050_accelerometer_scaler = mpu6050_accelerometer_get_scaler();
    const fix16_t mpu6050_gyroscope_scaler = mpu6050_gyroscope_get_scaler();
    const fix16_t hmc5883l_magnetometer_scaler = hmc5883l_magnetometer_get_scaler();

#endif // DATA_FUSE_MODE

    /************************************************************************/
    /* Prepare data fusion                                                  */
    /************************************************************************/

#if DATA_FUSE_MODE

    uint32_t last_transmit_time = 0;
    uint32_t last_fusion_time = systemTime();

    fusion_initialize();

#endif // DATA_FUSE_MODE

    /************************************************************************/
    /* Main loop                                                            */
    /************************************************************************/

    for(;;)
    {
        /* helper variables to track data freshness */
        uint_fast8_t have_gyro_data = 0;
        uint_fast8_t have_acc_data = 0;
        uint_fast8_t have_mag_data = 0;

        /************************************************************************/
        /* Determine if sensor data fetching is required                        */
        /************************************************************************/

        /* helper variables for event processing */
        int eventsProcessed = 0;
        int readMPU, readHMC;
#if ENABLE_MMA8451Q
        int readMMA;
#endif

        /* atomic detection of fresh data */
        __disable_irq();
#if ENABLE_MMA8451Q
        readMMA = poll_mma8451q;
#endif
        readMPU = poll_mpu6050;
        poll_mma8451q = 0;
        poll_mpu6050 = 0;
        __enable_irq();

        /* detection of HMC read */
        /*
         * TODO: read synchronized with MPU
         */
        readHMC = 0;
        uint32_t time = systemTime();
        if ((time - lastHMCRead) >= readHMCEvery)
        {
            readHMC = 1;
            lastHMCRead = time;
        }

        /************************************************************************/
        /* Fetching MPU6050 sensor data if required                             */
        /************************************************************************/

        /* read accelerometer/gyro */
        if (readMPU)
        {
            LED_BlueOff();

            I2CArbiter_Select(MPU6050_I2CADDR);
            MPU6050_ReadData(&accgyrotemp);

            /* mark event as detected */
            eventsProcessed = 1;

            /* check for data freshness */
            have_acc_data = (accgyrotemp.accel.x != previous_accgyrotemp.accel.x)
                            || (accgyrotemp.accel.y != previous_accgyrotemp.accel.y)
                            || (accgyrotemp.accel.z != previous_accgyrotemp.accel.z);

            have_gyro_data = (accgyrotemp.gyro.x != previous_accgyrotemp.gyro.x)
                             || (accgyrotemp.gyro.y != previous_accgyrotemp.gyro.y)
                             || (accgyrotemp.gyro.z != previous_accgyrotemp.gyro.z);

            /* loop current data --> previous data */
            previous_accgyrotemp = accgyrotemp;
        }

        /************************************************************************/
        /* Fetching HMC5883L sensor data if required                            */
        /************************************************************************/

        /* read compass data */
        if (readHMC)
        {
            I2CArbiter_Select(HMC5883L_I2CADDR);
            HMC5883L_ReadData(&compass);

            /* mark event as detected */
            eventsProcessed = 1;

            /* check for data freshness */
            have_mag_data = (compass.x != previous_compass.x)
                            || (compass.y != previous_compass.y)
                            || (compass.z != previous_compass.z);

            /* loop current data --> previous data */
            previous_compass = compass;
        }

        /************************************************************************/
        /* Fetching MMA8451Q sensor data if required                            */
        /************************************************************************/

#if ENABLE_MMA8451Q
        /* read accelerometer */
        if (readMMA)
        {
            LED_RedOff();

            I2CArbiter_Select(MMA8451Q_I2CADDR);
            MMA8451Q_ReadAcceleration14bitNoFifo(&acc);

            /* mark event as detected */
            eventsProcessed = 1;
        }
#endif

        /************************************************************************/
        /* Raw sensor data output over serial                                   */
        /************************************************************************/

#if DATA_FETCH_MODE

        /* data availability + sanity check
         * This sent me on a long bug hunt: Sometimes the interrupt would be raised
         * even if not all data registers were written. This always resulted in a
         * z data register not being fully written which, in turn, resulted in
         * extremely jumpy measurements.
         */
        if (readMPU && accgyrotemp.status != 0)
        {
            /* write data */
            uint8_t type = 0x02;
            P2PPE_TransmissionPrefixed(&type, 1, (uint8_t*)accgyrotemp.data, sizeof(accgyrotemp.data), IO_SendByte);
        }

        /* data availability + sanity check */
        if (readHMC && (compass.status & HMC5883L_SR_RDY_MASK) != 0) /* TODO: check if not in lock state */
        {
            uint8_t type = 0x03;
            P2PPE_TransmissionPrefixed(&type, 1, (uint8_t*)compass.xyz, sizeof(compass.xyz), IO_SendByte);
        }

#if ENABLE_MMA8451Q
        /* data availability + sanity check */
        if (readMMA && acc.status != 0)
        {
            uint8_t type = 0x01;
            P2PPE_TransmissionPrefixed(&type, 1, (uint8_t*)acc.xyz, sizeof(acc.xyz), IO_SendByte);
        }
#endif

#endif // DATA_FETCH_MODE

        /************************************************************************/
        /* Sensor data fusion                                                   */
        /************************************************************************/

#if DATA_FUSE_MODE

        // if there were sensor data ...
        if (eventsProcessed)
        {
            v3d gyro, acc, mag;

            // convert, calibrate and store gyroscope data
            if (have_gyro_data)
            {
                sensor_prepare_mpu6050_gyroscope_data(&gyro, accgyrotemp.gyro.x, accgyrotemp.gyro.y, accgyrotemp.gyro.z, mpu6050_gyroscope_scaler);
                fusion_set_gyroscope_v3d(&gyro);
            }

            // convert, calibrate and store accelerometer data
            if (have_acc_data)
            {
                sensor_prepare_mpu6050_accelerometer_data(&acc, accgyrotemp.accel.x, accgyrotemp.accel.y, accgyrotemp.accel.z, mpu6050_accelerometer_scaler);
                fusion_set_accelerometer_v3d(&acc);
            }

            // convert, calibrate and store magnetometer data
            if (have_mag_data)
            {
                sensor_prepare_hmc5883l_data(&mag, compass.x, compass.y, compass.z, hmc5883l_magnetometer_scaler);
                fusion_set_magnetometer_v3d(&mag);
            }

            // get the time differential
            const uint32_t current_time = systemTime();
            const fix16_t deltaT_ms = fix16_from_int(current_time - last_fusion_time);
            const fix16_t deltaT = fix16_mul(deltaT_ms, F16(0.001));

            last_fusion_time = current_time;

            FusionSignal_Predict();

            // predict the current measurements
            fusion_predict(deltaT);

            FusionSignal_Update();

            // correct the measurements
            fusion_update(deltaT);


            FusionSignal_Clear();

#if 0

            fix16_t yaw, pitch, roll;
            fusion_fetch_angles(&roll, &pitch, &yaw);

#if 0
            float yawf = fix16_to_float(yaw),
                  pitchf = fix16_to_float(pitch),
                  rollf = fix16_to_float(roll);

            IO_SendInt16((int16_t)yawf);
            IO_SendInt16((int16_t)pitchf);
            IO_SendInt16((int16_t)rollf);

            IO_SendByteUncommited('\r');
            IO_SendByte('\n');
#else
            if (current_time - last_transmit_time >= 100)
            {
                /* write data */
                uint8_t type = 42;
                fix16_t buffer[3] = { roll, pitch, yaw };
                P2PPE_TransmissionPrefixed(&type, 1, (uint8_t*)buffer, sizeof(buffer), IO_SendByte);

                last_transmit_time = current_time;
            }
#endif
#else
            if (current_time - last_transmit_time >= 100)
            {
                /* write data */
                switch (output_mode)
                {
                case RPY:
                {
                    fix16_t roll, pitch, yaw;
                    fusion_fetch_angles(&roll, &pitch, &yaw);

                    /* write data */
                    uint8_t type = 42;
                    fix16_t buffer[3] = { roll, pitch, yaw };
                    P2PPE_TransmissionPrefixed(&type, 1, (uint8_t*)buffer, sizeof(buffer), IO_SendByte);
                    break;
                }
                case QUATERNION:
                {
                    qf16 orientation;
                    fusion_fetch_quaternion(&orientation);

                    uint8_t type = 43;
                    fix16_t buffer[4] = { orientation.a, orientation.b, orientation.c, orientation.d };
                    P2PPE_TransmissionPrefixed(&type, 1, (uint8_t*)buffer, sizeof(buffer), IO_SendByte);
                    break;
                }
                case QUATERNION_RPY:
                {
                    fix16_t roll, pitch, yaw;
                    fusion_fetch_angles(&roll, &pitch, &yaw);

                    qf16 orientation;
                    fusion_fetch_quaternion(&orientation);

                    uint8_t type = 44;
                    fix16_t buffer[7] = { orientation.a, orientation.b, orientation.c, orientation.d, roll, pitch, yaw };
                    P2PPE_TransmissionPrefixed(&type, 1, (uint8_t*)buffer, sizeof(buffer), IO_SendByte);
                    break;
                }
                case SENSORS_RAW:
                {
                    uint8_t type = 0;
                    fix16_t buffer[6] = { acc.x, acc.y, acc.z, mag.x, mag.y, mag.z };
                    P2PPE_TransmissionPrefixed(&type, 1, (uint8_t*)buffer, sizeof(buffer), IO_SendByte);
                    break;
                }
                }

                last_transmit_time = current_time;
            }
#endif

        }

#endif // DATA_FUSE_MODE

        /************************************************************************/
        /* Read user data input                                                 */
        /************************************************************************/

        /* as long as there is data in the buffer */
        while(!RingBuffer_Empty(&uartInputFifo))
        {
            /* light one led */
            LED_RedOn();

            /* fetch byte */
            uint8_t data = IO_ReadByte();

            output_mode = (output_mode_t)data;

            LED_RedOff();
#if 0
            /* echo to output */
            IO_SendByte(data);

            /* mark event as detected */
            eventsProcessed = 1;
#endif
        }

        /************************************************************************/
        /* Save energy if you like to                                           */
        /************************************************************************/

        /* in case of no events, allow a sleep */
        if (!eventsProcessed)
        {
            /*
             * Care must be taken with this instruction here, as it can lead
             * to a condition where after being woken up (e.g. by the SysTick)
             * and looping through, immediately before entering WFI again
             * an interrupt would yield a true condition for the branches below.
             * In this case this loop would be blocked until the next IRQ,
             * which, in case of a 1ms SysTick timer, could be too late.
             *
             * To counter this behaviour, SysTick has been speed up by factor
             * four (0.25ms).
             */
#if 0
            __WFI();
#endif
        }
    }

    return 0;
}
示例#2
0
void raw_data(const int16_t *data)
{
	static int force_orientation_counter=0;
	float x, y, z, ratio, magdiff;
	Point_t point;

	add_magcal_data(data);
	x = magcal.V[0];
	y = magcal.V[1];
	z = magcal.V[2];
	if (MagCal_Run()) {
		x -= magcal.V[0];
		y -= magcal.V[1];
		z -= magcal.V[2];
		magdiff = sqrtf(x * x + y * y + z * z);
		//printf("magdiff = %.2f\n", magdiff);
		if (magdiff > 0.8f) {
			fusion_init();
			rawcount = OVERSAMPLE_RATIO;
			force_orientation_counter = 240;
		}
	}

	if (force_orientation_counter > 0) {
		if (--force_orientation_counter == 0) {
			//printf("delayed forcible orientation reset\n");
			fusion_init();
			rawcount = OVERSAMPLE_RATIO;
		}
	}

	if (rawcount >= OVERSAMPLE_RATIO) {
		memset(&accel, 0, sizeof(accel));
		memset(&mag, 0, sizeof(mag));
		memset(&gyro, 0, sizeof(gyro));
		rawcount = 0;
	}
	x = (float)data[0] * G_PER_COUNT;
	y = (float)data[1] * G_PER_COUNT;
	z = (float)data[2] * G_PER_COUNT;
	accel.GpFast[0] = x;
	accel.GpFast[1] = y;
	accel.GpFast[2] = y;
	accel.Gp[0] += x;
	accel.Gp[1] += y;
	accel.Gp[2] += y;

	x = (float)data[3] * DEG_PER_SEC_PER_COUNT;
	y = (float)data[4] * DEG_PER_SEC_PER_COUNT;
	z = (float)data[5] * DEG_PER_SEC_PER_COUNT;
	gyro.Yp[0] += x;
	gyro.Yp[1] += y;
	gyro.Yp[2] += z;
	gyro.YpFast[rawcount][0] = x;
	gyro.YpFast[rawcount][1] = y;
	gyro.YpFast[rawcount][2] = z;

	apply_calibration(data[6], data[7], data[8], &point);
	mag.BcFast[0] = point.x;
	mag.BcFast[1] = point.y;
	mag.BcFast[2] = point.z;
	mag.Bc[0] += point.x;
	mag.Bc[1] += point.y;
	mag.Bc[2] += point.z;

	rawcount++;
	if (rawcount >= OVERSAMPLE_RATIO) {
		ratio = 1.0f / (float)OVERSAMPLE_RATIO;
		accel.Gp[0] *= ratio;
		accel.Gp[1] *= ratio;
		accel.Gp[2] *= ratio;
		gyro.Yp[0] *= ratio;
		gyro.Yp[1] *= ratio;
		gyro.Yp[2] *= ratio;
		mag.Bc[0] *= ratio;
		mag.Bc[1] *= ratio;
		mag.Bc[2] *= ratio;
		fusion_update(&accel, &mag, &gyro, &magcal);
		fusion_read(&current_orientation);
	}
}