• 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
Miernik
#1
Witam, 

Potrzebuje pomoc przy programie.
Program ma mierzyć pojemność kondensatora, a w zasadzie trzech na raz. 

Kondensatory połączone w trójkąt do A0 A1 A2.


Kod:
const int OUT_PIN = A2;
const int IN_PIN = A0;
const float IN_STRAY_CAP_TO_GND = 24.48;
const float IN_CAP_TO_GND  = IN_STRAY_CAP_TO_GND;
const float R_PULLUP = 34.8; 
const int MAX_ADC_VALUE = 1023;
float correction;
float pomiar, wynik;

void setup(){
  pinMode(OUT_PIN, OUTPUT);
  pinMode(IN_PIN, OUTPUT);
  Serial.begin(9600);
}

void loop(){
    pinMode(IN_PIN, INPUT);
    digitalWrite(OUT_PIN, HIGH);
    int val = analogRead(IN_PIN);
    digitalWrite(OUT_PIN, LOW);

{
      pinMode(IN_PIN, OUTPUT);
      delay(1);
      pinMode(OUT_PIN, INPUT_PULLUP);
      unsigned long u1 = micros();
      unsigned long t;
      int digVal;

      do{
        digVal = digitalRead(OUT_PIN);
        unsigned long u2 = micros();
        t = u2 > u1 ? u2 - u1 : u1 - u2;
      } while ((digVal < 1) && (t < 400000L));

      pinMode(OUT_PIN, INPUT); 
      val = analogRead(OUT_PIN);
      digitalWrite(IN_PIN, HIGH);
      int dischargeTime = (int)(t / 1000L) * 5;
      delay(dischargeTime);   
      pinMode(OUT_PIN, OUTPUT); 
      digitalWrite(OUT_PIN, LOW);
      digitalWrite(IN_PIN, LOW);

      float capacitance = -(float)t / R_PULLUP / log(1.0 - (float)val / (float)MAX_ADC_VALUE);


      if (capacitance < 1500000.0) //kalibracja pomiaru
       correction = 0.9122;
      else correction = 0.60;


     
      if (capacitance > 1000.0){
        pomiar = (capacitance / 1000.0 * correction);
        wynik = (pomiar / 1.5);                         //przeliczenie na właściwą wartość - połączenie szeregowo równoległe kondensatorów
       
        Serial.print(F("Połączenie w trójkąt = "));
        Serial.print(wynik, 2);
        Serial.print(F(" uF"));
        Serial.print(F(" ("));
        Serial.print(F("t= "));
        Serial.print(t);
        Serial.print(F(" us, ADC= "));
        Serial.print(val);
        Serial.println(F(")"));
     
      }
     
    }
    while (millis() % 1000 != 0);   
}


to mi działa ale tylko na jednym boku trójkąta czyli mierzy tylko AB a ja potrzebuję jeszcze BC i CA


nie mam pomysłu jak to zrobić ;(
Proszę o pomoc
 
Odpowiedź
#2
Dwie sprawy:
1) Opisz w komentarzach co robi każda linia kodu, do czego służy dana zmienna itp. To pomoże zrozumieć działanie programu chętnym pomagierom.
2) Nie nazywaj w ten sposób zmiennych, to jest strasznie nieczytelne.
Jeśli masz problem z kodem lub sprzętem, zadaj pytanie na forum. Nie odpowiadam na PW, jeśli nie dotyczą one spraw forum lub innych tematów prywatnych.

[Obrazek: SsIndaG.jpg]
 
Odpowiedź
#3
(14-07-2020, 01:01)Robson Kerman napisał(a): Dwie sprawy:
1) Opisz w komentarzach co robi każda linia kodu, do czego służy dana zmienna itp. To pomoże zrozumieć działanie programu chętnym pomagierom.
2) Nie nazywaj w ten sposób zmiennych, to jest strasznie nieczytelne.
Kod nie jest mojego autorstwa ja coś tam musnąłem. Wydaje mi się, że większość jest jasna.

Tu całą abawa polega na tym, że fragment do pomiaru pozostaje ten sam zmieniać się będą tylko  piny tzn 1 pomiar A0 i A1, drugi pomiar A1 i A2, trzeci pomiar A2 i A0.

Rozumiem że będą np 3 linijki 

float capacitanceA0A1 = 
float capacitanceA1A2 = 
float capacitanceA2A0 = 

pomiar "na raz" odpada najlepiej po odczytaniu przełączyć się do kolejnego.

Nie wiem jak to lepiej ubrać w słowa.
 
Odpowiedź
#4
Skoro pracujemy na zmiennych IN_PIN i OUT_PIN, to można by wywalić wszystko z loop() do jakiejś funkcji i przekazywać jej w parametrach, który kondensator mierzyć.

Coś w ten deseń:

Kod:
void miernik( int inPin, int outPin)

Na początku tej funkcji trzeba przypisać i ustawić piny:

Kod:
  IN_PIN = inPin;
  OUT_PIN = outPin;
  pinMode(IN_PIN, INPUT);
  pinMode(OUT_PIN, OUTPUT);

Przed wyjściem z funkcji należy te piny ustawić jako wejścia, coby podnieść impedancję.

Kod:
    pinMode(OUT_PIN, INPUT);
    pinMode(IN_PIN, INPUT);
 
Można pokusić się o sprawdzenie, który to kondensator aktualnie mierzę:

Kod:
        Serial.print(F("Kondensator "));
        Serial.print(IN_PIN);
        Serial.print(" ");
        Serial.print(OUT_PIN);
        Serial.print(" = ");
        Serial.print(pomiar, 2);
        Serial.print(F(" uF"));
        Serial.print(F(" ("));
        Serial.print(F("t= "));
        Serial.print(t);
        Serial.print(F(" us, ADC= "));
        Serial.print(val);
        Serial.println(F(")"));

A, i wywalić to while, bo to do niczego się nie nadaje.

Suma summarum, ostatecznie funkcja mogłaby wyglądać jakoś tak:

Kod:
void miernik( int inPin, int outPin){

  IN_PIN = inPin;
  OUT_PIN = outPin;
  pinMode(IN_PIN, INPUT);
  pinMode(OUT_PIN, OUTPUT);
    digitalWrite(OUT_PIN, HIGH);
    int val = analogRead(IN_PIN);
    digitalWrite(OUT_PIN, LOW);

{
      pinMode(IN_PIN, OUTPUT);
      delay(100);
      pinMode(OUT_PIN, INPUT_PULLUP);
      unsigned long u1 = micros();
      unsigned long t;
      int digVal;

      do{
        digVal = digitalRead(OUT_PIN);
        unsigned long u2 = micros();
        t = u2 > u1 ? u2 - u1 : u1 - u2;
      } while ((digVal < 1) && (t < 400000L));

      pinMode(OUT_PIN, INPUT);
      val = analogRead(OUT_PIN);
      digitalWrite(IN_PIN, HIGH);
      int dischargeTime = (int)(t / 1000L) * 5;
      delay(dischargeTime);
      pinMode(OUT_PIN, OUTPUT);
      digitalWrite(OUT_PIN, LOW);
      digitalWrite(IN_PIN, LOW);

      float capacitance = -(float)t / R_PULLUP / log(1.0 - (float)val / (float)MAX_ADC_VALUE);

      if (capacitance < 1500000.0) //kalibracja pomiaru
       correction = 0.9122;
      else correction = 0.60;

      if (capacitance > 1000.0){
        pomiar = (capacitance / 1000.0 * correction);
        wynik = (pomiar / 1.5);                         //przeliczenie na właściwą wartość - połączenie szeregowo równoległe kondensatorów

        Serial.print(F("Kondensator "));
        Serial.print(IN_PIN);
        Serial.print(" ");
        Serial.print(OUT_PIN);
        Serial.print(" = ");
        Serial.print(pomiar, 2);
        Serial.print(F(" uF"));
        Serial.print(F(" ("));
        Serial.print(F("t= "));
        Serial.print(t);
        Serial.print(F(" us, ADC= "));
        Serial.print(val);
        Serial.println(F(")"));
      }
    }
    pinMode(OUT_PIN, INPUT);
    pinMode(IN_PIN, INPUT);
}

A wywoływać ją można tak:

Kod:
void loop(){
miernik(A0,A2);
miernik(A2,A4);
miernik(A4,A0);
}

Jak znasz wzór na pojemność zastępczą, to policz czy Ardu się nie myli.
Pomierz najpierw pojedyncze kondensatory, i te wyniki podstaw do wzoru, bo trzeba się liczyć z tym, że pojemności napisane na obudowach są jedynie orientacyjne.
Jeśli masz problem z kodem lub sprzętem, zadaj pytanie na forum. Nie odpowiadam na PW, jeśli nie dotyczą one spraw forum lub innych tematów prywatnych.

[Obrazek: SsIndaG.jpg]
 
Odpowiedź
#5
Super Wink chyba większość rozumiem...

Tylko co z deklaracją A0 A2 i A4? Nie widzę jej a działa..?
I jak pobiera aktualny port?
Jak zmienić wyświetlanie nr portu (14; 16; 18) na np AB; BC; CA

Co do samego startu cyklu pomiaru to start byłby z jakiegoś przycisku.
if (digitalRead(przycisk) == LOW) { //Jeśli przycisk wciśnięty
  Serial.print(" wcisniety");
          miernik(A0,A2);
          miernik(A2,A4);
          miernik(A4,A0);
  }


Jeśli chodzi o obliczenie pojemności to załatwiam to tu wynik = (pomiar / 1.5);
Dlatego że w trójkącie mamy dwa kondensatory szeregowo a że są jednakowe to dziele na pół i wtedy zostaje dwa równolegle które dodaje (Pomiar A0A2=1/2a+a; A0A2=1,5a / 1,5; a=A0A2/1,5). I tyle mi wystarcza Wink


z racji tego że kondensatory pracują na 400V to myślę dodać po przekaźniku na każdy kanał (styki NC/NO; styki trzech przekaźników połączone ze sobą rezystorami 1Ohm 5Wat - czyli w chwili podłączenia samoczynnie się profilaktycznie rozładowuje w momencie startu pomiaru wszystkie trzy się załączają i umożliwiają pomiar).
 
Odpowiedź
#6
Można wywalić z funkcji miernik(int,int) te wszystkie Serial.printy, a funkcję zmienić tak żeby zwracała floata:

Kod:
float miernik( int inPin, int outPin)

Na końcu funkcji dopisać:

Kod:
    return wynik;

A w loop() pobierać te wyniki i zapisywać do zmiennych:

Kod:
float zmienna1, zmienna2, zmienna3;

void loop(){
zmienna1 = miernik(A0,A2);
zmienna2 = miernik(A2,A4);
zmienna3 = miernik(A4,A0);
}


Potem możesz sobie je wyświetlać, albo jakoś inaczej wykorzystywać.
Jeśli chodzi o to, że to mają być wyniki z drugiego pomiaru, to możesz w funkcji miernik(int,int) umieścić cały kod pętli (oprócz return wynik; ) i zakręcić ją dwa razy.
Obsługę przycisków powinieneś ogarnąć.
Pozdrawiam.

P.S.

(15-07-2020, 15:56)sza86 napisał(a): Tylko co z deklaracją A0 A2 i A4? Nie widzę jej a działa..?
I jak pobiera aktualny port?
Jak zmienić wyświetlanie nr portu (14; 16; 18) na np AB; BC; CA

To jest zakodowane w pins_arduino.h, czy jakoś tak.

Kod:
#define PIN_A0   (14)
#define PIN_A1   (15)
#define PIN_A2   (16)
#define PIN_A3   (17)
#define PIN_A4   (18)
#define PIN_A5   (19)
#define PIN_A6   (20)
#define PIN_A7   (21)

static const uint8_t A0 = PIN_A0;
static const uint8_t A1 = PIN_A1;
static const uint8_t A2 = PIN_A2;
static const uint8_t A3 = PIN_A3;
static const uint8_t A4 = PIN_A4;
static const uint8_t A5 = PIN_A5;
static const uint8_t A6 = PIN_A6;
static const uint8_t A7 = PIN_A7;

A wyświetlanie portu możesz sobie porównywać w if itp.
Ale lepiej po prostu to zakoduj w ten sposób, że jak pracujesz na zmiennej zmienna1, to znaczy że chodzi o kondensator na wejściach AB itd.
Jeśli masz problem z kodem lub sprzętem, zadaj pytanie na forum. Nie odpowiadam na PW, jeśli nie dotyczą one spraw forum lub innych tematów prywatnych.

[Obrazek: SsIndaG.jpg]
 
Odpowiedź
#7
   
   

Hej

na chwilę obecną wgrałem taki kod i działa fajnie Wink

Kod:
int OUT_PIN = A2;
int IN_PIN = A0;
int przycisk = 2;
int przekazniki = 3;
const float IN_STRAY_CAP_TO_GND = 24.48;
const float IN_CAP_TO_GND  = IN_STRAY_CAP_TO_GND;
const float R_PULLUP = 34.8;
const int MAX_ADC_VALUE = 1023;
float correction;
float pomiar, wynik;

void setup() {
pinMode(przycisk, INPUT_PULLUP); //Przycisk jako wejście
pinMode(przekazniki, OUTPUT);
  pinMode(OUT_PIN, OUTPUT);
  pinMode(IN_PIN, OUTPUT);
  Serial.begin(9600);

}

void loop() {

if (digitalRead(przycisk) == LOW) { //Jeśli przycisk wciśnięty
   //   digitalWrite(przekazniki, HIGH);
   //   delay(100);
  Serial.print("Start");
  Serial.println();
          miernik(A0,A2);
          miernik(A2,A4);
          miernik(A4,A0);
  Serial.print("Stop");
      //  digitalWrite(przekazniki, LOW);
  }  

}

void miernik( int inPin, int outPin){


    IN_PIN = inPin;
    OUT_PIN = outPin;
    pinMode(IN_PIN, INPUT);
    pinMode(OUT_PIN, OUTPUT);
    digitalWrite(OUT_PIN, HIGH);
    int val = analogRead(IN_PIN);
    digitalWrite(OUT_PIN, LOW);

{
      pinMode(IN_PIN, OUTPUT);
      delay(100);
      pinMode(OUT_PIN, INPUT_PULLUP);
      unsigned long u1 = micros();
      unsigned long t;
      int digVal;

      do{
        digVal = digitalRead(OUT_PIN);
        unsigned long u2 = micros();
        t = u2 > u1 ? u2 - u1 : u1 - u2;
      } while ((digVal < 1) && (t < 400000L));

      pinMode(OUT_PIN, INPUT);
      val = analogRead(OUT_PIN);
      digitalWrite(IN_PIN, HIGH);
      int dischargeTime = (int)(t / 1000L) * 5;
      delay(dischargeTime);
      pinMode(OUT_PIN, OUTPUT);
      digitalWrite(OUT_PIN, LOW);
      digitalWrite(IN_PIN, LOW);

      float capacitance = -(float)t / R_PULLUP / log(1.0 - (float)val / (float)MAX_ADC_VALUE);

      if (capacitance < 1500000.0) //kalibracja pomiaru
       correction = 0.9122;
      else correction = 0.60;

      if (capacitance > 1000.0){
        pomiar = (capacitance / 1000.0 * correction);
        wynik = (pomiar / 1.5);                         //przeliczenie na właściwą wartość - połączenie szeregowo równoległe kondensatorów

        Serial.print(F("Kondensator "));
        Serial.print(IN_PIN);
        Serial.print(" ");
        Serial.print(OUT_PIN);
        Serial.print(" = ");
        Serial.print(pomiar, 2);
        Serial.print(F(" uF"));
        Serial.print(F(" ("));
        Serial.print(F("t= "));
        Serial.print(t);
        Serial.print(F(" us, ADC= "));
        Serial.print(val);
        Serial.println(F(")"));
      }
    }
    pinMode(OUT_PIN, INPUT);
    pinMode(IN_PIN, INPUT);
}

Całkiem fajny pomysł w wywaleniem serial.print tylko nie wiem czy w jednej zmiennej upchnę wynik pojemności czas i adc...

Serial.print chyba w ogóle zatopię i spróbuję UART wysyłać wyniki do programu który może jakoś napiszę :/ i do tego możliwość wyświetlania na małym oled przez SPI....

Na chwilę obecną zastanawiam się nad zasilaniem z USB bo doszły przekaźniki...;/
 
Odpowiedź
  


Skocz do:


Przeglądający: 1 gości