• Witaj na Forum Arduino Polska! Zapraszamy do rejestracji!
  • Znajdziesz tutaj wiele informacji na temat hardware / software.
Witaj! Logowanie Rejestracja


Ocena wątku:
  • 0 głosów - średnia: 0
  • 1
  • 2
  • 3
  • 4
  • 5
Stabilizator obrotów silnika spalinowego
#21
Witam,
Jeszcze co by serwo nie wykonywało gwałtownych ruchów:
Kod PHP:
#include <Servo.h> //Biblioteka odpowiedzialna za serwa
#define hallPin 2 //hall na pinie 2

Servo serwomechanizm //Tworzymy obiekt, dzięki któremu możemy odwołać się do serwa 
volatile byte pozycja 0//Aktualna pozycja serwa 0-180
unsigned long przerwa//czas miedzy 'mignieciami' niskiego stanu halla

void setup() { 
 
pinMode(hallPinINPUT_PULLUP); //ustawienie halla
 
serwomechanizm.attach(11);  //Serwomechanizm podłączony do pinu 11
 
Serial.begin(9600);


void loop() 

// zmmenna pomocnicza do oblicznia sredniej z 10-ciu pomiarow
byte licznik 0;
// zmienna do obliczenia sredniej arytmetycznej 
unsigned long srednia 0;
// zmienna pomocnicza pojedynczego odczytu
unsigned int odczyt;
// petla w ktorej obliczana jest serdnia z 10-ciu pomiarow
// z eliminacja odczytow z poza zakresu 
while (licznik 10)
{
 
 // odczyt 
 
 odczyt pulseIn(hallPinLOW);
 
 // sprawdzenie czy w zakresie
 
 if ((odczyt 2200)&&(odczyt 3250))
 
   {
 
     // jesli tak to dodanie wyniku do poprzednich
 
     srednia += odczyt;
 
     licznik++;
 
   }
}
// obliczenie sredniej
srednia /= 10;
// Obliczenie pozycji ktora serwo powinno osiagnac
byte obl_pozycja map(srednia32502200900);
// warunki sluzace "dazeniu" serwa do obliczonej pozycji
if(pozycja obl_pozycjapozycja++;
if(
pozycja obl_pozycjapozycja--;
serwomechanizm.write(pozycja); //Wykonajujemy ruch

delay(250);


Jeśli nadal będzie niezadawalająco to zrealizujemy określanie prędkości nie w oparciu o funkcję pulseIn().
Pozdrawiam,
Tomek.
 
Odpowiedź
#22
Psiakrew.

Utknąłem z próbami - wściekłe deszcze dostały się do elektryki i zalały... immobilizer. Tak, moja kosiarka posiada immobilizer, usunięcie go było zbyt skomplikowane. Mam nadzieję, że suszarka do warzyw Żony poradzi sobie z problemem, bo szukanie w internecie "jak usunąć/ominąć immobilizer" mija się z celem. Tajne przez poufne, zjeść przed przeczytaniem.

... zupełnie jakby ktoś chciał kraść skodę felicję Smile
>Robimy dziś grilla?
<ok. będę potrzebował: wiertarkę, arkusz blachy…
 
Odpowiedź
#23
Witam po przymusowej przerwie.
Cudowne ozdrowienie - nie dość, że imo potraktowane jak warzywo wyzdrowiało i silnik znów pali "od pierwszego kopa", to i ten ostatni kod przekonał wreszcie serwo.
Przestało wyrażać orczykiem swoją dezaprobatę Smile
Powalczyć muszę trochę z czasem reakcji (zrobiło się zbyt ślamazarne przy reakcji na zmianę obrotów). Sama zmiana delay-a, nawet na 10, niewiele pomogła. Spróbuje pokombinować z "pozycja++/--".
jak już się z tym uporam (pełen optymizmu zakładam, że dam radę Smile - następnym krokiem będzie dołożenie "prztyczka", celem zmiany "trybu pracy" naszego regulatora.
Robiąc puszkę na Arduino i wyprowadzając na zewnątrz listwę ze śrubkami, przewidziałem możliwość dołożenia dwóch "prztyczków" do ingerencji w program - wejścia na pin 7 i 9.
Wymyśliłem to sobie tak, żeby np. załączony prztyczek zawieszał sterowanie serwem, ustawiając go przy okazji w pozycji luzującej linkę gazu.
Będzie to konieczne zarówno przy uruchamianiu silnika, dając mu czas na jego własne pomysły z automatycznym ssaniem, jak i np. przy krótkich przerwach w pracy, kiedy nie warto gasić a bez sensu żeby ryczał 2500 obrotów skoro akurat nic nie robi.
Ale wszystko po kolei, najpierw trochę "żywsze" serwo, potem dalej.
Popróbuję, pochwalę się sukcesami (albo będę skiełczał dalej Smile
>Robimy dziś grilla?
<ok. będę potrzebował: wiertarkę, arkusz blachy…
 
Odpowiedź
#24
Witam,
Delay jest w kodzie zbędne. Poza tym można zastosować implementację / dekrementacje nie o jeden lecz o więcej.
Pozdrawiam.
 
Odpowiedź
#25
Witam - trochę przerwy ale nie, prace nie ustały Smile
Chwilowo "programista" ponownie przeistoczył się w ślusarza/ spawacza/ etc.
Rozpoczął się montaż, już taki docelowy (nie na "trytki"):
-skrócenie linki gazu,
-dorobienie dla niej krańcowego uchwytu,
-wykonanie i umocowanie solidnej, metalowej obudowy dla serwa (1000++ sposobów zastosowania zamkniętych profili),
-wzmocnienie orczyka (może i to serwo ma 13kg na cm ale ten plastikowy orczyk ni jak mnie nie przekonuje),
-trochę mi zajęło wykombinować, żeby serwo ciągnęło linkę prosto (będzie na zdjęciach).

Potem szybka przeróbka programu, żeby sczytać już tak konkretnie - ile/kiedy/czego potrzeba.
Odrazu pierwsza miła niespodzianka - jak wszystko na miejscu i solidnie umocowane, jak za linkę gazu płynnie i równo ciągnie serwo (a nie moja trzęsąca się ręka) - to i odczyty równiutkie.
Oczywiście z zastosowaniem Twojego uśrednienia:
Kod:
#include <Servo.h>
#define hallPin 2

Servo serwo;
volatile byte pozycja = 0;


void setup()
    {
    serwo.attach(11);
    pinMode(7, INPUT_PULLUP);
    pinMode(hallPin, INPUT_PULLUP);
    Serial.begin(9600);
    serwo.write(pozycja);
    }

void loop()
    {
    byte licznik = 0;
    unsigned long srednia = 0;
    unsigned int odczyt;

    while (licznik < 10)
        {
        odczyt = pulseIn(hallPin, LOW);
        if ((odczyt > 1000)&&(odczyt < 10000))
            {
            srednia += odczyt;
            licznik++;
            }
        }
    srednia /= 10;

    if (digitalRead(7) == HIGH)
        {
        Serial.print("regulator OFF");
        Serial.print("\    hall =\t");
        Serial.println(srednia);
        delay(250);
        }

    if (digitalRead(7) == LOW && pozycja <= 120)
        {
        pozycja ++;
        serwo.write(pozycja);
        Serial.print("regulator ON");
        Serial.print("\     hall =\t");
        Serial.print(srednia);
        Serial.print("\   serwo =\t");
        Serial.println(pozycja);
        delay(1000);  
        }
    }

odczyt:

lator OFF    hall =    8620
regulator OFF    hall =    8575
regulator OFF    hall =    8551 -------------------//~ 800rpm = obroty biegu jałowego
regulator OFF    hall =    8602
regulator ON     hall =    8602   serwo =    1
regulator ON     hall =    8599   serwo =    2
regulator ON     hall =    8580   serwo =    3
regulator ON     hall =    8697   serwo =    4
regulator ON     hall =    8477   serwo =    5
regulator ON     hall =    8782   serwo =    6
regulator ON     hall =    8661   serwo =    7
regulator ON     hall =    8639   serwo =    8
regulator ON     hall =    5780   serwo =    9
regulator ON     hall =    3934   serwo =    10
regulator ON     hall =    3487   serwo =    11
regulator ON     hall =    3450   serwo =    12
regulator ON     hall =    3322   serwo =    13
regulator ON     hall =    3280   serwo =    14------//Optymalne obroty 2500rpm = tyle powinien utrzymywać podczs pracy
regulator OFF    hall =    3202
regulator OFF    hall =    2784
regulator OFF    hall =    2692
regulator OFF    hall =    2707
regulator ON     hall =    2707   serwo =    15
regulator ON     hall =    2746   serwo =    16
regulator ON     hall =    2618   serwo =    17
regulator ON     hall =    2562   serwo =    18------// 3000rpm = max, więcej byłoby niebezpieczne dla maszyny i okolicy :)
regulator OFF    hall =    2473
regulator OFF    hall =    2413

Jak widać silnik reaguje bardzo żwawo na najmniejsze (co stopień) drgnięcie serwa. Może nawet trochę zbyt żwawo - może będę musiał zmniejszyć średnicę bębenka/orczyka, na który nawija się linka.
A może nie - pamiętać należy, że pracuje bez obciążenia. Później, gdy przyjdzie mu kręcić blisko 80-cio kilowym wałem z bijakami, jak dojdzie opór koszonej trawy - z tej wyrywności może pozostać niewiele.

Dziś już za ciemno a i wszyscy mamy dość - ale na jutro już naszykowane to:
Kod:
#include <Servo.h>
#define hallPin 2

Servo serwo;
volatile byte pozycja = 0;
unsigned long przerwa;

void setup()
    {
    pinMode(hallPin, INPUT_PULLUP);
    pinMode(7, INPUT_PULLUP);
    serwo.attach(11);
    serwo.write(pozycja);
    Serial.begin(9600);
    }

void loop()
    {
    byte licznik = 0;
    unsigned long srednia = 0;
    unsigned int odczyt;

    while (licznik < 10)
        {
        odczyt = pulseIn(hallPin, LOW);
        
        if ((odczyt > 2200)&&(odczyt < 3400))
            {
            srednia += odczyt;
            licznik++;
            }
        }

    srednia /= 10;
    byte obl_pozycja = map(srednia, 3400, 2200, 12, 18);

    if((pozycja < obl_pozycja)&&(obl_pozycja < 13)) pozycja++;
    if((pozycja > obl_pozycja)&&(obl_pozycja > 15)) pozycja--;

    if (digitalRead(7) == HIGH)
        {
        pozycja = 0;
        serwo.write(pozycja);
        Serial.print("regulator OFF\t");
        Serial.print("\pozycja serwa=\t");
        Serial.print(pozycja);
        Serial.print("\   hall=\t");
        Serial.println(srednia);
        delay(1000);
        }
   
    if (digitalRead(7) == LOW && pozycja < 12)
        {
        pozycja ++;
        serwo.write(pozycja);
        Serial.print("trwa ustawianie...\t");
        Serial.print("\pozycja serwa=\t");
        Serial.println(pozycja);
        delay(1000);  
        }
 
    if (digitalRead(7) == LOW && pozycja >= 12)
        {
        serwo.write(pozycja);
        Serial.print("regulator ON\t");
        Serial.print("\pozycja serwa =\t");
        Serial.print(pozycja);
        Serial.print("\   hall =\t");
        Serial.println(srednia);    
        }
    }

i będzie próba generalna.
Jeśli nie ma "byków" to zostanie kosmetyka - montaż "prztyczka" w przednim panelu, jakaś estetyczna diodka jako kontrolka, mocowanie wiązki przewodów itp.
Potem...próba pod obciążeniem!

ps. to ta nie informatyczna część prac:

   

A w zaistnieniu takiej oto maszynerii Twoja wiedza i dobra wola pomaga:

   
>Robimy dziś grilla?
<ok. będę potrzebował: wiertarkę, arkusz blachy…
 
Odpowiedź
#26
Witam,
Co na "dzień dobry" zauważyłem to...
Zamiast:
if((pozycja < obl_pozycja)&&(obl_pozycja < 13)) pozycja++;
if((pozycja > obl_pozycja)&&(obl_pozycja > 15)) pozycja--;
powinno być:
if((pozycja < obl_pozycja) || (obl_pozycja < 13)) pozycja++;
if((pozycja > obl_pozycja) || (obl_pozycja > 15)) pozycja--;
Pozdrawiam,
Tomek.
 
Odpowiedź
#27
Witam
Jest super Smile
Brnąc coraz głębiej, szukając zastosowania coraz to bardziej zagmatwanych poleceń i wciąż nie osiągając zadowalającego efektu – podeszliśmy do problemu „z innej beczki”.
Wychodząc z założenia, że im konstrukcja prostsza tym bardziej niezawodna – zacząłem to rozkminiać od podstaw, i tak:

-uśredniony odczyt z halla jest super (nie ruszać!)
-odczyt z halla jest ściśle związany z obrotami silnika więc przy tych moich wymarzonych 2500rpm wynosi po prostu ~3700,
-do utrzymania właśnie tej wartości ma dążyć program, ganiając z serwem w lewo lub prawo dotąd, aż ją osiągnie,
-czyli na dobrą sprawę mapowanie stało się zbędne bo wystarczy, że serwo poczynając od 0 dopyka po stopniu do optymalnych obrotów silnika (czyli również wartości odczytanej z halla) a potem, pykając stopień w przód lub w tył – po prostu ją utrzyma.
W ten sposób, zarówno utrzyma obroty bez obciążenia jak i wraz z jego wzrostem, będzie dalej uchylać przepustnicę starając się sprostać oczekiwaniom.
I odwrotnie, jak opory spadną i silnik będzie chciał się rozbujać – zacznie ją przymykać.
Wyszło mi, że kod spełniający taką funkcję musi wyglądać mniej/więcej tak:

Kod:
#include <Servo.h>
#define hallPin 2

Servo serwo;
volatile byte pozycja = 0;

void setup()
 {
 pinMode(hallPin, INPUT_PULLUP);
 pinMode(7, INPUT_PULLUP);
 serwo.attach(11);
 Serial.begin(9600);
 serwo.write(pozycja);
 }

void loop()
 {
 byte licznik = 0;
 unsigned long srednia = 0;
 unsigned int odczyt;

 while (licznik < 10)              //liczy srednią jak liczył
   {
   odczyt = pulseIn(hallPin, LOW);
   
   if ((odczyt > 1000)&&(odczyt < 10000)) //tylko zakres odczytów tak, żeby rozumial już od biegu jalowego
     {
     srednia += odczyt;
     licznik++;
     }
   }

 srednia /= 10;                  //wiem, że przy 2500rpm srednia z halla=3700 a serwo=12 bez obciążenia
 
 if(srednia > 3700) pozycja++;    //dokąd srednia jest większa niż 3700 dodawj serwu o 1 stoień co kolejna pętla
 if(srednia < 3700) pozycja--;  //jak srednia spadnie poniżej 3700 zacznij odejmować serwu po 1 stopień co kolejna pętla

 if (digitalRead(7) == HIGH)      //"prztyczek"- zerowanie serwa
   {
   pozycja = 0;
   serwo.write(pozycja);
   }
   
 if (digitalRead(7) == LOW)     //a jak prztyczka nie ma to daj serwu pozycję z linii 35/36
   {
   serwo.write(pozycja);
   }

  if ((digitalRead(7) == LOW) && (pozycja < 8)) //jak bez prztyczka a serwo<8 przyspiesz przyrost o jeszcze 1
   {
   pozycja++;
   serwo.write(pozycja);
   }
 
 
 }



Ten ostatni warunek ma z założenia przyspieszać reakcję silnika na nagle zwiększony opór. Nie jestem pewien czy jest z sensem ale jak nie patrzeć program działa – i to całkiem fajnie, równo i wystarczająco „żywo”.


Okazało się, jak to zwykle kiedy już wymyślone Smile że to całkiem proste było – niemniej jednak, faktem jest, że bez Twojej pomocy, zwłaszcza w części związanej z „ugłaskaniem” tego cholernego halla (pullup, rezystor, i while) pewnie nigdy bym sobie nie poradził.

Tak więc WIELKIE DZIĘKI – a jak dokończę „kosmetykę” to wstawię zdjęcia i filmik z działania.


Pozdrawiam,
Andrzej
>Robimy dziś grilla?
<ok. będę potrzebował: wiertarkę, arkusz blachy…
 
Odpowiedź
#28
Odgrzeję temat bo mam podobny problem. Usiłowałem wykorzystać to rozwiązanie do swojego urządzenia ogrodniczego, ale wyszukałem w sieci że z komputera seicento 900 z jakiego mam silnik na jednym pinie jest wyjście do obrotomierza. Wpiąłem się tam z opornikiem 470ohm do transoptora PC817 i na wyjściu GND i PIN2 ale nie zadziałało. Potem próbowałem podpiąć do wyjścia transoptora 3,3V i PIN2 ale też nie działa. W każdym przypadku serwo idzie do oporu i słychać że buczy. Jak myślicie iść dalej w tę stronę czy jak kolega wpiąć się z opornikiem w wyjście z czujnika halla?

pozdrawiam
Przemek
 
Odpowiedź
#29
Próbuje wykorzystać ten program do sterowania obrotami silnika 1.7 Isuzu, silnik ten napędza sprężarkę powietrza. Na razie robię próby na stole, do pomiarów obrotów użyłem czujnika halla wałka rozrządu z VW polo 1.4 MPI. Obroty silnika jakie potrzebuje utrzymywać na wale silnika to około 2400obr. Obecnie serwo reaguje od 1500obr. w górę, stopniowo dodając "gazu" aż dojdzie w skrajne położenie i na tym koniec. W programie zmieniam średnie wartości z czujnika i nic to nie daje. Czujnik gdy nie wykrywa punktu magnetycznego daje napiecie 4.63v, gdy wykrywa punkt napięcie spada do 0.09v. Brak mi pomysłu w czym jest problem...
 
Odpowiedź
  


Skocz do:


Przeglądający: 1 gości