base code for beer_project
Dependencies: mbed tsi_sensor FreescaleIAP MMA8451Q MPL3115A2
Diff: main.cpp
- Revision:
- 0:642dcee532b6
- Child:
- 1:3a57bceb88f8
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Mon Nov 12 22:13:57 2018 +0000 @@ -0,0 +1,405 @@ +/*******************************************************/ +/**** 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.010 // Time between 2 acquisitions in seconds + +// 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 Analog_PTE22; // 2 bytes +} Sensor_Data; // TOTAL = 16 bytes + +// --- 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); +AnalogIn myPTE22(PTE22); + +// 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.3; // 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; + +/*** 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; + +/***** 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; + + // Get temperature value + myData.Temperature = myMPL3115.getTemperature(); + + // Get ADC values + myData.Analog_PTE20 = myPTE20.read_u16(); + myData.Analog_PTE21 = myPTE21.read_u16(); + myData.Analog_PTE22 = myPTE22.read_u16(); + + /*** Save Data in Flash ***/ + Status = program_flash(Flash_Ptr, (char *) &myData, sizeof(Sensor_Data)); // Write in the Flash + if (Status != 0) + { + Host_Comm.printf("\n\rFlash_Write Error = %d", Status); + return WRITE_FLASH_ERROR; + } + Flash_Ptr += sizeof(Sensor_Data); + + if (Check_Jumper() != JUMPER_PRESENT) // If jumper removed -> Stop acquisition + { + return FLASH_ACQ_DONE ; + } + } + + return FLASH_ACQ_DONE ; +} + +int Read_Data_Logging() +{ + Sensor_Data * data = (Sensor_Data * )Flash_Base_Address; // Sensor_Data pointer of data stored in Flash + int Flash_Record_Ptr; + char cmd; + int Record_Counter; + int Max_Record; + Sensor_Data myRead_Data; // Data Structure used to retrieve saved value from Flash + + float Voltage_PTE20; + float Voltage_PTE21; + float Voltage_PTE22; + + Clear_Led(); + + Max_Record = (Nb_Sector * SECTOR_SIZE) / sizeof(Sensor_Data); + Record_Counter = 0; + Flash_Record_Ptr = 0; + + Host_Comm.printf("\n\rAccX AccY AccZ Temp PTE20 PTE21 PTE22"); + + while (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_X == -1) && (myRead_Data.Accel_Y == -1) && (myRead_Data.Accel_Z == -1)) // Valid data ? (!= 0xFFFFFFFF from empty Flash sector) + { + } + else + { + Voltage_PTE20 = ((float) myRead_Data.Analog_PTE20 / 0XFFFF) * KL25Z_VDD; // Convert to voltage + Voltage_PTE21 = ((float) myRead_Data.Analog_PTE21 / 0XFFFF) * KL25Z_VDD; + Voltage_PTE22 = ((float) myRead_Data.Analog_PTE22 / 0XFFFF) * KL25Z_VDD; + + Host_Comm.printf("\n\r%d ", Record_Counter); + Host_Comm.printf("%d %d %d ", myRead_Data.Accel_X, myRead_Data.Accel_Y, myRead_Data.Accel_Z); + Host_Comm.printf("%1.2f ", myRead_Data.Temperature); + Host_Comm.printf("%1.3f %1.3f %1.3f ", Voltage_PTE20, Voltage_PTE21, Voltage_PTE22); + } + + Record_Counter ++; + } + Clear_Led(); + return 0; +} + +/* Interrupt Task */ +void myTimer_Acq_Task() +{ + bTimer = 1; +}