Skocz do zawartości
marboz

Miernik długości przewodów

Pomocna odpowiedź

Cześć,  zbudowałem urządzenie do odmierzania długości przewodów, wężyków itp.  Długość mierzę po przez obroty rolki o średnicy 30 mm na boku której zamontowałem 6 magnesów. Do zliczania użyłem TLE4905L Czujnik Halla unipolarny.  Jeden  obrót koła to ok 9,5 cm.  Niby wszystko działa i pomiar jest powtarzalny jeżeli tylko przewód ciągnę stosunkowo wolno, jeżeli znacznie przyśpieszę (obroty rolki są większe) to czujnik gubi impulsy. 

Jestem 46 letnim świerzakiem jeżeli chodzi o arduino i programowanie. Jako że dwa tygodnie temu napisałem pierwszą linijkę kodu c++ i podłączyłem cokolwiek do arduino nie jestem pewny czy kod który się wykonuje jest prawidłowy lub  czy może czujnik nie nadaje się do tego zastosowania. Może ktoś z Was coś doradzi. Zmieniałem już rolkę na taką z 1 magnesem ale przy szybszych obrotach dzieje się to samo. Sprawdziłem też czas wykonywania petli - 15-16 milisekund. 

Szukam w necie od kilku dni informacji ale nic nie udało mi się znaleźć, przynajmneij nic co mógłbym zrozumieć ☺️ Za cenne uwagi będę wdzięczny.

 


#include <Wire.h>              // standardowa biblioteka Arduino
#include <LiquidCrystal_I2C.h> // dolaczenie pobranej biblioteki I2C dla LCD

LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); // Ustawienie adresu ukladu na 0x27

long start; //mierzy czas wykonywania pętli
int licznik = 0;
int czy_otwarte = 0;
int ostatni_stan = 0;

void setup()
{

  // put your setup code here, to run once:
  Serial.begin(9600);
  lcd.begin(16, 2); // Inicjalizacja LCD 2x16
  pinMode(4, INPUT_PULLUP);
}

void loop()
// put your main code here, to run repeatedly:
{
  start = millis(); //mierzy czas wykonywania pętli
  {

    {
      if (ostatni_stan == 0 && (digitalRead(2) == 1))
      {
        licznik++;
        ostatni_stan = 1;
        czy_otwarte = 1;
      }
      else if (ostatni_stan == 1 && (digitalRead(2) == 0))
      {
        ostatni_stan = 0;
        czy_otwarte = 0;
      }
    }

    {
      int sensorVal = digitalRead(4);
      if (sensorVal == LOW)
      {
        licznik = 0;
      }
    }
    Serial.println(licznik);
    lcd.clear();                  // Czysci ekran
    lcd.setCursor(0, 0);          // Ustawienie kursora w pozycji 0,0 (pierwszy wiersz, pierwsza kolumna)
    lcd.print((licznik)*15 / 10); //wyswietla dane
    delay(10);
  }
  Serial.println(millis() - start); //wyświetla czas wykonywania pętli
}


   

20200309_182007.jpg

  • Lubię! 2

Udostępnij ten post


Link to post
Share on other sites

Bardzo ciekawy projekt moim zdaniem i warto go doprowadzić do szczęśliwego końca 🙂

Zacznijmy od jednego:

Jeśli czas obrotu pętli będzie 15 msec, to nie będziesz mógł mierzyć impulsów przychodzących częściej niż co 30 msec - a więc ok. 33 razy na sekundę. Przy 6 magnesach będzie to raptem 5.5 obrotu koła na sekundę, czyli nie możesz przeciągać przewodu przez miernik szybciej niż pół metra na sekundę. Ot - takie prawa matematyki, których się nie przeskoczy...

Spójrzmy na program.

Przede wszystkim rzuca się w oczy delay(10). Po co on tam? Po to żeby spowolnić działanie pętli, prawda? A czym się objawi spowolnienie działania pętli? Zmniejszeniem w Twoim przypadku maksymalnej prędkości przeciągania przewodu. Pewnie gdybyś to wywalił to osiągnąłbyś jakieś 1.5 m/s - ale to i tak za mało.

Patrzmy dalej.

Zacznijmy od tego, że nie w ogóle ustawiasz pinu 2 jako wejście czy wyjście, w teorii powinien być ustawiony jako INPUT...  ale lepiej to w setup() wstawić.

Jak mniemam, sensor podłączony jest właśnie do pinu 2, a pin 4 to jakiś wichajster do kasowania licznika? To dlaczego zmienna w której przechowujesz stan wichajstra nazywa się sensorVal (co by sugerowało, że tam siedzi wartość odczytana z sensora) a dużo ważniejszej wartości (czyli tej z sensora) w ogóle do żadnej zmiennej nie wrzucasz? Jest to nieco niebezpieczne, ponieważ może zaistnieć taka sytuacja:

// ostatni_stan jest równy 1, wejście jest w stanie niskim

if (ostatni_stan == 0 && (digitalRead(2) == 1))
      { // ta część wyrażenia nie zadziała i prawidłowo
        licznik++;
        ostatni_stan = 1;
        czy_otwarte = 1;
      }
      else
        /* i w tym momencie zaczynają się dziwne rzeczy.
         * magnes przechodzi przed sensorem i stan wejście
         * zmienia się na wysoki
         */
        if (ostatni_stan == 1 && (digitalRead(2) == 0))
      { // ta część wyrażenia nie zadziała bo wejście zdążyło zmienić stan między pomiarami
        ostatni_stan = 0;
        czy_otwarte = 0;
      }

Uwierz mi - choć wygląda to na mało prawdopodobne, ale według praw Murphy'ego te najmniej prawdopodobne rzeczy zdarzą się akurat wtedy, kiedy będą przeszkadzać.

Przede wszystkim:

  • dopisz jakieś komentarze w kodzie (bo komentarz przy lcd.print() że coś wyświetla jest raczej niespecjalnie przydatny, ale przydały by się np. który pin jest do czego)
  • pozbądź się delayów
  • popraw ten fragment który mi się nie podoba

Oczywiście, nie będzie to jeszcze docelowa wersja programu (o niej następnym razem, nie chcę robić kilku rzeczy na raz bo będziesz miał galimatias w głowie) - ale powinna działać "nieco" lepiej... poza tym zdaje się że chcesz się czegoś nauczyć a nie zbudować jedno Bardzo Mądre Urządzenie Którego Nie Ma Żaden Sąsiad i osiąść na laurach 🙂

Pokaż poprawiony kod i będziemy kombinować dalej.

 

  • Lubię! 2

Udostępnij ten post


Link to post
Share on other sites

@ethanak 

Dzięki wielkie, wezmę się wieczorem do roboty. Niestety tak to jest jak kopiuje się różne zlepki kodów i łączy w całość z braku wiedzy.  Mechanicznie zdecydowanie lepiej mi to wychodzi :)

Ten delay(10) wstawiłem bo inaczej cyfra na wyświetlaczu wygląda jakby się mieniła - nie wiem jak to określić. 

Udostępnij ten post


Link to post
Share on other sites
(edytowany)
6 minut temu, marboz napisał:

Ten delay(10) wstawiłem bo inaczej cyfra na wyświetlaczu wygląda jakby się mieniła - nie wiem jak to określić. 

Wiem o co chodzi - możesz zrobić bardzo prostą rzecz:

// gdzieś tam zmienna globalna
int poprzedni_licznik;

// a w loop taka konstrukcja:

if (poprzedni_licznik != licznik) {
    poprzedni_licznik = licznik;
    Serial.println(licznik);
    lcd.clear();                  // Czysci ekran
    lcd.setCursor(0, 0);          // Ustawienie kursora w pozycji 0,0 (pierwszy wiersz, pierwsza kolumna)
    lcd.print((licznik)*15 / 10); //wyswietla dane
}

Można by też wyświetlać licznik zaraz po inkrementacji (licznik++), ale wtedy trzeba by było drugi kawałek kodu aby wyświetlić przy kasowaniu.

6 minut temu, marboz napisał:

Dzięki wielkie, wezmę się wieczorem do roboty.

OK - czekamy.

6 minut temu, marboz napisał:

Mechanicznie zdecydowanie lepiej mi to wychodzi 🙂

A mi odwrotnie 🙂

Edytowano przez ethanak
  • Lubię! 1
  • Pomogłeś! 1

Udostępnij ten post


Link to post
Share on other sites

Widzę że wieleeeee nauki przede mną 🙂 

 

Udostępnij ten post


Link to post
Share on other sites
(edytowany)

No niestety - takie hobby sobie znalazłeś że choćbyś się nawet wszystkiego nauczył - to przez ten czas powstanie coś nowego. Ja mam nieco więcej lat niż Ty, coś koło 40 lat zabawy z komputerami... a i tak cały czas coś nowego poznaję 🙂

 

Edytowano przez ethanak
  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites
(edytowany)
3 godziny temu, marboz napisał:

Widzę że wieleeeee nauki przede mną

Do opanowania arduino nie aż tak dużo żeby się za głowę łapać 🙂 Polecam poćwiczyć język C++ na na aplikacjach konsolowych w systemie operacyjnym, będzie duuuużo łatwiej pisać programy do arduino.

W tym projekcie aż się samo narzuca użycie przerwań od zmiany stanu pinu. Coś pomożemy jak będą postępy 🙂

2 godziny temu, ethanak napisał:

No niestety - takie hobby sobie znalazłeś że choćbyś się nawet wszystkiego nauczył - to przez ten czas powstanie coś nowego. Ja mam nieco więcej lat niż Ty, coś koło 40 lat zabawy z komputerami... a i tak cały czas coś nowego poznaję

Myślę, że należałoby się skupić na jakości niż lepszości w nowości. Sprawny programista elektronik wyciśnie więcej z AVR niż lamer z superkomputera. 🙂

Edytowano przez atMegaTona
literówki

Udostępnij ten post


Link to post
Share on other sites

Jedyna moja styczność z programowaniem to do tej pory vba w Escelu 🙂  Ale wziąłem się ostro za to bo na biurku z 50 rożnych czujników do testów. Niestety nie jest to moje jedyne hobby 🙂   W moim przypadku mam syna w I klasie technikum informatcznego i jak się dowiedziałem że zaczynają programować w c++ to myślałem że go wciągnę w arduino a tym czasem wciągnąłem siebie 😄

Kod poprawie wieczorem i zobaczymy co tam można dalej wymyślić. Niestety jak teraz czytam ten kod to wiem że choć działał ( nie do końca jak widać) to ja nie byłem pewny jak wklejając ślepo  skrawki tego co miałem przygotowane. 

Udostępnij ten post


Link to post
Share on other sites
2 minuty temu, marboz napisał:

Niestety jak teraz czytam ten kod to wiem że choć działał ( nie do końca jak widać) to ja nie byłem pewny jak wklejając ślepo  skrawki tego co miałem przygotowane. 

Aż tak źle nie jest, widziałem już lepszych magików a jeszcze pieniędzy za to chcieli 😄 Nie od razu Kraków zbudowano, małymi kroczkami traktując sprawę jako zabawę i z czasem będzie coraz lepiej.

Udostępnij ten post


Link to post
Share on other sites

@atMegaTona nie uprxedaz faktów - o prxerwaniach chciałem potem, po pokazaniy że w tej postaci nawet po poprawkach to nie ma prawa działać.

Udostępnij ten post


Link to post
Share on other sites

Większość kodu i tak będzie w przerwaniu więc trzeba będzie przepisać program od nowa ale masz rację -  nie wszystko na raz.

Udostępnij ten post


Link to post
Share on other sites

Czemu większość? W przerwaniu tylko inkrementacja licznika.

Udostępnij ten post


Link to post
Share on other sites

Bo to właśnie większość programu nie licząc wyświetlacza. Fajnie byłoby to zrobić w taki sposób, żeby mierzyło ten przewód co do centymetra. Dysponując drukarką 3D można łatwo dorobić kółko do czujnika szczelinowego, wtedy precyzja pomiaru znacznie wzrośnie a zamiast przerwania zmiany stanu wykorzystać timer w trybie ic... można też pójść na piwo. Najlepiej jak @marboz sam określi czego oczekuje po tym swoim wynalazku ;p

Udostępnij ten post


Link to post
Share on other sites

No przecież to ustrojstwo na razie mierzy do 1.5 cm... nic tu nie poprawisz, z wyjątkiem mierzenia dłuższych odcinków (przejście na floaty przy wyświetlaniu).

Poza tym kolega wątkotwórca - jak sam pisał - dobrze się czuje w mechanice i tego uczyć go nie musimy (przynajmniej ja mimo posiadania drukarki 3d nie mam najmniejszego zamiaru).

Mogę zasugerować więcej poprawek, ale umówmy się: kolega ma się czegoś nauczyć. Czujesz się dobrze jako nauczyciel?

 

Udostępnij ten post


Link to post
Share on other sites

No to nie brzmi optymistycznie 😂   Mierzy z dokladnością nawet do 1 cm ale to dla mnie ok czyli w granicach błędu, to nie do apteki. Bardziej chodzi mi o to żeby wynik był powtarzalny bez względu na prędkość 🙂

Owszem, zaprojektowac i wydrukować mogę co chcę bo to moje klimaty ale wydaje mi się że to będzie ok. Kwestia czy będzie potrafiło działać prawidłowo przy takim czy innym kodzie 🙂 Biorę się do roboty.

Biorę się za kod.

Udostępnij ten post


Link to post
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!

Gość
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...