Skocz do zawartości

Niepoprawny odczyt napięcia w lutownicy


Mechano

Pomocna odpowiedź

Oddzielne zasilanie wyświetlacza to dobry pomysł, zrobię to w pierwszej kolejności jak do tego usiądę. Wklejam poniżej cały, obecny kod, którego używam.

Mała uwaga: z oczywistych błędów, które mogę wskazać, to funkcja read_temperature() jest zadeklarowana jako float a zmienne jako inty. Tak ma być - testowo tak zrobiłem, żeby "uciąć" przecinek. Nie zauważyłem zmiany w działaniu programu (w sensie zmiany stabilności w opisywanym przypadku) między tymi wersjami, oczywiście poza częścią ułamkową w mierzonej wartości.

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define THERMOCOUPLE A0
#define HEATER 9 
#define UP 7
#define DOWN 8

// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET     4 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

int adc = 0;
float napiecie;
//float odczyt;
//float temp;
int odczyt;
int temp;
int nastawa = 0;
unsigned long previousMillis = 0; 
const long interval = 300;

void setup() {
  Serial.begin(115200);
  analogReference(INTERNAL);
  pinMode(HEATER, OUTPUT);
  pinMode(UP, INPUT_PULLUP);
  pinMode(DOWN, INPUT_PULLUP);

  display.begin(SSD1306_SWITCHCAPVCC, 0x3c);
  display.clearDisplay();
  display.setTextSize(2); // Draw 2X-scale text
  display.setTextColor(WHITE);
  display.setCursor(10, 0);
  display.println(F("Lutownica"));
  display.setTextSize(4); // Draw 2X-scale text
  display.setCursor(20, 32);
  display.println("V1.0");
  display.display();
  delay(2000);
}

void loop() {
  if (digitalRead(UP) == 0){
     delay(50);
     if(digitalRead(UP) == 0) nastawa = nastawa + 10;
   }
    if (digitalRead(DOWN) == 0){
     delay(50);
     if(digitalRead(DOWN) == 0) nastawa = nastawa - 10;
   }
   nastawa = constrain(nastawa, 0, 250);
     
   unsigned long currentMillis = millis();
   if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;
    digitalWrite(HEATER, 0);
    delay(10);
    Serial.print(nastawa);
    Serial.print(" ");
    Serial.print(temp);
    temp = read_temperature();  
    }
    
    analogWrite(HEATER, nastawa);
    display.setCursor(0, 0); //lewy gorny napis
    display.println("odcz:");
    display.setCursor(0, 20); //lewy srodkowy napis
    display.println("temp:");
    display.display();
   }
   
  

float read_temperature(){
  for(int i=0;i<10;i++){ //pomiar napiecia 
    adc = analogRead(THERMOCOUPLE);
    odczyt = odczyt + adc;
    Serial.print(adc);
    Serial.print(" ");
    }
   odczyt = odczyt / 10;
   napiecie = odczyt * (1.1 / 1024.0); //napiecie ze wzmacniacza
   napiecie=napiecie*1000; //napiecie w mV ze wzmacniacza
   Serial.println("");
   
   return (napiecie);
}

 

Link do komentarza
Share on other sites

12 godzin temu, Mechano napisał:

z oczywistych błędów, które mogę wskazać, to funkcja read_temperature() jest zadeklarowana jako float a zmienne jako inty

Ależ to wcale nie jest błąd - użycie niejawnego rzutowania jest tu jak najbardziej prawidłowe.

Zastanawia mnie tylko pewien fragment, który w uproszczeniu wygląda tak:
 

void loop()
{
  /* tu kawałek który się nie wykonuje bo nikt nic nie wciska */
  nastawa = constrain(nastawa, 0, 250); // po kiego grzyba? Magicznie się zmieniła czy co?
     
 unsigned long currentMillis = millis();
 if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;
    digitalWrite(HEATER, 0); // a nie analogWrite? Ja bym nie mieszał...
    delay(10);
    Serial.print(nastawa);
    Serial.print(" ");
     // ja bym najpierw przeczytał a potem napisał co przeczytałem...
    Serial.print(temp); 
    temp = read_temperature();  
  }
    
  /* czy ten kawałek kodu musi się co milisekundę wykonywać?
   * ATmega doskonale pamięta co jej w analogWrite wrzuciliśmy,
   * a wyświetlacz też ma swoją pamięć
   */
  
  analogWrite(HEATER, nastawa);
  display.setCursor(0, 0); //lewy gorny napis
  display.println("odcz:");
  display.setCursor(0, 20); //lewy srodkowy napis
  display.println("temp:");
  display.display();
}

Poza tym interval masz zadeklarowany jako long a używasz go w połączeniu z unsigned long - mieszanie w jednym wyrażeniu signed i unsigned może prowadzić do co najmniej dziwnych rezultatów.

Przy okazji - lepiej używać typów takich jak "uint32_t" niż "unsigned long" - będziesz chciał później to przerobić np. na ESP albo STM-a i się zderzysz ze ścianą (long ma tam 64 bity, a int 32).

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

Dnia 25.11.2019 o 19:44, atMegaTona napisał:

Faktycznie nie pomyślałem, że napięcie na wyjściu stabilizatora z czasem mogło by tak wzrosnąć, aż sprawdzę to praktycznie czy rzeczywiście taka sytuacja może się zdarzyć, najwyżej zepsuje stabilizator w imię nauki.

Wtrącę tu jeszcze tylko nieśmiało, trochę się tłumacząc i trochę kajając bo faktycznie nie pomyślałem a ostatni mini projekcik zmusił mnie do myślenia na ten temat przez 15 minut i oto takie tego rezultaty:

Otóż większość stabilizatorów działa lepiej przy pewnym minimalnym obciążeniu. Wniosek z tego taki, że sprawę rozwiązuje rezystor na wyjściu stabilizatora, niektórzy producenci nawet określają w DS ten minimalny prąd potrzebny do prawidłowej pracy stabilizatora czyli kilka mA.

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

(edytowany)

Kolejna aktualizacja:

Uruchomiłem lutownicę z wyświetlaczem na płytce stykowej obok, zasilanym akumulatorkiem i  wtedy całość działała świetnie. Pomiar był stabilny i wyświetlacz działa bardzo dobrze. Na tej podstawie chyba już jasno mogę stwierdzić, że to problem z zasilaniem. Pytanie, co mogę więcej poprawić? Dodać więcej kondensatorów? Może jakiś dławik? Nie mam pojęcia jakiego typu i o jakiej wartości go szukać. Co polecacie?

Co do kodu to, przede wszystkim, dziękuję za uwagi. Trochę pozmieniałem i uporządkowałem główną pętlę programu. Jeszcze nie zająłem się tematem różnych typów zmiennych ale to jest następny element do przemyślenia i poprawy. Mam nadzieję, że to już "jakoś" wygląda ale chętnie dowiem się co zrobić, żeby był lepszy.

void loop() {
  if (digitalRead(UP) == 0){
     delay(50);
     if(digitalRead(UP) == 0) nastawa = nastawa + 10;
     
   }
    if (digitalRead(DOWN) == 0){
     delay(50);
     if(digitalRead(DOWN) == 0) nastawa = nastawa - 10;
   }

   if(nastawa != poprzednia_nastawa){
    nastawa = constrain(nastawa, 0, 250); 
    poprzednia_nastawa = nastawa;
   }
    
    
   unsigned long currentMillis = millis();
   if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;
    digitalWrite(HEATER, 0);
    delay(10);
    temp = read_temperature();
    Serial.print(nastawa);
    Serial.print(" ");
    Serial.print(temp);
    Serial.print(" cyk ");
      
    analogWrite(HEATER, nastawa);
    display.setCursor(0, 0); //lewy gorny napis
    display.println("odcz:");
    display.setCursor(0, 20); //lewy srodkowy napis
    display.println("temp:");
    display.display();
    }

   }

 

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

Jeśli to tylko taki mały program ma być (bo i po co miałby być większy?) to możesz sobie doinstalować do tego jakiegoś prawdziwego PIDa dla bajeru. Myślę, że nie ma się tu więcej nad czym rozwodzić. Czekam na efekt końcowy i relację z użytkowania bo może też sobie zrobię taką stację ponieważ jestem zmuszony używać kolby oporowej z regulacją temperatury za pomocą komparatora czyli na oko.

Link do komentarza
Share on other sites

@atMegaTona

Jeszcze dużo brakuje do końca. Przede wszystkim ten kawałek kodu tylko mierzy napięcie wyjściowe, bez żadnego przeliczania na temperaturę a tym bardziej bez żadnej regulacji. Na razie się tym nie zajmuję bo pomiar nadal nie działa tak jakbym chciał. Przy pracującym wyświetlaczu odczyt jest strasznie niestabilny a jak tylko go odłączę to się uspokaja. Bardziej szczegółowo opisałem to w postach wyżej.

Link do komentarza
Share on other sites

Więc nadal występuje ten problem?? coś bardzo dziwnego bo wejścia wyświetlacza nie pobierają prawie prądu a sam wyświetlacz też dużo nie potrzebuje. Możesz dać na wszystkie wejścia rezystory z 1k i podłączyć go pod osobny stabilizator z rezystorem ze 3k na wyjściu i kondensatorem 100u. Teoretycznie niemożliwe jest aby wyświetlacz miał taki wpływ na procka. Jak to co do tej pory napisane nie pomoże to może zmień procka.  Jest jeszcze jedna opcja, wyjścia do wyświetlacza są bardzo blisko (fizycznie) pinu od ADC, może to być spowodowane przesłuchami pomiędzy tranzystorami w tym samym porcie, możesz spróbować odsunąć ADC od wyjścia na LCD jeśli masz jak.

Przeliczanie napięcia na temperaturę nie powinno być jakoś specjalnie trudne, przyda się do tego jakieś odniesienie w postaci gotowego termometru ale myślę, że do lutowania wystarczy odnieść się do danych katalogowych termopary i przeskalować wyniki pod kątem ustawionego wzmocnienia. Powodzenia.

Link do komentarza
Share on other sites

Przełom!

Zrobiłem dzisiaj kilka większych i mniejszych, fizycznych zmian na płytce lutownicy i odczyt się uspokoił podczas pracy z wyświetlaczem! Konkretnie to:

  • zmieniłem trasę "ścieżki" (przewodu) między wzmacniaczem a ADC, wcześniej kilka razy przechodził z jednej na drugą stronę płytki, teraz idzie tylko górą, przez co jest prawie o połowę krótszy,
  • wzmacniacz i wyświetlacz mają teraz osobne przewody zasilające, łączące się dopiero przy stabilizatorze,
  • dodałem dwa kondensatory ceramiczne 100n bezpośrednio na wejściu i wyjściu stabilizatora 5V,
  • dodałem rezystory podciągające 10k na liniach I2C,
  • dodałem rezystory 1k, szeregowo, na liniach I2C,
  • zmniejszyłem wzmocnienie przez dodanie równolegle drugiego rezystora 200k do tego już wlutowanego,

Trudno teraz powiedzieć, która zmiana konkretnie wywołała pożądany efekt ale wreszcie to działa i mogę przejść do następnego etapu. Dziękuję bardzo za pomoc! Postaram się w miarę postępów raportować co się udało a z czym mam problemy. Adminow/moderatorowi zostawiam decyzję czy to ma zostać tutaj, czy może przesunąć to do worklogów.

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

Działam dalej, udało mi się uruchomić pierwszą, działającą wersję. 

Mam duży problem z pomiarem rzeczywistej temperatury grota. Używam termopary z multimetru, którą wkładam w kroplę cyny na końcu grota, rozgrzewam lutownicę np. do (zmierzonych) 400*C, wyłączam grzałkę i spisuję wyniki z multimetru i z lutownicy. Niestety w ten sposób nie udało mi się zrobić pomiarów które różniły by się np. tylko o 5*C dla tego samego odczytu. To znaczy, że dla jednego odczytu z lutownicy za pierwszym razem mogę mieć temperaturę rzędu 300*C a następnym razem 340*C. Te różnice są niestety spore i nie wiem w jaki sposób mogę do dokładniej zmierzyć. Macie jakieś pomysły? Może muszę użyć innej termopary albo w ogóle robię totalnie źle te pomiary i źle używam termopary?

Zamiana wartości odczytanej z ADC na temperaturę odbywa się w dosyć prosty i nieelegancki sposób ale przynajmniej na ten moment działa, póki nie zrobię dokładniej pomiarów. Mam w kodzie zapisane dwie tablice:

int tabTemp[39] = {400,390,380,370,360,350,340,330,320,310,300,290,280,270,260,250,240,230,220,210,200,190,180,170,160,150,140,130,120,110,100,90,80,70,60,50,40,30,20}; 
int odczytTermopara[39] = {575,565,548,532,517,502,487,470,456,441,426,411,396,381,365,350,336,320,305,290,273,259,245,230,212,203,191,175,161,147,139,125,114,96,80,65,50,34,20};

Które potem przeszukuje prostą pętlą:

//przeszukiwanie tablicy > odczyt temperatury z tablicy
    for(int i = 0; i < 39; i++){
      if(temp <= odczytTermopara[i]){
        temperatura = tabTemp[i];
        //temperatura = 50;
      }
    }

Dalej mam bardzo prosty regulator. Wyznaczam błąd między temperaturą zadaną a rzeczywistą i jeśli jest on większy niż 20*C to grzałka pracuje z pełną mocą a jeśli się zawiera między 0 a 20 to grzałka dostaje trochę ponad połowę pwm'u. Dla błędu mniejszego od 0 grzałka jest wyłączana:

blad = nastawa - temperatura;
    if(blad >= 20){
      pwm = 250; //full gas pwm
    }
    else if(blad > 0 && blad < 20){
      pwm = 150;
    }
    else if(blad <= 0){
      pwm = 0;
    }
    analogWrite(HEATER, pwm);

W każdym razie trochę na pałę ale lutownica wreszcie jakoś działa i mogłem pierwszy raz ją przetestować. Lutuje się tym całkiem spoko i raczej nie brakuje mocy (a tej jest ledwie ~20W) ale mam trochę zużyty grot i w kilku miejscach już nie łapie cyny. Muszę zamówić nowy grot i sprawdzić jeszcze raz. Dalej w planach jest dokładniejsze stablicowanie pomiarów temperatury i zaimplementowanie jakieś formy regulatora PID, co dokładnie to się okaże. Raczej staram się tutaj przygotować solidnie jeden etap a potem przejść do następnego, żeby potem nie cofać się z powodu jakiejś pierdoły. Jeśli chodzi o wartości użytkowe to w tej formie jest to totalne nie do użytku 😉 Przyciski po bokach tylko przeszkadzają w pewnym chwycie, całość jest za długa a ten wyświetlacz jest praktycznie cały zasłonięty dłonią. Przyciski musiały by być przesunięte gdzieś na tył a wyświetlacz mógłby być między palcami. Jest co poprawiać w drugiej wersji.

 lutownica.thumb.jpg.996cb28a52a0362fa64855dbbc9c483a.jpg

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

ehh, termopara termoparze nierówna. Lepiej poszukaj sobie stałej temperatury i na podstawie specyfikacji termopary przelicz sobie wskazania na temperaturę bo mierzenie jedną termoparą a kalibrowanie drugiej na podstawie wskazań z tej pierwszej miałoby sens gdyby były identyczne. Musisz znać przynajmniej typ termopary, w dataszmacie jest tabela temperatur dla konkretnych wyników. Tu masz dla j i k

https://www.termoaparatura.com.pl/files_mce/its90_tc_k.pdf

https://www.termoaparatura.com.pl/files_mce/its90_j_pl.pdf

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.