Skocz do zawartości

Termometr mechaniczny na silniku z enkoderem


Pomocna odpowiedź

43 minuty temu, ArduinoBoss napisał:

a mi chodzi to nierównomierne ruchy wału silnika

Zawsze można jakiś ładny wielomian napisać 🙂

A sam program jest dość prosty:

Po pierwsze musisz znać aktualną pozycję wału (czy klapy czy czegoś tam czym kręcisz). Tak jak wspomniałeś - zjazd do krańcówki to zero, a potem proste zliczanie impulsów enkodera.

Za pomocą jakiejś magicznej funkcji (map, wielomian, tablica, banda ifów) obliczasz, jaka powinna być pozycja tego czegoś. Jeśli silnik jest zatrzymany a różnica między bieżącą a docelową jest większa niż ileś tam (to ileś tam musisz sobie doświadczalnie sprawdzić, zależy od wielu czynników, proponuję zacząć od 50 i zmniejszać) uruchamiasz silnik. Jeśli silnik pracuje a różnica jest mniejsza niż ileś tam (tym razem trochę mniej, np. połowa tego co poprzednio) lub znak różnicy zmienił się na przeciwny (czyli cała maszyneria przejechała przez właściwą pozycję) zatrzymujesz silnik.

Ważne jest określenie żądanej dokładności pozycji. Przy zbyt dużej silnik będzie cały czas pracować. Przy zbyt małej regulacja nie będzie wystarczająco skuteczna. Ale jak już wspomniałem - to trzeba zrobić doświadczalnie.

 

  • Lubię! 1
3 minuty temu, ArduinoBoss napisał:

Około  180° na enkoderze to jest jakieś 5000 impulsów 

I dlatego nie rozumiem dlaczego map nie bedzie tu dobre...powiedzmy zakres temp. To 0-50stopni, wiec co stopien silnik obrocic o 100 impulsow czyli o 180/50 = ~3.5 stopnia na ramieniu...

4 minuty temu, ethanak napisał:

Za pomocą jakiejś magicznej funkcji (map, wielomian, tablica, banda ifów) obliczasz, jaka powinna być pozycja tego czegoś. Jeśli silnik jest zatrzymany a różnica między bieżącą a docelową jest większa niż ileś tam (to ileś tam musisz sobie doświadczalnie sprawdzić, zależy od wielu czynników, proponuję zacząć od 50 i zmniejszać) uruchamiasz silnik. Jeśli silnik pracuje a różnica jest mniejsza niż ileś tam (tym razem trochę mniej, np. połowa tego co poprzednio) lub znak różnicy zmienił się na przeciwny (czyli cała maszyneria przejechała przez właściwą pozycję) zatrzymujesz silnik.

Gdybyś mógł zaprezentować jak taka magiczna funkcja mogłaby przykładowo wyglądać... 🤗 Byłbym bardzo wdzięczny.

Ahaaaa....chyba kapuje, chodzi o to ze wal ma sie poruszac w zakresie 180stopni, ale z roznym wychyleniem w zaleznosci jaki jest zakres temperatury tak? Jak tak to zamiast jednego map() mozna uzyc kilku...

3 minuty temu, farmaceuta napisał:

I dlatego nie rozumiem dlaczego map nie bedzie tu dobre

Dlatego że jeśli zakres 0-50 to chciałbym tak że przy 10°C obróć o 100 przy 15°C o 200 przy 20°C o 250 a przy 50°C o 800 impulsów. To nie będzie szło liniowo, dlatego map się nie nada.   

Przed chwilą, farmaceuta napisał:

Ahaaaa....chyba kapuje, chodzi o to ze wal ma sie poruszac w zakresie 180stopni, ale z roznym wychyleniem w zaleznosci jaki jest zakres temperatury tak? Jak tak to zamiast jednego map() mozna uzyc kilku...

To już chyba łatwiej na ifach

9 minut temu, ArduinoBoss napisał:

Dlatego że jeśli zakres 0-50 to chciałbym tak że przy 10°C obróć o 100 przy 15°C o 200 przy 20°C o 250 a przy 50°C o 800 impulsów. To nie będzie szło liniowo, dlatego map się nie nada.   

Ale to ma dzialac plynnie czy moze skakac co 5 stopni powiedzmy?

(edytowany)

Przykładowo...

// ilość przedziałów
#define TEMPSTEPS 10

static const int tout[TEMPSTEPS]= {0,10,30,60,100,150,220,300,400,500};
static const int tin[TEMPSTEPS] = {15,25,35,45,55,60,75,85,95,105};

int steps(int temp)
{
    /* szukamy interesującego przedziału.
       Dla niewielkiej ilości przedziałów prosta pętla będzie szybsza
       niż jakieś bsearche czy inne mądre algorytmy */
    for (i=0; i<TEMPSTEPS;i++) if (temp <= tin[i]) break;
    if (!i) return tout[0]; // poniżej zakresu pomiarowego
    if (i >= TEMPSTEPS) return tout[TEMPSTEPS-1]; // powyżej zakresu pomiarowego
    return map(temp, tin[i-1], tin[i], tout[i-1], tout[i]);
}

Przetwarza nieliniowo zakres 15..105 na 0..500

Może być?

Przepraszam za użycie map, ale co do nadawania się mamy nieco odmienne zdanie 😉

Edytowano przez ethanak
  • Lubię! 1
  • Pomogłeś! 1
(edytowany)
14 minut temu, ArduinoBoss napisał:

To już chyba łatwiej na ifach

Ło Panie 😱 nie wiesz w co się pchasz xD zrób sobie mapę ale swoją, czyli Tablicujesz wychylenie klapy do zadanej temperatury czyli 60st - 1429 impulsów 61 - 1450 chcesz 60.5? spoko bierzesz 1450 - 1429 dzielisz na dwa i dodajesz do 1429 itd

Edytowano przez _LM_
5 minut temu, ethanak napisał:

Przykładowo...


// ilość przedziałów
#define TEMPSTEPS 10

static const int tout[TEMPSTEPS]= {0,10,30,60,100,150,220,300,400,500};
static const int tin[TEMPSTEPS] = {15,25,35,45,55,60,75,85,95,105};

int steps(int temp)
{
    /* szukamy interesującego przedziału.
       Dla niewielkiej ilości przedziałów prosta pętla będzie szybsza
       niż jakieś bsearche czy inne mądre algorytmy */
    for (i=0; i<TEMPSTEPS;i++) if (temp <= tin[i]) break;
    if (!i) return tout[0]; // poniżej zakresu pomiarowego
    if (i >= TEMPSTEPS) return tout[TEMPSTEPS-1]; // powyżej zakresu pomiarowego
    return map(temp, tin[i-1], tin[i], tout[i-1], tout[i]);
}

Przetwarza nieliniowo zakres 15..105 na 0..500

Może być?

Właśnie o coś takiego mi chodziło, dzięki wielkie 😍

Teraz tylko żeby to przełożyć na ruch ramienia przekładni....😱

1 minutę temu, ethanak napisał:

A to już pisałem.

Jestem jeszcze zbyt zielony, żeby te słowa przełożyć na program 😁

Porównując moje wypociny z tym co tutaj jest prezentowane, to trochę mi jeszcze wiedzy brakuje 😕 Mój program to zlepki tego co znajde w internecie plus to co sam wymyślę 😆 

#include <stdio.h>
#include <DS18B20.h>
#define PWM 5  //sterowanie prędkością
#define IN1 6 //zasilanie silnika
#define IN2 7  //zasilanie silnika
#define NO 8 //krańcówka
#define NC 9 //krańcówka
#define ENCA 2 // Żółty sygnał A
#define ENCB 3 // Biały sygnał B

bool referencja=true;
bool krok1=true;
bool krok2=true;
int pos = 0;

int zerowa = 0;
float temperatura;

unsigned long czaszal = 0;

void setup() {
  Serial.begin(9600);

  pinMode(ENCA,INPUT);
  pinMode(ENCB,INPUT); 
  attachInterrupt(digitalPinToInterrupt(ENCA),readEncoder,RISING);
  pinMode(IN1, OUTPUT);
  pinMode(IN2, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(8, INPUT_PULLUP); //przycisk jako wejście NO
  pinMode(9, INPUT_PULLUP); //przycisk jako wejście NC
  pinMode(11, OUTPUT);  //dioda kontrolka czerwona
  pinMode(12, OUTPUT);//dioda kontrolka zielona
  digitalWrite(11, LOW);
  digitalWrite(12, LOW);
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, LOW);
  

 

}


void loop() {
   DS18B20 ds(4);
    while (ds.selectNext()) {
    Serial.println(ds.getTempC());
  }

 temperatura = ds.getTempC();
 czaszal = millis();  //Referencja
  
 if(czaszal <= 2000UL and digitalRead(8) == HIGH){
   digitalWrite(11, HIGH);
   digitalWrite(IN1, LOW);
   digitalWrite(IN2, HIGH);
   referencja=true;
   delay(50);
 }else if(digitalRead(8) == LOW and referencja==true ) {  
   digitalWrite(11, LOW);//Czerwona wyłącz
   digitalWrite(12, HIGH); //Zielona włącz
   digitalWrite(IN1, LOW);
   digitalWrite(IN2, LOW);
   zerowa = 0;
   referencja=false;
   
 }else if( krok2==false  and  referencja==false ){
  
 digitalWrite(IN1, LOW);
 digitalWrite(IN2, LOW);
 krok1=false;
 }
  


  Serial.print("\t");

 Serial.println(pos); // rzeczywista pozycja enkodera 
  analogWrite(5, 100); //prędkość silnika

 
}

void readEncoder(){
int b = digitalRead(ENCB);
  if(b>0){
    pos++;
  }
  else{
    pos--;
  }
}

 

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