LCD implementation of our project.
Dependencies: mbed mbed-rtos MLX90614
Revision 6:49a007861c76, committed 2015-05-30
- Comitter:
- ovidiup13
- Date:
- Sat May 30 14:58:44 2015 +0000
- Parent:
- 5:5b1a8ad6c187
- Child:
- 7:11675c1dce4f
- Commit message:
- integrated level meter functionality and added 3-way switch control
Changed in this revision
--- a/Item.h Thu May 28 16:07:00 2015 +0000 +++ b/Item.h Sat May 30 14:58:44 2015 +0000 @@ -3,12 +3,20 @@ #include "st7565LCD.h" #include "rtos.h" + +//screen configuration #define LEFT_MARGIN 5 #define DEFAULT_COLOR 20 #define SCREEN_WIDTH 128 #define SCREEN_HEIGHT 64 +//control macros +#define NL 121 //select - y +#define UP 119 //up - w +#define DOWN 115 //down - s + +//threading macros #define START_THREAD 1 #define PAUSE_THREAD 2
--- a/LevelMeter.cpp Thu May 28 16:07:00 2015 +0000 +++ b/LevelMeter.cpp Sat May 30 14:58:44 2015 +0000 @@ -26,12 +26,15 @@ void LevelMeter::update_cross() { lt->signal_wait(START_THREAD); //wait for signal to start thread + initSensors(); + Result_avrg result; //draw the static circle - int i = 0, j = 0; + //int i = 0, j = 0; while(true) { - draw_elements(i++, j++); - //do something - Thread::wait(30); + calc_avrg_or(&result,2); + draw_elements(result.x, result.y); + //printf("%0.0f, %0.0f\n", result.x, result.y); + Thread::wait(15); st7565->clear(); } } @@ -51,14 +54,22 @@ if(ry >= 270) ry -= 360; //calculate coordinates - cross_x = (int) ((rx * SCREEN_WIDTH)/360.0) + 63; - cross_y = (int) ((ry * SCREEN_HEIGHT)/360.0) + 35; + cross_x = (int) ((2*rx * SCREEN_WIDTH)/360.0) + X0; + cross_y = (int) ((2*ry * SCREEN_HEIGHT)/360.0) + Y0; - printf("Coordinates for cross are: %d, %d\n", cross_x, cross_y); + //printf("Coordinates for cross are: %d, %d\n", cross_x, cross_y); //draw the cross - st7565->drawline(cross_x, cross_y - RADIUS_lvl/2, cross_x, cross_y + RADIUS_lvl/2, DEFAULT_COLOR); - st7565->drawline(cross_x - RADIUS_lvl/2, cross_y, cross_x + RADIUS_lvl/2, cross_y, DEFAULT_COLOR); + st7565->drawline(cross_x, cross_y - RADIUS_lvl*3, cross_x, cross_y + RADIUS_lvl*3, DEFAULT_COLOR); + st7565->drawline(cross_x - RADIUS_lvl*3, cross_y, cross_x + RADIUS_lvl*3, cross_y, DEFAULT_COLOR); + + //draw results + char *rsx = (char*)malloc(sizeof(char)*7); + char *rsy = (char*)malloc(sizeof(char)*7); + sprintf(rsx, "X: %0.0f", rx); + sprintf(rsy, "Y: %0.0f", ry); + st7565->drawstring(3, 7, rsx); + st7565->drawstring(SCREEN_WIDTH - 38, 7, rsy); //display st7565->display();
--- a/LevelMeter.h Thu May 28 16:07:00 2015 +0000 +++ b/LevelMeter.h Sat May 30 14:58:44 2015 +0000 @@ -1,10 +1,11 @@ #include "Item.h" +#include "gyro.h" //define coordinates #define X0 63 //center -#define Y0 35 //center +#define Y0 31 //center #define POINTER_LENGTH 10 -#define RADIUS_lvl 10 +#define RADIUS_lvl 3 class LevelMeter: public Item { public:
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MKI124V1.h Sat May 30 14:58:44 2015 +0000 @@ -0,0 +1,84 @@ +// Defines for the MEMS sensors on the STEVAL-MKI124V1 board +// Liam Goudge. March 2014 + +// LPS331AP MEMS pressure and temperature sensor +#define LPS331addr 0xBA // I2C address of the sensor for writes (line SAO is tied high on this board so bit 1=1. Note this may not work on other boards). + +#define pWHO_AM_I 0x0F // "ping" register. Device will respond even when in sleep mode +#define pRES_CONF 0x10 // Reset value is 0x7A (512 pressure samples and 128 temperature samples) +#define pCTRL_REG1 0x20 +#define pCTRL_REG2 0x21 +#define pCTRL_REG3 0x22 +#define pPRESS_OUT_XL 0x28 +#define pPRESS_OUT_L 0x29 +#define pPRESS_OUT_H 0x2A +#define pTEMP_OUT_L 0x2B // Temperature data. 2's complement. Device will respond when in sleep mode +#define pTEMP_OUT_H 0x2C + +// LSM303DLHC MEMS ascceleratometer, magnetometer and temperature sensor +#define LSM303_m 0x3C // I2C base address of the magnetometer sensor +#define LSM303_a 0x32 // I2C base address of the accelerometer sensor + +// Magnetometer registers +#define mCRA_REG_M 0x00 // Magnetic sensor configuration register A +#define mCRB_REG_M 0x01 // Magnetic sensor configuration register B +#define mMR_REG_M 0x02 // Magnetometer mode register +#define mOUT_X_H_M 0x03 // X-axis magnetic field data High byte +#define mOUT_X_L_M 0x04 // X-axis magnetic field data Low byte +#define mOUT_Z_H_M 0x05 // Z-axis magnetic field data High byte +#define mOUT_Z_L_M 0x06 // Z-axis magnetic field data Low byte +#define mOUT_Y_H_M 0x07 // Y-axis magnetic field data High byte +#define mOUT_Y_L_M 0x08 // Y-axis magnetic field data Low byte +#define mSR_REG_M 0x09 // Magnetometer status register +#define mIRA_REG_M 0x0A // ID register A. Should read 0x48 +#define mCTRL_REG1_A 0x20 +#define mTEMP_OUT_H_M 0x31 // Magnetometer temperature register High byte +#define mTEMP_OUT_L_M 0x32 // Magnetometer temperature register Low byte + +// Accelerometer registers +#define aCTRL_REG1_A 0x20 // Accelerometer output data rate ODR, low power modes etc +#define aCTRL_REG4_A 0x23 // Accelerometer full scale selection etc +#define aOUT_X_L_A 0x28 // Accelerometer X axis low byte +#define aOUT_X_H_A 0x29 // Accelerometer X axis high byte +#define aOUT_Y_L_A 0x2A // Accelerometer Y axis low byte +#define aOUT_Y_H_A 0x2B // Accelerometer Y axis high byte +#define aOUT_Z_L_A 0x2C // Accelerometer Z axis low byte +#define aOUT_Z_H_A 0x2D // Accelerometer Z axis high byte + +// L3GD20 MEMS gyro. 3 axis angular rate sensor +#define L3GD20_ADDR 0xD6 // I2C base address of the gyro + +#define gWHO_AM_I 0x0F // Ping register. Response is 0xD4. Responds even when device is off +#define gCTRL_REG1 0x20 // Sets Output Data Rate, Bandwidth and Power mode +#define gCTRL_REG4 0x23 // +#define gOUT_TEMP 0x26 // Temperature data. 8 bit resolution +#define gOUT_X_L 0x28 // X-axis angular rate low byte expressed as 2's complement +#define gOUT_X_H 0x29 // X-axis angular rate high byte +#define gOUT_Y_L 0x2A +#define gOUT_Y_H 0x2B +#define gOUT_Z_L 0x2C +#define gOUT_Z_H 0x2D + + +// Structs +typedef struct{ + float pitch; + float roll; + int16_t aX; + int16_t aY; + int16_t aZ; + float heading; + float tempC; + float pressuremB; + } SensorState_t; + + + +typedef struct{ + float x; + float y; + float z; + int16_t aX; + int16_t aY; + int16_t aZ; +}Result_avrg;
--- a/Menu.h Thu May 28 16:07:00 2015 +0000 +++ b/Menu.h Sat May 30 14:58:44 2015 +0000 @@ -1,17 +1,8 @@ #ifndef _MENU_H_ #define _MENU_H_ -#include<stdio.h> -#include <stdlib.h> -#include "st7565LCD.h" #include "Item.h" -//define control keys -#define NL 121 //newline char -#define BS 8 //backspace -#define UP 119 -#define DOWN 115 - int const MAX_ITEMS = 16; int const TITLE_LINE = 1; int const FIRST_ITEM_LINE = 1;
--- a/UserInterface.h Thu May 28 16:07:00 2015 +0000 +++ b/UserInterface.h Sat May 30 14:58:44 2015 +0000 @@ -25,6 +25,13 @@ //define default color #define _DEFAULT_COLOR 20 +//define mbed pins +#define _MOSI p11 +#define _SCLK p13 +#define _RST p24 +#define _A0 p8 +#define _CS p12 + using namespace std; class Item;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gyro.cpp Sat May 30 14:58:44 2015 +0000 @@ -0,0 +1,219 @@ +#include "gyro.h" + +//DigitalOut myled(LED1); +//Serial pc(USBTX, USBRX); // tx, rx for USB debug printf to terminal console +I2C i2c(p28, p27); // LPC1768 I2C pin allocation +//DigitalIn din(p23); // used as a test button + +// Globals +int16_t const Offset_mX=-40.0; +int16_t const Offset_mY=-115.0; +float const RadtoDeg=(180.0/3.141592654); + + +char readByte(char address, char reg) +// Reads one byte from an I2C address +// Didn't bother to make a multi-byte version to read in X,Y,Z low/high series of registers because... +// the data registers of all sensors they are in the same XL,XH,YL,YH,ZL,ZH order apart from the magnetometer which is XH,XL,ZH,ZL,YH,YL... +{ + char result; + + i2c.start(); + i2c.write(address); // Slave address with direction=write + i2c.write(reg); // Subaddress (register) + + i2c.start(); // Break transmission to change bus direction + i2c.write(address + 1); // Slave address with direction=read [bit0=1] + + result = i2c.read(0); + i2c.stop(); + return (result); + } + +void writeByte(char address, char reg,char value) +// Sends 1 byte to an I2C address +{ + i2c.start(); + i2c.write(address); // Slave address + i2c.write(reg); // Subaddress (register) + i2c.write(value); + i2c.stop(); + + } + +void initSensors (void) +// Switch on and set up the 3 on-board sensors +{ + //pc.printf("--------------------------------------\n"); + //pc.printf("\nSTM MEMS eval board sensor init \n"); + +#ifdef LSM303_on + // LSM303DLHC Magnetic sensor + //pc.printf("LSM303DLHC ping (should reply 0x48): %x \n",readByte(LSM303_m,mIRA_REG_M)); + writeByte(LSM303_m,mCRA_REG_M,0x94); //switch on temperature sensor and set Output Data Rate to 30Hz + writeByte(LSM303_m,mCRB_REG_M,0x20); // Set the gain for +/- 1.3 Gauss full scale range + writeByte(LSM303_m,mMR_REG_M,0x0); // Continuous convertion mode + + // LSM303DLHC Accelerometer + writeByte(LSM303_a,aCTRL_REG1_A ,0x37); // Set 25Hz ODR, everything else on + writeByte(LSM303_a,aCTRL_REG4_A ,0x08); // Set full scale to +/- 2g sensitivity and high rez mode +#endif + + //pc.printf("--------------------------------------\n \n"); + wait(2); // Wait for settings to stabilize + } + +void LSM303 (SensorState_t * state) +// Magnetometer and accelerometer +{ + char xL, xH, yL, yH, zL, zH; + int16_t mX, mY, mZ,aX,aY,aZ; + float pitch,roll,faX,faY; + + xL=readByte(LSM303_m,mOUT_X_L_M); + xH=readByte(LSM303_m,mOUT_X_H_M); + yL=readByte(LSM303_m,mOUT_Y_L_M); + yH=readByte(LSM303_m,mOUT_Y_H_M); + zL=readByte(LSM303_m,mOUT_Z_L_M); + zH=readByte(LSM303_m,mOUT_Z_H_M); + + mX=(xH<<8) | (xL); // 16-bit 2's complement data + mY=(yH<<8) | (yL); + mZ=(zH<<8) | (zL); + + //pc.printf("mX=%hd %X mY=%hd %X mZ=%hd %X \n",mX,mX,mY,mY,mZ,mZ); + + mX=mX-Offset_mX; // These are callibration co-efficients to deal with non-zero soft iron magnetic offset + mY=mY-Offset_mY; + + xL=readByte(LSM303_a,aOUT_X_L_A); + xH=readByte(LSM303_a,aOUT_X_H_A); + yL=readByte(LSM303_a,aOUT_Y_L_A); + yH=readByte(LSM303_a,aOUT_Y_H_A); + zL=readByte(LSM303_a,aOUT_Z_L_A); + zH=readByte(LSM303_a,aOUT_Z_H_A); + + aX=(signed short) ( (xH<<8) | (xL) ) >> 4; // 12-bit data from ADC. Cast ensures that the 2's complement sign is not lost in the right shift. + aY=(signed short) ( (yH<<8) | (yL) ) >> 4; + aZ=(signed short) ( (zH<<8) | (zL) ) >> 4; + + //pc.printf("aX=%hd %X aY=%hd %X aZ=%hd %X \n",aX,aX,aY,aY,aZ,aZ); + + faX=((float) aX) /2000.0; // Accelerometer scale I chose is 1mg per LSB with range +/-2g. So to normalize for full scale need to divide by 2000. + faY=((float) aY) /2000.0; // If you don't do this the pitch and roll calcs will not work (inverse cosine of a value greater than 1) + //faZ=((float) aZ) /2000.0; // Not used in a calc so comment out to avoid the compiler warning + + // Trigonometry derived from STM app note AN3192 and from WikiRobots + pitch = asin((float) -faX*2); // Dividing faX and faY by 1000 rather than 2000 seems to give better tilt immunity. Do it here rather than above to preserve true mg units of faX etc + roll = asin(faY*2/cos(pitch)); + + float xh = mX * cos(pitch) + mZ * sin(pitch); + float yh = mX * sin(roll) * sin(pitch) + mY * cos(roll) - mZ * sin(roll) * cos(pitch); + float zh = -mX * cos(roll) * sin(pitch) + mY * sin(roll) + mZ * cos(roll) * cos(pitch); + + float heading = atan2(yh, xh) * RadtoDeg; // Note use of atan2 rather than atan since better for working with quadrants + if (yh < 0) + heading=360+heading; + + state->heading=heading; + state->pitch=pitch; + state->roll=roll; + state->aX = (float)aX; + state->aY = (float)aY; + state->aZ = (float)aZ; + //5.1f + //pc.printf("Orientation (deg): Rot_X: %0.0f Rot_Y: %0.0f Rot_Z: %0.0f \n",roll*RadtoDeg,pitch*RadtoDeg,heading); + //pc.printf("Acceleration (mg): X: %5hd Y: %5hd Z: %5hd \n",aX,aY,aZ); + +} + +//calculates the difference for acceleration in int16_t value +void calc_avrg_ac(Result_avrg* result,int samples){ + int i = 0; + result -> aX = 0; + result -> aY = 0; + result -> aZ = 0; + SensorState_t state; + for(i = 0;i<samples;i++){ + #ifdef LSM303_on + LSM303(&state); + #endif + result -> aX += state.aX; + result -> aY += state.aY; + result -> aZ += state.aZ; + //pc.printf("Acceleration (mg): X: %5hd Y: %5hd Z: %5hd \n",state.aX,state.aY,state.aZ); + + wait(0.01); + } + //pc.printf("Acceleration (mg): X: %5hd Y: %5hd Z: %5hd \n",result->aX,result->aY,result->aZ); + result -> aX = result -> aX / samples; + result -> aY = result -> aY / samples; + result -> aZ = result -> aZ / samples; + //pc.printf("rAcceleration (mg): X: %5hd Y: %5hd Z: %5hd \n",result->aX,result->aY,result->aZ); +} + +//calculates the difference for orientation in float value +void calc_avrg_or(Result_avrg* result,int samples){ + int i = 0; + result -> x = 0; + result -> y = 0; + result -> z = 0; + SensorState_t state; + for(i = 0;i<samples;i++){ + #ifdef LSM303_on + LSM303(&state); + #endif + result -> x += state.roll*RadtoDeg; + result -> y += state.pitch*RadtoDeg; + result -> z += state.heading; + //pc.printf("Orientation (deg): Rot_X: %0.0f Rot_Y: %0.0f Rot_Z: %0.0f \n",state.roll*RadtoDeg,state.pitch*RadtoDeg,state.heading); + wait(0.01); + } + //pc.printf("Orientation (deg): Rot_X: %0.0f Rot_Y: %0.0f Rot_Z: %0.0f \n", result -> x ,result -> y,result -> z); + result -> x = result -> x / samples; + result -> y = result -> y / samples; + result -> z = result -> z / samples; + //pc.printf("Orientation (deg): rRot_X: %0.0f rRot_Y: %0.0f rRot_Z: %0.0f \n", result -> x ,result -> y,result -> z); +} + +//gets the two results and saves the answer in r1 structure +void calc_diff(Result_avrg* r1, Result_avrg* r2){ + r1 -> x = abs(r1->x - r2->x); + r1 -> y = abs(r1->y - r2->y); + r1 -> z = abs(r1->z - r2->z); + + r1 -> aX = abs(r1->aX - r2->aX); + r1 -> aY = abs(r1->aY - r2->aY); + r1 -> aZ = abs(r1->aZ - r2->aZ); +} + +/* + +int main() +{ + SensorState_t state; + Result_avrg result1; + //Result_avrg result2; + initSensors(); + //pc.baud(115200); + calc_avrg_or(&result1,3); + //calc_avrg_ac(&result1,3); + //pc.printf("Orientation (deg): Rot_X: %0.0f Rot_Y: %0.0f Rot_Z: %0.0f \n", result1.x ,result1.y,result1.z); + //pc.printf("Acceleration (mg): X: %5hd Y: %5hd Z: %5hd \n",result1.aX,result1.aY,result1.aZ); + //calc_avrg_or(&result2,3); + //calc_avrg_ac(&result2,3); + //pc.printf("Orientation (deg): Rot_X: %0.0f Rot_Y: %0.0f Rot_Z: %0.0f \n", result2.x ,result2.y,result2.z); + //pc.printf("Acceleration (mg): X: %5hd Y: %5hd Z: %5hd \n",result2.aX,result2.aY,result2.aZ); + //calc_diff(&result1,&result2); + //pc.printf("Orientation (deg): Rot_X: %0.0f Rot_Y: %0.0f Rot_Z: %0.0f \n", result1.x ,result1.y,result1.z); + //pc.printf("Acceleration (mg): X: %5hd Y: %5hd Z: %5hd \n",result1.aX,result1.aY,result1.aZ); +#ifdef LSM303_on + //LSM303(&state); +#endif + + //pc.printf("Orientation (deg): Rot_X: %0.0f Rot_Y: %0.0f Rot_Z: %0.0f \n",state.roll*RadtoDeg,state.pitch*RadtoDeg,state.heading); + //pc.printf("Acceleration (mg): X: %5hd Y: %5hd Z: %5hd \n",state.aX,state.aY,state.aZ); + //pc.printf("\n"); + +} +*/ \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gyro.h Sat May 30 14:58:44 2015 +0000 @@ -0,0 +1,27 @@ +// MBED reference code for the ST Micro STEVAL-MKI124V1 header board +// This board has: LPS331 pressure/temperature sensor, L3GD20 gyroscope and LSM303DLHC magnetometer/accelerometer +// Code accesses each of the 3 MEMS sensors and calculates pressure, temp, heading, tilt, roll and angular velocity +// Code is not optimized for efficienecy but instead for clarity of how you use the sensors +// ST application note AN3192 was key in developing the tilt-corrected compass +// Developed on an LPC1768 +// By Liam Goudge. March 2014 + +#define LSM303_on + +#include "mbed.h" +#include "MKI124V1.h" +#include "math.h" + +char readByte(char address, char reg); + +void writeByte(char address, char reg,char value); + +void initSensors (void); + +void LSM303 (SensorState_t * state); + +void calc_avrg_ac(Result_avrg* result,int samples); + +void calc_avrg_or(Result_avrg* result,int samples); + +void calc_diff(Result_avrg* r1, Result_avrg* r2); \ No newline at end of file
--- a/main.cpp Thu May 28 16:07:00 2015 +0000 +++ b/main.cpp Sat May 30 14:58:44 2015 +0000 @@ -1,25 +1,22 @@ #include "UserInterface.h" #include "st7565LCD.h" -//define mbed pins -#define _MOSI p11 -#define _SCLK p13 -#define _RST p24 -#define _A0 p8 -#define _CS p12 - ST7565 st7565(_MOSI, _SCLK, _CS, _RST, _A0); // mosi, sclk, cs, rst, a0 Serial pc(USBTX, USBRX); //rx, tx //buttons DigitalIn down(p18); DigitalIn select(p19); +DigitalIn up(p20); -void init_config(UI *ui){ +int main(){ + //create god UI object + UI * ui = new UI(&st7565); + //initialize configuration //create main menu Menu * main_menu = new Menu(" Main Menu", &st7565); - /* + //create distance screens Measure *distance = new Measure(" Distance", &st7565, main_menu); distance->setDescription("Select Start from the menu below to start laser."); @@ -33,8 +30,6 @@ distance2->setNext(" Select", distance3); distance3->setNext(" Start again", distance); main_menu->addItem(distance); - */ - //create point-to-point screens Measure *p2p = new Measure(" Point-to-Point", &st7565, main_menu); @@ -75,12 +70,6 @@ thermo3->setNext(" Start", thermo); main_menu->addItem(thermo); - /* - //create settings menu - Menu *settings = new Menu(" Settings", &st7565); - main_menu->addItem(settings); - */ - //create header object Header * header = new Header(70, "", &st7565); @@ -88,28 +77,19 @@ ui->setCurrent(main_menu); ui->setHeader(header); ui->init(); -} - -int main(){ - //create god UI object - UI * ui = new UI(&st7565); - //initialize configuration - init_config(ui); while(1) { - if(down){ - ui->update('s'); + if(!down){ + ui->update('s'); //ascii 115 wait(0.2); } - else if(select){ - ui->update('y'); + else if(!select){ + ui->update('y'); //ascii 121 wait(0.2); } - /* - else{ - char c = pc.getc(); - ui->update(c); + else if(!up){ + ui->update('w'); //ascii 119 + wait(0.2); } - */ } } \ No newline at end of file