M5stack Voltmeter U087

I've added another 680K resistor so that I could read higher voltage and re-calibrated it and it all works great, I added another eeprom to store other data , But I stupidly erased the wrong eeprom by entering the wrong address of it.
And I've seen the comment about do not erase the EEprom But now I've tired to use the example code that come with the arduino library to re-calibrate it but the readings are incorrect compared to the other one.

The other unit that is still working if with the extra resistor in series of the 680K resistor if I use this code below to calibrate the it gives the correct readings set at 5.00V the readings are 5.00v.
But on the one I erased the eeprom on and save the calibration then apply the 5.00v the display now shows 2.578V

So i think EEprom holds other data that it uses has reference that it reads from for calibration means that is comes from factory like it .

I've tried to get my head around the ADS1115.h file but can't figure out what address it reads or how they say what address it reads. ADS115.h file shown below to.

*******************************************************************************
* Copyright (c) 2022 by M5Stack
*                  Equipped with M5Core sample source code
*                          配套  M5Core 示例源代码
* Visit for more information: https://docs.m5stack.com/en/unit/vmeter
* 获取更多资料请访问: https://docs.m5stack.com/zh_CN/unit/vmeter
*
* Describe: Vmeter_ADS1115.
* Date: 2022/8/10
*******************************************************************************
  Please connect to Port A,Measure voltage and display in the screen.
  请连接端口A,测量电压并显示到屏幕上
  Pay attention: EEPROM (0x53) has built-in calibration parameters when leaving
the factory. Please do not write to the EEPROM, otherwise the calibration data
will be overwritten and the measurement results will be inaccurate. 注意: EEPROM
(0x53)在出厂时具有内置的校准参数。请不要写入EEPROM,否则校准数据会被覆盖,测量结果会不准确。
*/

#include "M5Stack.h"
#include "M5_ADS1115.h"
#define MYDEBUG
#ifdef MYDEBUG
#define DEBUG_MSG(...) Serial.printf( __VA_ARGS__ )
#else
#define DEBUG_MSG(...)
#endif
ADS1115 voltmeter;

float page512_volt  = 5000.0F;
float page4096_volt = 60000.0F;

int16_t volt_raw_list[10];
uint8_t raw_now_ptr = 0;
int16_t adc_raw     = 0;

int16_t hope = 0.0;

ADS1115Gain_t now_gain = PAG_512;

void setup() {
    M5.begin();
    Wire.begin();

    voltmeter.setMode(SINGLESHOT);  // | PAG      | Max Input Voltage(V) |
    voltmeter.setRate(RATE_8);      // | PAG_6144 |        128           |
    voltmeter.setGain(PAG_512);     // | PAG_4096 |        64            |
    hope = page512_volt /
           voltmeter.resolution;  // | PAG_2048 |        32            |
                                  // | PAG_512  |        16            |
                                  // | PAG_256  |        8             |
    M5.Lcd.setTextFont(4);  // Set font to 4 point font.  设置字体为4号字体

    M5.Lcd.setCursor(
        52, 210);  // Set the cursor at (52,210).  将光标设置在(52, 210)
    M5.Lcd.printf("5V            60V           SAVE");
  //  voltmeter.calibration_factor = 1.995795;
}

void loop(void) {
 // voltmeter.calibration_factor = 1.939995;
    M5.update();  // Check the status of the key.  检测按键的状态
    if (M5.BtnA.wasPressed()) {
        voltmeter.setMode(SINGLESHOT);  // Set the mode.  设置模式
        voltmeter.setRate(RATE_8);      // Set the rate.  设置速率
        voltmeter.setGain(PAG_512);
        now_gain = PAG_512;
        hope     = page512_volt / voltmeter.resolution;

        for (uint8_t i = 0; i < 10; i++) {
            volt_raw_list[i] = 0;
        }
    }

    if (M5.BtnB.wasPressed()) {
        voltmeter.setMode(SINGLESHOT);
        voltmeter.setRate(RATE_8);
        voltmeter.setGain(PAG_4096);
        now_gain = PAG_4096;
        hope     = page4096_volt / voltmeter.resolution;

        for (uint8_t i = 0; i < 10; i++) {
            volt_raw_list[i] = 0;
        }
    }

    if (M5.BtnC.wasPressed()) {
        bool success =
            voltmeter.saveCalibration2EEPROM(now_gain, hope, adc_raw);
        M5.Lcd.setCursor(230, 210);

        if (success) {
            M5.Lcd.setTextColor(GREEN, BLACK);
        } else {
            M5.Lcd.setTextColor(RED, BLACK);
        }

        M5.Lcd.printf("SAVE");

        delay(300);
        M5.Lcd.setCursor(230, 210);
        M5.Lcd.setTextColor(WHITE, BLACK);
        M5.Lcd.printf("SAVE");

        voltmeter.setGain(now_gain);
    }

    voltmeter.getValue();
    
    volt_raw_list[raw_now_ptr] = voltmeter.adc_raw;
    raw_now_ptr                = (raw_now_ptr == 9) ? 0 : (raw_now_ptr + 1);

    int count = 0;
    int total = 0;

    for (uint8_t i = 0; i < 10; i++) {
        if (volt_raw_list[i] == 0) {
            continue;
        }
        total += volt_raw_list[i];
        count += 1;
    }

    if (count == 0) {
        adc_raw = 0;
    } else {
        adc_raw = total / count;
    }

    M5.Lcd.setTextColor(WHITE, BLACK);
    if (now_gain == PAG_512) {
        M5.Lcd.setCursor(10, 10);
        M5.Lcd.printf("Hope volt: %.2f mv             \r\n", page512_volt);
    } else {
        M5.Lcd.setCursor(10, 10);
        M5.Lcd.printf("Hope volt: %.2f mv              \r\n", page4096_volt);
    }

    M5.Lcd.setCursor(10, 40);
    M5.Lcd.printf("Hope ADC: %d     \r\n", hope);

    M5.Lcd.setTextColor(WHITE, BLACK);
    M5.Lcd.setCursor(10, 80);
    M5.Lcd.printf(
        "Cal volt: %.2f mv           \r\n",
        adc_raw * voltmeter.resolution * voltmeter.calibration_factor);

    M5.Lcd.setTextColor(WHITE, BLACK);
    M5.Lcd.setCursor(10, 110);
    M5.Lcd.printf("Cal ADC: %.0f      \r\n",
                  adc_raw * voltmeter.calibration_factor);

    M5.Lcd.setCursor(10, 150);

    if (adc_raw <= hope * 1.001 && adc_raw >= hope * 0.999) {//1.022995 1.001
        M5.Lcd.setTextColor(GREEN, BLACK);
    } else {
        M5.Lcd.setTextColor(RED, BLACK);
    }

    M5.Lcd.printf("RAW ADC: %d        \r\n", adc_raw);
    DEBUG_MSG("C: [ ");
  DEBUG_MSG("raw:%02f ", adc_raw );
  DEBUG_MSG("res:%02f ", hope);
  DEBUG_MSG("cal:%02f ", voltmeter.calibration_factor);
  DEBUG_MSG("cal:%02f ", now_gain);
  DEBUG_MSG("]\n");
}

ADS1115.H file

* @brief A 16-bit ADS1115 ADC converter library From M5Stack
 * @copyright Copyright (c) 2022 by M5Stack[https://m5stack.com]
 *
 * @Links [Unit Ameter](https://docs.m5stack.com/en/unit/ameter)
 * @Links [Unit Vmeter](https://docs.m5stack.com/en/unit/vmeter)
 * @version  V0.0.2
 * @date  2022-08-10
 */
#ifndef _M5_ADS1115_H_
#define _M5_ADS1115_H_
#pragma once

#include "Arduino.h"

#define AMETER 0
#define VMETER 1

#define AMETER_ADDR        0x49
#define VMETER_ADDR        0x48
#define AMETER_EEPROM_ADDR 0x53
#define VMETER_EEPROM_ADDR 0x50//50

#define ADS1115_RA_CONVERSION 0x00
#define ADS1115_RA_CONFIG     0x01

#define ADS1115_PGA_6144 0x00
#define ADS1115_PGA_4096 0x01
#define ADS1115_PGA_2048 0x02  // default
#define ADS1115_PGA_1024 0x03
#define ADS1115_PGA_512  0x04
#define ADS1115_PGA_256  0x05

#define ADS1115_MV_6144 0.187500F
#define ADS1115_MV_4096 0.125000F
#define ADS1115_MV_2048 0.062500F  // default
#define ADS1115_MV_1024 0.031250F
#define ADS1115_MV_512  0.015625F
#define ADS1115_MV_256  0.007813F

#define ADS1115_RATE_8   0x00
#define ADS1115_RATE_16  0x01
#define ADS1115_RATE_32  0x02
#define ADS1115_RATE_64  0x03
#define ADS1115_RATE_128 0x04  // default
#define ADS1115_RATE_250 0x05
#define ADS1115_RATE_475 0x06
#define ADS1115_RATE_860 0x07

#define MEASURING_DIR -1
#define MEASURING_DIR -1

#define ADS1115_MUX_P0N1 0x00  // ammeter & voltmeter  support

#define ADS1115_COMP_MODE_HYSTERESIS 0x00  // default
#define ADS1115_COMP_MODE_WINDOW     0x01

#define ADS1115_MODE_CONTINUOUS 0x00
#define ADS1115_MODE_SINGLESHOT 0x01  // default

#define AMMETER_PRESSURE_COEFFICIENT   0.05
#define VOLTMETER_PRESSURE_COEFFICIENT 0.015918958F

#define ADS1115_PAG_6144_CAL_ADDR 208
#define ADS1115_PAG_4096_CAL_ADDR 216
#define ADS1115_PAG_2048_CAL_ADDR 224
#define ADS1115_PAG_1024_CAL_ADDR 232
#define ADS1115_PAG_512_CAL_ADDR  240
#define ADS1115_PAG_256_CAL_ADDR  248

#define ADS1115_MODE_CONTINUOUS 0x00
#define ADS1115_MODE_SINGLESHOT 0x01  // default

#define VOLTMETER_FILTER_NUMBER 10

typedef enum {
    PAG_6144 = ADS1115_PGA_6144,
    PAG_4096 = ADS1115_PGA_4096,
    PAG_2048 = ADS1115_PGA_2048,  // default
    PAG_1024 = ADS1115_PGA_1024,
    PAG_512  = ADS1115_PGA_512,
    PAG_256  = ADS1115_PGA_256,
} ADS1115Gain_t;

typedef enum {
    RATE_8   = ADS1115_RATE_8,
    RATE_16  = ADS1115_RATE_16,
    RATE_32  = ADS1115_RATE_32,
    RATE_64  = ADS1115_RATE_64,
    RATE_128 = ADS1115_RATE_128,  // default
    RATE_250 = ADS1115_RATE_250,
    RATE_475 = ADS1115_RATE_475,
    RATE_860 = ADS1115_RATE_860,
} ADS1115Rate_t;

typedef enum {
    SINGLESHOT = ADS1115_MODE_SINGLESHOT,
    CONTINUOUS = ADS1115_MODE_CONTINUOUS,
} ADS1115Mode_t;

class ADS1115 {
   private:
    void i2cBegin();
    bool i2cReadBytes(uint8_t addr, uint8_t reg_addr, uint8_t* buff,
                      uint16_t len);
    bool i2cWriteBytes(uint8_t addr, uint8_t reg_addr, uint8_t* buff,
                       uint16_t len);
    bool i2cReadU16(uint8_t addr, uint8_t reg_addr, uint16_t* value);
    bool i2cWriteU16(uint8_t addr, uint8_t reg_addr, uint16_t value);
    float getResolution(bool devices, ADS1115Gain_t gain);
    uint16_t getCoverTime(ADS1115Rate_t rate);
    uint8_t getPGAEEEPROMAddr(ADS1115Gain_t gain);

    bool _device;
    uint8_t _ads1115_addr;
    uint8_t _eeprom_addr;

   public:
    ADS1115Gain_t _gain;
    ADS1115Rate_t _rate;
    ADS1115Mode_t _mode;

    float resolution;
    uint16_t cover_time;
    int16_t adc_raw;
    float calibration_factor;

   public:
    ADS1115(bool devices = VMETER, uint8_t ads1115_addr = VMETER_ADDR,
            uint8_t eeprom_addr = VMETER_EEPROM_ADDR);

    void setGain(ADS1115Gain_t gain);
    void setRate(ADS1115Rate_t rate);
    void setMode(ADS1115Mode_t mode);

    float getValue(bool calibration = true);

    int16_t getConversion(uint16_t timeout = 125);
    int16_t getAdcRaw();

    bool isInConversion();
    void startSingleConversion();

    bool EEPORMWrite(uint8_t address, uint8_t* buff, uint8_t len);
    bool EEPORMRead(uint8_t address, uint8_t* buff, uint8_t len);

    void setCalibration(int8_t voltage, uint16_t actual);
    bool saveCalibration2EEPROM(ADS1115Gain_t gain, int16_t hope,
                                int16_t actual);
    bool readCalibrationFromEEPROM(ADS1115Gain_t gain, int16_t* hope,
                                   int16_t* actual);
};

#endif

would it be possible some how to copy the good working EEprom then down load to the one I erased ?

1 Like

Should be able to fix this up..
Looking at the warning in the code, might just be 1 byte..
Read address 0x53, serial print it in hex..
Then write that value to same address on other board..

good luck.. ~q

1 Like

I may be doing something wrong either reading the bytes or writing the bytes.
This is the code I used for reading.

#include <Wire.h>
#include <stdint.h>
int Address= 0;
#define AT24C02_ADDR 0x53

void setup() {
  uint8_t dataAddr;
  Serial.begin(115200);
  Wire.begin();
  Wire.setClock(31000L); //31 kHz
  Wire.beginTransmission(AT24C02_ADDR);
  Wire.write(0x00); //Sets the start address for use in the upcoming reads
  Wire.endTransmission();
  for(uint8_t i=0;i<8;++i){ //cycle through enough times to capture entire EEPROM
    Wire.requestFrom(AT24C02_ADDR,32,1); //read 32 bytes at a time
    while (Wire.available()){
      uint8_t c = Wire.read();
      Serial.print("ADDRESS:");
      Serial.print(Address);
      Serial.print(":");
      Serial.println(c,HEX); //Send raw data over serial to computer
      Address = Address +1;
    }
  }

}

void loop() {
  
}

And this is what I get(I've removed all the FF

ADDRESS:0:FE
ADDRESS:1:20
ADDRESS:216:1
ADDRESS:217:1D
ADDRESS:218:D9
ADDRESS:219:1D
ADDRESS:220:DE
ADDRESS:221:6
ADDRESS:222:0
ADDRESS:223:0
ADDRESS:240:4
ADDRESS:241:13
ADDRESS:242:E6
ADDRESS:243:A
ADDRESS:244:81
ADDRESS:245:7A
ADDRESS:246:0
ADDRESS:247:0

And this is the code I wrote with

#include <Wire.h>
#define I2C_ADDRESS 0x53

void setup(){
  Wire.begin();
  Serial.begin(115200);
  
  unsigned int address ;//= 0;
   byte byteVal_1 = 0xFE;//ADDRESS:0:201
  byte byteVal_2 = 0x20;//ADDRESS:1:32
  byte byteVal_3 = 0x01;//ADDRESS:216:1
  byte byteVal_4= 0x1D;//ADDRESS:217:29
  byte byteVal_5 = 0XD9;//ADDRESS:218:217
  byte byteVal_6 = 0X1D;//ADDRESS:219:29
  byte byteVal_7 = 0XDE;//ADDRESS:220:222
  byte byteVal_8 = 0X06;//ADDRESS:221:6
  byte byteVal_9 = 0X00;//ADDRESS:222:0
  byte byteVal_10= 0X00;//ADDRESS:223:0
  byte byteVal_11 = 0X04;//ADDRESS:240:4
  byte byteVal_12 = 0X13;//ADDRESS:241:19
   byte byteVal_13 = 0XE6;//242:230
  byte byteVal_14 = 0X0A;//ADDRESS:243:10
  //########################################
  byte byteVal_15 = 0X81;//ADDRESS:244:69
  byte byteVal_16 = 0X7A;//ADDRESS:245:190
  byte byteVal_17 = 0X00;//ADDRESS:246:0
  byte byteVal_18= 0X00;//ADDRESS:247:0
    eepromByteWrite(0,byteVal_1);
  eepromByteWrite(1,byteVal_2);
  eepromByteWrite(216,byteVal_3);
  eepromByteWrite(217,byteVal_4);
  eepromByteWrite(218,byteVal_5);
  eepromByteWrite(219,byteVal_6);
  eepromByteWrite(220,byteVal_7);
  eepromByteWrite(221,byteVal_8);
  eepromByteWrite(222,byteVal_9);
  eepromByteWrite(223,byteVal_10);
  eepromByteWrite(240,byteVal_11);
  eepromByteWrite(241,byteVal_12);
  eepromByteWrite(242,byteVal_13);
  eepromByteWrite(243,byteVal_14);
  eepromByteWrite(244,byteVal_15);
  eepromByteWrite(245,byteVal_16);
  eepromByteWrite(2246,byteVal_17);
  eepromByteWrite(2247,byteVal_18);
  
  for(address=0; address<255; address++){
    Serial.print("Byte at address ");
    Serial.print(address);
    Serial.print(": ");
    Serial.println(eepromByteRead(address));
  }
  
}
void loop(){}

void eepromByteWrite(unsigned int addr, byte byteToWrite){
  Wire.beginTransmission(I2C_ADDRESS);
  Wire.write((byte)(addr>>8));
  Wire.write((byte)(addr&0xFF));
  Wire.write(byteToWrite);
  Wire.endTransmission();
  delay(5); // important!
}

int eepromByteRead(unsigned int addr){
  int byteToRead;
  Wire.beginTransmission(I2C_ADDRESS);
  Wire.write((byte)(addr>>8));
  Wire.write((byte)(addr&0xFF));
  Wire.endTransmission();
  Wire.requestFrom(I2C_ADDRESS, 1);
  byteToRead = Wire.read();
  return byteToRead;
}

But when I use the reading code to read back it's not the same and this what I get

ADDRESS:1:73
ADDRESS:2:73
ADDRESS:3:61
ADDRESS:4:67
ADDRESS:5:1
ADDRESS:6:1D
ADDRESS:7:D9
ADDRESS:8:1D
ADDRESS:9:DE
ADDRESS:10:6
ADDRESS:11:0
ADDRESS:12:0
ADDRESS:29:4
ADDRESS:30:13
ADDRESS:31:E6
ADDRESS:32:A
ADDRESS:33:4
ADDRESS:34:13

I must be writing wrong may be ?
Thanks

why does Address jump from 1 to 216??
it's an int you declare as 0 then increment in a while loop by 1..
i'm thinking Address is bad choice for a var name, maybe it's already defined??

strange.. ~q

I’ve removed all the other address’s save copy and paste 255 lines of code and posting it here, the ones I’ve posted above are the one that contain numbers rather than FF(255)

curious, where did you get that .h file from..
looks different from what i've found..
m5stack/M5-ADS1115

reason I ask is I don't see these..

  bool EEPORMWrite(uint8_t address, uint8_t* buff, uint8_t len);
  bool EEPORMRead(uint8_t address, uint8_t* buff, uint8_t len);

Maybe you can use these??

~q

That's what I thought I was using, I will have to try and find out where I though I got it from M5stack example folders but cant see it. I will look into it.
Strange that this code works this is the file name Unit_VMeter_M5Core

/*
*******************************************************************************
* Copyright (c) 2022 by M5Stack
*                  Equipped with M5Core sample source code
*                          配套  M5Core 示例源代码
* Visit for more information: https://docs.m5stack.com/en/unit/vmeter
* 获取更多资料请访问: https://docs.m5stack.com/zh_CN/unit/vmeter
*
* Describe: Vmeter_ADS1115.
* Date: 2022/8/10
*******************************************************************************
  Please connect to Port A,Measure voltage and display in the screen.
  请连接端口A,测量电压并显示到屏幕上
  Pay attention: EEPROM (0x53) has built-in calibration parameters when leaving
the factory. Please do not write to the EEPROM, otherwise the calibration data
will be overwritten and the measurement results will be inaccurate. 注意: EEPROM
(0x53)在出厂时具有内置的校准参数。请不要写入EEPROM,否则校准数据会被覆盖,测量结果会不准确。
*/

#include "M5Stack.h"
#include "M5_ADS1115.h"

ADS1115 voltmeter;

float page512_volt  = 5000.0F;
float page4096_volt = 60000.0F;

int16_t volt_raw_list[10];
uint8_t raw_now_ptr = 0;
int16_t adc_raw     = 0;

int16_t hope = 0.0;

ADS1115Gain_t now_gain = PAG_512;

void setup() {
    M5.begin();
    Wire.begin();

    voltmeter.setMode(SINGLESHOT);  // | PAG      | Max Input Voltage(V) |
    voltmeter.setRate(RATE_8);      // | PAG_6144 |        128           |
    voltmeter.setGain(PAG_512);     // | PAG_4096 |        64            |
    hope = page512_volt /
           voltmeter.resolution;  // | PAG_2048 |        32            |
                                  // | PAG_512  |        16            |
                                  // | PAG_256  |        8             |
    M5.Lcd.setTextFont(4);  // Set font to 4 point font.  设置字体为4号字体

    M5.Lcd.setCursor(
        52, 210);  // Set the cursor at (52,210).  将光标设置在(52, 210)
    M5.Lcd.printf("5V            60V           SAVE");
}

void loop(void) {
    M5.update();  // Check the status of the key.  检测按键的状态
    if (M5.BtnA.wasPressed()) {
        voltmeter.setMode(SINGLESHOT);  // Set the mode.  设置模式
        voltmeter.setRate(RATE_8);      // Set the rate.  设置速率
        voltmeter.setGain(PAG_512);
        now_gain = PAG_512;
        hope     = page512_volt / voltmeter.resolution;

        for (uint8_t i = 0; i < 10; i++) {
            volt_raw_list[i] = 0;
        }
    }

    if (M5.BtnB.wasPressed()) {
        voltmeter.setMode(SINGLESHOT);
        voltmeter.setRate(RATE_8);
        voltmeter.setGain(PAG_4096);
        now_gain = PAG_4096;
        hope     = page4096_volt / voltmeter.resolution;

        for (uint8_t i = 0; i < 10; i++) {
            volt_raw_list[i] = 0;
        }
    }

    if (M5.BtnC.wasPressed()) {
        bool success =
            voltmeter.saveCalibration2EEPROM(now_gain, hope, adc_raw);
        M5.Lcd.setCursor(230, 210);

        if (success) {
            M5.Lcd.setTextColor(GREEN, BLACK);
        } else {
            M5.Lcd.setTextColor(RED, BLACK);
        }

        M5.Lcd.printf("SAVE");

        delay(300);
        M5.Lcd.setCursor(230, 210);
        M5.Lcd.setTextColor(WHITE, BLACK);
        M5.Lcd.printf("SAVE");

        voltmeter.setGain(now_gain);
    }

    voltmeter.getValue();

    volt_raw_list[raw_now_ptr] = voltmeter.adc_raw;
    raw_now_ptr                = (raw_now_ptr == 9) ? 0 : (raw_now_ptr + 1);

    int count = 0;
    int total = 0;

    for (uint8_t i = 0; i < 10; i++) {
        if (volt_raw_list[i] == 0) {
            continue;
        }
        total += volt_raw_list[i];
        count += 1;
    }

    if (count == 0) {
        adc_raw = 0;
    } else {
        adc_raw = total / count;
    }

    M5.Lcd.setTextColor(WHITE, BLACK);
    if (now_gain == PAG_512) {
        M5.Lcd.setCursor(10, 10);
        M5.Lcd.printf("Hope volt: %.2f mv             \r\n", page512_volt);
    } else {
        M5.Lcd.setCursor(10, 10);
        M5.Lcd.printf("Hope volt: %.2f mv              \r\n", page4096_volt);
    }

    M5.Lcd.setCursor(10, 40);
    M5.Lcd.printf("Hope ADC: %d     \r\n", hope);

    M5.Lcd.setTextColor(WHITE, BLACK);
    M5.Lcd.setCursor(10, 80);
    M5.Lcd.printf(
        "Cal volt: %.2f mv           \r\n",
        adc_raw * voltmeter.resolution * voltmeter.calibration_factor);

    M5.Lcd.setTextColor(WHITE, BLACK);
    M5.Lcd.setCursor(10, 110);
    M5.Lcd.printf("Cal ADC: %.0f      \r\n",
                  adc_raw * voltmeter.calibration_factor);

    M5.Lcd.setCursor(10, 150);

    if (adc_raw <= hope * 1.001 && adc_raw >= hope * 0.999) {
        M5.Lcd.setTextColor(GREEN, BLACK);
    } else {
        M5.Lcd.setTextColor(RED, BLACK);
    }

    M5.Lcd.printf("RAW ADC: %d        \r\n", adc_raw);
}

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.