Bosch Sensortec Community

    cancel
    Showing results for 
    Search instead for 
    Did you mean: 
    SOLVED

    BSEC BME680 no IAQ output

    BSEC BME680 no IAQ output

    MJ_kio
    Member

    I have an issue with bsec light version 1.4.8.0. Everything seems to work, however I receive only 5 outputs and no IAQ output, even though I requested it. I base strongly on example from BSEC_1.4.8.0_Generic_Release_updated_v3
    I use BME680 sensor, which is configured in low power mode.

    I update structure and init sensor:

     

     

     

     

     

        gas_sensor.dev_id = BME680_I2C_ADDR_SECONDARY;
        gas_sensor.intf = BME680_I2C_INTF;
        gas_sensor.read = user_i2c_read;
        gas_sensor.write = user_i2c_write;
        gas_sensor.delay_ms = delay;
        /* amb_temp can be set to 25 prior to configuring the gas sensor
         * or by performing a few temperature readings without operating the gas sensor.
         */
        gas_sensor.amb_temp = 25;
    
       bsec_library_return_t status = BSEC_OK;
    
        auto result = bme680_init(&gas_sensor);
        KD_ERROR_IF(result != 0, KD_BME680_BSEC, "Error initializing: %d", result);
        status = bsec_init();
        KD_ERROR_IF(status != BSEC_OK, KD_BME680_BSEC, "Error initializing bsec: %d", status);
    
        bsec_version_t bsec_ver;
        status = bsec_get_version(&bsec_ver);
        KD_INFO(KD_BME680_BSEC, "BSEC bsec_get_version res: %d", (int)status);
        KD_INFO(KD_BME680_BSEC, "BSEC version %d.%d.%d.%d", bsec_ver.major, bsec_ver.minor, bsec_ver.major_bugfix,
                bsec_ver.minor_bugfix);
    
        status = bme680_bsec_update_subscription(BSEC_SAMPLE_RATE_LP);
        KD_ERROR_IF(status != BSEC_OK, KD_BME680_BSEC, "Error initializing bsec sensors init: %d", status);

     

     

     

     

     

    Then I call every specified time definded by next_call ( mostly 2920 ms) function:

     

     

     

     

     

       KD_DEBUG(KD_BME680_BSEC, "fetchData");
        bsec_library_return_t status = BSEC_OK;
        int8_t result = BME680_OK;
    
        /* time stamp */
        int64_t time_stamp = (int64_t)(m_clock->getMillisecondsSinceBoot()) * INT64_C(1000) * INT64_C(1000);  // nanoseconds;
        int64_t time_stamp_interval_ms = 0;
    
        /* BSEC sensor settings struct */
        bsec_bme_settings_t sensor_settings;
    
        /* Allocate enough memory for up to BSEC_MAX_PHYSICAL_SENSOR physical inputs*/
        bsec_input_t bsec_inputs[BSEC_MAX_PHYSICAL_SENSOR];
    
        /* Number of inputs to BSEC */
        uint8_t num_bsec_inputs = 0;
    
        // tmp
        KD_DEBUG_DUMP_MEMORY(KD_BME680_BSEC, "Timestamp nano       ", tmp, sizeof(tmp));
        // tmp
    
        /* Retrieve sensor settings to be used in this time instant by calling bsec_sensor_control */
        status = bsec_sensor_control(time_stamp, &sensor_settings);
        KD_ERROR_IF(status != BSEC_OK, KD_BME680_BSEC, "Error initializing bsec_sensor_control: %d", status);
    
        /* Trigger a measurement if necessary */
        result = bme680_bsec_trigger_measurement(&sensor_settings, delay);
        KD_ERROR_IF(result != BME680_OK, KD_BME680_BSEC, "Error initializing bme680_bsec_trigger_measurement: %d", result);
    
        /* Read data from last measurement */
        result = bme680_bsec_read_data(time_stamp, bsec_inputs, &num_bsec_inputs, sensor_settings.process_data);
        KD_ERROR_IF(result != BME680_OK, KD_BME680_BSEC, "Error initializing bme680_bsec_read_data: %d", result);
    
        KD_DEBUG(KD_BME680_BSEC, "num_bsec_inputs %d", num_bsec_inputs);
        /* Time to invoke BSEC to perform the actual processing */
        status = bme680_bsec_process_data(bsec_inputs, num_bsec_inputs, output_ready);
        KD_ERROR_IF(status != BSEC_OK, KD_BME680_BSEC, "Error initializing bme680_bsec_process_data: %d", status);
    
        time_stamp_interval_ms =
            (sensor_settings.next_call - (m_clock->getMillisecondsSinceBoot() * (int64_t)1000 * (int64_t)1000)) /
            (int64_t)1000000;
        KD_DEBUG(KD_BME680_BSEC, "Wakeup in %u ms", (uint32_t)time_stamp_interval_ms);

     

     

     

     

     

    following support functioins are used:

     

     

     

     

     

    static void output_ready(int64_t timestamp, float iaq, uint8_t iaq_accuracy, float temperature, float humidity,
                             float pressure, float raw_temperature, float raw_humidity, float gas,
                             bsec_library_return_t bsec_status, float static_iaq, uint8_t static_iaq_accuracy,
                             float co2_equivalent, uint8_t co2_accuracy, float breath_voc_equivalent,
                             uint8_t breath_voc_accuracy, float gas_percentage, uint8_t gas_percentage_acccuracy,
                             float comp_gas, uint8_t comp_gas_accuracy) {
        KD_DEBUG(KD_BME680_BSEC, "Bsec status: %d", bsec_status);
        KD_DEBUG(KD_BME680_BSEC, "Timestamp: %ld", timestamp / 1e6);
        KD_DEBUG(KD_BME680_BSEC, "Temperature: %d", (int)temperature);
        KD_DEBUG(KD_BME680_BSEC, "Temperature raw: %d", (int)raw_temperature);
        KD_DEBUG(KD_BME680_BSEC, "Pressure: %d", (int)pressure);
        KD_DEBUG(KD_BME680_BSEC, "Humidity: %d", (int)humidity);
        KD_DEBUG(KD_BME680_BSEC, "Humidity raw: %d", (int)raw_humidity);
        KD_DEBUG(KD_BME680_BSEC, "IAQ: %d", (int)iaq);
        KD_DEBUG(KD_BME680_BSEC, "IAQ accurway: %d", iaq_accuracy);
        KD_DEBUG(KD_BME680_BSEC, "IAQ static: %d", (int)static_iaq);
        KD_DEBUG(KD_BME680_BSEC, "IAQ static accurtacy: %d", static_iaq_accuracy);
        KD_DEBUG(KD_BME680_BSEC, "CO2 equivalent: %d", (int)co2_equivalent);
        KD_DEBUG(KD_BME680_BSEC, "CO2 equivalent accuracy: %d", co2_accuracy);
        KD_DEBUG(KD_BME680_BSEC, "VOC: %d", (int)breath_voc_equivalent);
        KD_DEBUG(KD_BME680_BSEC, "VOC accuracy: %d", breath_voc_accuracy);
        KD_DEBUG(KD_BME680_BSEC, "gas: %d", (int)gas);
        KD_DEBUG(KD_BME680_BSEC, "gas_percentage: %d", (int)gas_percentage);
        KD_DEBUG(KD_BME680_BSEC, "gas_percentage_acccuracy: %d", gas_percentage_acccuracy);
        KD_DEBUG(KD_BME680_BSEC, "comp_gas: %d", (int)comp_gas);
        KD_DEBUG(KD_BME680_BSEC, "comp_gas_accuracy: %d", comp_gas_accuracy);
    }
    
    
    bsec_library_return_t Bme680bsec::bme680_bsec_update_subscription(float sample_rate) {
        (void)sample_rate;
        bsec_sensor_configuration_t requested_virtual_sensors[NUM_USED_OUTPUTS];
        uint8_t n_requested_virtual_sensors = NUM_USED_OUTPUTS;
    
        bsec_sensor_configuration_t required_sensor_settings[BSEC_MAX_PHYSICAL_SENSOR];
        uint8_t n_required_sensor_settings = BSEC_MAX_PHYSICAL_SENSOR;
    
        bsec_library_return_t status = BSEC_OK;
    
        /* note: Virtual sensors as desired to be added here */
        requested_virtual_sensors[0].sensor_id = BSEC_OUTPUT_IAQ;
        requested_virtual_sensors[0].sample_rate = sample_rate;
        requested_virtual_sensors[1].sensor_id = BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE;
        requested_virtual_sensors[1].sample_rate = sample_rate;
        requested_virtual_sensors[2].sensor_id = BSEC_OUTPUT_RAW_PRESSURE;
        requested_virtual_sensors[2].sample_rate = sample_rate;
        requested_virtual_sensors[3].sensor_id = BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY;
        requested_virtual_sensors[3].sample_rate = sample_rate;
        requested_virtual_sensors[4].sensor_id = BSEC_OUTPUT_RAW_GAS;
        requested_virtual_sensors[4].sample_rate = sample_rate;
        requested_virtual_sensors[5].sensor_id = BSEC_OUTPUT_RAW_TEMPERATURE;
        requested_virtual_sensors[5].sample_rate = sample_rate;
        requested_virtual_sensors[6].sensor_id = BSEC_OUTPUT_RAW_HUMIDITY;
        requested_virtual_sensors[6].sample_rate = sample_rate;
        requested_virtual_sensors[7].sensor_id = BSEC_OUTPUT_STATIC_IAQ;
        requested_virtual_sensors[7].sample_rate = sample_rate;
    
        /* Call bsec_update_subscription() to enable/disable the requested virtual sensors */
        status = bsec_update_subscription(requested_virtual_sensors, n_requested_virtual_sensors, required_sensor_settings,
                                          &n_required_sensor_settings);
    
        return status;
    }
    
    int8_t Bme680bsec::bme680_bsec_trigger_measurement(bsec_bme_settings_t* sensor_settings, sleep_fct sleep) {
        uint16_t meas_period;
        uint8_t set_required_settings;
        int8_t bme680_status = BME680_OK;
    
        /* Check if a forced-mode measurement should be triggered now */
        if (sensor_settings->trigger_measurement) {
            /* Set sensor configuration */
    
            gas_sensor.tph_sett.os_hum = sensor_settings->humidity_oversampling;
            gas_sensor.tph_sett.os_pres = sensor_settings->pressure_oversampling;
            gas_sensor.tph_sett.os_temp = sensor_settings->temperature_oversampling;
            gas_sensor.gas_sett.run_gas = sensor_settings->run_gas;
            gas_sensor.gas_sett.heatr_temp = sensor_settings->heater_temperature; /* degree Celsius */
    
            /* Select the power mode */
            /* Must be set before writing the sensor configuration */
            gas_sensor.power_mode = BME680_FORCED_MODE;
            /* Set the required sensor settings needed */
            set_required_settings = BME680_OST_SEL | BME680_OSP_SEL | BME680_OSH_SEL | BME680_GAS_MEAS_SEL;
    
            /* Set the desired sensor configuration */
            bme680_status = bme680_set_sensor_settings(set_required_settings, &gas_sensor);
            if (bme680_status != BME680_OK) return bme680_status;
    
            /* Set power mode as forced mode and trigger forced mode measurement */
            bme680_status = bme680_set_sensor_mode(&gas_sensor);
            if (bme680_status != BME680_OK) return bme680_status;
    
            /* Get the total measurement duration so as to sleep or wait till the measurement is complete */
            bme680_get_profile_dur(&meas_period, &gas_sensor);
    
            /* Delay till the measurement is ready. Timestamp resolution in ms */
            sleep((uint32_t)meas_period);
    
            return bme680_status;
        }
    
        /* Call the API to get current operation mode of the sensor */
        bme680_status = bme680_get_sensor_mode(&gas_sensor);
        /* When the measurement is completed and data is ready for reading, the sensor must be in BME680_SLEEP_MODE.
         * Read operation mode to check whether measurement is completely done and wait until the sensor is no more
         * in BME680_FORCED_MODE. */
        while (gas_sensor.power_mode == BME680_FORCED_MODE) {
            /* sleep for 5 ms */
            sleep(5);
            bme680_status = bme680_get_sensor_mode(&gas_sensor);
            if (bme680_status != BME680_OK) return bme680_status;
        }
        return bme680_status;
    }
    
    int8_t Bme680bsec::bme680_bsec_read_data(int64_t time_stamp_trigger, bsec_input_t* inputs, uint8_t* num_bsec_inputs,
                                             int32_t bsec_process_data) {
        static struct bme680_field_data data;
        int8_t bme680_status = BME680_OK;
    
        /* We only have to read data if the previous call the bsec_sensor_control() actually asked for it */
        if (bsec_process_data) {
            bme680_status = bme680_get_sensor_data(&data, &gas_sensor);
            if (bme680_status != BME680_OK) return bme680_status;
    
            KD_DEBUG(KD_BME680_BSEC, "BSEC data staus %d bsec_process_data %d", data.status, bsec_process_data);
    
            if (data.status & BME680_NEW_DATA_MSK) {
                /* Pressure to be processed by BSEC */
                if (bsec_process_data & BSEC_PROCESS_PRESSURE) {
                    /* Place presssure sample into input struct */
                    inputs[*num_bsec_inputs].sensor_id = BSEC_INPUT_PRESSURE;
                    inputs[*num_bsec_inputs].signal = data.pressure;
                    inputs[*num_bsec_inputs].time_stamp = time_stamp_trigger;
                    (*num_bsec_inputs)++;
                    KD_DEBUG(KD_BME680_BSEC, "BSEC data pressure %d", (int)data.pressure);
                }
                /* Temperature to be processed by BSEC */
                if (bsec_process_data & BSEC_PROCESS_TEMPERATURE) {
                    /* Place temperature sample into input struct */
                    inputs[*num_bsec_inputs].sensor_id = BSEC_INPUT_TEMPERATURE;
    #ifdef BME680_FLOAT_POINT_COMPENSATION
                    inputs[*num_bsec_inputs].signal = data.temperature;
    #else
                    inputs[*num_bsec_inputs].signal = data.temperature / 100.0f;
    #endif
                    inputs[*num_bsec_inputs].time_stamp = time_stamp_trigger;
                    (*num_bsec_inputs)++;
    
                    KD_DEBUG(KD_BME680_BSEC, "BSEC data temperature %d", (int)data.temperature);
                    /* Also add optional heatsource input which will be subtracted from the temperature reading to
                     * compensate for device-specific self-heating (supported in BSEC IAQ solution)*/
                    inputs[*num_bsec_inputs].sensor_id = BSEC_INPUT_HEATSOURCE;
                    inputs[*num_bsec_inputs].signal = bme680_temperature_offset_g;
                    inputs[*num_bsec_inputs].time_stamp = time_stamp_trigger;
                    (*num_bsec_inputs)++;
                }
                /* Humidity to be processed by BSEC */
                if (bsec_process_data & BSEC_PROCESS_HUMIDITY) {
                    /* Place humidity sample into input struct */
                    inputs[*num_bsec_inputs].sensor_id = BSEC_INPUT_HUMIDITY;
    #ifdef BME680_FLOAT_POINT_COMPENSATION
                    inputs[*num_bsec_inputs].signal = data.humidity;
    #else
                    inputs[*num_bsec_inputs].signal = data.humidity / 1000.0f;
    #endif
                    inputs[*num_bsec_inputs].time_stamp = time_stamp_trigger;
                    (*num_bsec_inputs)++;
                    KD_DEBUG(KD_BME680_BSEC, "BSEC data humidity %d", (int)data.humidity);
                }
                /* Gas to be processed by BSEC */
                if (bsec_process_data & BSEC_PROCESS_GAS) {
                    /* Check whether gas_valid flag is set */
                    if (data.status & BME680_GASM_VALID_MSK) {
                        /* Place sample into input struct */
                        inputs[*num_bsec_inputs].sensor_id = BSEC_INPUT_GASRESISTOR;
                        inputs[*num_bsec_inputs].signal = data.gas_resistance;
                        inputs[*num_bsec_inputs].time_stamp = time_stamp_trigger;
                        (*num_bsec_inputs)++;
                        KD_DEBUG(KD_BME680_BSEC, "BSEC data gas_resistance %d", (int)data.gas_resistance);
                    }
                    KD_DEBUG(KD_BME680_BSEC, "BSEC data gas_resistance %d", (int)data.gas_resistance);
                }
            }
        }
        return bme680_status;
    }
    
    bsec_library_return_t Bme680bsec::bme680_bsec_process_data(bsec_input_t* bsec_inputs, uint8_t num_bsec_inputs,
                                                               output_ready_fct output_ready) {
        /* Output buffer set to the maximum virtual sensor outputs supported */
        bsec_output_t bsec_outputs[BSEC_NUMBER_OUTPUTS];
        uint8_t num_bsec_outputs = 0;
        uint8_t index = 0;
    
        bsec_library_return_t bsec_status = BSEC_OK;
    
        int64_t timestamp = 0;
        float iaq = 0.0f;
        uint8_t iaq_accuracy = 0;
        float temp = 0.0f;
        float raw_temp = 0.0f;
        float raw_pressure = 0.0f;
        float humidity = 0.0f;
        float raw_humidity = 0.0f;
        float raw_gas = 0.0f;
        float static_iaq = 0.0f;
        uint8_t static_iaq_accuracy = 0;
        float co2_equivalent = 0.0f;
        uint8_t co2_accuracy = 0;
        float breath_voc_equivalent = 0.0f;
        uint8_t breath_voc_accuracy = 0;
        float comp_gas_value = 0.0f;
        uint8_t comp_gas_accuracy = 0;
        float gas_percentage = 0.0f;
        uint8_t gas_percentage_acccuracy = 0;
    
        /* Check if something should be processed by BSEC */
        if (num_bsec_inputs > 0) {
            /* Set number of outputs to the size of the allocated buffer */
            /* BSEC_NUMBER_OUTPUTS to be defined */
            num_bsec_outputs = BSEC_NUMBER_OUTPUTS;
    
            /* Perform processing of the data by BSEC
               Note:
               * The number of outputs you get depends on what you asked for during bsec_update_subscription(). This is
                 handled under bme680_bsec_update_subscription() function in this example file.
               * The number of actual outputs that are returned is written to num_bsec_outputs. */
            bsec_status = bsec_do_steps(bsec_inputs, num_bsec_inputs, bsec_outputs, &num_bsec_outputs);
            if (bsec_status != BME680_OK) return bsec_status;
    
            KD_DEBUG(KD_BME680_BSEC, "num_bsec_outputs %d", num_bsec_outputs);
    
            /* Iterate through the outputs and extract the relevant ones. */
            for (index = 0; index < num_bsec_outputs; index++) {
                switch (bsec_outputs[index].sensor_id) {
                    case BSEC_OUTPUT_IAQ:
                        KD_DEBUG(KD_BME680_BSEC, "BSEC_OUTPUT_IAQ");
                        iaq = bsec_outputs[index].signal;
                        iaq_accuracy = bsec_outputs[index].accuracy;
                        break;
                    case BSEC_OUTPUT_STATIC_IAQ:
                        KD_DEBUG(KD_BME680_BSEC, "BSEC_OUTPUT_STATIC_IAQ");
                        static_iaq = bsec_outputs[index].signal;
                        static_iaq_accuracy = bsec_outputs[index].accuracy;
                        break;
                    case BSEC_OUTPUT_CO2_EQUIVALENT:
                        KD_DEBUG(KD_BME680_BSEC, "BSEC_OUTPUT_CO2_EQUIVALENT");
                        co2_equivalent = bsec_outputs[index].signal;
                        co2_accuracy = bsec_outputs[index].accuracy;
                        break;
                    case BSEC_OUTPUT_BREATH_VOC_EQUIVALENT:
                        KD_DEBUG(KD_BME680_BSEC, "BSEC_OUTPUT_BREATH_VOC_EQUIVALENT");
                        breath_voc_equivalent = bsec_outputs[index].signal;
                        breath_voc_accuracy = bsec_outputs[index].accuracy;
                        break;
                    case BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE:
                        KD_DEBUG(KD_BME680_BSEC, "BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE");
                        temp = bsec_outputs[index].signal;
                        break;
                    case BSEC_OUTPUT_RAW_PRESSURE:
                        KD_DEBUG(KD_BME680_BSEC, "BSEC_OUTPUT_RAW_PRESSURE");
                        raw_pressure = bsec_outputs[index].signal;
                        break;
                    case BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY:
                        KD_DEBUG(KD_BME680_BSEC, "BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY");
                        humidity = bsec_outputs[index].signal;
                        break;
                    case BSEC_OUTPUT_RAW_GAS:
                        KD_DEBUG(KD_BME680_BSEC, "BSEC_OUTPUT_RAW_GAS");
                        raw_gas = bsec_outputs[index].signal;
                        break;
                    case BSEC_OUTPUT_RAW_TEMPERATURE:
                        KD_DEBUG(KD_BME680_BSEC, "BSEC_OUTPUT_RAW_TEMPERATURE");
                        raw_temp = bsec_outputs[index].signal;
                        break;
                    case BSEC_OUTPUT_RAW_HUMIDITY:
                        KD_DEBUG(KD_BME680_BSEC, "BSEC_OUTPUT_RAW_HUMIDITY");
                        raw_humidity = bsec_outputs[index].signal;
                        break;
                    case BSEC_OUTPUT_COMPENSATED_GAS:
                        KD_DEBUG(KD_BME680_BSEC, "BSEC_OUTPUT_COMPENSATED_GAS");
                        comp_gas_value = bsec_outputs[index].signal;
                        comp_gas_accuracy = bsec_outputs[index].accuracy;
                        break;
                    case BSEC_OUTPUT_GAS_PERCENTAGE:
                        KD_DEBUG(KD_BME680_BSEC, "BSEC_OUTPUT_GAS_PERCENTAGE");
                        gas_percentage = bsec_outputs[index].signal;
                        gas_percentage_acccuracy = bsec_outputs[index].accuracy;
                        break;
                    default:
                        continue;
                }
    
                /* Assume that all the returned timestamps are the same */
                timestamp = bsec_outputs[index].time_stamp;
            }
    
            /* Pass the extracted outputs to the user provided output_ready() function. */
            output_ready(timestamp, iaq, iaq_accuracy, temp, humidity, raw_pressure, raw_temp, raw_humidity, raw_gas,
                         bsec_status, static_iaq, static_iaq_accuracy, co2_equivalent, co2_accuracy, breath_voc_equivalent,
                         breath_voc_accuracy, gas_percentage, gas_percentage_acccuracy, comp_gas_value, comp_gas_accuracy);
        }
    
        return bsec_status;
    }

     

     

     

     

    I noticed that timestamp in output function is always the same, is it correct bsec framework behaviour?

    I have checked normal version without config and with bsec_config_iaq, unfortunately results are exactly the same.

     

    What is the potenial reason, that I provide neccesary inputs, timestamps, I receive no error and in the outputs there is no IAQ value in every case?

     

    I studied all provided documents and I cannot find bug in my code. I attached also log file from device.
    Could you help me solve that mistert?
    Thank you in advance,
    MJ

     

    15 REPLIES 15

    BSTRobin
    Community Moderator
    Community Moderator

    Since there was no feedback for a long time, we close this topic first. You could update feedback in the future if you have.

    Icon--AD-black-48x48Icon--address-consumer-data-black-48x48Icon--appointment-black-48x48Icon--back-left-black-48x48Icon--calendar-black-48x48Icon--center-alignedIcon--Checkbox-checkIcon--clock-black-48x48Icon--close-black-48x48Icon--compare-black-48x48Icon--confirmation-black-48x48Icon--dealer-details-black-48x48Icon--delete-black-48x48Icon--delivery-black-48x48Icon--down-black-48x48Icon--download-black-48x48Ic-OverlayAlertIcon--externallink-black-48x48Icon-Filledforward-right_adjustedIcon--grid-view-black-48x48IC_gd_Check-Circle170821_Icons_Community170823_Bosch_Icons170823_Bosch_Icons170821_Icons_CommunityIC-logout170821_Icons_Community170825_Bosch_Icons170821_Icons_CommunityIC-shopping-cart2170821_Icons_CommunityIC-upIC_UserIcon--imageIcon--info-i-black-48x48Icon--left-alignedIcon--Less-minimize-black-48x48Icon-FilledIcon--List-Check-grennIcon--List-Check-blackIcon--List-Cross-blackIcon--list-view-mobile-black-48x48Icon--list-view-black-48x48Icon--More-Maximize-black-48x48Icon--my-product-black-48x48Icon--newsletter-black-48x48Icon--payment-black-48x48Icon--print-black-48x48Icon--promotion-black-48x48Icon--registration-black-48x48Icon--Reset-black-48x48Icon--right-alignedshare-circle1Icon--share-black-48x48Icon--shopping-bag-black-48x48Icon-shopping-cartIcon--start-play-black-48x48Icon--store-locator-black-48x48Ic-OverlayAlertIcon--summary-black-48x48tumblrIcon-FilledvineIc-OverlayAlertwhishlist