Sunday, March 12. 2017Nissan Leaf CAN Bus Man In The MiddleI wrote a man in the middle for the leaf battery communication. It uses can4python and Kayak's kcd format to describe the signals. It probably only works on Linux. Source code is here https://carrott.org/git/leaf-can-utils.git It decodes all the messages received on one interface (from the battery) into signals, lets me change their values, and then re-encodes them back into the can bus format, recalculates the new checksum when necessary and sends them out the other interface (to the car). It displays each signal and the received and sent signals: Hexadecimal Decimal In Out In Out 1db Checksum: 007e 007e 126 126 1db Counter: 0002 0002 2 2 1dc Checksum: 005d 005d 93 93 55b Checksum: 007e 00dc 126 220 5bc 2_2: 0002 0002 2 2 Capacity Bars: 000a 000a 10 10 Li-ion battery available charge signal (%): 0040 0040 64 64 Li-ion battery capacity signal (GID): 0074 0074 116 116 Li-ion battery current signal: -0001 -0001 -1 -1 Li-ion battery gradual capacity loss signal?: 0068 0068 104 104 Li-ion battery voltage signal: 017f 017f 383 383 Temperature: 007e 007e 126 126 Wheel Speed: 0000 0000 0 0 _1db 1_2: 00 00 0 0 _1db 3_2: 2a 2a 42 42 _1db 4: 00 00 0 0 _1db 5: 00 00 0 0 _1dc 0: 6e 6e 110 110 _1dc 1: 04 04 4 4 _1dc 2: df df 223 223 _1dc 3: fd fd 253 253 _1dc 4: 04 04 4 4 _1dc 5: d8 d8 216 216 _1dc 6: c6 c6 198 198 _55b 1_2: 00 00 0 0 _55b 2: aa aa 170 170 _55b 3: 00 00 0 0 _55b 4: e0 e0 224 224 _55b 5: 00 00 0 0 _55b 6: 10 10 16 16 _5bc 1_2: 03 03 3 3 _5bc 3: 3f 3f 63 63 _5bc 4_1: 09 09 9 9 _5bc 5: 05 05 5 5 _5bc 6: 40 40 64 64 _5bc 7: 5a 5a 90 90 _5bc Mux_02: 07 07 7 7 _5c0 3: 00 00 0 0 _5c0 6: 00 00 0 0 _5c0 7: 02 02 2 2 _5c0 Mux_1_40: 7e 7e 126 126 _5c0 Mux_1_80: 7e 7e 126 126 _5c0 Mux_1_c0: 7e 7e 126 126 _5c0 Mux_2_80: 7e 7e 126 126 _5c0 Mux_2_c0: 7e 7e 126 126 _5c0 Mux_5_40: 6c 6c 108 108 _5c0 Mux_5_80: d0 d0 208 208 _5c0 Mux_5_c0: c4 c4 196 196 Yesterday I spent some time testing it on a Gen 1 leaf at Blue Cars We cut the can bus wires inside the battery box, just after they go through the water proof connector to the outside and connected about 1 metre of thin figure 8 wire to each side of the cut. This let us access the bus on the car and the bus on the battery while the battery was plugged in under the car. It's possible to get enough slack in the internal battery loom to feed the connector all the way through the machined hole and make room for some extra wires to pass through. This is obviously only suitable for testing as the battery is no longer waterproof, but let us fasten the lid onto the battery before sliding it back under the car and lifting it up to meet the cables below the car. With the two pairs connected together, the car behaved normally, going into ready and spinning the wheels. The BMS module terminates the bus so we connected a termination resistor to the car side of the cut and used termination on the CAN interface talking to the battery. We plugged the other end of the man in the middle to the OBD2 port and didn't use termination. The MitM just worked! The car is very tolerant of errors on the CAN bus. You can stop the battery messages and it goes into turtle mode and all the battery info disappears off the instrument cluster. When you re-start the battery messages it goes back to normal mode and the battery info reappears. Start-up is quite critical, if you don't let the battery send it's start up messages the car doesn't go into ready mode. The car never shut down or went into a permanent turtle mode while I was messing with data on the bus -- it always went back to normal mode if I restored the unmodified message flow from the BMS. I modified the data in nearly every field to see what would happen. The car will go into ready and turn the wheels even when it cannot send messages to the battery. This means the startup sequence doesn't involve a car to battery handshake, even if the car is expecting some startup messages from the battery within a time window. The "check engine" light comes on and it does record some DTCs:
My MitM only works in one direction (from the battery to the car) and it turns out my CAN bus setup wouldn't let two programs play together, so when I started a CAN repeater (candump -b) to copy data from the car to the battery I got corrupted frames and no buffer space errors. I'm going to make the MitM work in both directions to resolve this. If you play a different car's battery messages into this car, it does not go into ready. I didn't spend much time on this and I didn't write code to start the BMS messages at the right time, I just started playing the recording of a running BMS and switched the car on. One experiment that I should have tried was to start the car with it's real battery and then switch to messages recorded from a different car. There are some new DTCs when you try to start a the car while playing messages recorded from another car including
The next experiment is to swap in a BMS module from another car. I figured out some more of the BMS protocol by messing with the data and seeing how the car reacted. The Fuel Gauge display on the instrument cluster is powered by the GIDs signal (the first 10 bits of 0x5BC), not the state of charge signal (first 10 bits of 0x55B). I guess it knows how many GIDS is "full" because the battery will have fewer gids and still read full as it ages. 0x5BC bits 36-39 (ie the high nibble of the 5th byte) somehow effects the Fuel Gauge, lower numbers mean more bars, all other things being the same. Maybe this is used to calculate how many GIDs each bar is worth? I haven't explored this. The battery capacity gauge (the bars outside the fuel gauge) is controlled by a muxed field, when 0x5BC bits 32-35 (ie the low nibble of the 5th byte) is 0x3, 0x5BC bits 16-19 (ie the low nibble of the 3rd byte) contains the capacity bars. I haven't yet used the mux field support in the kcd format to express this -- can4python doesn't support it so I had to hand code it. The cluster does not remember the capacity -- changing this value directly manipulates the number of bars displayed, the value on the can bus is literally the number of bars (0x0 -> no bars, 0xC -> 12 bars). The indicated temperature on the instrument cluster is controlled by another muxed field, when 0x5C0 is 0x40, the indicated temperature is controlled by the 3rd byte of 0x5C0. This mux has 3 values, on this car all 3 are similar in the 3rd byte, but only the when the mux is 0x40 does the 3rd byte control the temperature in the instrument cluster. Many thanks to Carl at Blue Cars for letting me torture his car and Bill & Ed for assisting. Friday, November 19. 2010BMS UpdateI've been fairly quiet recently, mostly because I fell off the blog wagon after going to Samoa on an olpc jaunt (see our report for details). I have been making slow progress on the EVD5 BMS. I fixed no less than 5 bad joints in my backplane arrangement (I specified the wrong size hole and ended up drilling them bigger and soldering the top and bottom, but not so well) and have the BMS behaving well on my 36 cell battery. I haven't implemented the necessary code to deal with voltage drop in the wires while shunting because I'm going to get rid of the wires. The wires are a disaster from a safety and construction point of view. Constructing the wires out of ribbon cable with soldered in fuses takes a very long time and I've already had to replace two blown ones (don't know the cause). My earlier backplane design packs too many boards too close together and makes me nervous. Removing the scary difficult wire while keeping the 5 cell EVD5 BMS is possible, if you make a backplane like Tritium's IQCell system. The squiggly bits in the circuit board will allow the cells to move as the car jiggles down the road. The problem with this is that the EVD5 has an awful lot of wires to each cell -- temperature, sense, shunt+ and shunt- and I'm having trouble getting them all through the squiggles. It's worse if I want to mount the shunt transistors away from the main EVD5 board. You'll note that Tritium's hardware is a lot simpler than the EVD5, this comes from more R&D, when Bob designed the hardware (in 2007!) it was much less clear what was needed, so he designed it to be very flexible. Its fair to say that the EVD5 isn't really suitable for prismatic cells and while this is true, it isn't a really a fair criticism as it was never designed for this purpose. It was designed for Bob's particular cylindrical cell construction. I've put together a schematic with only 3 wires to each cell and none of them carrying current by putting the shunt transistor at the cell and only passing it's gate back to the central EVD5 board. To control current, I abandon the current sensing system in the EVD5 and add a series resistor. I haven't yet done the layout and seen if this works better -- thinner and one fewer wires isn't all that compelling. If you've been watching the commit log, you'll see I've made a fair amount of progress with the software, with a bunch of small improvements to the laptop based monitor and better use of the LEDs on the EVD5 board. I also found another hardware bug, the reset line on U10, the 555 timer in the RS485 section is floating. This is a FET based part and it doesn't take very many electrons to reset the timer and stop communications. With this line tied high, I don't have problems with the software addressing any more. Saturday, May 1. 2010RS485 TantrumNot as serious as a reprap tantrum, my RS485 bus is not behaving very well. If I terminate it properly, it doesn't work at all, and if I don't terminate it at all, then it works, but charging at more than 10A causes a lot of extra characters to appear. Termination has two functions, first, it absorbs the energy in each character as it hits the end of the bus. Without terminators the pulses bounce off the end of the bus and travel back the way they came, causing interference. The second function of the terminators is to hold the bus in a relatively low impedance state, so any stray energy (say that created by the electric and magnetic fields generated by the charger) that gets onto the bus is absorbed without causing spurious characters. Without terminators, I'm seeing extra characters, but with a 2 metre bus, I don't have problems with reflections. So why doesn't it work with terminators? It turns out the transmit enable circuit cannot predict the future. With no cells transmitting, the bus floats, and both wires sit at 0 volts. When a cell enables it's transmitter, one wire rises to about 4V and the other to about 1V. This is how the bus should look when we send 0xFF: I tried enabling the bus with a very short pulse (arrowed) before sending a character (note inverting is on the bottom trace instead of the top like above): There are two possible solutions, capacitive termination, and increasing the baud rate. More on this later. Thursday, November 26. 2009SDCC Compiler BugI've been messing around with the BMS master hardware instead of welding stuff together. I'm trying to send a CAN message and, rather than write my own library from the datasheet, I tried to use Microchip application note AN878. It was easy to adjust so it would compile with SDCC but I seem to have found a bug in the compiler. Because the PIC is a Harvard Architecture CPU, pointers to code and pointers to data are handled differently, which SDCC implements by adding some extra bits to the pointer. Unfortunately it's possible to loose those bits while casting the address of an SFR to a pointer and assigning that to a pointer array element by index. With the the bits cleared, the write-to-pointer-target helper will do nothing, leaving the pointer on the stack. When it returns, the rest of the code freaks out because it expects the pointer to have been popped off the stack. The solution (apart from fixing the compiler bug) is to leave out the cast. It seems that assigning an SFR to a pointer array element doesn't actually need a cast.
Monday, November 16. 2009Backplane Update![]() Kevin at Lynx Innovation kindly organised to have my EVD5 Backplane design made. I've stuffed half the components and tested out a few channels and it looks like I didn't stuff anything up too badly. The biggest mistake I made was to specify the wrong hole size for the main header where the EVD5 board plugs in (the rows of white sockets). This is somewhat inconveniently fixed by drilling the holes bigger and then soldering the top and bottom. Drilling the holes bigger destroys the plating on the inside and disconnects the two layers, so you have to solder the top and the bottom separately.
There are a couple of places where I could move traces to increase separation (and reduce the chance of shorts) but otherwise, I'm very pleased. Now all I need to do is order the enclosures and find some elves to assemble everything. Monday, October 19. 2009BMS backplane attempt![]() This is my third BMS backplane layout.
Friday, October 16. 2009Kelvin Connection Not Necessary
To reduce the many wires and many fuses problem in my Thunder Sky battery, I am planning on (almost) only one wire to each cell. The BMS is set up for a kelvin connection which makes measuring the voltage easy. Without a kevlin connection, when I turn on the bypass current, the measured voltage will drop (because current is now flowing through relatively thin wires). This can be corrected in software as the voltage drop is purely resistive and won't change very quickly, if at all. We can see in the graph below that without a correction, the measured cell voltage drops 60mV when we bypass 500mA. With correction, this error is only 20mV. I used gnuplot to fit the line to the uncorrected data, and it appears to have given more weight to the low current end (where there are more points) as we have a larger error at higher currents. (I still need to investigate why I'm getting such quantised data)
Unfortunately, with one wire for each cell, adjacent cells share a wire and current bypassed in one cell will effect it's neighbours. Since the slaves do not talk to each other, the master will have to take care of this effect. Internally each cell's slave only uses the voltage reading to implement an antonymous "dumb" balancing. The master will coordinate normal BMS operation, so this won't be a great problem. Sunday, October 11. 2009LJTick-RelayDriver repair![]() I managed to blow up both of my LJTick-RelayDriver boards. These are little boards that plug into a LabJack and allow it to drive relays. Since I wanted to drive a relay to turn the battery charger on and off, I had to investigate. The circuit is quite simple, a ULN2003AI Darlington Transistor array and 3 resistors. R1 provides a return path for the base current by and also connects the relay power supply ground to the LabJack's ground. LabJack's datasheet suggests it should be 10Ω, but on both my units it was open circuit. I guess what happened was I put the relay power across this resistor (perhaps by using the a supply sharing a ground with the computer and connecting it backwards) which would cause a great deal of current to flow. If it was 12V, you would expect about 14W to be dissipated in a tiny surface mount component. No wonder it went open circuit. I replaced this resistor with a 120Ω 1/2W unit which will still be overloaded by a 12V fault, but will last a lot longer. Friday, October 9. 2009Measuring charge current![]() Normally I'd use my EVision to measure the charge current, but it needs more voltage than a few cells provide. Last year Vik gave me a few Alegro ACS754LCB-100 hall effect current sensors, so I dug them up and now I'm measuring the charge current. A hall effect sensor uses physics to measure the magnetic field created by a current passing along a wire -- this one is calibrated to produce 20mV on it's output per amp flowing in it's sense wire. I tried 3 sensors and only one of them matched the datasheet. After I'd soldered that one with my too-small soldering iron (which means the part was kept very hot for a long time) it wasn't all that close to specification either. It's response is still linear so I've just adjusted the mV/A value in my code. I'm measuring the signal with my LabJack U3. The code will be in svn soon. A hall effect sensor is good because it isolates the sensed current from the signal wires. This way I can tolerate one isolation fault between my computer and the battery. If I used a regular resistive shunt, the battery would be connected to the computer and an unexpected second isolation fault could cause potentially damaging current to flow. The low insertion losses of the hall sensor also make the charger's voltage regulator more accurate. The disadvantage of hall sensors is they produce more noise in the output signal than a typical resistive shunt. Below we see 3 cells being charged. The charge current starts out high, I adjust the voltage control down and we see the current drop as the cell voltage rises. Then I adjust it up a little. It becomes obvious that the green and blue cells are nearly full while the purple cell is not, so I connect a separate 3A supply to that cell only. This increases the total voltage and the charge current drops. The PFC30 voltage regulator seems to cut the charger off completely below about 300mA. ![]() Thursday, October 8. 2009Compressed air is not a good desoldering tool![]() If you have to use compressed air, blow from the solder side through to the component side, not the other way around. Blowing spreads solder everywhere, and doing it from the component side spreads it all over the components. The solder sticks to the tip of a hot fluxed soldering iron, so it's easy to clean the splatter, if you can get to it with the iron. It took about an hour and half to clean the solder off the components shown above. It took about 2 minutes to do the same job on the other board where I blew from the solder side and and the splatter wasn't hidden in all the component nooks and crannies.
« previous page
(Page 2 of 2, totaling 18 entries)
|
Errorserendipity error: could not include @serendipity_html_nugget_plugin:185f6f376b1b08b446a92b05bfcdc7a1 - exiting.
Errorserendipity error: could not include @serendipity_syndication_plugin:3350747ad57cf5d3bf3643dd4bfb538f - exiting.
Errorserendipity error: could not include @serendipity_archives_plugin:7015fd6c22523f7c6f1ff00a3ba7e879 - exiting.
|