-
Notifications
You must be signed in to change notification settings - Fork 319
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Plugin for CM1107 CO2 sensor #126
base: master
Are you sure you want to change the base?
Changes from 2 commits
6d55873
19de07c
851fb9e
84414b9
a09571e
f495261
9504d49
49308c7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,235 @@ | ||
//####################################################################################################### | ||
//######################## Plugin 177 CM1107 I2C CO2 Sensor ############################################ | ||
//####################################################################################################### | ||
// development version | ||
// by: V0JT4 | ||
|
||
|
||
#define PLUGIN_177 | ||
#define PLUGIN_ID_177 177 | ||
#define PLUGIN_NAME_177 "Gases - CO2 CM1107" | ||
#define PLUGIN_VALUENAME1_177 "CO2" | ||
|
||
boolean Plugin_177_init = false; | ||
|
||
|
||
#define CM1107_ADDR 0x31 // default address | ||
|
||
#define CM1107_CMD_CO2 0x01 | ||
#define CM1107_CMD_ABC 0x10 | ||
#define CM1107_CMD_CAL 0x03 | ||
#define CM1107_CMD_SN 0x1F | ||
#define CM1107_CMD_VER 0x1E | ||
|
||
#define CM1107_STATUS_INIT 0x01 //0 1 swapped compared to datasheet | ||
#define CM1107_STATUS_OK 0x00 | ||
#define CM1107_STATUS_ERR 0x02 | ||
#define CM1107_STATUS_OUT 0x03 | ||
#define CM1107_STATUS_NCAL 0x05 | ||
|
||
#define CM1107_CAL_ON 0x00 | ||
#define CM1107_CAL_OFF 0x02 | ||
|
||
|
||
|
||
boolean plugin_177_begin() | ||
{ | ||
Wire.begin(); | ||
return(true); | ||
} | ||
|
||
boolean plugin_177_setABC(unsigned char abc) | ||
// Set auto calibration period on CM1107 | ||
// Returns true (1) if successful, false (0) if there was an I2C error | ||
{ | ||
// Write auto calibration configuration | ||
Wire.beginTransmission(CM1107_ADDR); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why not use the functions in the existing I2C.ino file? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I didn't find any function that would cover sensor's requirements, number of bytes to read and write at once. |
||
Wire.write(CM1107_CMD_ABC); | ||
Wire.write(100); // defined by data-sheet | ||
if (abc) | ||
{ | ||
Wire.write(CM1107_CAL_ON); | ||
Wire.write(abc); | ||
} else | ||
{ | ||
Wire.write(CM1107_CAL_OFF); | ||
Wire.write(7); | ||
} | ||
// ? make calibration concentration value configurable | ||
Wire.write((uint8_t)(400 >> 8)); | ||
Wire.write((uint8_t)400); | ||
Wire.write(100); // defined by data-sheet | ||
return (Wire.endTransmission() == 0); | ||
} | ||
|
||
String plugin_177_getABC() | ||
{ | ||
I2C_write8(CM1107_ADDR, CM1107_CMD_ABC); | ||
//delay(500); | ||
uint8_t abc; //replace with function parameter? | ||
uint16_t co2; | ||
uint8_t checksum; | ||
|
||
Wire.requestFrom(CM1107_ADDR, (byte)8); | ||
String log = F("CM1107: ABC: "); | ||
checksum = Wire.read(); // expected CM1107_CMD_ABC | ||
if (checksum != CM1107_CMD_ABC) | ||
{ | ||
log += F("CMD_ERROR "); | ||
} | ||
checksum += Wire.read(); // expected 100 | ||
abc = Wire.read(); // expected 0 or 2 | ||
checksum += abc; | ||
if (abc) | ||
{ //expected read 1-15 | ||
abc = Wire.read(); | ||
checksum += abc; | ||
log += F("OFF, period: "); | ||
log += abc; | ||
abc = 0; | ||
} else | ||
{ | ||
abc = Wire.read(); | ||
checksum += abc; | ||
log += F("ON, period: "); | ||
log += abc; | ||
} | ||
log += F(", ppm: "); | ||
co2 = Wire.read(); // high byte ppm | ||
checksum += co2; | ||
co2 = (co2 << 8) | Wire.read(); // low byte ppm | ||
checksum += (uint8_t)co2; | ||
log += co2; | ||
checksum += Wire.read(); // expected 100 | ||
checksum += Wire.read(); // CS | ||
log += F(", checksum: "); | ||
if (checksum) | ||
{ | ||
log += F("ERR"); | ||
log += checksum; | ||
} else | ||
{ | ||
log += F("OK"); | ||
} | ||
addLog(LOG_LEVEL_INFO,log); | ||
return log; | ||
} | ||
|
||
uint16_t plugin_177_getCO2() | ||
// Retrieve CO2 data in ppm | ||
{ | ||
I2C_write8(CM1107_ADDR, CM1107_CMD_CO2); | ||
uint16_t co2; | ||
uint8_t status; | ||
uint8_t checksum; | ||
|
||
Wire.requestFrom(CM1107_ADDR, (byte)5); | ||
checksum = Wire.read(); // CM1107_CMD_CO2 | ||
co2 = Wire.read(); // high byte ppm | ||
checksum += (uint8_t)co2; | ||
co2 = (co2 << 8) | Wire.read(); // low byte ppm | ||
checksum += (uint8_t)co2; | ||
status = Wire.read(); // status | ||
checksum += status; | ||
checksum += Wire.read(); //CS | ||
|
||
String log = F("CM1107: CO2 ppm:"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please wrap this log creation code in a check for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you please expand how it's done? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. if(logLevelActiveFor(LOG_LEVEL_INFO)) {
String log = F("....");
log += bla;
addLog(LOG_LEVEL_INFO, log);
} It will make less memory allocations if not needed. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks. It's now added to the code but compilers does not like it much. I checked other plugins using it and nothing special to include such function shuldn't be needed. |
||
log += co2; | ||
log += F(", status: "); | ||
log += status; | ||
log += F(", checksum: "); | ||
if (checksum) | ||
{ | ||
log += F("ERR"); | ||
log += checksum; | ||
} else | ||
{ | ||
log += F("OK"); | ||
} | ||
addLog(LOG_LEVEL_INFO,log); | ||
return co2; | ||
} | ||
|
||
|
||
boolean Plugin_177(byte function, struct EventStruct *event, String& string) | ||
{ | ||
boolean success = false; | ||
|
||
switch (function) | ||
{ | ||
case PLUGIN_DEVICE_ADD: | ||
{ | ||
Device[++deviceCount].Number = PLUGIN_ID_177; | ||
Device[deviceCount].Type = DEVICE_TYPE_I2C; | ||
Device[deviceCount].VType = SENSOR_TYPE_SINGLE; | ||
Device[deviceCount].Ports = 0; | ||
Device[deviceCount].PullUpOption = false; | ||
Device[deviceCount].InverseLogicOption = false; | ||
Device[deviceCount].FormulaOption = true; | ||
Device[deviceCount].ValueCount = 1; | ||
Device[deviceCount].SendDataOption = true; | ||
Device[deviceCount].TimerOption = true; | ||
Device[deviceCount].GlobalSyncOption = true; | ||
break; | ||
} | ||
|
||
case PLUGIN_GET_DEVICENAME: | ||
{ | ||
string = F(PLUGIN_NAME_177); | ||
break; | ||
} | ||
|
||
case PLUGIN_GET_DEVICEVALUENAMES: | ||
{ | ||
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_177)); | ||
break; | ||
} | ||
|
||
case PLUGIN_WEBFORM_LOAD: | ||
{ | ||
addFormNumericBox(F("ABC period"), F("plugin_177_CM1107_abc"), Settings.TaskDevicePluginConfig[event->TaskIndex][0]); | ||
addUnit(F("days, 0=off")); | ||
success = true; | ||
break; | ||
} | ||
|
||
case PLUGIN_WEBFORM_SAVE: | ||
{ | ||
unsigned char abc = getFormItemInt(F("plugin_177_CM1107_abc")); | ||
if (abc > 15) abc = 15; | ||
Settings.TaskDevicePluginConfig[event->TaskIndex][0] = abc; | ||
success = true; | ||
break; | ||
} | ||
case PLUGIN_INIT: | ||
{ | ||
plugin_177_begin(); | ||
success = plugin_177_setABC((uint8_t) Settings.TaskDevicePluginConfig[event->TaskIndex][0]); | ||
I2C_write8(CM1107_ADDR, CM1107_CMD_CO2); | ||
break; | ||
} | ||
case PLUGIN_READ: | ||
{ | ||
plugin_177_begin(); | ||
co2 = plugin_177_getCO2(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Where is this variable There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed, missed declaration. Code worked because of same name global variable from my different plugin. |
||
UserVar[event->BaseVarIndex] = co2; | ||
if (co2 > 5000) | ||
{ | ||
addLog(LOG_LEVEL_INFO,F("CM1107: Sensor saturated! > 5000 ppm")); | ||
} | ||
success = true; | ||
break; | ||
} | ||
case PLUGIN_WRITE: | ||
{ | ||
if (string.equalsIgnoreCase(F("CMGETABC"))) | ||
{ | ||
success = true; | ||
SendStatus(event->Source, plugin_177_getABC()); | ||
I2C_write8(CM1107_ADDR, CM1107_CMD_CO2); | ||
} | ||
break; | ||
} | ||
} | ||
return success; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do not let a plugin call
Wire.begin()
It is already being dealt with in ESPeasy and this may disrupt other I2C communications of other plugins
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed