/* * Author: Henry Bruce * Copyright (c) 2015 Intel Corporation. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include #include #include #include #include "t6713.hpp" #define T6713_ADDR 0x15 /* REGISTER ADDRESSES */ #define T6713_REG_FIRMWARE_REVISION 0x1389 #define T6713_REG_STATUS 0x138A #define T6713_REG_GAS_PPM 0x138B #define T6713_REG_RESET_DEVICE 0x03E8 #define T6713_REG_START_SINGLE_POINT_CAL 0x03EC #define T6713_REG_CHANGE_SLAVE_ADDRESS 0x0FA5 #define T6713_REG_ABC_LOGIC_ENABLE_DISABLE 0x03EE using namespace upm; using namespace upm::t6713_co2; T6713::T6713 (int bus) : i2c(bus) { status = i2c.address(T6713_ADDR); uint16_t firmwareRevision = getFirmwareRevision(); if (firmwareRevision != mraa::SUCCESS) UPM_THROW("config failure"); } uint16_t T6713::getFirmwareRevision() { return(getSensorData(T6713_COMMAND_GET_FIRMWARE_REVISION)); } uint16_t T6713::getPpm () { return(getSensorData(T6713_COMMAND_GET_GAS_PPM)); } uint16_t T6713::getSensorData (MODBUS_COMMANDS cmd) { uint16_t data ,readBytes ; STATUS currStatus ; switch(currStatus = getStatus()) /* handle error conditions */ { case ERROR_CONDITION: UPM_THROW ("error condition"); break; case FLASH_ERROR: UPM_THROW ("flash error"); break; case CALIBRATION_ERROR: UPM_THROW ("calibration error"); break; case WARMUP_MODE: //UPM_THROW ("warmup mode"); break; case RS232: //printf("\nRS232 mode set\n "); break; case RS485: //printf("\nRS485 mode set\n "); break; case I2C: { //printf("\nI2C mode set\n"); data = 0; runCommand(cmd); RESPONSE response; if((readBytes = i2c.read((uint8_t*)(&response), sizeof(RESPONSE) ) != sizeof(RESPONSE))) { UPM_THROW("I2C read failed"); // TODO } if(response.function_code == READ_INPUT_REGISTERS) { if(response.byte_count == 2) { data = (response.status_msb << 8 | response.status_lsb); } } return(data); break; } default: syslog(LOG_WARNING, "%s: switch case not defined", std::string(__FUNCTION__).c_str()); } return 0; } mraa::Result T6713::runCommand(MODBUS_COMMANDS cmd) { COMMAND cmdPacket; mraa::Result ret = mraa::SUCCESS; switch(cmd) { case T6713_COMMAND_RESET: cmdPacket.function_code = WRITE_SINGLE_COIL; cmdPacket.register_address_msb = (T6713_REG_RESET_DEVICE >> 8); cmdPacket.register_address_lsb = (T6713_REG_RESET_DEVICE & 0xff); cmdPacket.input_registers_to_read_msb = 0xff; cmdPacket.input_registers_to_read_lsb = 0x00; ret = i2c.write((const uint8_t*) (&cmdPacket), sizeof(COMMAND)); /*no response from the slave */ break; case T6713_COMMAND_STATUS: /*created the modbus status command packet*/ cmdPacket.function_code = READ_INPUT_REGISTERS; cmdPacket.register_address_msb = (T6713_REG_STATUS >> 8); cmdPacket.register_address_lsb = (T6713_REG_STATUS & 0xff); cmdPacket.input_registers_to_read_msb = 0; cmdPacket.input_registers_to_read_lsb = 1; if((ret = i2c.write((const uint8_t*) (&cmdPacket), sizeof(COMMAND))) != mraa::SUCCESS) { UPM_THROW("I2C write failed"); } break; case T6713_COMMAND_GET_FIRMWARE_REVISION: cmdPacket.function_code = READ_INPUT_REGISTERS; cmdPacket.register_address_msb = (T6713_REG_FIRMWARE_REVISION >> 8); cmdPacket.register_address_lsb = (T6713_REG_FIRMWARE_REVISION & 0xff); cmdPacket.input_registers_to_read_msb = 0; cmdPacket.input_registers_to_read_lsb = 1; ret = i2c.write((const uint8_t*) (&cmdPacket), sizeof(COMMAND)); break; case T6713_COMMAND_GET_GAS_PPM: cmdPacket.function_code = READ_INPUT_REGISTERS; cmdPacket.register_address_msb = (T6713_REG_GAS_PPM >> 8); cmdPacket.register_address_lsb = (T6713_REG_GAS_PPM & 0xff); cmdPacket.input_registers_to_read_msb = 0; cmdPacket.input_registers_to_read_lsb = 1; if((ret = i2c.write((const uint8_t*) (&cmdPacket), sizeof(COMMAND))) != mraa::SUCCESS) { UPM_THROW("I2C write failed"); } break; } return ret; } STATUS T6713::getStatus() { uint16_t responseStatus = 0, readBytes = 0; RESPONSE response; runCommand(T6713_COMMAND_STATUS); if((readBytes = i2c.read((uint8_t*) (&response), sizeof(RESPONSE)) != sizeof(RESPONSE))) { UPM_THROW("I2C read failed"); } if(response.function_code == READ_INPUT_REGISTERS) { if(response.byte_count == 2) { responseStatus = (response.status_msb << 8 | response.status_lsb); } else { UPM_THROW("I2C read failed"); } } else { UPM_THROW("MODBUS function code failed"); } if(responseStatus & 0x0001) { return ERROR_CONDITION; } if(responseStatus & 0x0002) { return FLASH_ERROR; } if(responseStatus & 0x0004) { return CALIBRATION_ERROR; } if(responseStatus & 0x0800) { return WARMUP_MODE; } if(responseStatus & 0x8000) { return SINGLE_POINT_CALIBRATION; } if(responseStatus & 0x0100) { return RS232; } if(responseStatus & 0x0400) { return RS485; } else { return I2C; } }