Skocz do zawartości

Arduino Mega2560 + Ethernet + DS18B20 + 7-seg. moduł LED TM1637 - Pomiar temperatury i wysyłanie do bazy SQL


szczepulek

Pomocna odpowiedź

4 godziny temu, szczepulek napisał:

czas na wykonanie wyświetlenia LED8seg x2 to około 42-43ms

Dla mnie niedopuszczalne ale skoro

3 godziny temu, szczepulek napisał:

przyciski, jeśli mają być nie aktywne prze 5-10 sek, nie ma problemu

I nie będziesz używał odbioru z UART lub innych tego typu spraw (np slave I2C, SPI) to znaczy, że nawet te 1,4 sekundy robione przez 1-Wire nie jest problemem.

PS. Zastanawiam się jak ustawisz watchdoga? Jak tak dalej będziesz "szastał" czasem CPU używająć (swiadomnie czy nie) delay to podzielników może być za mało.

 

3 godziny temu, szczepulek napisał:

Będzie to sygnał że zaraz nic nie będzie można zmienić klawiszami.

Moja szczera opinia "amatorszczyzna wysokich lotów". Możesz tak zrobić w pierwszej wersji softu (do testów) ale nie w programie użytkowym. Gdy zaczniesz uzywać tego programu, gdzie masz "celować" kiedy wykonać jakąś operację, to po pewnym czasie wkurzysz się.  Z praktyki mogę napisać, że dużo bardziej błahe powody kończyły się tym, ze użytkownik "wbił" taborek w monitor czy rozwalił terminal.

Link do komentarza
Share on other sites

17 godzin temu, szczepulek napisał:

przed przystąpieniem do wpięcia eth schield musze skrócić czas wykonywania co do tej pory mam.

Bezwzględnie! 5 sekund, ile ramek możesz dostać? ENC to nie ESP, który na ARP czy ICPM odpowie, w przypadku ENC musisz to "załatwić"! Jak myślisz, router bedzie czekał 5 sekund na ARP?

Poczytaj o tym, będzie czekał, nawet i 5 minut, ale sprawdź na jakich zasadach (2,4,8.....) ale są tego konsekwencje! O tle dobrze wiem jak to działa, bo nieustannie "wykolejałem" router Edimax (może Asmax) zasypując go przez przypadek ARPami. Na szczęście działałem w wydzielonej sieci, bo serwerem "nadrzędnym" był "Windows xxx serwer" a to juz tak jest podatne na takie błędy, że szkoda klawiatury.

 

Do tych 5 sekund (sprawdzisz ile faktycznie jest, napisałem jak długo to trwa w przypadku ThingSpeak , na innych serwerach, zwłaszcza jak sam napiszesz, nie musi być tak długo, bo bez ASS, UDP a nie TCP o czym już pisałem) jak dodasz 1,4 sekundy, to niebezpiecznie zbliżasz się do 8 sekund, a w przypadku AVR to jest chyba max watchdoga. Możesz nie używac watchdoga, taj jak nie musisz używać pasów bezpieczeństwa, czy maski przeciwgazowej podczas ataku chemicznego ale czy jest to rozsądne działanie?

Link do komentarza
Share on other sites

(edytowany)

Ok, właśnie jestem po przywróceniu systemu do użyteczności, podczas kompilacji przekształconego kodu,  windows się wysypał. Niestety nie spodziewałem się takiego obrotu sprawy. Wpierw ustawię wartość rozdzielczości pomiarów dla 9 bit przez dodanie linii setResolution(9).

Musze jeszcze pobrać środowisko Arduino IDE.

@RFM w przykładzie na pomiar po określonym czasie do wyświetlenia wartości pomiaru wystarczy mi uint16_t  jeśli się nie mylę(??)

Po podłączeniu do oscylatora czas na pomiar w pętli trwa teraz ~335 ms. Po zmianie na 9bit rozdzielczości. Ot teraz kolej na odczyt bez oczekiwania na obliczanie czujnika

Edytowano przez szczepulek
dodano
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

2 godziny temu, szczepulek napisał:

na pomiar po określonym czasie do wyświetlenia wartości pomiaru wystarczy mi uint16_t  jeśli się nie mylę

Wystarczy ale wyjątkowo źle biblioteki używają ZUPEŁNIE NIEPOTRZEBNIE float ! Musiałbyś zmodyfikować bibliotekę a jest tam tyle do poprawiania, że najlepiej napisać swoją.

 

2 godziny temu, szczepulek napisał:

czas na pomiar w pętli trwa teraz ~335 ms

To też kosmos. Zrób jak pisałem, komenda pomiaru a po wymaganym czasie (sprawdź w nocie DS18B20) odczyt temperatury. Oczywiście nie czekasz używając delay tylko millis.

Link do komentarza
Share on other sites

(edytowany)
#include <TM1637Display.h>
#include <OneWire.h>
#include <DallasTemperature.h>


#define ONE_WIRE_temp_in 2 //pin dla 1 czujnika ds18b20
#define ONE_WIRE_temp_out 3 //pin dla drugiego czujnika
#define CLK1 5 //wyswietlacz nr1 8segm.4-cz dla wejscia powietrza - temp
#define DIO1 6 //wyswietlacz nr1 8segm.4-cz
#define CLK2 7 //wyswietlacz nr2 8segm.4-cz dla wyjscia powietrza - temp
#define DIO2 8 //wyswietlacz nr2 8segm.4-cz

TM1637Display display_1(CLK1, DIO1);
TM1637Display display_2(CLK2, DIO2);
OneWire oneWire_in(ONE_WIRE_temp_in);
OneWire oneWire_out(ONE_WIRE_temp_out);

DallasTemperature sensor_airin(&oneWire_in);
DallasTemperature sensor_airout(&oneWire_out);

uint16_t tPomiary;


void setup(void)
{
    Serial.begin(9600);
    Serial.println("Dallas Temperature Control Library Demo - TwoPin_DS18B20");
      sensor_airin.begin();
       sensor_airin.setResolution(9);
      sensor_airout.begin();
       sensor_airout.setResolution(9);
 
   display_1.setBrightness(0x0a); //jasnosc wysw nr 1 nizej 2
   display_2.setBrightness(0x0a); // -||-

pinMode(40, OUTPUT); // czas trwania dla DS18b20
pinMode(44, OUTPUT); //czas trwania dla LED-wysw
}

void loop(void)
{

    uint8_t wysw1LED[] = { 0x00, 0x00, 0x00, 0x00 };
    uint8_t wysw2LED[] = { 0x00, 0x00, 0x00, 0x00 };
    float tempIn;
    float tempOut;
    
    Serial.print("Requesting temperatures...");
  
    sensor_airin.requestTemperatures();  //komenda by rozpoczęto pomiar
    sensor_airout.requestTemperatures();
   
     digitalWrite(40, HIGH); //start pomiaru odczytu DS18B20

if ( millis() >= tPomiary )
     {    
        tPomiary = millis() + 100;
        Serial.println(" done");
    
        Serial.print("airin: ");
        tempIn = sensor_airin.getTempCByIndex(0);
        Serial.println(tempIn);
    
        Serial.print("airout: ");
        tempOut = sensor_airout.getTempCByIndex(0);
        Serial.println(tempOut); //wyswietla w serial monitor, ostatecznie bedzie usuniete
     }

   digitalWrite(40, LOW); //koniec pomiaru odczytu i przeliczenia na calkowita liczbe

  int  airinCalkow = tempIn *100; //pozbycie sie kropki w wyniku pomiaru xx.xx
  int  airoutCalkow = tempOut *100; //podobnie dla drugiego pomiaru


  //obsluga wyswietlania pierwszego wyswietlacza dla czujnika 1 ,szczegulna uwage nalezy zwrocic na prawidlowe odwolanie sie do uint, i display
  
 digitalWrite(44, HIGH);      //start wyswietlanie wartosci na led_tm1637
  
  wysw1LED[0] = display_1.encodeDigit(airinCalkow/1000%10); //wyswietla cyfre dziesiatek z pomiaru cz.1 na wyswietlaczu pierwszym
  wysw1LED[1] = display_1.encodeDigit(airinCalkow/100%10); //wyswietla cyfre jednosci z pomiaru cz.1 na wyswietlaczu pierwszym
  wysw1LED[2] = (SEG_A | SEG_B | SEG_F | SEG_G); // znak stopni zamiast kropki ktore brak w wyswietlaczu ktory posiadam
  wysw1LED[3] = display_1.encodeDigit(airinCalkow/10%10); //pierwsza cyfra czesci dziesietnych
  display_1.setSegments(wysw1LED); // wyswietlenie  temperatury na pierwszym wyswietlaczu
 
  //obsluga wyswietlania drugiego wyswietlacza dla czujnika 2
  
  wysw2LED[0] = display_2.encodeDigit(airoutCalkow/1000%10); //wyswietla cyfre dziesiatek z pomiaru cz.1 na wyswietlaczu pierwszym
  wysw2LED[1] = display_2.encodeDigit(airoutCalkow/100%10); //wyswietla cyfre jednosci z pomiaru cz.1 na wyswietlaczu pierwszym
  wysw2LED[2] = (SEG_A | SEG_B | SEG_F | SEG_G); // znak stopni zamiast kropki ktore brak w wyswietlaczu ktory posiadam
  wysw2LED[3] = display_2.encodeDigit(airoutCalkow/10%10); //pierwsza cyfra czesci dziesietnych
  display_2.setSegments(wysw2LED); // wyswietlenie  temperatury na pierwszym wyswietlaczu
  
  digitalWrite(44, LOW); //koniec pomiaru wyswietlania na 2 szt modulu LED wyswietlacz tm1637
  
}

Oto co udało mi się zrobić, 

udało się uzyskać czas dla pomiaru około 22ms na czujnik, w sumie około 44ms. Wyświetlanie to około 40ms dwa wyniki.  Jak na zdj wykresu oscylatora... reszta to długa przerwa. polecenie sensor_airin.requestTemperatures(); i sensor_airin.requestTemperatures(); powoduje tą przerwę. Gdy dam je w komentarz, to pętla się zamyka i widać że są wykonywane funkcje jedna po drugiej.

@RFM przeglądałem bibliotekę i nie znalazłem innego polecenia niż powyższe do rozpoczęcia pomiaru, próbowałem..

IMG_20191019_160548.jpg

IMG_20191019_160608.jpg

Edytowano przez szczepulek
Link do komentarza
Share on other sites

33 minuty temu, szczepulek napisał:

przeglądałem bibliotekę i nie znalazłem innego polecenia niż powyższe do rozpoczęcia pomiaru,

Albo słabo szukałeś albo kiepska biblioteka. Jesli kiepska to poszukaj lepszej lub sam popraw. Pomiar MUSI składac się z dwóch etapów, polecenie konwersji a po pauzie lub operacji sprawdzania czy pomiar się zakończył, odczyt wyniku. Tak działa DS18B20 i tego zmienić się nie da (zapoznałeś się z nota DS18B20?).

Link do komentarza
Share on other sites

(edytowany)

Jest jakiś przełom,

Mianowicie natrafiłem wcześniej na taki oto przykład, z nettigo

Cytat

z ciekawości pobrałem tę bibliotekę tam umieszczoną , to już 3 biblioteka o nazwie DS18B20.. a każda wcześniejsza była inna.

http://akademia.nettigo.pl/ds18b20/DS18B20.zip

Przerobiłem nieco kod dostosowując do tej właśnie, i w rezultacie mogę powiedzieć że osiągnąłem zapętlenie bez przerwy (w loop).

Patrząc na oscyloskop widzę że teraz funkcja pobierania temp wykonuje się raz, ale w miedzy czasie są 2 funkcje dla wyświetlania. ..tak to rozumiem.

przypominam żółty to dla ds a niebieski dla led8seg.

IMG_20191019_171227.jpg

dla pomiaru 2 DS18b20 to czas około 70ms, dla 2 wyświetlaczy z tm1637 czas około 43ms. W sumie około 118ms na obecną chwilę.

Edytowano przez szczepulek
Link do komentarza
Share on other sites

#include <DS18B20.h> //  BIBLIOTEKA NETTIGO

#include <TM1637Display.h>
#include <OneWire.h>

#define ONE_WIRE_temp_in 2 //pin dla 1 czujnika ds18b20
#define ONE_WIRE_temp_out 3 //pin dla drugiego czujnika
#define CLK1 5 //wyswietlacz nr1 8segm.4-cz dla wejscia powietrza - temp
#define DIO1 6 //wyswietlacz nr1 8segm.4-cz
#define CLK2 7 //wyswietlacz nr2 8segm.4-cz dla wyjscia powietrza - temp
#define DIO2 8 //wyswietlacz nr2 8segm.4-cz

TM1637Display display_1(CLK1, DIO1);
TM1637Display display_2(CLK2, DIO2);
OneWire oneWire_in(ONE_WIRE_temp_in);
OneWire oneWire_out(ONE_WIRE_temp_out);

DS18B20 sensor_airin(&oneWire_in);
DS18B20 sensor_airout(&oneWire_out);

  byte address1[8]; // adres 1 czujnika
  byte address2[8];//adres 2 czujnika

void setup(void)
{
    Serial.begin(9600);
    Serial.println("Nettigo DS18B20 lib - TwoPin_DS18B20");
      sensor_airin.begin(9); // rozdzielczość (9) 9 bit dla pomiarow
      sensor_airout.begin(9); // jak wyzej

  oneWire_in.reset_search(); //
  while(oneWire_in.search(address1))  //wyszukanie 1 adresu 1 czujnika
  {
    if (address1[0] != 0x28)
      continue;
      
    if (OneWire::crc8(address1, 7) != address1[7])
    {
      Serial.println(F("1-Wire IN bus connection error!"));
      break;
    }
  }

 oneWire_out.reset_search();
  while(oneWire_out.search(address2)) // tu dla 2 czujnika wyszukanie adresu.
  {
    if (address2[0] != 0x28)
      continue;
      
    if (OneWire::crc8(address2, 7) != address2[7])
    {
      Serial.println(F("1-Wire OUT bus connection error!"));
      break;
    }
  }
  
   display_1.setBrightness(0x0a); //jasnosc wysw nr 1 nizej 2
   display_2.setBrightness(0x0a); // -||-

pinMode(40, OUTPUT); // czas trwania dla DS18b20
pinMode(44, OUTPUT); //czas trwania dla LED-wysw
sensor_airin.request();
sensor_airout.request();


}

void loop(void)
{

    uint8_t wysw1LED[] = { 0x00, 0x00, 0x00, 0x00 };
    uint8_t wysw2LED[] = { 0x00, 0x00, 0x00, 0x00 };
    int airinCalkow;
    int airoutCalkow;
    
    Serial.print("Requesting temperatures...");
   
     digitalWrite(40, HIGH); //start pomiaru odczytu DS18B20

if ( sensor_airin.available() )
     {    

        Serial.println(" done");
    
        Serial.print("airin: ");
      float  tempIn = sensor_airin.readTemperature(address1);
        Serial.println(tempIn);
    
        Serial.print("airout: ");
     float  tempOut = sensor_airout.readTemperature(address2);
        Serial.println(tempOut); //wyswietla w serial monitor, ostatecznie bedzie usuniete
     

   digitalWrite(40, LOW); //koniec pomiaru odczytu i przeliczenia na calkowita liczbe

  airinCalkow = tempIn *100; //pozbycie sie kropki w wyniku pomiaru xx.xx
  airoutCalkow = tempOut *100; //podobnie dla drugiego pomiaru
sensor_airin.request();
sensor_airout.request();

     }
  //obsluga wyswietlania pierwszego wyswietlacza dla czujnika 1 ,szczegulna uwage nalezy zwrocic na prawidlowe odwolanie sie do uint, i display
  
 digitalWrite(44, HIGH);      //start wyswietlanie wartosci na led_tm1637
  
 // wyswietlenie  temperatury na pierwszym wyswietlaczu
   wysw1LED[0] = display_1.encodeDigit(airinCalkow/1000%10); //wyswietla cyfre dziesiatek z pomiaru cz.1 na wyswietlaczu pierwszym
  wysw1LED[1] = display_1.encodeDigit(airinCalkow/100%10); //wyswietla cyfre jednosci z pomiaru cz.1 na wyswietlaczu pierwszym
  wysw1LED[2] = (SEG_A | SEG_B | SEG_F | SEG_G); // znak stopni zamiast kropki ktore brak w wyswietlaczu ktory posiadam
  wysw1LED[3] = display_1.encodeDigit(airinCalkow/10%10); //pierwsza cyfra czesci dziesietnych
  display_1.setSegments(wysw1LED);
  //obsluga wyswietlania drugiego wyswietlacza dla czujnika 2
  
  wysw2LED[0] = display_2.encodeDigit(airoutCalkow/1000%10); //wyswietla cyfre dziesiatek z pomiaru cz.1 na wyswietlaczu pierwszym
  wysw2LED[1] = display_2.encodeDigit(airoutCalkow/100%10); //wyswietla cyfre jednosci z pomiaru cz.1 na wyswietlaczu pierwszym
  wysw2LED[2] = (SEG_A | SEG_B | SEG_F | SEG_G); // znak stopni zamiast kropki ktore brak w wyswietlaczu ktory posiadam
  wysw2LED[3] = display_2.encodeDigit(airoutCalkow/10%10); //pierwsza cyfra czesci dziesietnych
  display_2.setSegments(wysw2LED); // wyswietlenie  temperatury na pierwszym wyswietlaczu
  
  digitalWrite(44, LOW); //koniec pomiaru wyswietlania na 2 szt modulu LED wyswietlacz tm1637
}

 

Link do komentarza
Share on other sites

2 godziny temu, szczepulek napisał:

dla pomiaru 2 DS18b20 to czas około 70ms

Dużo za dużo. Już robiłem wyliczenia, napisze jeszcze raz:

Uruchomienie pomiaru to wysłanie 2 bajtów: SKIP_ROM (0xCC), CONVERT (0x44) co trwa trochę ponad 1 ms (0,064*8*2) do tego reset, presecne (poniżej 1 ms), razem 2ms.

Odczyt temperatury, razem z CRC (dużym błędem jest czytanie tylko TEMP_L i TEM_H, zwierasz magistralę i większość bibliotek odczytuje 0, jakie mogą być skutki zależy od urządzenia) to łącznie 11 bajtów: SKIP (0x44), read_scratchpad (0xbe), 8 bajtów danych, 1 crc. Odczyt 11 bajtów to czas poniżej 6ms (0,064*8*11) + 1 ms reset, presence czyli ok 7ms.

Twoje 70ms to stanowczo za dużo, coś ma zrobione niezbyt dobrze.

 

2 godziny temu, szczepulek napisał:

dla 2 wyświetlaczy z tm1637 czas około 43ms

O tym już pisałem, jak dla mnie za dużo. Zmiana biblioteki łatwa nie będzie, właściwie to jest niemożliwa. Obsługę TM1637 trzeba to napisać praktycznie od nowa. Czy użyjesz I2C, czy timera to już inna sprawa, z I2C będzie łatwiej. Sprawdź czy I2C ma bufor nadawczy (UART ma, chyba 64bajty, I2C 32 bajty, można spodziewać się, że I2C też ma bufor). Jeśli bufor jest wielkości liczby danych, które chcesz wysłać (może + 1 na adres) to pakujesz dane do I2C i wszystko leci ina przerwaniach, jeśli bufor za mały, to go zwiększ ale pamiętaj, że w arduino poszli na łatwiznę i o wielkości bufora nadawczego i odbiorczego decyduje ta sama definicja, więc trochę RAM zniknie.

Przyznam, że jak mam poprawiać niedociągnięcia bibliotek Arduino, to wole napisać je sam od nowa.

 

te serial.print "nabijają" niepotrzebnie czas. Zacznij od zwiększenia prędkości z 9600 na 115200. Niestety na UNO/MEGA itp o 921600 możesz zapomnieć, bo kwarc ma 16MHz (czemu nie 20? Mega może do 20 działać, fakt, ze M8 który był pierwotnie max 16 ale czemu nie zmienić?) gdyby miał 18,4321MHz to 921600 działa bez problemu. Kolejna opcja zwiększyć bufor (niestety, odbiorczy też się zwiększy). Teraz chyba zaczynasz widzieć, że UNO to zabawka i rozsądne minimum to ArduinoMEGA choć ja bym użył raczej AVRmega1284 z 16kB RAM.

Link do komentarza
Share on other sites

okej, siadłem dzisiaj na chwilę, problem miałem z prawidłowym połączeniem ze sobą (na razie) Arduino Mega 2560 z czujnikami i wyświetlaczami LED, jako nadajnik na serial'u, oraz Arduino Uno do odbioru na SoftwareSerial.h

Pierwsza sprawa, oba moduły muszą być połączone masami (GND) by krzaczków nie było, druga sprawa logiczna ale łatwo coś przeoczyć.. prędkość musi być taka sama po  obu stronach. Co do wieeeeeluuuuu poradników i przykładów, 99% ich nie działa lub jest niepełny opis/kod. Najwięcej pomógł mi opis:

Cytat

http://akademia.nettigo.pl/ds18b20/#dobieranie_rezystora_podciagajacego

a tam działające z tym kodem biblioteki DS18B20 w ważneeeee V.1.0

A co do komunikacji:

z YT kanał Elektromaniak

 

Niestety co do filmu "#100 jak przy użyciu komunikacji szerergowej połączyć dwa urządzenia [Arduino]" nie ma możliwości pobrania kodu źródłowego, nie aktualne linki. Ja przepisywałem kod z stop-klatki :D. Zmodyfikowałem i uprościłem pod siebie.

Umieszczam poniżej kody źródłowe dla mega2560 jako nadajnik serial pomiarów, obsługujący cz.temp i wyświetlacze, oraz kolejna płytka to arduino uno jako odbiorca danych. Domyślnie ma być to ESP 8266-12E

Kolego RFM dziękuje ci za pomoc, "na szybko" musiałem coś ustrugać by działało jako-tako. W wolnym czasie bez nacisku teraz zasiegnę do twoich rad by ulepszyć działanie całego układu, celowo nie pisze że tego kodu, wymagającego napisania od nowa.

 

Zamieszczam ten kod by osoby jak ja początkujące, i nie mogące się połączyć po serialu nie błądziły po stronach bezwartościowych, lub poruszających temat bez łopatologicznego pokazania że to działa i dobrze odbiera dane.

TX:

/*     SSS                                                L            K       (2019)
 *    S       ZZZZ    CCC   ZZZZ    EEE   PPPP    U   U   L      EEE   K   K
 *     SSS      Z    C        Z    E___   P   P   U   U   L     E___   K K
 *        S    Z     C       Z     E      P   P   U   U   L     E      K  K
 *    SSSS    ZZZZ    CCC   ZZZZ    EEE   PPPP     UUU     LL    EEE   K   K
 *                                        P
 *  KOMUNIKACJA PO SERIALU (SOFTWARE)
 *  Do komunikacji wykorzystano Nadawanie TX Arduino Mega 2560, odbior na Arduino Uno R3
 *  Na Mega 2560 uzyto Serial1, mozna uzyc serial2, czy serial3. Na Uno piny 2-oraz 3.
 *  WAZNE !!! nie zapomnijcie polaczyc ze soba GND obu plytek.
 *  u mnie dziala to dobrze. Przy nadawaniu temperatura jest zamieniana na liczbe calkowita bez przecinka/kropki poprzez
 *  pomnozenie przez 100 wyniku pomiaru. By uniknac zmiany dlugosci wysylanych danych przy ujemnych temperaturach,
 *  do wyniku dodaje 30 stopni, ktore przy pozniejszemu dekodowaniu na odbiorniku odejmuje (te 30st.),
 *  Dzieki temu zabiegowi temperatura np 22.50 st.C, zamienione na calkowite ma wartosc 2250. a po dodaniu wczesniej
 *  do pomiaru 30 ma wartosc 5250. I do wysylania potrzebne sa 4 bajty.
 *  Bez tego wartosc -23.00 st.C po pomnozeniu ma wartosc -2300 czyli ze znakiem minusa mamy 5 bajtow.
 *  Po dodaniu do pomiaru 30 st mamy 13 st (-23+30= 13) podsumowujac, minimalna temp przesylana bez bledu dekodowania/
 *  odczytu/ to temperatura  -29.50, natomiast maksymalna to 69.50 (bo 70.00+ 30 = 100, po pomnozeniu przekracza 4 bajty)
 *  Może i to  rozwiązanie mocno AMATORSKIE, ale działa :) teraz można ulepszac kod i przeksztalcac..
 */

// kod dla ARDUINO MEGA 2560 (4 x Serial) w trybie nadawania na Serial1



#include <DS18B20.h>
#include <TM1637Display.h>
#include <OneWire.h>



#define ONE_WIRE_temp_in 2 //pin dla 1 czujnika ds18b20
#define ONE_WIRE_temp_out 3 //pin dla drugiego czujnika
#define CLK1 5 //wyswietlacz nr1 8segm.4-cz dla wejscia powietrza - temp
#define DIO1 6 //wyswietlacz nr1 8segm.4-cz
#define CLK2 7 //wyswietlacz nr2 8segm.4-cz dla wyjscia powietrza - temp
#define DIO2 8 //wyswietlacz nr2 8segm.4-cz

TM1637Display display_1(CLK1, DIO1);
TM1637Display display_2(CLK2, DIO2);
OneWire oneWire_in(ONE_WIRE_temp_in);
OneWire oneWire_out(ONE_WIRE_temp_out);

DS18B20 sensor_airin(&oneWire_in);
DS18B20 sensor_airout(&oneWire_out);

  byte address1[8];
  byte address2[8];

  uint8_t wysw1LED[] = { 0x00, 0x00, 0x00, 0x00 };
  uint8_t wysw2LED[] = { 0x00, 0x00, 0x00, 0x00 };

//  char wyslij[7];    //dzialalo..

String wyspom1 [9];
 
  int i;

/*/....usun..test
int data [2];
int data1 [4];
int potPin = 0;  // analog pin used to connect the potentiometer
int pot0;    // variable to read the pot0ue from the analog pin
//...koniec */

void setup(void)
{
    Serial.begin(9600);  //   s e r i a l  1  !!!
    Serial1.begin(9600);

    Serial.println("Nettigo DS18B20 lib - TwoPin_DS18B20");

    //....test...ustDlaSerial3??
//   pinMode(15, INPUT);
//   pinMode(14, OUTPUT);
    //....

   display_1.setBrightness(0x0a); //jasnosc wysw nr 1 nizej 2
   display_2.setBrightness(0x0a); // -||-

      sensor_airin.begin(9);
      sensor_airout.begin(9);

  oneWire_in.reset_search();
  while(oneWire_in.search(address1))
  {
    if (address1[0] != 0x28)
      continue;
      
    if (OneWire::crc8(address1, 7) != address1[7])
    {
      Serial.println(F("1-Wire IN bus connection error!"));
      break;
    }
  }

 oneWire_out.reset_search();
  while(oneWire_out.search(address2))
  {
    if (address2[0] != 0x28)
      continue;
      
    if (OneWire::crc8(address2, 7) != address2[7])
    {
      Serial.println(F("1-Wire OUT bus connection error!"));
      
      break;
    }
  }
  
pinMode(40, OUTPUT); // czas trwania dla DS18b20
pinMode(44, OUTPUT); //czas trwania dla LED-wysw
sensor_airin.request();
sensor_airout.request();

}

void loop(void)
{
    int airinCalkow;
    int airoutCalkow;
int comTempIN;
int comTempOut;
    
    Serial.print("Requesting temp...");
   
     digitalWrite(40, HIGH); //start pomiaru odczytu DS18B20

if ( sensor_airin.available() )
     {    

        Serial.println(" done");
    
        Serial.print("airin: ");
      float  tempIn = sensor_airin.readTemperature(address1);
        Serial.println(tempIn);
    
        Serial.print("airout: ");
     float  tempOut = sensor_airout.readTemperature(address2);
        Serial.println(tempOut); //wyswietla w serial monitor, ostatecznie bedzie usuniete
     

   digitalWrite(40, LOW); //koniec pomiaru odczytu i przeliczenia na calkowita liczbe

  airinCalkow = tempIn *100; //pozbycie sie kropki w wyniku pomiaru xx.xx
  airoutCalkow = tempOut *100; //podobnie dla drugiego pomiaru
comTempIN = (tempIn+30)*100; //pozbycie sie kropki w wyniku pomiaru xx.xx
comTempOut = (tempOut+30) *100; //podobnie dla drugiego pomiaru


sensor_airin.request();
sensor_airout.request();

     }
  //obsluga wyswietlania pierwszego wyswietlacza dla czujnika 1 ,szczegulna uwage nalezy zwrocic na prawidlowe odwolanie sie do uint, i display
  
 digitalWrite(44, HIGH);      //start wyswietlanie wartosci na led_tm1637

  if ( airinCalkow < -9900  || airinCalkow == 0)
  {
    wysw1LED[0] = (SEG_A | SEG_D | SEG_E | SEG_F | SEG_G); // E
    wysw1LED[1] = (SEG_E | SEG_G); // r
    wysw1LED[2] = (SEG_E | SEG_G); // r
    wysw1LED[3] = display_1.encodeDigit(1); // 1
    display_1.setSegments(wysw1LED); // Err1
  }
 else
  {
      wysw1LED[0] = display_1.encodeDigit(airinCalkow/1000%10); //wyswietla cyfre dziesiatek z pomiaru cz.1 na wyswietlaczu pierwszym
      wysw1LED[1] = display_1.encodeDigit(airinCalkow/100%10); //wyswietla cyfre jednosci z pomiaru cz.1 na wyswietlaczu pierwszym
      wysw1LED[2] = (SEG_A | SEG_B | SEG_F | SEG_G); // znak stopni zamiast kropki ktore brak w wyswietlaczu ktory posiadam
      wysw1LED[3] = display_1.encodeDigit(airinCalkow/10%10); //pierwsza cyfra czesci dziesietnych
      display_1.setSegments(wysw1LED); // wyswietlenie  temperatury na pierwszym wyswietlaczu
  
  }
  
  //obsluga wyswietlania drugiego wyswietlacza dla czujnika 2
  if (airoutCalkow < -9999 || airoutCalkow == 0)
  {
    wysw2LED[0] = (SEG_A | SEG_D | SEG_E | SEG_F | SEG_G); // E
    wysw2LED[1] = (SEG_E | SEG_G); // r
    wysw2LED[2] = (SEG_E | SEG_G); // r
    wysw2LED[3] = display_2.encodeDigit(2); // 2
    display_2.setSegments(wysw2LED); // Err2
  }
  else
  {
    wysw2LED[0] = display_2.encodeDigit(airoutCalkow/1000%10); //wyswietla cyfre dziesiatek z pomiaru cz.1 na wyswietlaczu pierwszym
    wysw2LED[1] = display_2.encodeDigit(airoutCalkow/100%10); //wyswietla cyfre jednosci z pomiaru cz.1 na wyswietlaczu pierwszym
    wysw2LED[2] = (SEG_A | SEG_B | SEG_F | SEG_G); // znak stopni zamiast kropki ktore brak w wyswietlaczu ktory posiadam
    wysw2LED[3] = display_2.encodeDigit(airoutCalkow/10%10); //pierwsza cyfra czesci dziesietnych
    display_2.setSegments(wysw2LED); // wyswietlenie  temperatury na pierwszym wyswietlaczu
  }

// uwaga.. zamiana ulamka na calkowite i przez dodanie do wyniku +29 pozbycie sie ewentualnego znaku MINUS


char ti1=comTempIN/1000%10 + 48; //dodanie 48 by uzyskac znak typu char
char ti2=comTempIN/100%10 + 48;
char ti3=comTempIN/10%10 + 48;
char to1=comTempOut/1000%10 + 48;// L_._ dziesiatki
char to2=comTempOut/100%10 + 48;// _L._ jednosci
char to3=comTempOut/10%10 + 48;// __.L cz.dziesietne


  
 // char wyslij[5]; // 7 zn
  
  digitalWrite(44, LOW); //koniec pomiaru wyswietlania na 2 szt modulu LED wyswietlacz tm1637
char wyspom1 [9];
//char wyspom2 [5];

  //poszczegulne znaki w tabeli:
 wyspom1[0]=0x7B; //1 zn sprawdzajacy
 wyspom1[1]=ti1;
 wyspom1[2]=ti2;
 wyspom1[3]=ti3;
 wyspom1[4]='X'; //odziela t1 od t2 , czy tez TempIn od Out
 wyspom1[5]=to1;
 wyspom1[6]=to2;
 wyspom1[7]=to3;
 wyspom1[8]=0x7D; //2 zn sprawdzajacy

 
 Serial1.write(wyspom1, 9); 
Serial.println(wyspom1); //co wysyła??
//Serial1.write(comTempIN);
Serial.println(comTempIN);
 delay(400);        // delay in between reads for stability


}

Dla chcącego można użyć w kodzie sumy kontrolne , by profesjonalniej to działało.

 

RX - odbiór
 

/*     SSS                                                L            K       (2019)
 *    S       ZZZZ    CCC   ZZZZ    EEE   PPPP    U   U   L      EEE   K   K
 *     SSS      Z    C        Z    E___   P   P   U   U   L     E___   K K
 *        S    Z     C       Z     E      P   P   U   U   L     E      K  K
 *    SSSS    ZZZZ    CCC   ZZZZ    EEE   PPPP     UUU     LL    EEE   K   K
 *                                        P
 *  KOMUNIKACJA PO SERIALU (SOFTWARE)
 *  Do komunikacji wykorzystano Nadawanie TX Arduino Mega 2560, odbior na Arduino Uno R3
 *  Na Mega 2560 uzyto Serial1, mozna uzyc serial2, czy serial3. Na Uno piny 2-oraz 3.
 *  WAZNE !!! nie zapomnijcie polaczyc ze soba GND obu plytek.
 *  u mnie dziala to dobrze. Przy nadawaniu temperatura jest zamieniana na liczbe calkowita bez przecinka/kropki poprzez
 *  pomnozenie przez 100 wyniku pomiaru. By uniknac zmiany dlugosci wysylanych danych przy ujemnych temperaturach,
 *  do wyniku dodaje 30 stopni, ktore przy pozniejszemu dekodowaniu na odbiorniku odejmuje (te 30st.),
 *  Dzieki temu zabiegowi temperatura np 22.50 st.C, zamienione na calkowite ma wartosc 2250. a po dodaniu wczesniej
 *  do pomiaru 30 ma wartosc 5250. I do wysylania potrzebne sa 4 bajty.
 *  Bez tego wartosc -23.00 st.C po pomnozeniu ma wartosc -2300 czyli ze znakiem minusa mamy 5 bajtow.
 *  Po dodaniu do pomiaru 30 st mamy 13 st (-23+30= 13) podsumowujac, minimalna temp przesylana bez bledu dekodowania/
 *  odczytu/ to temperatura  -29.50, natomiast maksymalna to 69.50 (bo 70.00+ 30 = 100, po pomnozeniu przekracza 4 bajty)
 *  Może i to  rozwiązanie mocno AMATORSKIE, ale działa :) teraz można ulepszac kod i przeksztalcac..
 */

// kod dla ARDUINO UNO w trybie odbioru Serial

#include <SoftwareSerial.h>

SoftwareSerial mySerial(2, 3); //rx pin 2,  tx pin 3

char buff[9]; //Initialized variable to store recieved data // bufor na odbierane dane, w moim przypadku 9 znaków do odbioru
byte count;

void setup ()
{
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial)
 {
    ; // wait for serial port to connect. Needed for native USB port only
 }

  Serial.println("Start");
  mySerial.begin(9600);
  //mySerial.println("mySerial_begin");  //wyswietla w serialu sprzętowym inicjalizacje serialu sprzętowego

Serial.println("Start programu..");
}

void loop()
{
while (mySerial.available()>0)
  {
    buff[0]=mySerial.read();  //
    if (buff[0]==0x7B)  //sprawdza czy pierwszy bajt jest poprawny i jest to znak 0x7B (HEX) czyli "{"
    count=1;

      while (count<9)
      if (mySerial.available()>0) // jesli transmisja na serial software aktywna przechodzi dalej.
        {
         buff[count]=mySerial.read(); //odczyt z serial software
         count++;
        }
 
        if (count==9 && buff[8]==0x7D) // kontrola ostatniego bajtu/znaku (9 znak), w przypadku prawidłowego znaku kontynuacja
          {
          for (byte i=0;i<9;i++)  //zapisujemy do tabeli buff kolejne znaki odebrane
            {
              Serial.print(buff[i]);
              Serial.print(",");
            }

          Serial.println();
  float tempodczyt1 = (((buff[1]-48)*100)+((buff[2]-48)*10)+((buff[3]-48)+0.001))/10-30;
  Serial.println(tempodczyt1);
    float tempodczyt2 = (((buff[5]-48)*100)+((buff[6]-48)*10)+((buff[7]-48)+0.001))/10-30;
  Serial.println(tempodczyt2);
  }
 
 Serial.println("pauza pętli..");
  delay (250);
 
 }
}

 

Mega ma za zadanie odbierać dane z czujnika, przetworzyć je i wysłać przez Serial do ESP modułu wi fi, który będzie czekał na transmisję i po 5 minutach za pomocą strony php dodawał temp do bazy danych. Mega także ma obsługiwać wyświetlanie temperatur.

Dzięki takiemu połączeniu ESP i wykonanie na nim komunikacji z bazą nie będzie spowalniane przez termometry i tm1637 😄

W monitorze serial odbierania :

Cytat

Start
...
{,5,1,0,X,5,2,0,},
21.00
22.00
pauza..

{,5,1,0,X,5,2,0,}, odebrane bajty

21.00 - po przeliczeniu na wartość mierzoną przez DS.

Link do komentarza
Share on other sites

8 godzin temu, szczepulek napisał:

Pierwsza sprawa, oba moduły muszą być połączone masami (GND) by krzaczków nie było

Dla mnie to "oczywista oczywistość" i nawet do głowy by mi nie przyszło, że można popełnić taki błąd. Niestety, początkujący, nie znają podstaw elektroniki a efekty są jakie są, kilka godzin/dni/tygodni szukania tak błahego błędu. W jeszcze większe zdumienie może wprowadzić brak bezpośredniego połączenia mas, które jednak zamykają się przez kable USB czy kable programatora. Wtedy stopa błędów wzrasta i ciężko znaleźć przyczynę. Najciekawsze jest jednak to, że gdy odłączy się kabel programujący komunikacja przestaje działać. Wygląda na siły nieczyste.

Inny temat, to RS485/422. Tu w grę wchodzi często wymuszenie stanu spoczynkowego linii, jak go nie ma to pojawiają się np problemy z odbiorem pierwszych bajtów. Z masami też mogą być problemy. Wiele osób myśli, że mas nie trzeba łączyć w RS485/422. Aby na to odpowiedzieć trzeba by napisać niemały artykuł. W skrócie, gdy nie ma  izolacji galwanicznej, potencjał mas należy wyrównać ale nie łącząc masy bezpośrednio tylko przez rezystor o niewielkiej rezystancji. Pojawi sie też problem gdy urządzenie ma filtr wejściowy 230V połączony z PE a PE z GND. Gdy PE nie będzie podłączone do ziemni lub choćby zerowania może być źle, łącznie z uwolnieniem magicznego niebieskiego dymu z układów scalonych.

Co do zapisu danych na serwer, rozwijam soft

Dodałem obsługę NTP oraz pomiar czau wykonania pętli głównej. O różnicach czasu wysyłania danych na Thingspeak a własnych serwer lokalny lub zdalny napisałem w artykule o odczycie licznika ORNO, więc tu nie będę tego powtarzał, kto jest ciekaw sam przeczyta i pewnie będzie w szoku. Interesujące dla @szczepulek może być informacja o czasie wykonania pętli głównej. W przypadku programu do licznika ORNO jest to ok 60us, zwiększa się do 500..600us w czasie odpowiedzi na zapytanie GET (serwer HTTP). Max czas, przy wyłączonym thingspeak, nie przekracza 2ms. Naturalnie na UNO czy MEGA czasy te będą zdecydowanie dłuższe, spodziewałbym się tak ok 10 razy, ale 20ms jest jak najbardziej do zaakceptowania.  Gdy czas wykonania przekracza 50ms, należy zastanowić się nad zamianą sposobu działania programu, być może trzeba sięgnąć po RTOS. Przekroczenie 100ms, nazwałbym "skandalem". Oczywiście wiele programów może działać gdy pętla wykonuje się kilka czy kilkadziesiąt sekund ale warto pamiętać, że czas reakcji człowieka to ok 100ms. Jak program reaguje z opóźnieniem 500ms to wyraźnie to widać i obsługa urządzenia jest nieprzyjemna.

Człowiek to człowiek, gorzej gdy trzeba reagować na zdarzenia z urządzeń zewnętrznym, np zapytania z serwerów czy po UART. Wiele protokołów (np SAS) dopuszcza maksymalny czas na odpowiedź 100ms. Akurat z tym problemem pewna grupa osób (na szczęście nie grupa trzymająca władzę) nie mogła sobie poradzić z przesyłaniem danych w sieci lokalnej w 100ms. Czasem się udało, czasem nie. W konsekwencji nie można było przez SAS dokonywać operacji finansowych. Problem był złożony i trzeba było robić protezy. Po raz kolejny nieudolność programistów dysponujących GHz i GB trzeba było wspomagać małym uC z MHz i kB.

Na koniec mogę napisać, że soft ORNO jest napisany kiepsko. Odpowiedź przychodzi w ok 50ms. jak dla mnie to wieczność. Nie wiem jakim problemem było napisać odpowiedź na zapytania w przerwaniu? Jeszcze na 8051 nie miałem problemu aby odpowiedzieć na zapytanie w ok ms.

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

Dnia 16.10.2019 o 22:08, RFM napisał:

Jak chcesz dam Ci kody obsługi 1-Wire, które nie zawieszają przerwań a co ciekawsze,  mogą obsługiwać komunikacje na przerwaniach, co prawda nie dla overdrive, ale termometry nie obsługują tego trybu..

A czy ja też mogę prosić o te kody? Dzięki z góry. email na prv.

--------------------------

Dziękuję Ci bardzo @RFM  przejrzałem pobieżnie i już widzę, że się przydadzą, brakuje chyba jedynie twi.h ale damy radę, to co aktualnie potrzebuje jest, tak więc dzięki za oszczędzony czas i pozdrawiam.

Edytowano przez Anonim
Podziękowanie
Link do komentarza
Share on other sites

33 minuty temu, Elvis napisał:

Ja bym radził również powstrzymać się od komentowania pracy innych i określania ich jako np. kiepskich programistów. W końcu widzieliśmy próbki programowania autora tej opinii, więc może ktoś dojdzie do wniosku, że wcale nie jest najwyższej jakości kod - a po co sobie przykrości sprawiać na forum.

Jeśli by mnie ktoś określił takim mianem kiepskiego programisty, bym sie nie obraził.. w końcu nie odbiega to od prawdy :D, za każdym razem jak spoglądam na kod, widzę nieścisłości.. i rzeczy które można lepiej sprawniej zrobić, zaglądając do bibliotek, faktycznie zauważyć można zapisy w kodzie które można usprawnić jeśli się ma wiedzę. Jak się ją ma.. to jak wspomniał RFM, pisze się samemu. 🙂 Mi daleka droga do tego, co nie znaczy że nie będę próbował.

Ważne że jakieś  postępy robię, może nie koniecznie dobrą drogę obrałem.. to ja dziecku dać kalkulator, zamiast nauczyć tabliczki mnożenia.. no ale 😜

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.