Pages: [1]   Go Down
Author Topic: Ecriture sur carte SD  (Read 1247 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Full Member
***
Karma: 0
Posts: 127
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Bonjour à tous,

je me bats depuis plusieurs semaines sur ce code qui me permet de relever les impulsions sur une entrée puis de réaliser l'envoie du nombre d'impulsion et quelques autres infos sur une BDD Sql ou Cosm ou si je n'ai pas de connexion au web d'ecrire sur la carte SD.

Je n'ai pas de probleme pour ecrire dans la BDD ni sur COSM par conte l'ecriture sur la carte SD se fait mais de facon aléatoire ...... et en ce moment cela bloque à "Initialisation de la SD card...
Echec Ethernet DHCP"

Pour "Echec Ethernet DHCP" normal j'ai retiré le cable reseau pour simuler justement une panne reseau et forcer l'ecriture sur la carte SD.
Par contre je ne sais pas pourquoi rien ne s'ecrit sur ma carte .... pourtant ca eu marché comme on dit ...

Auriez vous une idée du problème ?


Code:
#include <SD.h>
#include <SPI.h>        
#include <Ethernet.h>
#include <EthernetUdp.h>
#include <Time.h>
#include <avr/pgmspace.h>
// --- Déclaration des constantes utiles ---
// Enter a MAC address for your controller below.
// Newer Ethernet shields have a MAC address printed on a sticker on the shield

// cosm
#define APIKEY         "oQ9B9mJPRT0g" // replace your Cosm api key here
#define FEEDID         569 // replace your feed ID
#define USERAGENT      "Vea" // user agent is the project name
//
// variables globales :
#define PERIOD_WRITE_DATA    120000
unsigned long last_write_data;

byte mac[] = {  
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xEF };

unsigned int localPort = 8888;      // local port to listen for UDP packets

IPAddress ip(192, 168, 0, 35);

IPAddress timeServer(192, 43, 244, 18); // time.nist.gov NTP server

IPAddress timeServer2(129, 6, 15, 28); //  time-a.nist.gov NTP server

IPAddress srvphp(192, 168, 0, 135); // Adresse IP serveur perso PHP


const int NTP_PACKET_SIZE= 48; // NTP time stamp is in the first 48 bytes of the message

byte packetBuffer[ NTP_PACKET_SIZE]; //buffer to hold incoming and outgoing packets

int Jour = day();  // variable d'initialisation pour la mise à zero de la production à minuit
volatile long comptageImpulsion=0; // variable accessible dans la routine interruption externe 0
int test; // Variable utilisée pour tester valeur renvoyée par fonctions SD Card

// A UDP instance to let us send and receive packets over UDP
EthernetUDP Udp;

// cosm
// initialize the library instance:
EthernetClient client;
char server[] = "api.cosm.com";   // name address for cosm API

unsigned long lastConnectionTime = 0;          // last time you connected to the server, in milliseconds
boolean lastConnected = false;                 // state of the connection last time through the main loop
// const unsigned long postingInterval = 10*1000; //delay between updates to cosm.com
//

time_t prevDisplay = 0; // when the digital clock was displayed
const  int timeZoneOffset = +1; // GMT zone;
// --- Déclaration des constantes des broches E/S numériques ---

const int brocheSDCardSelect=4;

// --- Déclaration des constantes des broches analogiques ---


// --- Déclaration des objets utiles pour les fonctionnalités utilisées ---
File file; // objet file
File root; // objet root pour le répertoire racine


void setup()   { // debut de la fonction setup()

  
  last_write_data = millis() - PERIOD_WRITE_DATA;
  comptageImpulsion = 0;


  Serial.begin(115200); // initialise connexion série à 115200 bauds
  // IMPORTANT : régler le terminal côté PC avec la même valeur de transmission

  
 // digitalWrite(10, HIGH); // mais désactive le  circuit intégré W5100 du module ethernet!

 

  attachInterrupt(0, gestionINT0, RISING); // attache l'interruption externe n°0 à la fonction gestionINT0()
  // mode déclenchement possibles = LOW, CHANGE, RISING, FALLING


    // start Ethernet and UDP
  if (Ethernet.begin(mac) == 0) {
    Serial.println( (__FlashStringHelper *)PSTR("Echec Ethernet DHCP"));
    Ethernet.begin(mac, ip);
    // no point in carrying on, so do nothing forevermore:
    //  for(;;)
    //    ;
  }

  Udp.begin(localPort);
  setSyncProvider(getNtpTime);
  while(timeStatus()== timeNotSet); // wait until the time is set by the sync provider
  
   //---- initialise l'utilisation de la carte mémoire SD en mode SPI  
  pinMode(10, OUTPUT); // met la broche 10 (SS) en sortie (nécessaire avec module ethernet)
  
} // fin de la fonction setup()


void loop(){ // debut de la fonction loop()

  // On purge l'arrivée de caractères, retour de COSM (pour debug)
// if (client.available()) {
//   while( client.available() )
 //    Serial.print(client.read() );
 // }

  // Si la communication a été coupée, on ferme le client et on indique lastConnected = false;
//  if (!client.connected() && lastConnected) {
 //   Serial.println();
 //   Serial.println( (__FlashStringHelper *)PSTR("disconnecting."));
  //  client.stop();
//    lastConnected = false;
 // }
  // Initialisation du compteur au changement de jour

  if (Jour != day()) {
    comptageImpulsion = 0;
    Jour = day();
    Serial.println( (__FlashStringHelper *)PSTR("Init compteur changement de jour"));
    file.println( (__FlashStringHelper *)PSTR("Init compteur changement de jour") );
  }

  // Si et seulement si PERIOD_WRITE_DATA s'est écoulé depuis la dernière fois, on exécute la fonction d'écriture SD et l'envoi sur COSM

  // Sinon, on recommence loop
  if ( (millis()-last_write_data) > PERIOD_WRITE_DATA )
  {
    // Initialisation de la variale permettant la réinitialisation du compteur au changement de jour
    Jour = day(); // Gestion de l'initialisation du compreur de changement de jour

    last_write_data = millis(); // variable de gestion de la boucle if

    // cosm
    // read the analog sensor:
    long sensorReading = comptageImpulsion ;  

    // A chaque fois qu'on écrit dans le fichier, on envoi aussi sur COSM.
    // La gestion du délai est déjà fait plus haut
    sendData(sensorReading);
    // store the state of the connection for next time through
    // the loop:
  //  lastConnected = client.connected();
  } // fin else
}

// fin de la fonction loop() - le programme recommence au début de la fonction loop sans fin
// ********************************************************************************







« Last Edit: December 22, 2012, 11:51:59 am by PITP2 » Logged

Offline Offline
Full Member
***
Karma: 0
Posts: 127
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
void sendData(int thisData) {
  // if there's a successful connection:
  if (client.connect(srvphp, 80)) {
    char reqhttp[100];
    int annee = year();
    int sec = second();
    int jour=day();
    int mois = month();
    int heure= hour();
    int minut= minute();
    
    Serial.println("connected srvphp");
    // Make a HTTP request:
    sprintf( reqhttp, "GET /solaire/txp2.php?nom_inst=Dupont&date_prod=%04d%02d%02d%02d%02d%02d&prod=%05d&commentaires=arduino HTTP/1.0",annee,mois,jour,heure,minut,sec,comptageImpulsion);
    client.println(reqhttp);
    client.println();
    Serial.println(F("Fin envoie srvphp"));
    client.stop();
    }
  else {
    if (client.connect(server, 80)) {
    Serial.println( (__FlashStringHelper *)PSTR("connecting COSM..."));
    // send the HTTP PUT request:
    client.print("PUT /v2/feeds/");
    client.print(FEEDID);
    client.println(".csv HTTP/1.1");
    client.println("Host: api.cosm.com");
    client.print("X-ApiKey: ");
    client.println(APIKEY);
    client.print("User-Agent: ");
    client.println(USERAGENT);
    client.print("Content-Length: ");

    // calculate the length of the sensor reading in bytes:
    // 8 bytes for "sensor1," + number of digits of the data:
    int thisLength = 8 + getLength(thisData);
    client.println(thisLength);

    // last pieces of the HTTP PUT request:
    client.println("Content-Type: text/csv");
    client.println("Connection: close");
    client.println();

    // here's the actual content of the PUT request:
    client.print("sensor2,");
    client.println(thisData);
    Serial.println(F("Fin envoie COSM"));
    client.stop();
  }
   else {
    char datafile[13] = {'\0'};
    int jour=day();
    int mois = month();
    int heure= hour();
    int minut= minute();

    sprintf(datafile,"%02d%02d%02d%02d.txt",mois,jour,heure,minut);  //  %d pour un int

      //----- initialisation de la carte SD -----
    Serial.println( (__FlashStringHelper *)PSTR("Initialisation de la SD card..."));


    SD.begin(brocheSDCardSelect); // initialisation de la carte SD avec broche 4 en tant que CS - renvoie true/false
  

    root = SD.open("/"); // ouvre la SD Card à la racine

    Serial.println( (__FlashStringHelper *)PSTR("Rep racine ouvert"));

    Serial.println(datafile);
    //---- crée fichier en écriture ---
    file = SD.open(datafile, FILE_WRITE); // ouvre le fichier en écriture
    // NB : le fichier est créé si il n'existe pas !

    //---- test si fichier dispo en écriture
    if (!file) { // si fichier pas dispo
      Serial.println( (__FlashStringHelper *)PSTR("Erreur ouverture fichier"));
    } // fin if
    else { // si le fichier existe et est ouvert
      Serial.println( (__FlashStringHelper *)PSTR("Fichier pret pour ecriture"));
      //----- Ecriture dans le fichier au format CSV -----
      Serial.println( (__FlashStringHelper *)PSTR("Enregistrement en cours"));
      

      // valeur deuxieme champ
      file.print(comptageImpulsion);
      file.print(';');
      // valeur quatrieme champ
      file.print(millis()), file.print(';');
      // le dernier champ doit se terminer par un saut de ligne +++
      if( now() != prevDisplay) //update the display only if the time has changed
      {
        prevDisplay = now();
        digitalClockDisplay();
      }  
      Serial.println( (__FlashStringHelper *)PSTR("connection failed"));
      Serial.println();
      Serial.println( (__FlashStringHelper *)PSTR("disconnecting"));

      file.close(); // ferme le fichier
      Serial.println( (__FlashStringHelper *)PSTR("Fin enregistrement"));  
      Serial.println( (__FlashStringHelper *)PSTR("Fermeture fichier"));
  }
    


  
  
    // note the time that the connection was made or attempted:
   // lastConnectionTime = millis();
    }
}
// This method calculates the number of digits in the
// sensor reading.  Since each digit of the ASCII decimal
// representation is a byte, the number of digits equals
// the number of bytes:
}
int getLength(int someValue) {
  // there's at least one byte:
  int digits = 1;
  // continually divide the value by ten,
  // adding one to the digit count for each
  // time you divide, until you're at 0:
  int dividend = someValue /10;
  while (dividend > 0) {
    dividend = dividend /10;
    digits++;
  }
  // return the number of digits:
  return digits;
}

// ------------------- fonction de gestion l'interruption externe n°0 (broche 2) ----------------
// cette fonction est appelée à chaque fois que l'interruption a lieu selon le mode configuré (LOW, CHANGE, RISING, FALLING)
void gestionINT0() {// la fonction appelée par l'interruption externe n°0

    comptageImpulsion=comptageImpulsion+1; // Incrémente la variable de comptage

  //---- affiche le nombre d'impulsions sur le port série
  Serial.print("Nombre impulsions = ");
  Serial.println(comptageImpulsion);

  // tout se passe dans la fonction de gestion de l'interruption externe

}


// ////////////////////////// AUTRES FONCTIONS DU PROGRAMME ////////////////////

void digitalClockDisplay(){
  // digital clock display of the time
 Serial.print(hour());
  printDigits(minute());
  printDigits(second());
  Serial.print(" -- ");
  Serial.print(day());
  Serial.print("/");
  Serial.print(month());
  Serial.print("/");
  Serial.print(year());
  Serial.println();
  file.print(hour()), file.print(';');
  printDigitsSD(minute()), file.print(';');
  printDigitsSD(second()), file.print(';');
  file.print(day()), file.print(';');
  file.print(month()), file.print(';');
  file.print(year()), file.print(';');
  file.println();  
}

void printDigits(int digits){
  // utility function for digital clock display: prints preceding colon and leading 0
  Serial.print(":");
  if(digits < 10)
    Serial.print('0');
  Serial.print(digits);
}
void printDigitsSD(int digits){
  // utility function for digital clock display: prints preceding colon and leading 0
  if(digits < 10)
    file.print('0');
  file.print(digits);
}
/*-------- NTP code ----------*/

unsigned long getNtpTime()
{
  sendNTPpacket(timeServer); // send an NTP packet to a time server
  delay(1000);
  if ( Udp.parsePacket() ) {  
    // We've received a packet, read the data from it
    Udp.read(packetBuffer,NTP_PACKET_SIZE);  // read the packet into the buffer

    //the timestamp starts at byte 40 of the received packet and is four bytes,
    // or two words, long. First, esxtract the two words:

    unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
    unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);  
    // combine the four bytes (two words) into a long integer
    // this is NTP time (seconds since Jan 1 1900):
    unsigned long secsSince1900 = highWord << 16 | lowWord;
    const unsigned long seventyYears = 2208988800UL;    
    // subtract seventy years and add the time zone:
    unsigned long epoch = secsSince1900 - seventyYears + (timeZoneOffset * 3600L);
    Serial.println( (__FlashStringHelper *)PSTR("Heure sur serveur ntp 1"));
    return epoch;
  }
  else {
    sendNTPpacket(timeServer2); // send an NTP packet to a time server
    delay(1000);
    if ( Udp.parsePacket() ) {  
      // We've received a packet, read the data from it
      Udp.read(packetBuffer,NTP_PACKET_SIZE);  // read the packet into the buffer

      //the timestamp starts at byte 40 of the received packet and is four bytes,
      // or two words, long. First, esxtract the two words:

      unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
      unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);  
      // combine the four bytes (two words) into a long integer
      // this is NTP time (seconds since Jan 1 1900):
      unsigned long secsSince1900 = highWord << 16 | lowWord;
      const unsigned long seventyYears = 2208988800UL;    
      // subtract seventy years and add the time zone:
      unsigned long epoch = secsSince1900 - seventyYears + (timeZoneOffset * 3600L);
      Serial.println( (__FlashStringHelper *)PSTR("Heure sur serveur ntp 2"));
      return epoch;
    }

  }
  return 0;

}
// send an NTP request to the time server at the given address
unsigned long sendNTPpacket(IPAddress& address)
{
  // set all bytes in the buffer to 0
  memset(packetBuffer, 0, NTP_PACKET_SIZE);
  // Initialize values needed to form NTP request
  // (see URL above for details on the packets)
  packetBuffer[0] = 0b11100011;   // LI, Version, Mode
  packetBuffer[1] = 0;     // Stratum, or type of clock
  packetBuffer[2] = 6;     // Polling Interval
  packetBuffer[3] = 0xEC;  // Peer Clock Precision
  // 8 bytes of zero for Root Delay & Root Dispersion
  packetBuffer[12]  = 49;
  packetBuffer[13]  = 0x4E;
  packetBuffer[14]  = 49;
  packetBuffer[15]  = 52;

  // all NTP fields have been given values, now
  // you can send a packet requesting a timestamp:  
  Udp.beginPacket(address, 123); //NTP requests are to port 123
  Udp.write(packetBuffer,NTP_PACKET_SIZE);
  Udp.endPacket();
}
« Last Edit: December 15, 2012, 07:22:29 am by PITP2 » Logged

France
Offline Offline
Full Member
***
Karma: 0
Posts: 154
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Je dirai ici

Quote
  // start Ethernet and UDP
  if (Ethernet.begin(mac) == 0) {
    Serial.println( (__FlashStringHelper *)PSTR("Echec Ethernet DHCP"));
    Ethernet.begin(mac, ip);
    // no point in carrying on, so do nothing forevermore:
    //  for(;smiley-wink
    //    ;
  }

ton câble ethernet est débranché, donc pas de serveur DHCP, donc tu rentres dans le if qui attribue une adresse fixe mais qui dit qu'àprès "so do nothing forevermore:" et qui le fait avec le "for(;smiley-wink" sans fin.

Edit : j'ai dis n'importe quoi, je n'avais pas fait attention que tu avais commenté les lignes en question.
« Last Edit: December 15, 2012, 09:03:27 am by Pac2Kro » Logged

Offline Offline
Full Member
***
Karma: 0
Posts: 127
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Oui mais je retire le cable apres que l'arduino ait obtenu l'adresse IP
Logged

Offline Offline
Full Member
***
Karma: 0
Posts: 127
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

ce qui est étrange c'est que si je copie le code qui s'occupe de l'enregistrement sur la carte SD dans la partie  setup et bien le fichier est créé sans pbl ....   smiley-confuse
Logged

Offline Offline
Full Member
***
Karma: 0
Posts: 127
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Bon et bien après avoir mis en commentaire quelques println pour libérer de la mémoire et bien le prog tourne bien ...
il semblerait que lorsque l'on s'approche de la limite de mémoire l'arduino n'apprécie pas trop et se mélange les pédales :-)
Logged

France
Offline Offline
Faraday Member
**
Karma: 52
Posts: 5341
Arduino Hacker
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Bonjour,

Bon et bien après avoir mis en commentaire quelques println pour libérer de la mémoire et bien le prog tourne bien ...
il semblerait que lorsque l'on s'approche de la limite de mémoire l'arduino n'apprécie pas trop et se mélange les pédales :-)
Si il n'y a pas ~100 octets de RAM libre la pile et le tas partent en sucette et le programme crash smiley-wink

Je vois déja un truc pas beau du tout !
Code:
sprintf( reqhttp, "GET /solaire/txp2.php?nom_inst=Dupont&date_prod=%04d%02d%02d%02d%02d%02d&prod=%05d&commentaires=arduino HTTP/1.0",annee,mois,jour,heure,minut,sec,comptageImpulsion);
    client.println(reqhttp);
Pourquoi ne pas envoyer la partie fixe avant (avec un jolie F(".......") pour stocker le texte en flash)
puis "sprintfté" la partie changeante ?

Code:
client.println(F("GET /solaire/txp2.php?nom_inst=Dupont&date_prod="));
sprintf( reqhttp, "%04d%02d%02d%02d%02d%02d&prod=%05",annee,mois,jour,heure,minut,sec,comptageImpulsion);
client.println(reqhttp);
client.println(F("d&commentaires=arduino HTTP/1.0"));
Ce qui ne nécéssite plus qu'un buffer "reqhttp" de 15 caractères (75 octets de grappillé !) !

Pareil toutes les chaines de caractéres "blabla" -> F("blabla") pour pas gaspiller la mémoire RAM.

Et aussi :
Code:
(__FlashStringHelper *)PSTR("blabla")
->
Code:
F("blabla")
La macro F() fait exactement la même chose (PSTR + cast) mais c'est beaucoup plus lisible smiley-wink

Au passage, un int ça va de -32768 à 32768 (2 octets), un byte de 0 à 255 (1 octet).
A ton avis pour stocker une date (valeur max 31) ou une heure (valeur max 60) qu'est ce qui est le plus adapté ?

Avec ça tu devrait gagner pas mal de RAM et ton problème de carte SD devrait se résoudre de lui même smiley-wink
(la librairie SD laisse ~600 octets de RAM libre sur une carte UNO, ça laisse à réfléchir question optimisation de la mémoire)
Logged

Des news, des tuto et plein de bonne chose sur http://skyduino.wordpress.com !

Offline Offline
Full Member
***
Karma: 0
Posts: 127
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Bon voici le nouveau code avec la prise en compte de tes remarques et l'ajout de la partie lecture carte SD pour envoyer les Data qui n'ont pas pu etre envoyés la première fois.

L'envoie vers le serveur et l'ecriture sur la carte SD en cas de défaut d'envoie sur le seruveur fonctionne,  la lecture de la carte SD ne fonctionne que lors de l'initialisation de la carte ....

J'ai bien essayé de mettre un SD.begin dans la fonction LectSD mais rien ne fonctionne.


Code:
// --- Inclusion des librairies ---
#include <SD.h>       /* Pour la carte SD */
#include <Ethernet.h> /* Pour la shield ethernet */
#include <SPI.h>      /* Pour la communication bas niveau (carte SD et ethernet) */
#include <EthernetUdp.h>
#include <Time.h>
//#include <avr/pgmspace.h>
// --- Déclaration des constantes utiles ---
/** Taille du buffer pour la lecture du fichier texte et l'envoi de la requete HTTP */
static const byte BUFFER_SIZE = 50;


// variables globales :
#define PERIOD_WRITE_DATA    120000
unsigned long last_write_data;

static byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xEF }; //Adresse MAC de l'ethernet shield

unsigned int localPort = 8888;      // local port to listen for UDP packets

static IPAddress ip(192, 168, 0, 35); // Adresse IP de l'ethernet shield

static IPAddress timeServer(192, 43, 244, 18); // time.nist.gov NTP server

static IPAddress timeServer2(129, 6, 15, 28); //  time-a.nist.gov NTP server

static IPAddress srvphp(192, 168, 0, 135); // Adresse IP serveur perso PHP


const int NTP_PACKET_SIZE= 48; // NTP time stamp is in the first 48 bytes of the message

byte packetBuffer[ NTP_PACKET_SIZE]; //buffer to hold incoming and outgoing packets

byte Jour = day();  // variable d'initialisation pour la mise à zero de la production à minuit
volatile long comptageImpulsion=0; // variable accessible dans la routine interruption externe 0
byte test; // Variable utilisée pour tester valeur renvoyée par fonctions SD Card

// A UDP instance to let us send and receive packets over UDP
EthernetUDP Udp;


EthernetClient client;


time_t prevDisplay = 0; // when the digital clock was displayed
const  byte timeZoneOffset = +1; // GMT zone;
// --- Déclaration des constantes des broches E/S numériques ---

const byte brocheSDCardSelect=4;

// --- Déclaration des constantes des broches analogiques ---


// --- Déclaration des objets utiles pour les fonctionnalités utilisées ---
File file; // objet file
File root; // objet root pour le répertoire racine

// ////////////////////////// 2. FONCTION SETUP = Code d'initialisation //////////////////////////
// La fonction setup() est exécutée en premier et 1 seule fois, au démarrage du programme

void setup()   { // debut de la fonction setup()

  // --- ici instructions à exécuter 1 seule fois au démarrage du programme ---

  // ------- Initialisation fonctionnalités utilisées ------- 
  // ------- Initialisation des variables utilisées ------- 
  last_write_data = millis() - PERIOD_WRITE_DATA;
 


  Serial.begin(115200); // initialise connexion série à 115200 bauds
  // IMPORTANT : régler le terminal côté PC avec la même valeur de transmission

 

 

  attachInterrupt(0, gestionINT0, RISING); // attache l'interruption externe n°0 à la fonction gestionINT0()
  // mode déclenchement possibles = LOW, CHANGE, RISING, FALLING


   
 /* Initialisation de la shield ethernet et UDP*/
    Ethernet.begin(mac, ip);
    Udp.begin(localPort);
   
    /* mise à l'heure du module via ntp */
    setSyncProvider(getNtpTime);
    while(timeStatus()== timeNotSet); // wait until the time is set by the sync provider
 

   /* Initialisation de la carte SD */
  Serial.print(F("Initialisation de la carte SD ... "));
  pinMode(10, OUTPUT); /* Obligatoire pour que la communication SPI fonctionne (10 UNO, 53 Mega)*/
  if (!SD.begin(4)) {  /* Broche "CS" de la carte SD sur D4 */
    Serial.println(F("Echec !"));
    for(;;);
  }
  Serial.println(F("Ok !"));

  /* Ouverture du dossier "root" */
  root = SD.open("/");
  Serial.println(F("Setup Termine !"));
} // fin de la fonction setup()

 
 
 
       
 





Logged

Offline Offline
Full Member
***
Karma: 0
Posts: 127
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
void loop(){ // debut de la fonction loop()


  if (Jour != day()) {
    comptageImpulsion = 0;
    Jour = day();
    Serial.println( (__FlashStringHelper *)PSTR("Init compteur changement de jour"));
    file.println( (__FlashStringHelper *)PSTR("Init compteur changement de jour") );
  }

  // Si et seulement si PERIOD_WRITE_DATA s'est écoulé depuis la dernière fois, on exécute la fonction d'écriture SD et l'envoi sur COSM

  // Sinon, on recommence loop
  if ( (millis()-last_write_data) > PERIOD_WRITE_DATA )
  {
    // Initialisation de la variale permettant la réinitialisation du compteur au changement de jour
    Jour = day(); // Gestion de l'initialisation du compreur de changement de jour

    last_write_data = millis(); // variable de gestion de la boucle if

    // read the analog sensor:
    long sensorReading = comptageImpulsion ;  

    sendData(sensorReading);
    LectSD();
  
  } // fin else
}

// fin de la fonction loop() - le programme recommence au début de la fonction loop sans fin
// ********************************************************************************


// ////////////////////////// FONCTIONS DE GESTION DES INTERRUPTIONS ////////////////////


// this method makes a HTTP connection to the server:
void sendData(int thisData) {
  // if there's a successful connection:
  if (client.connect(srvphp, 80)) {
    char reqhttp[50];
    int annee = year();
    byte sec = second();
    byte jour=day();
    byte mois = month();
    byte heure= hour();
    byte minut= minute();
    
    Serial.println(F("connected srvphp"));
    // Make a HTTP request:
    sprintf(reqhttp, "%04d%02d%02d%02d%02d%02d&prod=%05d", annee,mois,jour,heure,minut,sec,comptageImpulsion);
  client.print(F("GET /solaire/txp2.php?nom_inst=Dupont&date_prod="));
  client.print(reqhttp);
  client.println(F("&commentaires=arduino HTTP/1.0"));
  client.println();
  
    //sprintf( reqhttp, "GET /solaire/txp2.php?nom_inst=Dupont&date_prod=%04d%02d%02d%02d%02d%02d&prod=%05d&commentaires=arduino HTTP/1.0",annee,mois,jour,heure,minut,sec,comptageImpulsion);
    //client.println(reqhttp);
    // client.println();
    Serial.println(F("Fin envoie srvphp"));
    client.stop();
    }
  else {
  
  
    char datafile[13] = {'\0'};
    byte jour=day();
    byte mois = month();
    byte heure= hour();
    byte minut= minute();

    sprintf(datafile,"%02d%02d%02d%02d.txt",mois,jour,heure,minut);  //  %d pour un int
    
    
     Serial.println(datafile);
    
  //    SD.begin(brocheSDCardSelect); // initialisation de la carte SD avec broche 4 en tant que CS - renvoie true/false
    //---- crée fichier en écriture ---
    file = SD.open(datafile, FILE_WRITE); // ouvre le fichier en écriture
    // NB : le fichier est créé si il n'existe pas !

    //---- test si fichier dispo en écriture
    if (!file) { // si fichier pas dispo
      Serial.println(F("Erreur ouverture fichier"));
    } // fin if
    else { // si le fichier existe et est ouvert
      Serial.println(F("Fichier pret pour ecriture"));
      //----- Ecriture dans le fichier au format CSV -----
      Serial.println(F("Enregistrement en cours"));
      

      // valeur deuxieme champ
      file.print(';');
      file.print(comptageImpulsion);
      file.print(';');
      // valeur quatrieme champ
      file.print(millis()), file.print(';');
      // le dernier champ doit se terminer par un saut de ligne +++
      if( now() != prevDisplay) //update the display only if the time has changed
      {
        prevDisplay = now();
        digitalClockDisplay();
      }  
      Serial.println(F("connection failed"));
      Serial.println(F("disconnecting"));

      file.close(); // ferme le fichier
      Serial.println(F("Fin enregistrement"));  
      Serial.println(F("Fermeture fichier"));
  }
 }
}
  

// This method calculates the number of digits in the
// sensor reading.  Since each digit of the ASCII decimal
// representation is a byte, the number of digits equals
// the number of bytes:

int getLength(int someValue) {
  // there's at least one byte:
  int digits = 1;
  // continually divide the value by ten,
  // adding one to the digit count for each
  // time you divide, until you're at 0:
  int dividend = someValue /10;
  while (dividend > 0) {
    dividend = dividend /10;
    digits++;
  }
  // return the number of digits:
  return digits;
}

// ------------------- fonction de gestion l'interruption externe n°0 (broche 2) ----------------
// cette fonction est appelée à chaque fois que l'interruption a lieu selon le mode configuré (LOW, CHANGE, RISING, FALLING)
void gestionINT0() {// la fonction appelée par l'interruption externe n°0

    comptageImpulsion=comptageImpulsion+1; // Incrémente la variable de comptage

  //---- affiche le nombre d'impulsions sur le port série
  Serial.print(F("Nombre impulsions = "));
  Serial.println(comptageImpulsion);

  // tout se passe dans la fonction de gestion de l'interruption externe

}


// ////////////////////////// AUTRES FONCTIONS DU PROGRAMME ////////////////////

void digitalClockDisplay(){
  // digital clock display of the time
// Serial.print(hour());
  printDigits(minute());
  printDigits(second());
 // Serial.print(" -- ");
//  Serial.print(day());
//  Serial.print("/");
 // Serial.print(month());
 // Serial.print("/");
 // Serial.print(year());
 // Serial.println();
  file.print(hour()), file.print(';');
  printDigitsSD(minute()), file.print(';');
  printDigitsSD(second()), file.print(';');
  file.print(day()), file.print(';');
  file.print(month()), file.print(';');
  file.print(year()), file.print(';');
  file.println();  
}

void printDigits(int digits){
  // utility function for digital clock display: prints preceding colon and leading 0
 // Serial.print(":");
 // if(digits < 10)
  //  Serial.print('0');
//  Serial.print(digits);
}
void printDigitsSD(int digits){
  // utility function for digital clock display: prints preceding colon and leading 0
  if(digits < 10)
    file.print('0');
  file.print(digits);
}
/*-------- NTP code ----------*/

unsigned long getNtpTime()
{
  sendNTPpacket(timeServer); // send an NTP packet to a time server
  delay(1000);
  if ( Udp.parsePacket() ) {  
    // We've received a packet, read the data from it
    Udp.read(packetBuffer,NTP_PACKET_SIZE);  // read the packet into the buffer

    //the timestamp starts at byte 40 of the received packet and is four bytes,
    // or two words, long. First, esxtract the two words:

    unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
    unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);  
    // combine the four bytes (two words) into a long integer
    // this is NTP time (seconds since Jan 1 1900):
    unsigned long secsSince1900 = highWord << 16 | lowWord;
    const unsigned long seventyYears = 2208988800UL;    
    // subtract seventy years and add the time zone:
    unsigned long epoch = secsSince1900 - seventyYears + (timeZoneOffset * 3600L);
    Serial.println(F("Heure sur serveur ntp 1"));
    return epoch;
  }
  else {
    sendNTPpacket(timeServer2); // send an NTP packet to a time server
    delay(1000);
    if ( Udp.parsePacket() ) {  
      // We've received a packet, read the data from it
      Udp.read(packetBuffer,NTP_PACKET_SIZE);  // read the packet into the buffer

      //the timestamp starts at byte 40 of the received packet and is four bytes,
      // or two words, long. First, esxtract the two words:

      unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
      unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);  
      // combine the four bytes (two words) into a long integer
      // this is NTP time (seconds since Jan 1 1900):
      unsigned long secsSince1900 = highWord << 16 | lowWord;
      const unsigned long seventyYears = 2208988800UL;    
      // subtract seventy years and add the time zone:
      unsigned long epoch = secsSince1900 - seventyYears + (timeZoneOffset * 3600L);
      Serial.println(F("Heure sur serveur ntp 2"));
      return epoch;
    }

  }
  return 0;

}
// send an NTP request to the time server at the given address
unsigned long sendNTPpacket(IPAddress& address)
{
  // set all bytes in the buffer to 0
  memset(packetBuffer, 0, NTP_PACKET_SIZE);
  // Initialize values needed to form NTP request
  // (see URL above for details on the packets)
  packetBuffer[0] = 0b11100011;   // LI, Version, Mode
  packetBuffer[1] = 0;     // Stratum, or type of clock
  packetBuffer[2] = 6;     // Polling Interval
  packetBuffer[3] = 0xEC;  // Peer Clock Precision
  // 8 bytes of zero for Root Delay & Root Dispersion
  packetBuffer[12]  = 49;
  packetBuffer[13]  = 0x4E;
  packetBuffer[14]  = 49;
  packetBuffer[15]  = 52;

  // all NTP fields have been given values, now
  // you can send a packet requesting a timestamp:  
  Udp.beginPacket(address, 123); //NTP requests are to port 123
  Udp.write(packetBuffer,NTP_PACKET_SIZE);
  Udp.endPacket();
}
 
  
Logged

Offline Offline
Full Member
***
Karma: 0
Posts: 127
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
void LectSD() {
  /* Buffer temporaire pour la lecture du fichier et la création de la requete HTTP */
  char buffer[BUFFER_SIZE];

  /* Variables contenant les résultats de la lecture du fichier texte */
  int nbImpulsions, heures, minutes, secondes, jours, mois, annees;
 
  /* Ouverture du prochain fichier disponible sur la carte SD */
  File entry =  root.openNextFile();
  if (!entry) {
    Serial.println(F("Probleme d'ouverture ou plus de fichier disponible !"));
  //  for(;;);
    /* On pourrait aussi faire un rootDir.rewindDirectory() pour reprendre au 1er fichier */
  }
else {
  /* Test pour savoir si il s'agit d'un répertoire */
  if(entry.isDirectory()) {
    /* Dans le cas d'un répertoire il est posible de faire un scan récursive.
     * Ici on ignore juste les dossiers */
    entry.close();
    return;
  }

  /* Affichage du nom du fichier en cours (pour debug) */
  Serial.print(F("Traitement de "));
  Serial.println(entry.name());

  /* Lecture des données du fichier */
  byte i = 0;
  while(entry.available() > 0) { /* Jusqu'a la fin du fichier */
    buffer[i] = entry.read(); /* Buffering */

    /* Test anti buffer-overflow */
    if(++i == BUFFER_SIZE) {
      Serial.println(F("Fichier trop gros !"));
      entry.close();
      return;
    }
  }

  /* Fermeture du fichier */
  entry.close();
  

  /* Pour debug */
  Serial.print(F("Buffer: "));
  Serial.println(buffer);

  /* Extraction des champs */
  if(sscanf(buffer, ";%d ;%*d ;%d ;%d ;%d ;%d ;%d ;%d", &nbImpulsions, &heures, &minutes, &secondes, &jours, &mois, &annees) != 7) {
    Serial.println(F("Fichier malforme !"));
    SD.remove(entry.name());
    return;
  }

  /* Pour debug */
  Serial.print(F("Annees: "));
  Serial.println(annees);
  Serial.print(F("Mois: "));
  Serial.println(mois);
  Serial.print(F("Jours: "));
  Serial.println(jours);
  Serial.print(F("Heures: "));
  Serial.println(heures);
  Serial.print(F("Minutes: "));
  Serial.println(minutes);
  Serial.print(F("Secondes: "));
  Serial.println(secondes);
  Serial.print(F("Nb impulsions: "));
  Serial.println(nbImpulsions);

  /* Ouverture de la connexion TCP */
  EthernetClient client;
  Serial.print(F("Connexion au serveur ... "));
  if (!client.connect(srvphp, 80)) {
    Serial.println(F("Echec !"));
    return;
  }
  Serial.println(F("Ok !"));

  /* Envoi de la requete HTTP */
  sprintf(buffer, "%04d%02d%02d%02d%02d%02d&prod=%05d", annees, mois, jours, heures, minutes, secondes, nbImpulsions);
  client.print(F("GET /solaire/txp2.php?nom_inst=Dupont&date_prod="));
  client.print(buffer);
  client.println(F("&commentaires=arduino HTTP/1.0"));
  client.println();

  /* Fin de la requete HTTP */
  Serial.println(F("Fin envoi ..."));
  delay(10); /* Permet au serveur distant de recevoir les données avant de fermer la connexion*/
  client.stop();
  SD.remove(entry.name());
  }
   }
Logged

Offline Offline
Full Member
***
Karma: 0
Posts: 127
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Même en essayant de forcer une init de la carte SD dans loop cela ne fonctionne pas ..  smiley-confuse
etrange que cela fonctionne uniquement lors de l'init de la carte ... ce qui n'arrange pas mes affaires
Logged

Offline Offline
Full Member
***
Karma: 0
Posts: 127
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

J'ai aussi regardé si je n'explosais pas la capacité de la RAM avec FreeRam et cela semble bon je reste à un peu plus de 500 Octets de mémoire libre.
Je ne sais plus trop ou chercher ... smiley-cry
Logged

Offline Offline
Full Member
***
Karma: 0
Posts: 127
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Selon les conseils de Skywodd j'ai modifié le code.
Par contre malgré tout je rencontre tjrs le même problème lorsque je retire le cable réseau, le fichier s'enregistre bien sur la carte SD, par contre lorsque je le remets et bien le ou les fichiers ne sont pas renvoyés.
J'essaie pourtant ce que m'avait conseillé Barbudor à savoir mettre des SD.begin mais rien n'y fait ....

J'ai inséré le code en pièce jointe

Quote
Ton code un est peu "spaghetti" sur les bords

Déjà je vois des choses pas génial :
- trop de commentaire à des endroits tels que setup() ou loop() mais pas dans le code en lui même
- trop de variable globales, tu monopolises de la mémoire RAM pour des variables qui pourraient être locales (ou à défaut static dans une fonction)
- il reste des cast en FlashStringHelper de PSTR, utilise F("...") partout ça sera plus lisible
- déclare last_write_data en static dans loop initialisé à 0
- tu println() le nom du fichier dans un fichier qui n'est jamais ouvert
- de même tu envois à de multiple endroits des messages de debug dans le fichier (ce qui posera problème lors de la réouverture)
- tu as une fonction d'envoi des données en http, alors pourquoi avoir deux fois le code dans lectureSD() et sendData()
--> fait une seul fonction prenant en arguments : (annees, mois, jours, heures, minutes, secondes, nbImpulsions) et reprend le code que je t'avais donné
(cette fonction devra retourner un boolean, true -> envoi réussi : pour ensuite déclencher une lecture des fichiers sur la sd, false -> echec : pour ensuite déclencher une écriture sur la sd)
- tu as aussi pas mal de fonction "utilitaires" copier / coller depuis je ne sait ou, sont elles bien utiles ?
- tu devrais aussi revoir le nom de tes fonctions / variables, ex: last_write_data -> temps donc plutôt last_write_time

Ps: attache ton code complet en pièce jointe dans ton post, lire 3 morceaux de code séparé est un vrai casse tête

* code.txt (13.14 KB - downloaded 15 times.)
Logged

Pages: [1]   Go Up
Jump to: