Skocz do zawartości

Projekt z czujnikami do auta


MatJJ

Pomocna odpowiedź

Panowie jakbym mógł poprosić przykładowy kod dla tej mojej tabelki to byłbym wdzięczny bardzo 🙂
Wieczorem jakoś o 19 siadam do tego to bym może coś z Waszą pomocą stworzył. 

Przedziały które uważam że będą okej : 
image.thumb.png.e221e48826cf70efeebdec375435c208.png

image.thumb.png.949d41f76d7f970c83b30418e2476092.png


Jeżeli można to zagęścić bez uszczerbku na wydajności programu to potwierdźcie mi to i jak będę miał coś przykładowego np. dla tych wartości wyżej to już będe ogarniał 🙂

Dzięki wielkie !!!

Link do komentarza
Share on other sites

No więc tak.

Niedawno ktoś w innym wątku stwierdził, że wszystko już zostało wymyślone i nie warto robić nic nowego bo świata się nie zbawi. Postanowiłem mu uwierzyć i po krótkich poszukiwaniach znalazłem bibliotekę, która robi dokładnie to czego potrzebujemy, czyli MultiMap. Zabrzmiało to obiecująco, więc czym prędzej to coś zainstalowałem (na szczęście nie trzeba nic kombinować, otwierasz managera bibliotek i szukasz "multimap").

Pierwsze próby wypadły obiecująco. Nagryzmoliłem jakiś kawałek kodu (nie mam pod ręką żadnego AVR-a, więc po prostu skompilowałem program na pececie). Program dość krótki obsługujący czujnik cisnienia oleju wygląda u mnie tak:

// żeby g++ na pececie wiedzial gdzie jest printf
#include <stdio.h>

#include <MultiMap.h>


float press_out[]={0,   4.14, 5.52, 1.38, 2.76, 6.90, 8.28, 9.66, 10.35};
float press_in[]={0.26, 1.46, 2.18, 2.76, 3.14, 3.40, 3.51, 3.60, 3.71};

int main(void)
{
	int i;
	for (i=0; i<40; i++) {
		float p = i/10.0; // to powinn być zaczytane z wejscia analogowego
		float o = multiMap(p, press_in, press_out, 9);
		printf("%.2f %.2f\n", p, o);
	}
	return 0;
}

Wynik działania programu wygląda następująco:

0.00 0.00
0.10 0.00
0.20 0.00
0.30 0.14
0.40 0.48
0.50 0.83
0.60 1.17
0.70 1.52
0.80 1.86
0.90 2.21
1.00 2.55
1.10 2.90
1.20 3.24
1.30 3.59
1.40 3.93
1.50 4.22
1.60 4.41
1.70 4.60
1.80 4.79
1.90 4.98
2.00 5.17
2.10 5.37
2.20 5.38
2.30 4.66
2.40 3.95
2.50 3.24
2.60 2.52
2.70 1.81
2.80 1.53
2.90 1.89
3.00 2.25
3.10 2.61
3.20 3.72
3.30 5.31
3.40 6.90
3.50 8.15
3.60 9.66
3.70 10.29
3.80 10.35
3.90 10.35

Jak widać wyniki są OK, funkcja reaguje ładnie na wartości spoza zakresu, więc teoretycznie mona ją zastosować.

Niestety, fakt że ktoś coś tam napisał nie oznacza, że zrobił to dobrze. Funkcja ma dwie zasadnicze wady związane z Arduino:

Autor funkcji nie przewidział, że tabele in i out będą umieszczone w pamięci flash, a takie dane na Arduino odczytuje się nieco inaczej.

Nie przewidział również, że jeśli zastąpimy floaty intami funkcja zwróci w pewnych przypadkach bzdury nawet jeśli te inty siedzą w RAM-e; po prostu może wystąpić przepełnienie.

Jako że - jak pisałem - nie mam pod ręką żadnego AVR-a, nie będę zbawiał świata; ta funkcja pewnie wystarczy. Co prawda obie tabele (ciśnienie i temperatura) zajmą ponad 20% pamięci Arduino - ale nie powinno to sprawiać problemu...

Jeśli sprawi - daj znać, będziemy kombinować dalej.

 

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

Jakoś z pomocą tinkercada zrobiłem wersję działającą na tablicach we flashu:


const float PROGMEM press_out[]={0,   4.14, 5.52, 1.38, 2.76, 6.90, 8.28, 9.66, 10.35};
const float PROGMEM press_in[]={0.26, 1.46, 2.18, 2.76, 3.14, 3.40, 3.51, 3.60, 3.71};

// przepisane z oryginalnej funkcji, komentarze pozostawiłem
float multiMap(float value, const float * in, const float * out, uint8_t size)
{
    // take care the value is within range
    // value = constrain(value, in[0], in[size-1]);
    if (value <= pgm_read_float(in)) return pgm_read_float(out);
    if (value >= pgm_read_float(in+size-1)) return pgm_read_float(out+size-1);

    // search right interval
    uint8_t pos = 1;  // in[0] already tested
    while(value > pgm_read_float(in+pos)) pos++;

    // this will handle all exact "points" in the _in array
    if (value == pgm_read_float(in+pos)) return pgm_read_float(out+pos);

    // interpolate in the right segment for the rest
    return (value - pgm_read_float(in+pos-1)) * (pgm_read_float(out+pos) - pgm_read_float(out+pos-1)) /
		(pgm_read_float(in+pos) - pgm_read_float(in+pos-1)) + pgm_read_float(out+pos-1);
}

void setup()
{
	Serial.begin(9600);
	Serial.println("HELLO");
	int i;
	for (i=0;i<40; i++) {
		float p = i/ 10.0;
		float o = multiMap(p, press_in, press_out, 9);
		Serial.print(p); Serial.print(" ");Serial.println(o);
	}
}

void loop()
{
}

Dobra, dość naprawiania świata 🙂

  • Lubię! 1
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

Dzięki za kod. 

Po podaniu wejścia analogowego i wyświetleniu na ekranie powinno hulać ? 
Bo zrobiłem to i:

dla kodu nr1:
Wywala błąd float dla biblioteki liqiuid crystal i2c . 


dla kodu nr2:
 image.thumb.png.96191fdab4dfe0109a9bf6f1beae6c55.png 
I nic się nie dzieje. 

Jesteś w stanie w wolnym czasie napisać kod gotowy w którym tylko podmienił wejścia na takie na jakich faktycznie podepnę czujnik i ekran ? 
Niestety wychodzi na to że jestem cienki jak.. i nie mogę potrafię tego zrobić. Myślałem że to łatwiejsze zadanie 😕 
 

Link do komentarza
Share on other sites

Oj, popatrz dokładnie co robi mój kod.

- symuluje odczytanie różnych wartości i wstawia do zmiennej p;

- przelicza za pomocą funkcji multiMap wartość napięcia ze zmiennej p i wstawia do zmiennej o;

- wypisuje obie wartości.

Jeśli teraz zrobisz coś w stylu:

float p = odczyt_z_czujnika();
float o = multiMap (p, press_in, press_out, 9);

gdzie press_in to tabelka napięć, press_out to odpowiadające wartości ciśnień, a ostatni parametr to rozmiar tabelek - w zmiennej o będziesz miał ciśnienie.

Tabelki ciśnień masz przepisane. Korzystaj z mojej (drugiej) wersji i tablic PROGMEM.

Tak wystarczy?

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

(edytowany)

Wczoraj na szybko zrobilem według filmu https://www.youtube.com/watch?v=qwllQ3LI4qo
praktycznie wszystko jest okej tylko pokazuje mi wartości na odwrót, jak zwiekszam temp to rezystancja w programie rosnie zamiast maleć. 
Nie mogę znaleźć gdzie leży błąd w kodzie. Bo raczej w podłączeniu nie mogłem sie pomylić ? 
Teoretycznie dziala wszystko szybko tylko dla czujnika ciśnienia i temp musiałbym dac funkcje innego stopnia jezeli mialoby byc dokladniej. 

 

/* This example code shows how to display temperature
 *  from a standard 1 or 2 wire automotive coolant temperature
 *  sensor. These types of sensors are a simple thermistor in
 *  an industrial casing. Thermistor's change resistance based
 *  on temperature. A voltage divider circuit must be used to
 *  read the voltage to a microcontroller. Contact tylerovens@me.com
 *  if you have any questions.
 */

#define coolantsensorDivider 2970   //defines the resistor value that is in series in the voltage divider
#define coolantsensorPin A0         //defines the analog pin of the input voltage from the voltage divider
#define NUMSAMPLES 5                //defines the number of samples to be taken for a smooth average


const float steinconstA = 0.001592353;        //steinhart equation constant A, determined from wikipedia equations
const float steinconstB = 0.0002198841;       //steinhart equation constant B, determined from wikipedia equations
const float steinconstC = 0.000000311;    //steinhart equation constant C, determined from wikipedia equations

int samples[NUMSAMPLES];                              //variable to store number of samples to be taken

void setup() {
  Serial.begin(9600);                                 //start serial monitor
}

void loop() {
  uint8_t i;                                          //integer for loop
  float average;                                      //decimal for average
  
  for (i=0; i<NUMSAMPLES; i++) {                      
    samples[i] = analogRead(coolantsensorPin);        //takes samples at number defined with a short delay between samples
    delay(10);
  }

  average = 0;
  for (i=0; i< NUMSAMPLES; i++) {
    average += samples[i];                            //adds all number of samples together
  }
  average /= NUMSAMPLES;                              //divides by number of samples to output the average

  Serial.print("Average Analog Coolant Reading = ");
  Serial.println(average);                                        //analog value at analog pin into arduino
  average = (coolantsensorDivider*average)/(1023-average);        //conversion equation to read resistance from voltage divider
  Serial.print("Coolant Sensor Resistance = ");
  Serial.println(average);

  float steinhart;                              //steinhart equation to estimate temperature value at any resistance from curve of thermistor sensor
  steinhart = log(average);                     //lnR
  steinhart = pow(steinhart,3);                 //(lnR)^3
  steinhart *= steinconstC;                     //C*((lnR)^3)
  steinhart += (steinconstB*(log(average)));    //B*(lnR) + C*((lnR)^3)
  steinhart += steinconstA;                     //Complete equation, 1/T=A+BlnR+C(lnR)^3
  steinhart = 1.0/steinhart;                    //Inverse to isolate for T
  steinhart -= 273.15;                          //Conversion from kelvin to celcius

  Serial.print("Temperature = ");
  Serial.print(steinhart);                      //prints final temp in celcius
  Serial.println(" *C");
  
  delay(1000);                                  //delay between readings
}


 

Edytowano przez MatJJ
Link do komentarza
Share on other sites

(edytowany)

@ethanak moj kod: 

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



const float PROGMEM press_out[]={40,50,60,70,80,90,100,110,120,130,140,150};
const float PROGMEM press_in[]={3.69,3.28,2.85,2.44,2.02,1.65,1.33,1.07,0.85,0.68,0.55,0.44,};

// przepisane z oryginalnej funkcji, komentarze pozostawiłem
float multiMap(float value, const float * in, const float * out, uint8_t size)
{
    // take care the value is within range
    // value = constrain(value, in[0], in[size-1]);
    if (value <= pgm_read_float(in)) return pgm_read_float(out);
    if (value >= pgm_read_float(in+size-1)) return pgm_read_float(out+size-1);

    // search right interval
    uint8_t pos = 1;  // in[0] already tested
    while(value > pgm_read_float(in+pos)) pos++;

    // this will handle all exact "points" in the _in array
    if (value == pgm_read_float(in+pos)) return pgm_read_float(out+pos);

    // interpolate in the right segment for the rest
    return (value - pgm_read_float(in+pos-1)) * (pgm_read_float(out+pos) - pgm_read_float(out+pos-1)) /
    (pgm_read_float(in+pos) - pgm_read_float(in+pos-1)) + pgm_read_float(out+pos-1);
}

void setup()
{
  Serial.begin(9600);
  lcd.begin(20,4); //lcd Wire.begin(); 
  lcd.setBacklight(HIGH);
  
  Serial.println("HELLO");
  int i;
  for (i=0;i<40; i++) {
    float p = analogRead(wejscie);
    float o = multiMap(p, press_in, press_out, 12);
    Serial.print(p); 
    Serial.print(" ");
    Serial.print(o);
  }
}

void loop()
{
}


Efekt: 

COM8:
HELLO
260.00 150.00259.00 150.00258.00 150.00259.00 150.00259.00 150.00258.00 150.00259.00 150.00260.00 150.00260.00 150.00260.00 150.00259.00 150.00259.00 150.00259.00 150.00258.00 150.00259.00 150.00258.00 150.00259.00 150.00259.00 150.00258.00 150.00258.00 150.00258.00 150.00258.00 150.00260.00 150.00258.00 150.00258.00 150.00259.00 150.00258.00 150.00258.00 150.00258.00 150.00259.00 150.00258.00 150.00258.00 150.00259.00 150.00260.00 150.00258.00 150.00258.00 150.00258.00 150.00258.00 150.00258.00 150.00258.00 150.00


ehh.. 😕

Edytowano przez MatJJ
Link do komentarza
Share on other sites

Prosiłem o kod do tego kawałka programu który Ci działa (sam pisałeś że działa czujnik ciśnienia dołafowania  ja chcę to zobaczyć) -kopiowanie bez zrozumienia jakichś kodów które robią zupełnie coś innego to fatalny pomysł.

Przy okazji - napisałem wczoraj lepszą funkcję, ale to dopiero jak pokażesz kod o który prosiłem i jak się pożegnam ze Świętym Mikołajem 🙂

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

#include <LiquidCrystal_I2C.h> 
#include <Wire.h>
#include <MultiMap.h>
#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; 
const int pressureMax = 330; 
const int pressuretransducermaxBAR = 3; 

const int baudRate = 9600; 
const int sensorreadDelay = 250; //1/4 s odsw.


float pressureValue = 0; 
 

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

void loop() 
{
  //map sensor
  pressureValue = analogRead(pressureInput); 
  pressureValue = ((pressureValue-pressureZero)*pressuretransducermaxBAR)/(pressureMax-pressureZero); 
  Serial.print(pressureValue, 1); 
  Serial.println("bar"); 
  
  lcd.setCursor(0,0); //k0 l0
  lcd.print("Boost:"); 
  lcd.print(pressureValue-1, 1); 
  lcd.print("b");
  lcd.print("         ."); 
  
  lcd.print("OIL TEMP:  XX    *C");//3 linia
  
  lcd.setCursor(0, 1); //linia 2
  lcd.print("OIL PRESSURE:  XX b"); //Wyświetlenie tekstu na 2 linii
    
  lcd.print("Intake temp:  XX  ."); //Wyświetlenie tekstu na 4 linii
    
  delay(sensorreadDelay); 
}

To kod dla cisnienia doladowania. Na wartości nie ma co na razie patrzec bo skalibrowany jest mniej więcej, po świetach wakumetrem musze zweryfikowac co i jak. 

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.