GOTO pour monture équatoriale
ATmega32 + LINUX
pour télescope 114x900 ou lunette astronomique

Nécessite une monture équatoriale ayant les deux mouvements RA et DEC équipés de vis sans fin sur roue dentée. ( et non pas une vis + butée sur la déclinaison comme en en trouve sur certaines montures bon marché).
  • Montage unique pilotant le moteur d'ascension droite ET celui de déclinaison (moteurs pas-à-pas).
  • Avec affichage des 2 infos sur le même afficheur, LCD 4 lignes de 20 caractères, rétro-éclairé (bleu).
  • Compensation de la rotation terrestre (suivi en ascension droite).
  • Vitesses lentes (par moteur pas à pas) et rapides (par moteur DC démultiplié), avec embrayage automatique.
  • Montage basé sur un microcontrôleur AVR ATmega32 programmé directement en C (avec KontrollerLab sous LINUX), tournant à 16MHz.
  • Pilotage à distance avec une simple télécommande TV universelle.
  • Fonction GOTO.
  • Positions de 1000 étoiles de référence mémorisées dans un fichier texte dans une carte mémoire SD-card.
  • Le montage (carte ATmega de commande des moteurs et affichages + télécommande IR) peut fonctionner SANS l'ordi, d'une manière autonome.
  • Montage évolutif puisque les ATmega sont des uContrôleurs flash reprogrammables.
Cette réalisation est la suite logique de l'APE2002 ... APE2007 L'utilisation d'un ATmega32 permet de tout faire avec un seul microcontrôleur, ce qui simplifie grandement la réalisation, la mise au point, la complexité de l'électronique et l'évolution de l'ensemble. La programmation en langage C, par rapport à l'assembleur, devient un réel plaisir. Le temps d'étude et réalisation et divisé par dix! Les précédentes versions étaient programmées respectivement en assembleur AVR puis en Pascal sous Window$

Cette version est basée sur des logiciels LIBRES, sous LINUX.

1 Evolution:

Septembre 2009:
L'APE2009 remplace l'APE2008
La principale différence est que l'APE2009 est entièrement basé sur l'OS libre LINUX
Les softs seront programmés sous Linux, pour Linux.
Le programme PC associé permettant de visualiser les catalogues d'objets astronomiques et de les charger dans l'APE a été ré-écrit avec Lazarus sous Linux Ubuntu.
Le firmware est écrit en langage C sous KontrolleurLab, sous Linux (Ubuntu 9.04)

18 Octobre 2009:
Depuis la version 4.1 l'APE2009 lit directement les données (noms, numéros et coordonnées des objets célestes sur une carte mémoire SD-CARD)
( Un grand merci à CC Dharmani pour la partie interface SD-card (voir liens externes))

24 novembre 2009:
Le soft côté PC est désormais programmé en C++ et Qt4 pour LINUX avec qdevelop pour LINUX.

2 LA MISE AU POINT

On aperçoit en haut au centre le programmateur USB.

En haut à droite, c'est le récepteur IR à ATmega8 qui ne servira plus.

En bas à droite, l'alimentation 5V à découpage. (Voir sa description sur ma page de l'APE2007).

3 LA REALISATION

Le petit rectangle noir sur la photo, juste à gauche de l'ATmega32, c'est le récepteur Infra-rouge.

4 -

L'ensemble du boitier électronique et de la mécanique avec ses deux moteurs pas à pas et son moteur DC adaptés sur la monture équatoriale d'une lunette 120x600.

La partie mécanique est décrite plus bas sur cette page.

L'ensemble est piloté avec une télécommande IR universelle.

5 PRINCIPE

Tout d'abord je vous invite à consulter les articles suivants sur Wikipédia si vous n'êtes pas familiarisés avec toutes ces notions utilisées par l'APE2009: Ensuite vous trouverez des explications dans les commentaires du code source en C du firmware de l'ATmega32
(le fichier ape2009.c est un fichier au format texte qui s'ouvre avec n'importe quel éditeur de texte, comme gedit, edit etc...)

Voir aussi:
Ensuite vous trouverez des explications dans les commentaires du code source en C du firmware de l'ATmega32 (le fichier ape2009.c est un fichier au format texte qui s'ouvre avec n'importe quel éditeur de texte, comme gedit, edit etc...) Voir aussi les liens externes en bas de page.

6 Le programme

Ce soft permet en quelques clics d'importer des objets depuis les catalogues d'objets astronomiques (BSC5 soit 9100 étoiles et SAC soit 11000 objets du ciel profond, nébuleuses et galaxies...), de les gérer et de les enregistrer dans une SDcard.

On a ainsi accès à des catalogues de plusieurs dizaines de milliers d'étoiles et d'objets.

Une "petite" SDcard de 1Go permet de mémoriser des milliers d'objets ce qui devrait être suffisant pour une séance d'observation en utilisation autonome! (On a pas toujours envie de promener son ordi portable la nuit dans la nature ) ; toutefois, avec le Raspberry Pi, d'autre possibilités s'offrent à nous maintenant (en 2020).

11 oct 2020 :
J'ai en effet publié cet article en 2009, et en une dizaine d'année la technique à énormément évoluée. Je parlais ci-dessus d'une carte de 1Go, et à l'époque 4GB était la "norme". Actuellement on trouve plutôt des SDcards de 256 Go et plus !

7 -

Dessin du ciel en projection "orthographique", généré automatiquement à partir de la liste des objets. Rotations et zoom fonctionnels, le tout programmé en langage Qt4 et C++.

Je fournis les sources commentées et l'exécutable pour Linux (voir plus bas). Idéal pour débuter avec C++ et Qt4.

8 -

Une vue en mode aperçu avant impression. Sont affichés par défaut les numéros HR pour les étoiles et les numéros NGC pour les onjets du ciel profond. Tout est paramétrable.

9 -

Affichage des lettres grecques de la désignation de Bayer

10 -

Zoom sur la Lyre avec affichage du catalogue Tycho

11 -

Je me suis amusé à comparer une carte affichée par mon logiciel avec une vraie photo (en médailllon, affichée dans GIMP, après rotation ce qui la dégrade un peu...) que j'ai prise avec un vrai APN (boitier Pentax K100D) au foyer d'une vraie lunette (Skywarcher 120x600). C'est "le bout" de la constellation de La Lyre avec M57 en prime. Comme vous pouvez le constater les étoiles du catalogue Tycho sont correctement représentées.

12 Code source en C++ et Qt4 du soft Planétarium

CODE SOURCE en langage C++ (with QT)
  1. /**************************************************************************
  2.  * Copyright (C) 2009-2010 by Silicium628 (France) *
  3.  * http://silicium628.chez-alice.fr/ *
  4.  * http://www.silicium628.fr/ *
  5.  * *
  6.  * This program is free software; you can redistribute it and/or modify *
  7.  * it under the terms of the GNU General Public License as published by *
  8.  * the Free Software Foundation; *
  9.  * *
  10.  * This program is distributed in the hope that it will be useful, *
  11.  * but WITHOUT ANY WARRANTY; *
  12.  * See the GNU General Public License for more details. *
  13.  ***************************************************************************/
  14.  
  15. //programme ecrit avec le logiciel libre Qdevelop avec Qt4.5.2 (dispo sous Ubuntu 9.04 et >)
  16. //attention: sous Qt4.0 ce source ne compile pas (fonctions manquantes dans certaines classes)
  17. //et l'executable compile avec Qt4.5.2 ne tourne pas sous Ubuntu 8.10 et < pour la meme raison
  18. //note: j'ai supprime les accents dans les commentaires pour ameliorer la lisibilite sur tous les OS
  19. //desole pour les personnes respectueuses de la langue (dont je suis, enfin j'essaye...)
  20.  
  21. // derniere modification de ce programme le 10 aout 2010
  22.  
  23.  
  24. /*===========================================================================================
  25. RAPPELS:
  26. ===========================================================================================
  27. GENERALITES: (source Wikipedia)
  28. --------------------------------------------------------------------------------
  29. En une annee, la Terre effectue environ 365 tours sur elle-meme par rapport au Soleil,
  30. mais effectue aussi un tour complet autour du Soleil. Donc, par rapport aux etoiles,
  31. 365 jours solaires equivalent a 366 jours sideraux.
  32. Les jours sideraux sont donc un peu plus courts que les jours solaires.
  33. La periode reelle de l'annee etant de 365,2422 jours solaires, la duree exacte
  34. du jour sideral est de : 365,2422/(365,2422+1) = 0,9972696 jour solaire, soit 23h 56m 4,09s,
  35. soit une difference d'environ 4mn par rapport au jour solaire,
  36. le rapport entre les deux etant de 1/360 = 0.0027 soit moins de 0.3% dont il faut tenir compte.
  37.  
  38. En astronomie, la position d'un astre sur la sphere celeste est reperee par deux
  39. coordonnees, l'ascension droite et la declinaison.
  40. A tout instant la somme de l'ascension droite d'un astre et de son angle horaire
  41. est egale au temps sideral.
  42. En quelque sorte le temps sideral mesure le deplacement de la voûte celeste en
  43. un lieu donne par rapport au meridien local.
  44.  
  45. Unites de l'ascension droite
  46. L'heure d'ascension droite est une unite de mesure d'angle plan et vaut 360deg/24 = 15deg.
  47. La minute d'ascension droite vaut 1/60 heure d'ascension droite soit 15 minutes d'arc.
  48. La seconde d'ascension droite vaut 1/60 minute d'ascension droite = 15 secondes d'arc.
  49.  
  50. (fin de citation de Wikipedia)
  51. ==============================================================================================
  52. Remarque:
  53. Dans ce logiciel l'ascension droite est notee RA (de Right ascension en anglais )
  54. et la declinaison est notee DE (du 'dec' de declination en anglais, mais sans le 'c'
  55. pour ne pas confondre avec 'dec' = decimal ou decrementer...)
  56. ==============================================================================================
  57.  
  58. Une lunette astronomique immobile par rapport au sol terrestre pointe dans une
  59. direction du ciel dont l'ascenssion droite (RA) augmente de 1s (de coordonnees
  60. RA siderales, =15s d'arc) toutes les 1s (de temps sideral)
  61.  
  62. 1 jour solaire = 24h00 = 1440 mn
  63. 1 jour sideral = 23h56' = 1436 mn
  64. 365 * 4' = 24h (au bout d'une annee le decallage s'annule donc)
  65. Les 4' qu'il faut ajouter au jour sideral pour obtenir un jour terrestre sont dues
  66. au deplacement de la terre sur son orbite autour du soleil d'un jour sur l'autre
  67.  
  68.  
  69. ================================ Bright Star Catalogue ====================================
  70. Je cite ici l'article de Wikipedia (version 13 fevrier 2010):
  71.  
  72. Le Bright Star Catalogue (BSC), le Catalogue des etoiles brillantes,
  73. appele egalement Yale Catalogue of Bright Stars ou Yale Bright Star Catalogue,
  74. est un catalogue d'etoiles qui liste toutes les etoiles de magnitude inferieure ou egale 6,5,
  75. ce qui correspond en gros a toutes les etoiles visibles a l'oeil nu.
  76. Sa 5e edition est actuellement disponible en ligne sur plusieurs sites.
  77. Bien que l'abreviation du catalogue soit BS ou YBS, les citations des etoiles listees
  78. dans le catalogue utilisent HR avant le numero d'ordre, d'apres le nom de son predecesseur,
  79. le Harvard Revised Photometry Catalogue cree en 1908 par l'observatoire de Harvard.
  80. (fin de citation de Wikipedia)
  81. ==============================================================================================*/
  82.  
  83. #include "mainwindow.h"
  84. // #include <string.h>
  85.  
  86. #include <QFileDialog>
  87. #include <QTextStream>
  88. #include <QMessageBox>
  89. #include <QPainter>
  90. #include <QMouseEvent>
  91. #include <QWheelEvent>
  92. #include <QPrinter>
  93. #include <QPrintDialog>
  94. // #include <QApplication>
  95.  
  96. //TYPES
  97. enum ANGLE_ou_TEMPS { isA, isT };
  98.  
  99.  
  100. //VARIABLES
  101. long RA, DE; // en secondes (de temps pour RA et d'arc pour DE)
  102. long RA_pointe, DE_pointe; // RA et DE de l'objet clique a la souris
  103. int HR_pointe, NGC_pointe; // Numero HR de l'objet pointe
  104. int memo_HR_pointe, memo_NGC_pointe; // memo Numero HR de l'objet precedemment pointe
  105. long RA_centre, DE_centre; // coordonnees du centre de l'ecran en secondes (de temps pour RA et d'arc pour DE)
  106. long RA_aff_min, RA_aff_max, DE_aff_min, DE_aff_max; //en secondes (de temps pour RA et d'arc pour DE)
  107. float RA_min_deg, RA_max_deg, DE_min_deg, DE_max_deg;//en degres decimaux, D'ANGLE pour les deux
  108. int num_objet_BSC = 0;
  109. int num_objet_SAC = 0;
  110. int num_objet_BSC_pointe = 0;
  111. int num_objet_SAC_pointe = 0;
  112. int num_etoile_TYC_pointe = 0; // numero dans la 'liste_etoiles_TYC'
  113. QString cstl_pointee;
  114. int p1, l1;
  115. QStringList liste_figures_cstl;
  116. QStringList liste_noms_etoiles;
  117. bool objet_valide = false;
  118. bool fichier_cstl_ok = false;
  119. bool cliquee_G = false;
  120. bool a_dessiner = false;
  121. bool ne_pas_dessiner_maintenant = false;
  122. bool first = false;
  123. bool etoiles_tyc_visibles = false;
  124.  
  125. QString version_i = "v8.2";
  126. QString chemin_BSC;
  127. QString chemin_SAC;
  128. QString chemin_thycho2;
  129.  
  130. int w_ecran;
  131. int h_ecran;
  132. //QSize size1(1100, 620);
  133. //QSize size2(1200,890);
  134. QSize size_bordure(10,5);
  135. int x_max_ecran = 1200; // de l'ecran de projection
  136. int y_max_ecran = 800; // de l'ecran de projection
  137. int x_max_image = x_max_ecran; // de l'image calculee (qui peut etre plus grande que l'ecran, en particulier pour imprimer)
  138. int y_max_image = y_max_ecran; // de l'image calculee
  139. uchar buffer_image[32000000];
  140. QImage image1(buffer_image, 1200,800, QImage::Format_RGB32);
  141.  
  142. int PosX, PosY; // du clic de la souris
  143. int orientation_observateur;
  144.  
  145. double zoom_double;
  146. float zoom;
  147.  
  148. float angleA,angleB,angleC,angleD;
  149. float latitude_obs;
  150. int rayon_sphere = 600; //rayon de la sphere pour projection ecran
  151.  
  152. QDate date1;
  153. QTime time1;
  154. int day_oh_year1; // 0..365
  155.  
  156. QList<BSCrec> liste_etoiles_BSC; // 9110 objets du catalogue BSC5
  157. QList<TYC2rec> liste_etoiles_TYC; // liste des etoiles Tycho a afficher
  158. QList<RegionTYC> Liste_regions_tyc; // liste des numeros de regions TYCHO a afficher
  159.  
  160. int num_zone_BSC_centre;
  161. int num_zone_BSC_centre_memo;
  162.  
  163. QColor Tableau_couleurs_etoiles[7]; // O B A F G K M (oh be a fine girl, kiss me!)
  164. QColor couleur_etoile;
  165. QColor couleur_halo;
  166. int saturation = 100; // saturation des couleurs des etoiles
  167.  
  168. //pour gerer le TableWidget_BSC:
  169. #define colHR 0
  170. #define colNomCom 1
  171. #define colNomBay 2
  172. #define colHD 3
  173. #define colRA 4
  174. #define colDE 5
  175. #define colCSTL 6
  176. #define colMV 7
  177. #define colClsSpect 8
  178.  
  179. //pour gerer le TableWidget_NGC:
  180. #define colNGCNom1 0
  181. #define colNGCNom2 1
  182. #define colNGCRA 2
  183. #define colNGCDE 3
  184. #define colNGCType 4
  185. #define colNGCCons 5
  186. #define colNGCMagn 6
  187. #define colNGCDiam 7
  188.  
  189. int nb_objets_SAC = 0;
  190.  
  191.  
  192.  
  193. MainWindow::MainWindow (QWidget * parent, Qt::WFlags f)
  194. : QMainWindow(parent, f)
  195. {
  196. setupUi(this);
  197. setWindowTitle("APE2009 version: " + version_i);
  198.  
  199. chemin_BSC="/catalogues/bsc5/";
  200. chemin_SAC="/catalogues/sac/";
  201. chemin_thycho2="/thycho2/";
  202.  
  203. QMessageBox msgBox;
  204. QString tx1;
  205. tx1="Le chargement des catalogues va prendre un certain temps, veuillez cliquer sur ok pour continuer";
  206. msgBox.setText(tx1);
  207. msgBox.exec();
  208.  
  209. setCursor(Qt::WaitCursor);
  210.  
  211. InitTableBSC();
  212. InitTableNGC();
  213. createActions();
  214.  
  215. p1=0;
  216. l1=0;
  217.  
  218. Bt_copier_vers_cadre->setIcon(QIcon(QDir::currentPath() +"/fleche_verte3b.png"));
  219. Bt_top1->setIcon(QIcon(QDir::currentPath() +"/premier.png"));
  220.  
  221. liste_etoiles_BSC.clear();
  222. getBSC(&liste_etoiles_BSC, chemin_BSC + "bsc5_628.dat");
  223.  
  224. Listage_objets_BSC();
  225.  
  226. charger_fichier_SAC();
  227.  
  228. int z4 = charger_noms_etoiles(QDir::currentPath() + "/catalogues/noms_etoiles1.txt");
  229. // si le fichier a ete trouve dans le dir /catalogues, alors z=0 sinon on le chercher dans le dir de l'executable
  230. if (z4 == 1) { z4 = charger_noms_etoiles(QDir::currentPath() +"/noms_etoiles1.txt");}
  231.  
  232. Listage_noms_etoiles();
  233.  
  234. int z2 = charger_constellations(QDir::currentPath() + "/catalogues/constellations1.txt");
  235. // si le fichier a ete trouve dans le dir /catalogues, alors z=0 sinon on le chercher dans le dir de l'executable
  236. if (z2 == 1) { z2 = charger_constellations (QDir::currentPath() +"/constellations1.txt");}
  237. if (z2 == 0) {fichier_cstl_ok = true;}
  238.  
  239. int z3 = charger_figures_cstl(QDir::currentPath() + "/catalogues/figures_constellations.txt");
  240. // si le fichier a ete trouve dans le dir /catalogues, alors z=0 sinon on le chercher dans le dir de l'executable
  241. if (z3 == 1) { z3 = charger_figures_cstl (QDir::currentPath() +"/figures_constellations.txt");}
  242.  
  243. Tableau_couleurs_etoiles[0]= QColor::fromRgb(130,150,240,255); // O bleu
  244. Tableau_couleurs_etoiles[1]= QColor::fromRgb(116,220,235,255); // B cyan
  245. Tableau_couleurs_etoiles[2]= QColor::fromRgb(255,255,255,255); // A blanc
  246. Tableau_couleurs_etoiles[3]= QColor::fromRgb(250,250,200,255); // F jaune vif
  247. Tableau_couleurs_etoiles[4]= QColor::fromRgb(235,242,138,255); // G jaune orange
  248. Tableau_couleurs_etoiles[5]= QColor::fromRgb(240,190,140,255); // K orange
  249. Tableau_couleurs_etoiles[6]= QColor::fromRgb(250,112,100,255); // M rouge
  250.  
  251. Bt_nord->click();
  252. calendrier1->hide();
  253. Edit_ligne_cstl->hide();
  254. spinBox_magnitude_max->setValue(4.0);
  255. spinBoxZoom->setValue(3.0);
  256. MAJ_zoom(spinBoxZoom->value());
  257. Edit_FindName->setText("vega");
  258.  
  259. //a_dessiner = true;
  260. //dessiner_ciel(totalite);
  261.  
  262. this->setWindowState(Qt::WindowMaximized);
  263. w_ecran = width();
  264. h_ecran = height();
  265. // QString txt1;
  266.  
  267. // ordre d'empilement des widgets (parfois delicat a maitriser avec QDevelop, donc precise ici):
  268. frame_3->raise(); //Raises this widget to the top of the parent widget's stack -> "bring to front"
  269. Edit_ligne_cstl->raise();
  270. calendrier1->raise();
  271.  
  272. //calcul_anglesABC();
  273. angleD = 0;
  274. redimmensionner_tout();
  275. a_dessiner = true;
  276. dessiner_ciel(totalite);
  277.  
  278. setCursor(Qt::ArrowCursor);
  279. }
  280.  
  281. int charger_noms_etoiles(QString nom_fichier1)
  282. {
  283. int n=0;
  284. QFile file1(nom_fichier1);
  285. if (!file1.open(QIODevice::ReadOnly | QIODevice::Text)) return 1;
  286. QTextStream in(&file1);
  287. QString ligne;
  288. while ( !in.atEnd() )
  289. {
  290. ligne = in.readLine();
  291. if (ligne.left(1) !="#")
  292. {
  293. liste_noms_etoiles<<ligne;
  294. n++;
  295. }
  296. }
  297. file1.close();
  298. return 0;
  299. }
  300.  
  301.  
  302. int MainWindow::charger_constellations(QString nom_fichier1)
  303. {
  304. QStringList liste1;
  305. QFile file1(nom_fichier1);
  306. if (!file1.open(QIODevice::ReadOnly | QIODevice::Text)) return 1;
  307. QTextStream in(&file1);
  308. while ( !in.atEnd() )
  309. {
  310. QString line = in.readLine();
  311. if (line.left(1) !="#") { liste1<<line; }
  312. }
  313. liste1<<"===";
  314. Cbox_Constellations->addItems(liste1);
  315. file1.close();
  316. return 0;
  317. }
  318.  
  319.  
  320. void MainWindow::InitTableBSC(void)
  321. {
  322. int n;
  323. TableWidget_BSC->setColumnCount(10);
  324. QStringList liste_entetes_BSC;
  325. liste_entetes_BSC <<"HR"<<"Nom commun"<<"Bayer"<<"HD"<<"RA"<<"DE"<<"Cstl"<<"Mv"<<"Cls Spect";
  326. TableWidget_BSC->setHorizontalHeaderLabels (liste_entetes_BSC );
  327. TableWidget_BSC->resizeColumnsToContents();
  328.  
  329. for (n=0; n<9200; n++)
  330. {
  331. TableWidget_BSC->setItem(n, colNomCom, new QTableWidgetItem ("~") );
  332. TableWidget_BSC->setItem(n, colNomBay, new QTableWidgetItem ("~") );
  333. TableWidget_BSC->setItem(n, colHD, new QTableWidgetItem ("0") );
  334. TableWidget_BSC->setItem(n, colHR, new QTableWidgetItem ("----") );
  335. TableWidget_BSC->setItem(n, colRA, new QTableWidgetItem ("00000") );
  336. TableWidget_BSC->setItem(n, colDE, new QTableWidgetItem ("0000000") );
  337. TableWidget_BSC->setItem(n, colCSTL, new QTableWidgetItem ("~__") );
  338. TableWidget_BSC->setItem(n, colMV, new QTableWidgetItem ("=___") );
  339. TableWidget_BSC->setItem(n, colClsSpect, new QTableWidgetItem ("-") );
  340. }
  341. }
  342.  
  343.  
  344. void MainWindow::InitTableNGC(void)
  345. {
  346. TableWidget_NGC->setColumnCount(8);
  347. QStringList liste_entetes_NGC;
  348. liste_entetes_NGC <<"Nom1"<<"Nom2"<<"RA"<<"DE"<<"Type"<<"Const"<<"Magn"<<"Diam";
  349. // int count =TableWidget_BSC->rowCount();
  350. TableWidget_NGC->setHorizontalHeaderLabels (liste_entetes_NGC );
  351. // TableWidget_BSC->setItem(0,0, new QTableWidgetItem("ABC")); // ( pour ecrire dans 1 case)
  352. TableWidget_NGC->resizeColumnsToContents();
  353. }
  354.  
  355.  
  356.  
  357. int MainWindow::charger_texte_doc(QString nom_fichier1)
  358. {
  359. // listeDoc->setSource(QUrl::fromLocalFile(nom_fichier1));
  360.  
  361. QFile file1(nom_fichier1);
  362. if (!file1.open(QIODevice::ReadOnly | QIODevice::Text)) return 1;
  363. QTextStream in(&file1);
  364. listeDoc->clear();
  365. while ( !in.atEnd() )
  366. {
  367. QString line = in.readLine();
  368. listeDoc->addItem(line);
  369. }
  370. file1.close();
  371. return 0;
  372. }
  373.  
  374.  
  375. int charger_figures_cstl(QString nom_fichier1)
  376. {
  377. QFile file1(nom_fichier1);
  378. if (!file1.open(QIODevice::ReadOnly | QIODevice::Text)) return 1;
  379. QTextStream in(&file1);
  380. liste_figures_cstl.clear();
  381. while ( !in.atEnd() )
  382. {
  383. QString line = in.readLine();
  384. if (line.left(1) !="#") { liste_figures_cstl<<line; }
  385. }
  386. file1.close();
  387. return 0;
  388. }
  389.  
  390.  
  391. void MainWindow::enregistrer_fichier_ETOILES()
  392. {
  393. QString nom1, st1, st2, ligne1 ;
  394. QString RA_txt, DE_txt, DE1, magnitude_txt;
  395. float mv, mv_max;
  396.  
  397. QFile file1(QDir::currentPath() + "/catalogues/ETOILES1.ETL");
  398. if (!file1.open(QIODevice::WriteOnly | QIODevice::Text)) return;
  399. QTextStream out(&file1);
  400. setCursor(Qt::WaitCursor);
  401.  
  402. out<< "# Liste d'objets astronomiques (catalogue BSC) pour l'APE2009 (GOTO pour telescope base sur un ATmega32)";
  403. out<<'\n'; //retour a la ligne
  404. out<< "# Les positions sont donnees en secondes (de temps pour RA et d'arc pour DE)";
  405. out<<'\n'; //retour a la ligne
  406. out<< "# Les objets sont enregistres tries par numero HR qui constitue l'index de la table";
  407. out<<'\n'; //retour a la ligne
  408. out<<'#';
  409. out<<'\n'; //retour a la ligne
  410.  
  411. mv_max = 4.5;
  412. int compte = 0;
  413. int row = 0;
  414. while (row < 9110)
  415. {
  416. magnitude_txt = TableWidget_BSC->item(row,colMV)->text(); // magnitude
  417. mv = magnitude_txt.toFloat();
  418. if ((mv != 0) && (mv < mv_max))
  419. {
  420. //-------------------------------------------------------------------------------
  421. ligne1="!E";
  422. //-------------------------------------------------------------------------------
  423. st1 = TableWidget_BSC->item(row,colHR)->text(); // numero HR
  424. st1=("0000"+st1).right(4); // formatage: toujours 4 chiffres
  425. ligne1 += st1;
  426. //-------------------------------------------------------------------------------
  427. ligne1 += "_R";
  428. RA_txt = "00000"+TableWidget_BSC->item(row,colRA)->text(); // RA
  429. ligne1 += RA_txt.right(5);
  430. //-------------------------------------------------------------------------------
  431. ligne1 += "D";
  432. DE_txt = "0000000"+TableWidget_BSC->item(row,colDE)->text(); // DE
  433. ligne1 += DE_txt.right(7);
  434. ligne1 += "_";
  435. //-------------------------------------------------------------------------------
  436. nom1 = TableWidget_BSC->item(row,colNomCom)->text(); // nom commun
  437. nom1 +="----------";
  438. ligne1 += nom1.left(10);
  439. ligne1 += "_";
  440. //-------------------------------------------------------------------------------
  441. st1 = TableWidget_BSC->item(row,colCSTL)->text(); // constellation
  442. st1+="---";
  443. ligne1 += st1.left(3);
  444. ligne1 += "_";
  445. //-------------------------------------------------------------------------------
  446. ligne1 += magnitude_txt;
  447.  
  448. out<< ligne1;
  449. out<<'\n'; //retour a la ligne
  450. compte++;
  451. }
  452. row++;
  453. }
  454. out.flush();
  455.  
  456. setCursor(Qt::ArrowCursor);
  457. st1.setNum(compte); // conversion num -> txt
  458. st2.setNum(mv_max); // conversion num -> txt
  459.  
  460. QMessageBox msgBox;
  461. msgBox.setText("Le fichier ETOILES1.ETL a ete enregistre; Il comprend " + st1 + " Etoiles de magnitude < " + st2 );
  462. msgBox.exec();
  463.  
  464. TableWidget_BSC->setCurrentCell(0,0);
  465. }
  466.  
  467.  
  468. void MainWindow::enregistrer_fichier_NGC()
  469. {
  470. QString nom1, st1, st2, ligne1 ;
  471. QString RA_txt, DE_txt, DE1, magnitude_txt;
  472. float mv, mv_max;
  473. QFile file1(QDir::currentPath() + "/catalogues/NGCSKY1.OBJ");
  474. if (!file1.open(QIODevice::WriteOnly | QIODevice::Text)) return;
  475. QTextStream out(&file1);
  476.  
  477. setCursor(Qt::WaitCursor);
  478. out<< "# Liste d'objets astronomiques NGC (catalogue SAC) pour l'APE2009 (GOTO pour telescope base sur un ATmega32)";
  479. out<<'\n'; //retour a la ligne
  480. out<< "# Les positions sont donnees en secondes (de temps pour RA et d'arc pour DE)";
  481. out<<'\n'; //retour a la ligne
  482. out<<'#';
  483. out<<'\n'; //retour a la ligne
  484.  
  485. mv_max = 10;
  486. int compte = 0;
  487. int row = 0;
  488. while (row < nb_objets_SAC)
  489. {
  490. magnitude_txt = TableWidget_NGC->item(row,colNGCMagn)->text(); // magnitude
  491. mv = magnitude_txt.toFloat();
  492. if ((mv != 0) && (mv < mv_max))
  493. {
  494. //-------------------------------------------------------------------------------
  495. ligne1="!E";
  496. //-------------------------------------------------------------------------------
  497. st1 = TableWidget_NGC->item(row,colNGCNom1)->text(); // nom1 (NGCxxxx dans la plupart des cas)
  498. if (st1.left(3) == "NGC") // on ne retient que les objets NGC
  499. {
  500. st1.remove(0,3); // (NGC)
  501. st1=("0000"+st1).right(4); // formatage: toujours 4 chiffres
  502. ligne1 += st1;
  503. //-------------------------------------------------------------------------------
  504. ligne1 += "_R";
  505. RA_txt = "00000"+TableWidget_NGC->item(row,colNGCRA)->text(); // RA
  506. ligne1 += RA_txt.right(5);
  507. //-------------------------------------------------------------------------------
  508. ligne1 += "D";
  509. DE_txt = "0000000"+TableWidget_NGC->item(row,colNGCDE)->text(); // DE
  510. ligne1 += DE_txt.right(7);
  511. ligne1 += "_";
  512. //-------------------------------------------------------------------------------
  513. nom1 = TableWidget_NGC->item(row,colNGCNom2)->text(); // nom2
  514. nom1 +="----------";
  515. ligne1 += nom1.left(10);
  516. ligne1 += "_";
  517. //-------------------------------------------------------------------------------
  518. st1 = TableWidget_NGC->item(row,colNGCCons)->text(); // constellation
  519. st1+="---";
  520. ligne1 += st1.left(3);
  521. ligne1 += "_";
  522. //-------------------------------------------------------------------------------
  523. ligne1 += magnitude_txt;
  524.  
  525. out<< ligne1;
  526. out<<'\n'; //retour a la ligne
  527. compte++;
  528. }
  529. }
  530. row++;
  531. }
  532. out.flush();
  533.  
  534. setCursor(Qt::ArrowCursor);
  535. st1.setNum(compte); // conversion num -> txt
  536. st2.setNum(mv_max); // conversion num -> txt
  537. QMessageBox msgBox;
  538.  
  539. msgBox.setText("Le fichier NGCSKY1.OBJ a ete enregistre; Il comprend " + st1 + " objets de magnitude < " + st2 );
  540. msgBox.exec();
  541.  
  542. TableWidget_BSC->setCurrentCell(0,0);
  543. }
  544.  
  545.  
  546. void MainWindow::decodage_abrev_constell(void)
  547. //par comparaison des textes entiers et/ou des abreviations
  548. {
  549. int i1;
  550. QString texte1, texte2, texteA, texteB ="";
  551. i1=0;
  552.  
  553. texteB = Edit7->text().left(4); // debut du texte complet
  554. texte2 = Edit7->text().right(3); // abreviation seulement
  555. while ((texte1 != texte2 ) && (texteA != texteB ) && (i1<=88))
  556. {
  557. Cbox_Constellations->setCurrentIndex(i1);
  558. texteA = Cbox_Constellations->currentText().left(4);
  559. texte1 = Cbox_Constellations->currentText().right(3);
  560. i1++;
  561. }
  562. if (i1>88) { Edit12->setText(texte1); } else {Edit12 ->setText("===");}
  563. }
  564.  
  565.  
  566. int MainWindow::text2secondes (QLineEdit *Edit_i)
  567. // convertit le texte du QLineEdit passe par adresse en un nombre de secondes
  568. // le texte du QLineEdit doit etre de la forme "12:34:56" pour: degres:minutes:secondes OU heures:minutes:secondes
  569. {
  570. //19:8:39
  571. //on va decouper le texte en 3 tronçons '19' , '8' et '39'
  572. QString txt0,txt1,txt2,txt3;
  573. int p1,p2;
  574. int h,m,s;
  575. long s_out;
  576. char signeD ='+';
  577.  
  578. txt0 = Edit_i->text();
  579. p1 = txt0.indexOf(":"); // position du premier ":"
  580. txt1 = txt0.left(p1); // '19'
  581. if (txt1.left(1) == "-")
  582. {
  583. signeD='-';
  584. txt1.remove(0,1);
  585. }
  586. // if (txt0.contains("-", Qt::CaseInsensitive)) {signeD='-';}
  587. txt0.remove(0, p1+1); // on coupe le debut
  588. p2 = txt0.indexOf(":"); // position du ":" suivant
  589. txt2 = txt0.left(p2); // '8' remarque: ok quel que soit le nb de chiffres
  590. txt0.remove(0, p2+1); // on coupe le debut
  591. txt3 = txt0; // le compilateur simplifiera!
  592. h = txt1.toInt(); // conversion txt -> num
  593. m = txt2.toInt(); // conversion txt -> num
  594. s = txt3.toInt(); // conversion txt -> num
  595. s_out = s + 60 * m + 3600 * h;
  596. if (signeD == '-') { s_out = 324000 + s_out; }
  597. return s_out;
  598. }
  599.  
  600.  
  601. float sec2deg_decim(long nb_sec, ANGLE_ou_TEMPS typ_i)
  602. //convertit un nombre de secondes en degres decimaux (degres d'angles)
  603. // si la valeur entree est une ascension droite (RA), le resultat est une valeur comprise entre 0 et 360
  604. // si la valeur entree est une declinaison (DE), le resultat est une valeur comprise entre -90 et +90
  605. {
  606. float d;
  607. if( typ_i == isT)
  608. {
  609. d = 15 * (float)nb_sec / 3600; // RA=360deg/24h soit 15deg/h
  610. }
  611. else if( typ_i == isA)
  612. {
  613. if (nb_sec > 324000)
  614. {
  615. nb_sec -= 324000;
  616. d = -(float)nb_sec / 3600; // il y a un signe (-) devant float!!!!
  617. }
  618. else
  619. {
  620. d = (float)nb_sec / 3600;
  621. }
  622. }
  623. else d=0;
  624. return d;
  625. }
  626.  
  627.  
  628. long deg_decim2sec(float valeur)
  629. //convertit un reel (degres decimaux) en secondes
  630. {
  631. float f;
  632. long s;
  633.  
  634. f = valeur * 3600;
  635. if (valeur < 0) { f = -f +324000; }
  636. s = floor(f);
  637. return s;
  638. }
  639.  
  640.  
  641. void MainWindow::on_Bt_copier_vers_cadre_clicked()
  642. {
  643. long nb_secondes;
  644.  
  645. int row = TableWidget_BSC->currentRow();
  646. Edit_nom->setText(TableWidget_BSC->item(row,colNomCom)->text()); // nom commun
  647.  
  648. Edit_RAs->setText(TableWidget_BSC->item(row,colRA)->text()); // RA affichage en secondes
  649.  
  650. nb_secondes = Edit_RAs->text().toInt(); // conversion txt -> num
  651. Edit_RA->setText(nb_secondes2txt_hms(nb_secondes) ); //affichage hh:mm:ss
  652.  
  653. Edit_DEs->setText(TableWidget_BSC->item(row,colDE)->text());
  654. nb_secondes = Edit_DEs->text().toInt(); // conversion txt -> num
  655. if (nb_secondes > 324000) {nb_secondes = 324000 - nb_secondes ;}
  656. Edit_DE->setText(nb_secondes2txt_hms(nb_secondes) ); //affichage hh:mm:ss
  657.  
  658. Edit_magnitude->setText(TableWidget_BSC->item(row,colMV)->text()); // magnitude
  659.  
  660. Edit7->setText(TableWidget_BSC->item(row,colCSTL)->text()); // constellation
  661. decodage_abrev_constell();
  662. }
  663.  
  664.  
  665. void MainWindow::on_Edit_RA_editingFinished()
  666. {
  667. QString RA_txt;
  668. RA_txt.setNum(text2secondes(Edit_RA)); // conversion num -> txt
  669.  
  670. RA_txt.insert(0, "00000");
  671. RA_txt = RA_txt.right(5); // le string RA contient exactement 5 caracteres (avec des 0 devant)
  672. Edit_RAs -> setText(RA_txt);// AffichageEtendu en secondes; plus grand AffichageEtendu = '86400' (5 caract)
  673. }
  674.  
  675.  
  676. void MainWindow::on_Edit_DE_editingFinished()
  677. {
  678. QString DE_txt;
  679.  
  680. DE_txt.setNum(text2secondes(Edit_DE)); // conversion num -> txt
  681. DE_txt.insert(0, "00000");
  682. DE_txt = DE_txt.right(7); // le string DE contient exactement 7 caracteres (avec des 0 devant)
  683. Edit_DEs -> setText(DE_txt);// AffichageEtendu en secondes; plus grand AffichageEtendu = '-324000' (7 caract)
  684. }
  685.  
  686.  
  687. void MainWindow::on_actionEnregistrer_activated()
  688. {
  689. spinBox_magnitude_max->setValue(4.5);
  690. spinBoxNGC_mag_max->setValue(10.0);
  691. enregistrer_fichier_ETOILES(); // pour la SDcard
  692. enregistrer_fichier_NGC(); // pour la SDcard
  693. }
  694.  
  695.  
  696. void MainWindow::efface_objet_pointe()
  697. {
  698. Edit_objPointe->setText("");
  699. Edit_RAobjPointe->setText("");
  700. Edit_DEobjPointe->setText("");
  701. }
  702.  
  703. void MainWindow::efface_position_pointee()
  704. {
  705. Edit_RAposPointe->setText("");
  706. Edit_DEposPointe->setText("");
  707. }
  708.  
  709.  
  710. void MainWindow::extraire_RA_DE_from_Tableau(int row_i, long *RA_out, long *DE_out)
  711. {
  712. QString txt1;
  713. txt1 = TableWidget_BSC->item(row_i,colRA)->text(); // RA
  714. *RA_out = txt1.toInt(); // conversion txt -> num
  715. txt1 = TableWidget_BSC->item(row_i,colDE)->text(); // DE
  716. *DE_out = txt1.toLong();
  717. }
  718.  
  719.  
  720. int MainWindow::projection(long RAs, long DEs, QPoint *P)
  721. //convertit les coordonnees RA et DE (donnees en secondes de temps et d'arc) en projection plane
  722.  
  723. /*=============================== PROJECTION =====================================================
  724. Projection "orthographique":
  725. On place le plan de projection tangent a la sphere et on projette les points perpendiculairement a ce plan
  726. ==================================================================================================*/
  727. {
  728. double x = 0; // du point projete sur le plan
  729. double y = 0; // du point projete sur le plan
  730. double R, D; // de l'etoile, en radians
  731.  
  732. QPoint Pt1;
  733. Vecteur3D v1;
  734. QString txt1;
  735.  
  736. if (DEs > 324000) {DEs = 324000 - DEs ;}
  737.  
  738. R = 2*M_PI / (24*3600) * RAs; // en radians
  739. D = M_PI / (180*3600) * DEs; // en radians
  740.  
  741. v1.x = rayon_sphere * cos(D) * cos (R);
  742. v1.y = rayon_sphere * cos(D) * sin (R);
  743. v1.z = rayon_sphere * sin(D);
  744.  
  745. v1.RotZ(angleA); // rotation terrestre
  746. v1.RotY(angleB); // inclinaison de l'axe des poles due a la latitude RotX
  747. v1.RotZ(angleC); // rotation de l'observateur sur lui-meme
  748.  
  749. v1.RotX(angleD); // rotation de champ
  750.  
  751. /* REMARQUE:
  752. -les rotations se font par rapport a l'observateur (repere x,y,z) et non par rapport a l'objet
  753. -l'ordre des rotations est donc important
  754. */
  755.  
  756. //projection sur l'ecran:
  757. x = x_max_image/2 - zoom * v1.y;
  758. y = y_max_image/2 - zoom * v1.z;
  759.  
  760. Pt1.setX(x);
  761. Pt1.setY(y);
  762. *P = Pt1;
  763. if (v1.x < 0) {return 1;} else {return 0;} // pour ne pas tracer les objets situes derriere l'observateur
  764. }
  765.  
  766.  
  767. double arc_cos_sin(double cosAlpha, double sinAlpha)
  768. {
  769. //cettte fonction retourne l'angle en fontion du couple [cos, sin] ce qui leve l'ambiguite sur 4 quadrants
  770. if ( sinAlpha >= 0 ) {return acos(cosAlpha);} else {return -acos(cosAlpha);}
  771. }
  772.  
  773.  
  774. int MainWindow::projection_inverse(QPoint P, long *RAs, long *DEs)
  775. //calcule les coordonnees RA et DE en fonction de leur point projete sur le plan
  776. {
  777. double x = 0; // du point projete sur le plan
  778. double y = 0; // du point projete sur le plan
  779. double R, D; // de l'etoile, en radians
  780. double carre_x;
  781. Vecteur3D v1;
  782.  
  783. v1.x=0;
  784. v1.y=0;
  785. v1.z=0;
  786.  
  787. x=P.x();
  788. y=P.y();
  789.  
  790. v1.y = ( x_max_image/2 -x) /zoom;
  791. v1.z = ( y_max_image/2 -y) /zoom;
  792.  
  793. //le point se situant sur la sphere, v1.x est determine en fonction de v1.y et v1.z
  794. // (sur une sphere de rayon r et de centre 0, on a: x²+y²+z²=r² )
  795. // d'ou: x² = r² - y² - z²
  796. // x = SQRT(r² - y² - z²)
  797. carre_x = rayon_sphere * rayon_sphere - v1.y * v1.y - v1.z * v1.z;
  798. if (carre_x < 0)
  799. {// on a pointe en dehors de la sphere
  800. *RAs=0;
  801. *DEs=0;
  802. return 1;
  803. }
  804. v1.x = sqrt(carre_x);
  805. //reste a faire tourner le vecteur en sens inverse de celui de la fonction projection
  806. //et dans l'ordre inverse:
  807. v1.RotX(-angleD); // rotation de champ
  808. v1.RotZ(-angleC);
  809. v1.RotY(-angleB);
  810. v1.RotZ(-angleA);
  811. // il faut maintenant en deduire les coordonnees RA et DE du point de la sphere
  812. // RAPPEL:
  813. // v1.x = rayon_sphere * cos(D) * cos (R);
  814. // v1.y = rayon_sphere * cos(D) * sin (R);
  815. // v1.z = rayon_sphere * sin(D);
  816. D = asin(v1.z / rayon_sphere);
  817. R = arc_cos_sin(v1.x / rayon_sphere / cos(D) , v1.y / rayon_sphere / cos(D));
  818. //conversion des radians en secondes d'angle et de temps:
  819. // RAPPEL:
  820. // R = 2*M_PI / (24*3600) * RAs; // en radians
  821. // D = M_PI / (180*3600) * DEs; // en radians
  822. *RAs = R * 24 * 3600 / 2 / M_PI;
  823. if (*RAs<0) {*RAs += 24*3600;}
  824. *DEs = D * 180 * 3600 / M_PI;
  825. if (*DEs < 0) {*DEs = 324000 - *DEs ;}
  826.  
  827. return 0;
  828. }
  829.  
  830.  
  831. void MainWindow::trace_bande_H(int di, int pas_ri, int num_zone_min, QPainter *painter_i)
  832. //trace les arcs de cercles des longitudes ("verticales" passant par les poles)
  833. {
  834. int r1;
  835. int d1;
  836. int num_zone2 = num_zone_min;
  837. QPoint P;
  838. QString txt_num;
  839. QFont font1 = painter_i->font();
  840. painter_i->setPen(Qt::cyan);
  841.  
  842. for (r1=0; r1<=(23*3600); r1+=pas_ri)
  843. {
  844. if (projection(r1, 0, &P) == 0)
  845. {
  846. txt_num.setNum(r1 / 3600); // conversion num -> txt
  847. font1.setPointSize(7); painter_i->setFont(font1);
  848. painter_i->drawText(P,txt_num + "h");
  849. }
  850.  
  851. // 2.1.1) numerotation des zones hemisphere nord
  852. if (projection(r1+15*240, di*3600, &P) == 0)
  853. {
  854. txt_num.setNum(num_zone2); // conversion num -> txt
  855. font1.setPointSize(12); painter_i->setFont(font1);
  856. painter_i->drawText(P,txt_num);
  857. }
  858. // 2.1.1) numerotation des zones symetriques hemisphere sud
  859. if (projection(r1+15*240, -di*3600, &P) == 0)
  860. {
  861. txt_num.setNum(num_zone2+25); // conversion num -> txt
  862. font1.setPointSize(12); painter_i->setFont(font1);
  863. painter_i->drawText(P,txt_num);
  864. }
  865. // trace des lignes
  866. for (d1=3600*(di-15); d1<=3600*(di+15); d1+=2000)
  867. {
  868. if (projection(r1, d1, &P) == 0) { painter_i->drawPoint(P); }// trace un point
  869. if (projection(r1, -d1, &P) == 0) { painter_i->drawPoint(P); }// trace un point symetrique
  870. }
  871. num_zone2++;
  872. }
  873. }
  874.  
  875.  
  876. void MainWindow::calcul_aspect_etoile(float mv, float *z, float *rayon_etoile, int *rayon_halo, int *lum1 )
  877. //calcule tous ces parametres d'affichages en fonction de la magnitude mv
  878. {
  879. int m_max = spinBox_magnitude_max->value();
  880. if (m_max > 8) {m_max = 8; }
  881. *z = (16.0 - 2.1 * mv ) * m_max / 6;
  882. if (*z > 22) { *z=22;}
  883. if (*z < 1) {*z=1;}
  884.  
  885. *rayon_halo = int(*z * *z /6 * zoom_double / 4.0);
  886. *rayon_etoile = *z /2.0 * zoom_double / 4.0 ;
  887. if (actionEtoiles_ponctuelles->isChecked()) {*rayon_etoile=1.5;}
  888. if (actionMode_Impression->isChecked()) *rayon_etoile *= 4;
  889.  
  890. *lum1 = 255 - 10.0 * mv;
  891. if (*lum1>255) { *lum1=255;}
  892. if (*lum1<5) { *lum1=5;}
  893. }
  894.  
  895.  
  896. void MainWindow::affiche_legende_etoiles(QPainter *painter_i)
  897. {
  898. QPoint P;
  899. int n;
  900. float mv,z;
  901. int lum1, rayon_halo;
  902. float rayon_etoile;
  903. int h, s, v, a;
  904. QFont font1 = painter_i->font();
  905. QString txt;
  906. //==================================================================================
  907. //trace du cartouche des legendes
  908. painter_i->setPen(Qt::gray);
  909. painter_i->setBrush(Qt::black);
  910. painter_i->drawRect(1,1,280,70);
  911. //trace de la legende des couleurs des etoiles
  912. for (n=0; n<8; n++)
  913. {
  914. font1.setPointSize(7); painter_i->setFont(font1);
  915. painter_i->setBrush(Tableau_couleurs_etoiles[n]);
  916. painter_i->setPen(Tableau_couleurs_etoiles[n]);
  917. painter_i->drawEllipse(20+20*n,15,10,10); // dessine un cercle de couleur
  918. }
  919. painter_i->setPen(Qt::white);
  920. painter_i->drawText(20,40,"O B A F G K M");
  921.  
  922. //==================================================================================
  923. //trace de la legende de la taille des etoiles
  924. for (n=0; n<7; n++)
  925. {
  926. mv = n+1;
  927. calcul_aspect_etoile(mv, &z, &rayon_etoile, &rayon_halo, &lum1);
  928. // int demiRayonH = rayon_halo/2;
  929. couleur_etoile = Tableau_couleurs_etoiles[2];
  930. couleur_etoile.getHsv(&h,&s,&v,&a);
  931. couleur_etoile.setHsv(h,saturation,lum1,a);
  932.  
  933. couleur_halo = couleur_etoile;
  934. couleur_halo.getHsv(&h,&s,&v,&a);
  935. couleur_halo.setHsv(h,s,255,100);
  936.  
  937. P.setX(20+40*n);
  938. P.setY(50);
  939.  
  940. /*
  941. if (zoom > 1)
  942. {
  943. if (rayon_halo > 20)
  944. {
  945. QPen pen(Qt::white);
  946. pen.setWidth(1);
  947. painter_i->setPen(pen);
  948.   painter_i->drawLine(P.x()-demiRayonH,P.y(),P.x()+demiRayonH,P.y()); // aigrette V
  949.   painter_i->drawLine(P.x(),P.y()-demiRayonH,P.x(),P.y()+demiRayonH); // aigrette H
  950.   }
  951. painter_i->setBrush(couleur_halo);
  952. painter_i->setPen(Qt::NoPen);
  953.   painter_i->drawEllipse(P,rayon_halo,rayon_halo);
  954. }
  955. */
  956.  
  957. // DESSIN DES ETOILES
  958. painter_i->setBrush(couleur_etoile);
  959. painter_i->setPen(couleur_etoile);
  960. if (rayon_etoile < 1.5)
  961. {
  962. painter_i->setBrush(Qt::white);
  963. painter_i->drawPoint(P); // ponctuel
  964. }
  965. else
  966. {
  967. painter_i->setPen(Qt::NoPen);
  968. painter_i->drawEllipse(P,int(rayon_etoile),int(rayon_etoile)); // dessine une etoile
  969. }
  970.  
  971. painter_i->setPen(Qt::white);
  972. font1.setPointSize(7); painter_i->setFont(font1);
  973. txt.setNum(n+1);
  974. painter_i->drawText(25+40*n,65,txt);
  975. }
  976. }
  977.  
  978.  
  979. void MainWindow::trace_constellations(QPainter *painter_i, QColor couleur_ligne, QColor couleur_nom)
  980. {
  981. long RA_s, DE_s;
  982. QPoint P;
  983. QFont font1 = painter_i->font();
  984. int x1=0; int y1=0; int x2=0; int y2=0;
  985. QString ligne;
  986. QString nbtxt;
  987. QString nom2;
  988. QString separ1, separ2;
  989.  
  990. int nb_lignes = liste_figures_cstl.size();
  991. int l1, lg;
  992. int G_x, G_y; // coordonnees du barycentre de la constellation
  993. int pos1, pos2;
  994. int hr1, row1, row2;
  995.  
  996. if (actionTracer_Constellations->isChecked())
  997. {
  998. for (l1=0; l1<nb_lignes; l1++) // chaque ligne code pour une constellation
  999. {
  1000. G_x = 0;
  1001. G_y = 0;
  1002. ligne = liste_figures_cstl.operator [](l1);
  1003. pos1=ligne.indexOf(";");
  1004. if (pos1 != -1)
  1005. {
  1006. nom2= ligne.left(pos1); // recupere le nom de la constellation
  1007. int n=0;
  1008. //ls=ligne.size();
  1009. ligne.remove(0, pos1+1); // coupe le nom et le premier ";"
  1010. //a_tracer = false;
  1011. pos1=ligne.indexOf("-");
  1012. if (pos1 != -1)
  1013. { //des nombres sont presents
  1014. bool stop=false;
  1015. pos2=0;
  1016. row1=0;
  1017. row2=0;
  1018. separ1="";
  1019. separ2="";
  1020. while (!stop)
  1021. { //analyse du reste de la ligne (trace de la constellation)
  1022.  
  1023. pos2=0;
  1024. lg = ligne.length();
  1025. while ((pos2 < lg) && (ligne[pos2]!='-') && (ligne[pos2]!=';')) {pos2++;}
  1026.  
  1027. if (pos2 == lg) {stop=true;}
  1028.  
  1029. nbtxt=ligne.left(pos2); // extraction du nombre
  1030. hr1 = nbtxt.toInt(); // conversion txt -> num
  1031. row1 = row2; // debut du segment = fin du precedent
  1032. row2 = hr1-1; // fin du segment
  1033. separ1 = separ2;
  1034. separ2 = ligne[pos2];
  1035.  
  1036.  
  1037. ligne.remove(0, pos2+1); // coupe le nombre, et le separateur ("-" ou ";")
  1038.  
  1039.  
  1040. if ((separ1 == "-") && (row1 > 0) && (row2 > 0))
  1041. {
  1042. extraire_RA_DE_from_Tableau(row1, &RA_s, &DE_s);
  1043. if (projection(RA_s, DE_s, &P) == 0) // x et y sont modifies par cette fonction
  1044. {
  1045. x1=P.x();
  1046. y1=P.y();
  1047. G_x += x1;
  1048. G_y += y1;
  1049. n++;
  1050. }
  1051. extraire_RA_DE_from_Tableau(row2, &RA_s, &DE_s);
  1052. if (projection(RA_s, DE_s, &P) == 0)
  1053. {
  1054. x2=P.x();
  1055. y2=P.y();
  1056. }
  1057. painter_i->setPen(couleur_ligne);
  1058. long ds=sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2));
  1059. if (ds < 500*zoom) { painter_i->drawLine(x1,y1,x2,y2); }
  1060.  
  1061. }
  1062. //ls=ligne.indexOf("-"); // test d'arret de la boucle si plus de "-"
  1063. }
  1064. }
  1065. if (n>0)
  1066. {
  1067. G_x /=n;
  1068. G_y /=n;
  1069. }
  1070. if (!actionMode_Impression->isChecked())
  1071. {
  1072. font1.setPointSize(11);
  1073. painter_i->setFont(font1);
  1074. painter_i->setPen(couleur_nom);
  1075. painter_i->drawText(G_x,G_y,nom2);
  1076. }
  1077. }
  1078. }
  1079. }
  1080. }
  1081.  
  1082.  
  1083. void MainWindow::centrer_position(long RA_i, long DE_i)
  1084. //calul les angles dont il faut faire tourner la sphere afin que la position donnee
  1085. //soit affichee au centre de l'ecran
  1086. {
  1087. float R, D; // de l'objet, en radian
  1088. Vecteur3D v1;
  1089.  
  1090. if (DE_i > 324000) {DE_i = 324000 - DE_i ;}
  1091. R = 2*M_PI / (24*3600) * RA_i; // R en radian
  1092. D = M_PI / (180*3600) * DE_i; // D en radian
  1093.  
  1094. v1.x = rayon_sphere * cos(D) * cos (R);
  1095. v1.y = rayon_sphere * cos(D) * sin (R);
  1096. v1.z = rayon_sphere * sin(D);
  1097.  
  1098. angleA = -R;
  1099. angleB = D;
  1100. angleC = 0;
  1101.  
  1102. RA_centre = RA_i;
  1103. DE_centre = DE_i;
  1104. }
  1105.  
  1106.  
  1107. void MainWindow::calcul_anglesABC()
  1108. // en fonction de la date, de l'heure et de la position de l'observateur
  1109. {
  1110. time1 = timeEdit1->time();
  1111.  
  1112. float minutes = 8 + 60.0 * time1.hour() + time1.minute() + 4.0 * (day_oh_year1-79) * 0.9972696;
  1113. // sur la ligne qui suit j'ecris ostensiblement le signe moins afin qu'il ne se barre pas!
  1114. //(ce qui ferait tourner la Terre a l'envers!!!!)
  1115. angleA = (-1) * M_PI * (minutes * 0.25) / 180;
  1116. latitude_obs = M_PI / 180 *(90 - spinBox_latitude->value()); // en radian
  1117. angleB = latitude_obs;
  1118. angleC = M_PI * orientation_observateur / 180;
  1119. //angleD = M_PI / 180 *(spinBox_rot_champ->value()); // en radian
  1120. }
  1121.  
  1122.  
  1123. void MainWindow::dessiner_ciel(mode_dessin mode_i)
  1124. {
  1125. if (tabWidget1->currentIndex() != 2) { return; }
  1126. if (!a_dessiner) {return;}
  1127.  
  1128. a_dessiner = false;
  1129.  
  1130. //if (actionObjetsSDcardSeulement->isChecked())
  1131. //{
  1132. // spinBox_magnitude_max->setValue(4.5);
  1133. // spinBoxNGC_mag_max->setValue(7.0);
  1134. // actionAfficher_Numeros->setChecked(true);
  1135. // actionAfficher_Noms->setChecked(true);
  1136. //}
  1137.  
  1138. setCursor(Qt::WaitCursor);
  1139. int row;
  1140. long RA_s, DE_s;
  1141. float mv, z;
  1142. int lum1,rayon_halo;
  1143. float rayon_etoile;
  1144. int h, s, v, a;
  1145. QString txt_num, txt1, str1;
  1146. QString nom1, nom2, nomCommun, txt_numHR, classeSpectrale, cstl, bayer;
  1147. QString RAcentre_txt, DEcentre_txt;
  1148. QPoint P, P1, Pdecal_num, Pdecal_nom;
  1149. QPoint centre; // d'un objet
  1150.  
  1151.  
  1152. int x, y, pas_x, pas_y; // pour quadriller l'ecran avec des cases recevant du texte
  1153. bool tableau_cases[20][60]; // memorise les cases situees en [x][y] occupees par un texte (anti-collision)
  1154. for (x=0; x<20; x++) {for (y=0; y<60; y++) {tableau_cases[x][y]=false;}}
  1155.  
  1156. // QList <QPoint> listePoints;
  1157.  
  1158.  
  1159. // definition des couleurs
  1160. QColor gris_fonce = QColor::fromHsv(240, 0, 80, 255);
  1161. QColor gris_tres_fonce = QColor::fromHsv(240, 0, 45, 255);
  1162. QColor gris_galaxie = QColor::fromHsv(120, 5, 230, 70);
  1163.  
  1164. QColor bleu_tres_fonce = QColor::fromHsv(240, 255, 10, 255);
  1165. QColor bleu_fonce = QColor::fromHsv(240, 255, 120, 255);
  1166. QColor vert_fonce = QColor::fromHsv(120, 255, 100, 255);
  1167.  
  1168.  
  1169. //affectations des couleurs
  1170. QColor couleur_ciel = Qt::black;
  1171. QColor couleur_grille = gris_tres_fonce;
  1172. QColor couleur_texte_grille = gris_fonce;
  1173. QColor couleur_centre = Qt::white;
  1174. QColor couleur_zones_BSC = Qt::cyan;
  1175. QColor couleur_ecliptique = Qt::yellow;
  1176. QColor couleur_pointVernal = Qt::cyan;
  1177. QColor couleur_lignes_cstl = bleu_fonce;
  1178. QColor couleur_noms_cstl = Qt::yellow;
  1179. QColor couleur_point_vise = Qt::cyan;
  1180. QColor couleur_aigrettes = Qt::white;
  1181. QColor couleur_nom_etoile = gris_fonce;
  1182. QColor couleur_NGC = vert_fonce;
  1183. QColor couleur_champ_CCD = Qt::red;
  1184.  
  1185. if (actionMode_Impression->isChecked())
  1186. {
  1187. couleur_ciel = Qt::white;
  1188. couleur_grille = Qt::black;
  1189. couleur_texte_grille = Qt::black;
  1190. couleur_centre = Qt::black;
  1191. couleur_zones_BSC = Qt::black;
  1192. couleur_ecliptique = Qt::black;
  1193. couleur_pointVernal = Qt::black;
  1194. couleur_lignes_cstl = Qt::black;
  1195. couleur_noms_cstl = Qt::black;
  1196. couleur_point_vise = Qt::black;
  1197. couleur_aigrettes = Qt::black;
  1198. couleur_nom_etoile = Qt::black;
  1199. couleur_NGC = Qt::black;
  1200. couleur_champ_CCD = Qt::black;
  1201. }
  1202.  
  1203. if (actionMode_Impression->isChecked())
  1204. {
  1205. x_max_image = 2400;
  1206. y_max_image = 1800;
  1207. }
  1208. else
  1209. {
  1210. x_max_image = x_max_ecran;
  1211. y_max_image = y_max_ecran;
  1212. }
  1213.  
  1214. int x_centre_ecran = x_max_image/2;
  1215. int y_centre_ecran = y_max_image/2;
  1216.  
  1217. pas_x = int(x_max_image/20);
  1218. pas_y = int(y_max_image/60);
  1219.  
  1220. QPixmap pixmap1(x_max_image, y_max_image);
  1221. pixmap1.fill(couleur_ciel);
  1222.  
  1223. if (actionMode_Impression->isChecked())
  1224. {
  1225. Pdecal_nom.setX(15);
  1226. Pdecal_nom.setY(40);
  1227. Pdecal_num.setX(15);
  1228. Pdecal_num.setY(10);
  1229. }
  1230. else
  1231. {
  1232. Pdecal_nom.setX(10);
  1233. Pdecal_nom.setY(20);
  1234. Pdecal_num.setX(10);
  1235. Pdecal_num.setY(10);
  1236. }
  1237.  
  1238. int ri = 0;
  1239. int di = 45*3600;
  1240.  
  1241. zoom = float(pow(2,zoom_double)) /4;
  1242.  
  1243. if ((mode_i == totalite) || (mode_i == impr))
  1244. {
  1245. QPainter painter1(& pixmap1); // adresse de pixmap1 dans le constructeur
  1246. QFont font1 = painter1.font();
  1247.  
  1248. //==================================================================================
  1249. // boites de coordonnees de l'objet pointe
  1250. frame_4->setVisible(!actionMode_Impression->isChecked());
  1251. frame_5->setVisible(!actionMode_Impression->isChecked());
  1252.  
  1253. //==================================================================================
  1254. // trace le centre de l'image
  1255. if ( !actionPasTracerCentre->isChecked() || actionMode_Impression->isChecked() )
  1256. {
  1257.  
  1258. painter1.setPen(couleur_centre);
  1259. //painter1.setBrush(Qt::white);
  1260. painter1.drawLine(x_centre_ecran-20,y_centre_ecran,x_centre_ecran-10,y_centre_ecran); // 1er segment H
  1261. painter1.drawLine(x_centre_ecran+10,y_centre_ecran,x_centre_ecran+20,y_centre_ecran); // 2nd segment H
  1262. painter1.drawLine(x_centre_ecran,y_centre_ecran-20,x_centre_ecran,y_centre_ecran-10); // 1er segment V
  1263. painter1.drawLine(x_centre_ecran,y_centre_ecran+10,x_centre_ecran,y_centre_ecran+20); // 2nd segment V
  1264.  
  1265. //int r = zoom*103; painter1.drawEllipse(x0,y0, r, r); // cercle de 10 degres de diametre
  1266. //float r = zoom*103/10/3600; painter1.drawEllipse(x0,y0, r, r); // cercle de 1 seconde de diametre
  1267. }
  1268.  
  1269. //==================================================================================
  1270. // trace de la grille equatoriale
  1271. int LBL; // Largeur Bande Laterale
  1272. QPoint memo_P;
  1273. memo_P.setX(0);
  1274. memo_P.setY(0);
  1275. // 1) trace les cercles des latitudes ("horizontales // equateur")
  1276. if (actionTracer_grille->isChecked())
  1277. {
  1278. // 1) trace les cercles des latitudes ("horizontales // equateur")
  1279. if (!actionMode_Impression->isChecked())
  1280. {
  1281. font1.setPointSize(10);
  1282. LBL=200;
  1283. }
  1284. else
  1285. {
  1286. font1.setPointSize(16);
  1287. LBL=400;
  1288. }
  1289. painter1.setFont(font1);
  1290. for (di=-90*3600; di<=90*3600; di+=10*3600) // pas = 10 degres
  1291. {
  1292. painter1.setPen(couleur_texte_grille);
  1293.  
  1294. for (ri=10*60; ri<23.5*3600; ri+=3600)
  1295. {
  1296. if (projection(ri, di, &P) == 0)
  1297. {
  1298. if ( P.x() > 0 && P.x() < x_max_image && P.y() > 30 && P.y() < y_max_image)
  1299. { //dans l'ecran
  1300. if ( P.x() < LBL || P.x() > x_max_image - LBL)
  1301. { // mais en peripherie seulement
  1302. txt_num.setNum(di / 3600); // conversion num -> txt
  1303. painter1.drawText(P,txt_num + "deg");
  1304. }
  1305. }
  1306. }
  1307. }
  1308. painter1.setPen(couleur_grille);
  1309. memo_P.setX(0);
  1310. memo_P.setY(0);
  1311. for (ri=0; ri<=23.5*3600; ri+=400)
  1312. {
  1313. if (projection(ri, di, &P) == 0)
  1314. {
  1315. if ((P.x()!=0)&&(P.y()!=0)&&(memo_P.x()!=0)&&(memo_P.y()!=0))
  1316. { painter1.drawLine(memo_P,P);}
  1317. memo_P = P;
  1318. //painter1.drawPoint(P); // trace un point
  1319. }
  1320. else memo_P.setX(0);
  1321. }
  1322. }
  1323. // 2) trace les cercles des longitudes ("verticales" passant par les poles)
  1324.  
  1325. ri = 0;
  1326. di = 45*3600;
  1327.  
  1328. for (ri=0*3600; ri<=23*3600; ri+=1*3600) // pas =1h
  1329. {
  1330. painter1.setPen(couleur_texte_grille);
  1331. for (di=-68; di<=72; di+=10)
  1332. {
  1333. if (projection(ri, di*3600, &P) == 0)
  1334. {
  1335. if ( P.x() > 0 && P.x() < x_max_image && P.y() > 30 && P.y() < y_max_image)
  1336. { //dans l'ecran
  1337. if (P.y() < LBL || P.y() > y_max_image - LBL/2 )
  1338. { // mais en peripherie seulement
  1339. txt_num.setNum(ri / 3600); // conversion num -> txt
  1340. painter1.drawText(P,txt_num + "h");
  1341. }
  1342. }
  1343. }
  1344. }
  1345.  
  1346. painter1.setPen(couleur_grille);
  1347. memo_P.setX(0);
  1348. memo_P.setY(0);
  1349. for (di=-90*3600; di<=90*3600; di+=4000)
  1350. {
  1351.  
  1352. if (projection(ri, di, &P) == 0)
  1353. {
  1354. if ((P.x()!=0)&&(P.y()!=0)&&(memo_P.x()!=0)&&(memo_P.y()!=0))
  1355. { painter1.drawLine(memo_P,P);}
  1356. memo_P = P;
  1357. //painter1.drawPoint(P); // trace un point
  1358. }
  1359. else memo_P.setX(0);
  1360. }
  1361. }
  1362. }
  1363. //==================================================================================
  1364. // trace des limites des zones BSC5
  1365. // 1) trace les cercles des latitudes ("horizontales // equateur")
  1366. if (actionTracer_limites_cartes_BSC5->isChecked())
  1367. {
  1368. painter1.setPen(couleur_zones_BSC);
  1369. for (di=-90*3600; di<=90*3600; di+=30*3600) // pas = 30 degres
  1370. {
  1371. for (ri=0; ri<=24*3600; ri+=200)
  1372. {
  1373. if (projection(ri, di, &P) == 0) { painter1.drawPoint(P);}
  1374. }
  1375. }
  1376. // 2) trace les arcs de cercles des longitudes ("verticales" passant par les poles)
  1377. int num_zone =1;
  1378. trace_bande_H(15, 30*240, num_zone, &painter1); // entre 0deg et 30deg -> 12 zones de 30deg
  1379. num_zone =13;
  1380. trace_bande_H(45, 40*240, num_zone, &painter1); // entre 30deg et 60deg -> 9 zones de 40deg
  1381. num_zone =22;
  1382. trace_bande_H(75, 90*240, num_zone, &painter1); // entre 60deg et 90deg -> 4 zones de 90deg
  1383. }
  1384.  
  1385. //==================================================================================
  1386. // trace de l'ecliptique (plan dans lequel se meuh, pardon meut la Terre autour du soleil)
  1387. // et par consequence dans lequel on voit le soleil et les planetes depuis la Terre
  1388. if (actionTracer_Ecliptique->isChecked())
  1389. {
  1390. double ri_float, di_float;
  1391. memo_P.setX(0);
  1392. memo_P.setY(0);
  1393. for (ri_float=0; ri_float<=24*3600; ri_float+=1000)
  1394. {
  1395. di_float = 23.5 * 3600 * sin(ri_float/(24*3600)*2*M_PI);
  1396. painter1.setPen(couleur_ecliptique);
  1397. if (projection(ri_float, di_float, &P) == 0)
  1398. {
  1399. if ((P.x()!=0)&&(P.y()!=0)&&(memo_P.x()!=0)&&(memo_P.y()!=0))
  1400. { painter1.drawLine(memo_P,P);}
  1401. memo_P = P;
  1402. }
  1403. else memo_P.setX(0);
  1404. }
  1405. }
  1406. //==================================================================================
  1407. font1.setPointSize(7); painter1.setFont(font1);
  1408. if (projection(0, 0, &P) == 0)
  1409. {
  1410. painter1.setPen(couleur_pointVernal);
  1411. painter1.drawLine(P.x()-5,P.y(),P.x()+5,P.y()); // aigrette V
  1412. painter1.drawLine(P.x(),P.y()-5,P.x(),P.y()+5); // aigrette H
  1413. painter1.drawText(P,"Point Vernal");
  1414. }
  1415. font1.setPointSize(8); painter1.setFont(font1);
  1416.  
  1417. //==================================================================================
  1418. //calcul des coordonnees des 4 coins de l'ecran
  1419. QPoint P1;
  1420. P1.setX(0); P1.setY(0);
  1421. projection_inverse(P1, &RA_aff_max, &DE_aff_max);
  1422. P1.setX(x_max_ecran); P1.setY(y_max_ecran);
  1423. projection_inverse(P1, &RA_aff_min, &DE_aff_min);
  1424. RA_min_deg = sec2deg_decim(RA_aff_min, isT)-1;
  1425. RA_max_deg = sec2deg_decim(RA_aff_max, isT)+1;
  1426. DE_min_deg = sec2deg_decim(DE_aff_min, isA)-2;
  1427. DE_max_deg = sec2deg_decim(DE_aff_max, isA)+2;
  1428.  
  1429. /*
  1430. //affichage (pour test)
  1431. QString RA_aff_min_txt, RA_aff_max_txt, DE_aff_min_txt, DE_aff_max_txt;
  1432. RA_aff_min_txt.setNum(RA_min_deg,'f',2);
  1433. RA_aff_max_txt.setNum(RA_max_deg,'f',2);
  1434. DE_aff_min_txt.setNum(DE_min_deg,'f',2);
  1435. DE_aff_max_txt.setNum(DE_max_deg,'f',2);
  1436. Edit_afficheur->setText(" RAmin=" + RA_aff_min_txt +" RAmax=" + RA_aff_max_txt
  1437. +" DEmin=" + DE_aff_min_txt +" DEmax=" + DE_aff_max_txt);
  1438. */
  1439.  
  1440. /*====================================================================================
  1441. BOUCLE DE DESSIN DES ETOILES du catalogue Tycho2
  1442. ======================================================================================*/
  1443. if (actionCatalogue_Tycho->isChecked() && !actionMode_Impression->isChecked())
  1444. {
  1445. if (!actionMode_Impression->isChecked()) {font1.setPointSize(8);} else {font1.setPixelSize(30);}
  1446. painter1.setFont(font1);
  1447. QString st1, st2;
  1448.  
  1449. if (spinBoxZoom->value() > 5)
  1450. {
  1451. etoiles_tyc_visibles = true; // sert en particulier pour le menu contextuel et "trouve_TYC_at_xy"
  1452. Liste_regions_tyc.clear();
  1453. liste_etoiles_TYC.clear();
  1454. get_LSTreg_tyc2(RA_min_deg, RA_max_deg, DE_min_deg, DE_max_deg, &Liste_regions_tyc, "/tycho2/", 'A');
  1455. get_lst_Tyc2(&liste_etoiles_TYC, &Liste_regions_tyc,"/tycho2/", 'A');
  1456.  
  1457. if (spinBoxZoom->value() > 6)
  1458. {
  1459. get_LSTreg_tyc2(RA_min_deg, RA_max_deg, DE_min_deg, DE_max_deg, &Liste_regions_tyc, "/tycho2/", 'B');
  1460. get_lst_Tyc2(&liste_etoiles_TYC, &Liste_regions_tyc,"/tycho2/", 'B');
  1461. }
  1462.  
  1463. TYC2rec etoile1;
  1464. int32_t i;
  1465. int32_t i_max = liste_etoiles_TYC.count();
  1466. float RAr, DEr;
  1467. long tyc_RA, tyc_DE;
  1468.  
  1469. painter1.setBrush(Qt::white);
  1470.  
  1471. for (i=0; i<i_max; i++)
  1472. {
  1473. etoile1 = liste_etoiles_TYC.at(i);
  1474.  
  1475. RAr =(float)etoile1.ra/15; //RAr en heures decimales (1 heure = 15 degres d'angle)
  1476. DEr =(float)etoile1.de;
  1477.  
  1478. tyc_RA =deg_decim2sec(RAr);
  1479. tyc_DE =deg_decim2sec(DEr);
  1480.  
  1481. uint8_t vt = etoile1.vt;
  1482.  
  1483. if (vt < spinBox_magnitude_max->value())
  1484. {
  1485. rayon_etoile = (10-vt) * zoom_double / 5.5 ;
  1486.  
  1487. if (actionEtoiles_ponctuelles->isChecked()) {rayon_etoile=1;}
  1488.  
  1489. if (projection(tyc_RA, tyc_DE, &P) == 0)
  1490. {
  1491. if (rayon_etoile < 1)
  1492. {
  1493. painter1.setPen(Qt::white);
  1494. painter1.drawPoint(P);
  1495. }
  1496. else
  1497. {
  1498. painter1.setPen(Qt::NoPen);
  1499. painter1.setBrush(Qt::white);
  1500. painter1.drawEllipse(P,int(rayon_etoile),int(rayon_etoile));
  1501. }
  1502.  
  1503. }
  1504. }
  1505. }
  1506. }
  1507. else { etoiles_tyc_visibles = false;}
  1508. }
  1509.  
  1510. /*====================================================================================
  1511. BOUCLE DE DESSIN DES ETOILES du catalogue BSC5
  1512. ======================================================================================*/
  1513. if (!actionMode_Impression->isChecked()) {font1.setPointSize(8);} else {font1.setPixelSize(30);}
  1514. painter1.setFont(font1);
  1515.  
  1516. QRadialGradient radialGradient1;
  1517.  
  1518. // painter1.setPen(Qt::NoPen);
  1519.  
  1520. //parcours la Table Winget1
  1521. row = 0;
  1522. while (row < 9110)
  1523. {
  1524. txt1 = TableWidget_BSC->item(row,colMV)->text(); // magnitude
  1525. mv = txt1.toFloat(); // conversion txt -> num
  1526.  
  1527. if (mv < spinBox_magnitude_max->value())
  1528. {
  1529. extraire_RA_DE_from_Tableau(row, &RA_s, &DE_s); //RA et DE
  1530. P.setX(0);
  1531. P.setY(0);
  1532.  
  1533. // x et y vont etre calcules par la fonction 'projection' qui retourne 0 si le point est en arriere de l'observateur
  1534. if (projection(RA_s, DE_s, &P) == 0) // x et y sont calcules par cette fonction
  1535. {
  1536. if ( P.x() > 0 && P.x() < x_max_image && P.y() > 30 && P.y() < y_max_image )
  1537. {
  1538. //listePoints << P;
  1539.  
  1540. txt_numHR = TableWidget_BSC->item(row,colHR)->text(); // Numero HR
  1541. nomCommun = TableWidget_BSC->item(row,colNomCom)->text();//+ QChar(945); // Nom commun
  1542. removeCaractere('-', &nomCommun);
  1543. classeSpectrale = TableWidget_BSC->item(row,colClsSpect)->text(); // couleur
  1544. removeCaractere(' ', &classeSpectrale);
  1545. cstl = TableWidget_BSC->item(row,colCSTL)->text(); // Constellation
  1546. bayer = TableWidget_BSC->item(row,colNomBay)->text(); // abrev lettre grecque de bayer
  1547. int code_unicode_bayer = code_grec(bayer.left(3));
  1548.  
  1549. calcul_aspect_etoile(mv, &z, &rayon_etoile, &rayon_halo, &lum1);
  1550. int demiRayonH = rayon_halo/2;
  1551.  
  1552. if (classeSpectrale.at(0) == 'O') { couleur_etoile = Tableau_couleurs_etoiles[0];;}
  1553. else if (classeSpectrale.at(0) == 'B') { couleur_etoile = Tableau_couleurs_etoiles[1]; }
  1554. else if (classeSpectrale.at(0) == 'A') { couleur_etoile = Tableau_couleurs_etoiles[2]; }
  1555. else if (classeSpectrale.at(0) == 'F') { couleur_etoile = Tableau_couleurs_etoiles[3]; }
  1556. else if (classeSpectrale.at(0) == 'G') { couleur_etoile = Tableau_couleurs_etoiles[4]; }
  1557. else if (classeSpectrale.at(0) == 'K') { couleur_etoile = Tableau_couleurs_etoiles[5]; }
  1558. else if (classeSpectrale.at(0) == 'M') { couleur_etoile = Tableau_couleurs_etoiles[6]; }
  1559. else { couleur_etoile = Qt::white; }
  1560.  
  1561. couleur_etoile.getHsv(&h,&s,&v,&a);
  1562. //couleur_etoile.setHsv(h,saturation,lum1,a);
  1563. couleur_etoile.setHsv(h,saturation,v,a);
  1564.  
  1565. if (actionEtoiles_blanches->isChecked()) {couleur_etoile = Qt::white;}
  1566. if (actionMode_Impression->isChecked()) {couleur_etoile = Qt::black;}
  1567. if (actionSouligner_Etoiles_d_une_CSTL->isChecked())
  1568. {
  1569. if (cstl == cstl_pointee) { couleur_etoile = Qt::green;}
  1570. }
  1571.  
  1572. couleur_halo = couleur_etoile;
  1573. couleur_halo.getHsv(&h,&s,&v,&a);
  1574. couleur_halo.setHsv(h,s,255,100);
  1575. a=0;
  1576.  
  1577. radialGradient1.setColorAt(0.0, couleur_halo);
  1578. radialGradient1.setColorAt(1.0, Qt::black);
  1579.  
  1580. // DESSIN DES ETOILES
  1581. // 1 ) Aigrettes
  1582. centre = P;
  1583. if (zoom > 1)
  1584. {
  1585. if (rayon_halo > 20)
  1586. {
  1587. if (!actionEtoiles_ponctuelles->isChecked())
  1588. {
  1589. QPen pen(couleur_aigrettes);
  1590. pen.setWidth(1);
  1591. painter1.setPen(pen);
  1592. painter1.drawLine(P.x()-demiRayonH,P.y(),P.x()+demiRayonH,P.y()); // aigrette V
  1593. painter1.drawLine(P.x(),P.y()-demiRayonH,P.x(),P.y()+demiRayonH); // aigrette H
  1594. }
  1595. }
  1596. // 2) halo
  1597. if (!actionMode_Impression->isChecked()
  1598. && !actionEtoiles_ponctuelles->isChecked()
  1599. && !actionPas_de_halo->isChecked()
  1600. )
  1601. {
  1602. painter1.setBrush(couleur_halo);
  1603. painter1.setPen(Qt::NoPen);
  1604. radialGradient1.setCenter(P);
  1605. radialGradient1.setRadius(rayon_halo);
  1606. radialGradient1.setFocalPoint(P);
  1607. painter1.setBrush(radialGradient1);
  1608. painter1.drawEllipse(P,rayon_halo,rayon_halo);
  1609.  
  1610. }
  1611. }
  1612. // 3) disque de l'etoile
  1613. painter1.setBrush(couleur_etoile);
  1614. painter1.setPen(couleur_etoile);
  1615. if (rayon_etoile < 1.5)
  1616. {
  1617. painter1.setBrush(Qt::NoBrush);
  1618. painter1.drawPoint(P); // ponctuel
  1619. }
  1620. else
  1621. {
  1622. if (actionMode_Impression->isChecked())
  1623. {
  1624. painter1.setBrush(Qt::NoBrush);
  1625. }
  1626. else { painter1.setPen(Qt::NoPen);}
  1627.  
  1628. painter1.drawEllipse(P,int(rayon_etoile),int(rayon_etoile)); // dessine une etoile
  1629. }
  1630. //affichage du numero HR et du Nom
  1631. painter1.setPen(couleur_nom_etoile);
  1632. painter1.setBrush(Qt::NoBrush);
  1633. QPoint P_rayonEtoile;
  1634. P_rayonEtoile.setX(rayon_etoile);
  1635. P_rayonEtoile.setY(0);
  1636.  
  1637. QPoint P1 = P + P_rayonEtoile;
  1638. x = int(P1.x() / pas_x);
  1639. y = int(P1.y() / pas_y);
  1640.  
  1641. if (actionLettres_grecques->isChecked() && code_unicode_bayer !=-1)
  1642. {
  1643. font1.setPixelSize(16); painter1.setFont(font1);
  1644. painter1.setPen(couleur_etoile);
  1645. painter1.drawText(P1, QChar(code_unicode_bayer));
  1646. }
  1647. else if (actionAfficher_Noms->isChecked() && (nomCommun != "~"))
  1648. {
  1649. if (actionMode_Impression->isChecked())
  1650. { //en mode impression on evite le chevauchement des textes
  1651. if (tableau_cases[x][y+1] == false )
  1652. { // la case est libre
  1653. //painter1.drawRect(pas_x * x, pas_y * y, pas_x, pas_y);
  1654. painter1.drawText(pas_x * x, pas_y * (y+1) +50,nomCommun);
  1655. tableau_cases[x][y+1] = true; // on coche la case
  1656. }
  1657. }
  1658. else
  1659. { // en mode affichage ecran, on ecrit directement au plus pres de l'etoile
  1660. painter1.drawText(P1,nomCommun);
  1661. }
  1662. }
  1663. if (actionAfficher_Numeros->isChecked())
  1664. {
  1665. if (actionMode_Impression->isChecked())
  1666. { //en mode impression on evite le chevauchement des textes
  1667. if (tableau_cases[x][y] == false )
  1668. { // la case est libre
  1669. //painter1.drawRect(x * pas_x, pas_y * (y+1), pas_x, pas_y);
  1670. //painter1.drawLine(P.x(),P.y(),x * pas_x, pas_y * (y+1) +40);
  1671. painter1.drawText(x * pas_x, pas_y * y +50,txt_numHR);
  1672. tableau_cases[x][y] = true; // on coche la case
  1673. }
  1674. }
  1675. else
  1676. {
  1677. painter1.drawText(P + P_rayonEtoile + Pdecal_num,txt_numHR);
  1678. }
  1679. }
  1680. }
  1681. }
  1682. }
  1683. row++;
  1684. }
  1685.  
  1686. /*====================================================================================
  1687. BOUCLE DE DESSIN DES OBJETS du catalogue SAC (Ciel profond)
  1688. ======================================================================================*/
  1689. if (actionCiel_Profond->isChecked())
  1690. {
  1691. if (!actionMode_Impression->isChecked()) { font1.setPointSize(7);} else {font1.setPixelSize(25);}
  1692. painter1.setFont(font1);
  1693. row = 0;
  1694. while (row < nb_objets_SAC)
  1695. {
  1696. txt1 = TableWidget_NGC->item(row,colNGCMagn)->text(); // magnitude
  1697. mv = txt1.toFloat(); // conversion txt -> num
  1698. nom2 = TableWidget_NGC->item(row,colNGCNom2)->text(); // Nom2
  1699. bool isMessier = ( (nom2[0] == 'M') && nom2[1].isNumber() && nom2[2].isNumber());
  1700.  
  1701. if ( mv < spinBoxNGC_mag_max->value() || isMessier )
  1702. { // on affiche toujours les objets Messier quel que soit leur magnitude
  1703. txt1 = TableWidget_NGC->item(row,colNGCRA)->text(); // RA
  1704. RA_s = txt1.toInt();
  1705. txt1 = TableWidget_NGC->item(row,colNGCDE)->text(); // DE
  1706. DE_s = txt1.toLong();
  1707.  
  1708. txt1 = TableWidget_NGC->item(row,colNGCDiam)->text(); // diametre en secondes
  1709. long diametre_NGC = txt1.toLong();//en secondes
  1710. float d_NGC = zoom * diametre_NGC*103/10/3600; // en pixels
  1711.  
  1712. P.setX(0);
  1713. P.setY(0);
  1714.  
  1715. if (projection(RA_s, DE_s, &P) == 0) // x et y sont calcules par cette fonction
  1716. {
  1717. if ( P.x() > 0 && P.x() < x_max_image && P.y() > 30 && P.y() < y_max_image )
  1718. {
  1719. nom1 = TableWidget_NGC->item(row,colNGCNom1)->text(); // Nom1
  1720.  
  1721. if ((!actionObjetsSDcardSeulement->isChecked()) || (nom1.left(3) == "NGC") )
  1722. {
  1723. if (actionAfficher_Noms->isChecked() && (nom1 != "~"))
  1724. {
  1725. painter1.setPen(couleur_NGC);
  1726. if (actionMode_Impression->isChecked())
  1727. {
  1728. painter1.setBackgroundMode(Qt::OpaqueMode);
  1729. x = int(P.x() / pas_x);
  1730. y = int(P.y() / pas_y);
  1731.  
  1732. while ((x<20) && (y<60) && ((tableau_cases[x][y] == true ) || (tableau_cases[x+1][y] == true)))
  1733. { //tant que les deux cases ne sont pas libres pas libre, on decalle
  1734. x++;
  1735. y++;
  1736. }
  1737. painter1.drawLine(P.x(),P.y(),pas_x * x, pas_y * y +50);
  1738. painter1.drawText(pas_x * x, pas_y * y +50, nom1 +" " +nom2);
  1739. tableau_cases[x][y] = true; // on coche la case
  1740. tableau_cases[x+1][y] = true; // ainsi que la suivante
  1741. }
  1742. else {painter1.drawText(P+Pdecal_nom,nom1 +" " +nom2);}
  1743. //painter1.drawText(P+Pdecal_num,nom2);
  1744. }
  1745. painter1.setBrush(Qt::NoBrush);
  1746. if (actionMode_Impression->isChecked())
  1747. {
  1748. painter1.setPen(Qt::black);
  1749. painter1.drawEllipse(P.x()-d_NGC/2,P.y()-d_NGC/2, d_NGC, d_NGC); // dessine un objet
  1750. }
  1751. else
  1752. {
  1753. painter1.setPen(couleur_NGC);
  1754. painter1.drawEllipse(P.x()-d_NGC/2,P.y()-d_NGC/2, d_NGC, d_NGC); // dessine un objet
  1755. painter1.drawLine(P.x()-d_NGC/10,P.y()-d_NGC/10,P.x()+d_NGC/10,P.y()+d_NGC/10); // x pour situer le centre
  1756. painter1.drawLine(P.x()-d_NGC/10,P.y()+d_NGC/10,P.x()+d_NGC/10,P.y()-d_NGC/10);
  1757. }
  1758. }
  1759. }
  1760. }
  1761. }
  1762. row++;
  1763. }
  1764. }
  1765. //====================================================================================
  1766. // trace le dessin des constellations
  1767. trace_constellations(&painter1, couleur_lignes_cstl, couleur_noms_cstl);
  1768. //====================================================================================
  1769. // trace le champ CCD
  1770. if (actionAfficher_champ_CCD->isChecked())
  1771. {
  1772. painter1.setPen(couleur_champ_CCD);
  1773. painter1.setBrush(Qt::NoBrush);
  1774. float r = zoom*103/10/60; // 1' d'angle
  1775. int x_champ = 154*r; // pour un capteur 24x36mm (APN K100D) au foyer d'une focale de 600mm
  1776. int y_champ = 2 * x_champ / 3; // pour un capteur au format 3/2
  1777. painter1.drawRect(x_centre_ecran-x_champ/2, y_centre_ecran-y_champ/2, x_champ, y_champ);
  1778.  
  1779. }
  1780. //====================================================================================
  1781. // Imprime les coordonnees du centre de la page dans un cartouche en haut a gauche de la page
  1782. if (actionMode_Impression->isChecked())
  1783. {
  1784. RAcentre_txt = nb_secondes2txt_hms(RA_centre);
  1785. DEcentre_txt = nb_secondes2txt_hms(DE_centre);
  1786. int x0 =30;
  1787. int y0 = 3;
  1788. painter1.setPen(Qt::black);
  1789. painter1.setBrush(Qt::white);
  1790. painter1.setBackgroundMode(Qt::OpaqueMode);
  1791. painter1.drawRect(x0, y0, 250, 100); // cartouche
  1792.  
  1793. painter1.setBackgroundMode(Qt::TransparentMode);
  1794. painter1.setBrush(Qt::NoBrush);
  1795. painter1.drawText(x0+10,y0+30, "Centre de la page:");
  1796. painter1.drawText(x0+10,y0+60, "RA=" +RAcentre_txt);
  1797. painter1.drawText(x0+10,y0+90, "DE=" + DEcentre_txt);
  1798.  
  1799. // trace un rectangle autour de la zone imprimee
  1800. painter1.drawRect(0,0, x_max_image-1, y_max_image-3);
  1801. }
  1802. //====================================================================================
  1803. if (!actionEtoiles_blanches->isChecked() && (!actionMode_Impression->isChecked()))
  1804. {
  1805. affiche_legende_etoiles(&painter1);
  1806. }
  1807.  
  1808. }
  1809. /*====================================================================================
  1810. AFFICHAGE PARTIEL dans les modes ci-dessous
  1811. (ne tracent pas la totalite, mais juste un detail. Rechargent l'image du ciel precedemment
  1812. affichee sur laquelle on va continuer a dessiner)
  1813. ====================================================================================*/
  1814.  
  1815. else if (mode_i == partiel_BSC) //concerne: ETOILES BSC
  1816. {
  1817. pixmap1 = QPixmap::fromImage(image1);
  1818. QPainter painter2(& pixmap1); // adresse de pixmap1 dans le constructeur
  1819. QFont font1 = painter2.font();
  1820. row = num_objet_BSC_pointe -1;
  1821. extraire_RA_DE_from_Tableau(row, &RA_s, &DE_s); //RA et DE
  1822. P.setX(0);
  1823. P.setY(0);
  1824. // x et y vont etre calcules par la fonction 'projection' qui retourne 0 si le point est en arriere de l'observateur
  1825. if (projection(RA_s, DE_s, &P) == 0) // x et y sont calcules par cette fonction
  1826. {
  1827. if ( P.x() > 0 && P.x() < x_max_image && P.y() > 30 && P.y() < y_max_image )
  1828. {
  1829. txt_numHR = TableWidget_BSC->item(row,colHR)->text(); // Numero BSC
  1830. nomCommun = TableWidget_BSC->item(row,colNomCom)->text(); // Nom commun
  1831. removeCaractere('-', &nomCommun);
  1832. font1.setPointSize(7); painter2.setFont(font1);
  1833. painter2.setPen(Qt::cyan);
  1834. if (nomCommun !="~") {painter2.drawText(P+Pdecal_nom,nomCommun);}
  1835. painter2.drawText(P+Pdecal_num,"HR" + txt_numHR);
  1836.  
  1837. QString Nom=TableWidget_BSC->item(row, colNomCom)->text();
  1838. Edit_objPointe->setText("HR" + txt_numHR + " " +Nom);
  1839. txt1=TableWidget_BSC->item(row, colRA)->text();
  1840. long RAs=txt1.toLong();
  1841. Edit_RAobjPointe->setText(nb_secondes2txt_hms (RAs));
  1842. txt1=TableWidget_BSC->item(row, colDE)->text();
  1843. long DEs = txt1.toLong(); // conversion txt -> num
  1844. Edit_DEobjPointe->setText(nb_secondes2txt_hms (DEs));
  1845. }
  1846. }
  1847.  
  1848. }
  1849. else if (mode_i == partiel_NGC) //concerne: OBJETS NGC
  1850. {
  1851. pixmap1 = QPixmap::fromImage(image1);
  1852. QPainter painter2(& pixmap1); // adresse de pixmap1 dans le constructeur
  1853. QFont font1 = painter2.font();
  1854. QString nom1, nom2;
  1855. row = num_objet_SAC_pointe -1;
  1856. txt1 = TableWidget_NGC->item(row,colNGCRA)->text(); // RA
  1857. RA_s = txt1.toInt();
  1858. txt1 = TableWidget_NGC->item(row,colNGCDE)->text(); // DE
  1859. DE_s = txt1.toLong();
  1860.  
  1861. P.setX(0);
  1862. P.setY(0);
  1863. // x et y vont etre calcules par la fonction 'projection' qui retourne 0 si le point est en arriere de l'observateur
  1864. if (projection(RA_s, DE_s, &P) == 0) // x et y sont calcules par cette fonction
  1865. {
  1866. if ( P.x() > 0 && P.x() < x_max_image && P.y() > 30 && P.y() < y_max_image )
  1867. {
  1868. font1.setPointSize(7); painter2.setFont(font1);
  1869. painter2.setPen(Qt::cyan);
  1870. nom1=TableWidget_NGC->item(row, colNGCNom1)->text();
  1871. nom2=TableWidget_NGC->item(row, colNGCNom2)->text();
  1872. painter2.drawText(P+Pdecal_nom, nom1);
  1873. painter2.drawText(P+Pdecal_num, nom2);
  1874. Edit_objPointe->setText(nom1 +" "+nom2);
  1875. Edit_RAobjPointe->setText(nb_secondes2txt_hms (RA_s));
  1876. Edit_DEobjPointe->setText(nb_secondes2txt_hms (DE_s));
  1877. }
  1878. }
  1879. }
  1880.  
  1881. else if (mode_i == partiel_TYC) //concerne: ETOILES TYCHO
  1882. {
  1883. pixmap1 = QPixmap::fromImage(image1);
  1884. QPainter painter3(& pixmap1); // adresse de pixmap1 dans le constructeur
  1885. QFont font1 = painter3.font();
  1886. QString st1, st2;
  1887. TYC2rec etoile1 = liste_etoiles_TYC.at(num_etoile_TYC_pointe);
  1888. float RAr =(float)etoile1.ra/15;
  1889. float DEr =(float)etoile1.de;
  1890. long tyc_RA =deg_decim2sec(RAr);
  1891. long tyc_DE =deg_decim2sec(DEr);
  1892.  
  1893. // P.setX(0);
  1894. // P.setY(0);
  1895. // x et y vont etre calcules par la fonction 'projection' qui retourne 0 si le point est en arriere de l'observateur
  1896. if (projection(tyc_RA, tyc_DE, &P) == 0) // x et y sont calcules par cette fonction
  1897. {
  1898. font1.setPointSize(7); painter3.setFont(font1);
  1899. painter3.setPen(Qt::yellow);
  1900. painter3.setBrush(Qt::NoBrush);
  1901. painter3.drawEllipse(P,5,5);
  1902. st1.setNum(etoile1.gscz);
  1903. st1=st1.right(4);
  1904. st2.setNum(etoile1.gscn);
  1905. painter3.drawText(P.x()+7,P.y(), "TIC "+st1 +"-"+st2);
  1906.  
  1907. Edit_objPointe->setText("TIC "+st1 +"-"+st2);
  1908. Edit_RAobjPointe->setText(nb_secondes2txt_hms (tyc_RA));
  1909. Edit_DEobjPointe->setText(nb_secondes2txt_hms (tyc_DE));
  1910.  
  1911. }
  1912. }
  1913.  
  1914. image1 = pixmap1.toImage();
  1915.  
  1916. if (actionMode_Impression->isChecked())
  1917. { label_5->setScaledContents(true); }
  1918. else { label_5->setScaledContents(false);} // important, sinon projection inverse fausse!
  1919.  
  1920. label_5->setPixmap(pixmap1);
  1921.  
  1922. num_objet_SAC = num_objet_SAC_pointe;
  1923. setCursor(Qt::ArrowCursor);
  1924. }
  1925.  
  1926.  
  1927. void MainWindow::on_tabWidget1_currentChanged(int index)
  1928. {
  1929. if ((index == 0) ) //onglet tableau BSC5
  1930. {
  1931. // tabWidget1->resize(size1);
  1932. // this->resize(size1+size_bordure);
  1933. TableWidget_BSC->selectRow(num_objet_BSC_pointe-1);
  1934. }
  1935. else if ((index == 1) ) //onglet tableau NGC SKY
  1936. {
  1937. // tabWidget1->resize(size1);
  1938. // this->resize(size1+size_bordure);
  1939. TableWidget_NGC->selectRow(num_objet_SAC_pointe-1);
  1940. }
  1941. else if (index == 2) //onglet dessin de la carte
  1942. {
  1943. num_objet_BSC = TableWidget_BSC->currentRow()+1;
  1944. num_objet_SAC = TableWidget_NGC->currentRow()+1;
  1945. //tabWidget1->resize(2000,1500);
  1946. //label_5->setGeometry(0,0,w-40,h-40);
  1947. //label_5->setGeometry(0,0,1200,900);
  1948.  
  1949. // tabWidget1->resize(size2);
  1950. // this->resize(size2+size_bordure);
  1951. // label_5->setGeometry(0,0,1200,800);
  1952. a_dessiner = true;
  1953. dessiner_ciel(totalite);
  1954. }
  1955. else if (index == 3) //onglet texte DOC
  1956. {
  1957. // this->showMaximized();
  1958. int w = this->width();
  1959. int h = this->height();
  1960. // tabWidget1->resize(2000,1500);
  1961. listeDoc->resize(w-20,h-10);
  1962. }
  1963. }
  1964.  
  1965.  
  1966. void MainWindow::calcul_num_zone_BSC()
  1967. //determine le numero de zone (catalogue BSC) figurant au centre de l'ecran
  1968. {
  1969. int bande_DEC = 0;
  1970. QString str1;
  1971.  
  1972. //hemisphere nord ==============================================================================
  1973. if ((DE_centre > 0) && (DE_centre < 30*3600))
  1974. {
  1975. bande_DEC=15; // decli du centre de la bande qui comporte 12 zones de 30deg en RA
  1976. num_zone_BSC_centre = 1+(RA_centre/3600*15/30)%12;
  1977. }
  1978. else if ((DE_centre > 30*3600) && (DE_centre < 60*3600))
  1979. {
  1980. bande_DEC=45; // decli du centre de la bande qui comporte 9 zones de 40deg en RA
  1981. num_zone_BSC_centre = 13+(RA_centre/3600*15/40)%9;
  1982. }
  1983. else if ((DE_centre > 60*3600) && (DE_centre < 90*3600))
  1984. {
  1985. bande_DEC=75; // decli du centre de la bande qui comporte 4 zones de 90deg en RA
  1986. num_zone_BSC_centre = 22+(RA_centre/3600*15/90)%4;
  1987. }
  1988. //hemisphere sud ===============================================================================
  1989. if ((DE_centre < 0) && (DE_centre > -30*3600))
  1990. {
  1991. bande_DEC=-15; // decli du centre de la bande qui comporte 12 zones de 30deg en RA
  1992. num_zone_BSC_centre = 1+25+(RA_centre/3600*15/30)%12;
  1993. }
  1994. else if ((DE_centre < 30*3600) && (DE_centre > -60*3600))
  1995. {
  1996. bande_DEC=-45; // decli du centre de la bande qui comporte 9 zones de 40deg en RA
  1997. num_zone_BSC_centre = 25+13+(RA_centre/3600*15/40)%9;
  1998. }
  1999. else if ((DE_centre < 60*3600) && (DE_centre > 90*3600))
  2000. {
  2001. bande_DEC=-75; // decli du centre de la bande qui comporte 4 zones de 90deg en RA
  2002. num_zone_BSC_centre = 25+22+(RA_centre/3600*15/90)%4;
  2003. }
  2004. // =============================================================================================
  2005.  
  2006. str1.setNum(num_zone_BSC_centre); // conversion num -> txt
  2007. //Edit_zone_BSC_pointee->setText(str1);
  2008. str1.setNum(bande_DEC); // conversion num -> txt
  2009. //Edit_bande_DE->setText(str1);
  2010. }
  2011.  
  2012.  
  2013. int MainWindow::trouve_TYC_at_xy(QPoint P)
  2014. //retourne le numero HR de l'objet le plus proche de la position fournie
  2015. {
  2016. if (etoiles_tyc_visibles)
  2017. {
  2018. QString txt1;
  2019. bool ok=false;
  2020. TYC2rec etoile1;
  2021. int32_t i;
  2022. int32_t i_max = liste_etoiles_TYC.count();
  2023. float RAr, DEr;
  2024. long tyc_RA, tyc_DE;
  2025. num_etoile_TYC_pointe = 0;
  2026. i =1;
  2027. while ( (i < i_max) && !ok)
  2028. {
  2029. etoile1 = liste_etoiles_TYC.at(i);
  2030. RAr =(float)etoile1.ra/15; //etoile1.ra en degres d'angle; RAr en heures decimales
  2031. DEr =(float)etoile1.de;
  2032. tyc_RA =deg_decim2sec(RAr);
  2033. tyc_DE =deg_decim2sec(DEr);
  2034.  
  2035. P.setX(0);
  2036. P.setY(0);
  2037. // x et y vont etre calcules par la fonction 'projection' qui retourne 0 si le point est en arriere de l'observateur
  2038. if (projection(tyc_RA, tyc_DE, &P) == 0) // x et y sont calcules par cette fonction
  2039. { // on ne teste que les etoiles situee devant l'observateur
  2040. if ( P.x() > 0 && P.x() < x_max_image && P.y() > 30 && P.y() < y_max_image )
  2041. {// on ne teste que les etoiles projetables dans le rectangle de l'ecran
  2042. if ( (sqrt((P.x()-PosX)*(P.x()-PosX)+(P.y()-PosY)*(P.y()-PosY))) < 10)
  2043. { // on teste par calcul de la distance dans le plan de projection
  2044. num_etoile_TYC_pointe = i; // pour selectionner la ligne concernee dans le tableau
  2045. ok = true;
  2046. }
  2047. }
  2048. }
  2049.  
  2050. i++;
  2051. }
  2052. }
  2053. else num_etoile_TYC_pointe =0;
  2054. return num_etoile_TYC_pointe;
  2055. }
  2056.  
  2057.  
  2058. int MainWindow::trouve_NGC_at_xy(QPoint P)
  2059. //retourne le numero HR de l'objet le plus proche de la position fournie
  2060. {
  2061. QString txt1;
  2062. long RA_s, DE_s;
  2063. float mv;
  2064. int row = 0;
  2065. num_objet_SAC_pointe = 0;
  2066. bool ok=false;
  2067. while ( (row < nb_objets_SAC-1) && !ok)
  2068. {
  2069. txt1 = TableWidget_NGC->item(row,colNGCMagn)->text(); // magnitude
  2070. mv = txt1.toFloat(); // conversion txt -> num
  2071.  
  2072. if (mv < spinBoxNGC_mag_max->value())
  2073. { // on ne teste que les objets suffisamment lumineux pour etre affichees
  2074. txt1 = TableWidget_NGC->item(row,colNGCRA)->text(); // RA
  2075. RA_s = txt1.toInt();
  2076. txt1 = TableWidget_NGC->item(row,colNGCDE)->text(); // DE
  2077. DE_s = txt1.toLong();
  2078.  
  2079. P.setX(0);
  2080. P.setY(0);
  2081. // x et y vont etre calcules par la fonction 'projection' qui retourne 0 si le point est en arriere de l'observateur
  2082. if (projection(RA_s, DE_s, &P) == 0) // x et y sont calcules par cette fonction
  2083. { // on ne teste que les etoiles situee devant l'observateur
  2084. if ( P.x() > 0 && P.x() < x_max_image && P.y() > 30 && P.y() < y_max_image )
  2085. {// on ne teste que les etoiles projetables dans le rectangle de l'ecran
  2086. if ( (sqrt((P.x()-PosX)*(P.x()-PosX)+(P.y()-PosY)*(P.y()-PosY))) < 10)
  2087. { // on teste par calcul de la distance dans le plan de projection
  2088. num_objet_SAC_pointe = row+1;
  2089. ok = true;
  2090. }
  2091. }
  2092. }
  2093. }
  2094. row++;
  2095. }
  2096. return num_objet_SAC_pointe;
  2097. }
  2098.  
  2099.  
  2100.  
  2101. int MainWindow::trouve_etoile_at_xy(QPoint P)
  2102. //retourne le numero HR de l'etoile la plus proche de la position fournie
  2103. {
  2104. QString txt1;
  2105. long RA_s, DE_s;
  2106. float mv;
  2107. int row = 0;
  2108. num_objet_BSC_pointe = 0;
  2109. bool ok=false;
  2110. while ( (row < 9110) && !ok)
  2111. {
  2112. txt1 = TableWidget_BSC->item(row,colMV)->text(); // magnitude
  2113. mv = txt1.toFloat(); // conversion txt -> num
  2114.  
  2115. if (mv < spinBox_magnitude_max->value())
  2116. { // on ne teste que les etoiles suffisamment lumineuses pour etre affichees
  2117. extraire_RA_DE_from_Tableau(row, &RA_s, &DE_s); //RA et DE
  2118. P.setX(0);
  2119. P.setY(0);
  2120. // x et y vont etre calcules par la fonction 'projection' qui retourne 0 si le point est en arriere de l'observateur
  2121. if (projection(RA_s, DE_s, &P) == 0) // x et y sont calcules par cette fonction
  2122. { // on ne teste que les etoiles situee devant l'observateur
  2123. if ( P.x() > 0 && P.x() < x_max_ecran && P.y() > 30 && P.y() < y_max_ecran )
  2124. {// on ne teste que les etoiles projetables dans le rectangle de l'ecran
  2125. if ( (sqrt((P.x()-PosX)*(P.x()-PosX)+(P.y()-PosY)*(P.y()-PosY))) < 10)
  2126. { // on teste par calcul de la distance dans le plan de projection
  2127. num_objet_BSC_pointe = row+1; // pour selectionner la ligne concernee dans le tableau
  2128. ok = true;
  2129. }
  2130. }
  2131. }
  2132. }
  2133. row++;
  2134. }
  2135. return num_objet_BSC_pointe;
  2136. }
  2137.  
  2138.  
  2139. void MainWindow::mousePressEvent(QMouseEvent *event)
  2140. //remarque: le menu contextuel qui s'ouvre avec le clic de droite n'est pas declenche ici,
  2141. //void MainWindow::contextMenuEvent
  2142. {
  2143. if (actionMode_Impression->isChecked())
  2144. {
  2145. actionMode_Impression->setChecked(false); // revient a l'affichage ciel noir avec menu contextuel actif
  2146. return; // a cause de recadrage de l'image + grande que l'ecran
  2147. }
  2148.  
  2149. QString txt_HR, txt1, Nom, nom1, nom2;
  2150. QPoint P;
  2151. long RAs, DEs;
  2152. if (event->button() == Qt::LeftButton)
  2153. {
  2154. PosX = event->x() - label_5->x()-1;
  2155. PosY = event->y() - label_5->y() - 55;
  2156. if (PosY < 20) { return;}
  2157.  
  2158. P.setX(PosX);
  2159. P.setY(PosY);
  2160. projection_inverse(P, &RAs, &DEs);
  2161. RA_pointe = RAs;
  2162. DE_pointe = DEs;
  2163.  
  2164. efface_position_pointee();
  2165.  
  2166. Edit_RAposPointe->setText(nb_secondes2txt_hms (RAs));
  2167. Edit_DEposPointe->setText(nb_secondes2txt_hms (DEs));
  2168. HR_pointe = trouve_etoile_at_xy(P);
  2169.  
  2170. if (actionSouligner_Etoiles_d_une_CSTL->isChecked())
  2171. {
  2172. if (HR_pointe !=0)
  2173. {
  2174. cstl_pointee = TableWidget_BSC->item(HR_pointe-1,colCSTL)->text();
  2175. a_dessiner = true;
  2176. dessiner_ciel(totalite);
  2177. }
  2178. }
  2179.  
  2180. if ((HR_pointe !=0) && (HR_pointe != memo_HR_pointe))
  2181. {
  2182. efface_objet_pointe();
  2183. a_dessiner = true;
  2184. dessiner_ciel(partiel_BSC); // rajoute l'etiquette a cote de l'etoile pointee
  2185.  
  2186. if (actionEditeur_de_Constellations->isChecked())
  2187. {
  2188. txt_HR.setNum(HR_pointe);
  2189. Edit_ligne_cstl->insert(txt_HR + "-") ;
  2190. }
  2191. memo_HR_pointe = HR_pointe;
  2192. }
  2193. NGC_pointe = trouve_NGC_at_xy(P);
  2194. if ((NGC_pointe !=0) && (NGC_pointe != memo_NGC_pointe))
  2195. {
  2196. efface_objet_pointe();
  2197. a_dessiner = true;
  2198. dessiner_ciel(partiel_NGC); // rajoute l'etiquette a cote de l'objet pointe
  2199. memo_NGC_pointe = NGC_pointe;
  2200. }
  2201. trouve_TYC_at_xy(P);
  2202. if ((num_etoile_TYC_pointe !=0) && etoiles_tyc_visibles )
  2203. {
  2204. a_dessiner = true;
  2205. dessiner_ciel(partiel_TYC); // rajoute l'etiquette a cote de l'etoile TYC pointe
  2206. }
  2207. }
  2208. event->accept();
  2209. }
  2210.  
  2211.  
  2212. void MainWindow::wheelEvent (QWheelEvent * event)
  2213. {
  2214. if (tabWidget1->currentIndex() != 2) return;
  2215.  
  2216. int numDegrees = event->delta() / 8;
  2217. int numSteps = numDegrees / 15;
  2218.  
  2219. if (event->orientation() == Qt::Vertical)
  2220. {
  2221. if (numSteps>0)
  2222. { spinBoxZoom->setValue(spinBoxZoom->value()+ 0.5);}
  2223. else
  2224. { spinBoxZoom->setValue(spinBoxZoom->value()- 0.5);}
  2225. }
  2226.  
  2227. event->accept();
  2228. }
  2229.  
  2230.  
  2231. void MainWindow::redimmensionner_tout()
  2232. {
  2233. tabWidget1->resize(w_ecran-10, h_ecran-30);
  2234. TableWidget_BSC->setFixedHeight(h_ecran-100);
  2235. TableWidget_NGC->setFixedHeight(h_ecran-100);
  2236. Liste_Messier->setFixedHeight(h_ecran-252);
  2237.  
  2238. listeDoc->setFixedWidth(w_ecran-20);
  2239. listeDoc->setFixedHeight(h_ecran-120);
  2240.  
  2241. label_5->setFixedWidth(w_ecran-20);
  2242. label_5->setFixedHeight(h_ecran-60);
  2243. x_max_ecran = w_ecran-10;
  2244. y_max_ecran = h_ecran-60;
  2245. a_dessiner = true;
  2246. dessiner_ciel(totalite);
  2247. }
  2248.  
  2249.  
  2250. void MainWindow::resizeEvent(QResizeEvent *event)
  2251. {
  2252. w_ecran = event->size().width();
  2253. h_ecran = event->size().height();
  2254. event->accept();
  2255. redimmensionner_tout();
  2256. }
  2257.  
  2258.  
  2259. void MainWindow::MAJ_zoom(double z)
  2260. {
  2261. zoom_double = z;
  2262. if (actionMagnitude_max_auto->isChecked())
  2263. {
  2264. if (z<3) { actionAfficher_Noms->setChecked(false);}
  2265. spinBox_magnitude_max->setValue(2 + 2*zoom_double);
  2266. }
  2267.  
  2268. if (!ne_pas_dessiner_maintenant)
  2269. {
  2270. a_dessiner = true;
  2271. dessiner_ciel(totalite);
  2272. }
  2273. }
  2274.  
  2275.  
  2276. void MainWindow::on_spinBox_latitude_valueChanged(int )
  2277. {
  2278. calcul_anglesABC();
  2279. if (!ne_pas_dessiner_maintenant)
  2280. {
  2281. a_dessiner = true;
  2282. dessiner_ciel(totalite);
  2283. }
  2284. }
  2285.  
  2286.  
  2287. void MainWindow::on_pushButton_Date_clicked()
  2288. {
  2289. if ( !calendrier1->isVisible ()) {calendrier1->show();} else {calendrier1->hide();}
  2290. }
  2291.  
  2292.  
  2293. void MainWindow::on_actionRecharger_fichier_constellations_activated()
  2294. {
  2295. int z3 = charger_figures_cstl(QDir::currentPath() + "/catalogues/figures_constellations.txt");
  2296. // si le fichier a ete trouve dans le dir /catalogues, alors z=0 sinon on le chercher dans le dir de l'executable
  2297. if (z3 == 1) { z3 = charger_figures_cstl (QDir::currentPath() +"/figures_constellations.txt");}
  2298. a_dessiner = true;
  2299. dessiner_ciel(totalite);
  2300. }
  2301.  
  2302.  
  2303.  
  2304. int MainWindow::Listage_objets_BSC() // dans le TableWidget_BSC
  2305. {
  2306. QString st1, st2;
  2307. long RAs, DEs;
  2308. int n;
  2309. int nb_objets_lus=0;
  2310. int i;
  2311. int hr;
  2312. BSCrec etoile_i;
  2313.  
  2314. int i_max = liste_etoiles_BSC.length();
  2315. for (i=0; i< i_max; i++)
  2316. {
  2317. etoile_i = liste_etoiles_BSC.at(i);
  2318. RAs = etoile_i.ra * 3600 /15;
  2319. if (RAs !=0)
  2320. {
  2321. hr = etoile_i.hr;
  2322. st1.setNum(RAs); // conversion num -> txt
  2323. TableWidget_BSC->setItem(hr-1, colRA, new QTableWidgetItem (st1) ); // RA
  2324. DEs = etoile_i.de * 3600;
  2325. if (DEs<0) {DEs = 324000 - DEs;}
  2326. st1.setNum(DEs); // conversion num -> txt
  2327. TableWidget_BSC->setItem(hr-1, colDE, new QTableWidgetItem (st1) ); // DE
  2328. st1=""; for (n=0; n<=3; n++) {st1 += etoile_i.bayer[n]; } //lettre de Bayer
  2329. removeCaractere(' ', &st1);
  2330. st2=""; for (n=0; n<=2; n++) {st2 += etoile_i.cstl[n]; } // constellation
  2331. removeCaractere(' ', &st2);
  2332. TableWidget_BSC->setItem(hr-1, colCSTL, new QTableWidgetItem (st2) ); // constellation
  2333. TableWidget_BSC->setItem(hr-1, colNomBay, new QTableWidgetItem (st1+" "+st2) );
  2334. st1.setNum(long(etoile_i.hd)); // conversion num -> txt
  2335. TableWidget_BSC->setItem(hr-1, colHD, new QTableWidgetItem (st1) ); //HD
  2336. st1.setNum(etoile_i.hr); // conversion num -> txt
  2337. TableWidget_BSC->setItem(hr-1, colHR, new QTableWidgetItem (st1) ); //HR
  2338. st1.setNum(etoile_i.mv, 'f',3); // conversion num -> txt
  2339. if (st1.length()==1) { st1+=".00"; }
  2340. if (st1.length()==2) { st1+="00"; }
  2341. if (st1.length()==3) { st1+="0"; }
  2342. if (st1.length() > 4) { st1 = st1.left(4); }
  2343. TableWidget_BSC->setItem(hr-1, colMV, new QTableWidgetItem (st1) ); // magnitude visuelle
  2344. st1.setNum(etoile_i.mv); // conversion num -> txt
  2345. TableWidget_BSC->setItem(hr-1, colClsSpect, new QTableWidgetItem (st1) );
  2346. st1=""; for (n=0; n<=15; n++) {st1 += etoile_i.sp[n]; }
  2347. removeCaractere(' ', &st1);
  2348. TableWidget_BSC->setItem(hr-1, colClsSpect, new QTableWidgetItem (st1) ); // Classe spectrale
  2349. }
  2350.  
  2351. }
  2352. TableWidget_BSC->resizeColumnsToContents();
  2353. return nb_objets_lus;
  2354. }
  2355.  
  2356.  
  2357. void MainWindow::Listage_noms_etoiles()
  2358. {
  2359. int n, p;
  2360. QString ligne, nom1, nbtxt;
  2361. int hr;
  2362. int nb_lignes = liste_noms_etoiles.size();
  2363. n=0;
  2364. while (n<nb_lignes)
  2365. {
  2366. ligne = liste_noms_etoiles.operator [](n);
  2367. listeNoms->addItem(ligne);
  2368.  
  2369. p=ligne.indexOf(";");
  2370. nbtxt=ligne.left(p);
  2371. hr = nbtxt.toInt();
  2372. ligne.remove(0, p+1);
  2373. p=ligne.indexOf(";");
  2374. nom1= ligne.left(p); // recupere le 1er nom de l'etoile
  2375. TableWidget_BSC->setItem(hr-1, colNomCom, new QTableWidgetItem (nom1) );
  2376. n++;
  2377. }
  2378. }
  2379.  
  2380.  
  2381. int MainWindow::charger_fichier_SAC() // catalogue SAC contenant (essentiellement) les objets NGC
  2382. {
  2383. QString SAC_fileName, txt, magnitude;
  2384. int row;
  2385. int p;
  2386. row=0;
  2387.  
  2388. QDir repertoire1;
  2389. repertoire1.setPath(QDir::currentPath());
  2390. SAC_fileName = repertoire1.path() + chemin_SAC + "NGC628f.txt";
  2391. QFile file1(SAC_fileName);
  2392. if (file1.exists()) { file1.open(QIODevice::ReadOnly | QIODevice::Text); }
  2393. else
  2394. {
  2395. repertoire1.cdUp(); //si lance depuis le repertoire /run
  2396. SAC_fileName = repertoire1.path() + chemin_SAC + "NGC628f.txt";
  2397. file1.setFileName(SAC_fileName);
  2398. if (file1.exists()) { file1.open(QIODevice::ReadOnly | QIODevice::Text); }
  2399. else {return 1;}
  2400. }
  2401. QTextStream textStream1(&file1);
  2402. while ( !textStream1.atEnd() )
  2403. {
  2404. QString ligne = textStream1.readLine();
  2405. //Nom1 ;Nom2 ;TYPE ;Constell ;RAs ;DEs ;MAG ;SIZE_MAX ;SIZE_MIN ;PA
  2406. //NGC7831 ;IC1530 ;GALXY ;AND ;438 ;117420 ;12,8 ;1.5m ;0.3m ;38
  2407. //le fichier ne comprend pas les tabulations
  2408. if (ligne.left(1) !="#")
  2409. {
  2410. p=ligne.indexOf(";");
  2411. txt = ligne.left(p);
  2412. TableWidget_NGC->setItem(row, colNGCNom1, new QTableWidgetItem (txt) );
  2413. //hr = nbtxt.toInt();
  2414.  
  2415. ligne.remove(0, p+1); p=ligne.indexOf(";"); txt = ligne.left(p);
  2416. TableWidget_NGC->setItem(row, colNGCNom2, new QTableWidgetItem (txt) );
  2417.  
  2418. ligne.remove(0, p+1); p=ligne.indexOf(";"); txt = ligne.left(p);
  2419. TableWidget_NGC->setItem(row, colNGCType, new QTableWidgetItem (txt) );
  2420.  
  2421. ligne.remove(0, p+1); p=ligne.indexOf(";"); txt = ligne.left(p);
  2422. TableWidget_NGC->setItem(row, colNGCCons, new QTableWidgetItem (txt) );
  2423.  
  2424. ligne.remove(0, p+1); p=ligne.indexOf(";"); txt = ligne.left(p);
  2425. TableWidget_NGC->setItem(row, colNGCRA, new QTableWidgetItem (txt) );
  2426.  
  2427. ligne.remove(0, p+1); p=ligne.indexOf(";"); txt = ligne.left(p);
  2428. TableWidget_NGC->setItem(row, colNGCDE, new QTableWidgetItem (txt) );
  2429.  
  2430. ligne.remove(0, p+1); p=ligne.indexOf(";"); txt = ligne.left(p);
  2431. TableWidget_NGC->setItem(row, colNGCMagn, new QTableWidgetItem (txt) );
  2432.  
  2433. ligne.remove(0, p+1); p=ligne.indexOf(";"); txt = ligne.left(p);
  2434. TableWidget_NGC->setItem(row, colNGCDiam, new QTableWidgetItem (txt) );
  2435.  
  2436. row++;
  2437. }
  2438. nb_objets_SAC = row;
  2439. }
  2440. TableWidget_NGC->resizeColumnsToContents();
  2441. TableWidget_NGC->setSelectionBehavior(QAbstractItemView::SelectRows);
  2442. TableWidget_NGC->selectRow(0);
  2443. return 0;
  2444. }
  2445.  
  2446.  
  2447. void MainWindow::on_timeEdit1_timeChanged(QTime )
  2448. {
  2449. calcul_anglesABC();
  2450. a_dessiner = true;
  2451. dessiner_ciel(totalite);
  2452. }
  2453.  
  2454.  
  2455. void MainWindow::on_spin_inc_date_valueChanged(int valeur)
  2456. {
  2457. QString txt1;
  2458. day_oh_year1 = valeur;
  2459. txt1.setNum(day_oh_year1); // conversion num -> txt
  2460. Edit_dayOfYear->setText(txt1 + "/365");
  2461. calendrier1->hide();
  2462. calcul_anglesABC();
  2463. a_dessiner = true;
  2464. dessiner_ciel(totalite);
  2465. }
  2466.  
  2467.  
  2468. void MainWindow::on_spinBox_magnitude_max_valueChanged(double )
  2469. {
  2470. if (!ne_pas_dessiner_maintenant)
  2471. {
  2472. a_dessiner = true;
  2473. dessiner_ciel(totalite);
  2474. }
  2475. }
  2476.  
  2477.  
  2478. void MainWindow::on_Bt_Go_clicked()
  2479. {
  2480. QString str1;
  2481. int hr;
  2482. long RA1, DE1;
  2483. QString RAs, DEs;
  2484. str1 = Edit_GoNumBSC->text();
  2485. hr = str1.toInt();
  2486. if ((hr>=0) && (hr < 9110))
  2487. {
  2488. TableWidget_BSC->setCurrentCell(hr-1,colRA); // pour selectionner la ligne (a l'affichage)
  2489. RAs=TableWidget_BSC->item(hr-1,colRA)->text();
  2490. RA1 = RAs.toInt(); // conversion txt -> num
  2491. DEs=TableWidget_BSC->item(hr-1,colDE)->text();
  2492. DE1 = DEs.toLong(); // conversion txt -> num
  2493. spinBoxZoom->setValue(3); // zoom
  2494. actionAfficher_Noms->setChecked(true);
  2495. centrer_position (RA1, DE1);
  2496. num_objet_BSC = hr;
  2497. num_objet_BSC_pointe = hr;
  2498. }
  2499. }
  2500.  
  2501.  
  2502. void MainWindow::on_listeNoms_currentRowChanged(int )
  2503. {
  2504. QString ligne, hrtxt;
  2505. int p;
  2506. ligne = listeNoms->currentItem()->text();
  2507. p=ligne.indexOf(";");
  2508. hrtxt=ligne.left(p);
  2509. Edit_GoNumBSC->setText(hrtxt);
  2510. on_Bt_Go_clicked();
  2511. }
  2512.  
  2513.  
  2514. void MainWindow::on_Edit_FindName_textChanged(QString )
  2515. {
  2516. QString ligne, nom1, nom2;
  2517. int nb_car;
  2518. int n, p;
  2519. int nb_lignes = listeNoms->count();
  2520. nom1 = Edit_FindName->text().toLower();
  2521. nb_car = nom1.length();
  2522. n=0;
  2523. ligne = "";
  2524. nom2 = "";
  2525. while((nom1.left(nb_car) != nom2.left(nb_car)) && (n < nb_lignes))
  2526. {
  2527. listeNoms->setCurrentRow(n);
  2528. ligne = listeNoms->item(n)->text();
  2529. p=ligne.indexOf(";");
  2530. ligne.remove(0, p+1);
  2531. p=ligne.indexOf(";");
  2532. nom2= ligne.left(p).toLower();
  2533. n++;
  2534. }
  2535. }
  2536.  
  2537.  
  2538. void MainWindow::on_spinBoxNGC_mag_max_valueChanged(double )
  2539. {
  2540. if (!ne_pas_dessiner_maintenant)
  2541. {
  2542. a_dessiner = true;
  2543. dessiner_ciel(totalite);
  2544. }
  2545. }
  2546.  
  2547.  
  2548. void MainWindow::rechercher_LW(QString txt_i, QListWidget *listWidget_i)
  2549. // Recherche d'un texte dans un QListWidget
  2550. {
  2551. QString txt2;
  2552. int p =0;
  2553. if (txt_i != "")
  2554. {
  2555. setCursor(Qt::WaitCursor);
  2556.  
  2557. int nb_lignes = listWidget_i->count();
  2558. int num_ligne = listWidget_i->currentRow()+1;
  2559. bool ok = false;
  2560. while((num_ligne < nb_lignes) && !ok)
  2561. {
  2562.  
  2563. txt2 = listWidget_i->item(num_ligne)->text();
  2564. if (txt2.contains(txt_i,Qt::CaseInsensitive))
  2565. {
  2566. p = txt2.indexOf(txt_i,Qt::CaseInsensitive);
  2567. ok = true;
  2568. }
  2569. else { num_ligne++; }
  2570. }
  2571. setCursor(Qt::ArrowCursor);
  2572. if (num_ligne < nb_lignes)
  2573. {
  2574. listWidget_i->setCurrentRow(num_ligne);
  2575. }
  2576. else
  2577. {
  2578. listWidget_i->setCurrentRow(0);
  2579. QMessageBox msgBox;
  2580. msgBox.setText("Occurence non trouvee, retour en haut de la liste" );
  2581. msgBox.exec();
  2582. }
  2583. }
  2584. }
  2585.  
  2586.  
  2587. void MainWindow::rechercher_TW(QString txt_i, int col_i, QTableWidget *tableWidget_i)
  2588. // Recherche d'un texte dans la colonne 'col_i' d'un QTableWidget
  2589. {
  2590. QString txt2;
  2591. if (txt_i != "")
  2592. {
  2593. setCursor(Qt::WaitCursor);
  2594. int row = tableWidget_i->currentRow()+1;
  2595. bool ok = false;
  2596. while((row < nb_objets_SAC) && !ok)
  2597. {
  2598. txt2 = tableWidget_i->item(row,col_i)->text();
  2599. if (txt2.contains(txt_i,Qt::CaseInsensitive)) {ok = true;}
  2600. row++;
  2601. }
  2602. setCursor(Qt::ArrowCursor);
  2603. if (row != nb_objets_SAC)
  2604. {
  2605. tableWidget_i->setCurrentCell(row-1,0);
  2606. }
  2607. else
  2608. {
  2609. tableWidget_i->setCurrentCell(0,0);
  2610. QMessageBox msgBox;
  2611. msgBox.setText("Occurence non trouvee, retour en haut de la liste" );
  2612. msgBox.exec();
  2613. }
  2614. }
  2615. }
  2616.  
  2617.  
  2618. void MainWindow::on_Bt_okRech1_clicked()
  2619. {
  2620. rechercher_TW(Edit_FindNameNGC1->text(), 0, TableWidget_NGC);
  2621. }
  2622.  
  2623.  
  2624. void MainWindow::on_Bt_okRech2_clicked()
  2625. {
  2626. rechercher_TW(Edit_FindNameNGC2->text(), 1, TableWidget_NGC);
  2627.  
  2628. }
  2629.  
  2630.  
  2631. void MainWindow::on_Bt_top1_clicked()
  2632. {
  2633. TableWidget_NGC->setCurrentCell(0,0);
  2634. }
  2635.  
  2636.  
  2637. void MainWindow::on_Bt_rech_Messier_clicked()
  2638. {
  2639. QString txt1, txt2, txt3, ligne;
  2640. int row=0;
  2641. setCursor(Qt::WaitCursor);
  2642. Liste_Messier->clear();
  2643. while((row < nb_objets_SAC))
  2644. {
  2645. txt2 = TableWidget_NGC->item(row,1)->text().toUpper() + "0";
  2646. if( (txt2[0] == 'M') && txt2[1].isNumber() && txt2[2].isNumber())
  2647. {
  2648. txt1 = TableWidget_NGC->item(row,0)->text();
  2649. txt3.setNum(row+1);
  2650. txt2.truncate(txt2.size()-1);
  2651. ligne = txt2 + '\t' + txt1 + '\t' + txt3;
  2652. Liste_Messier->addItem(ligne);
  2653. }
  2654. row++;
  2655. }
  2656. Liste_Messier->sortItems(Qt::AscendingOrder);
  2657. setCursor(Qt::ArrowCursor);
  2658. }
  2659.  
  2660.  
  2661. void MainWindow::designe_objet_NGC(int row)
  2662. {
  2663. long RA1, DE1;
  2664. float mv;
  2665. QString RAs, DEs, txt1;
  2666.  
  2667. RAs=TableWidget_NGC->item(row, colNGCRA)->text();
  2668. RA1 = RAs.toInt(); // conversion txt -> num
  2669. DEs=TableWidget_NGC->item(row, colNGCDE)->text();
  2670. DE1 = DEs.toLong(); // conversion txt -> num
  2671.  
  2672. txt1=TableWidget_NGC->item(row, colNGCMagn)->text();
  2673. mv = txt1.toFloat(); // conversion txt -> reel
  2674.  
  2675. //la ligne suivante evite d'avoir d'innombrables noms affiches a l'ecran
  2676. if (mv < 10) {spinBoxZoom->setValue(4); } else {spinBoxZoom->setValue(6); } // zoom; attention modifie aussi spinBoxNGC_mag_max
  2677.  
  2678. spinBoxNGC_mag_max->setValue(mv+1);
  2679. actionAfficher_Noms->setChecked(true);
  2680. centrer_position (RA1, DE1);
  2681. }
  2682.  
  2683.  
  2684. void MainWindow::on_Liste_Messier_currentRowChanged(int currentRow1)
  2685. {
  2686.  
  2687. QString ligne, nNGCtxt;
  2688. int row = 0;
  2689. int p;
  2690. if (currentRow1 > 0)
  2691. {
  2692. ligne = Liste_Messier->item(currentRow1)->text();
  2693. p=ligne.indexOf('\t');
  2694. ligne.remove(0, p+1);
  2695. p=ligne.indexOf('\t');
  2696. ligne.remove(0, p+1);
  2697. nNGCtxt=ligne.left(p);
  2698. row=nNGCtxt.toInt()-1; // le numero de ligne dans le grand tableau est egal au numero NGC decrypte ici (-1)
  2699. // (-1 parce que la numerotation des lignes dans le tableau commence par 0 )
  2700. if ((row >= 0) && (row < nb_objets_SAC-1))
  2701. {
  2702. Edit_goNumNGC->setText(nNGCtxt);
  2703. // NGC_gotoLine(row);
  2704. TableWidget_NGC->setCurrentCell(row,colNGCRA);
  2705. designe_objet_NGC(row); // prepare son centrage sur la carte
  2706. }
  2707. }
  2708. }
  2709.  
  2710.  
  2711. void MainWindow::on_TableWidget_NGC_cellClicked(int row, int )
  2712. {
  2713. designe_objet_NGC(row); // prepare son centrage sur la carte
  2714. }
  2715.  
  2716.  
  2717. void MainWindow::on_TableWidget_BSC_cellClicked(int row, int )
  2718. {
  2719. long RA1, DE1;
  2720. QString RAs, DEs;
  2721.  
  2722. RAs=TableWidget_BSC->item(row, colRA)->text();
  2723. RA1 = RAs.toInt(); // conversion txt -> num
  2724. DEs=TableWidget_BSC->item(row, colDE)->text();
  2725. DE1 = DEs.toLong(); // conversion txt -> num
  2726. spinBoxZoom->setValue(3); // zoom
  2727. spinBoxNGC_mag_max->setValue(8.0);
  2728. actionAfficher_Noms->setChecked(true);
  2729. centrer_position (RA1, DE1);
  2730. }
  2731.  
  2732.  
  2733. void MainWindow::on_actionTracer_Ecliptique_toggled(bool )
  2734. {
  2735. a_dessiner = true;
  2736. dessiner_ciel(totalite);
  2737. }
  2738.  
  2739.  
  2740. void MainWindow::on_actionAfficher_Noms_toggled(bool )
  2741. {
  2742. if (!ne_pas_dessiner_maintenant)
  2743. {
  2744. a_dessiner = true;
  2745. dessiner_ciel(totalite);
  2746. }
  2747. }
  2748.  
  2749.  
  2750. void MainWindow::on_actionAfficher_Numeros_triggered()
  2751. {
  2752. if (!ne_pas_dessiner_maintenant)
  2753. {
  2754. a_dessiner = true;
  2755. dessiner_ciel(totalite);
  2756. }
  2757. }
  2758.  
  2759.  
  2760. void MainWindow::on_actionTracer_grille_toggled(bool )
  2761. {
  2762. if (!ne_pas_dessiner_maintenant)
  2763. {
  2764. a_dessiner = true;
  2765. dessiner_ciel(totalite);
  2766. }
  2767. }
  2768.  
  2769.  
  2770. void MainWindow::on_actionTracer_Constellations_toggled(bool )
  2771. {
  2772. a_dessiner = true;
  2773. dessiner_ciel(totalite);
  2774. }
  2775.  
  2776.  
  2777. void MainWindow::on_actionTracer_limites_cartes_BSC5_toggled(bool )
  2778. {
  2779. a_dessiner = true;
  2780. dessiner_ciel(totalite);
  2781. }
  2782.  
  2783.  
  2784. void MainWindow::centrer()
  2785. //slot appele par l'action correspondante du menu contextuel
  2786. {
  2787. cliquee_G = true;
  2788. centrer_position(RA_pointe, DE_pointe);
  2789. a_dessiner = true;
  2790. dessiner_ciel(totalite);
  2791. }
  2792.  
  2793.  
  2794. void MainWindow::centrer_plus_zoom()
  2795. //slot appele par l'action correspondante du menu contextuel
  2796. {
  2797. cliquee_G = true;
  2798. centrer_position(RA_pointe, DE_pointe);
  2799. spinBoxZoom->setValue(spinBoxZoom->value()+2);
  2800. a_dessiner = true;
  2801. dessiner_ciel(totalite);
  2802. }
  2803.  
  2804.  
  2805. void MainWindow::centrer_moins_zoom()
  2806. //slot appele par l'action correspondante du menu contextuel
  2807. {
  2808. cliquee_G = true;
  2809. centrer_position(RA_pointe, DE_pointe);
  2810. spinBoxZoom->setValue(spinBoxZoom->value()-2);
  2811. a_dessiner = true;
  2812. dessiner_ciel(totalite);
  2813. }
  2814.  
  2815.  
  2816. void MainWindow::centrer_objet()
  2817. //slot appele par l'action correspondante du menu contextuel
  2818. {
  2819. int row;
  2820. QString RAs, DEs;
  2821. long RA1, DE1;
  2822.  
  2823. efface_position_pointee();
  2824. row = HR_pointe-1;
  2825. RAs=TableWidget_BSC->item(row, colRA)->text();
  2826. RA1 = RAs.toInt(); // conversion txt -> num
  2827. DEs=TableWidget_BSC->item(row, colDE)->text();
  2828. DE1 = DEs.toLong(); // conversion txt -> num
  2829. actionAfficher_Noms->setChecked(true);
  2830. centrer_position (RA1, DE1);
  2831. if (!ne_pas_dessiner_maintenant)
  2832. {
  2833. a_dessiner = true;
  2834. dessiner_ciel(totalite);
  2835. }
  2836. }
  2837.  
  2838.  
  2839. void MainWindow:: a_propos_de()
  2840. {
  2841. QMessageBox msgBox;
  2842. QString st1,st2;
  2843. long RA_s, DE_s;
  2844. float RAr,DEr;
  2845. msgBox.setWindowTitle("Info");
  2846. if (HR_pointe !=0)
  2847. {
  2848. int row = HR_pointe-1;
  2849. extraire_RA_DE_from_Tableau(row, &RA_s, &DE_s);
  2850. QString ra_txt = nb_secondes2txt_hms (RA_s);
  2851. QString de_txt = nb_secondes2txt_hms (DE_s);
  2852. QString magnitude = TableWidget_BSC->item(row,colMV)->text();
  2853. QString cstl = TableWidget_BSC->item(row,colCSTL)->text();
  2854. QString bayer = TableWidget_BSC->item(row,colNomBay)->text();
  2855. QString classeSpectrale = TableWidget_BSC->item(row,colClsSpect)->text();
  2856. msgBox.setText(Edit_objPointe->text()
  2857. + '\n' + "Ascension droite " + ra_txt
  2858. + '\n' + "Declinaison " + de_txt
  2859. + '\n' + "Constellation: " + cstl
  2860. + '\n' + "magnitude visuelle: " + magnitude
  2861. + '\n' + "Classe spectrale: " + classeSpectrale);
  2862. }
  2863. else if (num_etoile_TYC_pointe != 0)
  2864. {
  2865. TYC2rec etoile1 = liste_etoiles_TYC.at(num_etoile_TYC_pointe);
  2866. st1.setNum(etoile1.gscz);
  2867. st1=st1.right(4);
  2868. st2.setNum(etoile1.gscn);
  2869.  
  2870. RAr =(float)etoile1.ra/5000000/15;
  2871. DEr =(float)etoile1.de/5000000;
  2872. RA_s =deg_decim2sec(RAr);
  2873. DE_s =deg_decim2sec(DEr);
  2874. QString ra_txt = nb_secondes2txt_hms (RA_s);
  2875. QString de_txt = nb_secondes2txt_hms (DE_s);
  2876.  
  2877. msgBox.setText("TIC "+st1 +"-"+st2
  2878. + '\n' + "Ascension droite " + ra_txt
  2879. + '\n' + "Declinaison " + de_txt);
  2880.  
  2881. }
  2882. msgBox.exec();
  2883.  
  2884. }
  2885.  
  2886.  
  2887. void MainWindow::createActions() // appele par la fonction principale
  2888. {
  2889. centrerAct = new QAction(tr("Centrer ici"), this);
  2890. connect(centrerAct, SIGNAL(triggered()), this, SLOT(centrer()));
  2891.  
  2892. centrer_objetAct = new QAction(tr("Centrer l'objet"), this);
  2893. connect(centrer_objetAct, SIGNAL(triggered()), this, SLOT(centrer_objet()));
  2894.  
  2895. centrer_zoom_plusAct = new QAction(tr("Centrer +zoom"), this);
  2896. connect(centrer_zoom_plusAct, SIGNAL(triggered()), this, SLOT(centrer_plus_zoom()));
  2897.  
  2898. centrer_zoom_moinsAct = new QAction(tr("Centrer -zoom"), this);
  2899. connect(centrer_zoom_moinsAct, SIGNAL(triggered()), this, SLOT(centrer_moins_zoom()));
  2900.  
  2901. aProposDeAct = new QAction(tr("A propos de..."), this);
  2902. connect(aProposDeAct, SIGNAL(triggered()), this, SLOT(a_propos_de()));
  2903. }
  2904.  
  2905.  
  2906. void MainWindow::contextMenuEvent(QContextMenuEvent *event)
  2907. //declenche le menu contextuel lors du clic de droite
  2908. {
  2909. if (actionMode_Impression->isChecked()) return; // a cause de recadrage de l'image + grande que l'ecran
  2910. if (tabWidget1->currentIndex() != 2) return;
  2911.  
  2912. QPoint P;
  2913. long RAs, DEs, RAsP, DEsP;
  2914. QString st1,st2, Nom;
  2915. int row;
  2916. QMenu menu(this);
  2917.  
  2918. menu.addAction(centrerAct);
  2919.  
  2920. PosX = event->x() - label_5->x()-1;
  2921. PosY = event->y() - label_5->y() - 55;
  2922.  
  2923. if (PosY < 20) { return;}
  2924.  
  2925. P.setX(PosX);
  2926. P.setY(PosY);
  2927.  
  2928. efface_objet_pointe();
  2929. efface_position_pointee();
  2930.  
  2931. projection_inverse(P, &RAsP, &DEsP);
  2932. RA_pointe = RAsP;
  2933. DE_pointe = DEsP;
  2934.  
  2935. Edit_RAposPointe->setText(nb_secondes2txt_hms (RAsP));
  2936. Edit_DEposPointe->setText(nb_secondes2txt_hms (DEsP));
  2937.  
  2938. HR_pointe = trouve_etoile_at_xy(P);
  2939. num_etoile_TYC_pointe =trouve_TYC_at_xy(P);
  2940.  
  2941. if (HR_pointe !=0)
  2942. {
  2943. row = HR_pointe-1;
  2944. st1.setNum(HR_pointe);
  2945. Nom=TableWidget_BSC->item(row, colNomCom)->text();
  2946. Edit_objPointe->setText("HR" + st1 + " " +Nom);
  2947. menu.addAction(centrer_objetAct);
  2948. centrer_objetAct->setText("Centrer " + Edit_objPointe->text()); //change le label dans le menu contextuel
  2949. st1=TableWidget_BSC->item(row, colRA)->text();
  2950. RAs=st1.toLong();
  2951. Edit_RAobjPointe->setText(nb_secondes2txt_hms (RAs));
  2952.  
  2953. st1=TableWidget_BSC->item(row, colDE)->text();
  2954. DEs = st1.toLong(); // conversion txt -> num
  2955. Edit_DEobjPointe->setText(nb_secondes2txt_hms (DEs));
  2956. }
  2957.  
  2958. menu.addAction(centrer_zoom_plusAct);
  2959. menu.addAction(centrer_zoom_moinsAct);
  2960.  
  2961. if (HR_pointe !=0)
  2962. {
  2963. menu.addAction(aProposDeAct);
  2964. aProposDeAct->setText("A propos de " + Edit_objPointe->text());
  2965. }
  2966. else if (num_etoile_TYC_pointe != 0)
  2967. {
  2968. TYC2rec etoile1 = liste_etoiles_TYC.at(num_etoile_TYC_pointe);
  2969. st1.setNum(etoile1.gscz);
  2970. st1=st1.right(4);
  2971. st2.setNum(etoile1.gscn);
  2972. menu.addAction(aProposDeAct);
  2973.  
  2974. aProposDeAct->setText("A propos de TIC "+st1 +"-"+st2);
  2975. a_dessiner = true;
  2976. dessiner_ciel(partiel_TYC); // rajoute l'etiquette a cote de l'etoile TYC pointe
  2977. }
  2978.  
  2979. menu.exec(event->globalPos()); // passe la main aux sous-menus
  2980. }
  2981.  
  2982.  
  2983. void MainWindow::on_actionEtoiles_blanches_toggled(bool )
  2984. {
  2985. a_dessiner = true;
  2986. dessiner_ciel(totalite);
  2987. }
  2988.  
  2989.  
  2990. void MainWindow::on_actionEtoiles_ponctuelles_toggled(bool )
  2991. {
  2992. a_dessiner = true;
  2993. dessiner_ciel(totalite);
  2994. }
  2995.  
  2996.  
  2997. void MainWindow::on_actionPasTracerCentre_toggled(bool )
  2998. {
  2999. a_dessiner = true;
  3000. dessiner_ciel(totalite);
  3001. }
  3002.  
  3003.  
  3004. void MainWindow::on_Bt_nord_clicked()
  3005. {
  3006. orientation_observateur=0;
  3007. calcul_anglesABC();
  3008. a_dessiner = true;
  3009. dessiner_ciel(totalite);
  3010. }
  3011.  
  3012.  
  3013. void MainWindow::on_Bt_sud_clicked()
  3014. {
  3015. orientation_observateur=180;
  3016. calcul_anglesABC();
  3017. a_dessiner = true;
  3018. dessiner_ciel(totalite);
  3019. }
  3020.  
  3021. void MainWindow::on_Bt_est_clicked()
  3022. {
  3023. orientation_observateur=90;
  3024. calcul_anglesABC();
  3025. a_dessiner = true;
  3026. dessiner_ciel(totalite);
  3027. }
  3028.  
  3029. void MainWindow::on_Bt_ouest_clicked()
  3030. {
  3031. orientation_observateur=-90;
  3032. calcul_anglesABC();
  3033. a_dessiner = true;
  3034. dessiner_ciel(totalite);
  3035. }
  3036.  
  3037. void MainWindow::on_calendrier1_clicked(QDate date)
  3038. {
  3039. QString txt1;
  3040. // date1 = calendrier1->selectedDate();
  3041. day_oh_year1 = date.dayOfYear();
  3042. spin_inc_date->setValue(day_oh_year1);
  3043. txt1.setNum(day_oh_year1); // conversion num -> txt
  3044. Edit_dayOfYear->setText(txt1 + "/365");
  3045. calendrier1->hide();
  3046. calcul_anglesABC();
  3047. a_dessiner = true;
  3048. dessiner_ciel(totalite);
  3049. }
  3050.  
  3051.  
  3052. void MainWindow::on_spinBoxZoom_valueChanged(double valeurZoom)
  3053. {
  3054. MAJ_zoom(valeurZoom);
  3055. }
  3056.  
  3057.  
  3058. void MainWindow::on_actionCiel_Profond_toggled(bool )
  3059. {
  3060. a_dessiner = true;
  3061. dessiner_ciel(totalite);
  3062. }
  3063.  
  3064.  
  3065. void MainWindow::on_actionObjetsSDcardSeulement_toggled(bool Checked)
  3066. {
  3067. if (Checked)
  3068. {
  3069. spinBox_magnitude_max->setValue(4.5);
  3070. spinBoxNGC_mag_max->setValue(7.0);
  3071. actionAfficher_Numeros->setChecked(true);
  3072. actionAfficher_Noms->setChecked(true);
  3073. }
  3074. else
  3075. {
  3076. spinBox_magnitude_max->setValue(7.0);
  3077. spinBoxNGC_mag_max->setValue(12.0);
  3078. actionAfficher_Numeros->setChecked(false);
  3079. actionAfficher_Noms->setChecked(false);
  3080. }
  3081. }
  3082.  
  3083.  
  3084. void MainWindow::on_actionImprimer_activated(int )
  3085. {
  3086. actionMode_Impression->setChecked(true);
  3087. a_dessiner = true;
  3088. dessiner_ciel(impr);
  3089. //image1 = image1.convertToFormat(QImage::Format_Mono, Qt::DiffuseDither);
  3090.  
  3091. QPrinter printer(QPrinter::HighResolution);
  3092. //QPrinter printer(QPrinter::ScreenResolution);
  3093. //printer.setColorMode(QPrinter::GrayScale);
  3094. printer.setPageSize(QPrinter::A4);
  3095. printer.setOrientation(QPrinter::Landscape);
  3096. printer.setResolution(300);
  3097. printer.setPageMargins ( 30, 20, 0, 0, QPrinter::Millimeter);
  3098. QPrintDialog *dialog = new QPrintDialog(&printer);
  3099. if (dialog->exec() == QDialog::Accepted)
  3100. {
  3101. QPainter painter (&printer);
  3102. painter.begin(&printer);
  3103. painter.drawImage (QRect(0,0,x_max_image,y_max_image),image1);
  3104. painter.end();
  3105. }
  3106. }
  3107.  
  3108.  
  3109. void MainWindow::on_actionMode_Impression_toggled(bool coche)
  3110. {
  3111. if (coche)
  3112. {
  3113. ne_pas_dessiner_maintenant = true; // evite de redessiner x fois a la suite
  3114. //actionTracer_grille->setChecked(false);
  3115. actionMagnitude_max_auto ->setChecked(false);
  3116. spinBoxZoom->setValue(spinBoxZoom->value() +1); //attention: cette ligne doit preceder la suivante
  3117. actionObjetsSDcardSeulement->setChecked(true); //attention: cette ligne doit suivre la precedente
  3118. }
  3119. else
  3120. {
  3121. actionObjetsSDcardSeulement->setChecked(false);
  3122. spinBoxZoom->setValue(spinBoxZoom->value() -1);
  3123. }
  3124. a_dessiner = true;
  3125. dessiner_ciel(impr);
  3126. ne_pas_dessiner_maintenant = false;
  3127. }
  3128.  
  3129.  
  3130. void MainWindow::on_Bt_docNGC_clicked()
  3131. {
  3132. int z3 = charger_texte_doc(QDir::currentPath() + "/catalogues/NGC/NGC_doc.txt");
  3133. // si le fichier a ete trouve dans le dir /catalogues, alors z=0 sinon on le chercher dans le dir de l'executable
  3134. if (z3 == 1) { z3 = charger_texte_doc (QDir::currentPath() +"/NGC_doc.txt");}
  3135. }
  3136.  
  3137.  
  3138. void MainWindow::on_Bt_astuces_clicked()
  3139. {
  3140. int z3 = charger_texte_doc(QDir::currentPath() + "/catalogues/astuces.txt");
  3141. // si le fichier a ete trouve dans le dir /catalogues, alors z=0 sinon on le chercher dans le dir de l'executable
  3142. if (z3 == 1) { z3 = charger_texte_doc (QDir::currentPath() +"/astuces.txt");}
  3143. }
  3144.  
  3145.  
  3146. void MainWindow::on_actionQuitter_activated()
  3147. {
  3148. close();
  3149. }
  3150.  
  3151.  
  3152. void MainWindow::on_actionEditeur_de_Constellations_toggled(bool coche)
  3153. {
  3154. Edit_ligne_cstl->setVisible(coche);
  3155. }
  3156.  
  3157.  
  3158. void MainWindow::on_actionSouligner_Etoiles_d_une_CSTL_toggled(bool )
  3159. {
  3160. a_dessiner = true;
  3161. dessiner_ciel(impr);
  3162. }
  3163.  
  3164. void MainWindow::on_actionLettres_grecques_toggled(bool )
  3165. {
  3166. a_dessiner = true;
  3167. dessiner_ciel(totalite);
  3168. }
  3169.  
  3170. void MainWindow::on_Bt_chercher_clicked()
  3171. {
  3172. rechercher_LW(Edit_rech->text(), listeDoc);
  3173. }
  3174.  
  3175. void MainWindow::on_actionAfficher_champ_CCD_toggled(bool )
  3176. {
  3177. a_dessiner = true;
  3178. dessiner_ciel(totalite);
  3179. }
  3180.  
  3181. void MainWindow::on_actionCatalogue_Tycho_toggled(bool )
  3182. {
  3183. a_dessiner = true;
  3184. dessiner_ciel(totalite);
  3185. }
  3186.  
  3187. void MainWindow::on_spinBox_rot_champ_valueChanged(int )
  3188. {
  3189. angleD = M_PI / 180 *(spinBox_rot_champ->value()); // en radian
  3190. if (!ne_pas_dessiner_maintenant)
  3191. {
  3192. a_dessiner = true;
  3193. dessiner_ciel(totalite);
  3194. }
  3195. }
  3196.  
  3197. void MainWindow::on_actionPas_de_halo_toggled(bool )
  3198. {
  3199. a_dessiner = true;
  3200. dessiner_ciel(totalite);
  3201. }
  3202.  

13 Evolution du programme:

26 janvier 2010: version 3.01
Accés au catalogue BSC5 (Bright Star Catalogue) contenant 9110 objets. Voir ci-dessus un aperçu du côté de Véga. Les étoiles sont affichées avec leurs couleurs.

10 février 2010: version 5.0
Permet de représenter les 10343 objets du ciel profond du catalogue SAC, en plus des 9100 étoiles du catalogue BSC5.

J'ai également ajouté des fonctions de recherche:
Recherche d'étoile par numéro BSC.
Recherche d'objet Messier par son numéro.
Pointage automatique de l'objet trouvé.
Centrage automatique de la carte sur l'étoile pointée.


21 février 2010: version 5.7
Zoom avec la molette de la souris (weelEvent).
Les grilles de coordonnées et l'écliptique sont maintenant représentées par des lignes et plus par des points.
La position représentée correspond vraiment à celle de la date choisie.
L'image du ciel est mémorisée en RAM avec un QImage et un buffer ce qui permet de rajouter des annotations sans tout redessiner (par exemple affichage du nom et du numéro HR lors d'un clic sur une étoile).
L'amélioration générale du code permet d'obtenir un affichage beaucoup plus rapide.

22 février 2010:
Le halo autour des étoiles est maintenant diffus ce qui est obtenu par la propriété "radialGradient" affectée à la brosse du QPainter associé au QPixmap du QLabel placé sur le QTabWidget. Le plus dur est de configurer les propriétés du QRadialGradient (position, rayon, couleurs, points"stop", mode et j'en passe!) J'me marre, mais une fois qu'on a pigé le truc ça devient pratiquement naturel!

6 mars 2010: version 5.10
Permet d'imprimer (sur fond blanc!) des régions du ciel. Une fonction anti-collision évite le chevauchement des textes lorsque les étoiles sont très proches angulairement l'une de l'autre. Figurent près de chaque étoile son nom et son numéro HR; Et près de chaque objet du ciel profond, son numéro NGC et son nom. De quoi utiliser le boitier électronique GOTO de l'APE2009 d'une manière autonome, sans ordi portable.

14 mars 2010: version 5.13

Ecriture des lettres de Bayer en alphabet grec.
Ajout de fonctions de recherche dans l'onglet documentation.
Amélioration des autres fonctions de recherche.

18 mars 2010: version 5.14
Représentation des objets du ciel profond avec leur diamètre apparent réel.

22 mars 2010: version 5.15
Affichage optionnel d'un rectangle représentant le champ d'un capteur CCD [de taille 24x36mm (APN K100D) au foyer d'un instrument de 600mm de focale. (ce paramètre est facilement modifiable... dans le code source pour l'instant)].

2 avril 2010: version 6.0
Grande nouveauté: affichage du catalogue Tycho contenant 2.5 millions d'étoiles jusqu'à la magnitude 11.

4 avril 2010: version 6.2
De nouvelles fonctions apparaissent dans le menu contextuel
Les étoiles du catalogue BSC5 qui sont affichées en couleur gardent leur couleur lors de l'affichage du catalogue Tycho2.

5 avril 2010: version 6.3
Nouvelle fonction: rotation du champ affiché par rapport au centre de l'écran. Permet de comparer plus facilement l'image avec des photos du ciel.

15 avril 2010: version 7.0
Nouveau format (libre et documenté) pour le catalogue tycho2 (nouvelle structure plus légère pour les enregistrements). Toute version antérieure à cette date est obsolète et ne fonctionnera pas. Toute version proposée pour d'autres logiciels de cartographie stellaire est incompatible.

17 avril 2010: version 8.1
Nouveau format (libre et documenté) pour le catalogue BSC5 (nouvelle structure plus légère pour les enregistrements). Toute version antérieure à cette date est obsolète et ne fonctionnera pas. Toute version proposée pour d'autres logiciels de cartographie stellaire est incompatible.

1er juillet 2010: version 8.1 x64
Je viens d'installer la version x64 de Ubuntu 10.04 sur mon AMD64 dual core. Et voyant que le logiciel en Qt4 compilé pour 32bits ne tournait plus, je l'ai recompilé en version 64bits, qui fonctionne parfaitement cette fois. Je vous la propose en téléchargement. (l'exécutable seul puisque les sources sont identiques).

10 aout 2010: version 8.2
modification du message au lancement (plus clair)
pas de surécriture des étiquettes lors de clics multiples sur le même astre
plus de redimensionnement intempestifs des fenêtres lors de changement d'onglets

14 A propos de ce programme en C++ et Qt4

Idéal pour débuter avec Qt disais-je... Voyez plutôt:

Vous y trouverez une fenêtre principale comprenant:
  • un menu simple.
  • un menu contextuel.
  • des boutons.
  • des boutons avec une image dessus.
  • des QLineEdit (boites de saisie texte).
  • un QComboBox (liste de choix, déroulante).
  • un QTextEdit ( equiv. Tmemo delphi, avec nombreuses fonctions d'éditions).
  • un QTableWidget (equiv. TStringGrid delphi avec fonctions de tri intégrées...)
  • des onglets: QTabWidget
  • les évennements générés par les boutons de la souris ainsi que par la rotation de sa molette.
  • des structures.
  • des objets.
  • des listes QList.
Dans le code source en C, commenté en français, du programme associé vous verrez comment exploiter les propriétés et les évènements générés par ces objets, en particulier comment:
  • copier le contenu texte du presse papier dans le QLineEdit.
  • trouver une ligne dans ce QTextEdit contenant un texte donné.
  • recopier une ligne ou un mot du QTextEdit dans un QLineEdit.
  • recopier le contenu d'un QLineEdit dans une case du QTableWidget.
  • rechercher du texte dans un QTableWidget ainsi que dans un QListWidget.
  • lire et sauvegarder sur le disque dur le contenu du QTableWidget.
  • utiliser des onglets: QTabWidget.
  • créer un menu principal.
  • DESSIN: dessiner avec des droites, des ellipses etc, et écrire sur une grande surface (dans un QPixmap associé à un QLabel ).
  • gérer la transparence et le gradient (circulaire en l'occurence).
  • sauvegarder (en RAM) les données d'un QPixmap (en passant par un QImage) afin de compléter un dessin en plusieurs fois (après avoir quitté la fonction déclarant le pixmap).
  • utiliser des couleurs pour dessiner et écrire.
  • récupérer les coordonnées de la souris lors d'un clic dans le pixmap.
  • créer un menu contextuel.
  • gérer la molette de la souris (pour le zoom en l'occurence).
  • créer des classes (nombres complexes, vecteurs3D...) et faire de la programmation orientée objet.
  • utiliser des listes dynamiques QList où T peut représenter des données (entiers, réels, structures etc...) et même des objets. Génial et puissant.
  • faire tourner des objets tridimensionnels dans l'espace et les projeter sur un plan.
  • décoder les abréviations des lettres grecques et les écrire en alphabet grec.
  • imprimer un tracé vectoriel plus grand que l'écran.
  • etc...

15 LE SCHEMA

Attention! Le schéma à jour est toujours celui sous format eagle disponible plus bas sur cette page.

Ce schéma a été tracé (puis routé) sous Linux Ubuntu 9.04 avec le logiciel EAGLE.

L'alimentation à découpage 5V (à partir du 12V) pour alimenter les moteurs permet d'économiser la batterie.

16 CODE SOURCE (en C) du programme pour l'ATmega32 (voir également les include dans le tar.gz)

CODE SOURCE en langage C
  1. /***************************************************************************
  2.  * Copyright (C) 2009 by Silicium628 (France) *
  3.  * http://silicium628.chez-alice.fr/ *
  4.  * http://www.silicium628.fr/ *
  5.  * sauf certaines parties dont les auteurs sont cités *
  6.  * en particulier certaines fonctions de gestion SD-card et FAT32 *
  7.  * ( Un grand merci à CC Dharmani pour l'ensemble de son travail! ) *
  8.  * *
  9.  * This program is free software; you can redistribute it and/or modify *
  10.  * it under the terms of the GNU General Public License as published by *
  11.  * the Free Software Foundation; *
  12.  * *
  13.  * This program is distributed in the hope that it will be useful, *
  14.  * but WITHOUT ANY WARRANTY; *
  15.  * See the GNU General Public License for more details. *
  16.  ***************************************************************************/
  17.  
  18. /*=========================================================================================
  19. APE2009
  20.  
  21. par Silicium628 - voir la description de cette réalisation sur mon site
  22. versions: voir plus bas dans la partie "const" - dernière mise à jour 22 fevrier 2010
  23. La version est visible sur l'afficheur au reset du programme
  24. Quel plaisir de programmer un uControleur en PASCAL ! disais-je:-)
  25. Car je précise que j'ai écrit ce firmware tout d'abord en pascal (APE2008) sous Windows :-(
  26. Puis désirant me passer définitivement de Window$ je l'ai réécrit en C avec kontrolleurlab
  27. Quel plaisir donc, de programmer un uControleur en C ! et sous Linux :-))
  28. ===========================================================================================
  29. PRINCIPE:
  30. --------------------------------------------------------------------------------
  31. GENERALITES: (source Wikipedia)
  32. --------------------------------------------------------------------------------
  33. En une année, la Terre effectue environ 365 tours sur elle-même par rapport au Soleil,
  34. mais effectue aussi un tour complet autour du Soleil. Donc, par rapport aux étoiles,
  35. 365 jours solaires équivalent à 366 jours sidéraux.
  36. Les jours sidéraux sont donc un peu plus courts que les jours solaires.
  37. La période réelle de l'année étant de 365,2422 jours solaires, la durée exacte
  38. du jour sidéral est de : 365,2422/(365,2422+1) = 0,9972696 jour solaire, soit 23h 56m 4,09s,
  39. soit une différence d'environ 4mn par rapport au jour solaire,
  40. le rapport entre les deux étant de 1/360 = 0.0027 soit moins de 0.3%
  41.  
  42. En astronomie, la position d'un astre sur la sphère céleste est repérée par deux
  43. coordonnées, l'ascension droite et la déclinaison.
  44. A tout instant la somme de l'ascension droite d'un astre et de son angle horaire
  45. est égale au temps sidéral.
  46. En quelque sorte le temps sidéral mesure le déplacement de la voûte céleste en
  47. un lieu donné par rapport au méridien local.
  48.  
  49. Unités de l'ascension droite
  50. L'heure d'ascension droite est une unité de mesure d'angle plan et vaut 360°/24 = 15°.
  51. La minute d'ascension droite vaut 1/60 heure d'ascension droite soit 15 minutes d'arc.
  52. La seconde d'ascension droite vaut 1/60 minute d'ascension droite = 15 secondes d'arc.
  53. --------------------------------------------------------------------------------
  54. (fin de citation de Wikipedia)
  55. --------------------------------------------------------------------------------
  56.  
  57. Une lunette astronomique immobile par rapport au sol terrestre pointe dans une
  58. direction du ciel dont l'ascenssion droite (RA) augmente de 1s (de coordonnees
  59. RA siderales, =15s d'arc) toutes les 1s (de temps sideral)
  60.  
  61. 1 jour solaire = 24h00
  62. 1 jour sideral = 23h56'
  63. 365 * 4' = 24h (au bout d'une annee le decallage s'annule donc)
  64. Les 4' qu'il faut ajouter au jour sideral pour obtenir un jour terrestre sont dues
  65. au deplacement de la terre sur son orbite autour du soleil d'un jour sur l'autre
  66.  
  67. Toutes les 1s de temps, l'horloge temps reel (RTclock qui bat la seconde solaire)
  68. incremente la variable RA_temps de 1s siderale
  69. Si on négligeait la différence entre le temps solaire et le temps sidéral on commettrait
  70. comme vu plus haut une erreur de 0.3% qui sur un suivi de 1h represente une erreur
  71. de 10s de temps ou 150" d'arc (2.5' d'arc) ce qui n'est pas acceptable.
  72. On doit donc absolument tenir compte de cette différence.
  73. Voir la procedure "RTCtickSecond"
  74.  
  75. Deux méthodes:
  76. --------------------------------------------------------------------------------
  77. 1) Ancienne methode: (APE2002)
  78. Lorsque le moteur pas à pas tourne, chaque pas est compté dans la variable compte_PAS
  79. lorsque ce nombre de pas atteint (1/(TP_suivi_RA * 1E-6)) c'est a dire la frequence
  80. du moteur qui est le nombre de pas par seconde en mode suivi, on decremente RA de 1;
  81. RESULTAT: lorsque le moteur tourne a la vitesse de suivi siderale, RA ne bouge plus.
  82. C'est le but recherche, la lunette pointant alors toujours le meme objet du ciel.
  83. Si le moteur est mis a l'arret ou bien tourne à vitesse rapide, la variable
  84. RA indiquera toujours l'ascension droite reellement pointee.
  85. Note: le "1E-6" because TP_suivi_RA est un nombre de microsecondes.
  86. --------------------------------------------------------------------------------
  87. 2) Nouvelle methode: (depuis la version APE2008 en pascal 3.0 puis APE2009 1.0 en C)
  88. Lorsque le moteur pas à pas tourne et est embraye, la roue codeuse incrémentale
  89. fixée sur l'axe RA envoie des impulsions qui sont comptées par l'ext_INT_0
  90. On calcule un angle proportionnel à ce nombre (précisement avec des valeurs
  91. représentées par des réels en virgule flotante, merci le Pascal et ici le C) (AngleHoraire)
  92. qui est décompté de la variable Temps_sid pour le calcul de RA (position pointée)
  93.  ===== voir la procedure "interrupt Int0" ========
  94. Avantage de cette seconde méthode mise en oeuvre ici: L'affichage de RA valide
  95. même lors de déplacements rapides avec un moteur DC (=courant continu), ou manuels.
  96.  
  97. Depuis la version en pascal 4.0 un moteur DC vient seconder le moteur pas à pas pour les
  98. déplacements rapides en ascension droite.
  99. (la vitesse est alors de 1h de déplacement RA (15 degrés d'arc) en dix secondes, soit 360x la vitesse sidérale
  100. Un embrayage électro-mecanique commandé automatiquement par ce soft permet de passer d'un moteur à l'autre
  101.  
  102. La vitesse maximale de déplacement en DECLI est d'environ 10 degrés d'arc en 10s,
  103. obtenue directement par le moteur pas à pas de déclinaison.
  104.  
  105. ================================================================================
  106. Remarque concernant la liaison RS232-USB :
  107. -Toutes les données sont transmises en mode texte et pas en binaire. En particulier
  108. les nombres sont transmis "chiffre par chiffre" (décimal) par leur représentation en
  109. mode texte (ASCII) et non par leur valeur directe.
  110. Ceci pour éviter des surprises lors de transmission de valeurs correspondant à
  111. des commandes systèmes (comme par exemple chr(10) ou chr(13)) qui sont la source de bugs.
  112.  
  113. Depuis la version 3.6 liaison 19200 Baud au lieu de 9600 Bauds
  114. Depuis la version 4.2, la liaison RS232 n'est plus utilisée (mémorisation des données sur une SD-card)
  115.  
  116. ================================================================================
  117. L'APE2008 répond aux signaux d'une télécommande TV infra rouge universelle.
  118. Beaucoup de modèles conviennent, il faudra adapter les codes des touches dans ce
  119. programme le cas écheant (voir les 'case octet_IR of') dans la partie "main"
  120. Pour ma part, j'utilise une PHILIPS type 'UNIVERSAL SBC RU 252 II'
  121. ================================================================================
  122.  
  123.  
  124.  
  125. ======================== Rappel ATmega32 =======================================
  126.  
  127. Device Flash EEPROM SRAM Speed Volts
  128. ATmega32 32kB 1024B 2048B 0 - 16MHz 4.5 - 5.5V
  129. ================================================================================
  130. */
  131.  
  132.  
  133. // #include <math.h>
  134. #include <stdlib.h>
  135. #include <stdint.h>
  136. #include <stdio.h>
  137. #include <string.h>
  138. #include <avr/wdt.h>
  139.  
  140. #include <avr/io.h>
  141. #include <avr/interrupt.h>
  142.  
  143. // #include <avr/eeprom.h>
  144. // #include "uart_628.h"
  145.  
  146. #include <util/delay.h>
  147. #include "dm_lcd.h"
  148.  
  149. #include <avr/pgmspace.h>
  150. #include "SPI_routines.h"
  151. #include "SD_routines_628.h"
  152. #include "FAT32_628.h"
  153.  
  154.  
  155. /*
  156.   RC5Rxport = PinD, 7, negative;
  157.   RC5mode = rc_6bit;
  158. */
  159.  
  160.  
  161. extern uint8_t asmfunction(uint8_t); // all assembly subroutines must be declared external to the C source
  162.  
  163. char * version = "5.2";
  164. int nbr_ast = 9110;
  165.  
  166.  
  167.  
  168. /*
  169. RAPPEL variables avr-gcc (vérifiable avec le .map)
  170.  
  171. char 1 -128 .. 127 ou caractères
  172. unsigned char 1 0 .. 255 (equiv à byte du pascal)
  173. uint8_t 1 (c'est la même chose que l'affreux 'unsigned char')
  174. char toto[n] n
  175. int 2 -32768 .. 32767
  176. int16_t 2 idem 'int'
  177. short int 2 pareil que int (?)
  178. unsigned int 2 0 .. 65535
  179. uint16_t 2 idem 'unsigned int'
  180. long int 4 -2 147 483 648 à 2 147 483 647
  181. int32_t 4 32 bits ; idem long int
  182. long long int 8
  183. unsigned long int 4 32 bits ; 0 .. 4 294 967 295 (4,2 x 10^9)
  184. uint32_t 4 32 bits ; idem 'unsigned long int'
  185. float 4
  186. double 4 // (?)
  187.  
  188. La déclaration char JOUR[7][9];
  189. réserve l'espace en mémoire pour 7 mots contenant 9 caractères (dont 8 caractères significatifs).
  190. */
  191.  
  192.  
  193.  
  194. /*PARAMETRES DECLINAISON
  195. 90º -> 78,5 tours de la roue blanche -> 77.5x 7.5 =581.25 tours du moteur pas à pas
  196. 1° -> 581.25/90 = 6.458 tours du moteur pas à pas
  197. 1°=3600s -> 581.25/90*48(pas/tour)= 310 pas
  198. 310 pas -> 3600s
  199. 1 pas -> 3600/310 =11.613s
  200. 10 pas -> 116,13s
  201. */
  202.  
  203. #define nb_max_PAS_DEC 10
  204. #define nbs_DEC 63
  205.  
  206.  
  207.  
  208. // variables en RAM
  209.  
  210. uint8_t octet_recu;
  211.  
  212. // char buffer_rs232[BUFF_SIZE];
  213. // char input_message[BUFF_SIZE];
  214. uint8_t i_buff;
  215. uint8_t input_message_ok; // BOOLEAN
  216. uint8_t buff_overfl; // BOOLEAN
  217.  
  218. uint8_t compteur1;
  219. uint8_t compteur2;
  220. uint16_t nb_ms2;
  221.  
  222. int stk1;
  223.  
  224. int32_t memoRA_1;
  225. int32_t memoRA_2;
  226. int32_t memoRA_3;
  227. int32_t memoRA_4;
  228. int32_t memoRA_5;
  229. int32_t memoRA_6;
  230.  
  231. int32_t RA; // Ascenssion droite actuellement pointée (en secondes de temps sideral)
  232. int32_t RA_affi; // valeur à afficher (non fluctuante)
  233. int32_t RA_objet; // ascension droite de l'objet en cours
  234. int32_t DECLI; // Declinaison (en secondes d'arc)
  235. int32_t pas_mouse; // comptés par le codeur incrémental
  236. float Angle_Horaire; // angle horaire mesuré par le codeur incremental (en secondes de temps sideral)
  237. float Temps_sid; // temps sideral (relatif / selection objet) en secondes
  238. int32_t G_RA; // goto RA (en secondes de temps sideral)
  239. int32_t G_DECLI; // goto DECLI (en secondes d'arc)
  240. int32_t sel_RA; // select RA (en secondes de temps sideral)
  241. int32_t sel_DECLI; // select DECLI (en secondes d'arc)
  242.  
  243. uint8_t rxAdr;
  244. uint8_t rxCmd;
  245. uint8_t adr1;
  246. uint8_t cmd1;
  247. uint8_t rxAdr_IR;
  248. uint8_t rxCmd_IR;
  249. uint8_t bit_bascul_IR; // BOOLEAN
  250. uint8_t octet_IR; //octet recu par le recepteur IR
  251. uint8_t bitsix;
  252. uint8_t memo_bitsix;
  253. uint8_t nouveau; // BOOLEAN // pour l'anti rebond signaux IR
  254. uint8_t stop; // BOOLEAN
  255.  
  256. uint8_t Sens_moteur_RA;
  257. uint8_t Moteur_RA ; // Moteur_RA[1,2] definissent le numero de pas [0..3] et le bit Moteur_RA[3]=ON,OFF
  258. uint32_t TP_suivi_RA; //Periode du moteur_RA correspondant au suivi (vitesse siderale)
  259. uint32_t TPi_RA; //Periode du moteur_RA a atteindre
  260. uint32_t TP_RA; //Periode du moteur_RA actuelle
  261. int num_vt_RA; //numero de la vitesse RA [-5..+5]
  262. uint8_t fx_vitesse_RA; // [1..2..4..8..16..32]
  263. int16_t cpt_PAS_RA; // attention: signé!
  264. int16_t nb_max_PAS_RA;
  265. uint8_t stop_RA; // BOOLEAN
  266. uint8_t terrestre; // BOOLEAN mode terrestre (arrêt du suivi - autres fonctions ok )
  267. uint8_t rech_rapide; // BOOLEAN mode suivi astro avec vitesses de déplacement rapides
  268.  
  269. uint8_t Sens_moteurDEC;
  270. uint8_t Moteur_DEC; // Moteur_RA[1,2] definissent le numero de pas [0..3] et le bit Moteur_DEC[3]=ON,OFF
  271. int8_t TP_DEC; // Periode du moteur_DEC -remarque: OCR2 est un registre 8 bits donc TP_DEC 8 bits aussi
  272. int8_t num_vt_DEC; // signé: numero de la vitesse RA [-5..+5]
  273. uint8_t fx_vitesse_DEC; // [1..2..4..8..16..32]
  274. int8_t cpt_PAS_DEC; // attention: signé!
  275. uint8_t stop_DEC; // BOOLEAN
  276. uint8_t reverse_inc_dec; // BOOLEAN
  277.  
  278. char txt1[10+1];
  279. char pos1[18+1];
  280. char nom1[10+1];
  281. uint16_t n_OBJ;
  282.  
  283. uint8_t prim_pass; // BOOLEAN
  284. uint8_t afficher_pos; // BOOLEAN
  285. uint8_t afficher_diff; // BOOLEAN
  286. uint8_t afficher_etat; // BOOLEAN
  287.  
  288. uint8_t in232_en_cours; // BOOLEAN
  289. uint8_t rattraper_jeu; // BOOLEAN
  290. uint8_t goto_en_cours; // BOOLEAN
  291. uint8_t sens_ra; // BOOLEAN
  292. uint8_t sens_decli; // BOOLEAN
  293. uint8_t goto_RA_termine; // BOOLEAN
  294. uint8_t goto_DECLI_termine; // BOOLEAN
  295. uint8_t mode_transfert; // BOOLEAN
  296. uint8_t FAT32_active;
  297.  
  298.  
  299. //--------------------------------------------------------------
  300.  
  301.  
  302. void init_ports(void) // ports perso DDRx 0=entree, 1=sortie
  303. {
  304. PORTA = 0b00000000;
  305. DDRA = 0b11111111;
  306.  
  307. PORTB = 0b11100000;
  308. DDRB = 0b10111111; // PB6 = MISO = entrée
  309.  
  310. DDRC = 0b11111111;
  311.  
  312. DDRD = 0b01000001; // 7=in RC5 - 6=out LED - PD0 = out TX RS232
  313. }
  314.  
  315.  
  316.  
  317. int32_t abs_int32(int32_t x)
  318. {
  319. if (x >= 0) return x ; else return -x;
  320. }
  321.  
  322.  
  323. int32_t distance_RA(int32_t Ra1, int32_t Ra2)
  324. // retourne la distance angulaire séparant deux RA, et donne le sens dans lequel il faut tourner pour le go_to
  325. // voir la figure "mode de calcul RA.jpg" dans le répertoire de ce fichier source
  326. {
  327. int32_t d;
  328.  
  329. d = Ra2-Ra1;
  330.  
  331. if (d<0)
  332. {
  333. d = -d;
  334. sens_ra = 1;
  335. }
  336. else { sens_ra = 0; }
  337.  
  338. if (d > 43200)
  339. {
  340. d = 86400 -d;
  341. sens_ra = 1-sens_ra; // on tourne dans "l'autre" sens, qui est le chemin le plus court
  342. }
  343.  
  344. return d;
  345. }
  346.  
  347.  
  348. uint32_t distance_DECLI(int32_t Decli1, int32_t Decli2)
  349. // retourne la distance angulaire séparant deux DECLI, et donne le sens dans lequel il faut tourner pour le go_to
  350. {
  351. uint32_t d;
  352. if (Decli2 >= Decli1)
  353. {
  354. d = (uint32_t) (Decli2-Decli1); // une décli peut être négative ; toutefois ici d est toujours > 0
  355. sens_decli = 0;
  356. }
  357. else
  358. {
  359. d = (uint32_t) (Decli1-Decli2); // une décli peut être négative ; toutefois ici d est toujours > 0
  360. sens_decli = 1;
  361. }
  362.  
  363. return d;
  364. }
  365.  
  366.  
  367. void strcpy_a_n(char *CH1, char *CH2, uint8_t a, uint8_t n )
  368. /*
  369. recopie n caractères depuis i0 de CH2 dans CH1
  370. attention: CH2 peut ne pas être un string (pas de \0 à la fin) ce qui peut être pratique pour lire un flux
  371. mais a+n ne doit pas déborder de CH1 et CH2 !
  372. ajoute \0 à la fin (le prévoir dans la longueur de la chaine CH1)
  373. */
  374. {
  375. uint8_t i;
  376. i=0;
  377. while ( i < n )
  378. {
  379. CH1[i] = CH2[a+i];
  380. i++;
  381. }
  382. CH1[i]='\0';
  383. }
  384.  
  385.  
  386. uint8_t isNumeric(char *CH1)
  387. {
  388. uint8_t i;
  389. i=0;
  390. while (CH1[i] != '\0')
  391. {
  392. if ((CH1[i]>='0' && CH1[i]<='9') == 0) return 0;
  393. i++;
  394. }
  395. return 1;
  396. }
  397.  
  398.  
  399.  
  400. void InitINTs(void)
  401. /*
  402. {Les 3 bits de poids faible de TCCR2 selectionnent l'horloge et le prescaler. voir page 119 et 125 du pdf
  403. Bit 6, 3 WGM21:0 = 01 -> mode CTC voir p:125 du pdfCTC = "Clear Timer on Compare Match" (CTC) Mode
  404. In "Clear Timer on Compare mode" (CTC mode, WGM21:0 = 2), the counter is cleared to zero when the
  405. counter value (TCNT2) matches the OCR2. The OCR2 defines the top value for the counter, hence also its resolution.
  406. */
  407. {
  408. // RAZ préalable (j'ai un doute sur les valeurs par defaut...)
  409. GICR = 0;
  410. TCCR1B = 0;
  411. TCCR2 = 0;
  412. TIMSK = 0;
  413. MCUCR = 0;
  414.  
  415. TCCR0 |= 0b01001000; // Timer0 en mode CTC (Clear Timer on Compare Match): WGM00=1 (bit6) et WGM01=0 (bit3) voir p:74 et 80
  416. TCCR0 |= 0b00000011; // Timer0 prescaller = 1/64. 0CS0[2,1,0] = 011 voir p:82 et p:80
  417. TIMSK |= 0b00000010; // Timer/Counter0 Output Compare Match Interrupt Enable.( Bit 1 – OCIE0) p:82
  418. TCCR2 |= 0b10001111;
  419. TIMSK |= 0b00010000; // Timer/Counter1, Output Compare A Match Interrupt Enable; Voir datasheet ATmega32 p:112
  420. TCCR1B |= 0b00000010; // Timer1 prescaler = 1/8 il faut donc encore /2 pour avoir 1 us ; voir p:110
  421. TCCR1B |= 0b00001000; // WGM12 =1 --> Timer1 en mode CTC
  422.  
  423. OCR0 = 250; // Timer0 freq = 16MHz/64/250= 1kHz
  424.  
  425. /*
  426. Timer2 en mode CTC p:98
  427. In Clear Timer on Compare or CTC mode (WGM13:0 = 4 or 12), the OCR1A or ICR1
  428. Register are used to manipulate the counter resolution. In CTC mode the counter is
  429. cleared to zero when the counter value (TCNT1) matches either the OCR1A (WGM13:0 = 4)
  430. voir aussi p:109 Table 47. "Waveform Generation Mode Bit Description" mode CTC = 4
  431. */
  432. TIMSK |= 0b10000000; // INT Timer2 comp enable; Voir le datasheet ATmega32.pdf p:130
  433. GICR |= 0b01000000; // extINT0 enable; voir page 67 du pdf
  434. MCUCR |= 0b00000011; // Le frond descendant de extINT0 genere une interrupt request. p:67 du pdf
  435. }
  436.  
  437.  
  438. void Timer1_setTime(int t) // en microsecondes
  439. // quartz = 16MHz et prescaller (du Timer1) = 1/8 ce qui fait 2MHz
  440. {
  441. OCR1A = 2 * t;
  442. }
  443.  
  444.  
  445. void lcd_gotoxy_clrEOL (int x, int y)
  446. // place le curseur en x,y et efface jusqu'a la fin de la ligne
  447. {
  448.  
  449. lcd_gotoxy(x, y);
  450. int i;
  451. for (i=x; i<(20-x); i++) lcd_puts(" ");
  452. lcd_gotoxy(x, y);
  453. }
  454.  
  455.  
  456. uint32_t StrTo_uint32 (char *string1)
  457. // nombres positifs (non signés) seulement 0...4 294 967 295 (4,2 x 10^9)
  458. // atoi m'a occasionné des problèmes... pour les grands nombres > 2 octets
  459. {
  460. uint8_t i;
  461. uint32_t x;
  462. i=0;
  463. x=0;
  464.  
  465. while (string1[i] != '\0')
  466. {
  467. x=(10 * x) + (string1[i] -48);
  468. i++;
  469. }
  470. return x;
  471. }
  472.  
  473.  
  474.  
  475. void lcd_aff_nb (int32_t valeur1, uint8_t nb_chiffres, uint8_t position_pt_decimal, char affi_zero )
  476. //affiche un nombre positif en representation decimale
  477. // affi_zero = 1 affiche les zéros non significatifs
  478. {
  479. int32_t N;
  480. uint8_t r ;
  481. char tbl[7];
  482. uint8_t i;
  483. char affz;
  484.  
  485. affz = affi_zero;
  486.  
  487. if ((valeur1 == 0) && (affz == 0)) // le zéro tout seul est significatif
  488. {
  489. for (i=1; i<nb_chiffres; i++) {lcd_putc(' '); }
  490. lcd_putc('0');
  491. }
  492. N = valeur1;
  493.  
  494. for (i=1; i<=nb_chiffres; i++)
  495. {
  496. r=48 + N % 10; // modulo (reste de la division)
  497. N /= 10; // quotient
  498. tbl[i]=r;
  499. }
  500.  
  501. for (i=1; i<=nb_chiffres; i++)
  502. {
  503. if (i == (nb_chiffres - position_pt_decimal +1) ) { lcd_puts("."); affz=1;} // après le . les 0 seront affichés
  504. if (tbl[nb_chiffres+1-i] != '0') affz=1; // si 1 digit est >0 alors les 0 ultérieurs deviennent significatifs
  505. if ((!affz) && (tbl[nb_chiffres+1-i] == '0')) lcd_putc(' ');
  506. else lcd_putc(tbl[nb_chiffres+1-i]);
  507. }
  508. }
  509.  
  510.  
  511. void lcd_aff_bin (unsigned long int valeur, int nb_digits)
  512. //affiche un nombre en representation binaire
  513. // 16 bits max
  514. {
  515. unsigned char r ;
  516. char tbl[17];
  517. unsigned i;
  518.  
  519. for (i=1; i<=nb_digits; i++)
  520. {
  521. r= 48 + valeur % 2; // modulo (reste de la division)
  522. valeur /= 2; // quotient
  523. tbl[i]=r;
  524. };
  525. for (i=1; i<=nb_digits; i++) lcd_putc(tbl[nb_digits +1 -i]);
  526. }
  527.  
  528.  
  529. void Affi_Etat(int fx_vitesse, int sens_moteur, int num_ligne)
  530. {
  531. int i;
  532.  
  533. char str1[3+1]; // ATTENTION: L'indice du premier élément du tableau est 0
  534.  
  535. if (afficher_etat)
  536. {
  537. for (i=0; i<=2; i++) { str1[i] = ' '; }
  538.  
  539. if (rech_rapide) str1[0]= 'F';
  540. if (terrestre) str1[1]= 'T';
  541. if (sens_moteur == 0) str1[2]= '-';
  542. str1[3] = '\0';
  543.  
  544. lcd_gotoxy(15,num_ligne);
  545. for (i=0; i<=2; i++) lcd_putc(str1[i]);
  546. }
  547. }
  548.  
  549.  
  550. void Affiche_distance_RA(uint8_t x, uint8_t y)
  551. {
  552. if (afficher_diff)
  553. {
  554. int32_t R1;
  555. char signe;
  556.  
  557. R1 = distance_RA(RA, G_RA);
  558. if (sens_ra == 0) {signe= '-';} else signe= ' ';
  559.  
  560. lcd_gotoxy(x,y);
  561. // lcd_puts("DIFF RA: ");
  562. lcd_putc(signe);
  563. lcd_aff_nb (R1,6,0,1);
  564. }
  565. }
  566.  
  567.  
  568. void Affiche_distance_DECLI(uint8_t x, uint8_t y)
  569. {
  570. if (afficher_diff)
  571. {
  572. uint32_t R1;
  573. char signe;
  574.  
  575. R1 = distance_DECLI(DECLI, G_DECLI);
  576. if (sens_decli == 0) {signe= '-';} else signe= ' ';
  577.  
  578. lcd_gotoxy(x,y);
  579. // lcd_puts("DIFF DECLI: ");
  580. lcd_putc(signe);
  581. lcd_aff_nb (R1,6,0,1);
  582. }
  583. }
  584.  
  585.  
  586. void Affiche_position (char num_ligne_LCD, char nom[3+1], int32_t nb_secondes)
  587. {
  588. uint8_t h_ou_d, mn, sec;
  589. uint32_t R1;
  590. char signe;
  591.  
  592. if (afficher_pos)
  593. {
  594. if (nb_secondes < 0)
  595. {
  596. nb_secondes = -nb_secondes;
  597. signe = '-';
  598. }
  599. else signe = ' ';
  600.  
  601. h_ou_d = nb_secondes / 3600;
  602. R1 = nb_secondes % 3600; // % c'est la fonction modulo
  603. mn = R1 / 60;
  604. sec = R1 % 60;
  605. lcd_gotoxy(0, num_ligne_LCD);
  606.  
  607. lcd_puts(nom);
  608. lcd_putc(signe);
  609. lcd_aff_nb (h_ou_d,2,0,1);
  610. lcd_putc(':');
  611. lcd_aff_nb (mn,2,0,1);
  612. lcd_putc(':');
  613. lcd_aff_nb (sec,2,0,1);
  614. }
  615. }
  616.  
  617.  
  618.  
  619. void PAS_moteur_RA(void)
  620. /*Moteur de suivi RA
  621. En mode FAST, ce moteur passe la main a un moteur DC rapide , permettant des vitesses rapides...bien
  622. plus rapides, plusieurs centaines de fois la vitesse siderale au lieu d'un timide 32 x la vitesse siderale}
  623. */
  624. // stk1= GetStackFree; // test la pile (stack) en runtime
  625.  
  626. {
  627.  
  628. if ((Moteur_RA == 0) || (Moteur_RA > 8)) Moteur_RA = 1;
  629.  
  630. if (!stop_RA)
  631. {
  632. if (Sens_moteur_RA == 1)
  633. {
  634. Moteur_RA = (Moteur_RA << 1);
  635. cpt_PAS_RA ++;
  636. if (Moteur_RA > 8) Moteur_RA = 1; //Moteur_RA = %0001 puis 0010 puis 0100 puis 1000 puis 0001 etc...
  637. }
  638. else
  639. {
  640. Moteur_RA = (Moteur_RA >> 1);
  641. cpt_PAS_RA --;
  642. if (Moteur_RA == 0) Moteur_RA = 8; //Moteur_RA =0b1000 puis 0100 puis 0010 puis 0001 puis 1000 etc...
  643. }
  644. Moteur_RA &= 0b00001111;
  645. PORTA &= 0b11110000; // RAZ tous les bits
  646. PORTA |= Moteur_RA; // PA[0..2] utilisees pour le moteur DEC. voir schema
  647. }
  648. else PORTA &= 0b11110000; //stop moteur RA
  649.  
  650. }
  651.  
  652.  
  653. void PAS_moteur_DEC(void)
  654. /*
  655. Remarque: un même sens de rotation du moteur de déclinaison peut augmenter ou diminuer la déclinaison pointée
  656. suivant le quadrant où l'on se trouve
  657. au reset, l'APE demande dans quel quadrant on se trouve (repérés sur la monture par des points de couleur)
  658. voir la figure "mode de calcul DECLI.jpg" dans le répertoire de ce fichier source
  659. voir aussi la fonction "select_secteur_DECLI()" dans ce code source
  660. */
  661.  
  662. {
  663. cli();
  664. if ((Moteur_DEC == 0) || (Moteur_DEC > 8))
  665. {
  666. Moteur_DEC = 1;
  667. }
  668. if (!stop_DEC)
  669. {
  670. if (Sens_moteurDEC == 1)
  671. {
  672. Moteur_DEC = (Moteur_DEC << 1);
  673. if (reverse_inc_dec == 1) {cpt_PAS_DEC++;} else {cpt_PAS_DEC--;}
  674. if (Moteur_DEC > 8) { Moteur_DEC = 1; }
  675. // Moteur_DEC = 0001 puis 0010 puis 0100 puis 1000 puis 0001 etc..
  676. }
  677. else
  678. {
  679. Moteur_DEC = (Moteur_DEC >> 1);
  680. if (reverse_inc_dec == 1) {cpt_PAS_DEC--;} else {cpt_PAS_DEC++;}
  681. if (Moteur_DEC == 0) { Moteur_DEC = 8; }
  682. // Moteur_DEC = 1000 puis 0100 puis 0010 puis 0001 puis 1000 etc..
  683. }
  684.  
  685. Moteur_DEC &= 0b00001111;
  686. PORTA &= 0b00001111;
  687. // uDelay(1);
  688. PORTA = PORTA | (Moteur_DEC << 4);
  689. // PA[4..7] utilisees pour le moteur DEC. voir schema
  690. if (cpt_PAS_DEC > nb_max_PAS_DEC)
  691. {
  692. DECLI = DECLI - nbs_DEC;
  693. if (DECLI < -323990) // on vient d'atteindre la déclinaison -90 (par le bas)
  694. {
  695. stop_DEC =1;
  696. PORTA &= 0b00001111; // stop moteur DEC
  697. }
  698. cpt_PAS_DEC= 0;
  699. }
  700. if (cpt_PAS_DEC < -nb_max_PAS_DEC) // nb_max_PAS_DEC = 10
  701. {
  702. DECLI = DECLI + nbs_DEC; // nbs_DEC = 64
  703. if (DECLI > 323990) // on vient d'atteindre la déclinaison +90 (par le haut)
  704. // voir la figure "mode de calcul DECLI.jpg" dans le repertoire de ce fichier source
  705. {
  706. stop_DEC = 1;
  707. PORTA &= 0b00001111; // stop moteur DEC
  708. }
  709. cpt_PAS_DEC= 0;
  710. }
  711. }
  712. else { PORTA &= 0b00001111; } // stop moteur DEC
  713. }
  714.  
  715.  
  716.  
  717. ISR(BADISR_vect)
  718. {
  719. // évite de planter si une int est enable et pas de procedure associée écrite (ce qui fait reseter l'ATmega)
  720. }
  721.  
  722.  
  723. ISR (TIMER1_COMPA_vect)
  724. // Timer1 comp A interrupt
  725. // voir datasheet ATmega32 p:44 pour les noms des vecteurs d'interruptions
  726. {
  727. PAS_moteur_RA();
  728. }
  729.  
  730.  
  731. ISR (INT0_vect)
  732. /*
  733. Int0 interrupt front descendant phase0 de la roue codeuse de souris sur RA
  734. LA roue codeuse incrementale
  735. je mesure 525 pas pour 1h00 (de graduations sidérales)
  736. 1mn -> 525/60 =8.75 pas
  737. 1s -> 525/3600 = 0.1458 pas
  738. 1 pas -> 6.857s sidérales
  739. */
  740. {
  741. if ((PIND & 0b00010000) > 0 ) { pas_mouse++; }
  742. // le niveau sur l'autre phase en quadrature determine le sens de rotation
  743. else { pas_mouse--; }
  744.  
  745. Angle_Horaire = (float) pas_mouse * 6.857; // la precision se fait ici
  746.  
  747. /*
  748. {On remarque en mode suivi que RA affiché ballade de qq decondes, c'est l'erreur
  749. périodique d'arrondi, sans conséquence sur le suivi, à laquelle s'ajoute un mouvement
  750. de plus grande periode, c'est l'erreur périodique de la mécanique du capteur
  751. incrémental, le moteur pas à pas tournant, lui, commme... une horloge
  752. Mais comme il entraine lui aussi le mouvement par un train d'engrenages,
  753. il y a tout de même une erreur périodique de suivi.
  754. On peut sérieusement envisager un suivi CCD sur étoile guide
  755. Vous l'aurez remarqué, tout cela n'est pas très simple, il faut jouer
  756. avec la précision de la mécanique et les concepts théoriques.
  757. Et lorsque quelque chose cloche, savoir diagnostiquer d'où cela peut bien provenir
  758. Les dérives se produisant sur des périodes longues, il faut savoir faire preuve
  759. de patience lors des mesures.
  760. */
  761. }
  762.  
  763.  
  764. ISR (TIMER2_COMP_vect)
  765. // REMARQUE: The OCF2 Flag is automatically cleared when the interrupt is executed. (p:116 du pdf)
  766. {
  767. PAS_moteur_DEC();
  768. OCR2 = TP_DEC; // OCR2 est un registre 8 bits
  769. }
  770.  
  771.  
  772.  
  773. void Event_1s(void)
  774. {
  775.  
  776. // ticked= 1;
  777.  
  778. if (!terrestre) { Temps_sid = Temps_sid + 1.00274; } // environ 366/365 voir le commentaire en intro
  779. /*
  780. on ajoute 1.00274 (l'inverse de 0,9972696) et pas 0,9972696 parce que la seconde
  781. sidérale dure moins longtemps que la seconde solaire et donc chaque seconde solaire
  782. il s'écoule un peu plus d'une seconde sidérale.
  783. remarque: pour un suivi de la Lune, il faudra utiliser un temps Lunaire, la Lune
  784. étant "en retard" d'environ une heure par jour... (24h soit un tour en 21 jours)
  785. */
  786.  
  787. memoRA_6 = memoRA_5;
  788. memoRA_5 = memoRA_4;
  789. memoRA_4 = memoRA_3;
  790. memoRA_3 = memoRA_2;
  791. memoRA_2 = memoRA_1;
  792.  
  793. RA = RA_objet + (int32_t) (Temps_sid + Angle_Horaire);
  794.  
  795. /*
  796. le premier terme (RA_objet) est fixe, pour un objet selectionné
  797. le second terme (Temps_sid) est fonction du temps
  798. le troisième terme est fonction du suivi
  799. la somme (RA) est l'ascension droite de la position effectivement pointé
  800. par le télescope à un instant donné
  801. */
  802.  
  803. memoRA_1 = RA;
  804. RA_affi = (memoRA_1 + memoRA_2 + memoRA_3 + memoRA_4 + memoRA_5 + memoRA_6) / 6; // intégration logicielle
  805.  
  806.  
  807. // ( moyenne de 6 valeurs pour éviter l'affichage fluctuant )
  808. // l'inconvéniant est que ça induit un retard dans l'affichage pendant les déplacements rapides (par ex: le go_to)
  809.  
  810. if (RA_affi < 0) { RA_affi = RA_affi + 86400; }
  811. if (RA_affi > 86400) { RA_affi = RA_affi % 86400; } // modulo
  812.  
  813. // RA doit toujours être compris entre 0..24h, jamais négatif
  814. if (RA < 0) { RA = RA + 86400; }
  815. if (RA > 86400) { RA = RA % 86400; }// modulo
  816.  
  817. // RA_affi = RA;
  818.  
  819. /*
  820. L'erreur d'arrondi ne depasse jamais la 1/2 seconde sur le total.
  821. Elle est donc négligeable apres quelques centaines de secondes.
  822. Temps_sid est incremente par le temps et Angle_Horaire par la rotation de l'axe RA
  823. si le moteur est embraye, l'un compense l'autre
  824. */
  825.  
  826.  
  827. }
  828.  
  829.  
  830. void calcul_TPi_RA (void) // en fontion du numero 'num_vt_RA'
  831. {
  832. int vt2;
  833. // stk1= GetStackFree; // test la pile (stack) en runtime
  834. if (num_vt_RA == -1) { stop_RA= 1; } else stop_RA= 0;
  835.  
  836. if (num_vt_RA >= 0) { vt2 = num_vt_RA; Sens_moteur_RA = 1; }
  837. else { vt2 = -num_vt_RA - 2; Sens_moteur_RA= 0; }
  838.  
  839. if (num_vt_RA != -1) {fx_vitesse_RA = 1 << vt2;} else {fx_vitesse_RA = 1;}
  840.  
  841. if (fx_vitesse_RA != 0 ) { TPi_RA= TP_suivi_RA / fx_vitesse_RA; } else { TPi_RA = TP_suivi_RA; }
  842. }
  843.  
  844.  
  845. void calcul_TP_DEC (void) // en fontion du numero 'num_vt_DEC'
  846. {
  847. unsigned char vt2;
  848.  
  849. stop_DEC = (num_vt_DEC == 0) ? 1 : 0;
  850.  
  851. if (num_vt_DEC >= 0) { vt2 = num_vt_DEC; Sens_moteurDEC = 1; }
  852. else { vt2 = - num_vt_DEC; Sens_moteurDEC = 0; }
  853.  
  854. if (vt2 > 0 ) { fx_vitesse_DEC = (1 << (vt2-1)); }
  855.  
  856. if (fx_vitesse_DEC != 0) { TP_DEC = 255 / fx_vitesse_DEC; }
  857. else { TP_DEC = 250; }
  858. }
  859.  
  860.  
  861. int RecvRC5 (void)
  862. /* recepteur RC5 bas niveau qui scrute le port relié au capteur et décode le signal
  863.  
  864. 2 bits de start
  865. 1 bit de basculement
  866. 5 bits d'adressage (type d'appareil, TV, VCR etc...)
  867. 6 bits de commande (touches)
  868. */
  869. {
  870. uint32_t t;
  871. uint8_t niv_entree, niv1, niv2; /* booleens - niveaux des deux demi plateaux constituant un bit */
  872. uint8_t n;
  873. uint16_t data;
  874.  
  875. t=0;
  876. niv1=0;
  877. niv2=0;
  878. data = 0;
  879.  
  880. niv_entree=1;
  881. /* attente pendant la durée d'une trame d'un front descendant (le signal issu du capteur est à 1 au repos) */
  882.  
  883. const unsigned long int tmax = 14*1778; //24892us = durée de 1 trame (environ 25ms donc)
  884.  
  885. while ( (niv_entree == 1) && (t<= tmax) )
  886. {
  887. if ( (PIND & 0b10000000) > 0) { niv_entree=1; } else { niv_entree=0; }
  888. _delay_us(1);
  889. t++;
  890. }
  891. /* si le signal parvient trop vite (< 2 bits) on en déduit qu'on a pris le train en marche et on saute,
  892. puisque lecture impossible de la trame en cours
  893. */
  894. if (t < (889 * 2)) return t;
  895.  
  896. if (t > tmax) return 2; /* temps maxi écoulé, pas de signal reçu */
  897.  
  898. /* ici on se trouve juste un epsilon après le basculement à 0 du premier bit de start (milieu de bit) */
  899.  
  900. _delay_us(444); /* durée de 1/4 bit */
  901.  
  902. for (n=1; n<=13; n++)
  903. {
  904. _delay_us(889); // durée de 1/2 bit
  905. /* ici on se trouve au milieu du niveau du plateau du demi bit */
  906. if ( (PIND & 0b10000000) == 0) { niv1 = 0; } else { niv1 = 1; }
  907. _delay_us(889); // durée de 1/2 bit
  908. /* ici on se trouve au milieu du second plateau du demi bit */
  909. if ( (PIND & 0b10000000) == 0) { niv2 = 0; } else { niv2 = 1; }
  910. /* ici on connait les valeurs des deux niveaux, on en déduit le sens de la transition (front montant ou descendant)*/
  911. if (niv1 == niv2) { return 3; } // erreur de lecture, bit non valide
  912. if ((niv1 == 1 ) && (niv2 == 0)) { data |= 0b00000001; }
  913. data = data << 1;
  914. }
  915. data = data >> 1; // on rejette le dernier décallage (sans perte de bit puisque largeur data = 16 bits > )
  916.  
  917. rxCmd_IR = data & 0b0000000000111111;
  918. rxAdr_IR = (data & 0b0000011111000000) >> 6;
  919. bit_bascul_IR = (data & 0b0000100000000000) >> 11;
  920. return 0;
  921. }
  922.  
  923.  
  924. void interroge_IR(void)
  925. {
  926. if (RecvRC5() == 0)
  927. {
  928. octet_IR = rxCmd_IR;
  929. memo_bitsix= bitsix;
  930. bitsix= bit_bascul_IR;
  931. if (bitsix != memo_bitsix) nouveau=1; else nouveau=0;
  932.  
  933. PORTD |= 0b01000000; /* allume LED */
  934. }
  935. else { octet_IR = 0xFF; }
  936.  
  937. PORTD &= 0b10111111; /* eteint LED */
  938.  
  939. if (!nouveau) { octet_IR = 0xFF; } /* pas de répétition auto dans cette application */
  940. }
  941.  
  942.  
  943. void test_IR(void)
  944. {
  945. int r1;
  946.  
  947. afficher_pos= 0;
  948. lcd_clrscr();
  949. lcd_gotoxy(0, 0);
  950.  
  951. lcd_puts("Test IR STOP=ok ou 0");
  952.  
  953. while (rxCmd_IR !=0)
  954. {
  955. r1 = RecvRC5();
  956. if (r1==0)
  957. {
  958. lcd_gotoxy(2,1);
  959. lcd_puts("CMD= ");
  960. lcd_aff_nb (rxCmd_IR, 5, 0, 0 );
  961.  
  962. lcd_gotoxy(2,2);
  963. lcd_puts("Adr= ");
  964. lcd_aff_nb (rxAdr_IR, 5, 0, 0 );
  965.  
  966. lcd_gotoxy(2,3);
  967. lcd_puts("Bsc= ");
  968. lcd_aff_nb (bit_bascul_IR, 5, 0, 0 );
  969.  
  970. _delay_ms(10);
  971. }
  972. }
  973. lcd_clrscr();
  974. afficher_pos = 1;
  975. }
  976.  
  977.  
  978. uint16_t saisie_nombre (uint8_t nb_chiffres, uint16_t valeur_max)
  979. {
  980. uint16_t x;
  981. uint8_t n;
  982.  
  983. x=0;
  984. n=0;
  985. while ((octet_IR != 23) && (n < nb_chiffres)) // touche ok (à voir... suivant la télécommande)
  986. {
  987. interroge_IR();
  988. if ((octet_IR != 255) && (octet_IR >= 0) && (octet_IR <= 9))
  989. {
  990. n++;
  991. x *= 10;
  992. x += octet_IR;
  993. if (x>valeur_max) { return valeur_max; }
  994.  
  995. lcd_gotoxy(5,2);
  996. lcd_aff_nb (x, nb_chiffres, 0, 0 );
  997. }
  998. }
  999. _delay_ms(200);
  1000. octet_IR = 255; // pour éviter que la derniere valeur saisie (23) ne soit interprétée par la fonction appelante
  1001. return x;
  1002. }
  1003.  
  1004.  
  1005. void select_Objet(char fileName_i[12+1]) // selectionne 1 etoile dans le fichier sur la SD-card
  1006. {
  1007. char nom_objet[10+1];
  1008. //char fileName1[12+1];
  1009. char etiquette1[6+1];
  1010. char ratxt[5+1];
  1011. char declitxt[7+1];
  1012. char string1[20+1];
  1013. uint16_t n1;
  1014. uint8_t result;
  1015.  
  1016. afficher_pos=0;
  1017. lcd_gotoxy(0,1);
  1018. lcd_puts("saisir NUM, puis Ok");
  1019. n1 = saisie_nombre(4, 9110);
  1020. if (n1<= nbr_ast) {n_OBJ = n1;}
  1021.  
  1022. //strcpy(fileName1, "ETOILES1.ETL"); // nom du fichier contenant les objets sur la SD-card
  1023. sprintf(etiquette1,"!E%04d",n_OBJ); // exemple: etiquette1 = E!0284 soit 6 caracteres (+1)
  1024.  
  1025. result = read_string_in_File ( etiquette1, fileName_i);
  1026. if (result==0)
  1027. {
  1028. /*
  1029. ici str_lu contient une ligne avec ce format: (à décoder)
  1030. !E0015_R00503D0104726_ALPHERATZ-_And_2.06
  1031. 01234567890123456789012345678901234567890123456789
  1032. 00000000001111111111222222222233333333334444444444
  1033. */
  1034. strcpy_a_n(nom_objet, str_lu, 22, 10 );
  1035. nom_objet[10]='\0';
  1036.  
  1037. strcpy_a_n(ratxt, str_lu, 8,5);
  1038. ratxt[5] = '\0';
  1039. sel_RA=StrTo_uint32(ratxt); // le format lu n'est pas signé; ne pas utiliser atoi ici !
  1040.  
  1041. strcpy_a_n(declitxt, str_lu, 14,7);
  1042. declitxt[7] = '\0';
  1043. sel_DECLI=StrTo_uint32(declitxt); // le format lu n'est pas signé; ne pas utiliser atoi ici !
  1044. }
  1045. else
  1046. {
  1047. lcd_clrscr();
  1048. lcd_puts("PAS TROUVE");
  1049. }
  1050. sprintf(string1,"%04d %10.10s",n_OBJ, nom_objet); //mise en forme pour l'affi
  1051. lcd_clrscr();
  1052. lcd_puts(string1);
  1053. _delay_ms(2000);
  1054.  
  1055. octet_IR=255;
  1056. lcd_clrscr();
  1057. afficher_pos=1;
  1058. }
  1059.  
  1060.  
  1061. void select_pos_actuelle_BSC(void)
  1062. {
  1063. char fileName1[12+1];
  1064. lcd_clrscr();
  1065. lcd_puts("Select HR actuelle");
  1066.  
  1067. strcpy(fileName1, "ETOILES1.ETL"); // nom du fichier contenant les objets sur la SD-card
  1068. select_Objet(fileName1);
  1069. Temps_sid = 0;
  1070. Angle_Horaire = 0;
  1071. pas_mouse = 0;
  1072. RA_objet = sel_RA;
  1073. memoRA_6 = sel_RA;
  1074. memoRA_5 = sel_RA;
  1075. memoRA_4 = sel_RA;
  1076. memoRA_3 = sel_RA;
  1077. memoRA_2 = sel_RA;
  1078. memoRA_1 = sel_RA;
  1079. DECLI = sel_DECLI;
  1080.  
  1081. // réaffiche la position goto qui n'est pas réaffichée cycliquement
  1082. // contrairement à la position actuelle
  1083. Affiche_position(2, "gA ", G_RA);
  1084. Affiche_position(3, "gD ", G_DECLI);
  1085. }
  1086.  
  1087.  
  1088. void select_pos_goto_BSC(void)
  1089. {
  1090. char fileName1[12+1];
  1091. lcd_clrscr();
  1092. lcd_puts("Select HR->GOTO");
  1093.  
  1094. strcpy(fileName1, "ETOILES1.ETL"); // nom du fichier contenant les objets sur la SD-card
  1095. select_Objet(fileName1);
  1096.  
  1097. G_RA = sel_RA;
  1098. G_DECLI = sel_DECLI;
  1099.  
  1100. // réaffiche la position goto qui n'est pas réaffichée cycliquement
  1101. // contrairement à la position actuelle
  1102. Affiche_position(2, "gA ", G_RA);
  1103. Affiche_position(3, "gD ", G_DECLI);
  1104. }
  1105.  
  1106.  
  1107. void select_pos_goto_DEEP(void)
  1108. {
  1109. char fileName1[12+1];
  1110. lcd_clrscr();
  1111. lcd_puts("Select NGC->GOTO");
  1112.  
  1113. strcpy(fileName1, "DEEPSKY1.OBJ"); // nom du fichier contenant les objets sur la SD-card
  1114. select_Objet(fileName1);
  1115.  
  1116. G_RA = sel_RA;
  1117. G_DECLI = sel_DECLI;
  1118.  
  1119. // réaffiche la position goto qui n'est pas réaffichée cycliquement
  1120. // contrairement à la position actuelle
  1121. Affiche_position(2, "gA ", G_RA);
  1122. Affiche_position(3, "gD ", G_DECLI);
  1123. }
  1124.  
  1125. void select_secteur_DECLI(void)
  1126. {
  1127. lcd_clrscr();
  1128. lcd_gotoxy(0, 0);
  1129. lcd_puts("Select secteur DECLI");
  1130. lcd_gotoxy(0, 1);
  1131. lcd_puts("1 - ORANGE");
  1132. lcd_gotoxy(0, 2);
  1133. lcd_puts("2 - VERT");
  1134.  
  1135. while ((octet_IR != 1) && (octet_IR != 2)) // touche ok (à voir... suivant la télécommande)
  1136. {
  1137. interroge_IR();
  1138. if (octet_IR != 255)
  1139. {
  1140. switch (octet_IR)
  1141. {
  1142. case 1 :{reverse_inc_dec=0;}
  1143. break;
  1144.  
  1145. case 2 :{reverse_inc_dec=1;}
  1146. break;
  1147. }
  1148. }
  1149. }
  1150. lcd_clrscr();
  1151. }
  1152.  
  1153.  
  1154. void go_to (uint8_t mode_exploration)
  1155. {
  1156. char fast_enable;
  1157. uint32_t dst_ra;
  1158. uint32_t memo_dst_ra;
  1159. uint32_t dst_decli;
  1160. uint32_t memo_dst_decli;
  1161. uint32_t memo_sens_decli;
  1162. uint16_t tp_max;
  1163.  
  1164. goto_en_cours = 1;
  1165. fast_enable = 1;
  1166. afficher_pos = 0; // concerne l'affichage auto par l'INT "onSysTick"
  1167. lcd_clrscr();
  1168. lcd_gotoxy(0, 0);
  1169. lcd_puts("GOTO........");
  1170. _delay_ms(300);
  1171. lcd_clrscr();
  1172.  
  1173. lcd_gotoxy(0,0);
  1174. lcd_puts("-*-*-*-*-");
  1175. lcd_gotoxy(0,1);
  1176. lcd_puts("-*-*-*-*-");
  1177.  
  1178. Affiche_position(2, "gA ", G_RA);
  1179. Affiche_position(3, "gD ", G_DECLI);
  1180.  
  1181.  
  1182. #define diff_Ra_min 10
  1183.  
  1184. // touches d'annulation du goto = '0' et 'POWER'(code 12)
  1185. // hum... cette fonction d'annulation est supprimée (trop gourmande en temps processeur) Faire un hard reset!
  1186. dst_ra=90000; // > à la plus grande possible (86400s)
  1187. dst_decli=325000; // > à la plus grande possible (324000)
  1188. tp_max=0;
  1189. goto_RA_termine = 0;
  1190. goto_DECLI_termine = 0;
  1191.  
  1192. dst_decli = distance_DECLI(DECLI, G_DECLI); // afin de déterminer sens_decli au préalable
  1193.  
  1194. while ( ( ( !goto_RA_termine) || ( !goto_DECLI_termine) )
  1195. && ((octet_IR != 0) && (octet_IR != 23) && tp_max < 12000 ) )
  1196. {
  1197. // au moins un goto (RA ou DEC) en cours
  1198.  
  1199. tp_max++;
  1200. // ==========================================================================================
  1201. memo_dst_ra = dst_ra;
  1202. dst_ra = distance_RA(RA, G_RA);
  1203.  
  1204. if ((dst_ra < 150) || (dst_ra > memo_dst_ra))
  1205. //si dans la grande fouchette, ou pire, si dépassé, ne repassera plus enable
  1206. {
  1207. fast_enable = 0;
  1208. if (mode_exploration)
  1209. {
  1210. PORTB &= 0b11111100; // stop moteur DC par ouverture du relais (PB1=0)
  1211. if (!terrestre) {num_vt_RA= 0; } else { num_vt_RA= -1; }
  1212. calcul_TPi_RA();
  1213. Timer1_setTime(TPi_RA);
  1214. goto_RA_termine = 1; // disjoncte définitivement} // on ne fignole pas dans ce cas
  1215. }
  1216. }
  1217. if (dst_ra < diff_Ra_min) // si dans la petite fouchette
  1218. { // goto RA terminé
  1219. if (!terrestre) {num_vt_RA= 0; } else { num_vt_RA= -1; }
  1220. calcul_TPi_RA();
  1221. Timer1_setTime(TPi_RA);
  1222. goto_RA_termine = 1; // disjoncte définitivement
  1223. lcd_gotoxy(0,0);
  1224. lcd_puts("FIN GT RA");
  1225. }
  1226. if (!goto_RA_termine) //si goto RA en cours...
  1227. {
  1228. TPi_RA = 1200;
  1229. Timer1_setTime(TPi_RA);
  1230. if (sens_ra == 0)
  1231. {
  1232. Sens_moteur_RA = 0;
  1233. if (fast_enable)
  1234. {
  1235. PORTB &= 0b11111110;
  1236. PORTB |= 0b00000010; // sens=0 ; mise en marche moteur DC
  1237. stop_RA = 1;
  1238. }
  1239. else
  1240. {
  1241. PORTB &= 0b11111100; // stop moteur DC par ouverture du relais (PB1=0)
  1242. stop_RA = 0;
  1243. }
  1244. }
  1245. if (sens_ra == 1)
  1246. {
  1247. Sens_moteur_RA = 1;
  1248.  
  1249. if (fast_enable)
  1250. {
  1251. PORTB &= 0b11111110;
  1252. PORTB |= 0b00000011; // sens=1 ; mise en marche moteur DC
  1253. stop_RA = 1;
  1254. }
  1255. else
  1256. {
  1257. PORTB &= 0b11111100; // stop moteur DC par ouverture du relais (PB1=0)
  1258. stop_RA = 0;
  1259. }
  1260. }
  1261. }
  1262. // ==========================================================================================
  1263.  
  1264. memo_dst_decli = dst_decli;
  1265. memo_sens_decli = sens_decli;
  1266. dst_decli = distance_DECLI(DECLI, G_DECLI);
  1267. if ( /*(dst_decli < nbs_DEC) ||*/ (sens_decli == !memo_sens_decli) )
  1268. { // si sens_decli change de valeur, goto DEC terminé
  1269. num_vt_DEC = 0;
  1270. calcul_TP_DEC();
  1271. goto_DECLI_termine = 1; // disjoncte définitivement
  1272. lcd_gotoxy(0,1);
  1273. lcd_puts("FIN GT DEC");
  1274. }
  1275.  
  1276. if (!goto_DECLI_termine) // si goto DECLI en cours...
  1277. {
  1278. stop = 0;
  1279. stop_DEC = 0;
  1280. if (!sens_decli)
  1281. {
  1282. if (!reverse_inc_dec) { num_vt_DEC = 4; /* if ( dst_decli < 200) num_vt_DEC = 1; */}
  1283. else { num_vt_DEC= -4; /* if ( dst_decli < 200) num_vt_DEC = -1; */ }
  1284. calcul_TP_DEC();
  1285. }
  1286. else
  1287. {
  1288. if (!reverse_inc_dec) { num_vt_DEC= -4; /* if ( dst_decli < 200) num_vt_DEC = -1; */ }
  1289. else { num_vt_DEC = 4; /* if ( dst_decli < 200) num_vt_DEC = 1; */ }
  1290. calcul_TP_DEC();
  1291. }
  1292. }
  1293. // ==========================================================================================
  1294.  
  1295. compteur2++;
  1296. switch (compteur2)
  1297. {
  1298. case 20 : Affiche_distance_RA(12,0);
  1299. break;
  1300.  
  1301. case 40 : { Affiche_distance_DECLI(12,1); compteur2 = 0; }
  1302. break;
  1303.  
  1304. }
  1305. _delay_ms(5);
  1306. //interroge_IR();
  1307.  
  1308. }
  1309.  
  1310. stop_RA = 0;
  1311. if (!terrestre) {num_vt_RA= 0; } else { num_vt_RA= -1; }
  1312. calcul_TPi_RA();
  1313. Timer1_setTime(TPi_RA);
  1314. num_vt_DEC = 0;
  1315. calcul_TP_DEC();
  1316. afficher_pos = 1;
  1317. PORTB &= 0b11111100; // stop moteur DC par ouverture du relais (PB1=0)
  1318. _delay_ms(1000);
  1319. goto_en_cours = 0;
  1320.  
  1321. lcd_clrscr();
  1322. // Affi_facteur_vitesse(fx_vitesse_RA, Sens_moteur_RA, stop_RA, 0);
  1323. }
  1324.  
  1325.  
  1326. void explore_zone (void)
  1327. {
  1328. uint8_t n;
  1329.  
  1330. lcd_clrscr();
  1331. lcd_gotoxy(0,0); lcd_puts("Explore zone");
  1332. lcd_gotoxy(0,2); lcd_puts("touche Ok pour stop");
  1333.  
  1334. G_RA = RA;
  1335. G_DECLI = DECLI;
  1336.  
  1337. G_RA -= 500;
  1338. if (G_RA < 0) { G_RA = G_RA + 86400; }
  1339. if (G_RA > 86400) { G_RA = G_RA % 86400; } // modulo
  1340. // RA doit toujours être compris entre 0..24h, jamais négatif
  1341. G_DECLI -= 18000;
  1342.  
  1343. go_to(1); // va au début de la première ligne
  1344. n=0;
  1345. while ((n<6) && (octet_IR != 23))
  1346. {
  1347. //interroge_IR();
  1348. n++;
  1349. G_RA += 1000; go_to(1);// explore la ligne sens direct
  1350. G_DECLI += 3000; go_to(1);//descend à la ligne suivante
  1351. G_RA -= 1000; go_to(1); // explore la ligne sens inverse
  1352. G_DECLI += 3000; go_to(1);//descend à la ligne suivante
  1353. }
  1354. lcd_clrscr();
  1355. }
  1356.  
  1357.  
  1358. ISR (TIMER0_COMP_vect)
  1359. // timer 1ms
  1360. {
  1361. nb_ms2++;
  1362. if (nb_ms2 >= 1000)
  1363. {
  1364. nb_ms2=0;
  1365. Event_1s();
  1366. }
  1367. }
  1368.  
  1369.  
  1370.  
  1371. void DECLI_plus (void)
  1372. {
  1373. stop = 0;
  1374. if (!terrestre && !rech_rapide)
  1375. {
  1376. num_vt_DEC++;
  1377. if (num_vt_DEC > 4) num_vt_DEC = 4;
  1378. }
  1379. else
  1380. {
  1381. if (num_vt_DEC == 0) num_vt_DEC = 4;
  1382. else num_vt_DEC = 0; // pour ne pas passer directement de -4 à +4 ! bonjour le choc mécanique!
  1383. }
  1384. }
  1385.  
  1386.  
  1387. void DECLI_moins (void)
  1388. {
  1389. stop= 0;
  1390. if (!terrestre && !rech_rapide)
  1391. {
  1392. num_vt_DEC--;
  1393. if (num_vt_DEC < - 4) num_vt_DEC = -4;
  1394. }
  1395. else
  1396. {
  1397. if (num_vt_DEC == 0) num_vt_DEC = -4;
  1398. else num_vt_DEC = 0; // pour ne pas passer directement de +4 à -4 !
  1399. }
  1400.  
  1401. }
  1402.  
  1403.  
  1404. void polaire(void)
  1405. {
  1406. RA_objet = 0;
  1407. memoRA_6 = 0;
  1408. memoRA_5 = 0;
  1409. memoRA_4 = 0;
  1410. memoRA_3 = 0;
  1411. memoRA_2 = 0;
  1412. memoRA_1 = 0;
  1413. DECLI=324000;
  1414.  
  1415. lcd_clrscr();
  1416. lcd_gotoxy(5,1);
  1417. lcd_puts("POLAIRE");
  1418. _delay_ms(1000);
  1419. lcd_clrscr();
  1420. Affiche_position(2, "gA ", G_RA);
  1421. Affiche_position(3, "gD ", G_DECLI);
  1422.  
  1423. }
  1424.  
  1425.  
  1426. void Test_SDcard(void)
  1427. {
  1428. char fileName1[12+1];
  1429. char etiquette1[5+1];
  1430. uint8_t i;
  1431.  
  1432. strcpy(fileName1, "ETOILES1.ETL");
  1433. strcpy(etiquette1, "!E029");
  1434.  
  1435. read_string_in_File ( etiquette1, fileName1);
  1436. for (i=0; i<40; i++) { lcd_putc(str_lu[i]); }
  1437.  
  1438. while (1) ;
  1439.  
  1440. }
  1441.  
  1442.  
  1443. void menu_secondaire(void)
  1444. {
  1445. uint8_t fin;
  1446.  
  1447. lcd_clrscr();
  1448. lcd_gotoxy(0,0); lcd_puts("1 - RESET");
  1449. lcd_gotoxy(0,1); lcd_puts("2 - POLAIRE");
  1450. lcd_gotoxy(0,2); lcd_puts("3 - ");
  1451. lcd_gotoxy(0,3); lcd_puts("4 - Explore Zone");
  1452.  
  1453. fin=0;
  1454. while ((octet_IR !=0) && !fin)
  1455. {
  1456. interroge_IR();
  1457. if (octet_IR != 255)
  1458. {
  1459. switch (octet_IR)
  1460. {
  1461. case 1 : // SOFT RESET
  1462. {
  1463.  
  1464. lcd_clrscr();
  1465. lcd_gotoxy(1,1);
  1466. lcd_puts("SOFT RESET dans 1s");
  1467. _delay_ms(1000);
  1468. wdt_enable( 10 ); // active le chien de garde
  1469. while(1); // boucle infinie --> le chien de garde fait reseter
  1470. }
  1471. break;
  1472.  
  1473. case 2 : polaire();
  1474. break;
  1475.  
  1476. case 3 : {fin=1;}
  1477. break;
  1478.  
  1479. case 4 :
  1480. {
  1481. explore_zone();
  1482. fin=1;
  1483. }
  1484. break;
  1485.  
  1486. case 0 : case 56 :
  1487. {
  1488. lcd_clrscr();
  1489. Affiche_position(2, "gA ", G_RA);
  1490. Affiche_position(3, "gD ", G_DECLI);
  1491. fin=1;
  1492. }
  1493. break;
  1494. }
  1495. }
  1496. }
  1497.  
  1498. }
  1499.  
  1500.  
  1501.  
  1502. int main (void)
  1503. {
  1504. unsigned char error, FAT32_active;
  1505.  
  1506. wdt_disable();
  1507. nb_ms2=0;
  1508. Moteur_RA = 0;
  1509. Moteur_DEC = 0;
  1510.  
  1511. init_ports();
  1512. InitINTs();
  1513.  
  1514. spi_init(); // fonction de SPI_routines.c
  1515.  
  1516. compteur1 = 0;
  1517. compteur2 = 0;
  1518. Sens_moteur_RA = 1;
  1519. terrestre = 0;
  1520. rech_rapide = 0;
  1521. goto_en_cours = 0;
  1522. mode_transfert = 0;
  1523. rattraper_jeu = 0;
  1524.  
  1525.  
  1526. /*PARAMETRES RA
  1527. Vis sans fin = roue dentée noire 34.25T -> 6h siderales
  1528. 1h sid-> 34.25/6 = 5.70833 T (A)
  1529. 1h sid-> A*81*60/26 = 1067.02 T du Moteur (B) (60 et 26 sont le nb de dents des roues blanches du coupleur de moteurs)
  1530. 10mn sid-> B/6 = 177.836 T du Moteur (C)
  1531. Frequence: C/600s * 1.00274 * 200 pas = 59.44127 Hz (D) le facteur 1.00274 = 366/365 voir commentaire en intro
  1532.  
  1533. */
  1534. TP_suivi_RA= 16823; // (soit 1/16823us = 59.44243Hz).
  1535. //le suivi peut donc se faire avec une precision ajustable à 59ppm près
  1536. nb_max_PAS_RA= 10000000 / TP_suivi_RA; // ce qui donne round(594.424) = 594 -> donc erreur d'arrondi 0.07%
  1537.  
  1538. //la précision est bonne mais en contre partie l'affichage n'est mis à jour que tous les 10s
  1539. //dans une version précédente l'affichage étais mis à jour toutes les secondes, mais l'erreur était de 1.22% !
  1540.  
  1541. num_vt_RA = 0; // [-5..+5] ( 0 = vitesse de suivi, -1 = stop moteur)
  1542. calcul_TPi_RA();
  1543. Timer1_setTime(TPi_RA);
  1544. cpt_PAS_RA = 0;
  1545. stop_RA = 0;
  1546. stop = 0;
  1547.  
  1548. Sens_moteurDEC = 1;
  1549. num_vt_DEC = 0;
  1550. calcul_TP_DEC();
  1551. stop_DEC = 1;
  1552.  
  1553. memoRA_6 = 0;
  1554. memoRA_5 = 0;
  1555. memoRA_4 = 0;
  1556. memoRA_3 = 0;
  1557. memoRA_2 = 0;
  1558. memoRA_1 = 0;
  1559.  
  1560. RA = 0;
  1561. RA_objet = 0;
  1562. DECLI = 0;
  1563. Temps_sid = 0;
  1564. Angle_Horaire = 0;
  1565. pas_mouse = 0;
  1566. G_RA = 0;
  1567. G_DECLI = 0;
  1568. reverse_inc_dec = 0;
  1569.  
  1570. lcd_init(LCD_DISP_ON);
  1571. lcd_clrscr();
  1572. lcd_home();
  1573. lcd_puts("APE2009 version v");
  1574. lcd_puts(version);
  1575. lcd_gotoxy(7,2);
  1576. lcd_puts("LINUX");
  1577. _delay_ms(1000);
  1578.  
  1579.  
  1580. SD_init();
  1581. FAT32_active = 1;
  1582.  
  1583. error = getBootSectorData (); //read boot sector and keep necessary data in global variables
  1584. if(error)
  1585. {
  1586. lcd_clrscr();
  1587. lcd_puts("FAT32 not found!"); //FAT32 incompatible drive
  1588. FAT32_active = 0;
  1589. _delay_ms(2000);
  1590. }
  1591.  
  1592. select_secteur_DECLI();
  1593.  
  1594. lcd_clrscr();
  1595.  
  1596. afficher_pos = 1;
  1597. afficher_diff = 1;
  1598. afficher_etat = 1;
  1599. in232_en_cours = 0;
  1600.  
  1601. Affiche_position(2, "gA ", G_RA);
  1602. Affiche_position(3, "gD ", G_DECLI);
  1603.  
  1604. _delay_ms(10);
  1605.  
  1606. Affi_Etat(fx_vitesse_RA, Sens_moteur_RA, 2);
  1607. Affi_Etat(fx_vitesse_DEC, Sens_moteurDEC, 3);
  1608.  
  1609.  
  1610. Timer1_setTime(TP_suivi_RA);
  1611.  
  1612.  
  1613. sei(); // enable interruptions
  1614.  
  1615. PORTA &= 0b11111011; // met le moteur RA en marche
  1616. n_OBJ = 1;
  1617.  
  1618.  
  1619. compteur1=0;
  1620.  
  1621.  
  1622. while (1)
  1623. {
  1624. // if (( mode_transfert) && (input_message_ok) && (!in232_en_cours)) { traitement_message();}
  1625.  
  1626. interroge_IR();
  1627.  
  1628. compteur1++;
  1629. if (compteur1 > 7) {compteur1 = 0;}
  1630.  
  1631. lcd_gotoxy(13,2);
  1632. if ( reverse_inc_dec ) { lcd_putc('V'); } else { lcd_putc('O'); }
  1633.  
  1634. lcd_gotoxy(13,3);
  1635. if (mode_transfert) { lcd_putc('S'); } else { lcd_putc(' '); }
  1636.  
  1637. switch (compteur1)
  1638. {
  1639. case 1 :
  1640. {
  1641. Affiche_position(0, " A ", RA_affi);
  1642. Affi_Etat(fx_vitesse_RA, Sens_moteur_RA, 2);
  1643. }
  1644. break;
  1645.  
  1646. case 2 : Affiche_position(1, " D ", DECLI);
  1647. break;
  1648.  
  1649. case 3 : Affiche_distance_RA(12,0);
  1650. break;
  1651.  
  1652. case 4 : Affiche_distance_DECLI(12,1);
  1653. break;
  1654.  
  1655. case 5 : Affi_Etat(fx_vitesse_DEC, Sens_moteurDEC, 3);
  1656. break;
  1657.  
  1658. case 6 : {;} // { if (mode_transfert) { traitement_message(); } } // RS232
  1659. break;
  1660.  
  1661. }
  1662.  
  1663.  
  1664. if (octet_IR != 255)
  1665. {
  1666. switch (octet_IR)
  1667. {
  1668. case 1 : select_pos_actuelle_BSC();
  1669. break;
  1670.  
  1671. case 2 : select_pos_goto_BSC();
  1672. break;
  1673.  
  1674. case 3 : select_pos_goto_DEEP();
  1675. break;
  1676.  
  1677. case 9 :
  1678. {
  1679. terrestre = !terrestre; // toggle mode terrestre
  1680. if (terrestre)
  1681. {
  1682. num_vt_DEC= 0;
  1683. num_vt_RA= - 1; // arret moteur RA
  1684. calcul_TPi_RA();
  1685. PORTB &= 0b11111100; // stop moteur DC par ouverture du relais (PB1=0)
  1686. }
  1687. }
  1688. break;
  1689.  
  1690. case 4 :
  1691. {
  1692. lcd_clrscr();
  1693. lcd_gotoxy(0, 1);
  1694. lcd_puts("UN HOMME A LA MER!");
  1695. G_RA = RA; // fonction qui permet de revenir au même emdroit (par le GO-TO)
  1696. G_DECLI = DECLI;
  1697. _delay_ms(500);
  1698. lcd_clrscr();
  1699. Affiche_position(2, "gA ", G_RA);
  1700. Affiche_position(3, "gD ", G_DECLI);
  1701. }
  1702. break;
  1703.  
  1704. case 5 : {Test_SDcard();}
  1705. break;
  1706.  
  1707. case 6 :
  1708. {
  1709. rech_rapide = !rech_rapide; // toggle mode FAST
  1710. Affi_Etat(fx_vitesse_RA, Sens_moteur_RA, 2);
  1711. Affi_Etat(fx_vitesse_DEC, Sens_moteurDEC, 3);
  1712. }
  1713. break;
  1714.  
  1715. case 7 :
  1716. {
  1717. select_secteur_DECLI();
  1718. Affiche_position(2, "gA ", G_RA);
  1719. Affiche_position(3, "gD ", G_DECLI);
  1720. }
  1721. break;
  1722.  
  1723. case 8 :
  1724. {
  1725. test_IR();
  1726. Affiche_position(2, "gA ", G_RA);
  1727. Affiche_position(3, "gD ", G_DECLI);
  1728. }
  1729. break;
  1730.  
  1731. case 12 :
  1732. {
  1733. stop = 0;
  1734. if (!terrestre) // touche rouge (i , marche-arret)
  1735. {
  1736. stop_RA = 0;
  1737. num_vt_RA = 0;
  1738. calcul_TPi_RA();
  1739. Timer1_setTime(TPi_RA);
  1740. num_vt_DEC = 0;
  1741. Affi_Etat(fx_vitesse_RA, Sens_moteur_RA, 2);
  1742. }
  1743. else
  1744. {
  1745. num_vt_RA= - 1; // arret moteur RA
  1746. num_vt_DEC= 0; // arret moteur DECLI
  1747. PORTB &= 0b11111100; // stop moteur DC par ouverture du relais (PB1=0)
  1748. }
  1749. }
  1750. break;
  1751.  
  1752. case 13 :
  1753. {
  1754. stop = 0;
  1755. num_vt_RA= - 1; // ARRET
  1756. PORTA |= 0b00000100;
  1757. TP_RA = TP_suivi_RA; // en vue de la remise en marche ulterieure
  1758. Timer1_setTime(TP_RA);
  1759. num_vt_DEC= 0;
  1760. calcul_TPi_RA();
  1761. PORTB &= 0b11111100; // stop moteur DC par ouverture du relais (PB1=0)
  1762. }
  1763. break;
  1764.  
  1765. case 32 : { if (!reverse_inc_dec) { DECLI_plus(); } else { DECLI_moins(); } }
  1766. //suivant le quadrant, le moteur ne doit pas tourner dans le même sens pour s'approcher de la polaire
  1767. break;
  1768.  
  1769. case 33 : { if (!reverse_inc_dec) { DECLI_moins(); } else { DECLI_plus(); } }
  1770. break;
  1771.  
  1772. case 23 : // remise en marche du SUIVI (ou STOP en mode terrestre)
  1773. {
  1774. stop = 0;
  1775. num_vt_DEC= 0; //touches ok et AV - à voir suivant télécommande
  1776. if (!terrestre)
  1777. {
  1778. num_vt_RA = 0; // moteur RA en vitesse de suivi
  1779. PORTB &= 0b11111100; // stop moteur DC par ouverture du relais (PB1=0)
  1780. }
  1781. else
  1782. {
  1783. num_vt_RA = - 1; // arret moteur RA
  1784. num_vt_DEC= 0; // arret moteur DECLI
  1785. PORTB &= 0b11111100; // stop moteur DC par ouverture du relais (PB1=0)
  1786. }
  1787. calcul_TPi_RA();
  1788. }
  1789. break;
  1790.  
  1791.  
  1792. case (16) :
  1793. {
  1794. stop = 0;
  1795. if ((terrestre + rech_rapide) == 0) // Touche fleche droite
  1796. {
  1797. if (num_vt_RA == 0) {num_vt_RA = 4 - 1;} // si vitesse de suivi
  1798. else { num_vt_RA= 0; } // sinon vitesse de suivi
  1799. calcul_TPi_RA();
  1800. }
  1801. else // dans ce cas on discrimine entre terrestre et rech_rapide
  1802. {
  1803. //--------------------------------------------------
  1804. // commencons par terrestre
  1805. if ((terrestre) && (!rech_rapide))
  1806. {
  1807. if (num_vt_RA == -1) { num_vt_RA = 4 - 1; } // si arreté
  1808. else { num_vt_RA = -1; } // sinon stop;
  1809. calcul_TPi_RA();
  1810. }
  1811.  
  1812. //--------------------------------------------------
  1813. // continuons par rech_rapide (attention: la recherche rapide fonctionne aussi en mode terrestre)
  1814. if (rech_rapide)
  1815. {
  1816. if ((num_vt_RA == -1) || (num_vt_RA == 0))
  1817. {
  1818. num_vt_RA = 4 - 1;
  1819. PORTB &= 0b11111110;
  1820. PORTB |= 0b00000011; // sens=1 ; mise en marche moteur DC
  1821. stop_RA = 1;
  1822. }
  1823. else
  1824. {
  1825. num_vt_RA = 0; //suivi; pour ne pas passer directement de -6 à +4 !
  1826. if (terrestre) { num_vt_RA = - 1; } //stop
  1827. calcul_TPi_RA();
  1828. PORTB &= 0b11111100; // stop moteur DC par ouverture du relais (PB1=0)
  1829. }
  1830. }
  1831. //--------------------------------------------------
  1832. }
  1833. }
  1834. break;
  1835.  
  1836. case (17) :
  1837. {
  1838. stop = 0;
  1839. if ((terrestre + rech_rapide) == 0)
  1840. {
  1841. if (num_vt_RA == 0) {num_vt_RA = -4 - 1;} // si vitesse de suivi
  1842. else { num_vt_RA= 0; } // sinon vitesse de suivi
  1843. calcul_TPi_RA();
  1844. }
  1845.  
  1846. else // dans ce cas on discrimine entre terrestre et rech_rapide
  1847. {
  1848. //--------------------------------------------------
  1849. // commencons par terrestre
  1850. if ((terrestre) && (!rech_rapide))
  1851. {
  1852. if (num_vt_RA == -1) {num_vt_RA = -4 - 1;} // si arreté }
  1853. else { num_vt_RA= -1; }
  1854. calcul_TPi_RA();
  1855. }
  1856.  
  1857. //--------------------------------------------------
  1858. // continuons par rech_rapide (attention: la recherche rapide fonctionne aussi en mode terrestre)
  1859. if (rech_rapide)
  1860. {
  1861. if ((num_vt_RA == -1) || (num_vt_RA == 0))
  1862. {
  1863. num_vt_RA = -4 - 1;
  1864. PORTB &= 0b11111110;
  1865. PORTB |= 0b00000010; // sens=0 ; mise en marche moteur DC
  1866. stop_RA = 1;
  1867. }
  1868. else
  1869. {
  1870. num_vt_RA = 0;
  1871. if (terrestre) { num_vt_RA = -1; }
  1872. calcul_TPi_RA();
  1873. PORTB &= 0b11111100; // stop moteur DC par ouverture du relais
  1874. }
  1875. }
  1876.  
  1877. }
  1878. }
  1879. break;
  1880.  
  1881. case (43) : {;} // LIBRE // Touche rouge du bas (<<)
  1882. break;
  1883.  
  1884. case (47) :
  1885. {
  1886. go_to(0); // touche (.) tout en bas de la télécommande
  1887. Affiche_position(2, "gA ", G_RA);
  1888. Affiche_position(3, "gD ", G_DECLI);
  1889. }
  1890. break;
  1891.  
  1892. case 56 : menu_secondaire(); // touche (>) en bas
  1893. break;
  1894.  
  1895.  
  1896. default : { ;}
  1897. }
  1898. Timer1_setTime(TPi_RA);
  1899. calcul_TP_DEC();
  1900. }
  1901. }
  1902. }
  1903.  
  1904.  
  1905.  
  1906.  

17 DOCUMENTS TECHNIQUES (auteur Silicium 628)

Voici l'arborescence correcte des fichiers du logiciel.
A noter que le catalogue tycho2 n'est pas rangé avec les autres pour la simple raison que je ne veux pas
l'uploader sur le serveur à chaque modification des sources, étant donné son volume (14Mo)
et du fait que le contenu ne changera pas.
Vous devez le charger séparément avec le lien ci-dessous,
et le placer le dossier "tycho2"obtenu au bon endroit comme indiqué ci-contre.
A noter: La structure des enregistrements dans les fichiers tyc2a628.dat et tyc2b628.dat m'est propre, elle est documentée. Les autres formats de ce catalogue que vous pouvez trouver ici et là sur internet NE CONVIENNENT PAS.
Quant à la version d'origine du catalogue Tycho2, elle est trop lourde (500Mo) pour l'usage que j'en fais (206 octets par étoile au lieu de 13 seulement).

ARCHIVES:

  • version 3.6 (avec liaison USB-RS232 et mémorisation des données en EEPROM)

18 A noter:

L'APE 2009 v3.6 (voir dans "archives") utilisait un convertisseur USB-RS232 du commerce basé sur une puce Prolific Technology PL2303, compatible Linux (sans drivers supplémentaires) fournissant un port série RS232 virtuel sous la forme /dev/ttyUSB0 Mon logiciel APE2009 le détecte automatiquement.

Je l'utilise actuellement avec satisfaction. J'ai acheté ce convertisseur dans une "boutique" sur Ebay...

Les ports com RX et TX de l'ATmega fonctionnant avec des niveaux logiques TTL (plus exactement CMOS) 0V / +5V et le convertisseur USB-RS232 fournissant un port com à la norme RS232 (niveaux -12V / + 12V environ), il faut ajouter un petit convertisseur de niveaux à transistors décrit ci-dessous.

19 Liaison ATmega - SD-card + Adaptateur de niveaux 5V - 3,3V (Les cartes SD-card fonctionnent exclusivement sous 3V3 )

20 Adaptateur de niveaux RS232 - TTL (pour la version 3.6 archivée)

21 A propos du firmware embarqué dans l'ATmega:

Pour ceux qui sont intéressés par la programmation des ATmega en langage C, vous trouverez dans les codes sources que je publie librement ici:

LCD La gestion d'un afficheur LCD en langage C
RC5 Une fonction de décodage des signaux RC5 de télécommandes IR universelles
USART Des fonctions USART de dialogue entre le PC et l'ATmega en mode série RS232 (dans la version 3.6 archivée)
SD card
Utilisation d'une carte mémoire SD-card par l'ATmega32 (Un grand merci à CC Dharmani (voir liens externes))
EEPROM> Des fonctions permettant au programme embarqué d'enregistrer et de lire des données en EEPROM de l'ATmega
Interruptions> Comment utiliser les Timers et gérer les interruptions de l'ATmega en langage C
avr-libc Comment utiliser des fonctions prédéfinies de avr-libc
Bibliothèques Comment inclure et utiliser des fonctions de bibliothèques externes
Chaines de caractères L'utilisation de fonctions de traitement de chaines de caractères (comme sprintf)
Affichage> Comment afficher des textes sur le LCD, mais aussi des caractères et des nombres entiers ou décimaux
Pointeurs L'utilisation des pointeurs en C


22 BAC A SABLE:

Je relate ici des expérimentations dont certaines seront retenues, d'autres pas. 14 mai 2008: J'ai fabriqué un codeur rotatif incrémental à partir du mécanisme d'une souris optique à boule, que j'ai placé sur l'axe de la vis sans fin de l'ascension droite. Cela permet de continuer à gérer la position RA même en débrayant le moteur pas à pas et en tournant la vis manuellement. C'est aussi la possibilité d'obtenir des vitesses de déplacement RA bien plus grandes que par le moteur pas à pas (manuellement ou avec un moteur électrique DC classique). Je conserverai quand même le moteur pas à pas qui est parfait pour le suivi.

23 -

J'utilise un modèle de souris avec deux leds IR et deux capteurs IR sur chaque axe (roues codeuses) et pas un seul capteur dont les signaux sont plus difficiles à interpréter (impulsions même en l'absence de rotation.

Avec un double capteur on obtient deux signaux en quadrature de phase, qu'il suffit de mettre en forme avec un trigger de Smith (CD40106) avant de les faire ingurgiter par l'ATmega32.

Et justement les pins d'entrées INT (INT0 et INT1) sont libres dans l'APE2009. Donc du côté logiciel la mise en oeuvre est un jeu d'enfant.
En fait une seule INT suffit: lors du front descendant d'une phase, on teste le niveau (haut ou bas) de l'autre phase pour déterminer le sens de rotation. Voir le code source en C.

Sur la photo on voit une roue dentée en nylon que je vais sertir sur l'axe métallique (un petit bout de tube d'antenne télescopique enfilé en force pour ajuster le diamètre et le tour est joué).

24 -

21 mai 2008:

La vitesse la plus rapide de déplacement en ascension droite, qui est de 32 fois la vitesse sidérale, et qui est obtenue directement avec le moteur pas à pas RA se révèle très insuffisante pour une utilisation confortable. Le problème est que moteur pas à pas en question décroche pour des vitesses plus importantes. J'ai pensé le remplacer par un moteur à courant continu asservi en vitesse, mais la vitesse de rotation requise pour le suivi est vraiment très basse pour un tel moteur compte tenu de la démultiplication utilisée. En conclusion le moteur pas à pas est parfait (aux vibrations près) pour le suivi qui demande une vitesse très faible et une précision très grande, alors qu'un moteur DC est parfait pour un déplacement rapide.

Que faire?
-un embrayage mécanique de l'un ou l'autre type de moteur suivant les circonstances? c'est compliqué. -monter les deux types de moteurs sur le même arbre? Le moteur DC non utilisé ne gêne en rien le PaP (à condition toutefois de ne pas le court-circuiter électriquement). Mais... le PaP non utilisé oppose un couple important, de plus de par la conception de l'APE2008, il se trouve court-circuité par les L272M au repos, avec le risque de consommer (coté moteur CD) et de griller les L272 par effet dynamo (coté moteur PaP).

Je pensais avoir trouvé la solution (non retenue, voir plus bas): pendant la rotation rapide, le moteur DC fait presque tout le boulot mais on alimente le moteur PaP avec une fréquence compatible avec ladite rotation (mais pour laquelle le moteur PaP seul aurait décroché depuis longtemps). Et ça tourne (très vite). On cumule ainsi la précision du PaP pour le suivi avec une vitesse maximale de plusieurs centaines de fois la vitesse sidérale.

25 -

26 mai 2008:
Le principe des deux moteurs montés sur le même arbre s'avère décevant! en fait le moteur PaP forcé à tourner trop vite (la tension contre-électromotrice [back EMF en anglais ou BEMF] devenant supérieure à la tension d'alimentation) se laisse certes entraîner, mais à une vitesse glissante par rapport aux signaux appliqués. Sur le plan électronique, ce n'est vraiment pas satisfaisant. J'abandonne donc cette idée pour la remplacer par celle de l'embrayage. C'est compliqué ai-je dit plus haut? Pas tant que ça, la preuve, je l'ai fait.

26 La partie mécanique

27 -

La mécanique comporte un moteur pas à pas (débrayable) pour le suivi et un moteur DC pour les déplacements rapides de la monture. Détail important: j'ai rajouté un contacteur de fin de course (micro-switch) qui, câblé en série avec le moteur DC, ne permet l'alimentation de ce dernier que lorsque la roue intermédiaire se trouve en position complètement débrayée.

En effet, un démarrage intempestif du moteur DC en mode embrayé n'entraîne pas le moteur PaP mais pourrait endommager les roues dentées en nylon.

Dès lors, le moteur DC ainsi protégé et l'électro-aimant peuvent être commandés par le même signal. Le soft n'a plus qu'un organe à gérer au lieu de deux, il y a moins de fils à relier, on économise un transistor de commande, et surtout la sécurité est excellente et totalement à l'abri d'un plantage logiciel éventuel.

28 -

29 mai 2008:

Le soft est modifié (depuis la version 4.0) pour gérer le moteur DC et les déplacements rapides. Cela permet de balayer 1h sidérale (soit 15 degrés d'arc) en 10 secondes de temps. Le déplacement rapide est également utilisé pendant le GO-TO. Le moteur DC est commandé par deux petits relais: un pour le sens de rotation, le second pour la mise en marche et l'arrêt.

29 UTILISATION

1- Une fois le télescope mis en station, pointer manuellement une étoile bien lumineuse, et l'indiquer à l'appareil en la choisissant parmi celles disponibles.

2-C'est tout ! L'affichage est dès lors étalonné, et vous pouvez utiliser les vitesses de déplacement rapide de la monture, l'affichage indiquera toujours la position réelle de celle-ci. La fonction GO-TO fera pivoter la monture vers un autre objet choisi parmi les milliers enregistrés sur la SDcard.

30 -

Liens...

34304