Skocz do zawartości

Jak pisać biblioteki na Arduino?


macizet

Pomocna odpowiedź

Tak na szybko.

Najpierw drobiazg:
 

#ifndef temp_sensor_H
#define temp_sensor_H

...

#endif

zamieniasz na
 

#pragma once

podobno wszystkie porządne kompilatory to rozumieją (gcc na pewno).

Dalej:

38 minut temu, jacabe napisał:

temp_sensor::temp_sensor(uint8_t pin) {
	_pin = pin;
	begin(); // to wywal i wywołuj po prostu w setup
}

 

 

40 minut temu, jacabe napisał:

pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, HIGH); 

 

To masz w setup, a powinno być w bibliotece, natomiast:

41 minut temu, jacabe napisał:

Serial.begin(9600);

 

to masz w bibliotece, a powinno być w setup() (biblioteka w tym przypadku nie ma prawa wiedzieć z jaką prędkością działa serial, a nawet czy w ogóle działa).

I zacznij od czegoś najprostszego - choćby od sprawdzenia, czy po zmianach po wywołaniu begin() pokaże się "start" na terminalu. Jeśli tak - to jesteś na dobrej drodze. Jeśli nie - pomyślimy...

Link do komentarza
Share on other sites

zrobilm jak radziles.

void setup(void)
{
  // start serial port
  Serial.begin(9600);

  pinMode(button1, INPUT_PULLUP);
  
  Tsensor.begin();
  // Start up the library
  //temp.begin();
  //oneWire.reset_search();
  //delay(1000);

}

/*
   Main function, calls the temperatures in a loop.
*/

uint8_t TC;
uint8_t idx;
bool search_ok;
uint8_t tempcnt;


void loop(void)
{

  //TC = EEPROM.read(TCcount);
  TC = 0;
  idx = 0;
  search_ok = false;
  uint8_t licz = 0;


  Serial.println("start");

  while(1);

w terminalu pojawia sie "st" ze slowa start i nic wiecej...

jakis progres jest.

 

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

 

void temp_sensor::begin(){

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

 

Edytowano przez jacabe
Link do komentarza
Share on other sites

Zaraz zaraz... ale ten Serial.println("start") to miał być w begin a nie loop();

I nie dawaj w takich przypadkach gołego while(1) tylko coś w stylu:

while(1) delay(1);

a w ogóle najlepiej dać jakiegoś większego delaja przed taką kończącą pętlą aby mieć pewnośc, że pokończył wszystko co tam się działo (np. powysyłał wszystko z buforów).

Link do komentarza
Share on other sites

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.

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

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 🙂

Link do komentarza
Share on other sites

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.

Link do komentarza
Share on other sites

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. 

Link do komentarza
Share on other sites

@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
Link do komentarza
Share on other sites

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ć 🙂

 

Link do komentarza
Share on other sites

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
Link do komentarza
Share on other sites

@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?

Link do komentarza
Share on other sites

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.

Link do komentarza
Share on other sites

@jacabe To po dwukropku to tzw. lista inicjalizacyjna konstruktora - https://pl.wikipedia.org/wiki/Lista_inicjalizacyjna_konstruktora. Czyli piszesz tam jakich członków klasy chcesz zainicjalizować jaki argumentami/wartościami. Tutaj DS(oneWire) - przypisz referencji DS referencje do obiektu oneWire przekazanego jako argument konstruktora.

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

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);

 

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.