• Witaj na Forum Arduino Polska! Zapraszamy do rejestracji!
  • Znajdziesz tutaj wiele informacji na temat hardware / software.
Witaj! Logowanie Rejestracja


Ocena wątku:
  • 0 głosów - średnia: 0
  • 1
  • 2
  • 3
  • 4
  • 5
Balon meteo z GPS, czujnikiem temperatury i wilgotności oraz modułem karty SD
#11
(17-10-2020, 08:05)Agregacik napisał(a):
(16-10-2020, 20:32)Jarewa0606 napisał(a): SoftwareSerial bazuje na przerwaniach, wiec twój projekt to wielka lipa i jedyna możliwość to zmiana na ardunio mega
Powiem tak, wcale nie musi być wielką lipą. Mam taki projekt z 3 SoftwareSerial i płytce nano i działa bardzo dobrze. Wszystko zależy co się chce osiągnąć. W moim przypadku poszczególne SoftwareSerial działają po kolei, czyli w danej chwili tylko jeden pyta i oczekuje odpowiedzi, inne śpią i nie oczekuję od nich działania w tle. Jeżeli ktoś oczekuje, że w tym samym czasie jak działa jeden SoftwareSerial drugi będzie zbierał w buforze dane to się może przeliczyć. Po zainicjowaniu każdego SoftwareSerial czyszczę bufor odbiorczy i dopiero wysyłam zapytania do podpiętego pod niego urządzenie. 
Do autora wątku, pokaż poprawiony kod. 



Podsyłam poprawiony kod:

Kod:
#include <SPI.h>                             // library for SPI devices (uSD board)
#include <TinyGPS.h>                         // library for GPS
#include <SoftwareSerial.h>                  // library for serial comm. with GPS
#include <SD.h>                              // library for the uSD board
#include <Wire.h>                            // library for comm. with I2C sensors
#include "DHT.h"                             // library for DHT temp and humidity sensor
#define DHTTYPE DHT22                        // DHT 22  (AM2302), AM2321
#define DHTPIN A0     

const byte chipSelect = 10;                   // the SD card CS pin is wired to pin 10
TinyGPS gps;                                 // make the tinyGPS object
SoftwareSerial ss(1, 0);                     // Assign the SoftwareSerial TX and RX pins for the GPS                 
DHT dht(DHTPIN, DHTTYPE);                   
SoftwareSerial sgsm(2, 3);
int state = 0;
const int pin = 4;
float gpslat, gpslon;

void setup()
    {
                            // only the GPS uses this
      Serial.begin(9600);                    // this is for displaying data on a serial monitor
                                 // Initialise the DHT sensor  
      pinMode(chipSelect, OUTPUT);           // The CS pin on the SD card                  
      if (!SD.begin(chipSelect))             // see if the card is present and can be initialized
         { while(1); }                       // Wait forever since we can't write data  
         
                 
    }
void loop()      
                    //GPS I KARTA SD  
   
   {  
    ss.begin(9600);
    dht.begin();                                                          
     bool newData = false;                    
     for (unsigned long start = millis(); millis() - start < 1000;)    // gather GPS data for 1 second
     {    
       while (ss.available())                         // while the GPS data is coming via software serial
       {
          char c = ss.read();                         // read the characters into c
          if (gps.encode(c))  newData = true;         // Did a new valid sentence come in?         
       }
     }
    String dataString = "";                           // start with an empty dataString
    if (newData)                                      // if a new valid GPS sentence was read
    {          
    float flat, flon, falt;                           // these next 9 lines parse the GPS data                   
    unsigned long age;
    int year;
    byte month, day, hour, minute, second, hundredths;
    gps.f_get_position(&flat, &flon, &age);
    falt = gps.f_altitude(); 
    gps.crack_datetime(&year, &month, &day, &hour, &minute, &second, &hundredths, &age);
    char sz[32];   
    sprintf(sz, "%02d/%02d/%02d,%02d:%02d:%02d,", month, day, year, hour, minute, second);
    File dataFile = SD.open("DANE.csv", FILE_WRITE);                      // write to this file
    dataFile.print("Data i Czas: ");
    dataFile.print(sz);
    dataFile.print(" Długosc: ");// write date time data to SD card
    dataFile.print(flon == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : flon, 6);     // write GPS data to SD card
    dataFile.print(",");
    Serial.print(" Długość: ");
    Serial.print(flon, 6);
    dataFile.print(" Szerokosc: ");
    dataFile.print(flat == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : flat, 6);     // write GPS data to SD card
    dataFile.print(",");
    Serial.print(" Szerokość: ");
    Serial.print(flat, 6);
    dataFile.print(" Wysokosc: ");
    dataFile.print(falt == TinyGPS::GPS_INVALID_ALTITUDE ? 0.0 : falt, 1);    // write GPS data to SD card 
    dataFile.print(" m,");
    Serial.print(" Wysokość: ");
    Serial.print(falt, 1);
    millis();  
             //TEMPERATURA i WILGOTNOSC                             
    float temperature;                              // Temperature variable
    float DHTh = dht.readHumidity();                // Read DHT sensor
    Serial.print(" Wilgotnosc: ");
    Serial.print(DHTh, 2);
    dataFile.print(" Wilgotnosc: ");
    dataFile.print(DHTh, 2);                        // write humidity data to SD card
    dataFile.print("%,");
    float DHTt = dht.readTemperature();             // Read temperature as Celsius (the default)
    Serial.print(" Temperatura: ");
    Serial.println(DHTt, 2);
    dataFile.print(" Temperatura: ");
    dataFile.print(DHTt, 2);                      // write temperature data to SD card and end line
    dataFile.println(" st. C ");
    dataFile.flush();
    dataFile.close();
    }                                       // endif (newData)
      millis();                         // write data to SD card only every few seconds
      while (ss.available())
  {
    //WYSYŁANIE DANYCH SMSEM
sgsm.begin(9600);
    int c = ss.read();
    if (gps.encode(c))
    {
      gps.f_get_position(&gpslat, &gpslon);
    }
  }
    if (sgsm.available() > 0) {
      String    c = sgsm.readString();
      c.trim();
      if (c.indexOf("GET-GPS") > 0) {
        sgsm.print("\r");
        millis();
        sgsm.print("AT+CMGF=1\r");
         millis();
        /*Replace XXXXXXXXXX to 10 digit mobile number &
          ZZ to 2 digit country code*/
        sgsm.print("AT+CMGS=\"+48790208796\"\r");
         millis();
        //The text of the message to be sent.
        sgsm.print("Szerokosc: ");
        sgsm.println(gpslat, 6);
        sgsm.print("Dlugosc: ");
        sgsm.println(gpslon, 6);
         millis();
        sgsm.write(0x1A);
         millis();
      }
    }
  }                          

Pozbyłem się jednego SoftwareSerial sgps bo używa on tej samej biblioteki co ss więc w kodzie zmieniłem sgps na ss. Po skompilowaniu i wgraniu nadal nic się nie dzieje. 
 
Odpowiedź
#12
Po pierwsze nie używaj pinów D0 i D1 bo one są podłączone do "seriala" który działa po USB i tam wyświetlasz sobie co chcesz na konsoli.
Naucz używać się millis() . Pisanie co jakiś czas miliis() nic nie daje bo samo millis to tylko liczba a właściwie czas jaku upłynął od startu procesora i nic nie robi. Trzeba nauczyć się jak to wykorzystać.
Ponadto chcesz jednocześnie korzystać z dwóch SoftwareSerial a tego się nie da zrobić o czym pisałem powyżej. Jeżeli tak chcesz robić to musisz zastosować "ARDUINO" mega jak pisał Jarewa0606.
Wspominałem Ci co zrobić, aby sprawdzić co się dzieje w programie. "Wyrzucaj" sobie kontrolne miejsca na konsolę, abyś wiedział gdzie jest teraz program i czy się nie zaciął w jakimś punkcie i czeka na godota.
 
Odpowiedź
#13
(17-10-2020, 13:20)Agregacik napisał(a): Po pierwsze nie używaj pinów D0 i D1 bo one są podłączone do "seriala" który działa po USB i tam wyświetlasz sobie co chcesz na konsoli. 
Naucz używać się millis() . Pisanie co jakiś czas miliis() nic nie daje bo samo millis to tylko liczba a właściwie czas jaku upłynął od startu procesora i nic nie robi. Trzeba nauczyć się jak to wykorzystać. 
Ponadto chcesz jednocześnie  korzystać z dwóch SoftwareSerial a tego się nie da zrobić o czym pisałem powyżej. Jeżeli tak chcesz robić to musisz zastosować "ARDUINO" mega jak pisał Jarewa0606.
Wspominałem Ci co zrobić, aby sprawdzić co się dzieje w programie.  "Wyrzucaj" sobie kontrolne miejsca na konsolę, abyś wiedział gdzie jest teraz program i czy się nie zaciął w jakimś punkcie i czeka na godota.

Rozumiem, o czym kolega pisze, aczkolwiek nie rozumiem do końca tych aspektów programowania. Dodałem sobie kontrolne wyświetlanie znaków ale program po uruchomieniu nic nie robi, nawet mi tego znaku nie wyświetla.Nie wiem nawet jak to przerobić więc albo przekażę to znajomemu do napisania lub jeżeli mogę kolegę Agregacik prosić o zmodyfikowanie tego kodu, aby był poprawnie napisany?
 
Odpowiedź
#14
Poprawa a właściwie napisanie od nowa całego programu nie jest takie szybkie i dla mnie proste. Trzeba mieć makietę z wszystkimi elementami. Wiedzieć, co po kolei ma się wykonywać a właściwie czego dokładnie oczekujesz.
Podziel program na "podprogramy" w LOOP powinno być, według mnie, tylko 3-4 pozycje z odniesieniami do podprogramów. Ułatwi to Ci analizę co się dzieje.
Może teraz program zatrzymuje się już na poziomie setup. Może masz coś źle podłączone i program czeka na odpowiedź podłączonych urządzeń, zatrzymuje się na którymś beginie i czeka.
Jak chcesz przeżywać przygodę z "arduino" to trzeba samemu dochodzić do wszystkiego. No może nie samemu bo jest wiele samouczków. Tutaj na grupie, czy gdzie indziej, pytać już o konkrety a nie "program mi nie działa".
Pytanie powinno brzmieć: program zatrzymuje się tu, co może być przyczyną, albo mam tak zrobione i mi nie czyta danych z czujnika co może być przyczyną.
Poczytaj może na początek tu: https://plociennik.info/index.php/arduino-wstep i tu: https://forbot.pl/blog/kurs-arduino-pods...rsu-id5290
Zapoznaj się z niezależnym miganiem diodami, to jest podstawą do sterowania opóźnieniami za pomocą millis().
I jeszcze jedna sprawa, jak piszesz program to dopisuj komentarze co dana linijka czy blok linijek ma robić. To ułatwia Tobie i ewentualnie doradzającym zrozumienie działania programu.
 
Odpowiedź
#15
(17-10-2020, 17:47)Agregacik napisał(a): Poprawa a właściwie napisanie od nowa całego programu nie jest takie szybkie i dla mnie proste. Trzeba mieć makietę z wszystkimi elementami. Wiedzieć, co po kolei ma się wykonywać a właściwie czego dokładnie oczekujesz.
Podziel program na "podprogramy" w LOOP powinno być, według mnie, tylko 3-4 pozycje z odniesieniami do podprogramów.  Ułatwi to Ci analizę co się dzieje.
Może teraz program zatrzymuje się już na poziomie setup. Może masz coś źle podłączone i program czeka na odpowiedź podłączonych urządzeń, zatrzymuje się na którymś beginie i czeka.
Jak chcesz przeżywać przygodę z "arduino" to trzeba samemu dochodzić do wszystkiego. No może nie samemu bo jest wiele samouczków. Tutaj na grupie, czy gdzie indziej, pytać już o konkrety a nie "program mi nie działa".
Pytanie powinno brzmieć: program zatrzymuje się tu, co może być przyczyną, albo mam tak zrobione i mi nie czyta danych z czujnika co może być przyczyną.
Poczytaj może na początek  tu: https://plociennik.info/index.php/arduino-wstep i tu: https://forbot.pl/blog/kurs-arduino-pods...rsu-id5290
Zapoznaj się z niezależnym miganiem diodami, to jest podstawą do sterowania opóźnieniami za pomocą millis().
I jeszcze jedna sprawa, jak piszesz program to dopisuj komentarze co dana linijka czy blok linijek ma robić. To ułatwia Tobie i ewentualnie doradzającym zrozumienie działania programu.

Podłączenie elementów jest prawidłowe. Jak pisałem, wszystko z osobna działa.
Poprawiłem kod, wróciłem do jego pierwotnej wersji. W tym momencie działa i zapisuje mi dane z czujnika temperatury i dane z GPS na kartę pamięci w fajnej dla mnie formie, wszystko w excelu. Nadal pozostaje kwestia rozwiązania wysyłania sms przez moduł ze swoim położeniem.  Aktualnie wygląda to tak:
Kod:
#include "Wire.h"
#include "SD.h"
#include "SoftwareSerial.h"
#include "TinyGPS.h"
#include "DHT.h"
#define DHTTYPE DHT22                        // DHT 22  (AM2302), AM2321
#define DHTPIN A0
const int chipSelect = 10;
File dataFile;
DHT dht(DHTPIN, DHTTYPE); 
TinyGPS gps;
SoftwareSerial ss(6, 7);

void setup() 
{
  Serial.begin(115200);
  Serial.print("Initializing SD card...");
  ss.begin(9600);
  dht.begin();
  pinMode(chipSelect, OUTPUT);
 
  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    while (1) ;
  }
  Serial.println("card initialized.");
 
  // Open up the file we're going to log to!
  dataFile = SD.open("GPStest.txt", FILE_WRITE);
  if (! dataFile) {
    Serial.println("error opening GPStest.txt");
    // Wait forever since we cant write data
    while (1) ;
  } 
}

void loop()                   
{
  bool newData = false;

for (unsigned long start = millis(); millis() - start < 1000;)
  {
    while (ss.available())
    {
      char c = ss.read();
      // Serial.write(c); // uncomment this line if you want to see the GPS data flowing
      if (gps.encode(c)) // Did a new valid sentence come in?
        newData = true;
    }
  }

    if (newData)
  {
    float flat, flon;
    unsigned long age;
    int year;
    byte month, day, hour, minute, second, hundredths;
    gps.f_get_position(&flat, &flon, &age);
    gps.crack_datetime(&year, &month, &day, &hour, &minute, &second, &hundredths, &age);
        char sz[32];
    sprintf(sz, "%02d/%02d/%02d, %02d:%02d:%02d,  ",
     month, day, year, hour, minute, second);
   
    Serial.print("");
    Serial.print("Szerokość: ");
    Serial.print(flon == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : flon, 6);
    Serial.print(", ");
    Serial.print("Długośc: ");
    Serial.print(flat == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : flat, 6);
    Serial.print(", ");

    dataFile.print("");
    dataFile.print(flon == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : flon, 6);
    dataFile.print(", ");
    dataFile.print(flat == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : flat, 6);
    dataFile.print(", ");
    float temperature;                              // Temperature variable
    delay (100);
    float DHTh = dht.readHumidity();                // Read DHT sensor
    Serial.print("Wilgotnosc: ");
    Serial.print(DHTh, 2);
    dataFile.print(" Wilgotnosc: ");
    dataFile.print(DHTh, 2);                        // write humidity data to SD card
    dataFile.print("%,");
    float DHTt = dht.readTemperature();             // Read temperature as Celsius (the default)
    Serial.print(" Temperatura: ");
    Serial.println(DHTt, 2);
    dataFile.print(" Temperatura: ");
    dataFile.println(DHTt, 2);                      // write temperature data to SD card and end line
  }

  dataFile.flush();
  delay(500);
}

W takim razie doszkalam się dalej i postaram się jakoś część z modułem GSM dodać do programu.
 
Odpowiedź
#16
Aby pójść dalej czyli "dorobić" wysyłanie SMSów trzeba najpierw zapisać odczytane dane z GPSa i czujników temperatury wilgotności i innych, jak ich dołożysz, do ZMIENNYCH GLOBALNYCH.
Teraz zapisujesz ich do zmiennych lokalnych, które po wykonaniu się pętli są "zabijane".
Zapamiętanie danych w zmiennych globalnych daje możliwość ich wykorzystania w innych podprogramach.
Można z grubsza powiedzieć, że na końcu pętli uruchamiasz SoftwareSerial od "SMSa" i wysyłasz zapisane dane w zmiennych globalnych czyli położenie i pomiary z czujników. Na końcu zerujesz zmienne globalne, po to aby wpisać nowe wartości w kolejnej pętli. Pozostawienie starych wartości może mylić, gdy nie będzie nowych a tak widząc 0 będziesz wiedział, że coś nie tak z odczytem.
Teraz na początku pętli uruchamiasz SoftwareSerial ss i zaczynasz gadać z GPSem.
To tak po krótce. Pewnie wymaga to wielu prób, aby działało prawidłowo.
Poczytaj o zasięgu zmiennych, aby lepiej zrozumieć co robisz, pisząc program.
 
Odpowiedź
#17
Tylko na zmienne globalne i stos trzeba mieć miejsce, ciekawe czy te 2kb starczy.. (kodu nie sprawdzałem)..
Arduino zostało wymyślone po to, by robić dobrze jedną prostą rzecz – migać diodą. 
 
Odpowiedź
#18
Nieco poprawiłem kod (nie wiem, czy można to nazwać poprawą). Dodałem przerwanie do pinu 3 od modułu GSM. Gdy będzie zmiana stanu (połączenie przychodzące lub sms) to wykonać ma się procedura wyslij_dane. Program się uruchamia, zapisuje sobie dane na kartę pamięci, w momencie wykonania połączenie de facto przerywa zapis danych ale już smsa nie wysyła.

Kod:
#include "Wire.h"
#include "SD.h"
#include "SoftwareSerial.h"
#include "TinyGPS.h"
#include "DHT.h"
#define DHTTYPE DHT22                        // DHT 22  (AM2302), AM2321
#define DHTPIN A0

const int chipSelect = 10;
File dataFile;
DHT dht(DHTPIN, DHTTYPE); 
TinyGPS gps;

SoftwareSerial ss(6, 7);
SoftwareSerial sgsm(3, 9);
const int pin = 9;
int state = 0;

float gpslat, gpslon;
void setup() 
{
  Serial.begin(115200);
  Serial.print("Initializing SD card...");
  pinMode(chipSelect, OUTPUT);
       sgsm.begin(9600);
  ss.begin(9600);
      dht.begin();

 
  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    while (1) ;
  }
  Serial.println("card initialized.");
 
  // Open up the file we're going to log to!
  dataFile = SD.open("GPStest.txt", FILE_WRITE);
  if (! dataFile) {
    Serial.println("error opening GPStest.txt");
    // Wait forever since we cant write data
    while (1) ;
  } 
}

void loop()                   
{
  bool newData = false;

for (unsigned long start = millis(); millis() - start < 1000;)
  {
    while (ss.available())
    {
      char c = ss.read();
      // Serial.write(c); // uncomment this line if you want to see the GPS data flowing
      if (gps.encode(c)) // Did a new valid sentence come in?
        newData = true;
    }
  }

    if (newData)
  {
    float flat, flon;
    unsigned long age;
    int year;
    byte month, day, hour, minute, second, hundredths;
    gps.f_get_position(&flat, &flon, &age);
     char sz[32];
        float falt = gps.f_altitude();
      Serial.print("");
    Serial.print("Szerokość: ");
    Serial.print(flon == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : flon, 6);
    Serial.print(", ");
    Serial.print("Długośc: ");
    Serial.print(flat == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : flat, 6);
    Serial.print(", ");
    Serial.print("Wysokośc: ");
    Serial.print(falt == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : falt, 2);
    Serial.print(", ");
    dataFile.print("");
    dataFile.print("Szerokosc: ");
    dataFile.print(flon == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : flon, 6);
    dataFile.print(", ");
    dataFile.print("Dlugosc: ");
    dataFile.print(flat == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : flat, 6);
    dataFile.print(", ");
    dataFile.print("Wysokosc: ");
    dataFile.print(falt == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : falt, 2);
    dataFile.print(", ");
    float temperature;                              // Temperature variable
    float DHTh = dht.readHumidity();                // Read DHT sensor
    Serial.print("Wilgotnosc: ");
    Serial.print(DHTh, 2);
    dataFile.print(" Wilgotnosc: ");
    dataFile.print(DHTh, 2);                        // write humidity data to SD card
    dataFile.print("%,");
    float DHTt = dht.readTemperature();             // Read temperature as Celsius (the default)
    Serial.print(" Temperatura: ");
    Serial.println(DHTt, 2);
    dataFile.print(" Temperatura: ");
    dataFile.println(DHTt, 2);                      // write temperature data to SD card and end line
    attachInterrupt(digitalPinToInterrupt(3), wyslij_dane, CHANGE);

        }
     

  dataFile.flush();
  delay(500);
}


void wyslij_dane()
{
      bool newData = false;

for (unsigned long start = millis(); millis() - start < 1000;)
  {
    while (ss.available())
    {
      char c = ss.read();
      // Serial.write(c); // uncomment this line if you want to see the GPS data flowing
      if (gps.encode(c)) // Did a new valid sentence come in?
        newData = true;
    }
  }

    if (newData)
  {

Serial.begin(9600);
sgsm.begin(9600);
  ss.begin(9600);
              Serial.print("AT+CMGF=1\r");

    float flat, flon;
    unsigned long age;
    int year;
    byte month, day, hour, minute, second, hundredths;
    gps.f_get_position(&flat, &flon, &age);
        char sz[32];
        sgsm.print("\r");
      sgsm.print("AT+CMGF=1\r");
            Serial.print("AT+CMGF=1\r");

      /*Replace XXXXXXXXXX to 10 digit mobile number &
        ZZ to 2 digit country code*/
      sgsm.print("AT+CMGS=\"+48790208796\"\r");
      //The text of the message to be sent.
      sgsm.print("Latitude :");
      sgsm.println(flat, 6);
      sgsm.print("Longitude:");
      sgsm.println(flon, 6);
      sgsm.write(0x1A);
      state = 1;
    }
  if (digitalRead(pin) == LOW) {
      state = 0;
    }
}
 
Odpowiedź
#19
przecież ardunio ma tylko 3 piny przerwania 2,3 i 8. I rs232
Arduino zostało wymyślone po to, by robić dobrze jedną prostą rzecz – migać diodą. 
 
Odpowiedź
#20
(19-10-2020, 20:17)Jarewa0606 napisał(a): przecież ardunio ma tylko 3 piny przerwania 2,3 i 8. I rs232

Co mam przez to rozumieć? Zdążyłem przeczytać że w Uno można zadeklarować na pinie 2 i 3 przerwanie. Ale moje pytanie brzmi czy to co napisałem w sekcji wyslij_dane ma sens i czy ma prawo działać?
 
Odpowiedź
  


Skocz do:


Przeglądający: 1 gości