Skocz do zawartości

Automatyczna pompa do wody


Krtstian

Pomocna odpowiedź

uint8_t stan = 0;
uint8_t stan1 = 0;
uint8_t zabezpiecz = 0;
uint32_t lasttime = 0;

int przeplyw = 0;                       
int hallsensor = 2;    //Sensor

long zapamietanyCzas = 0;

void setup()
{ 
 pinMode(10, OUTPUT); 
 pinMode(hallsensor, INPUT_PULLUP); 
 Serial.begin(9600); 
 
} 

void loop ()    
{
 if (digitalRead(hallsensor) == HIGH && stan == 0) {
  przeplyw++;
  stan = 1;
  }
if (digitalRead(hallsensor) == LOW) {
  stan = 0;
  }
  
 
            
 if (millis() - zapamietanyCzas >= 1000UL) {
            
 przeplyw *= 8; 

 Serial.print (przeplyw, DEC); 
 Serial.print (" L/godzr\r\n"); 

  if (przeplyw > 8 && stan1 == 0 )  { 
  digitalWrite(10, HIGH); 
  stan1 = 1;
  zabezpiecz = 1;
  lasttime = millis();
 }

 if (przeplyw > 600 && stan1 == 1 )  {
  digitalWrite(10, HIGH); 
   stan1 = 2;
   zabezpiecz = 0;
 }
 
 if (przeplyw < 410 && stan1 == 2)  {
  digitalWrite(10, LOW);
   stan1 = 0;
   zabezpiecz = 0;
   delay(2000); // trzeba dobrac czas probami
    }
   przeplyw = 0;
    zapamietanyCzas = millis();

 }
  if (millis() - lasttime > 5000UL && zabezpiecz == 1)  {  //zabezpieczenie przed samoczynnym wlaczeniem pompy.. po 5 sekundach bez odkrecenia kranu sie wylaczy
    digitalWrite(10, LOW);
    stan1 = 0;
    delay(2000); // trzeba dobrac
    zabezpiecz = 0;
}
  }
 

Takie cos...powinno dzialac wedlug opisu dzialania tej twojej pompy, ewentualnie dobrac czasy i wartosci czujnika...a jak cos to bedziemy poprawiac jesli sie pomylilem..😉

EDIT..teraz bedzie dzialac...popelnilem 2 bledy. tka to jest jak sie na telefonie bazgrze...

Edytowano przez farmaceuta
Link do komentarza
Share on other sites

14 godzin temu, farmaceuta napisał:

uint8_t stan = 0;
uint8_t stan1 = 0;
uint8_t zabezpiecz = 0;
uint32_t lasttime = 0;

int przeplyw = 0;                       int hallsensor = 2;    //Sensor

long zapamietanyCzas = 0;

void setup()
{ 
 pinMode(10, OUTPUT); 
 pinMode(hallsensor, INPUT); 
 Serial.begin(9600); 
 
} 

void loop ()    
{
 if (digitalRead(hallsensor) == HIGH && stan == 0) {
  przeplyw++;
  stan = 1;
  }
if (digitalRead(hallsensor) == LOW) {
  stan = 0;
  }
  
 
            
 if (millis() - zapamietanyCzas >= 1000UL) {
 zapamietanyCzas = millis;
            
 przeplyw *= 8; 

 Serial.print (przeplyw, DEC); 
 Serial.print (" L/godzr\r\n"); 

  if (przeplyw > 1 && stan1 == 0 )  { 
  digitalWrite(10, HIGH); 
  stan1 = 1;
  zabezpiecz = 1;
  lasttime = millis();
 }

 if (przeplyw > 600 && stan1 == 1 )  {
  digitalWrite(10, HIGH); 
   stan1 = 2;
   zabezpiecz = 0;
 }
 
 if (przeplyw < 410 && stan1 == 2)  {
  digitalWrite(10,LOW);
   stan1 == 0;
   zabezpiecz = 0;
   delay(?) // trzeba dobrac czas probami
    }
   przeplyw = 0;
 }
  if (millis() - lasttime > 5000 && zabezpiecz == 1)  {  //zabezpieczenie przed samoczynnym wlaczeniem pompy.. po 5 sekundach bez odkrecenia kranu sie wylaczy
    digitalWrite(10,LOW);
    stan1 = 0;
    delay(?) // trzeba dobrac
    
}
  }
 

Takie cos...powinno dzialac wedlug opisu dzialania tej twojej pompy, ewentualnie dobrac czasy i wartosci czujnika...a jak cos to bedziemy poprawiac jesli sie pomylilem..😉

Próbowałem na tym programie co wstawiłeś ale dane odczytane z licznika przepływu są zawsze 0 i odświeżanie danych odczytu jest bardzo szybkie, może dlatego wartość jest zawsze 0 bo za szybko się odświeża . Metodami prób i błędów końcu udało mi się osiągnąć zamierzony cel programu.

volatile int NbTopsFan; 
int przeplyw;                               
int hallsensor = 2;    //Sensor- czujnik przepływu

void rpm (){ 
 NbTopsFan++;  //pomiar zbocza czujnika halla
} 

void setup()
{ 
 pinMode(10, OUTPUT); //przekaźnik pompy
 digitalWrite(10, LOW);
 pinMode(hallsensor, INPUT); 
 Serial.begin(9600); 
 attachInterrupt(0, rpm, RISING);
} 

void loop ()    
{
 NbTopsFan = 0;
 sei();      

 if (przeplyw > 3 && przeplyw < 50){ //otwarcie kranu - włączenie pompy
  digitalWrite(10, HIGH); 
  delay (1500);  //czas ustabilizowania sie przepływu
  NbTopsFan = 0;
 }

 if (przeplyw > 411){ //pompa pracuje
  digitalWrite(10, HIGH); 
 }
 
 if (przeplyw < 410 && przeplyw > 51){ //zamknięcie kranu - wyłączenie pompy
  digitalWrite(10, LOW); 
  delay (5000); //czas ustabilizowania sie przepłuwu
  NbTopsFan = 0;
 }
     
 delay (1000); 
 cli();            
 przeplyw = (NbTopsFan * 60 / 7.5); 
 Serial.print (przeplyw, DEC); 
 Serial.print (" L/godzr\r\n"); 
}

 Nie wiem dlaczego ale jak if-y wstawię poniżej serial.print L/godz... tak jak to miało miejsce w pierwszej mojej wersji to wtedy to nie działa prawidłowo(nie ma tych zamierzonych przerw).

Link do komentarza
Share on other sites

2 godziny temu, Krtstian napisał:

Próbowałem na tym programie co wstawiłeś ale dane odczytane z licznika przepływu są zawsze 0 

A to dziwne...bo przez jedna sekunde zliczam ilosc impulsow...wystarczy ze bede mial jeden i juz powinienem miec 8l/h.

Moze dla tego za szybko odswieza bo czas millis powinien byc zapamietany przed wyjsciem z ifa a nie na jego poczatku..

Serial nie ma nic do delay()...tylko to cli() 

Edytowano przez farmaceuta
Link do komentarza
Share on other sites

Przede wszystkim za dużo delay w tym programie. Do takich obliczeń świetnie nada się timer aby obliczyć bieżącą ilość przepływającej wody, należy przyjąć jakąś stałą częstotliwość próbkowania. Przyjmijmy 1 sekundę. Nie wiem na jakim mikrokontrolerze dokładnie działasz jak i program może zawierać błędy. Mam nadzieję że ideę dobrze pokazałem.

#include <Arduino.h>

#include <Ticker.h>



#define HALLSENSOR 2

volatile uint32_t NbTopsFan;
volatile uint32_t flowLh;
Ticker tSample;



void licz_przeplyw(void){ // przerwanie co sekunde 
  static uint32_t last_flow;
  static int current_flow;
   
current_flow = NbTopsFan - last_flow; 
last_flow = NbTopsFan; // impulsy/s
/******** przeliczenie na l/h********/
current_flow *= 100; // zwiekszam rozdzielczosc pomiaru
if(current_flow < 450 ){
 flowLh = 0; 
 return; //!!!! tu NALEZY zrobic oblicznia gdy przeplyw < 0.01l/s
}
  flowLh /= 450;
  flowLh*=3600;


}

void rpm(void){
  NbTopsFan++;  //pomiar zbocza czujnika halla
}


void setup() {

 pinMode(10, OUTPUT); //przekaźnik pompy
 digitalWrite(10, LOW);
 pinMode(HALLSENSOR, INPUT); 
 Serial.begin(9600); 
 attachInterrupt(0, rpm, RISING);

  tSample.attach(1,licz_przeplyw);
}
uint32_t cpyFlow;
void loop() {

if(cpyFlow != flowLh){
  Serial.print("Przeplyw = ");Serial.println(flowLh);
  cpyFlow = flowLh; // wyswietlenie nastapi po zmianie przeplywu
}
}

I od tego bym zaczął przede wszystkim poprawne i nie blokujące wyświetlanie przepływu. 

Edytowano przez _LM_
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

9 minut temu, farmaceuta napisał:

.tylko to cli() 

Zerknij tutaj: https://www.nongnu.org/avr-libc/user-manual/group__util__atomic.html

Użycie ATOMIC_BLOCK jest czytelniejsze niż wałęsające się po kodzie sei/cli (które łatwo można wstawić nie tam gdzie trzeba, co bardzo dobrze widać w powyższym przypadku).

Poza tym w bloku ATOMIC powinien się znaleźć jak najkrótszy kod, przykładowo:

// na początku
#include <util/atomic.h>
  
  
// i gdzieś w programie:
  ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
  {
	przeplyw = NbTopsFan * (60/7.5);
  }

Dodatkowo ATOMIC gwarantuje prawidłowe sparowanie cli/sei nawet przy zagnieżdżonych blokach.

 

Link do komentarza
Share on other sites

ATOMIC_BLOCK jest tylko dla AVR-ów. ESP ma swoje mechanizmy (różne dla ESP8266 i ESP32).

Operacja pobrania 32-bitowej wartości z RAM jest w ESP atomowa, więc nie ma potrzeby stosowania jakichś wymyślnych mechanizmów poza oczywiście zdeklarowaniem zmiennej jako volatile.

 

  • Lubię! 1
Link do komentarza
Share on other sites

Wstawiam poprawioną wersję programu. Proszę dostosować piny czujnika HALLA i resztę. Ogólnie aby działało to prawidłowo przy małych przepływach to należy zmniejszyć częstotliwość próbkowania. Jest ona określona jako #define FSAMPLLE i powinna być wielokrotnością liczby 2. Jeśli ten projekt wykonujesz na małym AVR to trzeba stosować ATOMIC BLOCK tak jak pisał @ethanak

#include <Arduino.h>
#include <Ticker.h>

#define HALLSENSOR 5
#define FSAMPLLE 8 // 1 2 4 8 16 32 ....

volatile uint32_t NbTopsFan;
volatile uint32_t flowLh;
volatile bool new_bit;
Ticker tSample;

void licz_przeplyw(void) { // przerwanie co sekunde
  register uint32_t FanSpeed = NbTopsFan;
  static uint32_t last_flow;
  static int current_flow;

  current_flow = FanSpeed - last_flow;

  last_flow = FanSpeed; // impulsy/s
  /******** przeliczenie na l/h********/
  current_flow *= 10000; // zwiekszam rozdzielczosc pomiaru
  // Serial.println(current_flow);
  if (current_flow < 1) {
    flowLh = 0;
    return;
  }
  flowLh = current_flow / 450;
  flowLh *= (3600 / FSAMPLLE);
}

ICACHE_RAM_ATTR void rpm(void) {
  NbTopsFan++; // pomiar zbocza czujnika halla
  // digitalWrite(LED_BUILTIN,!digitalRead(LED_BUILTIN));
}

void setup() {
  Serial.begin(115200);
  Serial.println("Start");
  pinMode(LED_BUILTIN, OUTPUT);
  // pinMode(10, OUTPUT); //przekaźnik pompy
  // digitalWrite(10, LOW);
  pinMode(HALLSENSOR, INPUT_PULLUP);

  // attachInterrupt(0, rpm, RISING);
  attachInterrupt(digitalPinToInterrupt(HALLSENSOR), rpm, FALLING);
  tSample.attach(FSAMPLLE, licz_przeplyw);
}
uint32_t cpyFlow;

void loop() {

  if (cpyFlow != flowLh) { // nowa wartosc
    uint16_t cc;
    uint8_t cu;

    Serial.print("Przeplyw = ");
    Serial.println(flowLh);
    cpyFlow = flowLh; // wyswietlenie nastapi po zmianie przeplywu
    cc = flowLh / 10000;
    cu = (flowLh % 10000) / 100;
    Serial.print(cc);
    Serial.print(".");
    Serial.print(cu);
    Serial.println("l/h");
  }
}

 

Edytowano przez _LM_
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.