base code for beer_project
Dependencies: mbed tsi_sensor FreescaleIAP MMA8451Q MPL3115A2
main.cpp
- Committer:
- tuscasp
- Date:
- 2018-11-30
- Revision:
- 3:93bc37d442df
- Parent:
- 2:1bd31ca8a126
- Child:
- 4:64f3383f2c43
File content as of revision 3:93bc37d442df:
/*******************************************************/ /**** LELEC_2811 Multiple sensors logger ***/ /**** P. Gerard UCL 23/11/2016 ***/ /**** M. Lefebvre UCL 09/11/2018 ***/ /*******************************************************/ #include "mbed.h" #include "FreescaleIAP.h" // Library for Flash access #include "MMA8451Q.h" // Accelerometer #include "MPL3115A2.h" // Library for altimeter/temperature access #define KL25Z_VDD 2.7 // !!! Value of supply voltage VDD: To be measured on board KL25Z pin 3V3 (calibration) #define MMA8451_I2C_ADDRESS (0x1d<<1) #define FSR 0x02 // 0x00 for 2G, 0x01 for 4G, 0x02 for 8G #define REG_OUT_X_MSB 0x01 #define REG_OUT_Y_MSB 0x03 #define REG_OUT_Z_MSB 0x05 #define MPL3115A2_I2C_ADDRESS (0x60<<1) #define REG_ALTIMETER_MSB 0x01 #define DISABLE_STATE 0 #define ENABLE_STATE 1 #define NO_JUMPER 0 #define JUMPER_PRESENT 1 #define LEVEL_0 0 #define LEVEL_1 1 #define LED_ON 0 #define LED_OFF 1 #define FLASH_NO_ACQ_DONE 0 #define FLASH_ACQ_DONE 1 #define ERASE_FLASH_ERROR -1 #define WRITE_FLASH_ERROR -2 #define SECTOR_SIZE 1024 #define RESERVED_SECTOR 32 #define ACQ_TIMER_PERIOD 0.5 // Time between 2 acquisitions in seconds #define N_PER_AVERAGE 8 #define BOARD_STRAIGHT 0 #define BOARD_UPSIDE_DOWN 1 #define ACCEL_MINIMUM_FOR_STORAGE 0 // Structure of sensors Data !!!!! SIZE MUST BE A MULTIPLE OF 4 bytes !!!!! typedef struct{ int16_t Accel_X; // 2 bytes int16_t Accel_Y; // 2 bytes int16_t Accel_Z; // 2 bytes float Temperature; // 4 bytes unsigned short Analog_PTE20; // 2 bytes unsigned short Analog_PTE21; // 2 bytes unsigned short Empty; // 2 bytes } Sensor_Data; // TOTAL = 16 bytes typedef struct{ unsigned short Accel_Z; unsigned short Sallen_Key; unsigned short Interface; unsigned short Useless; } Stored_Data; int Number_Stored_Points; // --- Setup I2C for MMA8451 accelerometer // --- The last argument is the full scale range (FSR). 0x00 for 2G, 0x01 for 4G, 0x02 for 8G MMA8451Q my8451(PTE25, PTE24, MMA8451_I2C_ADDRESS, FSR); DigitalOut Accel_Enable(PTA13); // --- Set temperature sensor MPL3115A2 myMPL3115(PTE0, PTE1, MPL3115A2_I2C_ADDRESS); // --- Set serial port (for communication with PC) Serial Host_Comm(USBTX, USBRX); // Analog inputs (ADCs) AnalogIn myPTE20(PTE20); AnalogIn myPTE21(PTE21); // Analog output (DAC) AnalogOut myDAC(PTE30); // Digital outputs DigitalOut Led_Red(LED1); // Define I/O for LEDs DigitalOut Led_Green(LED2); DigitalOut Led_Blue(LED3); DigitalOut Start_Pulse_Out(PTC9); // Used to enter/exit acquisition mode DigitalIn Start_Pulse_In(PTC11); // Short pins J1_15 and J1_16 to enter in Acq_Mode // Global variables volatile bool bTimer; // 1 means a timer tick is done Ticker myTick_Acq; // Periodical timer for acquisition int Flash_Base_Address = RESERVED_SECTOR * SECTOR_SIZE; // Store Flash base address with 32K reserved for application code int Nb_Sector; uint32_t KL25_Flash_Size; // Functions declaration void Clear_Led(void); int Acquisition_Flash(void); int Read_Data_Logging(void); bool Check_Jumper(void); void myTimer_Acq_Task(void); void Acquisition_Task(void); void Read_Task(void); extern IAPCode verify_erased(int address, unsigned int length); int main() { uint8_t Count; // Count defining the number of time the LED blinks before data acquisition // Set DAC output voltage float vdac; uint16_t dac_value; // Local variable in 16 bits vdac = 0; // Voltage output value dac_value = (uint16_t) ((vdac * 65536) / KL25Z_VDD); // Transform desired voltage to fraction of 0xFFFF myDAC.write_u16(dac_value); // DAC value in range 0x0000 - 0xFFFF (see mbed's AnalogOut classe ref.) Start_Pulse_In.mode(PullNone); // Input pin is programmed as floating Accel_Enable = DISABLE_STATE; // Turn Accel. Enable I/O to disabled state // --- Baud rate setting Host_Comm.baud(115200); Clear_Led(); KL25_Flash_Size = flash_size(); // Get size of KL25 embedded Flash Nb_Sector = (KL25_Flash_Size / SECTOR_SIZE) - RESERVED_SECTOR; // Reserve max 32K for app code myTick_Acq.attach(&myTimer_Acq_Task, ACQ_TIMER_PERIOD); // Initialize timer interrupt Host_Comm.printf("\n\rLELEC2811 Multiple sensors logger V2.0 UCL 2018\n\r"); if ((sizeof(Sensor_Data) % 4) != 0) { Host_Comm.printf("\n\rERROR! Acquisition Data Structure size is NOT a multiple of 4!!! (%d)", sizeof(Sensor_Data)); for(;;); } myMPL3115.Oversample_Ratio(OVERSAMPLE_RATIO_4); myMPL3115.Barometric_Mode(); // Configure MPL3115 (used for temperature and pressure measurement) for (;;) { if (Check_Jumper() == JUMPER_PRESENT) { Clear_Led(); Count = 5; while (Count !=0) { if (Check_Jumper() == JUMPER_PRESENT) { Led_Blue = LED_ON; // Blink to alert user "Enter in Acquisition" after 5 seconds wait_ms(900); Led_Blue = LED_OFF; wait_ms(100); Count --; if (Count == 0) { Acquisition_Task(); } } else { Count = 0; } } } else { Read_Task(); } } } void Read_Task() { char host_cmd; IAPCode Flash_State; bool bAcq_Done; Flash_State = verify_erased(Flash_Base_Address, KL25_Flash_Size - (RESERVED_SECTOR * SECTOR_SIZE)); if (Flash_State == 0) // Virgin Flash ? { bAcq_Done = 0; } else { bAcq_Done = 1; } Clear_Led(); wait_ms(500); if (bAcq_Done == 1) { Led_Green = LED_ON; Host_Comm.putc('1'); } else { Led_Red = LED_ON; Host_Comm.putc('0'); } if(Host_Comm.readable()) // Did we receive a char from Host ? { host_cmd = Host_Comm.getc(); // Get it if ((host_cmd == 'R') || (host_cmd == 'r')) // Read Flash Command ? { Read_Data_Logging(); // Read and send acquisition data } } wait_ms(50); } void Acquisition_Task() { int Acq_Status; Clear_Led(); Acq_Status = Acquisition_Flash(); Clear_Led(); while (Check_Jumper() == JUMPER_PRESENT) { if (Acq_Status != FLASH_ACQ_DONE) { Led_Red = !Led_Red; } else { Led_Green = !Led_Green; } wait_ms(100); } } void Clear_Led(void) { Led_Red = LED_OFF; Led_Green = LED_OFF; Led_Blue = LED_OFF; // Bug on board : Turning on the blue LED decreases consumption... } bool Check_Jumper() // If J1_15 and J1_16 connected together -> return JUMPER_PRESENT { uint8_t i; for (i = 0 ; i < 2 ; i ++) { Start_Pulse_Out = LEVEL_1; wait_ms(1); if (Start_Pulse_In != LEVEL_1) { return NO_JUMPER; } Start_Pulse_Out = LEVEL_0; wait_ms(1); if (Start_Pulse_In != LEVEL_0) { return NO_JUMPER; } } return JUMPER_PRESENT; } int Acquisition_Flash(void) { int Status; int Flash_Ptr ; int Led_Counter; Sensor_Data myData; int Board_Position; int Count_Measurements; Stored_Data myStoredData; /*** Erase all Flash Page **/ for (Flash_Ptr = Flash_Base_Address ; Flash_Ptr < KL25_Flash_Size ; Flash_Ptr += 0x400) { Status = erase_sector(Flash_Ptr); // Erase sector if (Status !=0) { return ERASE_FLASH_ERROR; } } Flash_Ptr = Flash_Base_Address; // Begin of Storage Area in Flash Led_Blue = LED_ON; Led_Counter = 0; /*** Reset new variables **/ myStoredData.Accel_Z= 0; myStoredData.Interface = 0; myStoredData.Sallen_Key = 0; Board_Position = BOARD_STRAIGHT; Number_Stored_Points = 0; /***** Begin of Loop Acquisition - Write in Flash ***/ while (Flash_Ptr < (KL25_Flash_Size - sizeof(Sensor_Data)) ) // Acq Loop { while (bTimer == 0) // Wait Acq Tick Timer Done { } bTimer = 0; if ((float) Led_Counter * ACQ_TIMER_PERIOD == 1.0) // Blink at 1Hz { Led_Counter = 0; Led_Blue = !Led_Blue; } Led_Counter++; // Get accelerometer data Accel_Enable = ENABLE_STATE; // Rising edge -> Start accelerometer measurement // myData.Accel_X = my8451.getAccAxis(REG_OUT_X_MSB); // myData.Accel_Y = my8451.getAccAxis(REG_OUT_Y_MSB); myData.Accel_Z = my8451.getAccAxis(REG_OUT_Z_MSB); Accel_Enable = DISABLE_STATE; /*** verify if it is upside down ***/ if (myData.Accel_Z < ACCEL_MINIMUM_FOR_STORAGE) Board_Position = BOARD_UPSIDE_DOWN; if (Board_Position == BOARD_UPSIDE_DOWN){ Count_Measurements ++; // Get ADC values myData.Analog_PTE20 = myPTE20.read_u16(); myData.Analog_PTE21 = myPTE21.read_u16(); // add data to stored variable myStoredData.Accel_Z = myData.Accel_Z; myStoredData.Sallen_Key += myData.Analog_PTE20; myStoredData.Interface += myData.Analog_PTE21; Host_Comm.printf("\n\r%d %d", Count_Measurements, myStoredData.Accel_Z); // after N_PER_AVERAGE measurements, take average and store if (Count_Measurements >= N_PER_AVERAGE){ Count_Measurements = 0; myStoredData.Sallen_Key = myStoredData.Sallen_Key / N_PER_AVERAGE; myStoredData.Interface = myStoredData.Interface / N_PER_AVERAGE; /*** Save Data in Flash ***/ Number_Stored_Points ++; Status = program_flash(Flash_Ptr, (char *) &myStoredData, sizeof(Stored_Data)); // Write in the Flash if (Status != 0) { Host_Comm.printf("\n\rFlash_Write Error = %d", Status); return WRITE_FLASH_ERROR; } Flash_Ptr += sizeof(Stored_Data); // verifies if system comes back straight orientation if (myData.Accel_Z > ACCEL_MINIMUM_FOR_STORAGE) Board_Position = BOARD_STRAIGHT; if (Check_Jumper() != JUMPER_PRESENT) // If jumper removed -> Stop acquisition { return FLASH_ACQ_DONE ; } } } else { if (Check_Jumper() != JUMPER_PRESENT) // If jumper removed -> Stop acquisition return FLASH_ACQ_DONE ; } } return FLASH_ACQ_DONE ; } int Read_Data_Logging() { Stored_Data * data = (Stored_Data * )Flash_Base_Address; // Sensor_Data pointer of data stored in Flash int Flash_Record_Ptr; char cmd; int Record_Counter; int Max_Record; Stored_Data myRead_Data; // Data Structure used to retrieve saved value from Flash float Ethanol_Sallen_Key; float Ethanol_Interface; Clear_Led(); Max_Record = (Nb_Sector * SECTOR_SIZE) / sizeof(Sensor_Data); Record_Counter = 0; Flash_Record_Ptr = 0; Host_Comm.printf("\n\r# AccZ Eth_SK Eth_Int"); while (Record_Counter < Number_Stored_Points && Record_Counter < Max_Record) { Led_Green = !Led_Green; Led_Blue = !Led_Green; if(Host_Comm.readable()) { cmd = Host_Comm.getc(); if ((cmd == 'S') || (cmd == 's')) // Receiving 'S' or 's' means stop Read Flash { Clear_Led(); return 0; } } myRead_Data = data[Flash_Record_Ptr]; Flash_Record_Ptr ++; if (myRead_Data.Accel_Z == -1) // Valid data ? (!= 0xFFFFFFFF from empty Flash sector) { } else { Ethanol_Sallen_Key = ((float) myRead_Data.Sallen_Key / 0XFFFF) * KL25Z_VDD; // Convert to voltage Ethanol_Interface = ((float) myRead_Data.Interface / 0XFFFF) * KL25Z_VDD; Host_Comm.printf("\n\r%d ", Record_Counter); Host_Comm.printf("%d ", myRead_Data.Accel_Z); Host_Comm.printf("%1.3f %1.3f ", Ethanol_Sallen_Key, Ethanol_Interface); } Record_Counter ++; } Clear_Led(); return 0; } /* Interrupt Task */ void myTimer_Acq_Task() { bTimer = 1; }