Inexpensive DIY EV Monitoring System (Arduino based)
Not too long ago I decided to attempt to learn digital electronics. It is something that has always intrigued me, but something that has always been over my head. Circuits and wiring? Easy. Computer code? Not so much.
Long story short, I ended up getting a couple of Arduino boards and started playing around. Armed with a helpful tutorial in C here: HowStuffWorks "The Basics of C Programming" I started to get the hang of it. The reality is, there really is no end to what an Arduino board is capable of. My $14 Chinese Arduino Nano copy has 8 analog inputs and 13 digital I/0s. All that is required is the brain power to program it to make it do what you want. So I am now testing my code on a better battery monitoring system for the Electric Booger. Since it is 72V, all I need is 6 voltage monitoring inputs, one input from the amp sensor and maybe a temp sensor on the motor. I have successfully make an Ah counter program that works very well. Here it is running with a simulated volt and amp input: http://i1119.photobucket.com/albums/...pstah563ys.jpg It even works for charging, when current is reversed: http://i1119.photobucket.com/albums/...pslcofxteu.jpg Here is the code so far: Quote:
1) charge_correct: counts reverse amps at an 80% rate to account for battery charging inefficiency 2) fuel_tank: size of available Ah to begin with. |
Very cool! I'm glad someone else is trying this out.
I am curious how you plan on monitoring voltage and current. I would imagine you're going to tap into your ammeter's shunt? I used one of the Haas current sensors that Paul's open revolt uses in my BMS, but it wasn't as accurate as I'd like it to be. What is the plan for the voltage monitoring? |
My car doesn't actually have an ammeter. I know, I know. Lame. I have used a remote one on my multimeter in the past, so I have a pretty good idea of current vs voltage sag, so I just never bothered. But with an Ah counter, it will be essential.
I still have the hall effect amp transducer that I used to use when I was running a separate field controller with my former sepex motor. It is a 0-400A amp sensor (600A peak) - 0-5V analog output. 2.5V is 0 amps. Output goes up for one current direction and down in reverse direction. It is quite accurate, as far as I can tell. This one: http://www.farnell.com/datasheets/30908.pdf Volts is easy. Arduino GND to the most negative battery pack post. Then each positive post signal goes through a 10K/500 voltage splitter (so 100V = 5V) to Arduino A0-A5. |
Cool, your current sensor is quite similar to the one I was using. Just make sure to test it with a known load so you know you're getting accurate readings over time. Like I said, I had issues. I'm not an electronics guru. I do know a little programming so dealing with stuff like noise on lines is not easy for me.
I'd be interested to see how you plan on wiring / program the voltage monitoring to the arduino. Because your batteries are in series, each divider will add to the voltage of the previous batteries unless you have some way of getting around that. I assume you'll just have to compensate for the different voltage ranges in your code? |
cool, just fyi 10 bit adc @ 100v will give you about 0.1v resolution at the top of the pack, then you have to subtract out the lower voltage readings to get the individual voltage which create rounding errors on the "higher up" batteries, with 6 batteries it won't be a big deal though.
Also, you can use createChars to make 6 mini bargraphs (speaking of rounding errors :) ) on the display, one for each battery, from zero pixels to 8 pixels high (blank and full are already existing characters probably, maybe even 1 pixel high already exists), or expand them to 4 lines high. Lucky you have 8 ADC and 6 batteries! :) |
Yup, I was about to write that. 10 bits = 0-1023 output = about 0.1V resolution @ 100V, which is fine for me. If I had a lithium pack I would use multiple boards to get the resolution higher. 25+ separate measurements would require that anyway.
So bank2 reading - bank 1reading = bank 2 voltage, and so on. Also, the Vref pin is only ever used if you want to read an analog signal of less than 0-5V using all 10 bits of ADC. For example, if you wanted to measure a 0-2V signal with 1023 steps of measurement, you would feed a 2V signal to Vref and write the code accordingly. Normally, the ADC compares each analog input to +5, but the measured voltage potential needs GND to make the circuit. So I will hook GND up to the lowest pack potential as the zero ref. Schematics to come. |
you do have to watch out for overflow conditions. millis() overflows in 49 days, some of your "accumulators" might run out of room well before then too. Floating point is convenient, but the raw adc data is bits and might be more accurately accumulated in a double, or a int64_t if you have room. Adding 1024 to itself, 5 times per second will overflow a int32 in 4 days. Dunno if it matters though, depends how accurate it needs to be.
|
I got around that by resetting the counters once the charger hit full charge.
|
I will have a reset button for when it is fully charged. The negative current measuring and resulting "battery capacity regeneration" on the fuel gauge is more for if I want to graze charge while doing errands, charging a bit here and there while [hopefully] keeping my fuel gauge somewhat accurate. It will be interesting to see what sort of charge correction factor I will end up needing to give it some accuracy. I guess it will largely depend on how deeply discharged the pack is while charging - charging at the deep end is far more efficient than at the top end.
|
Now on to the charger monitoring side. I paid a solid $14 for this Arduino and plan to get all my money's worth!
Currently (PUN!), I have six 12V chargers. They put out 10A up to 14.7V and then hold 14.7V until the current drops down enough to switch to a 13.8V float. Too see what's going on remotely, I go look at my Kill A Watt, which I have learned to interpret pretty well. But this involves going down to the garage. I know, I know, first world problem, but wouldn't it be nicer to simply look out the window and see an LED status light flashing in the car? Yes, yes it would. I always look at the Kill A Watt at the beginning and end of a charge to make sure all chargers were working because I had a near fatal (from a battery's perspective) incident where a fuse popped in one charger without me noticing. I haven't gotten there yet, but my future code will watch for differences in voltages between banks and flag a warning LED and message (or text me if I buy a GSM Arduino shield?) if something is out of whack. Anyway, here is a circuit simulation: http://www.youtube.com/watch?v=ip3TT-6Zu1A And here is the code for this part. Many things will cross over from the battery fuel gauge code, as they will share the same inputs and logic. EDIT: I played around with it more and found that if the charger was turned off with the switch before it was finished, it would assume that it was on float and would start the float timer, permanently cutting off the charger relay (ch_enable pin) unless the arduino was reset. This, combined with possible reliability issues, has led me to use a SPDT switch - OFF, charge and charge with float timer, requiring two pins. I have changed the code below to reflect this. Quote:
|
Great project! I was thinking about how to use an arduino for a charge controller for a battery cycler I'm building and here it is:thumbup:. Keep up the good work.
Joe |
I was driving home from work the other day when I glanced at my fuel and temperature gauges, which currently do nothing, and suddenly thought, "man...I could totally put those to use now!!"
So today I found the wires that go to the ex-coolant temp and fuel level senders. When I ground the former, it draws 220mA and the coolant temp gauge pins to the max. When I ground the latter, it draws 117mA and the fuel gauge slowly moves to full. This will be incredibly simple to do....simply control current with an NPN transistor on each, feeding each a calibrated PWM. Actually...I will use opto-isolators to keep the 12V accessory side isolated from the 72V pack side that the Arduino will be in bed with. However, I do not know what their characteristics are compared to regular old transistors. Something tells me they take a lot more current to trigger/switch than transistors which take hardly anything. I may have to up the Arduino's juice with a transistor to trigger an opto-isolator. I must acquire one ASAP and do some playing. |
Quote:
So between 4 and 20mA normally. Someone correct me if this is wrong. |
You're correct.
|
Quote:
|
Yesterday I picked up a couple of PS2502-4 opto-isolators (4-channel):
http://i1119.photobucket.com/albums/...ps905d1242.png I started to play around with it at home: a 0-5K pot (as a variable resistor) putting 5V into pins 1 & 2, and an LED load on 15 & 16, powered by a 20V AC-DC converter through a 1K resistor. What I found is that the output is much more controllable by the input than a plain transistor. A transistor will trigger full blast with a 10K resistor on the gate. Even a 100K resistor. This chip needs more current, and I found that output basically peaks with a 220 ohm resistor into pins 1 & 2, drawing 13.7mA. And that's good, because the Arduino will have plenty of juice to power it. I also tested to see how it responds with PWM and it works just fine. I will use my little PWM program to find PWM calibration values for the fuel and temperature gauges. http://i1119.photobucket.com/albums/...psoaufd2s2.jpg Quote:
|
150ma collector emitter max on those optos, sounds like your "fuel" meter will work as-is, but the temp meter current is a bit high, but sounds like it needs some more resistance anyway (probably the original sensor wasn't 0 ohms at max temp, 12v+pot to determine FSD ohms). You are making it look easy :)
|
Today I went about testing the fuel and temp gauges with my simple PWM circuit and program. My LCD screen displayed "PWM Value", which is an 8-bit value (0-255).
Here is the circuit: http://i1119.photobucket.com/albums/...ps98f56add.png The coolant temp circuit worked great. The PWM range from the needle just barely off the bottom to the "H" line at the top is 60 to 185. This calibration will look something like this: Quote:
The fuel gauge did not work as well. The fuel gauge needs a very low resistance to show "full". The PS2502 opto-isolator's 1V collector emitter saturation voltage (woah, did I just write that??) keeps the gauge from getting past 7/8 full with the PWM at 255. I tried increasing the current into the diode side of the opto-isolator by using a smaller resistor but this didn't change anything. Empty happens at PWM 115. Oh well, I tried. I guess 7/8th of a tank is all I will get. http://i1119.photobucket.com/albums/...psmjohb3os.jpg This will look like this: Quote:
|
7/8ths is plenty good. But if it is still bugging you, driving a mosfet with the opto might get you the low resistance it needs for fsd.
0.107ohms @ 150ma = 0.016v drop across the mosfet ($0.29). RFD3055LE Fairchild Semiconductor | Mouser |
Quote:
|
Quote:
Something like this maybe? http://i1310.photobucket.com/albums/...ps08ea8527.png |
also, the pwm frequency doesn't need to be anymore than visual limits, like 60hz. But 7/8ths is plenty good too :)
|
Astro, the schematic you posted above is the exact circuit I attempted and could not make work. I suspect the opto is not very good at outputting a nice square wave, and since the transistor will stay on with the most minuscule voltage on the gate, it simply never turns off. I suppose I could try to slow down the PWM frequency (easy enough to do) but this throws all the delay timers off. And besides, I don't feel like doing it.:D
The solution I did come up with is simple enough - a 100 ohm bypass resistor between gauge signal and ground. At 0 PWM it sits on the empty line and at 255 PWM it is just short of the full line. Good enough! Here is the schematic of the whole entire thing: http://i1119.photobucket.com/albums/...ps0e4c7c9d.png INTERESTING BITS: Warning Lamp: the ex-low oil pressure warning lamp Vac Pump Switch/"Run" +12V: monitors the vacuum pump switch when the car is on; if the switch remains closed for more than 10 seconds, the warning lamp is flashed and "VACUUM PUMP FAILURE" is displayed "ACC" +12V: turns the display on when the keyswitch is turned the first click; I was going to trigger a pin on the Arduino (using lcd.display() and lcd.noDisplay() functions) but I ran out of pins :); opening the display's contrast pin also turns the screen off. All my bits and pieces have arrived from Digikey. All I am waiting for is my Hong Kong sourced 20X4 LCD display. |
Quote:
http://i1119.photobucket.com/albums/...psb2618e94.png The 47nF cap between 0V and 5V isn't necessary because the arduino already has a much larger cap between its 5V and ground. But the 4.7nF cap between output and 0V will no doubt smooth out signal irregularities. |
mucking about with resistor values:
Code:
tap divider sense watts resolution per bit |
Quote:
You're doing a great job! I look forward to more updates. :thumbup: |
All times are GMT -4. The time now is 05:32 AM. |
Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.
Content Relevant URLs by vBSEO 3.5.2
All content copyright EcoModder.com