Skip to content

Data Logger

– de completat –

1. Cuvant inainte

Continuare din pagina “Transformarea in Sanguino“. An terminat si prezentat pe web acest proiect in data de 01.01.2011, intr-o perioada cand aveam mari probleme cu sanatatea. Asa ca i-am multumit lui Dumnezeu pentru realizare. Asta mi-a fost toata „distractia” de anul nou🙂.

Programul este conceput ca un schelet pe care se pot construi aplicatii reale de monitorizare si inregistrare pe SD-Card a diverselor evenimente si date furnizate de senzori dintr-o arie mare de applicatii.

Aplicatia inregistreaza pe SD-Card la intervale regulate de timp (la fiecare ora), data calendaristica, ora, valorile digitale a doua potentiometre si temperatura in grade celsius. Aplicatia este proiectata sa fie cat mai interactiva posibil avand in vedere si posibilitatea ca placa sa poata rula in mediul extern (ex.: la o statie meteorologica, sau montata pe stalpul unei turbine eoliene pentru a inregistra viteza vantului, RPM-ul, voltajul si amperajul turbinei, etc.). Desigur, programul se poate modifica in orice fel, pentru a corespunde oricaror cerinte.

Denumirile fisierelor in care sunt inregistrate datele sunt compuse din anul si luna in care se fac inregistrarile, astfel ca la sfarsitul anului, vor exista 12 fisiere (ex.: 201207.txt, corespunzand anului 2012 si luna 07). In fiecare fisier vor fi cate 24 randuri de date * nr. de zile din luna curenta. De exemplu, presupunand ca luna curenta are 31 de zile, vor fi 24 de randuri de date pe zi, a cate 31 de zile. Adica in total,  744 de randuri evidentiate fiecare prin data si ora la care s-a facut inregistrarea. Deci, usor de prelucrat ulterior pe un PC.

2011/01/01 09:25:14 P1=396 P2=835 T:23.50
2011/01/01 10:25:15 P1=396 P2=835 T:23.56
2011/01/01 11:25:16 P1=396 P2=835 T:23.56
2011/01/01 12:25:17 P1=396 P2=835 T:23.56
2011/01/01 13:25:17 P1=396 P2=835 T:23.56
2011/01/01 14:25:18 P1=396 P2=835 T:23.56
2011/01/01 15:25:19 P1=396 P2=835 T:23.56
2011/01/01 16:25:20 P1=396 P2=835 T:23.56
2011/01/01 17:25:21 P1=396 P2=835 T:23.56
2011/01/01 18:25:22 P1=396 P2=835 T:23.56
2011/01/01 19:25:22 P1=396 P2=835 T:23.56
2011/01/01 20:25:23 P1=396 P2=835 T:23.56
2011/01/01 21:25:24 P1=396 P2=835 T:24.62
2011/01/01 22:25:25 P1=396 P2=835 T:24.62

Exemplu de continut

2. Setare placa

Pentru conexiunile acestui proiect aveti nevoie de mai mult de 10 fire, cu cat vine placa la vanzare. De aceea spuneam ca trebuie sa cumparati ulterior mai multe fire.

Conexiuni fire
 Pini ATmega
Pini periferice placa
 Alias
 Digital 0  Unul din cele 8 LED’s  de pe placa, la alegere (am ales RED color) Boot LED
 Digital 13  Unul din cele 8 LED’s  de pe placa, la alegere (I chosed GREEN color) Run LED
 Digital 14  Unul din cele 8 LED’s  de pe placa, la alegere (I chosed RED color) Error LED
 Digital 15  Unul din cele 8 LED’s  de pe placa, la alegere (I chose RED color) SD access LED
 Digital 12
 on S5 pin Run Button
 Digital 11
 on S4 pin Eject Button
 Digital 2  La pinul DS18B20 OneWire
 Digital 4  pin DAT3 on MMC/SD card peripheral
 Digital 5
 pin DI on MMC/SD card peripheral
 Digital 6
 pin DAT0 on MMC/SD card peripheral
 Digital 7
 pin CLK on MMC/SD card peripheral
 Digital 22  RS pin on LCD
 Digital 23
 E pin on LCD
 Digital 24
 D4 pin on LCD
 Digital 25
 D5 pin on LCD
 Digital 26
 D6 pin on LCD
 Digital 27
 D7 pin on LCD
 Analog 0
 POT1 pin  POT1
 Analog 1
 POT2 pin  POT2

3. Schita

/*****************************************************************************
 *  A logging application and the second target to achieve.
 *
 *  remember you can set the time by sending it YYMMDDhhmmss; from console.
 *  The semicolon on the end tells it you're done...
 *
 *  Author: Vasile Guta-Ciucur
 *  License: New BSD License.
 ******************************************************************************/
#include  // necessary, or the application won't build properly
#include
#include
#include
#include
#include  // use functions to print strings from flash memory
#include
#include // Data wire is plugged into port 2 on the Arduino
#define ONE_WIRE_BUS 2

Sd2Card card;
SdVolume volume;
SdFile root;
SdFile file;

// Setup a oneWire instance to communicate with any OneWire devices
//    (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);

int correct_address = 0;
PCF8583 p (0xA2);// the device's I2C read address on our board
LiquidCrystal lcd(22, 23, 24, 25, 26, 27);

int pot1, pot2;
char potbuf[10];
int b1, tmp, b2 = 1;
int runLED = 13;
int errorLED = 15;
int recordingLED = 14;
int runButton = 12;
int ejectButton = 11;
int oldHour = -1;

void clear_row1(){
  lcd.setCursor(0, 0);
  lcd.print("                ");
  lcd.setCursor(0, 0);
}

void clear_row2(){
  lcd.setCursor(0, 1);
  lcd.print("                ");
  lcd.setCursor(0, 1);
}

void blink_runLED(){
  tmp = digitalRead(runLED);
  if (tmp == LOW)
    digitalWrite(runLED,HIGH);
  else
    digitalWrite(runLED,LOW);
}

void blink_errorLED(){
  tmp = digitalRead(errorLED);
  if (tmp == LOW)
    digitalWrite(errorLED,HIGH);
  else
    digitalWrite(errorLED,LOW);
}

long previousMillis = 0;
unsigned long currentMillis;

void initCard(){
  digitalWrite(runLED, HIGH);
  previousMillis = 0;
  // initialize the SD card at SPI_HALF_SPEED to avoid bus errors with
  // breadboards.  use SPI_FULL_SPEED for better performance.
  if (!card.init(SPI_HALF_SPEED)){
    clear_row1();
    lcd.print("Error: SD card");
    clear_row2();
    lcd.print("initialization");
    while(1 == 1){
      currentMillis = millis();
      if(currentMillis - previousMillis > 100) {
        previousMillis = currentMillis;
        blink_errorLED();
      }
    }
  }

  // initialize a FAT volume
  if (!volume.init(&card)){
    clear_row1();
    lcd.print("Error: SD card");
    clear_row2();
    lcd.print("FAT volume");
    while(1 == 1){
      currentMillis = millis();
      if(currentMillis - previousMillis > 100) {
        previousMillis = currentMillis;
        blink_errorLED();
      }
    }
  }

  // open the root directory
  if (!root.openRoot(&volume)){
    clear_row1();
    lcd.print("Error: SD card");
    clear_row2();
    lcd.print("open Root");
    while(1 == 1){
      currentMillis = millis();
      if(currentMillis - previousMillis > 100) {
        previousMillis = currentMillis;
        blink_errorLED();
      }
    }
  }
}

void setup(void){
  Serial.begin(9600);
  // set up the LCD's number of columns and rows:
  lcd.begin(16, 2);
  pinMode(runLED, OUTPUT);  // digital 13 LED
  // Start up the dallas library
  sensors.begin();
  // two button inputs
  pinMode(ejectButton, INPUT);
  pinMode(runButton, INPUT);
  // set pull-ups on them
  digitalWrite(ejectButton, HIGH);
  digitalWrite(runButton, HIGH);
  // another two LEDs
  pinMode(recordingLED, OUTPUT);
  pinMode(errorLED, OUTPUT);
  digitalWrite(recordingLED, 1); // shut them off
  digitalWrite(errorLED, 1);
  // ready to set timer and/or press OK button
  digitalWrite(runLED, LOW);
  while(b2 == 1){
    //reading time setup from the serial console
    if(Serial.available() > 0){
      Serial.println("receiving...");
      // Use of (byte) type casting and ascii math to achieve result.
      p.year= (byte) ((Serial.read() - 48) *10 +  (Serial.read() - 48)) + 2000;
      p.month = (byte) ((Serial.read() - 48) *10 +  (Serial.read() - 48));
      p.day = (byte) ((Serial.read() - 48) *10 +  (Serial.read() - 48));
      p.hour  = (byte) ((Serial.read() - 48) *10 +  (Serial.read() - 48));
      p.minute = (byte) ((Serial.read() - 48) *10 +  (Serial.read() - 48));
      p.second = (byte) ((Serial.read() - 48) * 10 + (Serial.read() - 48));
      if(Serial.read() == ';'){
        Serial.println("setting date");
        p.set_time();
      }
    }
    // Blink runLED intermitently signaling that you must press the run button
    currentMillis = millis();
    if(currentMillis - previousMillis > 250) {
      // save the last time you blinked the LED
      previousMillis = currentMillis;
      blink_runLED();
    }
    // read the real time clock
    p.get_time();
    // printing the date
    char date[9];
    sprintf(date, "%04d/%02d/%02d",
	  p.year, p.month, p.day);
    lcd.setCursor(0, 0);
    lcd.print(date);
    lcd.print(" SET");
    char time[9];
    sprintf(time, "%02d:%02d:%02d",
	  p.hour, p.minute, p.second);
    //Serial.println(time);
    lcd.setCursor(0, 1);
    lcd.print(time);
    lcd.print("   CLOCK");
    b2 = digitalRead(runButton);
  }
  initCard();
}

void loop(void){
  //clear_row1();
  //clear_row2();
  digitalWrite(runLED, LOW);
  //read potentiometers
  pot1 = analogRead(0);
  pot2 = analogRead(1);
  sprintf(potbuf, "P1=%04d P2=%04d", pot1, pot2);
  clear_row1();
  lcd.print(potbuf);
  // printing the hour
  p.get_time();
  char time[9];
  sprintf(time, "%02d:%02d:%02d",
	  p.hour, p.minute, p.second);
  //Serial.println(time);
  lcd.setCursor(0, 1);
  lcd.print(time);
  lcd.print(" T:");
  // call sensors.requestTemperatures() to issue a global temperature
  // request to all devices on the bus
  sensors.requestTemperatures(); // Send the command to get temperatures
  lcd.print(sensors.getTempCByIndex(0));
  // see if eject button was pressed
  b1 = digitalRead(ejectButton);
  b2 = HIGH;
  if (b1 == LOW) {
    //clear_row1();
    lcd.setCursor(0, 0);
    lcd.print("Exchange SD and");
    //clear_row2();
    lcd.setCursor(0, 1);
    lcd.print("press RUN button");
    previousMillis = 0;
    while (b2 == HIGH){
      b2 = digitalRead(runButton);
      currentMillis = millis();
      if(currentMillis - previousMillis > 250) {
        previousMillis = currentMillis;
        blink_runLED();
      }
      //
    }
  } // end b1 event

  // let's logg the data on SD card at every hour
  // here check to see if is a new hour
  if(oldHour != p.hour){
    // Light the recording LED when access SD card
    digitalWrite(recordingLED, LOW);
    // create or open the file (the name is year+month)
    char fname[11];
    sprintf(fname, "%04d%02d.TXT", p.year, p.month);
    file.writeError = false;
    if (!file.open(&root, fname, O_CREAT | O_APPEND | O_WRITE)) {
      digitalWrite(runLED, HIGH);
      digitalWrite(recordingLED, HIGH);
      clear_row1();
      lcd.print("Error: SD card");
      clear_row2();
      lcd.print("create/open File");
      previousMillis = 0;
      while(1 == 1){
        currentMillis = millis();
        if(currentMillis - previousMillis > 100) {
          previousMillis = currentMillis;
          blink_errorLED();
        }
      }
    }

    // write the sensors and voltage into the file
    char date[9];
    sprintf(date, "%04d/%02d/%02d",
	  p.year, p.month, p.day);
    file.print(date);
    file.print(" ");
    file.print(time);
    file.print(" P1=");
    file.print(pot1, DEC);
    file.print(" P2=");
    file.print(pot2, DEC);
    file.print(" T:");
    file.println(sensors.getTempCByIndex(0));
    if (file.writeError){
      digitalWrite(runLED, HIGH);
      digitalWrite(recordingLED, HIGH);
      clear_row1();
      lcd.print("Error: SD card");
      clear_row2();
      lcd.print("write to File");
      previousMillis = 0;
      while(1 == 1){
        currentMillis = millis();
        if(currentMillis - previousMillis > 100) {
          previousMillis = currentMillis;
          blink_errorLED();
        }
      }
    }

    // close the file and reactualize the oldHour variable
    if (!file.close()) {
      digitalWrite(runLED, HIGH);
      digitalWrite(recordingLED, HIGH);
      clear_row1();
      lcd.print("Error: SD card");
      clear_row2();
      lcd.print("close File");
      previousMillis = 0;
      while(1 == 1){
        currentMillis = millis();
        if(currentMillis - previousMillis > 100) {
          previousMillis = currentMillis;
          blink_errorLED();
        }
      }
    }
    oldHour = p.hour;

    //switch OFF the recording LED
    digitalWrite(recordingLED, HIGH);

  } // end check if is a new hour

}

4. Rezultate

Nu am avut alt card de memorie cu care sa fac teste, decat cel de la camera foto. Asa ca pentru filme, nu mi-a mai ramas la dispozitie decat memoria interna a aparatului, atat de mica incat a trebuit sa filmez 3 „bucati” pentru a cuprinde tot proiectul. Scuzati engleza de balta (reamintesc ca actualele pagini sunt traduceri si adaptari de pe situl meu in engleza):

Partea 1-a. Setarea ceasului din consola. Microcontrollerul asteapta apasarea butonului „RUN” pentru a continua

Partea a 2-a. Apas butonul „RUN” si… „dezastru”! Microcontrollerul semnaleaza pe LCD ca am uitat sa inserez cardul.

Partea a 3-a. In sfarsit programul ruleaza fara alte incidente. De fapt, nu e chiar asa. Daca va uitati cu atentie la LCD veti observa ca am uitat sa setez ceasul (dupa un reset). Dar nu conteaza, sper ca ati prins ideea.

Din acest moment, si al doilea obiectiv propus a fost atins! Happy codding!

P.S. Daca aveti probleme cu copierea schitei (programului) din aceasta pagina, o puteti downloada de aici.

Lasă un comentariu

Va rog, nu folositi limbaj de messenger. Multumesc!

Completează mai jos detaliile despre tine sau dă clic pe un icon pentru autentificare:

Logo WordPress.com

Comentezi folosind contul tău WordPress.com. Dezautentificare / Schimbă )

Poză Twitter

Comentezi folosind contul tău Twitter. Dezautentificare / Schimbă )

Fotografie Facebook

Comentezi folosind contul tău Facebook. Dezautentificare / Schimbă )

Fotografie Google+

Comentezi folosind contul tău Google+. Dezautentificare / Schimbă )

Conectare la %s

%d blogeri au apreciat asta: