diff --git a/src/Command.cpp b/src/Command.cpp index 57ad675..52a88ea 100644 --- a/src/Command.cpp +++ b/src/Command.cpp @@ -130,6 +130,11 @@ CommandCodeEnum Command::getGCodeEnum(char *code) return F44; } + if (strcmp(code, "F52") == 0) + { + return F52; + } + if (strcmp(code, "F61") == 0) { return F61; diff --git a/src/Command.h b/src/Command.h index b889c32..bc6d10c 100644 --- a/src/Command.h +++ b/src/Command.h @@ -29,6 +29,7 @@ enum CommandCodeEnum F42 = 142, F43 = 143, F44 = 144, + F52 = 152, F61 = 161, F81 = 181, F82 = 182, diff --git a/src/F52Handler.cpp b/src/F52Handler.cpp new file mode 100644 index 0000000..9db9ad7 --- /dev/null +++ b/src/F52Handler.cpp @@ -0,0 +1,89 @@ +/* + * F52Handler.cpp + * + * Created on: 1 august 2024 + * Author: Finn Roters + */ + +#include "F52Handler.h" +#include "icp101xx.h" + +ICP101xx tempSensor; + +static F52Handler *instance; // defines a static pointer to an "F52Handler" instance (ensures that there is only one instance of the class). + + +// Check whether instance points to nullptr (i.e. no valid memory area) (if yes, a new instance of F52Handler is created). +F52Handler *F52Handler::getInstance() +{ + if (!instance) + { + instance = new F52Handler(); + }; + return instance; +}; + +// Constructor of the F52Handler class (empty, because no special initialisations are necessary). +F52Handler::F52Handler() +{ +} + + +int F52Handler::execute(Command *command) +{ + Serial.println("F52 command has started"); + // variable to keep initial pressure as reference point + // float reference_pressure = 0.0; + Serial.print("command->getP(): "); + Serial.println(command->getP()); + // Initialize the sensor. + tempSensor.begin(); + // tempSensor.begin(&Wire1); + delay(2000); + // Connect the sensor and read the calibration data. + if (!tempSensor.begin()) { + Serial.println("The sensor did not respond! #1"); + delay(200); + } else { + Serial.println("The sensor did respond! #1"); + } + while(!tempSensor.isConnected()) { + Serial.println("Sensor is not responding! #2"); + delay(250); + } + // Check if sensor is responding. + if (!tempSensor.isConnected()) { + Serial.println("Sensor is not responding! #3"); + } else { + // Start measurement cycle, waiting until it is completed. + // Optional: Measurement mode + // sensor.FAST: ~3ms + // sensor.NORMAL: ~7ms (default) + // sensor.ACCURATE: ~24ms + // sensor.VERY_ACCURATE: ~95ms + tempSensor.measure(tempSensor.VERY_ACCURATE); + while (!tempSensor.dataReady()) { + Serial.println("The sensor is not ready yet."); + delay(50); + } + // the sensor is done, process the data + // Read and output measured temperature in Celsius and pressure in Pascal. + if (command->getP() == 1) { + Serial.print("Temperature: "); + Serial.print(tempSensor.getTemperatureC()); + Serial.print(" °C, "); + } else if (command->getP() == 2) { + Serial.print(tempSensor.getTemperatureF()); + Serial.println(" °F, "); + Serial.print("Pressure: "); + } else if (command->getP() == 3) { + Serial.println(tempSensor.getPressurePa()); + Serial.print(" Pa, "); + Serial.print(tempSensor.getPressurePa()/100); + Serial.println(" mbar"); + } + } + + Serial.println("F52 command is done"); + return 0; +} \ No newline at end of file diff --git a/src/F52Handler.h b/src/F52Handler.h new file mode 100644 index 0000000..4ff3a5c --- /dev/null +++ b/src/F52Handler.h @@ -0,0 +1,29 @@ +/* + * F52Handler.h + * + * Created on: 31 july 2024 + * Author: Finn Roters + */ + +#ifndef F52HANDLER_H_ +#define F52HANDLER_H_ +#include "GCodeHandler.h" +#include "Config.h" +#include "CurrentState.h" +#include "pins.h" +#include "PinControl.h" + +class F52Handler : public GCodeHandler // Class F52Handler is defined, which inherits from GCodeHandler. +{ +public: // can be called from outside. + static F52Handler *getInstance(); // static method that returns an instance of the "F52Handler" class. + int execute(Command *); // method is used to execute the G- and F-code. + +private: // only accessible within the "F22Handler" class + F52Handler(); // private constructor of the class (prevents objects of the class from being created directly). + F52Handler(F52Handler const &); // private copy constructor (This prevents the class from being copied). + void operator=(F52Handler const &); // private assignment operator (This prevents objects from being assigned to the class). +}; + +#endif /* F52HANDLER_H_ */ + diff --git a/src/GCodeProcessor.cpp b/src/GCodeProcessor.cpp index 876b727..5e92381 100644 --- a/src/GCodeProcessor.cpp +++ b/src/GCodeProcessor.cpp @@ -296,6 +296,11 @@ GCodeHandler *GCodeProcessor::getGCodeHandler(CommandCodeEnum codeEnum) handler = F44Handler::getInstance(); } + if (codeEnum == F52) + { + handler = F52Handler::getInstance(); + } + if (codeEnum == F61) { handler = F61Handler::getInstance(); diff --git a/src/GCodeProcessor.h b/src/GCodeProcessor.h index d8272a5..4b4807e 100644 --- a/src/GCodeProcessor.h +++ b/src/GCodeProcessor.h @@ -39,6 +39,8 @@ #include "F43Handler.h" #include "F44Handler.h" +#include "F52Handler.h" + #include "F61Handler.h" #include "F81Handler.h" diff --git a/src/icp101xx.cpp b/src/icp101xx.cpp new file mode 100644 index 0000000..f52014c --- /dev/null +++ b/src/icp101xx.cpp @@ -0,0 +1,200 @@ +/****************************************************************** + Library for the TDK InvenSense ICP-101xx series of barometric + pressure sensors. These sensors communicate over I2C. + + Tested with ICP-10100, but likely to also work with ICP-10101, + ICP-10110 and ICP-10111. + + Written by Adrian Studer. + + BSD license, check license.txt for more information. + All text above must be included in any redistribution. +******************************************************************/ + +#include +#include +#include "icp101xx.h" + +#define ICP_I2C_ID 0x63 + +#define ICP_CMD_READ_ID 0xefc8 +#define ICP_CMD_SET_ADDR 0xc595 +#define ICP_CMD_READ_OTP 0xc7f7 +#define ICP_CMD_MEAS_LP 0x609c +#define ICP_CMD_MEAS_N 0x6825 +#define ICP_CMD_MEAS_LN 0x70df +#define ICP_CMD_MEAS_ULN 0x7866 + +// constants for presure calculation +const float _pcal[3] = { 45000.0, 80000.0, 105000.0 }; +const float _lut_lower = 3.5 * 0x100000; // 1<<20 +const float _lut_upper = 11.5 * 0x100000; // 1<<20 +const float _quadr_factor = 1 / 16777216.0; +const float _offst_factor = 2048.0; + +ICP101xx::ICP101xx() { + _i2c = NULL; + _pressure_Pa = 0.0; + _temperature_C = 0.0; + _meas_duration = 100; + _meas_start = millis(); + _data_ready = false; +} + +bool ICP101xx::begin(TwoWire* wire) { + // setup I2C object + if (wire) { + _i2c = wire; + } else { + _i2c = &Wire; + } + _i2c->begin(); + + // verify that the sensor is repsonding + if (!isConnected()) { + return false; + } + + // read sensor calibration data + uint8_t addr_otp_cmd[5] = { + (ICP_CMD_SET_ADDR >> 8) & 0xff, + ICP_CMD_SET_ADDR & 0xff, + 0x00, 0x66, 0x9c }; + uint8_t otp_buf[3]; + _sendCommand(addr_otp_cmd, 5); + for (int i=0; i<4; i++) { + _sendCommand(ICP_CMD_READ_OTP); + _readResponse(otp_buf, 3); + _scal[i] = (otp_buf[0] << 8) | otp_buf[1]; + } + return true; +} + +bool ICP101xx::isConnected(void) { + uint8_t id_buf[2]; + _sendCommand(ICP_CMD_READ_ID); + _readResponse(id_buf, 2); + uint16_t id = (id_buf[0] << 8) | id_buf[1]; + if ((id & 0x03f) == 0x08) { + return true; + } else { + return false; + } +} + +void ICP101xx::measure(ICP101xx::mmode mode) { + delay(measureStart(mode)); + while (!dataReady()); +} + +uint8_t ICP101xx::measureStart(ICP101xx::mmode mode) { + uint16_t cmd; + switch (mode) { + case ICP101xx::FAST: + cmd = ICP_CMD_MEAS_LP; + _meas_duration = 3; + break; + case ICP101xx::ACCURATE: + cmd = ICP_CMD_MEAS_LN; + _meas_duration = 24; + break; + case ICP101xx::VERY_ACCURATE: + cmd = ICP_CMD_MEAS_ULN; + _meas_duration = 95; + break; + case ICP101xx::NORMAL: + default: + cmd = ICP_CMD_MEAS_N; + _meas_duration = 7; + break; + } + _sendCommand(cmd); + _data_ready = false; + _meas_start = millis(); + return _meas_duration; +} + +bool ICP101xx::dataReady(void) { + if (_data_ready) + return true; + + if (millis() - _meas_start < _meas_duration) + return false; + + uint8_t res_buf[9]; + _readResponse(res_buf, 9); + _raw_t = (res_buf[0] << 8) | res_buf[1]; + uint32_t L_res_buf3 = res_buf[3]; // expand result bytes to 32bit to fix issues on 8-bit MCUs + uint32_t L_res_buf4 = res_buf[4]; + uint32_t L_res_buf6 = res_buf[6]; + _raw_p = (L_res_buf3 << 16) | (L_res_buf4 << 8) | L_res_buf6; + _calculate(); + + _data_ready = true; + + return true; +} + +float ICP101xx::getTemperatureC(void) { + return _temperature_C; +} + +float ICP101xx::getTemperatureF(void) { + return _temperature_C * 1.8 + 32; +} + +float ICP101xx::getPressurePa(void) { + return _pressure_Pa; +} + +void ICP101xx::_calculate(void) { + // calculate temperature + _temperature_C = -45.f + 175.f / 65536.f * _raw_t; + + // calculate pressure + float t = (float)(_raw_t - 32768); + float s1 = _lut_lower + (float)(_scal[0] * t * t) * _quadr_factor; + float s2 = _offst_factor * _scal[3] + (float)(_scal[1] * t * t) * _quadr_factor; + float s3 = _lut_upper + (float)(_scal[2] * t * t) * _quadr_factor; + float c = (s1 * s2 * (_pcal[0] - _pcal[1]) + + s2 * s3 * (_pcal[1] - _pcal[2]) + + s3 * s1 * (_pcal[2] - _pcal[0])) / + (s3 * (_pcal[0] - _pcal[1]) + + s1 * (_pcal[1] - _pcal[2]) + + s2 * (_pcal[2] - _pcal[0])); + float a = (_pcal[0] * s1 - _pcal[1] * s2 - (_pcal[1] - _pcal[0]) * c) / (s1 - s2); + float b = (_pcal[0] - a) * (s1 + c); + _pressure_Pa = a + b / (c + _raw_p); +} + +void ICP101xx::_sendCommand(uint16_t cmd) { + if (!_i2c) return; + + _i2c->beginTransmission(ICP_I2C_ID); + _i2c->write((cmd >> 8) & 0xff); + _i2c->write(cmd & 0xff); + _i2c->endTransmission(); +} + +void ICP101xx::_sendCommand(uint8_t *cmd_buf, uint8_t cmd_len) { + if (!_i2c) return; + + if (cmd_buf && cmd_len) { + _i2c->beginTransmission(ICP_I2C_ID); + for (int i=0; iwrite(cmd_buf[i]); + } + _i2c->endTransmission(); + } +} + +void ICP101xx::_readResponse(uint8_t *res_buf, uint8_t res_len) { + if (!_i2c) return; + + if (res_buf && res_len) { + _i2c->requestFrom(ICP_I2C_ID, res_len); + for (int i=0; iread(); + } + } +} \ No newline at end of file diff --git a/src/icp101xx.h b/src/icp101xx.h new file mode 100644 index 0000000..c14c4cb --- /dev/null +++ b/src/icp101xx.h @@ -0,0 +1,52 @@ +/****************************************************************** + Library for the TDK InvenSense ICP-101xx series of barometric + pressure sensors. These sensors communicate over I2C. + + Tested with ICP-10100, but likely to also work with ICP-10101, + ICP-10110 and ICP-10111. + + Written by Adrian Studer. + + BSD license, check license.txt for more information. + All text above must be included in any redistribution. + ******************************************************************/ + +#ifndef _icp101xx +#define _icp101xx + +#include +#include + +class ICP101xx +{ + public: + enum mmode { FAST, NORMAL, ACCURATE, VERY_ACCURATE }; + + ICP101xx(); + bool begin(TwoWire* wire = NULL); + bool isConnected(void); + void measure(ICP101xx::mmode mode = ICP101xx::NORMAL); + uint8_t measureStart(ICP101xx::mmode mode = ICP101xx::NORMAL); + bool dataReady(); + float getTemperatureC(void); + float getTemperatureF(void); + float getPressurePa(void); + + private: + void _calculate(void); + void _sendCommand(uint16_t cmd); + void _sendCommand(uint8_t *cmd_buf, uint8_t cmd_len); + void _readResponse(uint8_t *res_buf = NULL, uint8_t res_len = 0); + + TwoWire* _i2c; + float _scal[4]; + uint16_t _raw_t; + uint32_t _raw_p; + float _temperature_C; + float _pressure_Pa; + unsigned long _meas_start; + uint8_t _meas_duration; + bool _data_ready; +}; + +#endif \ No newline at end of file diff --git a/src/src.ino b/src/src.ino index 2a7bbff..c85953a 100644 --- a/src/src.ino +++ b/src/src.ino @@ -14,7 +14,8 @@ // the setup function runs once when you press reset or power the board void setup() { - startSerial(); + // startSerial(); + Serial.begin(9600); setPinInputOutput(); readParameters();