une 30aine passés sans pb entre les trames

Dependencies:   ADS1015 ARNSRS_SENSORS DmTftLibrary MS5803_14BA SDFileSystem mbed

Fork of ARNSRS_SERVOS_USB_TFT by POTLESS

main.cpp

Committer:
potless
Date:
2017-05-22
Revision:
23:40a6039cb140
Parent:
22:8e4ace42e4f5

File content as of revision 23:40a6039cb140:

/*
Stm32L476RG

2 servos
BLE => Android

*/

#include "mbed.h"
#include "SDFileSystem.h"
#include "ARNSRS_SENSORS.h"

#include <string>

#include "DmTftHX8353C.h"
#include "DmTftS6D0164.h"
#include "DmTftIli9325.h"
#include "DmTftIli9341.h"
#include "DmTftSsd2119.h"
#include "DmTftRa8875.h"

//Ecrit dans le moniteur série de la tablette à 9600 bds si sur 1, penser à mettre NEED_CONSOLE_OUTPUT à 0
#define NEED_ANDROID_OUTPUT 0
//Ecrit dans le moniteur série de l'ordi à 9600 bds si sur 1
#define NEED_CONSOLE_OUTPUT 1
//Pour utiliser le traceur du moniteur Arduino. Mettre NEED_CONSOLE_OUTPUT 0 si utilisé.
//En premier ouvrir le moniteur série pour régler la RTC, puis fermer et ouvrir le traceur série
#define NEED_GRAPH_OUTPUT 0
//Datalog carte SD si sur 1
#define NEED_SD_DATA_LOG 0

#if NEED_ANDROID_OUTPUT
#define ANDROID(...) { serialMonit.printf(__VA_ARGS__); }
#else
#define ANDROID(...)
#endif

#if NEED_CONSOLE_OUTPUT
#define DEBUG(...) { serialMonit.printf(__VA_ARGS__); } //tft.drawString(0,0,__VA_ARGS__);
#else
#define DEBUG(...)
#endif

#if NEED_GRAPH_OUTPUT
#define TRACE(...) { serialMonit.printf(__VA_ARGS__); }
#else
#define TRACE(...)
#endif


////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

//TFT
DmTftHX8353C tft(D2, D3, D4, D5, D6);  /* DmTftHX8353C(PinName mosi, PinName clk, PinName cs, PinName dc, PinName rst) DM_TFT18_101 */

//Bool des pages
bool FLAG_PAGE_1 = true;
bool FLAG_PAGE_2 = false;

//Changement de pages
InterruptIn mybutton(USER_BUTTON);

//Dessin du logo en t^te de page
int bmpWidth, bmpHeight;
uint8_t bmpImageoffset;
extern uint8_t dmlogo[];

// LITTLE ENDIAN!
uint16_t read16(uint8_t *src)
{
  uint16_t d;
  uint8_t b;
  b = *src;
  d = *(src+1);
  d <<= 8;
  d |= b;
  return d;
}

// LITTLE ENDIAN!
uint32_t read32(uint8_t *src)
{
  uint32_t d;
  uint16_t b;

  b = read16(src);
  d = read16(src+2);
  d <<= 16;
  d |= b;
  return d;
}

void drawBmpFromFlash(int x, int y)
{
  uint16_t pos = bmpImageoffset;

  uint16_t p;  // pixel
  uint8_t g, b;
  int i, j; // line, column

  for(i=bmpHeight; i>0; i--) {
    for(j=0; j<bmpWidth; j++) {
      b = *(dmlogo+pos++);
      g = *(dmlogo+pos++);
      p = *(dmlogo+pos++);

      p >>= 3;
      p <<= 6;

      g >>= 2;
      p |= g;
      p <<= 5;

      b >>= 3;
      p |= b;

      // write out the 16 bits of color
      tft.setPixel(j+x, i+y, p);
    }
  }
}


int bmpReadHeader() {
  uint32_t fileSize;
  uint32_t headerSize;
  uint16_t bmpDepth;
  uint16_t pos = 0;
 
  if (read16(dmlogo) !=0x4D42){ // read magic byte
    return false;
  }
  pos += 2;

  // read file size
  fileSize = read32(dmlogo+pos);
  pos += 4;

  pos += 4; // Skip creator bytes

  bmpImageoffset = read32(dmlogo+pos);
  pos += 4;

  // read DIB header
  headerSize = read32(dmlogo+pos);
  pos +=4;
  bmpWidth = read32(dmlogo+pos);
  pos += 4;
  bmpHeight = read32(dmlogo+pos);
  pos += 4;

  if (read16(dmlogo+pos) != 1){
    // number of color planes must be 1
    return false;
  }
  pos += 2;

  bmpDepth = read16(dmlogo+pos);
  pos +=2;

  if (read16(dmlogo+pos) != 0) {
    // compression not supported!
    return false;
  }
  pos += 2; // Should really be 2??

  return true;
}

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////




//Contrôle des servos
PwmOut servo1(PB_15);
AnalogIn FeedBack1(PC_2);
float Servo1_POS;
float Limit_min_S1, Limit_max_S1;
float Delta_FB_1;

PwmOut servo2(PB_1);
AnalogIn FeedBack2(PC_3);
float Servo2_POS;
float Limit_min_S2, Limit_max_S2;
float Delta_FB_2;

//Buffer pour Commandes servo
char commande_servo[20];
int indexCommande;

//Init de la lib ARNSRS;
ARNSRS arnsrs;

//COM Série vers l'ordi, Serial 2 par défaut
Serial serialMonit (USBTX,USBRX);

//Variable des capteurs
int co2 = 0;
int ppO2 = 0;
float pression = 0;
float Temp1 = 0;
float Temp2 = 0;
float Humi = 0;

//RTC
//Pour stocker le format date / heure
string DateHeure;
time_t seconds;

//SD card
SDFileSystem sd(D11, D12, D13, D10, "sd"); // MOSI, MISO, SCK, CS
DigitalInOut csSDCard(D10, PIN_OUTPUT, PullUp, 1);
FILE *fp;
char fileName[32];
int points = 1;

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////



////////////////////////////////////////////////////////////////////////////////
/////                       Remap d'une valeur                             /////
////////////////////////////////////////////////////////////////////////////////

float remap(float x, float in_min, float in_max, float out_min, float out_max)
{
    return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

////////////////////////////////////////////////////////////////////////////////
////        Fonction pour créer et envoyer la chaine d'infos en BLE         ////
////////////////////////////////////////////////////////////////////////////////

//On balance deux float
void build_send_Message_float(string com, float A, float B)
{
    char buf[50];
    sprintf(buf,"%s%.1f:%.1f\r\n", com.c_str(), A, B);
    ANDROID(buf);
    wait_ms(100);
}

//On balance deux int
void build_send_Message_int(string com, int A, int B)
{
    char buf[50];
    sprintf(buf,"%s%d:%d\r\n", com.c_str(), A, B);
    ANDROID(buf);
    wait_ms(100);
}


////////////////////////////////////////////////////////////////////////////////
////                  Fonction commande servos par port série                      ////
////////////////////////////////////////////////////////////////////////////////


void Servo_USB()
{

    //Variables pour décomposition du message
    char *commande="      ";
    char *valeur="      ";

    //La commande
    // un message valide est du type [Sx];yyy  avec x numero du servo et yyy compris entre 000 et 100
    DEBUG("index = %d commande_servo = %s \n", indexCommande, commande_servo);
    commande = strtok(commande_servo, ",;");
    DEBUG("Commande = %s\n", commande);

    //La valeur associée
    valeur = strtok(NULL, ",;");
    DEBUG("Valeur   = %s\n", valeur);

    //On compare la commande pour faire les actions

    //Commande servo1
    if(strcmp(commande, "[S1]") == 0) {
        servo1= atoi(valeur) / 100.f;
        DEBUG("  Servo 1    = %s\n", valeur);
        //indexCommande = 0;
    }

    //Commande servo2
    if(strcmp(commande, "[S2]") == 0) {
        servo2 =atoi(valeur) / 100.f;
        DEBUG("Servo 2    =  %f\r\n", valeur);
        //indexCommande = 0;
    }
    
    indexCommande = 0;
}

void callbackServo()
{  
   
    while(serialMonit.readable()) 
    commande_servo [indexCommande++] = serialMonit.getc();   
          
}

////////////////////////////////////////////////////////////////////////////////
////         Fonction qui change le nom du fichier ouvert pour le LOG       ////
////////////////////////////////////////////////////////////////////////////////

FILE *nextLogFile(void)
{
    static unsigned int fileNumber = 0;
    FILE *filePtr = NULL;
    do {
        if (filePtr != NULL)
            fclose(filePtr);
        sprintf(fileName,"/sd/LOG_Capteurs_%04u.txt",fileNumber++);
        filePtr = fopen(fileName,"r");
    } while (filePtr != NULL);
    return fopen( fileName,"w");
}

////////////////////////////////////////////////////////////////////////////////
////                 Réglage de l'heure par le moniteur série               ////
////////////////////////////////////////////////////////////////////////////////

void SetTime()
{
    //Reglage date / heure depuis le terminal
    struct tm t;
    serialMonit.printf("Entrer la date et l'heure :\n");
    serialMonit.printf("YYYY MM DD HH MM SS [enter]\n");
    serialMonit.scanf("%d %d %d %d %d %d", &t.tm_year, &t.tm_mon, &t.tm_mday
                      , &t.tm_hour, &t.tm_min, &t.tm_sec);
    t.tm_year = t.tm_year - 1900;
    t.tm_mon = t.tm_mon - 1;

    // set the time
    set_time(mktime(&t));

    if(NEED_CONSOLE_OUTPUT == 0) serialMonit.printf("OK. Vous pouvez fermer le moniteur serie");
}

////////////////////////////////////////////////////////////////////////////////
////                         Initialisation DATA LOG                        ////
////////////////////////////////////////////////////////////////////////////////

void init_DATALOG()
{
    DEBUG("Initialisation SD card\r\n");
    DEBUG("\r\n", "");
    fp = nextLogFile();

    if (!fp) {
        DEBUG("Probleme SD card...Fin du programme...\r\n");
        //exit(0);
    } else {
        DEBUG("Nouveau fichier LOG cree  =  %s\r\n", fileName);
        DEBUG("\r\n", "");
    }
}

////////////////////////////////////////////////////////////////////////////////
////           Fonction d'enregistrement des données sur carte SD           ////
////////////////////////////////////////////////////////////////////////////////

void DATA_LOG()
{
    seconds = time(NULL);

    if (fp) {
        fprintf(fp, "%s,%d,%d,%f,%f,%f,%f\r\n", ctime(&seconds), co2 , ppO2, pression, Temp1, Temp2, Humi);
        DEBUG("  Enregistrement d'un point sur la carte SD\r\n");
        DEBUG("  Nombre de points                      = %d\r\n", points);
        DEBUG("\r\n", "");
        points++;
    } else {
        DEBUG("  Probleme carte SD\r\n");
    }
}

////////////////////////////////////////////////////////////////////////////////
////              Calibration des limites de feedback des servos            ////
////////////////////////////////////////////////////////////////////////////////

void Calibration_servo()
{
    //Servos, calibration du feedback
    DEBUG("  Check Servos :\r\n");
    DEBUG("\r\n");
    servo1.period(0.001); // à mettre dans le setup si cette calib n'est pas appelée (je l ai trouvée commentée)
    servo2.period(0.001);
    //Rentrer les servos à fond
    servo1 = 0;
    servo2 = 0;
    wait(4);
    Limit_min_S1 = 1-FeedBack1.read();

    wait_ms(100);
    Limit_min_S2 = 1-FeedBack2.read();

    DEBUG("  FeedBack 1  min = %f\n", Limit_min_S1);
    DEBUG("  FeedBack 2  min = %f\n", Limit_min_S2);
    DEBUG("\r\n");

    //Sortir les servos à fond
    servo1 = 1;
    servo2 = 1;
    wait(4);
    Limit_max_S1 = 1-FeedBack1.read();
    wait_ms(100);
    Limit_max_S2 = 1-FeedBack2.read();

    DEBUG("  FeedBack 1  Max = %f\n", Limit_max_S1);
    DEBUG("  FeedBack 2  Max = %f\n", Limit_max_S2);
    DEBUG("\r\n");

    //Position milieu
    servo1 = (Limit_min_S1+Limit_max_S1)*0.5;
    servo2 = (Limit_min_S2+Limit_max_S2)*0.5;
    wait(4);

    //Mesure du delta consigne / feedback
    Delta_FB_1 = abs(remap(FeedBack1, Limit_min_S1, Limit_max_S1, 0, 100)-50);
    Delta_FB_2 = abs(remap(FeedBack2, Limit_max_S2, Limit_min_S2, 0, 100) - 50);

    DEBUG("  Delta Servo 1 = %f\n", Delta_FB_1);
    DEBUG("  Delta Servo 2 = %f\n", Delta_FB_2);

    if(Delta_FB_1 > 10 || Delta_FB_2 > 10)  DEBUG("  Delta Servos non satisfaisant...");
}

////////////////////////////////////////////////////////////////////////////////
////    Fonction d'affichage de tout dans le moniteur série ou le traceur   ////
////////////////////////////////////////////////////////////////////////////////

void Debug_Complet()
{
    //RTC
    seconds = time(NULL);

    DEBUG("  Date / Heure = %s\r\n", ctime(&seconds));

    //Retour capteurs
    DEBUG("  CO2           = %d\r\n"  , co2);
    DEBUG("  Humidite      = %f\r\n"  , Humi);
    DEBUG("  Temperature   = %f\r\n"  ,Temp1);
    //P / T sur MS5803
    DEBUG("  Pression      = %f\r\n", pression);
    DEBUG("  Temperature   = %f\r\n", Temp2);
    //PPO2 sur ADS1015
    DEBUG("  PPO2          = %d\r\n", ppO2);
    DEBUG("\r\n", "");

    //Retour position des servos
    DEBUG("  FeedBack 1   = %3.2f%%\n", Servo1_POS);
    DEBUG("  FeedBack 2   = %3.2f%%\n", Servo2_POS);
    DEBUG("\r\n", "");

    //Traceur
    TRACE("%d"  , co2);
    TRACE(", ");
    TRACE("%d"  , ppO2);
    TRACE(", ");
    TRACE("%f"  , Humi);
    TRACE(", ");
    TRACE("%f"  , Temp1);
    TRACE(", ");
    TRACE("%f"  , Temp2);
    TRACE(", ");
    TRACE("%f"  , pression);
    TRACE("\r\n");
}

////////////////////////////////////////////////////////////////////////////////
///                          PAGE tft 1                        //
////////////////////////////////////////////////////////////////////////////////

void tft_page_1()
{
        FLAG_PAGE_2 = false;
        FLAG_PAGE_1 = true;
        
        //tft.clearScreen(BLACK);
        
        if (!bmpReadHeader()) {   
        return;
        }
  
        drawBmpFromFlash(30, 2);
    
        tft.drawString(5,35, "CO2  ");
        tft.drawString(90,35, " ppm");
        
        tft.drawString(5,55, "ppO2 ");
        tft.drawString(90,55, " mb");
        
        tft.drawString(5,75, "T_1  ");
        tft.drawString(90,75, " C");
        
        tft.drawString(5,95, "T_2  ");
        tft.drawString(90,95, " C");
        
        tft.drawString(5,115, "Hum  ");
        tft.drawString(90,115, " %");
        
        tft.drawString(5,135, "P    ");
        tft.drawString(90,135, " m");
        
        tft.drawRectangle(0,0,126,32, WHITE);
        tft.drawRectangle(0,32,126,52, WHITE);
        tft.drawRectangle(0,52,126,72, WHITE);
        tft.drawRectangle(0,72,126,92, WHITE);
        tft.drawRectangle(0,92,126,112, WHITE);
        tft.drawRectangle(0,112,126,132, WHITE);
        tft.drawRectangle(0,132,126,152, WHITE);
        
 
 } 
 
 ////////////////////////////////////////////////////////////////////////////////
///                          PAGE tft 2                        //
////////////////////////////////////////////////////////////////////////////////

void tft_page_2()
{
        FLAG_PAGE_1 = false;
        FLAG_PAGE_2 = true;
        
        //tft.clearScreen(BLACK);
        
        if (!bmpReadHeader()) {   
        return;
        }
  
        drawBmpFromFlash(30, 2);
    
        tft.drawString(5,35, "CO2  ");
        tft.drawString(90,35, " ppm");
        
        tft.drawRectangle(0,0,126,32, WHITE);
        tft.drawRectangle(0,32,126,52, WHITE);
 } 

void pressed()
{
     tft.clearScreen(BLACK);
     
     if (FLAG_PAGE_1){
        tft_page_2();
     }
      
     if (FLAG_PAGE_2){      
        tft_page_1();
     }   
} 
       
////////////////////////////////////////////////////////////////////////////////
///                          fonction initialisation                          //
////////////////////////////////////////////////////////////////////////////////

void setup()
{
    wait(2);
    
    //Réglage de l'heure
    //SetTime();

    //Calibration des limites des servos pour remapper les feedback
    Calibration_servo();
    //servo1.period(0.001); // a mettre si pas de calib
    //servo2.period(0.001); // a mettre si pas de calib

    //Démarrage de l'écran
    DEBUG("Initialisation TFT\r\n");
    tft.init();
    tft_page_1();
    
    //Initialisation du Data log
    if (NEED_SD_DATA_LOG == 1) init_DATALOG();

    //Initialisation capteurs
    arnsrs.Sensors_INIT(false, 5, SPOOLING, DIGI_FILTER32, CALIB_AIR);
}

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
///                           procédure principale                           ///
////////////////////////////////////////////////////////////////////////////////

int main()
{
    setup();

    //interruption sur le boutton user pour changer de page
    mybutton.fall(&pressed);
    
    //Commande éventuelle pour les servos
    serialMonit.attach(&callbackServo, Serial::RxIrq);
        
    while (1) {

        //CO2 / H / T sur Cozir
        co2 = arnsrs.requestCO2();
        Humi = arnsrs.requestHUMI();
        Temp1 = arnsrs.requestTEMP();

        //P / T sur MS5803_14BA
        pression = arnsrs.requestPress();
        Temp2 =  arnsrs.requestTemp();

        //PPO2 sur ADS1015
        ppO2 = arnsrs.requestPpO2(false);

        //Retour position des servos
        Servo1_POS = 1-FeedBack1;//remap(FeedBack1, Limit_max_S1, Limit_min_S1, 0, 100);
        //Servo2_POS = remap(FeedBack2, Limit_max_S2, Limit_min_S2, 0, 100);

        //Debug
        Debug_Complet();

        //Data LOG
        if (NEED_SD_DATA_LOG == 1) DATA_LOG();

        //En accord avec app Android
        build_send_Message_int("t", co2, ppO2);
        build_send_Message_float("u", Temp1, Temp2);
        build_send_Message_float("v", Humi, pression);
        build_send_Message_float("f", Servo1_POS, Servo2_POS);
          
        if (indexCommande>0){
             Servo_USB();
             strcpy(commande_servo," ");
             }
        
        
        if(FLAG_PAGE_1) {
        tft.drawNumber(65,35,co2 ,3, false);
        tft.drawNumber(65,55,ppO2 ,3, false);      
        tft.drawNumber(65,75,Temp1 ,3, false);      
        tft.drawNumber(65,95,Temp2 ,3, false);    
        tft.drawNumber(65,115,Humi ,3, false);
        tft.drawNumber(65,135,pression ,3, false);
        }
        
        if(FLAG_PAGE_2) {   
        tft.drawNumber(65,35,co2 ,3, false);
        }
    }
}

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////