• 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
Problem z kodem do stacji meteo
#1
Witam.

Mam problem z kodem do stacji meteo mierzącej wilgotność, temperaturę oraz zanieczyszczenie powietrza w cząstkach PM2.5 i PM10.
Stacja składa się z nadajnika i odbiornika. Do nadajnika czyli do arduino nano są podłączone czujniki: DHT22 i PMS7003 oraz moduł transmisji radiowej NRF24L01, a do odbiornika czyli arduino nano jest podłączony moduł NRF24L01 i wyświetlacz, na którym są wyświetlone dane przesłane przez nadajnik. Problem tkwi w tym, że dane z DHT22 są wyświetlane normalnie na wyświetlaczu, a dane z PMS7003 przybierają wartość 0. Czujnik PMS7003 był sprawdzany przykładem z biblioteki przy aktualnym podłączeniu czujnika.
Dlatego prosiłbym o pomoc i sprawdzenie kodu.

Biblioteka PMS7003:https://github.com/fu-hsi/PMS

Kod-Nadajnik
Kod:
#include <nRF24L01.h>
#include <printf.h>
#include <RF24.h>
#include <RF24_config.h>
#include <DHT.h>
#include "PMS.h"

#define DHTPIN 5               
#define DHTTYPE DHT22         
DHT dht(DHTPIN, DHTTYPE);

PMS pms(Serial);
PMS::DATA data2;


RF24 transmit (7,8);                           
byte address [5] = "00001";                    

struct package
  {
    int temperature = 0;
    int humidity = 0;
    int PM25 = 0;
    int PM10 = 0;
  };

typedef struct package Package;
Package data;

void setup() {
  dht.begin();
  transmit.begin();
  transmit.openWritingPipe(address);           
  transmit.setPALevel(RF24_PA_MAX);            
  transmit.setDataRate(RF24_250KBPS);          
  transmit.setChannel(100);                    
  transmit.stopListening();
  Serial.begin(9600);
  }

void loop() {
  data.temperature = dht.readTemperature();
  data.humidity = dht.readHumidity();
  data.PM25 = (data2.PM_AE_UG_2_5);
  data.PM10 = (data2.PM_AE_UG_10_0);
  pms.requestRead();
  transmit.write(&data,sizeof(data));
  delay(1000);                                
}

Kod-Odbiornik
Kod:
#include <LiquidCrystal_I2C.h>
#include <nRF24L01.h>
#include <printf.h>
#include <RF24.h>
#include <RF24_config.h>
#include <Timers.h>


RF24 receive (7,8);                       
byte address [5] = "00001";              
LiquidCrystal_I2C lcd(0x27, 16, 2);



struct package
  {
    int temperature = 0;
    int humidity = 0;
    int PM25 = 0;
    int PM10 = 0;
  };

typedef struct package Package;
Package data;

void setup() {
  lcd.begin();
  lcd.backlight();
  lcd.setCursor(0,0);
  lcd.print("Otrzymane dane");
  receive.begin();
  receive.openReadingPipe(0,address);    
  receive.setPALevel(RF24_PA_MIN);      
  receive.setDataRate(RF24_250KBPS);    
  receive.setChannel(100);              
  receive.startListening();               
  }

void loop() {

  if (receive.available())               
  {
    receive.read(&data, sizeof(data));
    lcd.setCursor(0,0);
    lcd.print(data.temperature);
    lcd.print("C  ");
    lcd.print(data.humidity);
    lcd.print("%");
    lcd.setCursor(0,1);
    lcd.print(data.PM25);
    lcd.print("ug/m3  ");
    lcd.print(data.PM10);
    lcd.print("ug/m3");
   
  }
  delay(5000);
  lcd.clear();
}
 
Odpowiedź
#2
Skoro sprawdziłeś odczyt z czujnika i działa, to teraz sprawdź jak dane są przesyłane, np. zamiast przesyłać rzeczywistą zmienną to wymyśl sobie zmienna++ i 100+zmienna1++, i je wysyłaj co sekundę. Będziesz widział czy są przesyłane prawidłowo. Ten czujnik nie zwraca jakiegoś floata?
No i zająłeś sprzętowy UART na odczyt czujnika, ale zawsze możesz sobie zrobić jakiś softowy na wolnym pinie tylko do wysyłania danych i lokalnie obserwować czy w końcowym programie również odczyty są prawidłowe.
 
Odpowiedź
#3
(07-08-2019, 22:13)kaczakat napisał(a): Skoro sprawdziłeś odczyt z czujnika i działa, to teraz sprawdź jak dane są przesyłane, np. zamiast przesyłać rzeczywistą zmienną to wymyśl sobie zmienna++ i 100+zmienna1++, i je wysyłaj co sekundę. Będziesz widział czy są przesyłane prawidłowo. Ten czujnik nie zwraca jakiegoś floata?
No i zająłeś sprzętowy  UART na odczyt czujnika, ale zawsze możesz sobie zrobić jakiś softowy na wolnym pinie tylko do wysyłania danych i lokalnie obserwować czy w końcowym programie również odczyty są prawidłowe.
Sprawdziłem odczyty ze zmienną ++ i wiadomo że liczba nie dodawała się co 1 ale to przez delay, jednak wynik był widoczny na wyświetlaczu. O Softwareowym UART to ja nie pomyślałem, spróbuję i zobaczę jak to wyjdzie Big Grin.
 
Odpowiedź
#4
W odbiorniku nie powinieneś mieć żadnego delaya.
Jeśli masz nowe dane:
-odbierasz,
-czyścisz ekran,
-wyświetlasz,
-nasłuchujesz nowych danych.
W nadajniku jest to obojętne jak zaplanujesz kiedy wysyłasz, delay na pierwsze testy też jest OK, ale odbiornik powinien być gotowy na akcję zawsze.
 
Odpowiedź
#5
(08-08-2019, 15:12)kaczakat napisał(a): W odbiorniku nie powinieneś mieć żadnego delaya.
Jeśli masz nowe dane:
-odbierasz,
-czyścisz ekran,
-wyświetlasz,
-nasłuchujesz nowych danych.
W nadajniku jest to obojętne jak zaplanujesz kiedy wysyłasz, delay na pierwsze testy też jest OK, ale odbiornik powinien być gotowy na akcję zawsze.
Kod:
#include <LiquidCrystal_I2C.h>
#include <nRF24L01.h>
#include <printf.h>
#include <RF24.h>
#include <RF24_config.h>
#include <Timers.h>

Timer Timer1;

RF24 receive (7,8);                       
byte address [5] = "00001";              
LiquidCrystal_I2C lcd(0x27, 16, 2);



struct package
  {
    int temperature = 0;
    int humidity = 0;
    int PM25 = 0;
    int PM10 = 0;
  };

typedef struct package Package;
Package data;

void setup() {
  lcd.begin();
  lcd.backlight();
  lcd.setCursor(0,0);
  lcd.print("Otrzymane dane");
  receive.begin();
  receive.openReadingPipe(0,address);    
  receive.setPALevel(RF24_PA_MIN);      
  receive.setDataRate(RF24_250KBPS);    
  receive.setChannel(100);              
  receive.startListening();
  Timer1.begin(SECS(10));              
  }

void loop() {
    if(Timer1.available())
{
  lcd.clear();
  delay(1);
  Timer1.restart();
}
  if (receive.available())               
  {
    receive.read(&data, sizeof(data));
    lcd.setCursor(0,0);
    lcd.print(data.temperature);
    lcd.print("C  ");
    lcd.print(data.humidity);
    lcd.print("%");
    lcd.setCursor(0,1);
    lcd.print(data.PM25);
    lcd.print("ug/m3  ");
    lcd.print(data.PM10);
    lcd.print("ug/m3");
   
  }
}
Poprawiłem kod odbiornika, jednak dane z czujnika PMS7003 nie wyświetlają się w dalszym ciągu.
 
Odpowiedź
#6
(08-08-2019, 15:12)kaczakat napisał(a): W odbiorniku nie powinieneś mieć żadnego delaya.
Jeśli masz nowe dane:
-odbierasz,
-czyścisz ekran,
-wyświetlasz,
-nasłuchujesz nowych danych.
W nadajniku jest to obojętne jak zaplanujesz kiedy wysyłasz, delay na pierwsze testy też jest OK, ale odbiornik powinien być gotowy na akcję zawsze.
Kod:
#include <nRF24L01.h>
#include <printf.h>
#include <RF24.h>
#include <RF24_config.h>
#include <DHT.h>
#include "PMS.h"
#include <SoftwareSerial.h>

SoftwareSerial Serial2(10, 11);

PMS pms(Serial2);
PMS::DATA data2;

#define DHTPIN 5                // do not connect to pin 0 or pin 1
#define DHTTYPE DHT22          // Define DHT11 module
DHT dht(DHTPIN, DHTTYPE);//create DHT object called dht


RF24 transmit (7,8);                            //create RF24 object called transmit
byte address [5] = "00001";                     //set address to 00001

struct package
  {
    int temperature = 0;
    int humidity = 0;
    int PM25 = 0;
    int PM10 = 0;
  };

typedef struct package Package;
Package data;

void setup() {
 
  Serial2.begin(9600);
  Serial.begin(57600);
 
  dht.begin();
  transmit.begin();
  transmit.openWritingPipe(address);            //open writing pipe to address 00001
  transmit.setPALevel(RF24_PA_MAX);             //set RF power output to maximum
  transmit.setDataRate(RF24_250KBPS);           //set datarate to 250kbps
  transmit.setChannel(100);                     //set frequency to channel 100
  transmit.stopListening();

  }

void loop() {

    if (pms.read(data2))
  {

    Serial.print("PM 2.5 (ug/m3): ");
    Serial.println(data2.PM_AE_UG_2_5);

    Serial.print("PM 10.0 (ug/m3): ");
    Serial.println(data2.PM_AE_UG_10_0);

    Serial.println();
  }
  data.temperature = dht.readTemperature();
  data.humidity = dht.readHumidity();
  data.PM25 = (data2.PM_AE_UG_2_5);
  data.PM10 = (data2.PM_AE_UG_10_0);
  pms.requestRead();
  transmit.write(&data,sizeof(data));
  delay(1000);                                 
}
Dopisałem do odbiornika wyświetlanie danych na serial monitorze i podłączyłem czujnik przez softwareserial, w tym przypadku na serial monitorze nie pojawia się kompletnie nic.
Kod:
#include "PMS.h"
#include <SoftwareSerial.h>

SoftwareSerial Serial2(10, 11);

PMS pms(Serial2);
PMS::DATA data2;

void setup()
{
  Serial.begin(57600);   // GPIO1, GPIO3 (TX/RX pin on ESP-12E Development Board)
  Serial2.begin(9600);  // GPIO2 (D4 pin on ESP-12E Development Board)
}

void loop()
{
  if (pms.read(data2))
  {
    Serial.print("PM 1.0 (ug/m3): ");
    Serial.println(data2.PM_AE_UG_1_0);

    Serial.print("PM 2.5 (ug/m3): ");
    Serial.println(data2.PM_AE_UG_2_5);

    Serial.print("PM 10.0 (ug/m3): ");
    Serial.println(data2.PM_AE_UG_10_0);

    Serial.println();
  }

  // Do other stuff...
}
Tu jest zmodyfikowany przeze mnie przykład z podłączonym czujnikiem przez soft serial i o dziwo wyniki pomiaru pojawiają się na serial monitorze.
 
Odpowiedź
#7
Zacząłem usuwać linijki kodu po stronie nadajnika i dane z czujnika PMS7003 zaczęły się pojawiać po usunięciu tych linijek, a dokładnie linii z void setup odpowiedzialnych za obsługę modułu nrf24l01
Kod:
  transmit.begin();
  transmit.openWritingPipe(address);           
  transmit.setPALevel(RF24_PA_MAX);           
  transmit.setDataRate(RF24_250KBPS);           
  transmit.setChannel(100);                   
  transmit.stopListening();
Czym może być to spowodowane?
 
Odpowiedź
#8
Może jednak Twoje moduły nie mają wystarczającej mocy zasilania
transmit.setPALevel(RF24_PA_MAX); ja dodaję zamiast tego transmit.setPALevel(RF24_PA_MIN);
Na min działa zazwyczaj bez kondensatora.
transmit.setDataRate(RF24_250KBPS); tego nie używam, więc wartość domyślna.
 
Odpowiedź
#9
(09-08-2019, 12:16)kaczakat napisał(a): Może jednak Twoje moduły nie mają wystarczającej mocy zasilania
transmit.setPALevel(RF24_PA_MAX);    ja dodaję zamiast tego transmit.setPALevel(RF24_PA_MIN); 
Na min działa  zazwyczaj bez kondensatora.           
  transmit.setDataRate(RF24_250KBPS);        tego nie używam, więc wartość domyślna.
Nawet jeśli odłączę nrf24 zostawiając linijki obsługujące ten moduł to i tak jest ten sam problem, brak danych z PMS7003 na serialu. Może biblioteka nrf24l01 koliduje z PMS7003. To samo jest gdy usunę linijkę odpowiedzialną za prędkość transmisji i ustawię moc transmisji na minimum Confused .
 
Odpowiedź
#10
Jeśli odłączasz jakiś moduł to być może wisi na etapie inicjalizacji czekając na konkretną odpowiedź. Jak coś testujesz to powinieneś mieć komunikat wysyłany co 1s na UART np. ze zmienną++, jakiś migający led w loop, coś co pozwala stwierdzić, że program ruszył i działa, nawet jeśli nie dogaduje się z jakimś konkretnym podzespołem.
PMS korzysta z UART, NRF z SPI, DHT to albo jakiś dziki 1-wire albo coś ala i2c albo i2c. Ciężko tu zrobić jakiś konflikt. O DTH słyszałem, że lubi się zawiesić i wysyła jakieś głupoty aż do odłączenia zasilania, że warto go zasilić z pinu IO i co jakiś czas zapobiegawczo odłączyć. Sprawdź też jak często możesz czytać wskazania z tych czujników, nie wiem jak PMS ale co 1s dla DHT to może być za często, na pewno się podgrzewa co zmienia wskazania i temperatury i RH, nie wiem co tam mierzysz, ale czujnik nadaje się co najwyżej do WC lub pogody, a tu pomiar raz na minutę to świat. Oczywiście zamiast delay trzeba użyć millis() by odmierzać sobie czasy między pomiarami.
 
Odpowiedź
  


Skocz do:


Przeglądający: 1 gości