Power monitor для встраиваемых систем (Linux)

p5xzmjwiw6wqtpqnpmv_phzax_i.png
// синглтон для записи логов
static logger& loggerInstance = logger::Instance();

I2cPoll::I2cPoll() {
// создаем класс БД
        db = new DbConnection();
        if(db->isConnecting()) {
                loggerInstance.appendToLog("I2cPoll: db-connected-OK\r\n");
        } else {
                loggerInstance.appendToLog("I2cPoll: db opening -ERROR\r\n");
        }
// структура позволят опрашивать больше одного устройства
// указываем с которого начинать опрос
        this->currentDeviceType = startDeviceType;
}

// функция опроса
void I2cPoll::pollExect() {
        uint8_t *p_data = NULL;
        uint16_t word = 0;
        bool res = false;
        char cmd_command[128] = {0};
        S_insertData device_data;
        int device_addr = 0;

        // формируем запрос
        switch(currentDeviceType) {

        case dev_i2c_ina260: {
                // извлекаем из БД id устройства
                device_addr = db->getDeviceAddrFromName(
                                             i2c_Dev_typeName.ina260.name_text.c_str()
                                       );
               // если извлекли правильно
                if(device_addr != 0) {
                        // интересует 3 параметра - ток, напряжение и мощность
                        for(int i=0; i<3; i++) {
                                switch(i) {
                                // curent
                                case 0:
                                        sprintf(cmd_command, "i2cget -y 0 0x%X 0x01 w\r\n", device_addr);
                                        // отправляем в консоль
                                        res = readWord(cmd_command, &word);
                                        if(res) {  // проверяем ответ
                                                p_data = (uint8_t*)&word;
                                                float raw_data;
                                                fprintf(stdout, "Raw u16 %x\r\n", word);
                                                // преобразование по описанию из даташита
                                                raw_data = (0xFF & p_data[1]) | ((0xFF & (p_data[0])) << 8);
                                                device_data.parameter.power_monitor.currnetFlowing = 
                                                     raw_data * 1.25 / 1000;
                                                fprintf(stdout, "Current %4.2f\r\n", 
                                                     device_data.parameter.power_monitor.currnetFlowing
                                                );
                                        }
                                        break;
                                        // voltage
                                case 1:
                                        sprintf(cmd_command, "i2cget -y 0 0x%X 0x02 w", device_addr);
                                        // отправляем в консоль
                                        res = readWord(cmd_command, &word);
                                        if(res) {  // проверяем ответ
                                                p_data = (uint8_t*)&word;
                                                float raw_data;
                                                fprintf(stdout, "Raw u16 %x\r\n", word);
                                                // преобразование по описанию из даташита
                                                raw_data = (0xFF & p_data[1]) | ((0xFF & (p_data[0])) << 8);
                                                device_data.parameter.power_monitor.voltage = 
                                                      raw_data * 1.25 / 1000;
                                                fprintf(stdout, "Volage %4.2f\r\n", 
                                                     device_data.parameter.power_monitor.voltage
                                                );
                                        }
                                        break;

                                case 2:
                                        //  power
                                        sprintf(cmd_command, "i2cget -y 0 0x%X 0x03 w\r\n", device_addr);
                                        // отправляем в консоль
                                        res = readWord(cmd_command, &word);
                                        if(res) {  // проверяем ответ
                                                p_data = (uint8_t*)&word;
                                                float raw_data;
                                                fprintf(stdout, "Raw u16 %x\r\n", word);
                                                // преобразование по описанию из даташита
                                                raw_data = (0xFF & p_data[1]) | ((0xFF & (p_data[0])) << 8);
                                                device_data.parameter.power_monitor.currentPower = 
                                                      raw_data * 1.25;
                                                fprintf(stdout, "Power %4.2f\r\n", 
                                                    device_data.parameter.power_monitor.currentPower
                                                );
                                        }
                                        break;
                                }
                        }
                        // если все опросили, отправляем данные в БД
                        if(res) {
                                db->insertData(device_data);
                        }
                }
        }
        break;

        default : // если что-то не так, начинаем с первого устройства
                currentDeviceType = startDeviceType;
                break;

        }
        // после конца цикла, начинаем с первого устройства
        if(currentDeviceType >= (E_I2c_device)endTypeDeviceType) {
                currentDeviceType = startDeviceType;
                fprintf(stdout, "I2c parce -endDev\r\n");
        } else { // иначе опрашиваем следующий
                currentDeviceType++;
                fprintf(stdout, "I2c parce -nextDev\r\n");
        }
}

// формируем запрос на шину i2c
// парсим данные в ответе
bool I2cPoll::readWord(char *cmd_command, uint16_t *p_word) {
        int res = false;
        int word = 0;
        FILE *stream;
        // отправляем в консоль
        stream = popen(cmd_command, "r");
        fprintf(stdout, "cmd_command - %s\r\n", cmd_command);

        std::string data;
        if (stream) {
                char reply_buff[128] = {0};
                while (!feof(stream))
                        if(fgets(reply_buff, sizeof(reply_buff), stream) != NULL) {
                                data.append(reply_buff);
                        }
                pclose(stream);
        }

        // проверяем ответ
        fprintf(stdout, "shell result :\r\n%s\r\n", data.c_str());
        if(data.length() != 0) {
                char *p_start = strstr((char*)data.c_str(), "0x");
                if(p_start != NULL) {
                        res = sscanf(p_start, "%x", &word);
                        if(res) {
                                *p_word = (uint16_t)word;
                        }
                        fprintf(stdout, "getWord %x\r\n", *p_word);
                }
        }
        return res;
}

I2cPoll::~I2cPoll() {
        // TODO Auto-generated destructor stub
}


© Habrahabr.ru