Skocz do zawartości

Problem z programem arduino +nrf24L01


slon2005

Pomocna odpowiedź

Witam, mam problem z dojściem do poprawnego zapisania programu tak żeby działał. Projekt to jedno arduino uno a z nim 3 czujniki ds18b20, jeden dht22 i nrf24l01 które ma wysyłać na około 500m do drugiego arduino uno z nrf24l01, wyświetlaczem oled, oraz syrenką. Syrenka ma się załączyć jak na jednym, wybranym z czujników temperatura spadnie poniżej 2 stopni, do tego przycisk który wyciszy syrenkę na określony czas i możliwość regulacji czasu wyciszenia. Wysyłanie i odbieranie działa dobrze, jeszcze nie wiem czy odległość nadawania i odbioru uzyskam. Problem mam z ustawieniem czasu wyciszenia siedzę już z 3 dni i już mi się wszystko miesza. W obecnej sytuacji próbuję to zrobić z użyciem switch case ale program mi się blokuje po pierwszych kilku odczytach. Do tego nie wszystkie dane są odczytywane z czujników. próbowałem w loop najpierw dać odbieranie sygnałów i póżniej w case dać funkcje wyciszenia i załączenia syrenki, jednak to nie działało więc później próbowałem w loop dać case w nim odbieranie wyświetlanie i if który załączy syrenkę oraz drugi case też z odbieraniem oraz if który będzie wyciszał syrenkę oraz pilnował czasu wyciszenia. Narazie same niepowodzenia, pomożecie?

#include <Bounce2.h>
#include <nRF24L01.h>
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SH110X.h>
Adafruit_SH1106G display = Adafruit_SH1106G(128, 64, &Wire, -1);
RF24 radio(7, 8);
Bounce przycisk = Bounce();
unsigned long aktualnyCzas = 0;
unsigned long zapamietanyCzas = 0;
unsigned long roznicaCzasu = 0;
unsigned long aktualnyCzasWyciszenia = 0;
unsigned long zapamietanyCzasWyciszenia = 0;
unsigned long roznicaCzasuWyciszenia = 0;
unsigned long czasWyciszenia = 10000;
float wyniki[5];
int wyciszenie = 0;

void setup() {
  przycisk.attach(6, INPUT_PULLUP);
  przycisk.interval(10);
  Serial.begin(9600);
  radio.begin();
  radio.openReadingPipe(0, 00001);
  radio.startListening();
  display.begin();
  display.clearDisplay();
  display.setRotation(3);
  display.setTextSize(2);
  display.setTextColor(SH110X_WHITE);
}

void loop() {
  aktualnyCzas = millis();
  roznicaCzasu = aktualnyCzas - zapamietanyCzas;

  if (roznicaCzasu >= 1200UL) {
    zapamietanyCzas = aktualnyCzas;
    Serial.println(aktualnyCzas);
    display.clearDisplay();
    if (radio.available()) {
      radio.read(&wyniki, sizeof(wyniki));
      Serial.println("Alarm aktywny");
      Serial.println("Odczyty : ");
      Serial.print("RH: ");
      Serial.println(wyniki[0]);
      Serial.print("T1: ");
      Serial.println(wyniki[1]);
      Serial.print("T2: ");
      Serial.println(wyniki[2]);
      Serial.print("T3: ");
      Serial.println(wyniki[3]);
      Serial.print("T4: ");
      Serial.println(wyniki[4]);
      display.setTextSize(2);
      display.setCursor(0, 0);
      display.print(wyniki[0]);
      display.println(wyniki[1]);
      display.println(wyniki[2]);
      display.println(wyniki[3]);
      display.println(wyniki[4]);
      display.display();
    }
    if (!radio.available()) {
      Serial.println("Brak sygnału!");
    }
  }
  switch (wyciszenie) {
    case 0:
      if (wyniki[4] < 2) {
        Serial.println("Alarm !");
        digitalWrite(3, HIGH);
      }
      if (wyniki[4] >= 2) {
        digitalWrite(3, LOW);
      }
      if (przycisk.rose()) {
        wyciszenie = 1;
        zapamietanyCzasWyciszenia = millis();
      }
      delay(50);
      break;
    case 1:
      roznicaCzasuWyciszenia = aktualnyCzasWyciszenia - zapamietanyCzasWyciszenia;
      Serial.println("Alarm Wyciszony");
      digitalWrite(3, LOW);
      if (roznicaCzasuWyciszenia >= czasWyciszenia) {
        wyciszenie = 0;
      }
      if (przycisk.rose()) {
        wyciszenie = 0;
      }
      delay(50);
      break;
  }
}
Link do komentarza
Share on other sites

Pół kilometra to kawałek już jest. Lepiej zawsze mniejsza moc i mocniejsza antena, ale żeby było poniżej 20 dBm EIRP (tutaj pewnie nie trzeba na maksa jechać i tak) przy 2,4 Ghz. Coś o WiFi, ale ISM 2,4 to 2,4. Podejrzewam moduł ze wzmacniaczem i 2 dBi patykiem. Racja?

Edytowano przez matsobdev
Link do komentarza
Share on other sites

Następna próba powoduje też "zablokowanie" programu po wyświetleniu pierwszego odczytu z czujników. natomiast jeżeli gubi łączność to daje komunikaty o braku łączności. Kombinowałem na różne sposoby, jak tylko dodam if pod komendami wyświetlania danych z tablicy to już się psuje.

#include <Bounce2.h>
#include <nRF24L01.h>
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SH110X.h>
Adafruit_SH1106G display = Adafruit_SH1106G(128, 64, &Wire, -1);
RF24 radio(7, 8);
Bounce przycisk = Bounce();
unsigned long aktualnyCzas = 0;
unsigned long zapamietanyCzas = 0;
unsigned long roznicaCzasu = 0;
unsigned long aktualnyCzasWyciszenia = 0;
unsigned long zapamietanyCzasWyciszenia = 0;
unsigned long roznicaCzasuWyciszenia = 0;
unsigned long czasWyciszenia = 5000;
float wyniki[5];
int wyciszenie = 0;
String tryb;
void setup() {
  przycisk.attach(6, INPUT_PULLUP);
  przycisk.interval(10);
  Serial.begin(9600);
  radio.begin();
  radio.openReadingPipe(0, 00001);
  radio.startListening();
  display.begin();
  display.clearDisplay();
  display.setRotation(3);
  display.setTextSize(2);
  display.setTextColor(SH110X_WHITE);
}

void loop() {
  aktualnyCzas = millis();
  roznicaCzasu = aktualnyCzas - zapamietanyCzas;
  aktualnyCzasWyciszenia = millis();
  roznicaCzasuWyciszenia = aktualnyCzasWyciszenia - zapamietanyCzasWyciszenia;
  if (roznicaCzasu >= 1200UL) {
    zapamietanyCzas = aktualnyCzas;
    Serial.println(aktualnyCzas);
    display.clearDisplay();
    if (radio.available()) {
      radio.read(&wyniki, sizeof(wyniki));
      Serial.println(tryb);
      Serial.println("Odczyty : ");
      Serial.print("RH: ");
      Serial.println(wyniki[0]);
      Serial.print("T1: ");
      Serial.println(wyniki[1]);
      Serial.print("T2: ");
      Serial.println(wyniki[2]);
      Serial.print("T3: ");
      Serial.println(wyniki[3]);
      Serial.print("T4: ");
      Serial.println(wyniki[4]);
      display.setTextSize(2);
      display.setCursor(0, 0);
      display.print(wyniki[0]);
      display.println(wyniki[1]);
      display.println(wyniki[2]);
      display.println(wyniki[3]);
      display.println(wyniki[4]);
      display.setTextSize(1);
      display.println(tryb);
      display.display();
    }
  }
  if (wyniki[4] < 2 && wyciszenie == 0) {
    Serial.println("Alarm !");
    digitalWrite(3, HIGH);
    wyciszenie = 0;
  }
  if (wyniki[4] >= 2 && wyciszenie == 0) {
    digitalWrite(3, LOW);
  }
  if (przycisk.rose() && wyciszenie == 0) {
    wyciszenie = 1;
    zapamietanyCzasWyciszenia = millis();
  }
  if (przycisk.rose() && wyciszenie == 1) {
    wyciszenie = 0;
  }
  if (roznicaCzasuWyciszenia >= czasWyciszenia) {
    wyciszenie = 0;
  }
  if (wyciszenie = 0) {
    tryb = "Alarm aktywny";
  }
  if (wyniki[4] < 2 && wyciszenie == 0) {
    tryb = "Alarm ! ! !";
  }
  if (wyciszenie == 1) {
    tryb = "Alarm Wyciszony";
  }

  if (!radio.available()) {
    Serial.println("Brak sygnału!");
  }
}

 

Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

Pytanie pierwsze: czy nadajnik zawsze wydziela z siebie komunikat o długości sizeof(wyniki)? Bo jeśli nie, to może być lipa. O tego masz fafnascie parametrów dla nrf-a żeby długość odbieranego komunikatu była taka sama, jak nadanego.

Pytanie drugie: jeśli read.available zwraca coś pozytywnego, niby dlaczego następne wywołanie zwracające zero jest uznane za błąd?

Czy nadajnik w ogóle wie, że komunikat został odebrany? Z tego co widzę to chyba niespecjalnie...

Link do komentarza
Share on other sites

@ethanak Ogólnie to wszystko działa poprawnie do póki nie zacznę dopisywać warunków które piszę z zamiarem wyciszania syrenki. W nadajniku kod wygląda tak:

#include <OneWire.h>
#include <DS18B20.h>
#include <SPI.h>
#include "DHT.h"
#include <nRF24L01.h>
#include <RF24.h>
RF24 myRF24 (7, 8); 
DHT dht(2, DHT22);
OneWire onewire(5);
DS18B20 sensors(&onewire);
byte address1[8] = {0x28, 0xB4, 0x43, 0xED, 0x5C, 0x21, 0x1, 0x2D};
byte address2[8] = {0x28, 0x2A, 0x90, 0xD2, 0x5C, 0x21, 0x1, 0x4D};
byte address3[8] = {0x28, 0x19, 0xBC, 0xB9, 0X5C, 0x21, 0x1, 0x24};
float wyniki[5];
unsigned long last;
void setup() {
  Serial.begin(9600);
  dht.begin();
  sensors.begin();
  myRF24.begin();
  myRF24.openWritingPipe(00001);  
}
void loop() {
  if (sensors.available() && millis() - last > 1000UL) { 
   sensors.request(address1);
   sensors.request(address2);                
   sensors.request(address3);
   wyniki[2] = sensors.readTemperature(address1);
   wyniki[3] = sensors.readTemperature(address2);
   wyniki[4] = sensors.readTemperature(address3);
   wyniki[0] = dht.readHumidity();
   wyniki[1] = dht.readTemperature();
   myRF24.write(wyniki, sizeof(wyniki)); 
   last = millis();
  }
}

Bez dopisanych warunków które miały by wyciszać syrenkę odczyty są co 1200ms i syrenka załącza się poniżej zadanej wartości a powyżej wyłącza. Za pierwszym razem zamiast millis używałem delaya, jednak podczas próby wyciszania pojawił się problem że trzeba było klawisz trzymać przez dwa przejścia pętli loop, więc pomyślałem że na millis będzie lepiej. Jednak każda próba dopisania warunków wyciszających syrenkę i określających czas w porcie szeregowym kończy się jednym odczytem i później jak by program stał. Jak wyłączę nadajnik to zwraca mi awarię, a później znowu jeden odczyt i stoi.

Link do komentarza
Share on other sites

@slon2005 strasznit ten kod pokręcony (mówię o odbiorniku).

Po pierwsze, brak przycisk.update() w loop, czyli możesz sobie przyciskać ile chcesz a program nie będzie o tym wiedział.

Po drugie, wyjaśnij jak to ma działać bo nie rozumiem (w skrócie Twój kod):

if (radio.available()) {
  radio.read(coś tam); // wyczyszczebnie bufora
}
if (!radio.available()) {
  // nadajnik nie działa?
}

 

Przecież w tej sytuacji będziesz dostawał komunikat o niedziałaniu nadajnika cały czas...

Robiłem coś podobnego, mniej więcej tak:

void loop()
{
  if (radio.available()) {
    lastRadio = millis();
    nadajnik_dziala = true;
    radio.read()// i tak dalej, coś robie z tym co odebrałem
  }
  ...
  if (nadajnik_dziala %% millis() - lastRadio > 1000UL) {
    nadajnik_dzala = false;
    printf("Nadajnik zdechł\n");
  }
  digitalWrite(GREEN_LED, nadajnik_dziala);
  
    
    

No i oczywiście ustawione 

:

// w setup w odbiorniku
radio.setAutoAck(1);
radio.setPayLoadSize(sizeof(moje_dane);
                  
// setup w nadajniku
radio.setPayLoadSize(sizeof(moje_dane);
radio.setRetries(15,15);

 

  • Lubię! 1
Link do komentarza
Share on other sites

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Anonim
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.

×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.