Skocz do zawartości

DS18b20 z ILI9341 SPI 240x320


Y0ogi

Pomocna odpowiedź

Witam. Czy jest mi ktoś w stanie pomóc ogarnąć kod do odczytu DS18B20 ( na zasilaniu pasożytniczym ) na wyświetlaczu 2.8" SPI TFT ILI9341 240x320. Niestety szukałem gdzie sie da jakiś informacji jak zrobić taki odczyt temperatury, wielokrotnie próbowałem napisać go samodzielnie na podstawie innych programów które odczytują temperatury z innych czujników na tym wyświetlaczu. Niestety wszystkie te próby kończyły sie niepowodzeniem, dlatego zwracam sie o pomoc tutaj, może jest osoba która jest w stanie pomóc przy tym kodzie.

Edytowano przez Y0ogi
Link do komentarza
Share on other sites

9 godzin temu, Gieneq napisał:

@Y0ogi witam na forum 🙂 

Nie sprecyzowałeś na co chcesz napisać ten program.

Tak, przepraszam zapomniałem o najważniejszym. Program chciał bym napisać na Arduino uno lub nano 🙂

Link do komentarza
Share on other sites

19 godzin temu, Y0ogi napisał:

Niestety wszystkie te próby kończyły sie niepowodzeniem,

Jakie próby? Odczytu temperatury przy pomocy Arduino i czujnika, czy wyświetlenia odczytanych wartości na ekranie tft?

Edytowano przez SOYER
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

Przed chwilą, SOYER napisał:

Jakie próby? Odczytu temperatury przy pomocy Arduino i czujnika, czy wyświetlenia odczytanych wartości na ekranie?

wyświetlenia odczytu na wyświetlaczu

Link do komentarza
Share on other sites

(edytowany)
#include <SPI.h>
#include "Adafruit_ILI9341.h"
#include "Adafruit_GFX.h"
#include <OneWire.h>  //odpowiada za komunikację za pomocą protokołu 1-Wire
#include <DallasTemperature.h>  //Biblioteka ze wszystkimi funkcjami czujnika DS18B20

// Numer pinu do którego podłaczasz czujnik
#define ONEWIRE_PIN 2 //W definicji o nazwie ONEWIRE_PIN przechowywany jest numer
                      //pinu do którego podłączasz wyjście danych DQ z czujników.


// Adres czujnika
byte address[8] = {0x28, 0xB1, 0x6D, 0xA1, 0x3, 0x0, 0x0, 0x11}; //W tablicy address przechowywany jest adres czujnika z którego chcesz odczytywać
                                                                 //temperaturę. Tu musisz wpisać adres twojego czujnika.


                                                                 
OneWire onewire(ONEWIRE_PIN); //Deklaruje obiekt onewire odpowiedzialny za komunikację za pomocą protokołu 1-Wire.
                              //W argumencie konstruktora podajesz numer pinu do którego podłaczone są urządzenia magistrali 1-Wire.

DallasTemperature sensors(&onewire); //Deklaruje obiekt sensors odpowiedzialny za obsługę czujników DS18B20.
                           //W argumecie konstruktora przekazywany jest wskaźnik do obiektu magistrali 1-Wire do której podłączony jest termometr.

DeviceAddress sensor1;                           

// Definicje Kolorów
#define WHITE 0xFFFF
#define BLACK 0x0000
#define BLUE 0x001F
#define RED 0xF800
#define GREEN 0x07E0
#define CYAN 0x07FF
#define MAGENTA 0xF81F
#define YELLOW 0xFFE0


   
#define TFT_DC 9              
#define TFT_CS 10             
#define TFT_RST 8             
#define TFT_MISO 12           
#define TFT_MOSI 11           
#define TFT_CLK 13


void setup() {
Serial.begin(9600);
sensors.begin();
delay(500);
tft.begin();
tft.fillScreen(ILI9341_BLACK);

}

void loop(){
// Get temperature
sensors.requestTemperatures();
Serial.println(sensors.getTempCByIndex(0));
testText();
}

unsigned long testText() {
//tft.clearScreen();
  tft.setCursor(30, 40);
  tft.setTextColor(BLACK,BLUE);
  tft.setTextSize(1);
  tft.println("Temperatura");
  tft.setTextSize(3);
  tft.setCursor(20, 63);
  tft.println(sensors.getTempCByIndex(0));
}

 

Chce tylko dodać że jestem początkującym w tego typu sprawach. Jeśli coś jest zle lub czegoś nie powinno być/ czegoś nie ma to proszę o krótkie wyjaśnienie dlaczego tak a nie inaczej  jesli jest taka możliwość.

Edytowano przez Y0ogi
Link do komentarza
Share on other sites

Wiem, że pytanie dotyczyło przede wszystkich wyświetlacza. Ja pozwolę sobie dodać informacje na temat DS18B20.

Program jest identyczny, obojętnie jaki jest sposób podłączenia, tj. standardowe z trzema przewodami lub pasożytnicze z dwoma. Jesteś w stanie jedynie odczytać, co wykrywa sieć 1 wire za pomocą isParasitePowerMode(void). 

Adresy nadane poszczególnym czujnikom możesz odczytać za pomocą funkcji getAddress(DeviceAddress* adres, int index). Podając indeks (numerowany od 0), funkcja zapisuje w tablicy adres czujnika. Nie jest on jednak niezbędnie potrzebny, możesz posługiwać się wyłącznie indeksami. Posiadając adres, możesz jedynie sprawdzić przed odczytem, czy czujnik nadal znajduje się na sieci. Jeśli funkcja isConnected(DeviceAddress adres) zwraca 0, czujnik o podanym adresie nie został znaleziony na sieci.  Posługując się adresem, odczytujesz pomiar za pomocą funkcji getTempC(DeviceAddress adres). Równie dobrze możesz zastosować indeks, stosując getTempCByIndex(int index). 

W zaprezentowanym programie odczyt temperatury powoduje zablokowanie procesora. Do czasu zakończenia konwersji wykonywanie programu jest blokowane (czas konwersji zależy od ustawionej rozdzielczości i wynosi od kilkuset ms do ok. 1 sekundy). Jesteś w stanie to wyłączyć, stosując funkcję setWaitForConversion(LOW). Wówczas po stronie programisty pozostaje, aby zachować odpowiedni czas od wywołania funkcji requestTemperatures() (inicjującej konwersję) a getTempCByIndex(0) (zwracającej odczytaną temperaturę). W tym przypadku program prezentowałby się mniej więcej tak:

unsigned long convertionTime = 1000;
unsigned long lastTime = 0;
float temperature;

void loop()
{
if ( millis() - lastTime > conversionTime)
 {
  // odczyt temperatury z czujnika o indeksie 0
  temperature = sensors.getTempCByIndex(0);
  // zadanie ponownej konwersji temperatury	
  sensors.requestTemperatures();                    
  lastTime = millis();   
 }
 // pozostaly program, ktorego wykonanie nie jest blokowane na czas konwersji ds18b20
}

 

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

(edytowany)
31 minut temu, opp34 napisał:

Wiem, że pytanie dotyczyło przede wszystkich wyświetlacza. Ja pozwolę sobie dodać informacje na temat DS18B20.

Program jest identyczny, obojętnie jaki jest sposób podłączenia, tj. standardowe z trzema przewodami lub pasożytnicze z dwoma. Jesteś w stanie jedynie odczytać, co wykrywa sieć 1 wire za pomocą isParasitePowerMode(void). 

Adresy nadane poszczególnym czujnikom możesz odczytać za pomocą funkcji getAddress(DeviceAddress* adres, int index). Podając indeks (numerowany od 0), funkcja zapisuje w tablicy adres czujnika. Nie jest on jednak niezbędnie potrzebny, możesz posługiwać się wyłącznie indeksami. Posiadając adres, możesz jedynie sprawdzić przed odczytem, czy czujnik nadal znajduje się na sieci. Jeśli funkcja isConnected(DeviceAddress adres) zwraca 0, czujnik o podanym adresie nie został znaleziony na sieci.  Posługując się adresem, odczytujesz pomiar za pomocą funkcji getTempC(DeviceAddress adres). Równie dobrze możesz zastosować indeks, stosując getTempCByIndex(int index). 

W zaprezentowanym programie odczyt temperatury powoduje zablokowanie procesora. Do czasu zakończenia konwersji wykonywanie programu jest blokowane (czas konwersji zależy od ustawionej rozdzielczości i wynosi od kilkuset ms do ok. 1 sekundy). Jesteś w stanie to wyłączyć, stosując funkcję setWaitForConversion(LOW). Wówczas po stronie programisty pozostaje, aby zachować odpowiedni czas od wywołania funkcji requestTemperatures() (inicjującej konwersję) a getTempCByIndex(0) (zwracającej odczytaną temperaturę). W tym przypadku program prezentowałby się mniej więcej tak:




unsigned long convertionTime = 1000;
unsigned long lastTime = 0;
float temperature;

void loop()
{
if ( millis() - lastTime > conversionTime)
 {
  // odczyt temperatury z czujnika o indeksie 0
  temperature = sensors.getTempCByIndex(0);
  // zadanie ponownej konwersji temperatury	
  sensors.requestTemperatures();                    
  lastTime = millis();   
 }
 // pozostaly program, ktorego wykonanie nie jest blokowane na czas konwersji ds18b20
}

 

W takim razie jak powinien wyglądać kod z twoimi zmianami biorąc pod uwagę tego aby program przed uruchomieniem sie brał pod uwagę to czy czujnik znajduje sie w sieci 1 wire i mimo to dalej sie odpalał. Nie ukrywam też że jest tu trochę linijek z kilku innych kodów. dlatego mogą być tutaj napisane głupoty dla innych oczywiste.

Edytowano przez Y0ogi
Link do komentarza
Share on other sites

Poniżej znajduje się program, który odczytuje pomiar z jednego czujnika DS18B20. Program teoretycznie powinien działać, tym niemniej zaznaczam, że go nie testowałem - przeniosłem fragmenty z innego funkcjonującego projektu. Kod się kompiluje.

W setupie sieć 1 wire jest inicjalizowana, odczytywany jest adres czujnika o indeksie 0 oraz ustawiana jest jego rozdzielczość. Potem w loop jest odmierzany czas od ostatniego odczytu, a jeśli przekroczył on ustawiony czas trwania konwersji, wówczas program sprawdza, czy czujnik o podanym adresie znajduje się na sieci. Jeśli tak, następuje odczyt temperatury oraz rozpoczęcie konwersji. 

// pliki naglowkowe
#include <OneWire.h>
#include <DallasTemperature.h>

// definicje pinow
#define ONEWIRE_PIN 2       // numer pinu, do ktorego podlaczona jest siec 1 wire 

#define SENSOR_RES  12      // rozdzielczosc pomiaru czujnikow ds18b20 (9, 10, 11 lub 12 bit)

// interfejs sieci 1 wire
OneWire one_wire(ONEWIRE_PIN);
DallasTemperature ds18s20_net(&one_wire);

// struktura przechowujaca dane z pojedynczego czujnika
struct SENSOR
{
  uint8_t bus_address[8];
  float value;
  int8_t fault;
};

struct SENSOR sensors;
unsigned long conversionTime = 2000;
unsigned long lastTime = 0;


void setup() {
  // inicjalizacja sieci one wire
  ds18s20_net.begin();

  // odczyt adresow na podstawie podanego indeksu czujnika
  // indeksy sa nadawane automatycznie, poczawszy od 0
  ds18s20_net.getAddress(sensors.bus_address, 0);
  // ustawienie rozdzielczosci
  ds18s20_net.setResolution(sensors.bus_address, SENSOR_RES);
    
  lastTime = millis();
}

void loop() {
  if ( millis() - lastTime > conversionTime)
  {
    // sprawdzanie, czy czujnik znajduje sie na sieci
    if (ds18s20_net.getAddress(sensors.bus_address, 0) == 0)
    {
      // blad czujnika
      sensors.fault = 1;
    }
    else
    {
      // brak bledu czujnika
      sensors.fault = 0;

      // odczyt temperatury z czujnika o indeksie 0
      sensors.value = ds18s20_net.getTempCByIndex(0);
      // oczekiwanie na zakonczenie konwersji jest przeprowadzane przy uzyciu timera
      ds18s20_net.setWaitForConversion(LOW);
      // zadanie ponownej konwersji temperatury
      ds18s20_net.requestTemperatures();
      lastTime = millis();
    }
  }

  // przestrzen na pozostala czesc programu, np. obsluge wyswietlacza
}

 

 

  • Pomogłeś! 1
Link do komentarza
Share on other sites

17 minut temu, opp34 napisał:

Poniżej znajduje się program, który odczytuje pomiar z jednego czujnika DS18B20. Program teoretycznie powinien działać, tym niemniej zaznaczam, że go nie testowałem - przeniosłem fragmenty z innego funkcjonującego projektu. Kod się kompiluje.

W setupie sieć 1 wire jest inicjalizowana, odczytywany jest adres czujnika o indeksie 0 oraz ustawiana jest jego rozdzielczość. Potem w loop jest odmierzany czas od ostatniego odczytu, a jeśli przekroczył on ustawiony czas trwania konwersji, wówczas program sprawdza, czy czujnik o podanym adresie znajduje się na sieci. Jeśli tak, następuje odczyt temperatury oraz rozpoczęcie konwersji. 


// pliki naglowkowe
#include <OneWire.h>
#include <DallasTemperature.h>

// definicje pinow
#define ONEWIRE_PIN 2       // numer pinu, do ktorego podlaczona jest siec 1 wire 

#define SENSOR_RES  12      // rozdzielczosc pomiaru czujnikow ds18b20 (9, 10, 11 lub 12 bit)

// interfejs sieci 1 wire
OneWire one_wire(ONEWIRE_PIN);
DallasTemperature ds18s20_net(&one_wire);

// struktura przechowujaca dane z pojedynczego czujnika
struct SENSOR
{
  uint8_t bus_address[8];
  float value;
  int8_t fault;
};

struct SENSOR sensors;
unsigned long conversionTime = 2000;
unsigned long lastTime = 0;


void setup() {
  // inicjalizacja sieci one wire
  ds18s20_net.begin();

  // odczyt adresow na podstawie podanego indeksu czujnika
  // indeksy sa nadawane automatycznie, poczawszy od 0
  ds18s20_net.getAddress(sensors.bus_address, 0);
  // ustawienie rozdzielczosci
  ds18s20_net.setResolution(sensors.bus_address, SENSOR_RES);
    
  lastTime = millis();
}

void loop() {
  if ( millis() - lastTime > conversionTime)
  {
    // sprawdzanie, czy czujnik znajduje sie na sieci
    if (ds18s20_net.getAddress(sensors.bus_address, 0) == 0)
    {
      // blad czujnika
      sensors.fault = 1;
    }
    else
    {
      // brak bledu czujnika
      sensors.fault = 0;

      // odczyt temperatury z czujnika o indeksie 0
      sensors.value = ds18s20_net.getTempCByIndex(0);
      // oczekiwanie na zakonczenie konwersji jest przeprowadzane przy uzyciu timera
      ds18s20_net.setWaitForConversion(LOW);
      // zadanie ponownej konwersji temperatury
      ds18s20_net.requestTemperatures();
      lastTime = millis();
    }
  }

  // przestrzen na pozostala czesc programu, np. obsluge wyswietlacza
}

 

 

Dziękuję ci bardzo, za poświęcony czas i dokładne objaśnienie jak powinno to wyglądać.

Link do komentarza
Share on other sites

Daj znać, jeśli będą trudności z DS18B20 lub na przykład będziesz potrzebował obsłużyć więcej niż jeden czujnik. Na temat wyświetlacza się nie wypowiem, bo tego typu sprzęt nie stosowałem od dawien dawna i mógłbym tylko wprowadzić w błąd. Jedynie znalazłem ten opis. Wynika z niego, że wyświetlacz pracuje z logiką 3.3V (nie tylko zasilanie, ale też przesyłane sygnały) a arduino z logiką 5V (jeśli ustawisz wyjście w stan wysoki i zmierzysz napięcie, powinno ono wynosić około 5V). Autor wpisu zastosował najprostszą technikę, to znaczy dzielniki napięcia. Innym rozwiązaniem jest konwerter poziomów logicznych, np. tego typu płytka.  

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

(edytowany)
Serial.begin(9600); 
 Serial.println();

Dodając te dwie linijki pod

void setup() 

Odczyt powinien zostać wysyłany do monitora portu szeregowego tak ? bo na tą chwile bez wyświetlacza to jedyny sposób aby zweryfikować czy jest wysyłana jakaś temperatura

Edytowano przez Y0ogi
Link do komentarza
Share on other sites

Żeby przesłać informacje do monitora, w setup trzeba zainicjować wymianę danych poprzez Serial.begin(9600). W nawiasie podajesz prędkość transmisji, ważne, żeby po otwarciu monitora w Arduino IDE ustawić tę samą wartość.

Do wyświetlania zarówno statycznego tekstu, jak i wartości zmiennych stosuje się funkcje print (wypisuje wartość i nie przechodzi do nowej linii) i println (wyświetla wartość i przechodzi do następnej linii). Przykładowo: 

Serial.print("tekst"); // w monitorze wyświetli się statyczny tekst, który został podany w nawiasie w cudzysłowie, tj. tekst, program nie przyjdzie do nastepnej linii
Serial.println("inny tekst"); // wyświetli się statyczny tekst, tj. inny tekst i program automatycznie przejdzie do nastepnej linii (jakby użytkownik wcisnął enter, pisząc w edytorze tekstu)
Serial.print("przyklad\n"); // wyświetli się przyklad i pomimo zastosowania funkcji print program przejdzie do nastepnej linii, poniewaz wpisano znak konca linii \n
Serial.print(value); // wyświetli się wartość, jaką posiada zmienna o nazwie value i program nie przechodzi do nastepnej linii

Po dodaniu obsługi monitora portu szeregowego byłoby więc:

// pliki naglowkowe
#include <OneWire.h>
#include <DallasTemperature.h>

// definicje pinow
#define ONEWIRE_PIN 2       // numer pinu, do ktorego podlaczona jest siec 1 wire 

#define SENSOR_RES  12      // rozdzielczosc pomiaru czujnikow ds18b20 (9, 10, 11 lub 12 bit)

// interfejs sieci 1 wire
OneWire one_wire(ONEWIRE_PIN);
DallasTemperature ds18s20_net(&one_wire);

// struktura przechowujaca dane z pojedynczego czujnika
struct SENSOR
{
  uint8_t bus_address[8];
  float value;
  int8_t fault;
};

struct SENSOR sensors;
unsigned long conversionTime = 2000;
unsigned long lastTime = 0;


void setup() {
  // inicjalizacja portu szeregowego
  Serial.begin(9600);
  // inicjalizacja sieci one wire
  ds18s20_net.begin();

  // odczyt adresow na podstawie podanego indeksu czujnika
  // indeksy sa nadawane automatycznie, poczawszy od 0
  ds18s20_net.getAddress(sensors.bus_address, 0);
  // ustawienie rozdzielczosci
  ds18s20_net.setResolution(sensors.bus_address, SENSOR_RES);
    
  lastTime = millis();
}

void loop() {
  if ( millis() - lastTime > conversionTime)
  {
    // sprawdzanie, czy czujnik znajduje sie na sieci
    if (ds18s20_net.getAddress(sensors.bus_address, 0) == 0)
    {
      // blad czujnika
      sensors.fault = 1;
      Serial.println("Błąd czujnika DS18B20");
    }
    else
    {
      // brak bledu czujnika
      sensors.fault = 0;

      Serial.println("Brak błędu czujnika DS18B20");
      
      // odczyt temperatury z czujnika o indeksie 0
      sensors.value = ds18s20_net.getTempCByIndex(0);
      Serial.print("Temperatura: ");
      Serial.print(sensors.value);
      Serial.println(" oC");
      
      // oczekiwanie na zakonczenie konwersji jest przeprowadzane przy uzyciu timera
      ds18s20_net.setWaitForConversion(LOW);
      // zadanie ponownej konwersji temperatury
      ds18s20_net.requestTemperatures();
      lastTime = millis();
    }
  }

  // przestrzen na pozostala czesc programu, np. obsluge wyswietlacza
}

 

  • Pomogłeś! 1
Link do komentarza
Share on other sites

(edytowany)
#include "Adafruit_GFX.h"     
#include "Adafruit_ILI9341.h" 
#include <Wire.h>
#include "Sodaq_DS3231.h"
#include  <SPI.h>

#define TFT_DC 9              
#define TFT_CS 10             
#define TFT_RST 8             
#define TFT_MISO 12           
#define TFT_MOSI 11           
#define TFT_CLK 13          

Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_MOSI, TFT_CLK, TFT_RST, TFT_MISO);


char temperatureChar[10];

float temperature = 0;
float previousTemperature = 0;

uint32_t old_ts;
  
void setup(){
  
  Serial.begin(9600);
  tft.begin();                      
  tft.setRotation(3);            
  tft.fillScreen(ILI9341_BLACK);

  Wire.begin();
  rtc.begin();

  printText("TEMPERATURA", ILI9341_YELLOW,30,50,4); // napisz temperatura 


}
 
void loop()
{
 float temperature = rtc.getTemperature();
  DateTime now = rtc.now(); //get the current date-time
 uint32_t ts = now.getEpoch();

   if (old_ts == 0 || old_ts != ts) {
  old_ts = ts;
  
  
  if(temperature != previousTemperature)
  {
    previousTemperature = temperature;
    String temperatureString = String(temperature,1);
   temperatureString.toCharArray(temperatureChar,10);
    tft.fillRect(50,175,150,40,ILI9341_BLACK);
    printText(temperatureChar, ILI9341_WHITE,65,110,5);
    printText("o", ILI9341_WHITE,200,105,3);
    printText("C", ILI9341_WHITE,222,110,4);


    }
  }
}
    delay(1000);

}

void printText(char *text, uint16_t color, int x, int y,int textSize)
{
  tft.setCursor(x, y);
  tft.setTextColor(color);
  tft.setTextSize(textSize);
  tft.setTextWrap(true);
  tft.print(text);
}

 Jest ktoś w stanie określić czy powyższy kod jest poprawny do obsługi wyświetlacza  TFT 2,8"  i pod działanie z DS18B20???

Edytowano przez Y0ogi
Link do komentarza
Share on other sites

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • 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.