Simple library for interfacing to Nokia 5110 LCD display (as found on the SparkFun website).
Fork of N5110 by
Diff: N5110.cpp
- Revision:
- 20:4145b7a59ef7
- Parent:
- 19:ba8addc061ea
--- a/N5110.cpp Thu Apr 23 18:57:52 2015 +0000 +++ b/N5110.cpp Thu May 07 16:12:53 2015 +0000 @@ -4,8 +4,10 @@ @brief Member functions implementations */ + +#include "N5110.h" #include "mbed.h" -#include "N5110.h" +#include "BMP180.h" N5110::N5110(PinName pwrPin, PinName scePin, PinName rstPin, PinName dcPin, PinName mosiPin, PinName sclkPin, PinName ledPin) @@ -404,3 +406,317 @@ } } + + + +BMP180::BMP180(PinName sdaPin, PinName sclPin) +{ + i2c = new I2C(sdaPin,sclPin); // create new I2C instance and initialise + i2c->frequency(400000); // I2C Fast Mode - 400kHz + leds = new BusOut(LED4,LED3,LED2,LED1); +} + +Measurement BMP180::readValues() +{ + // algorithm for taking measurement is taken from datasheet + int32_t UT = readUncompensatedTemperatureValue(); + int32_t UP = readUncompensatedPressureValue(); + // once you have the uncompensated T and P, you can calculate the true T and P + // using the equations from the datasheet + int32_t T = calcTrueTemperature(UT); + int32_t P = calcTruePressure(UP); + + Measurement measurement; + measurement.temperature = T*0.1; // scaled by 0.1 C + measurement.pressure = P*0.01; // Put pressure in mb + + return measurement; +} + +int32_t BMP180::readUncompensatedTemperatureValue() +{ + // from algorithm in datasheet - p15 + sendByteToRegister(0x2E,0xF4); + wait_ms(5); // 4.5 ms delay for OSS = 1 + char MSB = readByteFromRegister(0xF6); + char LSB = readByteFromRegister(0xF7); + // combine in 16-bit value + int UT = (MSB << 8) | LSB; +#ifdef DEBUG + UT = 27898; // test data from datasheet + printf("****DEBUG MODE****\nUT = %d\n",UT); +#endif + return UT; +} + +int32_t BMP180::readUncompensatedPressureValue() +{ + // from datasheet + char byte = 0x34 + (oss << 6); + sendByteToRegister(byte,0xF4); + wait_ms(8); // 7.5 ms delay for OSS = 1 + + char MSB = readByteFromRegister(0xF6); + char LSB = readByteFromRegister(0xF7); + char XLSB = readByteFromRegister(0xF7); + int UP = (MSB << 16 | LSB << 8 | XLSB) >> (8 - oss); + +#ifdef DEBUG + UP = 23843; // test data from datasheet + printf("UP = %d\n",UP); +#endif + return UP; +} + +int32_t BMP180::calcTrueTemperature(int32_t UT) +{ + // equations from data sheet + X1 = ((UT - calibration.AC6)*calibration.AC5) >> 15; + X2 = (calibration.MC << 11) / (X1 + calibration.MD); + B5 = X1 + X2; + int32_t T = (B5 + 8) >> 4; +#ifdef DEBUG + printf("****\nX1=%d\nX2=%d\nB5=%d\nT=%d\n",X1,X2,B5,T); +#endif + return T; +} + +int32_t BMP180::calcTruePressure(int32_t UP) +{ + // equations from data sheet + B6 = B5 - 4000; + X1 = (calibration.B2 * ((B6*B6) >> 12))>>11; + X2 = (calibration.AC2*B6)>>11; + X3 = X1 + X2; + B3 = (((calibration.AC1*4 + X3) << oss)+2)/4; +#ifdef DEBUG + printf("*****\nB6=%d\nX1=%d\nX2=%d\nX3=%d\nB3=%d\n",B6,X1,X2,X3,B3); +#endif + X1 = (calibration.AC3*B6)>>13; + X2 = (calibration.B1*((B6*B6)>>12))>>16; + X3 = ((X1+X2)+2)/4; + B4 = (calibration.AC4*(uint32_t)(X3+32768))>>15; +#ifdef DEBUG + printf("X1=%d\nX2=%d\nX3=%d\nB4=%u\n",X1,X2,X3,B4); +#endif + B7 = ((uint32_t)UP - B3)*(50000>>oss); +#ifdef DEBUG + printf("B7=%u\n",B7); +#endif + int32_t P; + if (B7 < 0x80000000) + P = (B7*2)/B4; + else + P = (B7/B4)*2; +#ifdef DEBUG + printf("P=%d\n",P); +#endif + X1 = (P>>8)*(P>>8); +#ifdef DEBUG + printf("X1=%d\n",X1); +#endif + X1 = (X1*3038)>>16; +#ifdef DEBUG + printf("X1=%d\n",X1); +#endif + X2 = (-7357*P)>>16; +#ifdef DEBUG + printf("X2=%d\n",X2); +#endif + P = P + (X1+X2+3791)/16; +#ifdef DEBUG + printf("P=%d\n",P); +#endif + + return P; + +} + +// configure the barometer +void BMP180::init() +{ + i2c->frequency(400000); // set Fast Mode I2C frequency + + char data = readByteFromRegister(ID_REG); // Section 4 - datasheet + if (data != 0x55) { // if correct ID not found, hang and flash error message + error(); + } + + readCalibrationData(); + + oss = 1; // standard power oversampling setting + +#ifdef DEBUG + oss = 0; // used when testing data sheet example +#endif + + +} + +// Reads factory calibrated data +void BMP180::readCalibrationData() +{ + + char eeprom[22]; + + readBytesFromRegister(EEPROM_REG_ADD,22,eeprom); + // store calibration data in structure + calibration.AC1 = (int16_t) (eeprom[0] << 8) | eeprom[1]; + calibration.AC2 = (int16_t) (eeprom[2] << 8) | eeprom[3]; + calibration.AC3 = (int16_t) (eeprom[4] << 8) | eeprom[5]; + calibration.AC4 = (uint16_t) (eeprom[6] << 8) | eeprom[7]; + calibration.AC5 = (uint16_t) (eeprom[8] << 8) | eeprom[9]; + calibration.AC6 = (uint16_t) (eeprom[10] << 8) | eeprom[11]; + calibration.B1 = (int16_t) (eeprom[12] << 8) | eeprom[13]; + calibration.B2 = (int16_t) (eeprom[14] << 8) | eeprom[15]; + calibration.MB = (int16_t) (eeprom[16] << 8) | eeprom[17]; + calibration.MC = (int16_t) (eeprom[18] << 8) | eeprom[19]; + calibration.MD = (int16_t) (eeprom[20] << 8) | eeprom[21]; + + // test data from data sheet +#ifdef DEBUG + calibration.AC1 = 408; + calibration.AC2 = -72; + calibration.AC3 = -14383; + calibration.AC4 = 32741; + calibration.AC5 = 32757; + calibration.AC6 = 23153; + calibration.B1 = 6190; + calibration.B2 = 4; + calibration.MB = -32768; + calibration.MC = -8711; + calibration.MD = 2868; + printf("****EXAMPLE CALIBRATION DATA****\n"); + printf("AC1=%d\nAC2=%d\nAC3=%d\nAC4=%u\nAC5=%u\nAC6=%u\nB1=%d\nB2=%d\nMB=%d\nMC=%d\nMD=%d\n", + calibration.AC1,calibration.AC2,calibration.AC3,calibration.AC4,calibration.AC5,calibration.AC6, + calibration.B1,calibration.B2,calibration.MB,calibration.MC,calibration.MD); +#endif +} + + +// reads a byte from a specific register +char BMP180::readByteFromRegister(char reg) +{ + int nack = i2c->write(BMP180_W_ADDRESS,®,1,true); // send the register address to the slave + if (nack) + error(); // if we don't receive acknowledgement, flash error message + + char rx; + nack = i2c->read(BMP180_W_ADDRESS,&rx,1); // read a byte from the register and store in buffer + if (nack) + error(); // if we don't receive acknowledgement, flash error message + + return rx; +} + +// reads a series of bytes, starting from a specific register +void BMP180::readBytesFromRegister(char reg,int numberOfBytes,char bytes[]) +{ + int nack = i2c->write(BMP180_W_ADDRESS,®,1,true); // send the slave write address and the configuration register address + + if (nack) + error(); // if we don't receive acknowledgement, flash error message + + nack = i2c->read(BMP180_W_ADDRESS,bytes,numberOfBytes); // read bytes + if (nack) + error(); // if we don't receive acknowledgement, flash error message + +} + +// sends a byte to a specific register +void BMP180::sendByteToRegister(char byte,char reg) +{ + char data[2]; + data[0] = reg; + data[1] = byte; + // send the register address, followed by the data + int nack = i2c->write(BMP180_W_ADDRESS,data,2); + if (nack) + error(); // if we don't receive acknowledgement, flash error message + +} + +void BMP180::error() +{ + while(1) { + leds->write(15); + wait(0.1); + leds->write(0); + wait(0.1); + } +} + + + + +N5110 lcd(p7,p8,p9,p10,p11,p13,p26);//The ports being connected of the mbed +BusOut leds(LED4,LED3,LED2,LED1);//The ports being connected of the LCD +BMP180 bmp180(p28,p27);//The ports being connected to the sensor +Serial serial(USBTX,USBRX);//Timer set-up tool + + +//Define the variable +void serialISR();//ISR that is called when serial data is received +void setTime();// function to set the UNIX time +int setTimerFlag = 0;// flag for ISR +char rxString[16];//Create a 16 chars row to display the data + +int main() +{ + lcd.init(); + bmp180.init();//Display the word before the sensor data + lcd.printString("Weather",0,0);//At the location (0,0),display word "Weather" + lcd.printString("Station",1,3);//At the location (1,3),display word "Station" + wait(2.0);//The word above stay for 2s + lcd.clear();//Clean the display for the continued work + + Measurement measurement; + + serial.attach(&serialISR);//attach serial ISR + char t[30];//Create a 30 chars row to display the time + while(1) { + + time_t seconds = time(NULL);//get current time + // format time into a string (time and date) + strftime(t, 30 , "%X %D",localtime(&seconds));// + // print over serial + serial.printf("Time = %s\n" ,t);//Display the timer + lcd.printString(t,0,5);//The location of the timer + + if(setTimerFlag) {// if updated time has been sent + setTimerFlag = 0;//clear flag + setTime();// update time + + } + + measurement = bmp180.readValues();// + char T[14];//Create a 14 chars row to display the temperature + int length =sprintf(T,"T = %.2f C",measurement.temperature);//Set up "T = sensor data" as the thing will be shown + if (length <= 14)//Judge the length of chars + lcd.printString(T,0,1);//The location of the T will be shown + char P[14];//Create a 14 chars row to display the pressure + length = sprintf(P,"P = %.2f mb",measurement.pressure);//Set up "P = sensor data" as the thing will be shown + lcd.printString(P,0,3); //The location of the P will be shown + wait(1);//Repeat the circulate each 1s + lcd.clear(); //Clear the data for next processing + } +} + + +void setTime()//// print time for debugging +{ + + serial.printf("set_time - %s",rxString); + //// atoi() converts a string to an integer + int time = atoi(rxString); + //update the time + set_time(time); +} + +void serialISR()// when a serial interrupt occurs, read rx string into buffer +{ + + serial.gets(rxString,16); + //// set flag + setTimerFlag = 1; +}