1

I'm reading data from the Shinyei PPD42 particle sensor unit.
Everything seems to work, but I'm encountering two problems

  1. When I restart Arduino, the file is not being extended, nor overwritten. It just remains how it was before.

  2. Even though my code looks fine, Arduino stops writing data to the SD card after 90 seconds.

Thanks for having a look at my code.

#include <SPI.h>  //een bibliotheek aan code toevoegen; Arduino heeft deze nodig om de Shield te kunnen 'lezen'
#include <SD.h>   //zie hierboven

int PM=8; //de fijnstofmeter zit in digitaal poortnummer 8

const int chipSelect = 10; //const = een variabele die nooit verandert

unsigned long sampletime_ms = 30000;  //unsigned long = een variabele die erg hoog kan oplopen, maar nooit negatief kan zijn

//hieronder volgen nog enkele variabelen. Denk eraan: float betekent dat het decimale getallen kunnen zijn

unsigned long duration; 
unsigned long starttime;
unsigned long lowpulseoccupancy = 0;
unsigned long timediff;
float ratio = 0;
float concentration = 0;
unsigned long tijd = 30;

//void setup wordt één keer uitgevoerd, bij het opstarten van de Arduino-minicomputer

void setup()
  {
    Serial.begin(9600); //de snelheid (in bits/second) aan welke de seriële data zal worden getransfereerd
    pinMode(PM,INPUT);  /*PM is de variabele van helemaal bovenaan: pinMode vraagt twee parameters 1)de poort (werd gedefinieerd bovenaan) 2)INPUT of OUTPUT 
                          Ditmaal leest de fijnstofmeter gegevens die we vervolgens IN onze Arduino willen importeren, dus INPUT*/

    starttime = millis(); //hoelang draait het programma? millis() geeft de duur sinds het werd opgestart

    Serial.println("SD-kaart opstarten indien aanwezig... "); //Je schrijft nu neer dat de SD-kaart wordt gezocht en opgestart (println = hierna op volgende regel verder gaan)

    //hieronder staat een 'als'-lus: als aan de eerste voorwaarde wordt voldaan, voert hij uit wat eronder staat, anders gaat Arduino verder achter de afsluitende accolade

    if (!SD.begin(chipSelect)) //Als er NIET (!) kan worden begonnen met de SD-kaart te selecteren ...
      {
        Serial.println("Corrupte of ontbrekende SD-kaart!"); //dan wordt deze boodschap getoond 
        return;
      }
    //Als de SD-kaart dus WEL werkt, gaan we hieronder verder

    Serial.println("SD-kaart werkt...");
    Serial.print("Fijnstofsensor start op. Even geduld! Metingen om de 30 seconden.");
    Serial.println("\n");
  }

//void setup wordt oneindig lang uitgevoerd, tenzij je dat anders bepaalt

void loop ()
  {
    duration = pulseIn(PM, LOW); //als de fijnstofdetector niet meet (LOW), beginnen meten
    lowpulseoccupancy = lowpulseoccupancy+duration; //na elke meting de 'duration' (30 sec)  optellen bij de totale tijd

    if ((millis()-starttime) >= sampletime_ms)
      {
        //hieronder de wiskundige berekeningen om het fijnstofgehalte te berekenen

        ratio = lowpulseoccupancy/(sampletime_ms*10.0);
        concentration = 1.1*pow(ratio,3)-3.8*pow(ratio,2)+520*ratio+0.62; 

        //hieronder alles wat zal worden geprint naar het seriële venster

        Serial.print("Fijnstofconcentratie na ");
        Serial.print(tijd);
        Serial.println(" seconden:");
        Serial.print(concentration);
        Serial.println(" deeltjes/0,01cf");
        Serial.print("\n");

        File dataFile = SD.open("test.txt", FILE_WRITE); //het bestand meting.txt moet op de SD-kaart worden geopend om erin te schrijven

        if (dataFile) //als het bestand kan worden geopend, volgende gegevens printen
          {
            dataFile.print("Fijnstofconcentratie na ");
            dataFile.print(tijd);
            dataFile.print(" seconden: ");
            //dataFile.println(ratio);
            dataFile.print(concentration);
            dataFile.print(" deeltjes/0,01cf");
            dataFile.print("\n");
            dataFile.close();
          }

        else //als het bestand niet kan worden geopend ...
          {
            Serial.println("Fout bij het openen van test.txt");
          }

        tijd = tijd + 30; //meting afgerond, totale tijd = +30 seconden
        lowpulseoccupancy = 0; //de status van de fijnstofmeter is terug 'LOW'
        starttime  = millis(); //volgende meting starten
      }
  }
  • Try to put your comments also in English (you never know when a non-Dutch person will read it ... like mostly here) ... succes! – Michel Keijzers May 6 '17 at 1:21
1

You need to open the file in append mode:

SD.open("file.txt", O_RDWR | O_APPEND);

It depends on the file being there. If it fails to open because the file isn't there you can open it in "create" mode instead:

SD.open("file.txt", O_RDWR | O_CREAT);

For example:

// Try and append
File f = SD.open("file.txt", O_RDWR | O_APPEND);
if (!f) {
    // It failed, so try and make a new file.
    f = SD.open("file.txt", O_RDWR | O_CREAT);
    if (!f) {
        // It failed too, so give up.
        Serial.println("Failed to open file.txt");
    }
}

// Only write to the file if the file is actually open.
if (f) {
    f.print(/* your data here */)
    f.close();
}
  • Do I only add the second line instead of the SD.open line I had? – Michael Apr 19 '17 at 16:26
  • No. You need both. I'll expand to show you. – Majenko Apr 19 '17 at 16:30
  • Thank you. Will this yield the same result? File dataFile = SD.open("test.txt", O_CREAT | O_APPEND | O_WRITE); – Michael Apr 19 '17 at 16:34
  • I don't think you can both create and append at the same time. You can give it a go though. Personally I like to be specific about these things so there is no chance for ambiguity. – Majenko Apr 19 '17 at 16:36
  • Majenko, any idea what I did wrong here? Using your solutions since my adaptation doesn't work after all: pastebin.com/k4xbyBpR – Michael Apr 19 '17 at 17:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.