Skocz do zawartości

Jak pisać biblioteki na Arduino?


Pomocna odpowiedź

Robilem i w loop ten napis i w begin. Poza tym jak zakomentuje linie z Ds to dziala, jak przerzucilem start nad linie konstruktora OneWire to tez caly napis wysyla. Wiec pies jest pogrzebany w konstruktorze DS.

Jak znajdę termometr (gdzieś jeden powinien leżeć) to spróbuję to uruchomić... ale to już nie dzisiaj, mam dwa arduina podłączone do kompa (pro mini i uno) i za chwilę zaprogramuję nie ten co trzeba 🙂

Zaraz...

Dlaczego:

private:
	OneWire &DS;

a nie na przykład:

private:
	OneWire DS;

Przecież nie tworzysz instancji OneWire w konstruktorze ani nie przekazujesz istniejącego obiektu OneWire (tak jak w bibliotece do DS18B20)...

Poza tym ja nie cierpię nadużywania "private" tam gdzie powinno być "protected"... ale to takie moje prywatne wydumki.

Tak wyczytalem w sieci, ja chce stworzyc obiekt onewire w mojej bibliotece. Jak wpisuje bez lacznika and to wyskakuje mi ze konstruktor jest niekompletny.

Ja jestem bardzo poczatkujacym w cpp. Jak pisalem na poczatku poszukalem w sieci ale tam niewiele znalazlem i dlatego zwrocilem sie z pytaniem na forum. 

(edytowany)

@jacabe ciekawe, że kompiluje Ci się ten kod, nawet gdy nie masz  zainicjalizowanej referencji w konstruktorze (o czym zaraz):

private:
	OneWire &DS;

Tutaj: https://godbolt.org/z/cK2DBS minimalny kod, który pokazuje to co chcesz osiągnąć - sprawdź ostrzeżenia (które na razie wiele nie mówią).

5 godzin temu, jacabe napisał:

jak zakomentuje w bibliotece jedna linie to pojawia sie caly napis "start"


void temp_sensor::begin(){

  //DS = OneWire(_pin);
  ...
}

No bo właśnie tutaj jest kolejny mega poważny problem - próbujesz do DS przypisać referencję do obiektu tymczasowego, przykład z wyjaśnieniem: https://godbolt.org/z/dHwdFs (sprawdź okno po prawej na dole - wydrukowane informacje do konsoli z programu). Pewnie dlatego po za komentowaniu reszta kodu zaczyna działać. A dlaczego tak nie można robić to znajdziesz tutaj: https://www.quora.com/Why-cant-you-return-a-local-variable-by-reference

To co nieświadomie chciałeś zrobić - to tak implementuje się wstrzykiwanie zależności, tylko wtedy tą referencję DS trzeba przypisać w konstruktorze np. tak: https://godbolt.org/z/pqHKEU. A jak chcesz stworzyć obiekt bezpośrednio w klasie, tak jak wskazywał @ethanak to robisz tak: https://godbolt.org/z/uy-D2t

@ethanak Sporo best practices własnie nie poleca #pragma once, bo nie wszystkie kompilatory implementują, #ifndef #define #endif akurat zrozumie każdy. Dlatego jak piszemy biblioteki (jak w tym temacie) to raczej powinniśmy używać tego drugiego 😄 

Edytowano przez Matthew11
  • Lubię! 1
6 godzin temu, Matthew11 napisał:

Sporo best practices własnie nie poleca #pragma once, bo nie wszystkie kompilatory implementują

Podaj przykład 🙂

Oczywiście są takie miejsca gdzie include guards będzie lepszym rozwiązaniem - w większości przypadków #pragma once jest lepsza (a przynajmniej czytelniejsza, i nie zajmuje niepotrzebnie przestrzeni nazw). A szczególnie w przypadku początkujących programistów czytelność jest bardzo ważna. Tam mi się przynajmniej wydaje i nikt nie musi się z tym zgadzać 🙂

 

(edytowany)
58 minut temu, ethanak napisał:
7 godzin temu, Matthew11 napisał:

Sporo best practices własnie nie poleca #pragma once, bo nie wszystkie kompilatory implementują

Podaj przykład 🙂

Jasne, C++ Core Guidelines, Autosar C++14 punkt 6.16.7. Natomiast, mój argument - "bo nie wszystkie kompilatory implementują" - nie był za bardzo trafny...

Edytowano przez Matthew11
  • Lubię! 1

@Matthew11Prosiłem o przykład kompilatora który tego nie implementuje a nie jakichś wytycznych, które co prawda mówią że "nie" ale nie mówią dlaczego (to już w Wikipedii znajdziesz więcej materiału na ten temat wraz z konkretnymi przykładami).

Pytanie: jeśli GCC (którego tu wszyscy przy Arduino używamy) oferuje jakąś dodatkową możliwość, czy mamy z niej nie korzystać? W imię czego... czystości języka? Kompatybilności z Turbo C 2.0?

Dziekuje kolegom @Matthew11  i @ethanak za pomoc.

wykonalem co napisales @Matthew11

temp_sensor.cpp:

temp_sensor::temp_sensor(OneWire& oneWire):DS(oneWire)
{  
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, LOW);
}

temp_sensor.h:

public:

  uint8_t termo[8];
  
  temp_sensor(OneWire& oneWire);
  //void begin();
  bool search_ds(uint8_t cnt);
  uint8_t save_TCS(uint8_t *rom, uint8_t cnt);
  void get_temp(uint8_t Tsensor);
  bool porownaj(uint8_t *rom, uint8_t cnt);
  void start_measT();

private:

  OneWire &DS;

plik main:

void loop(void)
{

  TC = 0;
  idx = 0;
  search_ok = false;
  uint8_t licz = 0;


  Serial.println("start");

  
  while (1) {

    if (!search_ok) search_ok = Tsensor.search_ds(TC);


    if (search_ok == 1) {
      Serial.print(".");

      if (digitalRead(button1) == push) {

        idx = Tsensor.save_TCS(Tsensor.termo, TC);
        if(idx == 1){
          TC++;
          search_ok = 0;
        }
        delay(1000);
      }
    }


    if (idx > 0) {
      for (uint8_t x = 0; x < TC; x++) {
        Tsensor.get_temp(x);
      }
      
      Tsensor.start_measT();
      delay(1500);
    }
  }
}

Dziala 👌

wytlumaczcie mi prosze te linijke :   temp_sensor::temp_sensor(OneWire& oneWire):DS(oneWire) 

co ona robi po dwukropku?

Bede praktykowal i sie uczyl dalej, w razie zaciecia bede prosil o pomoc.

  • 10 miesiące później...

Witam panowie.. mam takie dreczace mnie pytanie na ktore za chiny nie moge znalezdz odpowiedzi..mianowicie mam plik naglowkowy "h" gdzie w bibliotekach znajduje skladnie funkcji, w przypadku funkcji z agrumentami czasem mam tylko typ zmiennej a czasem typ zmiennej z nazwa...no i nie moge rozgryzdz po co jest tam ta nazwa argumentu skoro juz w pliku "cpp" i tak od nowa tworze typ i nazwe tego argumentu? (no chyba ze wtedy nie musze pisac juz typu) 

Dla przykladu 

void TEST(uint8_t);
//lub
void TEST(uint8_t test);

 

@farmaceuta Sprawa jest prosta, deklaracja funkcji (czyli dokładnie to co podałeś - funkcja bez jej ciała/implementacji) musi zawierać jedynie nazwę typu/typów argumentów jakie przyjmuje - nie muszą te argumenty mieć nazw.

Dlatego możesz spotkać się właśnie z sytuacją gdy ktoś w .h przy deklaracjach nie podaje nazw argumentów lub je po prostu podaje - wtedy nie musisz zaglądać do pliku z implementacją żeby zrozumieć o co chodzi. Obie sytuacje są ok. Co więcej, w pliku .h możesz nazwać argument np:

// .h
void fun(int nazwa);

a w pliku z implementacją możesz ten argument nazwać inaczej:

// .c/.cpp
void fun(int innaNazwa){}

i też to będzie ok z punktu widzenia kompilatora, z punktu widzenia użytkownika biblioteki już niekoniecznie. 

Czasami możesz się też spotkać z sytuacją że dostawca oprogramowania dostarcza Ci plik .h a implementację już w postaci skompilowanej biblioteki - gdzie nie masz już dostępu do implementacji, jeśli argumenty w pliku .h nie byłyby nazwane to trochę trudno by się pracowało z taką biblioteką 😛   

  • Lubię! 1
  • Pomogłeś! 1
24 minuty temu, Matthew11 napisał:Dlatego możesz spotkać się właśnie z sytuacją gdy ktoś w .h przy deklaracjach nie podaje nazw argumentów lub je po prostu podaje - wtedy nie musisz zaglądać do pliku z implementacją żeby zrozumieć o co chodzi. Obie sytuacje są ok.

 

Tak wlasnie myslalem ze w pliku .h podaje nazwy do argumentow tylko po to zebym mogl szybciutko sprawdzic/domyslic sie do czego co sluzy zamiast wertowac mnostwo linii .cpp

Sprawdzalem tak dla testu z tymi nazwami i w kazdym przypadku biblioteka dziala prawidlowo, ale wolalem sie upewnic i zapytac madrzejszych zeby pozniej placzu nie bylo ze w jakiejs specyficznej sytuacji moga pojawic sie bledy w dzialaniu😉

Bardzo dziekuje za odpowiedz i poswiecony czas!🙂

A jeszcze takie pytanko..

Wszystkie zmienne ktore sa deklarowane po za funkcjami w pliku .cpp zachowuja sie jak zmienne globalne tak? Tylko czy one sa globalne tylko w bibliotece czy w  calym szkicu w ktorym jest glowny kod?

4 minuty temu, farmaceuta napisał:

Wszystkie zmienne ktore sa deklarowane po za funkcjami w pliku .cpp zachowuja sie jak zmienne globalne tak? Tylko czy one sa globalne tylko w bibliotece czy w  calym szkicu w ktorym jest glowny kod?

Są "globalne" w tym konkretnym .cpp - tylko w nim są widoczne. 

  • Pomogłeś! 1

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