I had complains!
It may not show here, but I had a few friends calling and sending emails, disappointed I diverted from the initial idea and instead of working to the Ship Computer, I wasted time on a battery monitor...
Well, rejoice!
I changed a couple bits and now, the Battery Monitor can get connected to the Ship Computer (when it will be build that is...) and will be used as a probe for suppling data on current and voltage.
How about that?
Friday, 7 March 2014
Monday, 3 March 2014
Arduino-based battery monitor
Hello again!
I started with the Ship Computer last October but had to stop working on it for a couple of months and hoped to start over again in January.
Which, unfortunately I didn't.
The same time I am setting up a trip around Ionian for which I am planning to get going by mid May, that is, less than 2 and a half months away, and I have to prepare the boat and everything.
Which means that probably there won't be much time for software development...
Nevertheless, I absolutely need some of the functionality the ship computer was going to give me, and knowing that probably I won't have the Ship Computer ready for this trip, I started thinking of alternatives.
One thing that I have to have is a battery monitor.
On the boat I have a 120W solar panel for charging a 65AH battery and, if absolutely necessary, I can also use the outboard alternator for additional 60W of battery charging power. As far as consumption goes, I have installed led-based navigation and cabin lights so that will keep the consumption down. Other source of power consumption include the instruments and the autohelm, for which I am particularly worried.
Anyway, since I only carry a single battery, I need to know how much consumption is there, what is the charging current when applicable and the battery voltage.
In order to get this functionality, I used an arduino Pro Mini, a current sensor (similar to this), a voltage divider set up with two resistors and a 16x2 LCD screen connected to I2C.
For powering I used a low cost 6V UBEC like this one: http://r.ebay.com/NQZ0ne
The finished project looks like this:
The source code for the project is very simple and has as following:
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
float amperes=0;
float volts=0;
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
void setup()
{
// initialize the lcd
lcd.begin(16,2);
lcd.clear();
lcd.print("Amps=");
lcd.setCursor ( 0, 1 );
lcd.print("Volts=");
}
void clearValues(){
lcd.setCursor ( 6, 0 );
lcd.print(" ");
lcd.setCursor ( 7, 1 );
lcd.print(" ");
}
void showValues(float Amps,float Volts){
clearValues();
lcd.setCursor ( 6, 0 );
lcd.print(Amps,3);
lcd.setCursor ( 7, 1 );
lcd.print(Volts);
}
void loop()
{
// MEASURE CURRENT
// ampere sensor connected to A3
amperes=0;
long temp=0;
//150 reads, 15 usec delay = total 2.25msec
for(int i = 0; i < 150; i++) {
temp+=analogRead(A7);
amperes = amperes + (.0264 * analogRead(A3) -13.51) / 150;
//function calibrated for 5A sensor
delayMicroseconds(15); //15 usec delay for the A2D to "reset"
}
temp/=150;
amperes=(0.0049*(temp-512))/0.185;
//negative on discharge, positive on charge
amperes*= (-1);
//
// MEASURE VOLTAGE
// voltage divider (1/5) conected at pin A2
temp=0;
//150 reads, 15 usec delay = total 2.25msec delay for a measurement
for(int i = 0; i < 150; i++) {
temp+=analogRead(A3);
delayMicroseconds(15); //15 usec delay for the A2D to "reset"
}
temp/=150; // get the average value
volts=temp*5.01*((19.93+6.8)/6.8)/1024.0; // calculate actual voltage
showValues(amperes,volts);
delay(300);
}
The whole setup is simple, works like a charm and is a way to get some limited but needed functionality even if the Ship Computer is not ready in time for the trip.
That said, I hope to be back soon with a post about the ship computer itself!
Thanks for reading,
G.
I started with the Ship Computer last October but had to stop working on it for a couple of months and hoped to start over again in January.
Which, unfortunately I didn't.
The same time I am setting up a trip around Ionian for which I am planning to get going by mid May, that is, less than 2 and a half months away, and I have to prepare the boat and everything.
Which means that probably there won't be much time for software development...
Nevertheless, I absolutely need some of the functionality the ship computer was going to give me, and knowing that probably I won't have the Ship Computer ready for this trip, I started thinking of alternatives.
One thing that I have to have is a battery monitor.
On the boat I have a 120W solar panel for charging a 65AH battery and, if absolutely necessary, I can also use the outboard alternator for additional 60W of battery charging power. As far as consumption goes, I have installed led-based navigation and cabin lights so that will keep the consumption down. Other source of power consumption include the instruments and the autohelm, for which I am particularly worried.
Anyway, since I only carry a single battery, I need to know how much consumption is there, what is the charging current when applicable and the battery voltage.
In order to get this functionality, I used an arduino Pro Mini, a current sensor (similar to this), a voltage divider set up with two resistors and a 16x2 LCD screen connected to I2C.
For powering I used a low cost 6V UBEC like this one: http://r.ebay.com/NQZ0ne
The finished project looks like this:
In this picture:
- #1 is the current sensor
- #2 if the arduino Pro Mini
- #3 is the insulation for the arduino
- #4 is the UBEC with the insulattion sleeve in place
- #5 is the 16x2 LCD screen
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
float amperes=0;
float volts=0;
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
void setup()
{
// initialize the lcd
lcd.begin(16,2);
lcd.clear();
lcd.print("Amps=");
lcd.setCursor ( 0, 1 );
lcd.print("Volts=");
}
void clearValues(){
lcd.setCursor ( 6, 0 );
lcd.print(" ");
lcd.setCursor ( 7, 1 );
lcd.print(" ");
}
void showValues(float Amps,float Volts){
clearValues();
lcd.setCursor ( 6, 0 );
lcd.print(Amps,3);
lcd.setCursor ( 7, 1 );
lcd.print(Volts);
}
void loop()
{
// MEASURE CURRENT
// ampere sensor connected to A3
amperes=0;
long temp=0;
//150 reads, 15 usec delay = total 2.25msec
for(int i = 0; i < 150; i++) {
temp+=analogRead(A7);
amperes = amperes + (.0264 * analogRead(A3) -13.51) / 150;
//function calibrated for 5A sensor
delayMicroseconds(15); //15 usec delay for the A2D to "reset"
}
temp/=150;
amperes=(0.0049*(temp-512))/0.185;
//negative on discharge, positive on charge
amperes*= (-1);
//
// MEASURE VOLTAGE
// voltage divider (1/5) conected at pin A2
temp=0;
//150 reads, 15 usec delay = total 2.25msec delay for a measurement
for(int i = 0; i < 150; i++) {
temp+=analogRead(A3);
delayMicroseconds(15); //15 usec delay for the A2D to "reset"
}
temp/=150; // get the average value
volts=temp*5.01*((19.93+6.8)/6.8)/1024.0; // calculate actual voltage
showValues(amperes,volts);
delay(300);
}
The whole setup is simple, works like a charm and is a way to get some limited but needed functionality even if the Ship Computer is not ready in time for the trip.
That said, I hope to be back soon with a post about the ship computer itself!
Thanks for reading,
G.
Friday, 17 January 2014
The Wind Sensor
Hello again!
it's almost 2 months since my last post and believe it or not, I have not abandoned the project.
To say the truth I have been tempted to "postpone" developments and start a couple new ones and actually I have started working on a drone BUT I have to go on with this "Ship Computer" project -if not for anything else- for the simple reason that I need to have it!
So, on my last post I was putting a draft version of the system together using a Raspberry PI as the heart of the system.
I had also mentioned that I was going to use an I2C Analog to Digital converter and I had actually bought a couple -pretty expensive- ones.
The thing is, I thought it over a bit and decided to use a Arduino Pro Mini for interfacing with the Wind Sensor.
The Arduno Pro Mini is this one:
It is a full-fledged Arduino in a tiny package.
How tiny is tiny?
Tiny enough to look small next to a credit-card sized Raspberry:
The same time it can be bought from ebay for just a couple euros, making it extremely more cost effective compared to the ADC I was thinking of using while still far more versatile.
So, it was not much of a question really, I was going to use the Arduino in order to get measurements for wind speed and direction.
The actual transducer for getting this measurements was a low cost NASA MARINE masthead unit as shown here.
Two months and something ago I had tried to get in contact with Nasa Marine in order to get some info on this unit but there was not a reply.
So, I had to do a bit of reverse engineering.
The unit terminates on a 5-pin DIN connector, same as the one of the old (pre-nineties) PC keyboard, whose pin layout is as follows:
Playing a bit with a multimeter, I decoded the signals:
The wind speed would be almost proportional to the rotating speed of the cup rotor, which produced a pulse for a full turn.
Next I attached the masthead unit to a bookcase next to my desk so that I could rotate the windex and the cup rotor:
...and I fed the signals to the Arduino:
...and also connected an LCD display so that I would have a quick way to see what was going on.
All I needed was a bit of software, the soul that would make it tick.
I spent a couple of nights and here it is:
It is completely Interrupt Driven (the main loop all it does is to display the readings), it handles smoothing of the analog values, it is a perfect base for I want to do next, which is to set the Arduino as a I2C slave device, connect it to the Raspberry and set up a high-level protocol for their communication.
But more on that next time!
Thanks for reading,
G.
PS
Using the NASA Masthead unit was a dog.
The analog values are not stable enough, they change along with the ambient temperature and the cup rotor only creates a single pulse per revolution. This is a low cost unit and it shows.
Nevertheless, if anyone is thinking of using it in a project, do drop a line, we might exchange notes!
it's almost 2 months since my last post and believe it or not, I have not abandoned the project.
To say the truth I have been tempted to "postpone" developments and start a couple new ones and actually I have started working on a drone BUT I have to go on with this "Ship Computer" project -if not for anything else- for the simple reason that I need to have it!
So, on my last post I was putting a draft version of the system together using a Raspberry PI as the heart of the system.
I had also mentioned that I was going to use an I2C Analog to Digital converter and I had actually bought a couple -pretty expensive- ones.
The thing is, I thought it over a bit and decided to use a Arduino Pro Mini for interfacing with the Wind Sensor.
The Arduno Pro Mini is this one:
It is a full-fledged Arduino in a tiny package.
How tiny is tiny?
Tiny enough to look small next to a credit-card sized Raspberry:
The same time it can be bought from ebay for just a couple euros, making it extremely more cost effective compared to the ADC I was thinking of using while still far more versatile.
So, it was not much of a question really, I was going to use the Arduino in order to get measurements for wind speed and direction.
The actual transducer for getting this measurements was a low cost NASA MARINE masthead unit as shown here.
Two months and something ago I had tried to get in contact with Nasa Marine in order to get some info on this unit but there was not a reply.
So, I had to do a bit of reverse engineering.
The unit terminates on a 5-pin DIN connector, same as the one of the old (pre-nineties) PC keyboard, whose pin layout is as follows:
- Pin 1:Pulse per Wind Cups rotation
- Pin 2:GND
- Pin 3:+5V
- Pin 4:Analog output 1
- Pin 5:Analog output 2
The wind speed would be almost proportional to the rotating speed of the cup rotor, which produced a pulse for a full turn.
Next I attached the masthead unit to a bookcase next to my desk so that I could rotate the windex and the cup rotor:
...and I fed the signals to the Arduino:
...and also connected an LCD display so that I would have a quick way to see what was going on.
All I needed was a bit of software, the soul that would make it tick.
I spent a couple of nights and here it is:
#define bsize 10Style-wise it could be better polished but function-wise I think it's fine.
#include <LiquidCrystal.h>
#include <FlexiTimer2.h>
LiquidCrystal lcd(4, 5, 6, 7, 8, 9);
const int APin2 = A1;
const int APin4 = A0; //Connector PIN4, Wire color BROWN
const int led = 13; //Built-in led
const int PulsePin = 3; //The wind rotor, PI5, color ORANGE
struct buffer {
int data[bsize];
byte bptr;
int total;
int average;
};
struct buffer V2bf, V4bf;
int heading = 0;
int V2 = 0;
int V4 = 0;
int period=0;
void getHeading(){
V2= analogRead(APin2);
V4= analogRead(APin4);
V2bf.total-=V2bf.data[V2bf.bptr];
V2bf.data[V2bf.bptr]=V2;
V2bf.total+=V2bf.data[V2bf.bptr];
V2bf.average=V2bf.total/bsize;
V2bf.bptr++;
if (V2bf.bptr>=bsize) V2bf.bptr=0;
V2=V2bf.average;
V4bf.total-=V4bf.data[V4bf.bptr];
V4bf.data[V4bf.bptr]=V4;
V4bf.total+=V4bf.data[V4bf.bptr];
V4bf.average=V4bf.total/bsize;
V4bf.bptr++;
if (V4bf.bptr>=bsize) V4bf.bptr=0;
V4=V4bf.average;
if (V2<=180){//1st quadrand, 1-90, based on V4
// V4 takes values
// it corresponds to a function of a line that passes from points (18,89) & (78,0)
// see http://www.webmath.com/equline1.html
heading=(-89.0/58*V4/10+3382.0/29);
}
if (V4<=220){ //2nd quadrand, 91-180, based on V2, passing from (18,90) & (76,179)
heading=(89.0/58*V2/10+1809.0/29);
}
if (V2>=758){ //3rd quadrand, 181-270, based on V4, passing from (22,180) & (76,269)
heading=(89.0/54*V4/10+3881.0/27);
}
if (V4>=758){ //4th quadrand, 271-360 based on V2, passing from (76,270) & (18,359)
heading=(-89.0/57*V2/10+1166.0/3);
}
if (heading>=360) heading-=360;
if (heading<0) heading+=360;
}
void pulse(){ //this runs when a pulse is received from the windmeter rotor
static int msecs=0;
int temp;
temp=millis();
period=temp-msecs;
msecs=temp;
}
void setup() {
lcd.begin(16,2);
lcd.clear();
lcd.print("WindMeter");
FlexiTimer2::set(50, getHeading); // 50ms period
pinMode (led,OUTPUT);
attachInterrupt (1, pulse, FALLING); // attach interrupt handler
FlexiTimer2::start();
}
void loop() {
lcd.clear();
lcd.print("dir=");lcd.print(heading);
lcd.setCursor (8,0);
lcd.print("p=");lcd.print(period);
lcd.setCursor (0,1);
lcd.print("V2=");lcd.print(V2);
lcd.setCursor (8,1);
lcd.print("V4=");lcd.print(V4);
delay(200);
}
It is completely Interrupt Driven (the main loop all it does is to display the readings), it handles smoothing of the analog values, it is a perfect base for I want to do next, which is to set the Arduino as a I2C slave device, connect it to the Raspberry and set up a high-level protocol for their communication.
But more on that next time!
Thanks for reading,
G.
PS
Using the NASA Masthead unit was a dog.
The analog values are not stable enough, they change along with the ambient temperature and the cup rotor only creates a single pulse per revolution. This is a low cost unit and it shows.
Nevertheless, if anyone is thinking of using it in a project, do drop a line, we might exchange notes!
Subscribe to:
Posts (Atom)