In recent months I’ve been busy on a project I’m doing with some friends: launch a weather balloon into the stratosphere (over 38km of altutudine).
Although is not a new project in the world, and even in Italy (see the project Stratospera), we believe there is new compared to other similar projects.
First of all, the project is entirely open source, both for hardware than for the software: each aspect it will come out, will be published on the official website.
In secondo luogo, il “computer di bordo”, è realizzato interamente con Arduino, che si occuperà quindi della gestione della posizione, dei dati meteorologici, del datalogging, di una parte di comunicazione, e della gestione del “cut-off” di emergenza. Android si occuperà prevalentemente invece della gestione della posizione e dell’invio tramite rete cellulare dei dati in tempo reale (ovviamente quando sarà sotto copertura di rete, cioè realisticamente fino a 5-6km di altitudine).
As the tird innovation, there is in preparation, not from the first launch of course, the possibility of recovering the payload (containing all the electronic equipment), via a glider drone, which should autonomously bring everything to the point of launch…
From the point of view of the feasibility study we have finished, while now we are focusing on the Arduino software, and we are proceeding with the request of various authorizations, as well as to raise funds for various expenses …
We are also looking for people willing to contribute to the project, not only economically but also humanly to the project.
In addition, if some company wants to sponsor us with material that can be used in the project, we will be happy.
I will keep you updated!
And now another interesting little project.
After seeing various online projects, especially based on the PIC microcontroller, I decided to make a charger for NiMH batteries driven by an ATtiny85.
Why we need a microcontroller to manage charging a battery? The answer is very simple … The most economic charger that on the market, regulate the charge based on a timer, that is if I charge a 2500mAh battery for example, they provide a charging current of 250mAh, keeping the charge for eg 14 hours (a part of the energy will be lost, so 10 hours would not be enough).
This way of charging NiMh or NiCd batteries is not very functional. It is a slow process, and does not guarantee a 100% accurate cell charge, as well as increasing the risk of overload.
“Smart” chargers however, charge batteries correctly, but besides being quite expensive, their usually charge current is not very high, leading to charging times still quite long.
So in addition to the curiosity and the desire to create something of my own, this project was born …
But lets proceed with order, starting with a video showing the finished running project:
Let us now try to understand the operating principle.
First nickel batteries require a constant current to be charged properly. So we used a transistor-based constant current source, derived from what we saw in a previous post, and so far nothing special, but how do we know when the battery is fully charged?
We need to constantly read the voltage of the battery being charged, and when there will be a maximum peak voltage followed by a sudden drop of about 20mV, the battery may be considered charged. This phenomenon (called Negative Delta V) is related to the chemistry of this type of battery, and allows to establish precisely the right moment to terminate charging.
Thus we see the circuit diagram:
The schematic is pretty simple. The darlington transistor Q1 (TIP127), through LED1 (which must be absolutely RED) and the resistance R3 from 0.3 Ω, creates a constant current flowing in the direction of the 6-cell battery (7.2V), while the Schottky diode 1N5822, serves to protect the entire circuit in the case that is lacking the input voltage with the battery connected. The voltage divider R4-R5, serves to bring to port 7 of the ATtiny (A1) the battery voltage decreased to about 1/3, in such a way that it can operate with voltages up to 15V (the analog input of the ATtiny can not exceed 5V). The transistor Q2, driven by the port 5 of the ATtiny (D0), serves as a switch to enable or disable the LED-1 and the transistor Q1. It’s really important that LED1 is RED, and this is not a matter of aesthetics, but because the power output is given by the ratio between the voltage of the LED (the red LED is about 1.8 to 2.2 V) and resistance R3. Using a green LED, the reference voltage is raised, and consequently also the current rises (and not just a little bit).
The circuit above, can deliver about 1.5-2.5 A: you may have to do some testing with various types of red LED, or vary the resistance, which must be at least 2W. If you can not find resistance with so low values, you can use 3 or 4 1Ω resistors in parallel.
Another thing to remember, is the power dissipated by the TIP127, which can be up to 20 watt (depending on the current and the voltage difference between the input and the battery), then a heat sink need to be mounted properly. In my case was enough to use the aluminum enclosure.
Last note is the input voltage, which must not be too high otherwise you risk to burn the transistor, but must not be even too low, because otherwise the dropout induced by the various components makes too low the charging current. Can fit approximately a difference of about 5V between the input voltage and the nominal value of the battery. For example, with 6-cell a voltage of 12.2 V is recommended (maybe 12). Of course you can also charge less cells, by suitably adjusting the input voltage. For a cell, we should feed the device with a voltage of about 1.2 + 5 = 6.2 V (maybe 6 or 7).
Let us consider now the printed circuit board:
Note the two gems that were not visible in the schematic. The ICSP connector (ie the ability to update the firmware on the ATtiny – via UsbTinyISP programmer for example – and the debug connector, to be connected to a TTL converter in order to read the battery voltage during charging.
The J1 connector is a jumper that must be closed at all times, except when updating the firmware of Attiny85.
About firmware … The source code is as follows:
/*
NiMh Charger 0.9
with AtTiny85 @ 1Mhz
by Luca Soltoggio
10/03/2012 - 20/04/2012
Use negative deltaV to determine end of charge.
Suitable for NiMh and NiCD battery pack.
Default is for 6 cells 2500mAh.
Need some hardware/software adjustment for changing current / cells number
See http://arduinoelettronica.wordpress.com/
*/
const int inputPin = A1;
const int outputPin = 0;
const int numReadings = 30; // number of analog read before checking battery status
const int multi = 1614; // multi coefficent for obtaining millivolts from analogread
long interval = 1000; // interval for pulse charging and analog read - don't change this
long interval2 = 250; // pulse off interval - you can adjust power with this. Use 100 for 2-4Ah battery packs, 500 for 1-2Ah battery pack
long interval2b=interval2;
long previousMillis,currentMillis,currentMillis2,trickleMillis = 0;
unsigned int readingtemp;
unsigned int total = 0;
unsigned int average,medium,maxmedium = 0;
boolean executed,endcharge,trickle=false; // booleans for controlling various activities (for example "end of charge")
unsigned int myarray [7]; // array for keeping last 7 readings
int index,i = 0;
void setup()
{
Serial.begin(9600);
pinMode(0,OUTPUT);
// Some readings for initial check
for (i=0;i<10;i++) {
readingtemp = analogRead(inputPin);
total=total+readingtemp;
}
average = (((float)total / 1023.0) * (float)multi) / 10.0 + 0.5;
if (average<=70) endcharge=true; // If there is no battery, end charge
Serial.println(average);
total=0;
average=0;
}
void pusharray() {
// push the array
for (i=0;i<=5;++i) {
myarray[i]=myarray[i+1];
}
myarray[6]=average;
}
void voltread() {
readingtemp = analogRead(inputPin); // read analog input
total= total + readingtemp;
index++;
// if numReadings reached, calculate the average
if (index==numReadings) {
index=0;
average = (((float)total / 1023.0) * (float)multi) / numReadings + 0.5;
if (average<=70) endcharge=true; // stop charge if battery is detached
total=0;
pusharray(); // insert new average in array
medium=(float)(myarray[6]+myarray[5]+myarray[4]+myarray[3]+myarray[2]+myarray[1]+myarray[0])/7.0+0.5; // calculate the average of the last 7 readings
if (medium>maxmedium) maxmedium=medium; // save the value of highest medium in "maxmedium"
Serial.print(medium);
Serial.print(",");
Serial.print(maxmedium);
Serial.print(",");
Serial.println(myarray[6]);
if ( ((medium+1) < maxmedium) && ((millis()/60000)>=11) ) { // if battery charged (average voltage is dropped 0.02v), but not in the firsts 11 mintues
if (!trickle) trickleMillis=millis(); // start trickle timer
trickle=true; // enter final trickle charging mode
if ((millis()/60000)<=15) endcharge=true; // if battery is charged in the firts 15 minutes, don't apply trickle charge (maybe was yet charged)
}
}
}
void loop() {
currentMillis = millis();
// executed every "interval" millis
if(currentMillis - previousMillis > interval) {
voltread(); // call reading and check volts function
digitalWrite(outputPin,LOW); // temporaly stop charging
previousMillis = currentMillis;
executed=false; // boolean for setting and checking if has been yet turned ON charge
// in the firsts 10 minutes and in the endings 15 minutes do a trickle charge (change OFF interval)
if ( ( (trickle) && (((millis()-trickleMillis)/60000)<15) ) || ((millis()/60000)<10) ) {
interval2=(interval-(interval-interval2b)/5);
} else if ((millis()/60000)>=10) interval2=interval2b; // after initial trickle charghe set back right time
if ( (trickle) && (((millis()-trickleMillis)/60000)>=15) ) endcharge=true; // if final trickle charge end, end charge
}
currentMillis2 = millis();
// executed "interval2" millis after turning OFF charge
if ((currentMillis2 - previousMillis > interval2) && (!executed)) {
executed=true;
if (!endcharge) {
digitalWrite(outputPin,HIGH); // if battery is not charged, re-enable charging
}
}
}
The code is pretty simple and self-explanatory.
I conclude with a few pictures of the finished project:
Finally after a long absence, in which I was immersed in the final realization of this project, I did it!
After months of planning, studies, research and other obstacles, the RGB LED Lamp 1.0 by Toggio is reality.
Here’s the video showing the final result obtained:
And now a brief history.
One of the things that attracted me the most when I first heard of Arduino, was light, and in particular I have always dreamed of achieving an LED lamp RGB.
Nothing difficult, you might think … Except that along this route I found several obstacles.
First of all, I did not find complete projects on the net … There is something, but, in my opinion, with bad algorithms, with little explanation or with complicated methods.
I wanted a simple present to give to the person who I love and that gave me a beautiful daughter …
I wanted something that had a powerful enough light, without too much heat. I wanted something that had a chance to choose the color and not a simple “color cycler.” I wanted something that would serve also as a standard lamp. And finally, I wanted something that was modular and upgradeable in the future.
After these reflections, I began to study the hardware first. I did not want to use the Arduino UNO because it seemed too big for my project. So I decided (and this could open up a huge parentheses) to use a board not so common, but in my opinion awesome (so much that I bought 4 or 5 piece): The Arduino Mini Pro.
(It is understood that in the project of this post, it can easily be replaced by an Arduino UNO or any other board.)
It ‘a very small board (18mm x 33mm), 100% compatible with Arduino Dumilanove, and low power consumption. It is available in four versions: with Atmega328 or with ATmega168, both with 3.3V or 5V.
So I opted in this project for the 5V version with ATmega168. In short it is a very economic solution (it costs about half of the Arduino UNO), very compact and beautiful to see.
I then thought of using the useful LED RGB strips, which offer many advantages over using 1W or 3W power LEDs: they do not heat up, they are powered with 12V and they offer a power up to 13-14W per meter.
Each channel can be powered by a PWM output of the Arduino using a simple transistor (in my case I used the BC337, but for higher power you can use other transistor, or even the MOSFET).
I then proceeded to build a kind of shield for my board. Practically I made a circuit in which the Arduino Pro Mini would fit with strip connectors and with the ability to be removed to upgrade the firmware. Everything has been designed with Fritzing and built by Fritzing Fab.
The final result of the printed circuit is as follows:
You can see the two rows of holes where the Mini Pro will be mounted… Basically, it’s the opposite of a shield 🙂
But let’s step back and see the circuit schematic:
I hope it is clear enough even if I have not drawn just fine!
In any case, the operation principle is as follows: The two 10k potentiometers connected between +5 V and ground, are the two analog inputs that allow to adjust the brightness and other parameters set by the software. The 3-position switch SW2 allows you to select three different functions for the lamp. The digital outputs 3,5,6 go through a resistor to drive the 3 BC337 transistors that will give negative voltage to the 3 channels (R, G, B) of the LED strip. The common positive goes to +12 V, while the Arduino is powered by RAW port (input from 7V to 13V) via a diode that in addition to providing reverse polarity protection, slightly lowers the voltage. SW1 is simply the bridge where will be connected a standard power switch.
Once soldered the components, connectors, potentiometers, mounted the circuit, encapsulated the Arduino board, and assembled it all in a electrician box, the result is as in the following picture:
The size of the box is approximately 10cmx10cmx7cm.
For the top, I used about 70cm of RGB led strip, for a total power of about 10W. To fit the whole strip I rolled it around the support of a “50 CD-R set”. I cut with a utility knife and I glued all with spacers on the box. I then glued with hot glue the wrapping strip led… In short, the job is a little rough but the end result is as follows:
The glass you see on the desk, is the final piece: the glass cover of a IKEA lamp, properly cut by a local glazier, so that it remains empty on both sides. This coverage will finally resting on the box and glued, obtaining the following results:
Not bad right?
Of course there is still the icing on the cake, a not less important part: the software.
The self-explanatory code is as follows:
/*
RGB Led Lamp 1.0a
by Luca Soltoggio
15/03/2012
http://arduinoelettronica.wordpress.com/
*/
int rpin = 3; // red pin
int gpin = 5; // green pin
int bpin = 6; // blue pin
unsigned int r=0, g=0, b=0,bm=0; // r,g,b, value and blue coefficient
unsigned int valh=0, vals=0, valv=0; // hue, saturation, value
unsigned int sensorValue; // analog sensor value
const int analogInPin = A0; // potentiometer pins
const int analogInPin2 = A1;
const int digitalInPin = 10; // switch pins
const int digitalInPin2= 11;
int red[]={255,255,135}; // predefined arrays for RGB / White
int green[]={157,255,158};
int blue[]={51,255,255};
boolean DIG1, DIG2;
long previousMillis = 0;
int i=0,j=0;
int dl=0; // delay
void setup()
{
pinMode(digitalInPin,INPUT);
pinMode(digitalInPin2,INPUT);
}
void loop()
{
DIG1=digitalRead(digitalInPin);
DIG2=digitalRead(digitalInPin2);
if (DIG1) {
bm=1.1;
HSV_Game();
}
else if (DIG2) {
bm=1.9;
RAINBOW_Game();
}
else {
bm=2.4;
LIGHT_Game();
}
analogWrite(rpin, r/1.09); // write RED PIN
analogWrite(gpin, g/1); // write GREEN PIN
analogWrite(bpin, b/bm); // write BLUE PIN
}
// analog input smoothing function
int SensorSmooth (int pin) {
sensorValue=0;
for (int i = 0; i<10; i++) {
sensorValue+= analogRead(pin);
}
return int ((float)sensorValue/10+0.5);
}
// first light game: modify HUE and VALUE with potentiometer
void HSV_Game() {
valh = SensorSmooth(analogInPin);
vals = 255;
valv = SensorSmooth(analogInPin2);
valh = map(valh,0,1023,0,359);
valv = map(valv,0,1023,32,255);
hsv2rgb(valh,vals,valv,r,g,b);
}
// second light game: three positions for Warm White, White and Cold White
void LIGHT_Game() {
valv = SensorSmooth(analogInPin2);
valv = map(valv,0,1023,16,255);
valh = SensorSmooth(analogInPin);
if (valh<=281) valh=0;
if (valh>=742) valh=2;
if (valh>2) valh=1;
r=red[valh]*valv/255;
g=green[valh]*valv/255;
b=blue[valh]*valv/255;
}
// color cycler
void RAINBOW_Game() {
dl = SensorSmooth(analogInPin); // delay time
dl = map(dl,0,1023,1,100);
valv = SensorSmooth(analogInPin2);
valv = map(valv,0,1023,64,255);
unsigned long currentMillis = millis();
switch (j) {
case 0:
r=255*valv/255;
g=i*valv/255;
b=0*valv/255;
break;
case 1:
r=(255-i)*valv/255;
g=255*valv/255;
b=0*valv/255;
break;
case 2:
r=0*valv/255;
g=255*valv/255;
b=i*valv/255;
break;
case 3:
r=0*valv/255;
g=(255-i)*valv/255;
b=255*valv/255;
break;
case 4:
r=i*valv/255;
g=0*valv/255;
b=255*valv/255;
break;
case 5:
r=255*valv/255;
g=0*valv/255;
b=(255-i)*valv/255;
}
if (currentMillis-previousMillis > (long)(100-dl)) { // use millis instead of delay
previousMillis=currentMillis;
i=i+1;
if (i==256) {
i=1;
j=j+1;
if (j==6) j=0;
}
}
}
/* HSV2RGB function
(c) Elco Jacobs, E-atelier Industrial Design TU/e, July 2011
http://code.google.com/p/shiftpwm/source/browse/trunk/examples/ShiftPWM_Example1/hsv2rgb.cpp?r=3
*/
void hsv2rgb(int hue, int sat, int val, unsigned int& r, unsigned int& g, unsigned int& b)
{
int H_accent = hue/60;
int bottom = ((255 - sat) * val)>>8;
int top = val;
int rising = ((top-bottom) *(hue%60 ) ) / 60 + bottom;
int falling = ((top-bottom) *(60-hue%60) ) / 60 + bottom;
switch(H_accent) {
case 0:
r = top;
g = rising;
b = bottom;
break;
case 1:
r = falling;
g = top;
b = bottom;
break;
case 2:
r = bottom;
g = top;
b = rising;
break;
case 3:
r = bottom;
g = falling;
b = top;
break;
case 4:
r = rising;
g = bottom;
b = top;
break;
case 5:
r = top;
g = bottom;
b = falling;
break;
}
}
Here is a simple solar tracker, made with Arduino …
It ‘s just a draft, a starting point to be improved for building new projects.
The idea is very simple. Using two photoresistors (LDRs), one pointing slightly to the right and the other slightly to the left, let’s read the values and move a continuous rotation servo in the direction of the photoresistor receiving more light, until the brightness is about the same on both LDRs.
The end result is what we see in the following video:
As you can see I used Arduino Mini Pro, but nothing change using Arduino UNO. The only difference is that feeding the Arduino Pro Mini I had to use an external regulator, because the inside is not enough to drive the servo.
But let’s get to the list of materials needed:
1 – An Arduino UNO board (or any other compatible)
2 – Two 20K LDR photoresistors (with a few adjustments may also fit other values)
3 – Two 4.7K resistors (with different lighting conditions you can use different values)
4 – A continuous rotation servo. (Difficult and/or expensive to find, so I modified a standard servo following the directions found at this link
5 – One 9V battery, a breadboard, plastic holders and little else
The components must be connected to Arduino as follows:
/*
ISArduino 0.1
Arduino Solar Tracker
by Luca Soltoggio - 2012
http://arduinoelettronica.wordpress.com
*/
#include <Servo.h>
#include <Narcoleptic.h>
/*
A library that allows to put the microcontroller in standby
while in idle (delay), saving lot of energy.
You can safely remove it (but in this case you have to replace
the last staement Narcoleptic.delay(15) with delay(15).
*/
Servo myservo;
int Value;
int Center=105;
/*
The variable Center represents the centering value of the servo.
In my case it is 105, while usually it is 90.
With this value, the servo must stop running.
*/
void setup() {
Serial.begin(9600);
myservo.attach(9); // Attach servo to PIN 9
}
void loop() {
int sensorValue = analogRead(A0); // Read left LDR value
int sensorValue2 = analogRead(A1); // Read left LDR value
Value=(sensorValue-sensorValue2)/10;
/*
Compute the differnce between the two sensors
*/
if (Value==0) myservo.detach(); else myservo.attach(9);
/*
Detach servo if idle (for energy saving)
*/
if (Value>10) Value=10;
if (Value<-10) Value=-10;
/*
Limits the maximum difference between -10 and + 10
(in order to avoid an excessive speed)
*/
Serial.println(Value); // Debug
myservo.write(Center+Value);
/*
If "Value" is positive, move the servo to right, else to left
The speed is directly proportional to the absolute value of "Value"
*/
Narcoleptic.delay(15);
/*
Rather than using a simple delay, we use this to save energy
You can eventually replace with delay(15)
*/
}