// -------------------------------------- // Modified i2c_scanner to find, dump and update a DTM0660 based multimeter EEPROM // to hack in missing features. // // See http://www.kerrywong.com/2016/03/19/hacking-dtm0660l-based-multimeters/comment-page-1/#comment-874169 // for more about hacking this chipset // Modified slighty by Kbird March 2017 for Use with OSEPP Uno R4 and to clarify some things for Noobs like myself.... // This Code is not mine, I do not Code, I have simply clarified things for myself and people new to this kind of thing. // I soldered a 5 pin female Header to the UT139c PCB on the RH side where I beleive Uni-T uses a Pogo Pin Adaptor + Programmer, // in the 5 Holes ,ie VDD_WP_SLC_SDA_WP_V- above the two holes labelled CAL (leave these empty), No need to remove the LCD at all. // When attaching the Uno or connecting to the Serial Port, the Buzzer on the PCB will "Chirp" as normal , as you must have the Meter ON // to Programme it , it can be in ANY MODE except OFF, so after pulling the Meter's batteries Turn the Dial to V before further disassembly. // If you hear the Buzzer "Ticking" or chirping Constantly remove the 3.3v pwr wire and Check your wiring or try the ALT SDA and SCL positions // IF you Find the EEPROM is programmed with FF in the positions you tried to change instead of what was intended Don't panic ! // Check your Wiring especially that WP is to Pin 8 and that V- is to Ground (GND) to allow the Write process.... // And then just let it run again after reconnecting the Uno. ( the Sketch should still be looping , open Serial Monitor to watch progress) // *** NOTE ALL OPTIONS ARE DISABLED BELOW CURRENTLY ..the sketch will just scan the I2C Bus and print the EEPROM to the Serial Monitor Window // *** THIS IS YOUR DEFUALT EEPROM ...COPY AND PASTE IT TO NOTEPAD and save it somewhere safe so you have a Copy in case your efforts go sideways // Using the Uno (or Leonardo) connect the UT139C Pins thus.... // VDD Pin to 3.3v Power pin // SDA to A4 pin ( or Pin2 on Leonardo) *Can also use SDA PIN too if Working -- not working on some Clones // SLC to A5 pin ( or Pin3 on Leonardo) *Can also use SLC PIN too if Working -- not working on some Clones // GND to GND pin // WP to no#8 Pin (as defined above by ..... #define BOARD_WP 8) #include // #define BLINK_PIN 13 // Unused.. Can be used to assist with debugging. #define BOARD_POWER 9 // This can theoretically be used to power the multimeter/24c02 since the board draws a few miliamps. // In the end, I just opted to power the board from 3v3 directly, as this makes manually resetting the multimeter only, easier. #define BOARD_WP 8 // Pull down WP pin to allow us to write to the 24c02 - by default this is held high by a pullup resistor on the multimeter. // ***Attach Meter WP (write protect) Wire to Pin 8 on Uno void setup() { // Allow the USB to re-enumerate before we attempt to talk. You can probably shorten this delay considerably. Default 30000 (30 Secs) delay(10000); Serial.begin(9600); // Power up the multimeter if connected to the BOARD_POWER pinMode(BOARD_POWER, OUTPUT); digitalWrite(BOARD_POWER, HIGH); //Enable writing to the eeprom pinMode(BOARD_WP, OUTPUT); digitalWrite(BOARD_WP, LOW); Serial.println("\nDTM0660 EEPROM dumper and updater."); Wire.begin(); Serial.println("Waiting for DTM0660 POST and i2c Bus to settle."); delay(3000); } void loop() { byte error, address; int nDevices; Serial.println("Scanning..."); nDevices = 0; for (address = 1; address < 127; address++ ) { // The i2c_scanner uses the return value of // the Write.endTransmisstion to see if // a device did acknowledge to the address. Wire.beginTransmission(address); error = Wire.endTransmission(); if (error == 0) { Serial.print("\nI2C device found at address 0x"); if (address < 16) { Serial.print("0"); } Serial.print(address, HEX); Serial.println(" "); // Dump the current rom values, so we have somthing to fall back on if it all goes pear shaped. // NOTE: The 24c02 also contains calibration values, so should be unique to the meter, simply pasting the hexdump from // one meter to another will screw up the calibration. dump24c02(address); // Enable serial. // NOTE: On some meters, this will break the button matrix, or screw up some other features. // You do this entirely at your own risk.. magic smoke and a dead meter may result. // If in doubt, check whether pin 20 on the DTM0660 looks to be connected to some other circuitry before attempting to enable serial output. // It is however safe to do this on the version of Victor VC921 I have as the Tx pin pad is not connected to anything else. // *** Remove the Comment Marks (//) to enable the the following Options *** //enableRS232(); // Set LCD bias to 3.3V by Removing the // below... Coutesy of FrozenFrog on EEVBlog //VLCD(); //Select one of the following three modes by Removing the // in front of your choice //enable4000Count(); //enable6000Count(); //enable8000Count(); //extendPowerOn(); //extendBacklightOn(); // I just copied and renamed extendPowerOn(); // ADD EXTRA CHANGES HERE AND DEFINE THEM BELOW nDevices++; } else if (error == 4) { Serial.print("Unknow error at address 0x"); if (address < 16) Serial.print("0"); Serial.println(address, HEX); } } if (nDevices == 0) Serial.println("No I2C devices found\n"); else Serial.println("\nDone.\n"); // Put any changes to bytes immediately after the dump, since that will ensure they hit the found i2c device. delay(5000); // Wait 5 seconds then re-scan. } void dump24c02(byte i2cAddress) { int addrPointer = 0; int romLength = 0xff; // 24c02 - 256x8 bits (256 bytes) byte b = 0; Serial.println("-- : 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F"); while (addrPointer <= romLength) { if (!(addrPointer % 16)) { Serial.print("\n"); if (addrPointer < 16) { Serial.print("0"); } Serial.print(addrPointer, HEX); Serial.print(" : "); } b = i2c_eeprom_read_byte(i2cAddress, addrPointer); // Read byte addrPointer++; // increment address pointer if (b < 0x10) { Serial.print("0"); } Serial.print(b, HEX); // Print byte Serial.print(" "); } Serial.println(" "); } byte i2c_eeprom_read_byte( int deviceaddress, unsigned int eeaddress ) { Wire.beginTransmission(deviceaddress); Wire.write((int)eeaddress); Wire.endTransmission(); Wire.requestFrom(deviceaddress, 1); if (Wire.available()) { return Wire.read(); } else { return 0xff; } } void i2c_eeprom_write_byte( int deviceaddress, unsigned int eeaddress, byte data ) { digitalWrite(BOARD_WP, LOW); delay(100); int rdata = data; Wire.beginTransmission(deviceaddress); Wire.write((int)(eeaddress)); // Wire.write(rdata); Wire.endTransmission(); //digitalWrite(BOARD_WP, HIGH); } void enableRS232() { Serial.println("Enabling RS232"); i2c_eeprom_write_byte(0x50, 0xFA, 0xCE); Serial.println("Done"); } void extendPowerOn() { Serial.println("Extending Power On time"); i2c_eeprom_write_byte(0x50, 0xFB, 0x1e); Serial.println("Done"); } void extendBacklightOn() { Serial.println("Extending Backight On time"); i2c_eeprom_write_byte(0x50, 0xFC, 0x1e); // Copied and change Byte From extendPowerOn Serial.println("Done"); } // COPY AND PASTE void settings here for your Other Byte Changes enabled above void VLCD() { Serial.println("Setting LCD bias to 3.3V"); i2c_eeprom_write_byte(0x50, 0xF9, 0xC3); Serial.println("Done"); } void enable8000Count() { Serial.println("Enabling 8000 Count Mode"); // Enable 8000 Count - Values taken from - this thread. May require a little polishing, but do appear to work. // https://www.eevblog.com/forum/testgear/canadian-tire-mastercraft-dmm-new-and-old-revision-teardown/msg928377/#msg928377 i2c_eeprom_write_byte(0x50, 0x10, 0x40); // Full Scale 0x1F40 - 8000 i2c_eeprom_write_byte(0x50, 0x11, 0x1F); // Note: Little endian byte swap // i2c_eeprom_write_byte(0x50, 0x12, 0x41); // Range Up 0x1F41 - 8001 i2c_eeprom_write_byte(0x50, 0x13, 0x1F); // Note: Little endian byte swap // i2c_eeprom_write_byte(0x50, 0x14, 0xEE); // Range down value, changed to 750 (0x02EE). i2c_eeprom_write_byte(0x50, 0x15, 0x02); // Note: Little endian byte swap Serial.println("Done"); } void enable6000Count() { Serial.println("Enabling 6000 Count Mode"); // Enable 6000 Count - values similar to 8000 count mode, but based on Kerry Wong's ennoLogic eM860T dump i2c_eeprom_write_byte(0x50, 0x10, 0x70); // Full Scale 0x1710 - 5904 i2c_eeprom_write_byte(0x50, 0x11, 0x17); // Note: Little endian byte swap // i2c_eeprom_write_byte(0x50, 0x12, 0x17); // Range Up 0x1838 - 6200 i2c_eeprom_write_byte(0x50, 0x13, 0x71); // Note: Little endian byte swap // i2c_eeprom_write_byte(0x50, 0x14, 0x44); // Range down value, changed to 580 (0x0244). i2c_eeprom_write_byte(0x50, 0x15, 0x02); // Note: Little endian byte swap Serial.println("Done"); } void enable4000Count() { Serial.println("Enabling 4000 Count Mode"); // Enable 4000 Count - these values are taken from the Victor VC921 unmodified dump. i2c_eeprom_write_byte(0x50, 0x10, 0xA0); // Full Scale 0x0FA0 - 4000 i2c_eeprom_write_byte(0x50, 0x11, 0x0F); // Note: Little endian byte swap // i2c_eeprom_write_byte(0x50, 0x12, 0x68); // Range Up 0x1068 - 4200 i2c_eeprom_write_byte(0x50, 0x13, 0x10); // Note: Little endian byte swap // i2c_eeprom_write_byte(0x50, 0x14, 0x7C); // Range down value, changed to 380 (0x017C). i2c_eeprom_write_byte(0x50, 0x15, 0x01); // Note: Little endian byte swap Serial.println("Done"); }