Toteutin Arduinolla dataloggerin joka kerää auton/mp:n anturidataa.
Data on tällä hetkellä tämännäköistä
[rivi, kaasu, rpm, map, lambda1, lambda2]
1, 0, 1400, 260, 0.98, 1.05, 2, 1, 1550, 275, 1.02, 1.03, 3, 0.9, 1600, 290, 1.04, 0.97,
Tässä vaiheessa yritän keksiä, miten ohjelman saisi käymään läpi koko lokitiedoston ja laskemaan lambda-arvojen keskiarvon tiettyjen ehtojen mukaisesti.
Kaasun eri asentovälejä (prosenttia auki) on 22 kpl ja kierroslukualueita 31 kpl. Lambda-arvojen keskiarvot pitäisi saada esitettyä kaikilla kaasun asennoilla ja kullakin kaasun asennolla kaikilla kierroslukualueilla.
Millainen olisi fiksu toteutus?
Alla oleva koodin pätkä osaa tutkia yhden tapauksen 682:sta.
'''Data''' import sys #Constant variables ThrottlePos = 1 #index number for Throttle position RPM = 2 #index number for RPM #Functions here def Analyze_Data(cyl): #Variables for this function Lambda = 0 Counter = 0 if cyl == 1: Read_Lambda = 4 else: Read_Lambda = 5 Data = open("LoggedData.txt", "r") for line in Data: list = line.split(',') if 0 <= float(list[(ThrottlePos)]) < 1: if 500 <= float(list[RPM]) < 1500: Lambda += float(list[(Read_Lambda)]) Counter += 1 print list[ThrottlePos], list[RPM], list[(Read_Lambda)] #elif 1500 <= float(list[RPM]) < 2000: # Lambda += float(list[(Read_Lambda)]) # Counter += 1 # print list[ThrottlePos], list[RPM], list[(Read_Lambda)] print 'Average lambda: ', Lambda/Counter Data.close() def main(): Selected_Cyl = 1 Analyze_Data(Selected_Cyl); if __name__ == '__main__': main()
Dictionaryyn voi tallentaa erilliset arvot kaikille (throttle, rpm)-pareille.
Menevätkö lukurajat säännölisesti throttlessa yhden välein ja rpm:ssä tuhannen välein alkaen 500:sta? Tässä nopea esimerkkitoteutus.
INDEX_THROTTLE = 1 INDEX_RPM = 2 INDEX_LAMBDA1 = 4 INDEX_LAMBDA2 = 5 def make_key(throttle, rpm): throttle = int(throttle) rpm = int((rpm - 500) / 1000) return (throttle, rpm) def show_key(key): throttle, rpm = key return '%d <= throttle < %d, %d <= rpm < %d' % ( throttle, throttle + 1, rpm * 1000 + 500, rpm * 1000 + 1500, ) def analyze_data(): counts = {} lambdas1 = {} lambdas2 = {} with open("LoggedData.txt", "r") as data: for line in data: values = [float(x) for x in line.split(',')[:6]] key = make_key(values[INDEX_THROTTLE], values[INDEX_RPM]) lambdas1[key] = values[INDEX_LAMBDA1] + lambdas1.get(key, 0) lambdas2[key] = values[INDEX_LAMBDA2] + lambdas2.get(key, 0) counts[key] = 1 + counts.get(key, 0) for key in sorted(counts.keys()): avg1 = lambdas1[key] / counts[key] avg2 = lambdas2[key] / counts[key] print('Average lambdas for (%s): %f, %f' % (show_key(key), avg1, avg2)) if __name__ == '__main__': analyze_data()
$ python2 yamato.py Average lambdas for (0 <= throttle < 1, 500 <= rpm < 1500): 0.980000, 1.050000 Average lambdas for (0 <= throttle < 1, 1500 <= rpm < 2500): 1.040000, 0.970000 Average lambdas for (1 <= throttle < 2, 1500 <= rpm < 2500): 1.020000, 1.030000
Kiitos, siinä tulikin melkein valmis ratkaisu.
Lukurajat eivät mene säännöllisesti, enkä pysty niihin vaikuttamaan. Rajat näkee linkin takaa löytyvästä kuvakaappauksesta moottorinohjaussoftasta.
Ajatuksena on saada näkymään lokidata vastaavalla tavalla, jonka pohjalta voi tehdä tarvittavat muutokset moottorinohjaukseen eli tässä tapauksessa ruiskutettavan polttoaineen määrään.
Täytyy opiskella lisää for -looppien ja dictionaryjen sielunelämää. Vaikuttaa erittäin kätevältä. Ideatasolla ymmärrän tuon kirjoittamasi koodin, mutta en riittävästi pystyäkseni muokkaamaan mieleiseksi.
Idea on siis, että jos esimerkiksi throttle=0.9 ja rpm=1599, nämä pyöristetään alaspäin lähimpään rajaan, tässä tapauksessa throttle -> 0 ja rpm -> 1470. Kun tätä normalisoitua paria käytetään dictionaryn avaimena, kaikki samojen rajojen välissä olevat (throttle,rpm)-parit lasketaan samaan keskiarvoon.
Rajat voi tallentaa listaan ja etsimisen voi tehdä silmukalla.
INDEX_THROTTLE = 1 INDEX_RPM = 2 INDEX_LAMBDA1 = 4 INDEX_LAMBDA2 = 5 THROTTLE_LIMITS = [ 0, 1, 2, 3, 4, 5, 6, 8, 10, 15, 20, 25, 30, 35, 40, 50, 60, 70, 80, 100, ] RPM_LIMITS = [ 0, 800, 1050, 1250, 1470, 1600, 1800, 2000, 2200, 2300, 2400, 2500, 2600, 2800, 3000, 3250, 3500, 3750, 4000, 4500, 5000, 5500, 6000, 6500, 7000, 7500, 8000, 8500, 9000, 9500, 10000, 10500, ] def find_lower(x, values): for a, b in zip(values, values[1:]): if a <= x < b: return a return values[-1] def make_key(throttle, rpm): throttle = find_lower(throttle, THROTTLE_LIMITS) rpm = find_lower(rpm, RPM_LIMITS) return (throttle, rpm) def show_key(key): return 'throttle >= %d, rpm >= %d' % key # ... loput niin kuin ennenkin
Average lambdas for (throttle >= 0, rpm >= 1250): 0.980000, 1.050000 Average lambdas for (throttle >= 0, rpm >= 1600): 1.040000, 0.970000 Average lambdas for (throttle >= 1, rpm >= 1470): 1.020000, 1.030000
jlaire kirjoitti:
def find_lower(x, values): for a, b in zip(values, values[1:]): if a <= x < b: return a return values[-1]
Irrallisena toteutusteknisenä vinkkinä mainitsen, että tuossa voisi hyödyntää myös bisect.bisect_left-funktiota, joka etsii nousevassa järjestyksessä olevasta listasta annettua arvoa vastaavan kohdan indeksin binäärihakua käyttäen.
Tässä sovelluskohteessa tuon merkitys on olematon, mutta tämä oli lähinnä aasinsilta siihen, että haluan rohkaista kaikkia Pythoniin perehtyviä selaamaan standardikirjaston tarjonnan läpi. Sieltä löytyy vaikka mitä hyödyllistä.
Kiitos vinkeistä. Lisäilin ohjelmaan oman osion MAP/RPM datan esittämiselle ja funktion, joka määrittää meneekö esitetty data Throtte/RPM vai MAP/RPM karttaan.
Nyt tuo data pitäisi saada visuaaliseen muotoon samaan tapaan kuin aiemmin linkkaamassani kuvassa. Pythoniin on näköjään vaikka minkälaisia lisäpalikoita tarjolla, millä toteutus onnistuu. Kunhan osaisi valita sopivimman.
Yamato kirjoitti:
Nyt tuo data pitäisi saada visuaaliseen muotoon samaan tapaan kuin aiemmin linkkaamassani kuvassa. Pythoniin on näköjään vaikka minkälaisia lisäpalikoita tarjolla, millä toteutus onnistuu. Kunhan osaisi valita sopivimman.
Tekisin tuollaisen taulukkomuodon HTML:llä, jota on helppo tuottaa suoraan Pythonilla ilman mitään lisäpalikkaa. Kuvaksi sen saa kuvaruutukaappauksella ja tallentamalla esim. PNG-muotoon.
Joku toinen voisi käyttää SVG-muotoa. Joku kolmas kirjoittaisi datat CSV-muotoon, veisi sen taulukkolaskentaohjelmaan ja määrittäisi siellä solujen väriarvot lukujen perusteella. Ja se neljäs hoitaisi homman Pythonin lisäpalikalla.
Kokeilin harjoituksen vuoksi kirjoittaa datan CSV-tiedostoon.
fo = open("datacsv.csv", "w") fo.write('Throtte/RPMs,,') for y in THROTTLE_LIMITS: fo.write('%s,' % (y)) for x in RPM_LIMITS: fo.write('\n %s,' % (x)) for y in THROTTLE_LIMITS: if lambdas1.get((y, x), 0) != 0: lambda_value = lambdas1.get((y, x), 0)/ counts.get((y, x), 0) lambda_value = round(lambda_value ,2) #print lambda_value fo.write('%s,' % (lambda_value)) else: fo.write(',')
Throtte/RPMs,,0,1,2,3,4,5,6,8,10,15,20,25,30,35,40,50,60,70,80,100, 0,,,,,,,,,,0.96,,1.03,,,,,0.97,,0.91,, 800,,,,,,,,,,0.99,,,,,,0.92,,,,, 1050,,,,,,,,,,,,0.92,,1.08,,,,1.0,,, 1250,,,,,,,,,,,,,,,,,,,,, 1470,,,,,,,,,,,0.92,,,,,1.09,,,,, 1600,,,,,,,,,,,,,1.0,,,,,1.0,,,
Ei ole ehkä "kaunis" ratkaisu, mutta tekee mitä pyydetään.
Pitää silti koittaa saada aikaan Python -pohjainen ratkaisu. Tavoitteena olisi tehdä vielä jonkunlainen GUI, jolla saa haettua lokitiedoston Arduinon muistikortilta yms. pientä.
Aihe on jo aika vanha, joten et voi enää vastata siihen.