-
Par F6AGV le 7 Avril 2016 à 22:59
//#include <DHT.h>
#include <TinyGPS.h> // http://arduiniana.org/libraries/tinygpsplus/
#include <SD.h>
//SoftwareSerial SerialGPS(9,10); // RX, TX
TinyGPS gps; // create a TinyGPS object
//#define DHTPIN 3
//#define DHTTYPE DHT22
int chipSelect=4;
int LED=7;
unsigned long t1, fix_age;
float lat, lon, alti, vitesse;
int annee,fix,i;
byte c,mois, jour, seconde, minute, heure, centiemes;
String date ="";
void setup()
{
Serial.begin(9600);
Serial1.begin(9600); // GPS devices frequently operate at 4800 baud
Serial.println("Initialisation...");
pinMode(chipSelect, OUTPUT);
pinMode(5,OUTPUT);
pinMode(10,OUTPUT); // Carte Ethernet
digitalWrite(chipSelect,LOW);
digitalWrite(5,HIGH);
digitalWrite(10,HIGH); // désactiver Carte SD
pinMode(LED,OUTPUT);
if (!SD.begin(chipSelect)) Serial.println("Erreur carte SD"); else Serial.println("Carte presente");
t1=millis();
}
void loop()
{
while (Serial1.available()&&millis()-t1>4000)
{
c = Serial1.read();
Serial.write(c);
if (gps.encode(c)&&millis()-t1>5000) lireGPS(); // tempo pour lire une trame RMC
if (millis()-t1>6000) { // Attente du Fix
fix++;
Serial.println();
Serial.println("Attente du FIX... ");
Serial.print(6*fix); Serial.println(" s");
t1=millis();}
}
}
void lireGPS()
{
gps.f_get_position(&lat, &lon); // Fonction de la bibliothèque TinyGPS
gps.crack_datetime(&annee, &mois, &jour, &heure, &minute, &seconde, ¢iemes, &fix_age);
date =String(jour) + "/" + String(mois) + "/" + String(annee) + " "+ String (heure+1) + ":" + String (minute) + ":" + String (seconde);
Serial.println();
Serial.println(date);
Serial.print("Mesure ");Serial.println(i);
Serial.print("Latitude = ");Serial.println(lat,5);
Serial.print("Longitude = ");Serial.println(lon,5);
alti = gps.f_altitude(); // +/- altitude in meters
Serial.print("Altitude = ");Serial.print(alti,1);Serial.println(" m");
vitesse = gps.f_speed_mps();
Serial.print("Vitesse = ");Serial.print(vitesse,1);Serial.println(" m/s");
Serial.print(lat,5);Serial.print(",");Serial.println(lon,5);
Serial.println();
digitalWrite(LED,1);
if (i==0) entete();
ecritureSD();
digitalWrite(LED,0);
t1=millis();
i++;
fix=0;
}
void entete(){ // Pour utiliser Google table de fusion séparateur
File GPStab = SD.open("GPS_Tab.csv", FILE_WRITE);
if (GPStab) {
GPStab.print("date");
GPStab.print(";");
GPStab.print("latitude");
GPStab.print(";");
GPStab.print("longitude");
GPStab.print(";");
GPStab.print("Altitude");
GPStab.print(";");
GPStab.println("Mesure");
GPStab.close();
}
}
void ecritureSD() {
File GPStab = SD.open("GPS_Tab.csv", FILE_WRITE);
if (GPStab) {
GPStab.print(date);
GPStab.print(";");
GPStab.print(lat,5);
GPStab.print(";");
GPStab.print(lon,5);
GPStab.print(";");
GPStab.print(alti,1);
GPStab.print(";");
GPStab.println(i);
GPStab.close();
}
else {
Serial.print("Erreur GPS_Tab.csv");}
}---------------------------------------------------------------------------
Cette fois, c'est au tour du GPS, ce programme devrait permettre de le tester. Je ne l'ai pas encore programmé, mais
je vous le soumet pour le tester. Si vous voulez le fichier .ino pour ce programme ou pour les autres,
ainsi que les librairies, je peux vous les faire parvenir par mail, mais sans garantie si non testé.
J'aurai l'occasion de commenter dans un article, ce que vous pouvez récupérer avec votre GPS. En gros, vous pouvez
obtenir dans l'ordre :
la date, l'heure, la latitude, la longitude, et l'altitude.
Si votre GPS ne convient pas pour les vols sur un ballon haute altitude, l'indication d'altitude sera bloquée en vol, en
général vers 18 km.
Merci pour votre participation et vos commentaires.
Alain F6AGV - BHAF - f6agv (@) free.fr Ballons Haute Altitude France
votre commentaire -
Par F6AGV le 7 Avril 2016 à 22:34
/* test RTTY BEACON du module NTX2B
*/
//définir la pin de sortie vers NTX2B
#define RADIOPIN 9
//définir les bibliothèques
#include <string.h>
#include <util/crc16.h>
//définir la taille du texte à transmettre en balise
char datastring[80];
void setup(){
pinMode(RADIOPIN,OUTPUT);
Serial.begin(9600);
}
void loop(){
snprintf(datastring,80,"$$$$$F6AGV-11,RTTY,TEST,BEACON"); //placer le texte dans datastring
unsigned int CHECKSUM=gps_CRC16_checksum(datastring); //calcul du checksum pour ce texte
char checksum_str[6];
sprintf(checksum_str,"*%04X\n",CHECKSUM);
strcat(datastring,checksum_str);
rtty_txstring(datastring);
}
void rtty_txstring(char*string){
//envoyer des caractéres d'un octet de 8 bits (byte)
char c;
c=*string++;
while (c !='\0'){
rtty_txbyte(c);
c=*string++;
}
}
void rtty_txbyte(char c){
//envoyer chaque bit d'un caractére
//le LSB est transmit en premier
//chaque octet est précédé d'un zéro (start)
//chaque octet est suivi d'un ou deux un (stop)
int i;
rtty_txbit(0); //start bit
//envoyer les bits avec LSB en premier
for (i=0;i<7;i++) { //
if(c&1) rtty_txbit(1);
else rtty_txbit(0);
c = c>>1;
}
rtty_txbit(1); //stop bit
rtty_txbit(1); //stop bit
}
void rtty_txbit (int bit) {
if (bit) {
// high
analogWrite(RADIOPIN,110);
}
else {
// low
analogWrite(RADIOPIN,100);
}
delayMicroseconds(10000);
delayMicroseconds(10150);
/* pour 300 bauds (3370)
pour 50 bauds (20150)
*/
}
uint16_t gps_CRC16_checksum (char*string){
size_t i;
uint16_t crc;
uint8_t c;
crc = 0xFFFF;
//calcul du checksum les deux premiers $$ ne comptent pas
for(i=2; i <strlen(string);i++) {
c=string[i];
crc=_crc_xmodem_update (crc, c);
}
return crc;
}
------------------------------------------------------------
Petit commentaire : ce programme écrit par Anthony M0UPU, vous permettra de tester votre émetteur NTX2 ou NTX2B.
Ainsi que la réception du message "$$$$$F6AGV-11,TEST,RTTY,BEACON". Pour recevoir, cette émission, il vous faut
un récepteur UHF sur la bande 434 MHz en USB, une antenne verticale quart d'onde (ou 7 éléments pour recevoir des
émissions de ballons plus lointains). Il vous faut un ordinateur avec le logiciel DL-FLDIGI HAB ou normal.
Ce logiciel vous permet de recevoir d'autres modes numériques utilisés par les ballons haute altitude.
Je recommande une interface d'isolement entre le PC et le récepteur UHF. Si vous n'en avez pas encore, il suffit
d'alimenter le récepteur avec une batterie 12 volts. La configuration à placer sur DL-FLDIGI pour recevoir ces trames
de test en mode balise est RTTY ---> custom ---> 50 bauds 7 bits ascii none et 2 bits de stop.
Ce programme a été testé avec succès, si vous avez une erreur à cause d'une mauvaise librairie, je pourrai vous
faire parvenir les miennes qui sont dans le programme.
Merci pour votre participation et vos commentaires.
Alain F6AGV : f6agv (@) free.fr
votre commentaire -
Par F6AGV le 7 Avril 2016 à 22:15
#include <NewSoftSerial.h>
#include <TinyGPS.h>
#include <SD.h>
#include <OneWire.h>
#include <util/crc16.h>
//capteur de temperature
#define DS18B20 0x28
OneWire ds(5);
OneWire ds2(6);
int temperature_val_ext=0;
int temperature_val=0;
//GPS
TinyGPS gps;
NewSoftSerial mySerial(2, 3);
char msg[80];
int count = 1;
long lat, lon;
unsigned long time;
//carte memoire
File theFile;
//radio
char datastring[80];
#define RADIOPIN 8
//variable globale
int pression_val=0;
int altitude_val=0;
void setup()
{
Serial.begin(115200);
mySerial.begin(9600);
pinMode(10, OUTPUT);
if (!SD.begin(10))
{
Serial.println(" Card failed, or not present");
return;
}
pinMode(RADIOPIN,OUTPUT);
}
////////////////////////////////////////////////////////////////////////////////////////////RADIO
void rtty_txstring (char * string)
{
/* Simple function to sent a char at a time to
** rtty_txbyte function.
** NB Each char is one byte (8 Bits)
*/
char c;
c = *string++;
while ( c != '\0')
{
rtty_txbyte (c);
c = *string++;
}
}
void rtty_txbyte (char c)
{
/* Simple function to sent each bit of a char to
** rtty_txbit function.
** NB The bits are sent Least Significant Bit first
**
** All chars should be preceded with a 0 and
** proceded with a 1. 0 = Start bit; 1 = Stop bit
**
*/
int i;
rtty_txbit (0); // Start bit
// Send bits for for char LSB first
for (i=0;i<7;i++) // Change this here 7 or 8 for ASCII-7 / ASCII-8
{
if (c & 1) rtty_txbit(1);
else rtty_txbit(0);
c = c >> 1;
}
rtty_txbit (1); // Stop bit
rtty_txbit (1); // Stop bit
}
void rtty_txbit (int bit)
{
if (bit)
{
// high
digitalWrite(RADIOPIN, HIGH);
}
else
{
// low
digitalWrite(RADIOPIN, LOW);
}
// delayMicroseconds(3370); // 300 baud
delayMicroseconds(10000); // For 50 Baud uncomment this and the line below.
delayMicroseconds(10150); // You can't do 20150 it just doesn't work as the
// largest value that will produce an accurate delay is 16383
// See : http://arduino.cc/en/Reference/DelayMicroseconds
}
uint16_t gps_CRC16_checksum (char *string)
{
size_t i;
uint16_t crc;
uint8_t c;
crc = 0xFFFF;
// Calculate checksum ignoring the first two $s
for (i = 2; i < strlen(string); i++)
{
c = string[i];
crc = _crc_xmodem_update (crc, c);
}
return crc;
}
////////////////////////////////////////////////////////////////////////////////////////////TEMPERATURE
boolean getTemperature(int *temperature_val){
byte data[9], addr[8];
if (!ds.search(addr)) {
ds.reset_search();
return false;
}
if (OneWire::crc8(addr, 7) != addr[7])
return false;
if (addr[0] != DS18B20)
return false;
ds.reset();
ds.select(addr);
ds.write(0x44, 1);
delay(800);
ds.reset();
ds.select(addr);
ds.write(0xBE);
for (byte i = 0; i < 9; i++)
data[i] = ds.read();
// Calcul de la température en degré Celsius
*temperature_val = ((data[1] << 8) | data[0]) * 0.0625;
return true;
}
////////////////////////////////////////////////////////////////////////////////////////////TEMPERATURE EXTERIEUR
boolean getTemperature_ext(int *temperature_val_ext){
byte data[9], addr[8];
if (!ds2.search(addr)) {
ds2.reset_search();
return false;
}
if (OneWire::crc8(addr, 7) != addr[7])
return false;
if (addr[0] != DS18B20)
return false;
ds2.reset();
ds2.select(addr);
ds2.write(0x44, 1);
delay(800);
ds2.reset();
ds2.select(addr);
ds2.write(0xBE);
for (byte i = 0; i < 9; i++)
data[i] = ds2.read();
// Calcul de la température en degrée Celsius
*temperature_val_ext = ((data[1] << 8) | data[0]) * 0.0625;
return true;
}
////////////////////////////////////////////////////////////////////////////////////////////CARTE MEMOIRE
void sd(int temperature_val,int temperature_val_ext, int altitude_val, int pression_val, long lat, long lon, long altGPS)
{
File theFile = SD.open("fichier.txt", FILE_WRITE);
theFile.print(lat);
theFile.print(" ");
theFile.print(lon);
theFile.print(" ");
theFile.print(altGPS);
theFile.print(" ");
theFile.print(pression_val);
theFile.print(" ");
theFile.print(altitude_val);
theFile.print(" ");
theFile.print(temperature_val);
theFile.print(" ");
theFile.println(temperature_val_ext);
theFile.close();
Serial.println("carte sd ecrit !");
}
////////////////////////////////////////////////////////////////////////////////////////////PRESSION
float pression()
{
int val = analogRead(0);
float tension = ((val-10)*0.0049);
// Calcul de la pression réel
int pression_val = (100.1-(((tension/5)-0.04) / 0.009))*10;
return pression_val;
}
////////////////////////////////////////////////////////////////////////////////////////////ALTITUDE
int getAltitude(long pression_val)
{
pression_val=pression_val/0.01;
// Pression au niveau de la mer (Pa)
const float p0 = 101325;
int altitude = (float)44330 * (1 - pow(((float) pression_val/p0), 0.190295))+230;
return altitude;
}
////////////////////////////////////////////////////////////////////////////////////////////GPS
void GPS(){
if (mySerial.available()) {
if(!gps.encode(mySerial.read())) return;
gps.get_position(&lat, &lon, NULL);
gps.get_datetime(NULL, &time, NULL);
snprintf(msg, 80,
"heure : %02li:%02li:%02li lat/lon : %s%li.%05li,%s%li.%05li altitude : %li",
time / 1000000, time / 10000 % 100, time / 100 % 100,
(lat >= 0 ? "" : "-"), labs(lat / 100000), labs(lat % 100000),
(lon >= 0 ? "" : "-"), labs(lon / 100000), labs(lon % 100000),
gps.altitude() / 100
);
Serial.println(msg);
delay(1000);
}
}
////////////////////////////////////////////////////////////////////////////////////////////LOOP
void loop()
{
for (unsigned long start = millis(); millis() - start < 1000;)
GPS();
pression_val=pression();
Serial.print("pression = ");
Serial.println(pression_val);
altitude_val=getAltitude(pression_val);
Serial.print("altitude = ");
Serial.println(altitude_val);
getTemperature(&temperature_val);
Serial.print("Temperature : ");
Serial.println(temperature_val);
getTemperature_ext(&temperature_val_ext);
Serial.print("Temperature exterieur : ");
Serial.println(temperature_val_ext);
sd(temperature_val,temperature_val_ext, altitude_val, pression_val, lat, lon, gps.altitude());
noInterrupts();
snprintf(datastring, 250,
"T : %02li:%02li:%02li lat/lon : %s%li.%05li,%s%li.%05li altGPS : %li P = %dHpa alt = %dm temp = %d tempext = %d",
time / 1000000, time / 10000 % 100, time / 100 % 100,
(lat >= 0 ? "" : "-"), labs(lat / 100000), labs(lat % 100000),
(lon >= 0 ? "" : "-"), labs(lon / 100000), labs(lon % 100000),
gps.altitude() / 100,
pression_val,
altitude_val,
temperature_val,
temperature_val_ext
);
unsigned int CHECKSUM = gps_CRC16_checksum(datastring);
char checksum_str[6];
sprintf(checksum_str, "\n", CHECKSUM);
strcat(datastring,checksum_str);
rtty_txstring (datastring);
interrupts();
delay(5000);
asm volatile (" jmp 0");
}
-----------------------------------------------------------------------------------Ce programme semble complet pour un vol de ballon, mais je ne l'ai pas encore testé !
Je vous le livre quand même, et si vous pouvez le faire fonctionner sur un Arduino Uno ou un Méga,
je serai très intéressé ainsi que les lecteurs de savoir si il fonctionne et quelques remarques.
Merci pour votre participation.
Alain F6AGV - BHAF - Ballons Haute Altitude France - 7 avril 2016
votre commentaire -
Par F6AGV le 14 Octobre 2014 à 14:15
Cet écran graphique est fourni par le logiciel Sonde Monitor. (Cliquez dans la barre en haut).
La courbe en bleu représente la variation de la pression atmosphérique, avec la montée (10, 1, 3),
ensuite vient l'éclatement de l'enveloppe (3) et enfin la descente sous parachute (3, 2, 20).
Attention, l'échelle est inversée. A l'éclatement (burst) la pression est au minimum (ici 16,2 hPa).
Certains montages de capteur de pression inverse la tension de sortie. On dira que la sortie est
normale ou inversée.
La courbe marron (ou brun) représente les variations de la température de l'air pendant le vol.
On distingue, trois parties :
(10, 1) la montée.
(1, 2) une période de fluctuations de température, autour d'une valeur moyenne. On dira que cette température
ne varie pas, dans certaine publication et parfois même, qu'elle est constante. (ici moyenne autour de -52°C).
(2, 20) la descente. En principe à la montée et à la descente, les données ne changent pas. Mais en toute rigueur
la radiosonde s'est déplacée et les valeurs changent constamment, y compris pour un même point.
Les météorologues ne considèrent que les données à la montée en principe, bien que les radiosondes mesurent
toutes les valeurs depuis le décollage jusque l'atterrissage.
Parfois, la radiosonde arrête d'émettre ses données au cours de la descente. Parfois les enveloppes éclatent
à des altitudes légèrement au dessus de 12000 mètres car elles sont d'une capacité réduit en volume.
La trace rouge/orange est la courbe de l'humidité relative en %. On remarque qu'au dessus d'une certaine valeur
de l'altitude, ce paramètre Hu % est nul : l'air est sec.
Le graphe ci-dessus est obtenu à partir de quelques points, température en (x) et altitude en (y).
On remarque tout de suite que la partie de la courbe entre 0 et 10000 mètres est linéaire.
De 10000 mètres jusqu'à l'altitude d'éclatement (27852 m) on admettra que la température reste
constante à - 53 °C environ. (fluctuations).
Il serait intéressant de connaitre l'équation de la droite : altitude = f ( température ).
Et son inverse : température = g ( altitude ).
Attention, les paramètres changent et la détermination de l'altitude doit se faire à partir de la pression.
A partir des points connus, on établit l'équation : température = -0,007 . altitude + 19,3
Z en mètres et T en ° C.
On peut retenir que pour une montée de 1000 m, la température diminue de 7 °C.
L'équation inversée est :
altitude = -141,65 . température + 2768,6
Remarque : voir sur les courbes de température, à proximité du sol, celle ci n'est plus conforme
à l'équation. Sur les graphes ci-dessus elle est plus faible au voisinage du sol !
Le fichier EXCEL est disponible sur demande ainsi que le fichier du vol du 14 octobre 0Z.
Source : GITE - BHAF
Auteur : F6AGV
votre commentaire -
Par F6AGV le 4 Octobre 2014 à 18:33
Les équations de ces courbes sont :
bleu : vitesse = 21.538 . e ^ 0.00007 * altitude
rose : vitesse = 4.9496 . e ^ 0.00007 * altitude
jaune : vitesse = 2.6173 . e ^ 0.00009 * altitude
Avec l'altitude exprimée en mètres, et la vitesse en m/s
Remarques :
Quand le parachute est absent ou défaillant, la vitesse de chute est grande de l'ordre de -150 m/s.
La vitesse au final est de l'ordre de -20 m/s si les conditions ne changent pas.
Les courbes rose et jaune sont voisines. Peu de différence de vitesse finale entre un parachute parfait
et presque parfait. Les conditions d'ouvertures peuvent changer en cours de descente !
SOURCE : GITE-BHAF
AUTEUR : F6AGV
MAIL : f6agv (AT) free.fr
votre commentaire -
Par F6AGV le 4 Octobre 2014 à 16:50
Les vitesses de descente avec le parachute sont rapide, moyenne et normale.
Nous allons comparer les données de trois vols :
Herstmonceux le 1 octobre 2014 0Z
Herstmonceux le 2 octobre 2014 0Z
Herstmonceux le 2 octobre 2014 12Z
Les graphiques suivent cet ordre.
1-ALTITUDE et PRESSION ATMOSPHERIQUE : alt = f ( p )
Le 1 octobre 0Z : y = -6495,2 ln (x) + 46005
Le 2 octobre 0Z : y = -6580 ln (x) + 46263
Le 2 octobre 12Z : y = -6614,6 ln (x) + 46399
Notation : alt = A . ln ( p ) + B
2- VITESSE DE DESCENTE ET ALTITUDE :
Lire le graphe en partant du point à droite localisé après l'éclatement de l'enveloppe : 27000 m et vitesse nulle.
Ensuite il y a une chute libre, avec une vitesse au alentour de -160 m/s. La vitesse est comptée comme
négative pendant la période de descente. Vers 16500 m, la descente se poursuit avec un freinage : ouverture
du parachute ? Fin de descente rapide vers -20 m/s !
La même courbe mais inversée en comptant les vitesses de descente comme positives.
Il y avait des données manquantes à la transmission, aussi les traits rouges complètent le tracé.
On va donner l'équation de la partie comprise entre 16500 m et 0 m.
Cette fois, avec la Radiosonde du 2 octobre 2014, la descente est moins rapide que précédemment.
Après l'éclatement (burst), il y a la chute libre moins rapide mais plus courte en temps. On assiste à
une ouverture du parachute vers les 25000 mètres de plus en plus complète avec l'augmentation de la densité
de l'air pendant la descente. Fin de descente à la vitesse d'environ 5 m/s :
Le 2 octobre à 12Z, le parachute a fonctionné parfaitement car dans sa configuration normale.
Avec les vitesse négatives :
Cette fois, le parachute s'ouvre en fin de chute libre vers -32 m/s. La vitesse se réduit progressivement
jusqu'au sol avec une valeur de -2,7 m/s, qui sera considérée comme "normale".
Le 1 octobre 0Z : y = 21,538 . e ^ 7. 10-5 x
Le 2 octobre 0Z : y = 4,9496. e ^ 7. 10-5 x
Le 2 octobre 12Z : y = 2,6173. e ^ 9. 10-5 x
Notation : vitesse = vitesse finale . e ^ K . (altitude)
3- TEMPERATURE DE L'AIR ET ALTITUDE :
Le 1 octobre 2014 0Z :
Sur ce graphe, on remarque que la température varie linéairement de 12000 m jusqu'au sol.
12000 m : -60 °C
0 m : +8 °C
Soit environ 5,666 °C par 1000 mètres.
De 12000 m à 15000 m on remarque un palier vers - 60°C et ensuite la température diminue à l'éclatement.
Attention la courbe doit être lue du point d'éclatement vers le point au sol, car c'est la descente sous parachute.
A la montée, on aurait sensiblement le même profil mais les mesures de se prennent pas aux mêmes points.
Mais on constatera un tracé sous forme de W !
Le 2 octobre 2014 0Z :
Le 2 octobre 2014 à 12Z :
A suivre,
SOURCE : GITE-BHAF
AUTEUR : F6AGV
CONTACT : f6agv (AT) free.fr
votre commentaire
Suivre le flux RSS des articles de cette rubrique
Suivre le flux RSS des commentaires de cette rubrique