Implementing the first story
By Irving on Thursday, March 19 2020, 19:24 - Charge Monitor - Permalink
We flesh out the first story and choose some practical quick n dirty solutions to try out.
Lets remind ourselves of the first story:
- As a user I want to measure the battery terminal voltage at 1 sec intervals and store the tuple (time, voltage) on a PC for later processing.
So simply by inspection of the story we know we need some way to measure the voltage at a given time interval and transmit that value, and a count representing the number of time intervals that have passed, to a PC. Measuring the voltage requires an analog to digital converter (ADC). Most analog to digital converters have a limited voltage range at the input, typically 1, 3, or 5 volts. As our battery is nominally 24v and the charging volts could be as high as 28v we need some voltage division at the front end.
Transmitting the voltage reading to the PC most conveniently would be done, these days, by a USB connection. So we need a USB connected ADC, and unsurprisingly such things exist. An example being this one (left). Despite its attractive low price (£6 from China) this solution isn't really viable as it doesn't have any on-board firmware which will allow it to be programmed from the Arduino programming environment (and all the software supplied appears to have a Chinese user interface). Another option is this one (right), which is marketed as a PC oscilloscope for around £20 - 25. It has an extensive suite of software written in Visual Basic, the source code of which is available on request. I quite like this one. Its based on a Microchip PIC microcontroller, is available in both 10 (5v in 5mV steps) and 12 bit (5v in 1mV steps) resolution and has 6 ADC channels. I'll get one ordered very soon. But for now, and for simplicity and speed of creation, I'm going to go with our old friend, the Arduino Uno, which has a built-in 6-channel 10bit ADC with a 5v input.
For those that haven't met the Arduino before, I suggest you scurry over to the Arduino website and have a look at the tutorials. For now I'm going to assume you have some knowledge about the Arduino and programming in general. I'm also going to assume a little knowledge of electronics, at least the basics of voltage, current and resistance.
So here is the diagram of our first trial. It can easily be set-up on a breadboard, some stripboard (Veroboard) or just a free space rats nest. We'll use the Arduino's ADC on channel 0 (hence the connection to the A0 pin).
The core of the front end is the voltage divider comprising resistors R1 - R3. These create a voltage divider with a division ratio between 0.1636 and 0.1695 depending on the actual values of the resistors, the actual ratio required being 0.1666:1. Since the maximum input voltage to the Arduino is 5 volts, this allows for a maximum battery voltage of 5/0.1666 = 30v. The exact division value isn't critical because we will run a calibration procedure as described later, but it needs to be close to get the best result. Too low a ratio and the reading will be off the scale, too high and you lose dynamic range (the abiity to differentiate between two readings). The Arduino ADC, by default, uses its 5v supply as the reference, so ADC readings are returned as relative to the supply voltage. You must use an external power supply and not rely on the USB supply if you want the ADC reading to be remotely accurate as the supply voltage on USB power can be as low as 4.7V and not stable giving inconsistent results.
There are two other components shown, capacitor C1 and diode D1. These are optional but represent good design practice. The connection from our test module to the battery is a length of wire probably at least a metre long. Even if twisted pair is used this will still pick up noise, mains hum and other unwanted signals on top off the ripple and switching spikes from the charger. C1 in conjunction with the resistor network act like a low pass filter. It has little effect on the DC voltage we are measuring but will significantly reduce signals above 10Hz. Diode D1 serves to protect the Arduino against voltage spikes that could come from the charger or the wheelchair. Any voltage arriving at the Arduino will be clamped to the 5v supply, limiting the input voltage at analogue input A0 to a safe 5.6v.
The code for the Arduino couldn't be simpler:
/************** * * Simple logging voltmeter. Averages 10 readings and sends the result once per second over USB to PC. * * Capture to file on PC using putty, then import into Excel to graph. * * Version 1.01 30-03-2020 * ***************/ #define CALIBRATION_FACTOR 30.0 #define SENDS_PER_SEC 1 #define SEND_INTERVAL 1000/SENDS_PER_SEC #define READS_PER_SEND 10 #define READ_INTERVAL SEND_INTERVAL/READS_PER_SEND int voltagePin = A0; // select the input pin for the voltage measurement long timeValue = 0; // variable to store the time count float voltageValue = 0; // variable to store the battery voltage int analogValue = 0; // raw ADC reading int loopCount = 0; // counter for averages long timeNow = 0; //time counters long timeLastRead = 0; long timeLastSent = 0; void setup() { Serial.begin(115200); while (!Serial); // wait for the serial port timeLastRead = millis(); // start timing timeLastSent = timeLastRead; } void loop() { timeNow = millis(); if( timeNow = timeLastRead + READ_INTERVAL) { timeLastRead = timeNow; // acquire the voltage analogValue += analogRead(voltagePin); // read the ADC and accumulate loopCount += 1; // increment count of reads. added 30/03/20 } if( timeNow = timeLastSent + SEND_INTERVAL) { timeLastSent = timeNow; voltageValue = (analogValue * CALIBRATION_FACTOR)/(1024.0 * loopCount); // convert to average volts. modified to use loopCount 30/03/20 // print time & voltage tuple as "[ time, voltage ] Serial.print("[ "); Serial.print(timeValue); Serial.print(", "); Serial.print(voltageValue); Serial.println(" ]"); analogValue = 0; // reset accumulator loopCount = 0; // reset loopCount. added 30/03/20 timeValue += SEND_INTERVAL; // increment time counter } }
The calibration procedure is very simple too. The purpose here is to adjust the calibration constant to take account of errors in the voltage divider and the actual ADC reference voltage. Connect up the battery and measure the voltage between R1 & ground (ideally with a good 4-digit, 6000 count multimeter), and call this v1. Now run the program, open the serial monitor, and see what voltage is reported. This is averaged over 10 reads so should be reasonably stable, but if it varies take a further average, and call this v2. Divide v2/v1 and multiply by 30. The result is the calibration constant to use in place of the value 30.0 in the program, so adjust the line containing "#define CALIBRATION_CONSTANT" to suit.
In the next blog I'll deal with Story 2, measuring the current.
Comments
I'd like to thank you for the efforts you've put in writing this site. I am hoping to view the same high-grade content from you later on as well. In truth, your creative writing abilities has motivated me to get my own website now ;)|
It is not my first time to pay a visit this website, i am browsing this web page dailly and take pleasant information from here daily.|
Hi there, I discovered your blog via Google even as searching for a similar matter, your website got here up, it appears to be like great. I've bookmarked it in my google bookmarks.
There's definately a lot to learn about this issue. I like all the points you have made.|
Hello, I enjoy reading through your article. I wanted to write a little comment to support you.|
I am no longer positive the place you are getting your info, however great topic. I needs to spend some time studying much more or working out more. Thanks for magnificent information I was in search of this information for my mission.|
I always spent my half an hour to read this blog's articles or reviews all the time along with a cup of coffee.|
I am now not sure where you're getting your info, however great topic. I needs to spend a while learning much more or understanding more. Thank you for fantastic info I was searching for this info for my mission.|
Every weekend i used to go to see this web page, for the reason that i wish for enjoyment, as this this web site conations genuinely nice funny information too.|
Magnificent beat ! I wish to apprentice even as you amend your site, how can i subscribe for a weblog website? The account helped me a appropriate deal. I had been a little bit acquainted of this your broadcast offered brilliant transparent concept|
I'm amazed, I have to admit. Rarely do I encounter a blog that's equally educative and amusing, and without a doubt, you've hit the nail on the head. The problem is something not enough men and women are speaking intelligently about. I'm very happy I found this in my hunt for something regarding this.|
Pretty great post. I just stumbled upon your weblog and wished to mention that I have really enjoyed surfing around your weblog posts. In any case I will be subscribing on your feed and I'm hoping you write once more very soon!|