Помогите с кодом
- Войдите на сайт для отправки комментариев
Чт, 01/02/2018 - 23:02
Здравствуйте, помогите пожалуйста , уже 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();
}
У вас в коде так и есть - в случае одметра новое значение километража прибавляется с старому, а в случае с benz_full вы прочитанные из ЕПРОМ данные в программе нигде не используете, а вместо этого в строке 66 считаете banz_full с нуля.
ЗЫ На будущее - не создавайте тем с глупыми, ничего не значащими названиями - типа "Помогите новичку" или как у вас. Пишите конкретно - "Не заполняется массив", "Не обновляются данные из епром" и тд
Спасибо, буду исправляться)
если вас правильно понял то код должен быть такой?
#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(); }мне кажется, вы не вполне понимаете логику своей (?) программы. Я не очень хорошо понимаю, что вообще такое benz_full. но, по-моему, вы его снова считаете неправильно. Во-всяком случае, в этом скетче вы точно также, как и в первом, не используете данные, прочитанные из ЕПРОМ.
Уже голова кругом если честно , вообщем benz_full это количество спаленного топлива за время работы ардуино . Так вот я хочу сделать чтобы , оно при отключении питания сохранялось , а при включении ардуино , продолжала его . Просто как мне кажется , я с full_Benz делаю тоже самое , что и с odometr. Но одометр считается , а бензин нет.
строчки 66-68 попробуйте так переписать
Наверное так не получится мне нудно сохранить в eeprom именно количество топлива , то есть например benz_full = 1.0 при выключении ардуино оно его сохраНила в eeprom , а при включении достало его и начала считать дальше , 1.0 ,1.1 ,1.2 ....
нет, немного не так. Если я правильно понимаю ваши формулы - вот так надо
только комментарии неверные.
benz_add - это бензин не за всю поездку, а только со времени предыдущего расчета, а benz_100 - расход не за поездку, а за все время накопления данных
по-моему, мы это и делаем, что вас смущает?
Скажите для определенности - эти формулы ваши или вы их где-то в инете скопировали вместе с кодом? Вы их понимаете и можете обьяснить, что и как считается в формулах?
Нет формула Benz_full выводит кол-во литров топлива , которое авто спалило с момента включения ардуино. Т.е
inj_time_full - это сумарное время открытых форсунок с момента включения
0.005416666666667 - это производительность форсунки
При выводе формулы на экран показывает кол-во потраченного бензина с момента включения.
Код мой , на него уже месяц потратил , все работает , только с eeprom как-то тяжеловато.
Нужно сохранять benz_full и при включении продолжать его .
ок, но тогда придется ввести переменную benz_full_new
код:
По-моему, сейчас все строго так, как вы хотели.
В начале программы читаете из ЕЕПРОМ общий расход бензина в переменную benz_full , а в конце работы сохраняете новое значение из переменной benz_full_new
Вы гений ,спасибо , вроде разобрался. Завтра напишу результат , сейчас на работу ушел.
#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(); }Спасибо работает.
Сделал вроде правильно, если понял вас правильно)
Спасибо работает.
Сделал вроде правильно, если понял вас правильно)
в строке 22 ошибка, вот это - неправильно:
benz_full = EEPROM.get(104, benz_full_new);
у метода EEPROM.get() нет возвращаетмого значения, поэтому приравнивать что-либо к нему бессмысленно. правильный код такой:
исправил
теперь осталось сделать условие, при котором оно будет сохнатять в 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(); }Общепринятых подхода два:
1) писать в ЕПРОМ, когда данные изменились более чем на определенное значение. Этот вариант совсем несложный, главное - определить разумную точность обновляемых данных. Например, показания одометра можно сохранять раз в километр, что дает вам гарантированный минимальный ресурс ЕЕПРОМ 100 000 км, а на практике в несколько раз больше. Для кол-ва топлива разумно писать данные 1 раз на каждый литр или 0.1 литра - при типичном расходе это даст такой же ресурс, как скилометрами.
2)пытаться определить момент окончания работы программы и писать только при выходе. В этом варианте обычно трудность составляет то, что нужно успеть записать ЕПРОМ, пока не пропало питание. Но так как у вас блок будет стоять на авто, где есть акамулятор, возможно этот вариант можно сделать проще.
Первый вариант проще, второй - эффективнее.
ЗЫ - еще раз внимательно посмотрел формулы - мне все же кажется, что кол-во и расход бензина в строках 62 -68 считается неверно. Проверьте еще раз. Например, точно ли разницу во времени надо считать по переменной t ? - это получается не время с прошлого цикла, а какое-то случайное значение