Skocz do zawartości

Wyświetlanie temperatury na wyświetlaczu 7-seg


Pomocna odpowiedź

Napisano

Cześć,
Chciałbym wyświetlić na wyświetlaczu temperaturę wczytaną z czujnika DS18B20 jednak mam problem z wyświetlaczem który wariuje. Nie zwracajcie uwagi na kablologię: https://imgur.com/gallery/YaKg7sE

Próbowałem bez czekania sekundy wykorzystując millis() ale efekty te same. Już nie wiem czego się czepić- macie jakieś pomysły?

#include <SevSeg.h>
SevSeg sevseg;

//czujnik
#include<OneWire.h>
#include<DallasTemperature.h>

OneWire oneWire(A5);// Podłączony do pinu A5
DallasTemperature sensors(&oneWire);

//zmienne
unsigned long zapCzas =0;
unsigned long aktCzas =0;
unsigned long rozCzas =0;
int temp=0;

void setup()
{
  //wyswietlacz
  byte numDigits = 2;   
  byte digitPins[] = {10,9}; //Digits: 1,2,3,4 <--put one resistor (ex: 220 Ohms, or 330 Ohms, etc, on each digit pin)
  byte segmentPins[] = {7, 5, 2, 4, 3, 8, 6}; //Segments: A,B,C,D,E,F,G,Period
  bool resistorsOnSegments= true;
  byte hardwareConfig = N_TRANSISTORS;
  
  sevseg.begin(hardwareConfig, numDigits, digitPins, segmentPins, resistorsOnSegments);
  sevseg.setBrightness(10); //Note: 100 brightness simply corresponds to a delay of 2000us after lighting each segment. A brightness of 0 
                            //is a delay of 1us; it doesn't really affect brightness as much as it affects update rate (frequency).
                            //Therefore, for a 4-digit 7-segment + pd, COMMON_ANODE display, the max update rate for a "brightness" of 100 is 1/(2000us*8) = 62.5Hz.
                            //I am choosing a "brightness" of 10 because it increases the max update rate to approx. 1/(200us*8) = 625Hz.
                            //This is preferable, as it decreases aliasing when recording the display with a video camera....I think.
  //czujnik
  Serial.begin(9600);
  sensors.begin();// rozpoczęcie transmisji z czujnikiem
}

void loop()
{
  //local vars
  static byte decPlace = 0;
  float tempr2,tempround;
  //czujnik
  unsigned long aktCzas = millis();
  rozCzas=aktCzas-zapCzas;
  if(rozCzas >= 1000UL){
    zapCzas=aktCzas;
    sensors.requestTemperatures();//pobieranie informacji
    Serial.print(aktCzas);
    Serial.print(" Aktualna temperatura: ");
    Serial.print(sensors.getTempCByIndex(0));
    tempr2=(sensors.getTempCByIndex(0)*2);
    tempround=round(tempr2);
    temp=(tempround/2);
    Serial.print(" - ");
    Serial.println(temp);
  }
  
  //wyswietlacz
  sevseg.setNumber(temp,decPlace);
  decPlace++;
  decPlace %= 4; //rollover back to 0 once variable gets to 4; To anyone wondering: the % is called the "modulo" operator; see here for explanation & example: https://www.arduino.cc/en/Reference/Modulo
  sevseg.refreshDisplay(); // Must run repeatedly; don't use blocking code (ex: delay()) in the loop() function or this won't work right
  
  
}

 

@Madoc, witam na forum 😉 Widzę, że to Twoje pierwsze kroki na Forbocie, oto najważniejsze informacje na start:

  • Chcesz przywitać się z innymi członkami naszej społeczności? Skorzystaj z tematu powitania użytkowników.
  • Opis najciekawszych funkcji, które ułatwiają korzystanie z forum znajdziesz w temacie instrukcja korzystania z forum - co warto wiedzieć?
  • Poszczególne posty możesz oceniać (pozytywnie i negatywnie) za pomocą reakcji - ikona serca w prawym dolnym rogu każdej wiadomości.
18 godzin temu, Madoc napisał:

Już nie wiem czego się czepić- macie jakieś pomysły?

Wydzieliłem Twój temat z kursu Arduino, aby nie robić tam zamieszania 😉

Zacznij analizowanie swojego programu od sprawdzenia, co już działa. Twój program realizuje ewidentnie dwie funkcje: mierzy temperaturę i pokazuje ją na wyświetlaczu. Czy sprawdzałeś jak działają obie te funkcje niezależnie od siebie? Tj. czy obecny program będzie potrafił poprawnie pokazywać dowolną liczbę na wyświetlaczu? Analogicznie: czy sam program termometru działa poprawnie? 

  • Lubię! 1

Żeby nie było czekania to musisz w programie raczej to wymusić, bo biblioteka domyślnie czeka sobie sama i nawet delay nie jest tu potrzebny. Jest do tego funkcja włączająca tryb asynchroniczny (setWaitForConversion    KEYWORD2). Wtedy jednak robisz tak, że odczytujesz temperaturę, zlecasz wykonanie pomiaru i wracasz tu za nie mniej niż 750ms (przy 12bitach). 

Sama część do segmentowego też jest raczej źle, bo %4 sugeruje, że masz wyświetlaną wartość na 4 wyświetlaczach. I raczej powinieneś pokazywać, którą cyfrę gdzie wrzucasz.

No i całość i tak nie będzie miła dla oka, bo nawet asynchroniczny odczyt 1 czujnika DS trwa ponad 25ms i jest to widoczne jako mrugnięcie ledów.

  • Pomogłeś! 1

Przepraszam, że tak długo nie odpowiadałem ale ostatnio nie miałem czasu żeby przysiąść do tego.

Dnia 10.12.2018 o 16:47, kaczakat napisał:

Żeby nie było czekania to musisz w programie raczej to wymusić, bo biblioteka domyślnie czeka sobie sama i nawet delay nie jest tu potrzebny. Jest do tego funkcja włączająca tryb asynchroniczny (setWaitForConversion    KEYWORD2). Wtedy jednak robisz tak, że odczytujesz temperaturę, zlecasz wykonanie pomiaru i wracasz tu za nie mniej niż 750ms (przy 12bitach). 

Sama część do segmentowego też jest raczej źle, bo %4 sugeruje, że masz wyświetlaną wartość na 4 wyświetlaczach. I raczej powinieneś pokazywać, którą cyfrę gdzie wrzucasz.

No i całość i tak nie będzie miła dla oka, bo nawet asynchroniczny odczyt 1 czujnika DS trwa ponad 25ms i jest to widoczne jako mrugnięcie ledów.

Dzięki wielkie to działa! 🙂 🙂Tryb asynchroniczny to było to czego mi brakowało. %4 poprawiłem na %2 a co do mrugania to trzeba będzie się po prostu przyzwyczaić.

Dzięki za pomoc.

Gość es2
(edytowany)
Dnia 10.12.2018 o 16:47, kaczakat napisał:

bo nawet asynchroniczny odczyt 1 czujnika DS trwa ponad 25ms

Kilka bajtów + reset/presence aż 25 ms?

Reset + presence ok 600us

Odczyt bajtu to 512us. Komenda + wszystkie dane z crc, łącznie 10 bajtów, to ok 5ms. Wszystko razem poniżej 6ms a biorąc pod uwagę, że większość bibliotek czyta tylko temperaturę (2 bajty + komenda) odczyt zajmuje nieco ponad 2ms.

Multipleksowana obsługa 4 7-seg LED z częstotliwością 100Hz następuje co 2,5ms (z taką częstotliwością należy wywoływać przerwania). Wydawać by się mogło, że się nie da ale nawet przy obsłudze 1-wire przez GPIO co powoduje konieczność zawieszania przerwań, czas poziomu  H na magistrali pomiędzy bitami może byc dowolnie długi. Wtedy przerwania mogą a właściwie muszą być odblokowane. Dzięki temu obsługa LED przebiega bez zakłóceń.

Zrealizowałem w praktyce obsługę  1-Wire przez GPIO, więc z blokowaniem przerwań, czytam 7 termometrów, obsługuję 4 cyfrowy multipleksowany LED oraz w przerwaniach steruje WS2812. Nic nie miga!

Wystarczy aby obsłużyć LED jak należy na przerwaniach. 1-Wire najlepiej na USART, jak nie ma takiej możliwości blokować przerwania TYLKO na czas generowania poziomu L i odczytu bitu (czyli max 15us) w standardowej prędkości.

 

Problem zawieszania przerwań rozwiązuje też master 1-Wire po I2C DS2482/4. Naszukasz się SearchRom dla DS-a, chyba, że jest gotowiec dla Arduino albo zaakceptujesz, że SearchRom będzie działać w żółwim tempie. DS2482/4 działa troszkę wolniej niż GPIO  ale załatwia "silne" podciąganie sprzętowo, pozwalając wycisnąć max długość i szybkość magistrali i (co ważne w szybkich transmisjach do EEPROM, GPIO itp) spełnia kryteria czasowe trybu overdrive co do osiągnięcia na GPIO dla AVR takie oczywiste nie jest,chyba, że na UART ale nie próbowałem (1MB/s dla AVR problemem nie jest).

 

Edytowano przez es2

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...