DBMandrake
Posts: 223
Joined: Mon Mar 20, 2017 4:57 am
Location: Scotland

Re: eeprom readout for CMU Board

Fri Oct 25, 2019 5:22 am

kiev wrote:Here is a picture of the lower 256 words, the upper 256 were exactly identical just add 0x100 to the address in the left column.

If the two 256 word banks are mirrored doesn't that suggest a problem with the most significant address bit of your reader not addressing the whole chip properly ? Remember Rupert had problems with his read attempts as well...

I can't imagine why they would purposefully duplicate the data in this way. And if the most significant bit was not used in the CMU board (left grounded for example) because they only needed 256 words, you would not expect to find duplicated data in the top 256 words, they should be empty or random.

Seems a little fishy to me.
- Simon

EV: 2011 Peugeot Ion
ICE: 1997 Citroen Xantia V6

kiev
Posts: 1005
Joined: Sun May 03, 2015 7:15 am
Location: The Heart o' Dixie
Contact: Website

Re: CMU board notes, eprom, cell numbering

Fri Oct 25, 2019 2:39 pm

[edit: ignore this, the github library code is defective]

The code will let you read any memory address and i tried it with settings to read just the lower 256 and then read the entire block. The data seems to be contained in 0x040 blocks (64 words) on my card, which came from a 4-cell module. The CMU ID data repeats 2 times in each 256 block for a total of 4 times in a 4-cell module.

Rupert's second board reading in which it identified the CMU number in the first word was from an 8-cell module. His lower 256 block repeats the ID data 4 times using the 0x040 blocks which would be a total of 8 times in an 8-cell module.

Don't yet know what the values mean, maybe it is calibration and scale factors?

Listings of the Arduino source code for library, header and sketch files.

Code: Select all

/*
  MicrowireEEPROM Arduino Library Source File to
 Read and write a Microwire EEPROM.
 Written by Timo S <timos@perlplexity.org>
 Mods by MarkGen (MG).
 notes by kiev, 10/23/2019
 This code was found on github in the public domain.
*/

#include "Arduino.h"
#include "MicrowireEEPROM.h"

// class :: member
MicrowireEEPROM::MicrowireEEPROM(int cs_pin, int clk_pin, int di_pin,
                                 int do_pin, int pg_size, int addr_width,
                         int clock_period)
{
//use the "this" pointer for current class member reference
  this->CS = cs_pin;
  this->CLK = clk_pin;
  this->DI = di_pin;
  this->DO = do_pin;

  this->ADDRWIDTH = addr_width;
  this->PAGESIZE = pg_size;
  this->HALF_CLOCK_PERIOD = clock_period / 2;

  // make CS, CLK, DI outputs
  pinMode(CS, OUTPUT);
  pinMode(CLK, OUTPUT);
  pinMode(DI, OUTPUT);
 
  // make DO an input
  pinMode(DO, INPUT);
}

// member function used to either send or read some data value
long MicrowireEEPROM::transmit(int data, int bits)
{
        int dout = 0; //create loop to shift bits
        for (int i=(bits-1); i>=0; i--) {
                dout |= ((int) digitalRead(DO)) << i;//read bit, typecast it,
      //then bitshift left and compound OR to get new dout integer

                if ((1 << i) & data) {
         digitalWrite(DI, HIGH);//send data
          }
                else {
         digitalWrite(DI, LOW);
          }

                delayMicroseconds(HALF_CLOCK_PERIOD);
                digitalWrite(CLK, HIGH);
                delayMicroseconds(HALF_CLOCK_PERIOD);
                digitalWrite(CLK, LOW);
        }
        digitalWrite(DI, LOW);
        return dout;
}

void MicrowireEEPROM::send_opcode(char op)
{
      //------
      //MG added to ensure CS & DI are low before
      //making them HIGH.
      digitalWrite(CS, LOW);
      digitalWrite(DI, LOW);
         
      //----------
     //MG - Commented out
        //digitalWrite(CLK, HIGH);
        //delayMicroseconds(HALF_CLOCK_PERIOD);
     //----------
        digitalWrite(CLK, LOW);
      delayMicroseconds(HALF_CLOCK_PERIOD); //MG added to
      //ensure adequate time for CLK to go LOW
      //93LC86 Must have CS  & DI High on positive
      //edge of the clock bit   
                        
        digitalWrite(CS, HIGH);
        digitalWrite(DI, HIGH);
        // transmit start bit and two bit opcode
        transmit((1 << 2) | op, 3);
}

//class member function to read a memory address
int MicrowireEEPROM::read(int addr)
{
        send_opcode(2); //the opcode for read is 02
        transmit(addr, ADDRWIDTH); //sends the desired address
      //a leading dummy zero is returned, add extra bit holder
        long data = transmit(0, PAGESIZE+1); //return with the value
        digitalWrite(CS, LOW);
        return data;
}

void MicrowireEEPROM::writeEnable(void)
{
        send_opcode(0);
     //---------------------------------
     //transmit(0xFF, ADDRWIDTH);
      //MG - Increased 1's data from 8 bits to 16bit
     //EEPROM 93LC86 has 11/10 bit Adress width
     //0xFF is 0000 0000 1111 1111 results in sending
     //leading zeros for ADW's > 8
        //0xFFFF fills all 16 bits of the INT with 1's
     //0xFFFF = 1111 1111 1111 1111
        transmit(0xFFFF, ADDRWIDTH);
        digitalWrite(CS, LOW);
}

void MicrowireEEPROM::writeDisable(void)
{
        send_opcode(0);
        transmit(0x00, ADDRWIDTH);
        digitalWrite(CS, LOW);
}

void MicrowireEEPROM::write(int addr, int data)
{
        send_opcode(1);
        transmit(addr, ADDRWIDTH);
        transmit(data, PAGESIZE);
        digitalWrite(CS, LOW);
}


Code: Select all

/*
  MicrowireEEPROM library header file
  added notes, kiev 10/24/2019
 */

#ifndef MICROWIREEEPROM_H
#define MICROWIREEEPROM_H

#include "Arduino.h"

class MicrowireEEPROM {
  private:
  // Microwire needs four wires (apart from VCC/GND) DO,DI,CS,CLK
  // configure them here, note that DO and DI are the pins of the
  // EEPROM, so DI is an output of the uC, while DO is an input
  int CS;
  int CLK;
  int DI;
  int DO;
  // an EEPROM can have a varying register or word size, usually 8 or 16 bits per memory word

  int PAGESIZE;

  // an EEPROM can have a varying address width (depending on its storage size)

  int ADDRWIDTH;

  // (half of) the clock period in us
  int HALF_CLOCK_PERIOD;

  long transmit(int data, int bits);
  void send_opcode(char op);

  public:
  MicrowireEEPROM(int cs_pin, int clk_pin, int di_pin, int do_pin, int pg_size,
                  int addr_width, int clock_period);
  int read(int addr);
  void writeEnable(void);
  void writeDisable(void);
  void write(int addr, int data);
};

#endif


Code: Select all

/*
  arduino sketch file
  CMU_ee_reader.ino for reading
  Microwire S93C76A EEPROM
  kwh, 10/23/2019
  This is a bit-banger routine forcing the lines as needed
  to make a brute force read of the chip.
*/

#include <MicrowireEEPROM.h>

// Microwire needs four wires (apart from VCC/GND) DO,DI,CS,CLK
// configure them to pin# here, note that DO and DI are the pins of the
// EEPROM, so DI (chip input) is an output of the arduino uC, while
// DO (chip output) is an arduino input.

int CS=13; int CLK=12; int DI=7; int DO=2;

// Configure the memory word size in bits (16 or 8) called PGS in this // code, and the number of bits for the address bus called
// ADW. The speed at which the clock is run, SPD, is configured in
// microseconds.

int PGS=16; int ADW=9; int SPD=200;

// initialize the library

MicrowireEEPROM ME(CS, CLK, DI, DO, PGS, ADW, SPD);

//start the program setup and main loop functions
//setup opens serial port and sets the baud rate
//main loop reads the device

void setup() {
  Serial.begin(9600);
}

void loop() {
   //print headers
   Serial.print("Address");
   Serial.print("\t");

   Serial.println("Hex Value");
   Serial.println(); 
   delay(200);

   // create a loop to read each address

  for (int addr=0; addr < (1<<ADW); addr++) {
   
    // read the value
    int r = ME.read(addr);
   
    // give some debug output

    Serial.print(addr, HEX);
    Serial.print("\t");
   
    Serial.println(r, HEX);
       
    delay(100); // delay 100 msec
  }
 
}
Last edited by kiev on Tue Nov 05, 2019 8:49 am, edited 1 time in total.
kiev = kenny's innovative electric vehicle

kiev
Posts: 1005
Joined: Sun May 03, 2015 7:15 am
Location: The Heart o' Dixie
Contact: Website

Re: CMU board eeprom data

Sun Oct 27, 2019 9:19 am

[edit: ignore this, the github library code is defective]

For the 4-cell CMU board, the ID number and most of the data is repeated 4 times. But a few data words are only repeated twice, such as that strange couple of words on the last row shown previously.

A blank chip has all bits set to 1, so reading a register would show 0xFFFF.

Here is a another view of the Hex address and value, and decimal value for the bulk of the data which starts at 0x020 registers after the CMU ID.

Image
Last edited by kiev on Tue Nov 05, 2019 8:50 am, edited 1 time in total.
kiev = kenny's innovative electric vehicle

kiev
Posts: 1005
Joined: Sun May 03, 2015 7:15 am
Location: The Heart o' Dixie
Contact: Website

Re: eeprom readout for CMU Board

Tue Nov 05, 2019 8:45 am

DBMandrake wrote:I can't imagine why they would purposefully duplicate the data in this way. And if the most significant bit was not used in the CMU board (left grounded for example) because they only needed 256 words, you would not expect to find duplicated data in the top 256 words, they should be empty or random.

Seems a little fishy to me.


So i went out and bought some blank chips to use for testing and to verify the reader, and you were right--this was fishy data.

i had used a microwire eeprom library for arduino found on github, but it turns out to have problems and issues. When reading a blank chip, which comes filled with 0xFFFF in every register, the library code would only display the results as 0x7FFF, or in binary as 0111 1111 1111 1111. That leading zero was due to a left bitshifting routine that was used in the code to read the register contents. The chip was responding with the correct data as seen in this scope trace, but the github code is fubar. i can't waste any more time to troubleshoot that code.

Yellow is the clock signal, Blue is the address request (last register), Green is the memory data
Image


So i found another arduino library M93Cx6, https://github.com/TauSolutions/M93Cx6, and found that it did read the blank chip properly. Then i used that code to read the eeprom from the 4-cell CMU board. The first register hex value is 0x00C, which is decimal "12" (which btw agrees with an incomplete left bitshifted "6").

Now i'm thinking that this board was from CMU12. The data repeats in the upper and lower 256 words; i don't know why, or that it is a problem. i will do another test to write and read a blank chip to verify the code reads all the chip correctly, but i have no reason to think it is not.

i noticed some possible ascii text string buried in here. It doesn't look like a VIN, but looks something like a mitsubishi part number, " 9? 94 A9 97 5? Z?".

[For example, the label on BMU has part number 9499B116, and on the 8-cell CMU has 9499A794 with a serial number.]

Image
kiev = kenny's innovative electric vehicle

coulomb
Posts: 176
Joined: Sun Jun 10, 2018 8:32 pm
Location: Brisbane, Australia

Re: eeprom readout for CMU Board

Wed Nov 06, 2019 3:36 am

kiev wrote: i noticed some possible ascii text string buried in here. It doesn't look like a VIN, but looks something like a mitsubishi part number, " 9? 94 A9 97 5? Z?".

[For example, the label on BMU has part number 9499B116, and on the 8-cell CMU has 9499A794 with a serial number.]

I note that if you byte swap them (i.e. process the double bytes little end first), you get "9499A795 " (two spaces at the end). That's about as close as you can get to the CMU label's number as you can get, without actually equalling it ;)

DBMandrake
Posts: 223
Joined: Mon Mar 20, 2017 4:57 am
Location: Scotland

Re: CMU board notes, eprom, cell numbering

Wed Nov 06, 2019 3:39 am

Nice work - testing the ability to read and write and read back a new blank chip seems to be the sensible thing to do to verify the results we're getting, otherwise there are too many unknowns if we're not even sure our diagnostic equipment is working properly...

Regarding CMU numbering I found a little nugget in the official i-Miev service manuals that may not have been spotted before. I think we've all seen and referred to these manuals before:

http://mmc-manuals.ru/manuals/i-miev/on ... dex_M1.htm

In 54D-ELECTRIC MOTOR UNIT AND TRACTION BATTERY -> BATTERY MANAGEMENT UNIT (BMU) AND TRACTION BATTERY -> DIAGNOSIS FUNCTION we have the following page describing how to use the MUT-III diagnostic tool with the battery:

http://mmc-manuals.ru/manuals/i-miev/on ... 800ENG.HTM

And this caught my eye:

NUMBERING CMU ID PROCEDURE

Because done at the factory, numbering the CMU ID is not necessary.

We know this statement is true as the CMU's are numbered (somehow) at the factory, however why even mention at all that the "numbering CMU ID procedure" is not necessary unless the diagnostic tool provides an option to do this ? :)

This implies to me that there MIGHT be a diagnostic procedure that can be run on a MUT-III to trigger a renumber of the CMU's.

From what I remember of previous discussion on this the speculation was that there is a daisy chain signal between the CMU boards that is wired in a certain order which would allow the CMU's to "self organise" themselves into the correct CanBUS ID order when commanded to do so. This is not something you would want to do all the time so it makes sense that it would be a diagnostic procedure that can be initiated at the factory and also on the MUT-III diagnostic tool.

Perhaps they originally planned for module level swapping at dealers to be possible, and thus built the CMU numbering procedure into the diagnostic tool, but later decided that dealers would only do whole pack replacements (less training required) and thus the advice is now that the numbering CMU ID procedure is not necessary and should not be used by the dealer.

The question is, who is brave enough to poke around in the MUT-III settings to see if they can find this renumbering procedure ? Does anyone have a scrap car which they can still communicate with the battery pack with ?

I will have a poke around in Diagbox on my car at some point however the Diagbox UI is very different and is not a one for one replication of the options in the MUT-III, so potentially CMU renumbering may not be possible in Diagbox. It is something that could potentially be added to a third party tool like Hobdrive though.

Martin in this Speak EV thread is having to repair/replace a CMU with a faulty LTC chip and has a spare CMU board on hand but doesn't know which number it is, I've suggested the possibility of trying to find and use the CMU renumbering procedure so he might be the first to give it a try if it does exist!

Edit: It also occurs to me that for the renumber procedure to work even in the case that you start with a clash of CanBus ID's between two or more boards, there would have to be an out of band hardware control signal coming from somewhere else to initiate the renumber - didn't we find a non-Canbus control signal going from the BMU to the CMU's in the schematics ? Maybe the diagnostic tool sends a CanBus command to the BMU to initiate the process and the BMU then sends the necessary non-Canbus signal to the CMU's ?

Finding the secret sauce to easily renumber CMU's using a readily available third party diagnostic tool such as Hobdrive / icarsoft etc (no soldering/eeprom swapping) would be a breakthrough for the DIY and aftermarket repair and servicing of these battery packs.
- Simon

EV: 2011 Peugeot Ion
ICE: 1997 Citroen Xantia V6

kiev
Posts: 1005
Joined: Sun May 03, 2015 7:15 am
Location: The Heart o' Dixie
Contact: Website

Re: CMU board notes, eprom, cell numbering

Wed Nov 06, 2019 9:54 am

Martin probably won't be able to do any testing because he sent me that extra CMU board--that's the board i have been using for this thread and to extract the eeprom data.

The label on this board has the following information, so it looks like Mike is right about the byte order.

p/n: 9499A795
s/n: 02000003391
type: G8D-795M-4
kiev = kenny's innovative electric vehicle

Return to “Batteries and Battery Management”