Помогите с кодом

Fiell
Offline
Зарегистрирован: 01.02.2018
Здравствуйте, помогите пожалуйста , уже 2 недели мучаюсь. Я новичек в Arduino поэтому прошу не пинать меня)
Код бортового компьютера для авто. Код работает, но есть проблемма.
Проблемма заключается в сохранении EEPROM.
 
Использую строки   
EEPROM.get(104, benz_full);
EEPROM.get(200, odometr);
 
и записываю
 
  EEPROM.put(104, benz_full);
  EEPROM.put(200, odometr);
Но после перезапуска Odometr загружается и считает дальше, а benz_full загружается но после получения данных сбрасывает на 0 и начитает считать. Код прилагаю.
 
#include <LiquidCrystal_I2C.h>
#include <EEPROM.h>
#include "ecu.h"

LiquidCrystal_I2C lcd(0x27, 20, 4); // LiquidCrystal(rs, enable, d4, d5, d6, d7)

Ecu ecu;
unsigned long time_new, time_old, time_old_gurnal;
uint32_t t;
int  rpm_var, uoz_var, polozh_dross_zaslon, speed_var, inj_time_var, speed_var3, speed_var4, tmp_var, t2, t1;
float  time,  inj_time_full, odometr_add, inj_time_cycle, odometr_add3, odometr_add4, voltage, benz_full_eeprom;
bool flagNulSpeed = true;

float odometr = 0;
float benz_full = 0;
float benz_100 = 0;
void setup()
{
  Serial.begin(38400);
  lcd.init();
  lcd.backlight();
  t = millis();
  EEPROM.get(104, benz_full);
  EEPROM.get(200, odometr);

}

void loop()
{

  uint32_t new_t;
  uint16_t diff_t;
  inj_time_cycle = 0;
  int rpm_var = ecu.getRpm();
  int tmp_var = ecu.getEct();
  int voltage = ecu.getBattery();
  t = millis();
  {
    Speed(); // получить скорость

    if (time_old == 0) {
      time_old = millis();  // выполнится один раз при появлении оборотов
    }

    time_new = millis();   // время со старта программы в мс
    time = (double(time_new - time_old) / 1000.0); // прошло время с последнего расчета скорости, расхода  - в сек
    if (time > 10) {
      time = 0;
    }
    time_old = time_new;  // записать новое время для сравнения в следующем цикле

    if (speed_var > 0) {
      odometr_add = double((double(speed_var * 1000.0) / 3600.0) * time) / 1000.0;
      odometr = odometr + odometr_add; //обший пробег в км

    }
  }

  Benz(); // расход и время форсунок

  if (inj_time_var > 0) {
    new_t = millis();
    diff_t = new_t - t;
    inj_time_cycle = rpm_var / 120000.0 * 4.0 * (float)diff_t  * inj_time_var;//общее время форсунок за поездку
    inj_time_full = double(double(inj_time_cycle + inj_time_full)) ; //общее время форсунок за поездку (соовсем общее)
    benz_full = double(double((inj_time_full * 0.005416666666667) / 10.0)); //бензин за поездку
    benz_100 = benz_full / odometr * 100;//средний расход на 100 км за поездк

  }

  EEPROM.put(104, benz_full);
  EEPROM.put(200, odometr);

  lcd.setCursor(0, 0);
  lcd.print(speed_var); // Скорость
  lcd.print(" km/h");
  lcd.setCursor(12, 0);
  lcd.print(rpm_var); //Обороты
  lcd.print(" rpm");
  lcd.setCursor(0, 1);
  float cons = ecu.getInstantConsumption();
  lcd.print(cons); // л/час
  lcd.print(" L/h");
  lcd.setCursor(12, 1);
  lcd.print(benz_full);
  lcd.setCursor(0, 2);
  float cons1 = ecu.getInstantfFuel();
  lcd.print(cons1);
  lcd.print(" L/100");
  lcd.setCursor(12, 2);
  lcd.print(tmp_var);  //Температура
  lcd.setCursor(0, 3);
  lcd.print(odometr); // пройденный путь с заводки авто
  lcd.print(" km");
  lcd.setCursor(12, 3);
  lcd.print(benz_100); // средний расход на 100 км
  lcd.print(" L");
}

void Speed(void) {
  speed_var = ecu.getVss();
}

void Benz(void) {
  inj_time_var = ecu.getInj();
}

void Tmp(void) {
  tmp_var = ecu.getEct();
}

void Rpm(void) {
  rpm_var = ecu.getRpm();
}

void DavlenVpuskKoll(void) {
  ecu.getMap();
}

void IntakeAirTemp(void) {
  ecu.getIat();
}

void Voltage(void) {
  voltage = ecu.getBattery();
}

void Uoz(void) {
  ecu.getInj();
}

void Pdz(void) {
  ecu.getTps();
}

 

 

b707
Offline
Зарегистрирован: 26.05.2017

Fiell пишет:

Но после перезапуска Odometr загружается и считает дальше, а benz_full загружается но после получения данных сбрасывает на 0 и начитает считать. Код прилагаю.

У вас в коде так и есть - в случае одметра новое значение километража прибавляется с старому, а в случае с benz_full вы прочитанные из ЕПРОМ данные в программе нигде не используете, а вместо этого в строке 66 считаете banz_full с нуля.

 

ЗЫ На будущее - не создавайте тем с глупыми, ничего не значащими названиями - типа "Помогите новичку" или как у вас. Пишите конкретно - "Не заполняется массив", "Не обновляются данные из епром" и тд

Fiell
Offline
Зарегистрирован: 01.02.2018

Спасибо, буду исправляться)

если вас правильно понял то код должен быть такой?

#include <LiquidCrystal_I2C.h>
#include <EEPROM.h>
#include "ecu.h"

LiquidCrystal_I2C lcd(0x27, 20, 4); // LiquidCrystal(rs, enable, d4, d5, d6, d7)

Ecu ecu;
unsigned long time_new, time_old, time_old_gurnal;
uint32_t t;
int  rpm_var, uoz_var, polozh_dross_zaslon, speed_var, inj_time_var, speed_var3, speed_var4, tmp_var, t2, t1;
float  time,  inj_time_full, odometr_add, inj_time_cycle, odometr_add3, odometr_add4, voltage, benz_full_eeprom, benz_full;
bool flagNulSpeed = true;

float odometr = 0;
float benz_add = 0;
float benz_100 = 0;
void setup()
{
  Serial.begin(38400);
  lcd.init();
  lcd.backlight();
  t = millis();
  EEPROM.get(104, benz_add);
  EEPROM.get(200, odometr);

}

void loop()
{

  uint32_t new_t;
  uint16_t diff_t;
  inj_time_cycle = 0;
  int rpm_var = ecu.getRpm();
  int tmp_var = ecu.getEct();
  int voltage = ecu.getBattery();
  t = millis();
  {
    Speed(); // получить скорость

    if (time_old == 0) {
      time_old = millis();  // выполнится один раз при появлении оборотов
    }

    time_new = millis();   // время со старта программы в мс
    time = (double(time_new - time_old) / 1000.0); // прошло время с последнего расчета скорости, расхода  - в сек
    if (time > 10) {
      time = 0;
    }
    time_old = time_new;  // записать новое время для сравнения в следующем цикле

    if (speed_var > 0) {
      odometr_add = double((double(speed_var * 1000.0) / 3600.0) * time) / 1000.0;
      odometr = odometr + odometr_add; //обший пробег в км

    }
  }

  Benz(); // расход и время форсунок

  if (inj_time_var > 0) {
    new_t = millis();
    diff_t = new_t - t;
    inj_time_cycle = rpm_var / 120000.0 * 4.0 * (float)diff_t  * inj_time_var;//общее время форсунок за поездку
    inj_time_full = double(double(inj_time_cycle + inj_time_full)) ; //общее время форсунок за поездку (соовсем общее)
    benz_full = double(double((inj_time_full * 0.005416666666667) / 10.0)); //бензин за поездку
    benz_add = benz_full + benz_add;
    benz_100 = benz_add / odometr * 100;//средний расход на 100 км за поездк

  }

  Eeprom(); // расход и время форсунок

  if (speed_var = 0) {
    EEPROM.put(104, benz_add);
    EEPROM.put(200, odometr);
    delay(3000);
  }

  lcd.setCursor(0, 0);
  lcd.print(speed_var); // Скорость
  lcd.print(" km/h");
  lcd.setCursor(12, 0);
  lcd.print(rpm_var); //Обороты
  lcd.print(" rpm");
  lcd.setCursor(0, 1);
  float cons = ecu.getInstantConsumption();
  lcd.print(cons); // л/час
  lcd.print(" L/h");
  lcd.setCursor(12, 1);
  lcd.print(benz_add);
  lcd.setCursor(0, 2);
  float cons1 = ecu.getInstantfFuel();
  lcd.print(cons1);
  lcd.print(" L/100");
  lcd.setCursor(12, 2);
  lcd.print(tmp_var);  //Температура
  lcd.setCursor(0, 3);
  lcd.print(odometr); // пройденный путь с заводки авто
  lcd.print(" km");
  lcd.setCursor(12, 3);
  lcd.print(benz_100); // средний расход на 100 км
  lcd.print(" L");
}

void Speed(void) {
  speed_var = ecu.getVss();
}

void Benz(void) {
  inj_time_var = ecu.getInj();
}

void Eeprom(void) {

}

void Tmp(void) {
  tmp_var = ecu.getEct();
}

void Rpm(void) {
  rpm_var = ecu.getRpm();
}

void DavlenVpuskKoll(void) {
  ecu.getMap();
}

void IntakeAirTemp(void) {
  ecu.getIat();
}

void Voltage(void) {
  voltage = ecu.getBattery();
}

void Uoz(void) {
  ecu.getInj();
}

void Pdz(void) {
  ecu.getTps();
}

 

b707
Offline
Зарегистрирован: 26.05.2017

мне кажется, вы не вполне понимаете логику своей (?) программы. Я не очень хорошо понимаю, что вообще такое benz_full. но, по-моему, вы его снова считаете неправильно. Во-всяком случае, в этом скетче вы точно также, как и в первом, не используете данные, прочитанные из ЕПРОМ.

Fiell
Offline
Зарегистрирован: 01.02.2018

Уже голова кругом если честно , вообщем benz_full это количество спаленного топлива за время работы ардуино . Так вот я хочу сделать чтобы , оно при отключении питания сохранялось , а при включении ардуино , продолжала его . Просто как мне кажется , я с full_Benz делаю тоже самое , что и с odometr. Но одометр считается , а бензин нет.

b707
Offline
Зарегистрирован: 26.05.2017

строчки 66-68 попробуйте так переписать

benz_add = double(double((inj_time_full * 0.005416666666667) / 10.0)); //бензин за поездку
benz_full = benz_full + benz_add;
benz_100 = benz_full/ odometr * 100;//средний расход на 100 км за поездк

 

Fiell
Offline
Зарегистрирован: 01.02.2018

Наверное так не получится мне нудно сохранить в eeprom именно количество топлива , то есть например benz_full = 1.0 при выключении ардуино оно его сохраНила в eeprom , а при включении достало его и начала считать дальше , 1.0 ,1.1 ,1.2 ....

b707
Offline
Зарегистрирован: 26.05.2017

нет, немного не так. Если я правильно понимаю ваши формулы - вот так надо

benz_add = double(double((inj_time_cycle * 0.005416666666667) / 10.0)); //бензин за поездку
benz_full = benz_full + benz_add;
benz_100 = benz_full/ odometr * 100;//средний расход на 100 км за поездк

только комментарии неверные.

benz_add - это бензин не за всю поездку, а только со времени предыдущего расчета, а benz_100 - расход не за поездку, а за все время накопления данных

b707
Offline
Зарегистрирован: 26.05.2017

Fiell пишет:
Наверное так не получится мне нудно сохранить в eeprom именно количество топлива , то есть например benz_full = 1.0 при выключении ардуино оно его сохраНила в eeprom , а при включении достало его и начала считать дальше , 1.0 ,1.1 ,1.2 ....

по-моему, мы это и делаем, что вас смущает?

Скажите для определенности - эти формулы ваши или вы их где-то в инете скопировали вместе с кодом? Вы их понимаете и можете обьяснить, что и как считается в формулах?

Fiell
Offline
Зарегистрирован: 01.02.2018

Нет формула Benz_full выводит кол-во литров топлива , которое авто спалило с момента включения ардуино. Т.е
inj_time_full - это сумарное время открытых форсунок с момента включения
0.005416666666667 - это производительность форсунки
При выводе формулы на экран показывает кол-во потраченного бензина с момента включения.
Код мой , на него уже месяц потратил , все работает , только с eeprom как-то тяжеловато.
Нужно сохранять benz_full и при включении продолжать его .

b707
Offline
Зарегистрирован: 26.05.2017

ок, но тогда придется ввести переменную benz_full_new

код:

benz_add = double(double((inj_time_full * 0.005416666666667) / 10.0)); //бензин за поездку
benz_full_new = benz_full + benz_add;
benz_100 = benz_add / odometr * 100;//средний расход на 100 км за поездк

По-моему, сейчас все строго так, как вы хотели.

benz_add = /бензин за поездку
benz_100 =  средний расход на 100 км за поездку

В начале программы читаете из ЕЕПРОМ общий расход бензина в переменную benz_full , а в конце работы сохраняете новое значение из переменной  benz_full_new

Fiell
Offline
Зарегистрирован: 01.02.2018

Вы гений ,спасибо , вроде разобрался. Завтра напишу результат , сейчас на работу ушел.

Fiell
Offline
Зарегистрирован: 01.02.2018
#include <LiquidCrystal_I2C.h>
#include <EEPROM.h>
#include "ecu.h"

LiquidCrystal_I2C lcd(0x27, 20, 4); // LiquidCrystal(rs, enable, d4, d5, d6, d7)

Ecu ecu;
unsigned long time_new, time_old, time_old_gurnal;
uint32_t t;
int  rpm_var, uoz_var, polozh_dross_zaslon, speed_var, inj_time_var, speed_var3, speed_var4, tmp_var, t2, t1;
float  time,  inj_time_full, odometr_add, inj_time_cycle, odometr_add3, odometr_add4, voltage, benz_full_eeprom, benz_full, benz_full_new, benz_add;
bool flagNulSpeed = true;

float odometr = 0;
float benz_100 = 0;
void setup()
{
  Serial.begin(38400);
  lcd.init();
  lcd.backlight();
  t = millis();
  benz_full = EEPROM.get(104, benz_full_new);
  EEPROM.get(200, odometr);

}

void loop()
{

  uint32_t new_t;
  uint16_t diff_t;
  inj_time_cycle = 0;
  int rpm_var = ecu.getRpm();
  int tmp_var = ecu.getEct();
  int voltage = ecu.getBattery();
  t = millis();
  {
    Speed(); // получить скорость

    if (time_old == 0) {
      time_old = millis();  // выполнится один раз при появлении оборотов
    }

    time_new = millis();   // время со старта программы в мс
    time = (double(time_new - time_old) / 1000.0); // прошло время с последнего расчета скорости, расхода  - в сек
    if (time > 10) {
      time = 0;
    }
    time_old = time_new;  // записать новое время для сравнения в следующем цикле

    if (speed_var > 0) {
      odometr_add = double((double(speed_var * 1000.0) / 3600.0) * time) / 1000.0;
      odometr = odometr + odometr_add; //обший пробег в км

    }
  }

  Benz(); // расход и время форсунок

  if (inj_time_var > 0) {
    new_t = millis();
    diff_t = new_t - t;
    inj_time_cycle = rpm_var / 120000.0 * 4.0 * (float)diff_t  * inj_time_var;//общее время форсунок за поездку
    inj_time_full = double(double(inj_time_cycle + inj_time_full)) ; //общее время форсунок за поездку (соовсем общее)
    benz_add = double(double((inj_time_full * 0.005416666666667) / 10.0)); //бензин за поездку
    benz_full_new = benz_full + benz_add;
    benz_100 = benz_full_new / odometr * 100;//средний расход на 100 км за поездк

  }


    EEPROM.put(104, benz_full_new);
    EEPROM.put(200, odometr);
  
  lcd.setCursor(0, 0);
  lcd.print(speed_var); // Скорость
  lcd.print(" km/h");
  lcd.setCursor(12, 0);
  lcd.print(rpm_var); //Обороты
  lcd.print(" rpm");
  lcd.setCursor(0, 1);
  float cons = ecu.getInstantConsumption();
  lcd.print(cons); // л/час
  lcd.print(" L/h");
  lcd.setCursor(12, 1);
  lcd.print(benz_full_new);
  lcd.setCursor(0, 2);
  float cons1 = ecu.getInstantfFuel();
  lcd.print(cons1);
  lcd.print(" L/100");
  lcd.setCursor(12, 2);
  lcd.print(tmp_var);  //Температура
  lcd.setCursor(0, 3);
  lcd.print(odometr); // пройденный путь с заводки авто
  lcd.print(" km");
  lcd.setCursor(12, 3);
  lcd.print(benz_100); // средний расход на 100 км
  lcd.print(" L");
}

void Speed(void) {
  speed_var = ecu.getVss();
}

void Benz(void) {
  inj_time_var = ecu.getInj();
}

void Eeprom(void) {

}

void Tmp(void) {
  tmp_var = ecu.getEct();
}

void Rpm(void) {
  rpm_var = ecu.getRpm();
}

void DavlenVpuskKoll(void) {
  ecu.getMap();
}

void IntakeAirTemp(void) {
  ecu.getIat();
}

void Voltage(void) {
  voltage = ecu.getBattery();
}

void Uoz(void) {
  ecu.getInj();
}

void Pdz(void) {
  ecu.getTps();
}

 

Fiell
Offline
Зарегистрирован: 01.02.2018

Спасибо работает.

Сделал вроде правильно, если понял вас правильно)

b707
Offline
Зарегистрирован: 26.05.2017

Fiell пишет:

Спасибо работает.

Сделал вроде правильно, если понял вас правильно)

в строке 22 ошибка, вот это - неправильно:

benz_full = EEPROM.get(104, benz_full_new);

у метода EEPROM.get() нет возвращаетмого значения, поэтому приравнивать что-либо к нему бессмысленно. правильный код такой:

EEPROM.get(104, benz_full);
EEPROM.get(104, benz_full_new);

 

Fiell
Offline
Зарегистрирован: 01.02.2018

исправил 

теперь осталось сделать условие, при котором оно будет сохнатять в EEPROM данные, насколько знаю EEPROM не любит частой перезаписи. 

#include <LiquidCrystal_I2C.h>
#include <EEPROM.h>
#include "ecu.h"

LiquidCrystal_I2C lcd(0x27, 20, 4); // LiquidCrystal(rs, enable, d4, d5, d6, d7)

Ecu ecu;
unsigned long time_new, time_old, time_old_gurnal;
uint32_t t;
int  rpm_var, uoz_var, polozh_dross_zaslon, speed_var, inj_time_var, speed_var3, speed_var4, tmp_var, t2, t1;
float  time,  inj_time_full, odometr_add, inj_time_cycle, odometr_add3, odometr_add4, voltage, benz_full_eeprom, benz_full, benz_full_new, benz_add;
bool flagNulSpeed = true;

float odometr = 0;
float benz_100 = 0;
void setup()
{
  Serial.begin(38400);
  lcd.init();
  lcd.backlight();
  t = millis();
  EEPROM.get(104, benz_full);
  EEPROM.get(104, benz_full_new);
  EEPROM.get(200, odometr);

}

void loop()
{

  uint32_t new_t;
  uint16_t diff_t;
  inj_time_cycle = 0;
  int rpm_var = ecu.getRpm();
  int tmp_var = ecu.getEct();
  int voltage = ecu.getBattery();
  t = millis();
  {
    Speed(); // получить скорость

    if (time_old == 0) {
      time_old = millis();  // выполнится один раз при появлении оборотов
    }

    time_new = millis();   // время со старта программы в мс
    time = (double(time_new - time_old) / 1000.0); // прошло время с последнего расчета скорости, расхода  - в сек
    if (time > 10) {
      time = 0;
    }
    time_old = time_new;  // записать новое время для сравнения в следующем цикле

    if (speed_var > 0) {
      odometr_add = double((double(speed_var * 1000.0) / 3600.0) * time) / 1000.0;
      odometr = odometr + odometr_add; //обший пробег в км

    }
  }

  Benz(); // расход и время форсунок

  if (inj_time_var > 0) {
    new_t = millis();
    diff_t = new_t - t;
    inj_time_cycle = rpm_var / 120000.0 * 4.0 * (float)diff_t  * inj_time_var;//общее время форсунок за поездку
    inj_time_full = double(double(inj_time_cycle + inj_time_full)) ; //общее время форсунок за поездку (соовсем общее)
    benz_add = double(double((inj_time_full * 0.005416666666667) / 10.0)); //бензин за поездку
    benz_full_new = benz_full + benz_add;
    benz_100 = benz_full_new / odometr * 100;//средний расход на 100 км за поездк

  }


  EEPROM.put(104, benz_full_new);
  EEPROM.put(200, odometr);

  lcd.setCursor(0, 0);
  lcd.print(speed_var); // Скорость
  lcd.print(" km/h");
  lcd.setCursor(12, 0);
  lcd.print(rpm_var); //Обороты
  lcd.print(" rpm");
  lcd.setCursor(0, 1);
  float cons = ecu.getInstantConsumption();
  lcd.print(cons); // л/час
  lcd.print(" L/h");
  lcd.setCursor(12, 1);
  lcd.print(benz_full_new);
  lcd.setCursor(0, 2);
  float cons1 = ecu.getInstantfFuel();
  lcd.print(cons1);
  lcd.print(" L/100");
  lcd.setCursor(12, 2);
  lcd.print(tmp_var);  //Температура
  lcd.setCursor(0, 3);
  lcd.print(odometr); // пройденный путь с заводки авто
  lcd.print(" km");
  lcd.setCursor(12, 3);
  lcd.print(benz_100); // средний расход на 100 км
  lcd.print(" L");
}

void Speed(void) {
  speed_var = ecu.getVss();
}

void Benz(void) {
  inj_time_var = ecu.getInj();
}

void Eeprom(void) {

}

void Tmp(void) {
  tmp_var = ecu.getEct();
}

void Rpm(void) {
  rpm_var = ecu.getRpm();
}

void DavlenVpuskKoll(void) {
  ecu.getMap();
}

void IntakeAirTemp(void) {
  ecu.getIat();
}

void Voltage(void) {
  voltage = ecu.getBattery();
}

void Uoz(void) {
  ecu.getInj();
}

void Pdz(void) {
  ecu.getTps();
}

 

b707
Offline
Зарегистрирован: 26.05.2017

Общепринятых подхода два:

1) писать в ЕПРОМ, когда данные изменились более чем на определенное значение. Этот вариант совсем несложный, главное - определить разумную точность обновляемых данных. Например, показания одометра можно сохранять раз в километр, что дает вам гарантированный минимальный ресурс ЕЕПРОМ 100 000 км, а на практике в несколько раз больше. Для кол-ва топлива разумно писать данные 1 раз на каждый литр или 0.1 литра - при типичном расходе это даст такой же ресурс, как скилометрами.

2)пытаться определить момент окончания работы программы и писать только при выходе. В этом варианте обычно трудность составляет то, что нужно успеть записать ЕПРОМ, пока не пропало питание. Но так как у вас блок будет стоять на авто, где есть акамулятор, возможно этот вариант можно сделать проще.

Первый вариант проще, второй - эффективнее.

 

ЗЫ - еще раз внимательно посмотрел формулы - мне все же кажется, что кол-во и расход бензина в строках 62 -68 считается неверно. Проверьте еще раз. Например, точно ли разницу во времени надо считать по переменной t ? - это получается не время с прошлого цикла, а какое-то случайное значение