Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: BLE_API mbed nRF51822
Fork of SenseAirLP8 by
LP8.h
- Committer:
- jony1401
- Date:
- 2017-06-05
- Revision:
- 1:b512a405b584
- Parent:
- 0:ee3787c8e209
- Child:
- 2:d02255d8c36f
File content as of revision 1:b512a405b584:
#ifndef LP8_H
#define LP8_H
/* To initialize the lp8 object, you need to pass a serial (tx, rx), an DigitalOut signal for the en_vbb,
an DigitalIn for the ready signal and a timer object. */
class LP8
{
public:
//constructor
LP8(Serial &device, DigitalOut &vbb_en, DigitalIn &rdy, Timer &_timer):
Device(device),
VBB_EN(vbb_en),
RDY(rdy),
lp8Wait(_timer)
{
Device.baud(9600); //set baud rate to 9600
//initialize arrays with lp8 modbus commands.
//initial startup command:
firstWrite[0] = 0xfe; //device adress
firstWrite[1] = 0x41; //write to ram
firstWrite[2] = 0x00; //
firstWrite[3] = 0x80; //starting adress
firstWrite[4] = 0x01; //nr of bytes to send
firstWrite[5] = 0x10; //calculation control byte
firstWrite[6] = 0x28; //crc low
firstWrite[7] = 0x7e; //crc high
//write previous sensor state to lp8, command:
stateWrite[0] = 0xfe; //device adress
stateWrite[1] = 0x41; //write to ram
stateWrite[2] = 0x00; //
stateWrite[3] = 0x80; //starting adress
stateWrite[4] = 0x18; //nr of bytes to send
stateWrite[5] = 0x20; //Calculation Control
for(int k = 6; k < 31; k++) { stateWrite[k] = 0x00; } //
//read request from the lp8:
stateRead[0] = 0xfe; //adress
stateRead[1] = 0x44; //read from ram
stateRead[2] = 0x00; //
stateRead[3] = 0x80; //starting adress
stateRead[4] = 0x2c; //number of bytes to read
stateRead[5] = 0x00; //crc_l
stateRead[5] = 0x00; //crc_h
//response buffer
for(int k = 0; k < 60; k++) { response[k] = 0x00; }
//variable initialization
co2 = 400; //co2 value
counter = 0; //
CRC = 0x0000; //crc value
_timeMe = 0.350; //wait timer(ms)
};
//LP8 Initialization .
bool lp8Init(){
VBB_EN.write( 1 ); //power on
//wait for rdy signal
timeIt( _timeMe ); //wait for lp8 rdy signal
transmitPacket(firstWrite, 8); //Send out msg (and nr of bytes) over serial line
Response( 4 ); //read 4 bytes response
//compute crc
CRC = modbusCrc(stateRead, 5);
//add crc value to the transmit package
stateRead[5] = (uint8_t)CRC; //crc_l
stateRead[6] = (uint8_t)(CRC >> 8); //crc_h
//wait for rdy
timeIt( _timeMe ); //
transmitPacket(stateRead, 7); //transmit packet
Response( 49 ); //read sensor state and co2 value(s)
VBB_EN.write( 0 ); //power off lp8
//was the talk a success? (simple check...)
if ( getValue() < 1 ) {
return 1; }
else {
return 0; }
};
//send subsequent messages to the lp8
void lp8Talk(uint8_t ccByte){
//transfer previous sensor state to the new msg out
for (int u = 4; u < 23+4; u++) {
stateWrite[u+2] = response[u];
}
//Set Calibration Control Byte (see end of page for explantion)
stateWrite[5] = ccByte;
//compute new crc value
CRC = modbusCrc(stateWrite, 29);
//add new crc value to send list
stateWrite[29] = (uint8_t)CRC;
stateWrite[30] = (uint8_t)(CRC >> 8);
//initialize new transfer sequence
VBB_EN.write( 1 ); //power on sensor
timeIt( _timeMe );
transmitPacket(stateWrite, 31); //Send out msg with previous state (and nr of elements) over serial line
Response( 4 ); //read 4 bytes response
//compute crc
CRC = modbusCrc(stateRead, 5);
//add crc value to the read request transmit package
stateRead[5] = (uint8_t)CRC; //crc_l
stateRead[6] = (uint8_t)(CRC >> 8); //crc_h
timeIt( _timeMe );
//send read request
transmitPacket(stateRead, 7); //transmit packet
//read sensor response
Response( 49 ); //read sensor state and co2 value(s)
VBB_EN.write( 0 ); //power off
};
//get co2 value from lp8 response
unsigned long getValue()
{
int high = response[29];
int low = response[30];
unsigned long val = high * 256 + low;
return val;
}
/************************************************* Helper Functions ********************************************/
/************************************************* ********************************************/
//purge response buffer
void responsePurge(int bytesToPurge){
for (int j = 0; j < bytesToPurge; j++) {
response[j] = 0x00;
}
};
//read from the lp8
void Response(int bytesToRead ){
lp8Wait.start(); //poll rx line for 0.5 seconds
do {
if(Device.readable()) {
response[counter] = Device.getc();
counter++;
}
}
while( lp8Wait.read() < 0.5 );
counter = 0;
lp8Wait.stop();
lp8Wait.reset();
};
//transmit data over serial lines
void transmitPacket(uint8_t msg[], int le ){
//Send out msg over serial line:
while(!Device.writeable() ) { /* wait for serial available*/ }
for(int pos = 0; pos < le; pos++) {
Device.putc(msg[pos]);
}
};
//timer
void timeIt(float &timeMe){
//start amd stop timer...
lp8Wait.start();
while (lp8Wait.read() < timeMe ) { /* W A I T I N G */ }
lp8Wait.stop();
lp8Wait.reset();
};
// Computation for the modbus 16-bit crc
uint16_t modbusCrc(uint8_t buffer[], int len){
uint16_t crc = 0xFFFF;
for (int pos = 0; pos < len; pos++) {
crc ^= (uint16_t)buffer[pos]; // XOR byte into least sig. byte of crc
for (int i = 8; i != 0; i--) { // Loop over each bit
if ((crc & 0x0001) != 0) { // If the LSB is set
crc >>= 1; // shift right and XOR 0xA001
crc ^= 0xA001;
}
else // Else LSB is not set
crc >>= 1; // shift right
}
}
// Note, this number has low and high bytes swapped
return crc;
};
//variables and buffers
private:
Serial &Device;
DigitalOut &VBB_EN;
DigitalIn &RDY;
Timer &lp8Wait;
//msg containers
uint8_t firstWrite[8];
uint8_t stateWrite[31];
uint8_t stateRead[7];
uint8_t response[60];
int co2; //CO2 initial value
int counter; //simple counter
uint16_t CRC; //modbus crc value
float _timeMe; //timer value
};
#endif
/*
LP8 Modbus Communication Protocol (With no external Pressure Sensor):
--------------------------------------------------------------------------------
Initial Measurement (first read after powerup): COMMANDS:
--------------------------------------------------------------------------------
1) host powers up sensor: VBB_EN = 1
2) host waits until rdy signal goes low: RDY = 0;
3) host writes command, "write 24 bytes starting from adress 0x0080": { 0xfe, 0x41, 0x00, 0x80, 0x18, 0x10, ... [any 23 bytes] ..., CRC_low, CRC_high };
4) host reads response: { 0xfe, 0x41, 0x81, 0xe0 };
5) host waits until rdy signal goes high: RDY = 1;
6) host writes command "read 44 bytes starting from adress 0x0080": { 0xfe, 0x44, 0x00, 0x80, 0x2c, CRC_low, CRC_high };
7) host reads response: { 0xfe, 0x44, 0x2c, 0x00, SS1, SS2, ..., SS23, PP_H, PP_L, D1, D2, ..., D18, CRC_low, CRC_high };
8) host powers down sensor: VBB_EN = 0;
[------------------------------------------------------------------------------]
Optional first reading W/O pressure sensor
[------------------------------------------------------------------------------]
1) host powers up sensor: VBB_EN = 1
2) host waits until rdy signal goes low: RDY = 0;
3) host writes command, "write 24 bytes starting from adress 0x0080": { 0xfe, 0x41, 0x00, 0x80, 0x18, 0x10, 0x28, 0x7e };
4) host reads response: { 0xfe, 0x41, 0x81, 0xe0 };
5) host waits until rdy signal goes high: RDY = 1;
6) host writes command "read 44 bytes starting from adress 0x0080": { 0xfe, 0x44, 0x00, 0x80, 0x2c, CRC_low, CRC_high };
7) host reads response: { 0xfe, 0x44, 0x2c, 0x00, SS1, SS2, ..., SS23, PP_H, PP_L, D1, D2, ..., D18, CRC_low, CRC_high };
8) host powers down sensor: VBB_EN = 0;
--------------------------------------------------------------------------------
Subsequent readings:
--------------------------------------------------------------------------------
1) host powers up sensor: VBB_EN = 1
2) host waits until rdy signal goes low: RDY = 0;
3) host writes command, "write 24 bytes starting from adress 0x0080": { 0xfe, 0x41, 0x00, 0x80, 0x18, CC, SS1, ..., SS23, CRC_low, CRC_high };
4) host reads response: { 0xfe, 0x41, 0x81, 0xe0 };
5) host waits until rdy signal goes high: RDY = 1;
6) host writes command "read 44 bytes starting from adress 0x0080": { 0xfe, 0x44, 0x00, 0x80, 0x2c, CRC_low, CRC_high };
7) host reads response: { 0xfe, 0x44, 0x2c, 0x00, SS1, SS2, ..., SS23, PP_H, PP_L, D1, D2, ..., D18, CRC_low, CRC_high };
8) host powers down sensor: VBB_EN = 0;
--------------------------------------------------------------------------------
LP8 Background Calibration, Calculation Control Byte
--------------------------------------------------------------------------------
To calibrate the lp8, commands needs to be sent with the calculation control byte
Calculation:
CC =
0x10 Initial measurement (filters reset, ABC sample reset and other,
0x20 Subsequent measurement,
0x40 Zero calibration using unfiltered data,
0x41 Zero calibration using filtered data,
0x42 Zero calibration using unfiltered data + reset filters,
0x43 Zero calibration using filtered data + reset filters,
0x50 Background calibration using unfiltered data,
0x51 Background calibration using filtered data,
0x52 Background calibration using unfiltered data + reset filters,
0x53 Background calibration using filtered data + reset filters,
0x70 ABC (based on filtered data),
0x72 ABC (based on filtered data) + reset filters
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
CC = Calculation Control, 1 byte
SS = Sensor State, Sensor State, 23 bytes
D = Measured data and Sensor Status, 23 bytes
PP = Host Pressure Value
CRC= 16 bit CRC error check
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
*/
