Skocz do zawartości

Projekt z czujnikami do auta


Pomocna odpowiedź

Napisano (edytowany)

Cześć,
Chciałbym wykonać projekt na arduino który polegałby na czytaniu danych z trzech czujników i wyświetlał dane na ekranie wyświetlacza LCD.
Czujniki to : ciśnienie doładowania, ciśnienie oleju, temp oleju.
Z ciśnieniem doładowania poradziłem sobie szybko, ponieważ działa on liniowo, a pozostałe dwa nie.
Oto dane dla dwóch czujników które otrzymałem od producenta:
(Dane są „na gotowo” po dobraniu odpowiednich oporników.)

Ciśnienie oleju:

image.thumb.png.ace0afa33d0caec2528d30bb555e1519.png

 


Temp oleju:
image.thumb.png.3edb96b169d07f384c136330bda93a51.png

 



Wyznaczyłem z tego wzory funkcji :
Ciśnienie oleju:
image.thumb.png.e7154b1512605ac77576ac096c0f9304.png


Temp oleju: 
image.thumb.png.54d53856a82f58fb5d1d47a3966e0546.png



I tutaj się zatrzymałem.
Za cienki jestem i nie potrafię napisać kodu z użyciem tych funkcji. A informacje z internetu nie za wiele mi mówią 😕
Czy ktoś mógłby mi pomóc, podpowiedzieć coś w napisaniu kodu dla tych dwóch czujników ?

 

 

 

image.png

image.png

image.png

Edytowano przez MatJJ
załączniki bład

Z czym konkretnie masz problem? Nie potrafisz napisać wzoru/algorytmu na odczytanie rzeczywistej wartości czy może znasz wzór a nie potrafisz napisać kodu?

Uściślij, bo chciałbym pomóc ale nie bardzo wiem jak.

(edytowany)

Jezeli te rozdzielczosci z tabel sa dla Ciebie wystarczajace to mozna dane pomiaru i dane analogowe wpakowac do dwoch tablic i odpowiednio porownywac z adc...z tym ze na "wyjsciu" uzyskasz tylko to co masz w tabelach...nic posredniego

Edytowano przez farmaceuta
(edytowany)

Znam tylko te informacje 
image.thumb.png.931c2aaf4452d2ed0389727a69d96a8f.png (np.dla temp oleju)

ale nie potrafię napisać tego w kodzie, nie wiem jak odczytać i wypisać wartości. 

To kod którego używam do odczytania wartości z czujnika ciśnienia doładowania który jest liniowy i nie opornosciowy: 

 

#include <LiquidCrystal_I2C.h> //użyte biblioteki 
#include <Wire.h> //użyte biblioteki 
#define BACKLIGHT_PIN 3 //pin podświetlenia wyświetlacza 
LiquidCrystal_I2C lcd(0x27, 20 , 4); //adres wyświetlacza 

//Map sensor
const int pressureInput = A0; //PIN OD MAP SENSORA
const int pressureZero = 0; //analog reading of pressure transducer at 0psi
const int pressureMax = 330; //analog reading of pressure transducer at 100psi
const int pressuretransducermaxPSI = 3; //psi value of transducer being used


const int baudRate = 9600;
const int sensorreadDelay = 250; 


float pressureValue = 0; 
float OTValue = 0; 
float OPValue = 0; 

void setup() 
{
  Serial.begin(baudRate); 
    
    lcd.begin(20,4); //lcd Wire.begin(); 
    lcd.setBacklight(HIGH);
    
}

void loop() //loop routine runs over and over again forever
{
  //map sensor
  pressureValue = analogRead(pressureInput); //reads value from input pin and assigns to variable
  pressureValue = ((pressureValue-pressureZero)*pressuretransducermaxPSI)/(pressureMax-pressureZero); 
  Serial.print(pressureValue, 1);
  Serial.println("bar"); //prints label to serial

  
  lcd.setCursor(0,0); 
  lcd.print("Boost:"); 
  lcd.print(pressureValue-1, 1); 
  lcd.print("b"); 
  lcd.print("         .");
  
  lcd.print("OIL TEMP:         *C");//3 linia
  
  lcd.setCursor(0, 1); //Ustawienie kursora na drugiej linii i pierwszym znaku 
  lcd.print("OIL PRESSURE:      b"); //Wyświetlenie tekstu na 2 linii
    
  lcd.print("Intake temp:      ."); //Wyświetlenie tekstu na 4 linii
    
  delay(sensorreadDelay);
}


 

Znalazłem gdzieś w internetach że ktoś robił coś podobnego tylko na seryjny czujnik w porshe i użył takiego kodu : 
 

// the setup routine runs once when you press reset:
void setup() {}

// the loop routine runs over and over again forever:
void loop() {
// read the input on analog pin A3 and convert the analog reading (which goes from 0 - 1023) to voltage (0 - 5V):
float v = analogRead(A3) * (5.0 / 1023.0);
float vout = 2.0; // To ensure the needle stays below 120F when the temp is below 120F
//y = -0.3023x2 + 1.3098x + 0.294
if (v < 2.0) { vout = -0.3023*pow(v,2) + 1.3098*v + 0.294; }
// If using a non-Vision VDO oil temp gauge, comment out the previous line and uncomment the following line
//if (v < 2.0) { vout = -0.2352*pow(v,2) + 1.3098*v + 0.3117; }
//float vout = v; // Uncomment this line for calibration
// convert vout (0 - 5.0V) to output (0 - 255) and write to D1
analogWrite(1, (int)(255.0*vout/5.0));
delay(100);
}



Dla funkcji : 
image.thumb.png.76d1a9eae2c9bfba3c68b5aed6cdd17b.png

Niestety nie mam wiedzy i pojęcia jak to zrobić u mnie. Miałem kiedyś C++ w technikum ale nie za wiele pamiętam , C jest podobne ale nie mogę tego ogarnąć 😕 
PS. dostałem jeszcze gdzieś info żeby zastosować schemat Hornera, wtedy będzie to o wiele szybciej działać i mniej obciążać arduino i to już wgl dobiło moje umiejętności 😕 

 



 

Edytowano przez MatJJ
15 minut temu, farmaceuta napisał:

Jezeli te rozdzielczosci z tabel sa dla Ciebie wystarczajace to mozna dane pomiaru i dane analogowe wpakowac do dwoch tablic i odpowiednio porownywac z adc...z tym ze na "wyjsciu" uzyskasz tylko to co masz w tabelach...nic posredniego

W tabelach mam dane co ileś tam wartości, a chcę żeby działało to dla temperatury co 1*C a dla ciśnienia co do 0.1b 

(edytowany)
3 minuty temu, MatJJ napisał:

W tabelach mam dane co ileś tam wartości, a chcę żeby działało to dla temperatury co 1*C a dla ciśnienia co do 0.1b 

A no wlasnie...to moja metoda odpada z powodu malej ilosci probek...moze wiedzac powyzsze kolega @ethanak cos pomoze, bo ja nie mam pojecia czy da sie jakos algorytmem ogarnac taka nieliniowosc...🤔

A ..i wklej ten kod poprawnie

Edytowano przez farmaceuta
(edytowany)

No to albo napiszesz jakiś porąbany wielomian, albo po prostu potraktujesz wykres jako łamaną i odczytasz sobie wartość znajdując przedział. Niech U1 i U2 to są napięcia granic przedziału, Y1 i Y2 to graniczne wartości rzeczywiste dla tegoż przedziału, U0 to zmierzone napięcie. Wtedy wystarczy

float U= U0 - U1;
float x = (U-U1)/(U2-U1);
float Y= Y1 + (Y2 - Y1) * x;

I w zmiennej Y masz wynik, biorąc pod uwagę dokładność przetworników Arduino tak samo dokładny jak najprecyzyjniejszy wielomian.

Możesz to uprościć, wstawiając w tabele nie rzeczywiste napięcia a wartości typu int odczytane z przetwornika, a jako wartości wynikowe również wartości typu int jako wielokrotności Twojej rozdzielczości. Wtedy wystarczy prosta funkcja map:

 

Y=map(U0, U1, U2, Y1, Y2);

 

Edytowano przez ethanak
  • Lubię! 1

Co do wielomianu to chyba coś udało mi się zrobić żeby się pokrywało. Tylko nie mam wiedzy co dalej z tym zrobić 

image.thumb.png.85f253353f17f7e20edab45a85a38ff0.png

image.thumb.png.63679729e549e1b21a9620f299c8fbad.png

(po kliknięciu widać na górze). 

Z takimi informacjami coś mądrego uda się już zrobić? Jeżeli tak to czy byłbyś w stanie mi pomoc? Bo ja za cholerę nie potrafię a już dobre kilka dni próbuję 😕 

Dokladnie jak kolega @ethanak pisze..."dzielisz" skale na odcinki i liniowo sobie skalujesz...w przypadku temperatury to ladnie wyjdzie bo probek jest na tyle duzo ze praktycznie w kazdym odcinku masz zachowana liniowosc wiec wynik zawsze bedzie prawidlowy...gorzej z olejem...jezeli ten wykres powyzej jest dobry to szukasz sobie punktow gdzie od A do B jest w miare linia prosta...zapisujesz skrajne napiecia i odczyty, i mapujesz...powinno dzialac bardzo dobrze

Noo faktycznie! to będzie mega proste. 
@ethanak jesteś geniuszem !!! 😄

Czyli to: 

float U= U0 - U1;
float x = (U-U1)/(U2-U1);
float Y= Y1 + (Y2 - Y1) * x;

Robię dla każdego przedziału czyli przykładowo dzielę sobię mój wykres np. 
image.thumb.png.0e1ccbc55767a3b024560db2d42d46cd.png
I będzie okej 🙂 


I pytanko jak "połączyć" te przedziały? (To chyba najgłupsze pytanie jakie dziś mogłem zadać wybaczcie mi proszę ale chociaż czegoś się nauczę 🙂 



Panowie wielkie dzięki !!! 

 

Ja bym to zrobil na tablicach...tylko 5 przedzialow...sprawdzasz czy adc przekroczylo pierwszy przedzial...jesli tak to przechodzisz do nastepnego i na odwrot...caly czas oczywiscie skalujesz z uzyciem map() (zeby wyswietlic wynik)

(edytowany)

Dokładnie tak - i przejdź na inty, bo floaty są tu absolutnie niepotrzebne, a funkcja map() działa właśnie na intach.

Jak chcesz przykładowy kod to wieczorem, bo na telefonie słabo się kidy pisze.

Edytowano przez ethanak

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