Aller au contenu

Est-ce que cela intéresse qqun,un driver indi et code arduino pour l'ouverture d'un toit à distance ?


Messages recommandés

Posté (modifié)

OK c'est tout bon!! j'ai bien le driver dans EKOS.

Maintenant il me reste à faire causer mon UNO avec le driver ^^ pour le moment j'ai un initial contact controller failed!! je vais jouer avec le UNO maintenant!!

 

Edit: après avoir remis la bonne valeur de vitesse de connexion c'est du tout bon!!

 

me reste à comprendre le fonctionnement du driver et aussi le montage.

D’ailleurs n'aurais tu pas ca à tout hasard? histoire de comprendre les connexion entre les swicth et relais sur le UNO stp.

 

merci.

Modifié par olivier1986
Posté

:)

il y a 4 minutes, olivier1986 a dit :

me reste à comprendre le fonctionnement du driver et aussi le montage.

D’ailleurs n'aurais tu pas ca à tout hasard? histoire de comprendre les connexion entre les swicth et relais sur le UNO stp.

 

merci.

 

Posté

Pas de soucis pour le montage et commands il fonctionne. 

Par contre pour le driver pure, je peux pas trop t'aider, car même moi je ne comprends pas tous. 

Je te montre tous ça demain 

Posté

Super, merci :)

 

j'ai essayer le driver sur tinkercad, cela fonctionne. Je peux ainsi tester les différents Switch et relais en simulation!! ca va aider je pense :)

 

Bonne nuit et encore merci.

Posté

@ch_porchet

Bonjour,

 

j'ai pu faire en mode plaque d'essais le montage de l'abris en limitant les choses.

J'ai pu brancher ma carte 4 relais, 2 switch on-off qui simule les fin de courses ainsi que deux boutons pour OPEN et CLOSE en local.

 

Mais je ne parviens pas à faire bouger mon petit moteur 5V car j'ai un soucis avec EKOS: dans le driver, je recois le message suivant:

"roof is externaly locked, no movement possible" avec une led rouge sur "roof lock" dans la fenetre de configuration du driver.

 

j'ai essayé ton programme ainsi que celui du github avec les deux boutons.

 

Une idée?

 

Olivier

Posté

Hello

Je pense que c'est a cause de mes capteurs de position Park pour la monture. 

Mais si tu pontes à la masse l'entrée A5 (de mémoire) cela devrais simuler la chose. 

Ou alors tu peut supprimé cette fonctions sans le code arduino ou alors, le plus simple c'est de changer l'état dans les condition des "case" 

Posté

Ok. Je vais essayer de voir ca 🙂

 

et aurais tu aussi des plans/schemas des branchements faits stp. Notament sur l’utilité d’un « bouton relais » etc...

 

merci 😄

Posté (modifié)

hello

alors j'ai ça comme schémas ,je sais pas si ça te suffit .

je l'avais fais pour Tom .

IMG_20200326_223406-1.jpg4

 

le switch "I-Optron" c'est la position park de la monture.

le bouton "power" c'est la commande manuel pour mettre sous 220V l'observatoire

 

Modifié par ch_porchet
Posté (modifié)

@ch_porchet

Merci pour l'image.

Je vais regarder cela de près.

 

Je bloque sur le code arduino.

J'ai bien débloqué les fonctions liées au park monture dans kstars.

 

Du coup tout fonctionne presque bien, car j'ai un unique problème, mais pas des moindre!!

Tout fonctionne: les relais, le moteur, les fdc, les boutons ouvrir fermé ect .... sauf que, via l'interface INDI lorsque je clique sur OPEN ou CLOSE et que je simule le déplacement du toit via les fdc, INDI me dit bien que la toit est OPEN ou CLOSE ou MOVING, par contre, et c'est là le pb, les relais se déclenche pas, donc le moteur ne tourne pas 😕

En faisant avec les boutons là ça fonctionne, donc il s'agit dans mon pb uniquement du corps du programme qui dit ouvre les relais, ferme les relais etc..

J'ai beau zieuter je fatigue!!

 

je te joins le code si tu veux bien regarder ^^ Merci :)

 

 

RollOff_codefinal.ino

Modifié par olivier1986
Posté

Quand kstars se connecte à l'arduino , est-ce que le relais 220V s’enclenche ?

car c'est aussi une condition pour que le reste fonctionne .

Sinon t'on code me semble juste  

Posté

Je ne l’ai pas installé a vrai dire.

il es déclaré dans le sketch mais son pin n’est raccordé a rien.

je vais essayer avec un petit relais qui me reste!

je te redis

Posté

Ouai, il faut essayé ça, comme ça tu es sur que la condition et OK. 

D'ailleurs c'est aussi ce que j'ai fais. 😉

 

Bon je vais ouvrir un sujet pour ma combine de ma station météo car impossible de l'installer 😞

Posté

Et d’ailleurs, peux tu m’expliquer le fonctionnement en general?

lors d’une soirée, tu programmes ta soirée, ekos ouvre l’abris fais la séance et le referme c’est bien ca?

quel est l’interêt du relais sur le 220v?

les équipements sur le relais 12v démarre t-ils au démarrage d’ekos?

 

merci 🙂

Posté (modifié)
Il y a 2 heures, olivier1986 a dit :

lors d’une soirée, tu programmes ta soirée, ekos ouvre l’abris fais la séance et le referme c’est bien ca?

Juste c'est bien ça !

Il y a 2 heures, olivier1986 a dit :

les équipements sur le relais 12v démarre t-ils au démarrage d’ekos?

Oui ,tous démarre quand Kstars se connecte 

C'est pour ça que  le relais 220v me sert a alimenté mon transformateur 220V-12VC

et il sert aussi à alimenté le bloc de prises près de la monture pour alimenté les caméra ,la monture etc.....

Comme cela quand je n’utilise pas l’observatoire il n'y a que le pc en veille qui est alimenté par une prise indépendante du reste. 

Modifié par ch_porchet
Posté

Bonsoir,

 

je reviens donner des news.

Tout fonctionne super bien en mode simulation avec ma plaquette d'essais.

J'ai pu lancer avec le mode simulator des télescope et CCD de kstars.

du coup voici l’essai (mes d'autres ont été fait :) )

- création de la séance via le scheduler,

- le toit s'ouvre,

- le télescope se depark et va sur la cible,

- déroulement de la séquence,

- park du télescope,

- park du toit.

 

Bref c'est merveilleux!!

 

Je vais pousser les essais avec mon flip flat crée y'a pas longtemps.

 

@ch_porchet

J'ai beau avoir parcouru en long et en large le programme, je ne comprends pas certaines choses:

le switch général alimentation, il est sensé être toujours allumé non? sinon à quoi sert-il?

Pareil, quel est l'utilité du bouton "power" dans le système? car d'après les essais, pour un fonctionnement sur les boutons OPEN et CLOSE il faut faire un appuis, qui change l'état de "estAlimente" à "!estAlimente' qui revient donc à dire que c'est son contraire.

Par ailleurs j'ai un poil du remodifier le programme mais rien de grave ^^

Bref je vois pas trop.

 

EN revanche, l'idée d'alimenter les relais 12V c'est plutôt cool. J'ai déjà une idée des relais dispo (2 sur les 8 dans le cas d'une carte relais 8 channels)!!

 

Encore merci :)

 

Posté (modifié)

hello

J'ai pas eu le temps de répondre avant je suis entrain de m’intéresser une station météo arduino qui puisse intervenir sur l'ouverture/fermeture du toit.

et pour l'instant c'est pas encore gagné, hélas....

Bref,,

Citation

le switch général alimentation, il est sensé être toujours allumé non?

Non pas tout à fais,il et surtout la pour faire que Kstars puisse tout éteindre a la fin du séance ,car dès que l'arduino reçois des infos par l'usb il enclanche le relais et après 5 min ou il n'as plus rien 

cela coupe l'alimentation 220V

Citation

Pareil, quel est l'utilité du bouton "power" dans le système?

Le bouton "power" et pour enclenché le 220V si kstars n'est pas connecter .

Mais normalement si tu appuies pas sur power avant , et que le pc n'est pas allumé tu ne peux pas ouvrir le toit , mais je ne suis plus sur du tous .

Car on a pas mal modifier le code  pour qu'il fonctionne au mieux avec kstars.

Citation

Par ailleurs j'ai un poil du remodifier le programme mais rien de grave

ok , mais c'est plus pour ta config perso, ou alors tu as simplifier ou améliorer le code , car si cela apporte une amélioration je suis preneur .

Modifié par ch_porchet
Posté

@ch_porchet

Merci pour tes explications.

Je n'ai pas vu de post ouvert pour ta station météo.

Je vais regarder de mon coté puisqu'il s'agit pour moi aussi d'un élément clé de l'observatoire.

De fait, je peux t'accompagner avec mes petites connaissances.

 

La station météo de ce site "https://indilib.org/develop/arduino/meteostation.html"

a un driver déjà implanté dans Kstars (meteostation) dans l’onglet météo lors du choix des drivers dans les profils. J'imagine donc qu'il ne reste qu'à assembler les différents éléments qui compose la station.

 

quel est ton problème?

Posté

salut,

 

j'ai aussi des erreurs, notamment sur le nombre de pin analog.

en remplaçant les valeurs par celle d'un UNO que j'ai sous la main il compile sans erreur. Il faut avoir télécharger toutes les librairies nécessaires.

EN revanche, une fois connecté à Kstars ça se connecte une fois puis de déconnecte. Je pense que c'est lié au fait que je n'ai pas de capteurs de brancher sur le UNO.

J'ai un DHT11 qui semble mort donc il me reste juste le MLX90614 pour tester. Dans le code Arduino on peut désactivé tout le reste. Il faut que j’essaie!

Posté (modifié)

Tu as mis qu'elle code arduino, car moi j'ai déjà des erreurs en vérifiant le code avant d'installer ! 

Tu peut me mettre le lien du code que tu as trouvé, ou directement le code en copie. 

Modifié par ch_porchet
Posté

Pas de soucis.

je peux pas de suite mais pas de soucis.

dans la journée 😉

 

pour info j’ai pu connecter l’arduino sans soucis a kstars avec mon UNO + le mlx90614.

 

avec le code météo test je vois bien la température du mlx90614 mais avec le code final kstars m’indique 0 degrés res, c’est donc qu’il n’arrive pas a lire le capteur.

je pense regarder le code un peu mieux, certainement une histoire de pin

Posté

@ch_porchet

Ci joint le fichier de test avec mon mlx90614. c'est celui fourni avec indi.

j'ai désactivé les sorties non nécessaires pour ne laisser que l'IR.

 

et ci après le code final avec seulement le mlx90614. là ca se connecte bien à kstar mais j'ai 0° donc à voir!! c'est le début! seulement commencé cette nuit à regarder ^^

 

Révélation

/* INDIDUINOMETEO FIRMWARE.
  NACHO MAS 2013. http://indiduino.wordpress.com
  Magnus W. Eriksen 2017 https://github.com/magnue

  Several modifications over indiduinoTemplate:
  .- Include  "i2cmaster.h",  "Adafruit_BMP085.h", "Adafruit_MLX90614.h" and  "dht.h" libraries
   to read the sensors.
  .- Add custimization of pinnumbers, and flags for frezzing and daylight.
  .- Allow user to disable any sensor(s) and its (their) code when compiling.
  .- Several additional functions to read the sensor and calculate flags,
   cloudcover and dew point.
  .- Extend event loop fail checks to awoid reading values from unreadable sensors (IR, P and DHT).
  .- Overwrite firmata TOTAL_ANALOG_PINS and TOTAL_PINS to make room for
   aditional (>6) analog calculate inputs.
  .- Use pullup resitor on inputs for signal flags.
  .- Made new firmware version to make use of recent sensors (BME280 and TSL2591). G. Gagnon 2019
  .- Added BME280 support (BME280 includes Barometric pressure, humidity and temperature sensors)
     -> Removed BMP and DHT G.Gagnon 2019
  .- Added TSL2591 support to replace irradiance sensor. Provides estimate of Sky Quality. G. Gagnon 2019
  .- BME280 and TSL2591 are I2C sensors that connect the same as the MLX90614, through an I2C bus. It is recommended to get
    3.3 volts parts along with the Arduino (Arduino Pro Mini is available in a 3.3V version) to avoid having to use level
    shifters.

  IMPORTANT: Customize following values to match your setup
*/

// Comment out if your setup don't include some sensor.Some sensor combinations are exclusive; BME280 replaces both
// DHT and BMP series sensors, TSL replaces the irradiance sensor but could be used alongside it is the firmware is
// modified appropriately.
//#define USE_DHT_SENSOR          //USE DHT HUMITITY SENSOR. Comment if not.
#define USE_MLX_SENSOR            //USE MELEXIS IR SENSOR. Comment if not.
//#define USE_BME_SENSOR            //USE BME280 ENVIRONMENT SENSOR. Comment if not.
//#define USE_TSL_SENSOR            //USE TSL2591 SENSOR. Comment if not.
//#define USE_P_SENSOR            //USE BMP085 PRESSURE SENSOR. Comment if not.
//#define USE_IRRADIANCE_SENSOR   //USE IRRADIANCE SENSOR (solar cell). Comment if not.

#if defined USE_P_SENSOR && defined USE_BME_SENSOR
  #error Choose either USE_BME_SENSOR or USE_P_SENSOR
#endif

#if defined USE_DHT_SENSOR && defined USE_BME_SENSOR
  #error Choose either USE_BME_SENSOR or USE_DHT_SENSOR
#endif

#if defined USE_TSL_SENSOR && defined USE_IRRADIANCE_SENSOR
  #error Choose either USE_TSL_SENSOR or USE_IRRADIANCE_SENSOR
#endif

//Not everyone consider zero celsius as frezzing and other drivers will react to frezzing as an alert.
//define temperature limit for issuing alert.
//Default 0
#define FREZZING 0

//All sensors (Thr=DHT22,Tir=MELEXIS and Tp=BME280) include a ambient temperature
//Chosse  that sensor, only one, is going to use for main Ambient Temperature:
//#define T_MAIN_Thr
#define T_MAIN_Tir
//#define T_MAIN_Tp

#ifdef USE_IRRADIANCE_SENSOR
  //A multitude of solar cells can be used as IRRADIANCE sensor.
  //Set MINIMUM_DAYLIGHT to the IRRADIANCE output at start of dusk.
  #define MINIMUM_DAYLIGHT 100

   // what analog pin we connected IRRADCIANCE to
  #define IR_RADIANCE_PIN 0
#endif //USE_IRRADIANCE_SENSOR

#ifdef USE_TSL_SENSOR
//Set DAYLIGHT to the SQM output at start of dusk. 15.0 is probably a reasonnable value.
#define DAYLIGHT 15.0
#endif //USE_TSL_SENSOR

#ifdef USE_MLX_SENSOR
//Cloudy sky is warmer that clear sky. Thus sky temperature meassure by IR sensor
//is a good indicator to estimate cloud cover. However IR really meassure the
//temperatura of all the air column above increassing with ambient temperature.
//So it is important include some correction factor:
//From AAG Cloudwatcher formula. Need to improve futher.
//http://www.aagware.eu/aag/cloudwatcher700/WebHelp/index.htm#page=Operational%20Aspects/23-TemperatureFactor-.htm
//Sky temp correction factor. Tsky=Tsky_meassure - Tcorrection
//Formula Tcorrection = (K1 / 100) * (Thr - K2 / 10) + (K3 / 100) * pow((exp (K4 / 1000* Thr)) , (K5 / 100));
#define  K1 33.
#define  K2 0.
#define  K3 4.
#define  K4 100.
#define  K5 100.

//Clear sky corrected temperature (temp below means 0% clouds)
#define CLOUD_TEMP_CLEAR  -8
//Totally cover sky corrected temperature (temp above means 100% clouds)
#define CLOUD_TEMP_OVERCAST  0
//Activation treshold for cloudFlag (%)
#define CLOUD_FLAG_PERCENT  30
#endif //USE_MLX_SENSOR

#define IPS_OK    1
#define IPS_ALERT 3

// Having only two states covering IPS_IDLE, IPS_OK, ... is problematic
// We map IPS_OK to 1 and everything else to 0

#define STATUS_OK HIGH
#define STATUS_NOT_OK LOW

/*END OFF CUSTOMITATION. YOU SHOULT NOT NEED TO CHANGE ANYTHING BELOW */

/*
 * Pin settings
*/
#define PIN_STATUS_CLOUDY   2
#define PIN_STATUS_DEW      4
#define PIN_STATUS_FREZZY   5
#define PIN_STATUS_DAYLIGHT 6
#define PIN_STATUS_SQM      6
#define PIN_STATUS_MLX      7
#define PIN_STATUS_TSL      8
#define PIN_STATUS_BMP      9
#define PIN_STATUS_BME      9

/*
   Firmata is a generic protocol for communicating with microcontrollers
   from software on a host computer. It is intended to work with
   any host computer software package.

   To download a host software package, please clink on the following link
   to open the download page in your default browser.

   http://firmata.org/wiki/Download
*/

/*
  Copyright (C) 2012 Nacho Mas. By default Standard firmata write analog
  input value to PWM pin directly and send the ADC readings to analog output
  without modification. By this modification you can adapt this behaviour.

  two functions are added to the original StandardFirmata.:

  mapAndSendAnalog(int pin):

    Change the value returned by readAnalog before send through
    firmata protocol. By this you can adapt the 0-1024 stadard ADC range
    to more apropiate range (i.e phisical range of a sensor). Also you
    can do some logic or event sent a variable value instead of
    readAnalog.

  mapAndWriteAnalog(int pin,int value):

    Change the value recived through firmata protocol before write to
    PWM output. Alternative can be used to change internal variable value instead
    of setting PWM output.

  (TODO: same for digital input/output)

  NOTE: This only a template and by default do nothing! You have to addapt
    to your real needs before.

  Copyright (C) 2006-2008 Hans-Christoph Steiner.  All rights reserved.
  Copyright (C) 2010-2011 Paul Stoffregen.  All rights reserved.
  Copyright (C) 2009 Shigeru Kobayashi.  All rights reserved.
  Copyright (C) 2009-2011 Jeff Hoefs.  All rights reserved.

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  See file LICENSE.txt for further informations on licensing terms.

  formatted using the GNU C formatting and indenting
*/

/*
   TODO: use Program Control to load stored profiles from EEPROM
*/

#include <Servo.h>
#include "Wire.h"
#include <Firmata.h>


#ifdef USE_MLX_SENSOR
#include "Adafruit_MLX90614.h"
Adafruit_MLX90614 mlx = Adafruit_MLX90614();
#endif //USE_MLX_SENSOR

#ifdef USE_DHT_SENSOR
#include "DHT.h"

#define DHTPIN 3     // Digital pin connected to the DHT sensor

// Uncomment whatever type you're using!
#define DHTTYPE DHT11   // DHT 11
//#define DHTTYPE DHT22   // DHT 22  (AM2302), AM2321
//#define DHTTYPE DHT21   // DHT 21 (AM2301)

DHT dht(DHTPIN, DHTTYPE);
#endif //USE_DHT_SENSOR

#ifdef USE_P_SENSOR
  #include "Adafruit_BMP085.h"
  Adafruit_BMP085 bmp;
#endif //USE_P_SENSOR

#ifdef USE_BME_SENSOR
#include "Adafruit_BME280.h"
Adafruit_BME280 bme;
#endif //USE_BME_SENSOR

#ifdef USE_TSL_SENSOR
#include "Adafruit_TSL2591.h"
Adafruit_TSL2591 tsl = Adafruit_TSL2591();
#endif //USE_TSL_SENSOR


float P, HR, IR, T, Tp, Thr, Tir, Dew, Light, brightness, lux, mag_arcsec2, Clouds, skyT;
int cloudy, dewing, frezzing;
bool mlxSuccess, bmpSuccess, bmeSuccess, tslSuccess, dhtSuccess;

#define TOTAL_ANALOG_PINS       6
#define TOTAL_PINS              20

void setupMeteoStation() {
#ifdef USE_MLX_SENSOR
  if (!(mlxSuccess = mlx.begin())) {
    //set IR sensor fail flag
    digitalWrite(PIN_TO_DIGITAL(PIN_STATUS_MLX), STATUS_NOT_OK);
    IR = 0;
    Tir = 0;
  } else digitalWrite(PIN_TO_DIGITAL(PIN_STATUS_MLX), STATUS_OK); //Make sure IR sensor fail flag is off on success

#endif //USE_MLX_SENSOR

#ifdef USE_TSL_SENSOR
  if (!(tslSuccess = tsl.begin())) {
    //set TSL sensor fail flag
    digitalWrite(PIN_TO_DIGITAL(PIN_STATUS_TSL), STATUS_OK);
    mag_arcsec2 = 0.0;
  } else digitalWrite(PIN_TO_DIGITAL(PIN_STATUS_TSL), STATUS_NOT_OK); //Make sure TSL sensor fail flag is off on success

#endif //USE_MLX_SENSOR

#ifdef USE_P_SENSOR
        if (!(bmpSuccess=bmp.begin())) {
            //set P sensor fail flag
            digitalWrite(PIN_TO_DIGITAL(PIN_STATUS_BMP), STATUS_NOT_OK);
            Tp=0;
            P=0;
        } else digitalWrite(PIN_TO_DIGITAL(PIN_STATUS_BMP), STATUS_OK); //Make sure P sensor fail flag is off on success

#endif //USE_P_SENSOR

#ifndef USE_IRRADIANCE_SENSOR
    Light=0;
#endif //USE_IRRADIANCE_SENSOR

#ifdef USE_BME_SENSOR
  if (!(bmeSuccess = bme.begin())) {
    //set P sensor fail flag
    digitalWrite(PIN_TO_DIGITAL(PIN_STATUS_BME), STATUS_NOT_OK);
    Tp = 0;
    P = 0;
    HR = 0;
  } else digitalWrite(PIN_TO_DIGITAL(PIN_STATUS_BME), STATUS_OK); //Make sure P/BME sensor fail flag is off on success

#endif //USE_BME_SENSOR

#ifdef USE_DHT_SENSOR
 if (dhtSuccess == false) {
    dht.begin();
    // check if we really get a proper result to ensure
    // that the initialization succeeded
    dhtSuccess = !isnan(dht.readHumidity());
    if (dhtSuccess)
      digitalWrite(PIN_TO_DIGITAL(PIN_STATUS_TSL), STATUS_OK);
    else
      digitalWrite(PIN_TO_DIGITAL(PIN_STATUS_TSL), STATUS_NOT_OK);

  }
#endif //USE_DHT_SENSOR

}

/*==============================================================================
   METEOSTATION FUNCTIONS
  ============================================================================*/

#ifdef USE_TSL_SENSOR
void configureSensor(tsl2591Gain_t gainSetting, tsl2591IntegrationTime_t timeSetting)
{
  // You can change the gain on the fly, to adapt to brighter/dimmer light situations
  tsl.setGain(gainSetting);

  // Changing the integration time gives you a longer time over which to sense light
  // longer timelines are slower, but are good in very low light situtations!
  tsl.setTiming(timeSetting);

  /* Display the gain and integration time for reference sake */
  tsl2591Gain_t gain = tsl.getGain();
}

float advancedLightSensorRead(void)
{
  // More advanced data read example. Read 32 bits with top 16 bits IR, bottom 16 bits full spectrum
  // That way you can do whatever math and comparisons you want!
  uint32_t lum = tsl.getFullLuminosity();
  uint16_t ir, full;
  float lux;
 
//  Serial.print("advancedLightSensorRead: GAIN = "); Serial.println(tsl.getGain());
//  Serial.print("advancedLightSensorRead: INTEGRATIONTIME = "); Serial.println(100 + 100*tsl.getTiming());
  lum = tsl.getFullLuminosity(); // first reading will be incorrect of Gain or Time was changed
  ir = lum >> 16;
  full = lum & 0xFFFF;
//  Serial.print("advancedLightSensorRead: lum = "); Serial.println(lum);
//  Serial.print("advancedLightSensorRead: ir = "); Serial.println(ir);
//  Serial.print("advancedLightSensorRead: full = "); Serial.println(full);
  lux = tsl.calculateLux(full, ir);
//  Serial.print("advancedLightSensorRead: lux = "); Serial.println(lux);
 
  if (full < 100){ //Increase GAIN (and INTEGRATIONTIME) if light level too low
    switch (tsl.getGain())
    {
    case TSL2591_GAIN_LOW :
      configureSensor(TSL2591_GAIN_MED, TSL2591_INTEGRATIONTIME_200MS);
      break;
    case TSL2591_GAIN_MED :
      configureSensor(TSL2591_GAIN_HIGH, TSL2591_INTEGRATIONTIME_200MS);
      break;
    case TSL2591_GAIN_HIGH :
      configureSensor(TSL2591_GAIN_MAX, TSL2591_INTEGRATIONTIME_200MS);
      break;
    case TSL2591_GAIN_MAX :
      if(full < 100) {
        switch (tsl.getTiming())
        {
        case TSL2591_INTEGRATIONTIME_200MS :
          configureSensor(TSL2591_GAIN_MAX, TSL2591_INTEGRATIONTIME_300MS);
          break;
        case TSL2591_INTEGRATIONTIME_300MS :
          configureSensor(TSL2591_GAIN_MAX, TSL2591_INTEGRATIONTIME_400MS);
          break;
        case TSL2591_INTEGRATIONTIME_400MS :
          configureSensor(TSL2591_GAIN_MAX, TSL2591_INTEGRATIONTIME_500MS);
          break;
        case TSL2591_INTEGRATIONTIME_500MS :
          configureSensor(TSL2591_GAIN_MAX, TSL2591_INTEGRATIONTIME_600MS);
          break;
        default:
          configureSensor(TSL2591_GAIN_MAX, TSL2591_INTEGRATIONTIME_600MS);
          break;
        }
      }
      break;
    default:
      configureSensor(TSL2591_GAIN_MED, TSL2591_INTEGRATIONTIME_200MS);
      break;
    }
  }

  if (full > 30000){ //Decrease GAIN (and INTEGRATIONTIME) if light level too high
    switch (tsl.getGain())
    {
    case TSL2591_GAIN_LOW :
      break;
    case TSL2591_GAIN_MED :
      configureSensor(TSL2591_GAIN_LOW, TSL2591_INTEGRATIONTIME_200MS);
      break;
    case TSL2591_GAIN_HIGH :
      configureSensor(TSL2591_GAIN_MED, TSL2591_INTEGRATIONTIME_200MS);
      break;
    case TSL2591_GAIN_MAX :
      configureSensor(TSL2591_GAIN_HIGH, TSL2591_INTEGRATIONTIME_200MS);
      break;
    default:
      configureSensor(TSL2591_GAIN_MED, TSL2591_INTEGRATIONTIME_200MS);
      break;
    }
  }
  return lux;
}

float get_mag_arcsec2(float lux)
{
//  Serial.print("get_mag_arcsec2: GAIN = "); Serial.println(tsl.getGain());
//  Serial.print("get_mag_arcsec2: INTEGRATIONTIME = "); Serial.println(100 + 100*tsl.getTiming());
//  Serial.print("get_mag_arcsec2: lux = "); Serial.println(lux);

  mag_arcsec2 = log10(lux/108000)/-0.4;  //(log((ulux/108000) ) /(-0.4)
//  Serial.print("get_mag_arcsec2: mag_arcsec2 = "); Serial.println(mag_arcsec2);
 
  return(mag_arcsec2);
}
#endif

void runMeteoStation() {

#ifdef USE_MLX_SENSOR
  if (mlxSuccess) {
    Tir = mlx.readAmbientTempC() / 100.0;
    IR = mlx.readObjectTempC() / 100.0;
  } else if (mlxSuccess = mlx.begin()) {
    // Retry mlx.begin(), and clear MLX sensor fail flag
    digitalWrite(PIN_TO_DIGITAL(PIN_STATUS_MLX), STATUS_OK);
  }

  Clouds = cloudIndex();
  skyT = skyTemp();
  if (Clouds > CLOUD_FLAG_PERCENT) {
    cloudy = IPS_ALERT;
  } else {
    cloudy = IPS_OK;
  }
#else
  //set MLX sensor fail flag
  digitalWrite(PIN_TO_DIGITAL(PIN_STATUS_MLX), STATUS_NOT_OK);
#endif //USE_MLX_SENSOR

#ifdef USE_DHT_SENSOR
    HR=dht.readHumidity();
    Thr=dht.readTemperature();

    Dew=dewPoint(Thr,HR);
    if (Thr<=Dew+2) {
        dewing=IPS_ALERT;
    } else {
        dewing=IPS_OK;
    }
#else
  #ifndef USE_TSL_SENSOR
    //set HR sensor fail flag
    digitalWrite(PIN_TO_DIGITAL(PIN_STATUS_TSL), STATUS_NOT_OK);
  #endif
#endif //USE_DHT_SENSOR

#ifdef USE_TSL_SENSOR
  if (tslSuccess) {
    brightness = advancedLightSensorRead();
    mag_arcsec2 = get_mag_arcsec2(brightness);
  } else if (tslSuccess = tsl.begin()) {
    // Retry tsl.begin(), and clear TSL sensor fail flag
    digitalWrite(PIN_TO_DIGITAL(PIN_STATUS_TSL), STATUS_OK);
  }
#else
  #ifndef USE_DHT_SENSOR
    //set HR sensor fail flag
    digitalWrite(PIN_TO_DIGITAL(8), STATUS_NOT_OK);
  #endif
#endif //USE_TSL_SENSOR

#ifdef USE_P_SENSOR
    if (bmpSuccess) {
        Tp=bmp.readTemperature();
        P=bmp.readPressure();
    } else if (bmpSuccess=bmp.begin()) {
        // Retry bmp.begin(), and clear P sensor fail flag
        digitalWrite(PIN_TO_DIGITAL(PIN_STATUS_BMP), STATUS_OK);
    }
#else
  #ifndef USE_BME_SENSOR
    //set P sensor fail flag
    digitalWrite(PIN_TO_DIGITAL(PIN_STATUS_BME), STATUS_NOT_OK);
  #endif
#endif //USE_P_SENSOR

#ifdef USE_BME_SENSOR
  if (bmeSuccess) {
    Tp = bme.readTemperature();
    P = bme.readPressure();
    HR = bme.readHumidity();

    Dew = dewPoint(Tp, HR);
    if (Tp <= Dew + 2) {
      dewing = 1;
    } else {
      dewing = 0;
    }
  } else if (bmeSuccess = bme.begin()) {
    // Retry bme.begin(), and clear BME sensor fail flag
    digitalWrite(PIN_TO_DIGITAL(PIN_STATUS_BME), STATUS_OK);
  }
#else
  #ifndef USE_P_SENSOR
    //set BME sensor fail flag
    digitalWrite(PIN_TO_DIGITAL(PIN_STATUS_BME), STATUS_NOT_OK);
  #endif
#endif //USE_BME_SENSOR

#ifdef USE_IRRADIANCE_SENSOR
    Light=analogRead(IR_RADIANCE_PIN);
#endif //USE_IRRADIANCE_SENSOR

#if defined T_MAIN_Thr
    T=Thr;
#elif defined T_MAIN_Tir
  T = Tir;
#elif defined T_MAIN_Tp
  T = Tp;
#endif  //T_MAIN

    if (T<FREZZING) {
      frezzing=IPS_ALERT;
    } else {
      frezzing=IPS_OK;
    }
}

void checkMeteo() {

    if (cloudy==IPS_OK) {
       digitalWrite(PIN_TO_DIGITAL(PIN_STATUS_CLOUDY), STATUS_OK); // enable internal pull-ups
    } else {
       digitalWrite(PIN_TO_DIGITAL(PIN_STATUS_CLOUDY), STATUS_NOT_OK); // disable internal pull-ups
    }
 
    if (dewing==IPS_OK) {
       digitalWrite(PIN_TO_DIGITAL(PIN_STATUS_DEW), STATUS_OK); // enable internal pull-ups
    } else {
       digitalWrite(PIN_TO_DIGITAL(PIN_STATUS_DEW), STATUS_NOT_OK); // disable internal pull-ups
    }

    if (frezzing==IPS_OK) {
       digitalWrite(PIN_TO_DIGITAL(PIN_STATUS_FREZZY), STATUS_OK); // enable internal pull-ups
    } else {
       digitalWrite(PIN_TO_DIGITAL(PIN_STATUS_FREZZY), STATUS_NOT_OK); // disable internal pull-ups
    }
 
#ifdef USE_IRRADIANCE_SENSOR
    if (Light <= MINIMUM_DAYLIGHT) {
       digitalWrite(PIN_TO_DIGITAL(PIN_STATUS_DAYLIGHT), STATUS_OK); // enable internal pull-ups
    } else {
       digitalWrite(PIN_TO_DIGITAL(PIN_STATUS_DAYLIGHT), STATUS_NOT_OK); // disable internal pull-ups
    }
#endif //USE_IRRADIANCE_SENSOR

#ifdef USE_TSL_SENSOR
  if (mag_arcsec2 > DAYLIGHT) {
    digitalWrite(PIN_TO_DIGITAL(PIN_STATUS_SQM), STATUS_OK); // enable internal pull-ups
  } else {
    digitalWrite(PIN_TO_DIGITAL(PIN_STATUS_SQM), STATUS_NOT_OK); // disable internal pull-ups
  }
#endif //USE_TSL_SENSOR

}

// dewPoint function NOAA
// reference: http://wahiduddin.net/calc/density_algorithms.htm
double dewPoint(double celsius, double humidity)
{
  double A0 = 373.15 / (273.15 + celsius);
  double SUM = -7.90298 * (A0 - 1);
  SUM += 5.02808 * log10(A0);
  SUM += -1.3816e-7 * (pow(10, (11.344 * (1 - 1 / A0))) - 1);
  SUM += 8.1328e-3 * (pow(10, (-3.49149 * (A0 - 1))) - 1);
  SUM += log10(1013.246);
  double VP = pow(10, SUM - 3) * humidity;
  double T = log(VP / 0.61078); // temp var
  return (241.88 * T) / (17.558 - T);
}

// delta max = 0.6544 wrt dewPoint()
// 5x faster than dewPoint()
// reference: http://en.wikipedia.org/wiki/Dew_point
double dewPointFast(double celsius, double humidity)
{
  double a = 17.271;
  double b = 237.7;
  double temp = (a * celsius) / (b + celsius) + log(humidity / 100);
  double Td = (b * temp) / (a - temp);
  return Td;
}

#ifdef USE_MLX_SENSOR
//From AAG Cloudwatcher formula. Need to improve futher.
//http://www.aagware.eu/aag/cloudwatcher700/WebHelp/index.htm#page=Operational%20Aspects/23-TemperatureFactor-.htm
//https://azug.minpet.unibas.ch/wikiobsvermes/index.php/AAG_cloud_sensor#Snow_on_the_sky_temperature_sensor
double skyTemp() {
  //Constant defined above
  double Td = (K1 / 100.) * (T - K2 / 10) + (K3 / 100.) * pow((exp (K4 / 1000.* T)) , (K5 / 100.));
  double Tsky = IR - Td;
  return Tsky;
}


double cloudIndex() {
  double Tcloudy = CLOUD_TEMP_OVERCAST, Tclear = CLOUD_TEMP_CLEAR;
  double Tsky = skyTemp();
  double Index;
  if (Tsky < Tclear) Tsky = Tclear;
  if (Tsky > Tcloudy) Tsky = Tcloudy;
  Index = (Tsky - Tclear) * 100 / (Tcloudy - Tclear);
  return Index;
}
#endif //USE_MLX_SENSOR

/* Nacho Mas.
    Change the value returned by readAnalog before send through
    firmata protocol. By this you can adapt the 0-1024 stadard ADC range
    to more apropiate range (i.e phisical range of a sensor). Also you
    can do some logic or event sent a variable value instead of
    readAnalog.
*/
int mapAndSendAnalog(int pin) {

  //some scalation are use. Don't change without changing also skeleton file
  int value = 0;
  int result = 0;

  switch (pin) {
    //PIN 14->A0, 24->A10
    case 0:
      result = (IR + 273) * 20;
      break;
    case 1:
      result = (Tir + 273) * 20;
      break;
    case 2:
      result = (P / 10);
      break;
    case 3:
      result = (Tp + 273) * 20;
      break;
    case 4:
      result = HR * 100;
      break;
    case 5:
      result = (Thr + 273) * 20;
      break;
    case 6:
      result = (Dew + 273) * 20;
      break;
    case 7:
#ifdef USE_TSL_SENSOR
      result = mag_arcsec2 * 100;
#endif
#ifdef USE_IRRADIANCE_SENSOR
      result=Light;
#endif
      break;
    case 8:
      result = Clouds;
      break;
    case 9:
      result = (skyT + 273) * 20;
      break;
    case 10:
      result = (T + 273) * 20;
      break;


    default:
      result = value;
      break;
  }
  Firmata.sendAnalog(pin, result);
}

/* Nacho Mas.
    Change the value recived through firmata protocol before write to
    PWM output. Alternative can be used to change internal variable value instead
    of setting PWM output.
*/
int mapAndWriteAnalog(int pin, int value) {
  int pwmPin = PIN_TO_PWM(pin);
  int result = 0;
  switch (pwmPin) {
    case 5:
    case 6:
    case 9:
    //             result=map(value, 0, 100, 0, 255);
    //             break;
    default:
      result = value;
      break;
  }
  analogWrite(pwmPin, result);
}

/*==============================================================================
   STANDAR FIRMATA FUNCTIONS
  ============================================================================*/

void disableI2CPins();
void enableI2CPins();
void reportAnalogCallback(byte analogPin, int value);

// move the following defines to Firmata.h?
#define I2C_WRITE B00000000
#define I2C_READ B00001000
#define I2C_READ_CONTINUOUSLY B00010000
#define I2C_STOP_READING B00011000
#define I2C_READ_WRITE_MODE_MASK B00011000
#define I2C_10BIT_ADDRESS_MODE_MASK B00100000

#define MAX_QUERIES 1
#define MINIMUM_SAMPLING_INTERVAL 1000 //

#define REGISTER_NOT_SPECIFIED -1

/*==============================================================================
   GLOBAL VARIABLES
  ============================================================================*/

/* analog inputs */
int analogInputsToReport = 0; // bitwise array to store pin reporting

/* digital input ports */
byte reportPINs[TOTAL_PORTS];       // 1 = report this port, 0 = silence
byte previousPINs[TOTAL_PORTS];     // previous 8 bits sent

/* pins configuration */
byte pinConfig[TOTAL_PINS];         // configuration of every pin
byte portConfigInputs[TOTAL_PORTS]; // each bit: 1 = pin in INPUT, 0 = anything else
int pinState[TOTAL_PINS];           // any value that has been written

/* timer variables */
unsigned long currentMillis;        // store the current value from millis()
unsigned long previousMillis = 0;     // for comparison with currentMillis
int samplingInterval = 19;          // how often to run the main loop (in ms)

/* i2c data */
struct i2c_device_info {
  byte addr;
  byte reg;
  byte bytes;
};

/* for i2c read continuous more */
i2c_device_info query[MAX_QUERIES];

byte i2cRxData[32];
boolean isI2CEnabled = false;
signed char queryIndex = -1;
unsigned int i2cReadDelayTime = 0;  // default delay time between i2c read request and Wire.requestFrom()

Servo servos[MAX_SERVOS];

void readAndReportData(byte address, int theRegister, byte numBytes) {
  // allow I2C requests that don't require a register read
  // for example, some devices using an interrupt pin to signify new data available
  // do not always require the register read so upon interrupt you call Wire.requestFrom()
  if (theRegister != REGISTER_NOT_SPECIFIED) {
    Wire.beginTransmission(address);
#if ARDUINO >= 100
    Wire.write((byte)theRegister);
#else
    Wire.send((byte)theRegister);
#endif
    Wire.endTransmission();
    delayMicroseconds(i2cReadDelayTime);  // delay is necessary for some devices such as WiiNunchuck
  } else {
    theRegister = 0;  // fill the register with a dummy value
  }

  Wire.requestFrom(address, numBytes);  // all bytes are returned in requestFrom

  // check to be sure correct number of bytes were returned by slave
  if (numBytes == Wire.available()) {
    i2cRxData[0] = address;
    i2cRxData[1] = theRegister;
    for (int i = 0; i < numBytes; i++) {
#if ARDUINO >= 100
      i2cRxData[2 + i] = Wire.read();
#else
      i2cRxData[2 + i] = Wire.receive();
#endif
    }
  }
  else {
    if (numBytes > Wire.available()) {
      Firmata.sendString("I2C Read Error: Too many bytes received");
    } else {
      Firmata.sendString("I2C Read Error: Too few bytes received");
    }
  }

  // send slave address, register and received bytes
  Firmata.sendSysex(SYSEX_I2C_REPLY, numBytes + 2, i2cRxData);
}

void outputPort(byte portNumber, byte portValue, byte forceSend)
{
  // pins not configured as INPUT are cleared to zeros
  portValue = portValue & portConfigInputs[portNumber];
  // only send if the value is different than previously sent
  if (forceSend || previousPINs[portNumber] != portValue) {
    Firmata.sendDigitalPort(portNumber, portValue);
    previousPINs[portNumber] = portValue;
  }
}

/* -----------------------------------------------------------------------------
   check all the active digital inputs for change of state, then add any events
   to the Serial output queue using Serial.print() */
void checkDigitalInputs(void)
{
  /* Using non-looping code allows constants to be given to readPort().
     The compiler will apply substantial optimizations if the inputs
     to readPort() are compile-time constants. */
  //Nacho Mas.
  //TODO: Cach deafult behaviour
  boolean send_always = false;
  if (TOTAL_PORTS > 0 && reportPINs[0]) outputPort(0, readPort(0, portConfigInputs[0]), send_always);
  if (TOTAL_PORTS > 1 && reportPINs[1]) outputPort(1, readPort(1, portConfigInputs[1]), send_always);
  if (TOTAL_PORTS > 2 && reportPINs[2]) outputPort(2, readPort(2, portConfigInputs[2]), send_always);
  if (TOTAL_PORTS > 3 && reportPINs[3]) outputPort(3, readPort(3, portConfigInputs[3]), send_always);
  if (TOTAL_PORTS > 4 && reportPINs[4]) outputPort(4, readPort(4, portConfigInputs[4]), send_always);
  if (TOTAL_PORTS > 5 && reportPINs[5]) outputPort(5, readPort(5, portConfigInputs[5]), send_always);
  if (TOTAL_PORTS > 6 && reportPINs[6]) outputPort(6, readPort(6, portConfigInputs[6]), send_always);
  if (TOTAL_PORTS > 7 && reportPINs[7]) outputPort(7, readPort(7, portConfigInputs[7]), send_always);
  if (TOTAL_PORTS > 8 && reportPINs[8]) outputPort(8, readPort(8, portConfigInputs[8]), send_always);
  if (TOTAL_PORTS > 9 && reportPINs[9]) outputPort(9, readPort(9, portConfigInputs[9]), send_always);
  if (TOTAL_PORTS > 10 && reportPINs[10]) outputPort(10, readPort(10, portConfigInputs[10]), send_always);
  if (TOTAL_PORTS > 11 && reportPINs[11]) outputPort(11, readPort(11, portConfigInputs[11]), send_always);
  if (TOTAL_PORTS > 12 && reportPINs[12]) outputPort(12, readPort(12, portConfigInputs[12]), send_always);
  if (TOTAL_PORTS > 13 && reportPINs[13]) outputPort(13, readPort(13, portConfigInputs[13]), send_always);
  if (TOTAL_PORTS > 14 && reportPINs[14]) outputPort(14, readPort(14, portConfigInputs[14]), send_always);
  if (TOTAL_PORTS > 15 && reportPINs[15]) outputPort(15, readPort(15, portConfigInputs[15]), send_always);
}

// -----------------------------------------------------------------------------
/* sets the pin mode to the correct state and sets the relevant bits in the
   two bit-arrays that track Digital I/O and PWM status
*/
void setPinModeCallback(byte pin, int mode)
{
  if (pinConfig[pin] == I2C && isI2CEnabled && mode != I2C) {
    // disable i2c so pins can be used for other functions
    // the following if statements should reconfigure the pins properly
    disableI2CPins();
  }
  if (IS_PIN_SERVO(pin) && mode != SERVO && servos[PIN_TO_SERVO(pin)].attached()) {
    servos[PIN_TO_SERVO(pin)].detach();
  }
  if (IS_PIN_ANALOG(pin)) {
    reportAnalogCallback(PIN_TO_ANALOG(pin), mode == ANALOG ? 1 : 0); // turn on/off reporting
  }
  if (IS_PIN_DIGITAL(pin)) {
    if (mode == INPUT) {
      portConfigInputs[pin / 8] |= (1 << (pin & 7));
    } else {
      portConfigInputs[pin / 8] &= ~(1 << (pin & 7));
    }
  }
  pinState[pin] = 0;
  switch (mode) {
    case ANALOG:
      if (IS_PIN_ANALOG(pin)) {
        if (IS_PIN_DIGITAL(pin)) {
          pinMode(PIN_TO_DIGITAL(pin), INPUT); // disable output driver
          digitalWrite(PIN_TO_DIGITAL(pin), LOW); // disable internal pull-ups
        }
        pinConfig[pin] = ANALOG;
      }
      break;
    case INPUT:
      if (IS_PIN_DIGITAL(pin)) {
        pinMode(PIN_TO_DIGITAL(pin), INPUT); // disable output driver
        digitalWrite(PIN_TO_DIGITAL(pin), LOW); // disable internal pull-ups
        pinConfig[pin] = INPUT;
      }
      break;
    case OUTPUT:
      if (IS_PIN_DIGITAL(pin)) {
        digitalWrite(PIN_TO_DIGITAL(pin), LOW); // disable PWM
        pinMode(PIN_TO_DIGITAL(pin), OUTPUT);
        pinConfig[pin] = OUTPUT;
      }
      break;
    case PWM:
      if (IS_PIN_PWM(pin)) {
        pinMode(PIN_TO_PWM(pin), OUTPUT);
        analogWrite(PIN_TO_PWM(pin), 0);
        pinConfig[pin] = PWM;
      }
      break;
    case SERVO:
      if (IS_PIN_SERVO(pin)) {
        pinConfig[pin] = SERVO;
        if (!servos[PIN_TO_SERVO(pin)].attached()) {
          servos[PIN_TO_SERVO(pin)].attach(PIN_TO_DIGITAL(pin));
        }
      }
      break;
    case I2C:
      if (IS_PIN_I2C(pin)) {
        // mark the pin as i2c
        // the user must call I2C_CONFIG to enable I2C for a device
        pinConfig[pin] = I2C;
      }
      break;
    default:
      Firmata.sendString("Unknown pin mode"); // TODO: put error msgs in EEPROM
  }
  // TODO: save status to EEPROM here, if changed
}

void analogWriteCallback(byte pin, int value)
{
  if (pin < TOTAL_PINS) {
    switch (pinConfig[pin]) {
      case SERVO:
        if (IS_PIN_SERVO(pin))
          servos[PIN_TO_SERVO(pin)].write(value);
        pinState[pin] = value;
        break;
      case PWM:
        if (IS_PIN_PWM(pin))
          //Nacho Mas. Write analog and do something before set PWM.
          mapAndWriteAnalog(pin, value);
        pinState[pin] = value;
        break;
    }
  }
}

void digitalWriteCallback(byte port, int value)
{
  byte pin, lastPin, mask = 1, pinWriteMask = 0;

  if (port < TOTAL_PORTS) {
    // create a mask of the pins on this port that are writable.
    lastPin = port * 8 + 8;
    if (lastPin > TOTAL_PINS) lastPin = TOTAL_PINS;
    for (pin = port * 8; pin < lastPin; pin++) {
      // do not disturb non-digital pins (eg, Rx & Tx)
      if (IS_PIN_DIGITAL(pin)) {
        // only write to OUTPUT and INPUT (enables pullup)
        // do not touch pins in PWM, ANALOG, SERVO or other modes
        if (pinConfig[pin] == OUTPUT || pinConfig[pin] == INPUT) {
          pinWriteMask |= mask;
          pinState[pin] = ((byte)value & mask) ? 1 : 0;
        }
      }
      mask = mask << 1;
    }
    //Nacho Mas. TODO: sustitute this call by
    //mapAndWriteDigital(port, (byte)value, pinWriteMask)
    writePort(port, (byte)value, pinWriteMask);
  }
}


// -----------------------------------------------------------------------------
/* sets bits in a bit array (int) to toggle the reporting of the analogIns
*/
//void FirmataClass::setAnalogPinReporting(byte pin, byte state) {
//}
void reportAnalogCallback(byte analogPin, int value)
{
  if (analogPin < TOTAL_ANALOG_PINS) {
    if (value == 0) {
      analogInputsToReport = analogInputsToReport & ~ (1 << analogPin);
    } else {
      analogInputsToReport = analogInputsToReport | (1 << analogPin);
    }
  }
  // TODO: save status to EEPROM here, if changed
}

void reportDigitalCallback(byte port, int value)
{
  if (port < TOTAL_PORTS) {
    reportPINs[port] = (byte)value;
  }
  // do not disable analog reporting on these 8 pins, to allow some
  // pins used for digital, others analog.  Instead, allow both types
  // of reporting to be enabled, but check if the pin is configured
  // as analog when sampling the analog inputs.  Likewise, while
  // scanning digital pins, portConfigInputs will mask off values from any
  // pins configured as analog
}

/*==============================================================================
   SYSEX-BASED commands
  ============================================================================*/

void sysexCallback(byte command, byte argc, byte *argv)
{
  byte mode;
  byte slaveAddress;
  byte slaveRegister;
  byte data;
  unsigned int delayTime;

  switch (command) {
    case I2C_REQUEST:
      mode = argv[1] & I2C_READ_WRITE_MODE_MASK;
      if (argv[1] & I2C_10BIT_ADDRESS_MODE_MASK) {
        Firmata.sendString("10-bit addressing mode is not yet supported");
        return;
      }
      else {
        slaveAddress = argv[0];
      }

      switch (mode) {
        case I2C_WRITE:
          Wire.beginTransmission(slaveAddress);
          for (byte i = 2; i < argc; i += 2) {
            data = argv + (argv[i + 1] << 7);
#if ARDUINO >= 100
            Wire.write(data);
#else
            Wire.send(data);
#endif
          }
          Wire.endTransmission();
          delayMicroseconds(70);
          break;
        case I2C_READ:
          if (argc == 6) {
            // a slave register is specified
            slaveRegister = argv[2] + (argv[3] << 7);
            data = argv[4] + (argv[5] << 7);  // bytes to read
            readAndReportData(slaveAddress, (int)slaveRegister, data);
          }
          else {
            // a slave register is NOT specified
            data = argv[2] + (argv[3] << 7);  // bytes to read
            readAndReportData(slaveAddress, (int)REGISTER_NOT_SPECIFIED, data);
          }
          break;
        case I2C_READ_CONTINUOUSLY:
          if ((queryIndex + 1) >= MAX_QUERIES) {
            // too many queries, just ignore
            Firmata.sendString("too many queries");
            break;
          }
          queryIndex++;
          query[queryIndex].addr = slaveAddress;
          query[queryIndex].reg = argv[2] + (argv[3] << 7);
          query[queryIndex].bytes = argv[4] + (argv[5] << 7);
          break;
        case I2C_STOP_READING:
          byte queryIndexToSkip;
          // if read continuous mode is enabled for only 1 i2c device, disable
          // read continuous reporting for that device
          if (queryIndex <= 0) {
            queryIndex = -1;
          } else {
            // if read continuous mode is enabled for multiple devices,
            // determine which device to stop reading and remove it's data from
            // the array, shifiting other array data to fill the space
            for (byte i = 0; i < queryIndex + 1; i++) {
              if (query.addr = slaveAddress) {
                queryIndexToSkip = i;
                break;
              }
            }

            for (byte i = queryIndexToSkip; i < queryIndex + 1; i++) {
              if (i < MAX_QUERIES) {
                query.addr = query[i + 1].addr;
                query.reg = query[i + 1].addr;
                query.bytes = query[i + 1].bytes;
              }
            }
            queryIndex--;
          }
          break;
        default:
          break;
      }
      break;
    case I2C_CONFIG:
      delayTime = (argv[0] + (argv[1] << 7));

      if (delayTime > 0) {
        i2cReadDelayTime = delayTime;
      }

      if (!isI2CEnabled) {
        enableI2CPins();
      }

      break;
    case SERVO_CONFIG:
      if (argc > 4) {
        // these vars are here for clarity, they'll optimized away by the compiler
        byte pin = argv[0];
        int minPulse = argv[1] + (argv[2] << 7);
        int maxPulse = argv[3] + (argv[4] << 7);

        if (IS_PIN_SERVO(pin)) {
          if (servos[PIN_TO_SERVO(pin)].attached())
            servos[PIN_TO_SERVO(pin)].detach();
          servos[PIN_TO_SERVO(pin)].attach(PIN_TO_DIGITAL(pin), minPulse, maxPulse);
          setPinModeCallback(pin, SERVO);
        }
      }
      break;
    case SAMPLING_INTERVAL:
      if (argc > 1) {
        samplingInterval = argv[0] + (argv[1] << 7);
        if (samplingInterval < MINIMUM_SAMPLING_INTERVAL) {
          samplingInterval = MINIMUM_SAMPLING_INTERVAL;
        }
      } else {
        //Firmata.sendString("Not enough data");
      }
      break;
    case EXTENDED_ANALOG:
      if (argc > 1) {
        int val = argv[1];
        if (argc > 2) val |= (argv[2] << 7);
        if (argc > 3) val |= (argv[3] << 14);
        analogWriteCallback(argv[0], val);
      }
      break;
    case CAPABILITY_QUERY:
      Serial.write(START_SYSEX);
      Serial.write(CAPABILITY_RESPONSE);
      for (byte pin = 0; pin < TOTAL_PINS; pin++) {
        if (IS_PIN_DIGITAL(pin)) {
          Serial.write((byte)INPUT);
          Serial.write(1);
          Serial.write((byte)OUTPUT);
          Serial.write(1);
        }
        if (IS_PIN_ANALOG(pin)) {
          Serial.write(ANALOG);
          Serial.write(10);
        }
        if (IS_PIN_PWM(pin)) {
          Serial.write(PWM);
          Serial.write(8);
        }
        if (IS_PIN_SERVO(pin)) {
          Serial.write(SERVO);
          Serial.write(14);
        }
        if (IS_PIN_I2C(pin)) {
          Serial.write(I2C);
          Serial.write(1);  // to do: determine appropriate value
        }
        Serial.write(127);
      }
      Serial.write(END_SYSEX);
      break;
    case PIN_STATE_QUERY:
      if (argc > 0) {
        byte pin = argv[0];
        Serial.write(START_SYSEX);
        Serial.write(PIN_STATE_RESPONSE);
        Serial.write(pin);
        if (pin < TOTAL_PINS) {
          Serial.write((byte)pinConfig[pin]);
          Serial.write((byte)pinState[pin] & 0x7F);
          if (pinState[pin] & 0xFF80) Serial.write((byte)(pinState[pin] >> 7) & 0x7F);
          if (pinState[pin] & 0xC000) Serial.write((byte)(pinState[pin] >> 14) & 0x7F);
        }
        Serial.write(END_SYSEX);
      }
      break;
    case ANALOG_MAPPING_QUERY:
      Serial.write(START_SYSEX);
      Serial.write(ANALOG_MAPPING_RESPONSE);
      for (byte pin = 0; pin < TOTAL_PINS; pin++) {
        Serial.write(IS_PIN_ANALOG(pin) ? PIN_TO_ANALOG(pin) : 127);
      }
      Serial.write(END_SYSEX);
      break;
  }
}

void enableI2CPins()
{
  byte i;
  // is there a faster way to do this? would probaby require importing
  // Arduino.h to get SCL and SDA pins
  for (i = 0; i < TOTAL_PINS; i++) {
    if (IS_PIN_I2C(i)) {
      // mark pins as i2c so they are ignore in non i2c data requests
      setPinModeCallback(i, I2C);
    }
  }

  isI2CEnabled = true;

  // is there enough time before the first I2C request to call this here?
  Wire.begin();
}

/* disable the i2c pins so they can be used for other functions */
void disableI2CPins() {
  isI2CEnabled = false;
  // disable read continuous mode for all devices
  queryIndex = -1;
  // uncomment the following if or when the end() method is added to Wire library
  // Wire.end();
}

/*==============================================================================
   SETUP()
  ============================================================================*/

void systemResetCallback()
{
  // initialize a defalt state
  // TODO: option to load config from EEPROM instead of default
  if (isI2CEnabled) {
    disableI2CPins();
  }
  for (byte i = 0; i < TOTAL_PORTS; i++) {
    reportPINs = false;      // by default, reporting off
    portConfigInputs = 0;    // until activated
    previousPINs = 0;
  }
  // pins with analog capability default to analog input
  // otherwise, pins default to digital output
  for (byte i = 0; i < TOTAL_PINS; i++) {
    if (IS_PIN_ANALOG(i)) {
      // turns off pullup, configures everything
      setPinModeCallback(i, ANALOG);
    } else {
      // sets the output to 0, configures portConfigInputs
      setPinModeCallback(i, OUTPUT);
    }
  }
  // by default, do not report any analog inputs
  analogInputsToReport = 0;

  /* send digital inputs to set the initial state on the host computer,
     since once in the loop(), this firmware will only send on change */
  /*
    TODO: this can never execute, since no pins default to digital input
        but it will be needed when/if we support EEPROM stored config
    for (byte i=0; i < TOTAL_PORTS; i++) {
    outputPort(i, readPort(i, portConfigInputs), true);
    }
  */
  setupMeteoStation();
}

void setup()
{
  Firmata.setFirmwareVersion(FIRMATA_MAJOR_VERSION, FIRMATA_MINOR_VERSION);

  Firmata.attach(ANALOG_MESSAGE, analogWriteCallback);
  Firmata.attach(DIGITAL_MESSAGE, digitalWriteCallback);
  Firmata.attach(REPORT_ANALOG, reportAnalogCallback);
  Firmata.attach(REPORT_DIGITAL, reportDigitalCallback);
  Firmata.attach(SET_PIN_MODE, setPinModeCallback);
  Firmata.attach(START_SYSEX, sysexCallback);
  Firmata.attach(SYSTEM_RESET, systemResetCallback);

  Firmata.begin(57600);
  systemResetCallback();  // reset to default config
}

/*==============================================================================
   LOOP()
  ============================================================================*/
void loop()
{
  byte pin, analogPin;

  /* DIGITALREAD - as fast as possible, check for changes and output them to the
     FTDI buffer using Serial.print()  */
  //Nacho Mas. TODO: sustitute this call by
  //mapAndSendDigital()
  //checkDigitalInputs();

  /* SERIALREAD - processing incoming messagse as soon as possible, while still
     checking digital inputs.  */
  while (Firmata.available())
    Firmata.processInput();

  /* SEND FTDI WRITE BUFFER - make sure that the FTDI buffer doesn't go over
     60 bytes. use a timer to sending an event character every 4 ms to
     trigger the buffer to dump. */

  currentMillis = millis();
  if (currentMillis - previousMillis > samplingInterval) {
    previousMillis += samplingInterval;
    checkMeteo();
    runMeteoStation();
    checkDigitalInputs();
    /* ANALOGREAD - do all analogReads() at the configured sampling interval */
    for (pin = 0; pin < TOTAL_PINS; pin++) {
      if (IS_PIN_ANALOG(pin) && pinConfig[pin] == ANALOG) {
        analogPin = PIN_TO_ANALOG(pin);
        if (analogInputsToReport & (1 << analogPin)) {
          //Nacho Mas. Read analog and do something before send. Then send it
          mapAndSendAnalog(analogPin);
        }
      }
    }
    // report i2c data for all device with read continuous mode enabled
    if (queryIndex > -1) {
      for (byte i = 0; i < queryIndex + 1; i++) {
        readAndReportData(query.addr, query.reg, query.bytes);
      }
    }
  }
}

 

METEOtest.rar

Posté

@ch_porchet

salut,

 

J'ai pu tout connecter.

En fait dans le code de l'arduino final il y' avait une erreur au niveau du MLX, les valeurs étaient divisées par 100, j'ai donc retrouvé mes 20° de la maison.

Pour que tout fonctionne j'ai du faire ceci:

 

- réinstaller le driver indiduino meteostation sur ma tinkerboard avec la console.

Comme la 3rdparty de indi est installé sur ma TB tu vas dans le dossier: /home/"ton nom"/Projects/indi-3rdparty/indi-duino

 

tu ouvres tu consoles puis tu tapes:

- cmake ../../indi-3rdparty/indi-duino

- make

- sudo make install

 

et là il t'a recompilé le driver.

 

tu lances kstars et ekos, tu mets "Arduino Meteostation" dans la liste des choix météo.

 

tu sélectionnes le bon port dans l'onglet connexion et c'est tout bon!

 

Bon après je suis arrêté à ce stade.

 

Je ne comprends rien à la suite pour l'interface web... dommage.

 

j'espère t'avoir aidé.

 

Olivier

Posté

Hello

Alors j'ai pas eu trop de temps pour regarder ça se week-end. 

Je vais voir ce soir, mais faut que je commande des files pour connecter ma mini uno au différent capteurs. 

Et je te redis. 

 

Merci pour la marche a suivre 

 

Posté
il y a 12 minutes, ch_porchet a dit :

j'ai essayé cette méthode de nombreuses fois!! mais je bute toujours sur l'interface web... rien à faire, je comprends pas comment l'afficher depuis mon navigateur.

A chaque fois je tombe sur la page initiale de ma tinker... grrr

Posté

Est-ce que tu kstars sur ta tinker ? 

Car, il me semble qu'il dédie une RPi que pour la météo, c'est peut être ça la solution. 

 

Bon j'avoue que ses temps j'ai pas eu trop le temps de regarder , et j'attends en plus mes câble,mais  j'espère demain....... 

Et dès que c'est bon j'attaque 😉

 

Posté

Oui kstars tourne sur la tinkerboard.

il s’agit d’un ubuntu, j’ai donc acces a bcp de source.

pour dire vrai c’est grâce au projet NAFABOX. 

C’est peut etre lié a cela. Je ne sais pas!

wait & see comme on dit!

  • En ligne récemment   0 membre est en ligne

    • Aucun utilisateur enregistré regarde cette page.
×
×
  • Créer...

Information importante

Nous avons placé des cookies sur votre appareil pour aider à améliorer ce site. Vous pouvez choisir d’ajuster vos paramètres de cookie, sinon nous supposerons que vous êtes d’accord pour continuer.