Jump to content

Обнуляются millis и плывут значения переменных


LukaS_St
 Share

Recommended Posts

Всем привет. Столкнулся с такой проблемой: Пишу программу для устройства мониторинга оборотов двух валов используя датчик холла. Настроил прерывания,  перевод в RPM, все проверил, в .порт отправляются верные значения, и после настройки индикации столкнулся с проблемой неадекватного поведения переменных считающих millis, а после и индикации. В Arduino я не спец, Гляньте на код, может чем помогите. Заранее благодарен.

#include <EEPROM.h>
	#define CLOCK 13 //SH_CP
#define DATA 11  //DS
#define LATCH 10  //ST_CP
int numbers[5];
boolean ee = 0;
int mh;
int hh;
int et_mah;
int et_shl;
int ot_mah;
int ot_shl;
volatile  int rpm_mah = 0;
volatile  int rpm_shl = 0;
 int rpmmah_count = 0;
 int rpmshl_count = 0;
unsigned long lastmillis_mah = 0;
unsigned long lastmillis_shl = 0;
unsigned long lastmillis_show = 0;
unsigned char number[] =
{
  0b01111110, //0
  0b00110000, //1
  0b01101101, //2
  0b01111001, //3
  0b00110011, //4
  0b01011011, //5
  0b01011111, //6
  0b01110000, //7
  0b01111111, //8
  0b01111011, //9
  0b00000001, //-
  0b00000000  //тушим индикатор
};
	void setup() {
  Serial.begin(9600);
	  attachInterrupt(0, rpm_mahovik, FALLING);
  attachInterrupt(1, rpm_shluz, FALLING);
  pinMode(CLOCK, OUTPUT);
  pinMode(DATA, OUTPUT);
  pinMode(LATCH, OUTPUT);
	}
	void rpm_mahovik() { /* this code will be executed every time the interrupt 0 (pin2) gets low.*/
  rpmmah_count++;
}
void rpm_shluz() { /* this code will be executed every time the interrupt 0 (pin2) gets low.*/
  rpmshl_count++;
}
	// чтение
//int EEPROM_int_read(int addr) {
//  byte raw[2];
 // for (byte i = 0; i < 2; i++) raw[i] = EEPROM.read(addr + i);
 // int &num = (int&)raw;
//  return num;
//}
	// запись
//void EEPROM_int_write(int addr, int num) {
//  byte raw[2];
 // (int&)raw = num;
 // for (byte i = 0; i < 2; i++) EEPROM.write(addr + i, raw[i]);
//}
	void show () {
  int x;
	
  for (x = 5; x >= 0; x--) {
   Serial.print("x= "); Serial.println(x);
    //включаем LATCH (Начинаем общение)
    digitalWrite(LATCH, LOW);
    shiftOut(DATA, CLOCK, LSBFIRST, number[numbers[x]]);
    //выключаем LATCH
    digitalWrite(LATCH, HIGH);
    //отключаем LATCH (чтобы регистр не ждал данных)
    digitalWrite(LATCH, HIGH);
  }
	}
//void ee_write () {
 // EEPROM_int_write(0, mh);
//  EEPROM_int_write(2, hh);
//  EEPROM_int_write(4, et_mah);
//  EEPROM_int_write(6, et_shl);
//  EEPROM_int_write(8, ot_mah);
//  EEPROM_int_write(10, ot_shl);
//}
	void loop() {
//  if ((millis() <= 100) & (ee == 0)) {
  //  mh = EEPROM_int_read(0);
 //   hh = EEPROM_int_read(2);
//    et_mah = EEPROM_int_read(4);
 //   et_shl = EEPROM_int_read(6);
 //   ot_mah = EEPROM_int_read(8);
 //   ot_shl = EEPROM_int_read(10);
 //   ee = 1;
 // }
	  if (millis() - lastmillis_mah == 1000) {
    detachInterrupt(0);
    rpm_mah = rpmmah_count * 60;
    rpmmah_count = 0;
    lastmillis_mah = millis();
    attachInterrupt(0, rpm_mahovik, FALLING);
  }
	  if (millis() - lastmillis_shl == 5000) {
    detachInterrupt(1);
    rpm_shl = rpmshl_count * 12;
    rpmshl_count = 0;
    lastmillis_shl = millis();
    attachInterrupt(1, rpm_shluz, FALLING);
  }
  if (millis() - lastmillis_show == 1000) {
    numbers[0] = rpm_mah / 1000;
    numbers[1] = (rpm_mah % 1000) / 100;
    numbers[2] = ((rpm_mah % 1000) % 100) / 10;
    numbers[3] = ((rpm_mah % 1000) % 100) % 10;
    numbers[4] = rpm_shl / 10;
    numbers[5] = rpm_shl % 10;
    lastmillis_show = millis();
  show();
Serial.print("RPM mah= "); Serial.println (rpm_mah); 
Serial.print("RPM shl= "); Serial.println (rpm_shl);  
Serial.print("Show millis= "); Serial.println(lastmillis_show);
Serial.print("Show mah= "); Serial.println(lastmillis_mah);
Serial.print("Show shl= "); Serial.println(lastmillis_shl);
  }
}

123.png

Edited by LukaS_St
Link to comment
Share on other sites

Реклама: ООО ТД Промэлектроника, ИНН: 6659197470, Тел: 8 (800) 1000-321

Пересоздал проект, ввел почти тот же код, почти все заработало корректно, но индикация через некоторое время останавливается (хотя микроконтроллер на кнопки реагирует). На железе индикация пропадает после 17 секунды, а в протеусе после 104.

#include <EEPROM.h>
#include <Bounce2.h>
	Bounce knopka_m = Bounce();
Bounce knopka_mah_plus = Bounce();
Bounce knopka_mah_minus = Bounce();
Bounce knopka_shl_plus = Bounce();
Bounce knopka_shl_minus = Bounce();
	#define CLOCK 13 //SH_CP
#define DATA 11  //DS
#define LATCH 10  //ST_CP
unsigned long lastmillis_show = 0;
byte numbers[] = {0, 0, 0, 0, 0, 0};
volatile int rpmmah_count = 0;
volatile int rpmshl_count = 0;
boolean ee = 0;
byte menu = 0;
int mh = 1234;
int hh = 0;
int et_mah = 900;
int et_shl = 80;
int ot_mah = 30;
int ot_shl = 3;
int rpm_mah = 0;
int rpm_shl = 0;
unsigned long lastmillis_mah = 0;
unsigned long lastmillis_shl = 0;
	unsigned char number[] =
{
  0b01111110, //0
  0b00110000, //1
  0b01101101, //2
  0b01111001, //3
  0b00110011, //4
  0b01011011, //5
  0b01011111, //6
  0b01110000, //7
  0b01111111, //8
  0b01111011, //9
  0b00000001, //-
  0b00000000  //тушим индикатор
};
	// чтение
int EEPROM_int_read(int addr) {
  byte raw[2];
  for (byte i = 0; i < 2; i++) raw[i] = EEPROM.read(addr + i);
  int &num = (int&)raw;
  return num;
}
	// запись
void EEPROM_int_write(int addr, int num) {
  byte raw[2];
  (int&)raw = num;
  for (byte i = 0; i < 2; i++) EEPROM.write(addr + i, raw[i]);
}
	void ee_write () {
  EEPROM_int_write(0, mh);
  EEPROM_int_write(2, hh);
  EEPROM_int_write(4, et_mah);
  EEPROM_int_write(6, et_shl);
  EEPROM_int_write(8, ot_mah);
  EEPROM_int_write(10, ot_shl);
}
	void show() {
  int x;
  for (x = 5; x >= 0; x--) {
    //включаем LATCH (Начинаем общение)
    digitalWrite(LATCH, LOW);
    shiftOut(DATA, CLOCK, LSBFIRST, number[numbers[x]]);
    //отключаем LATCH (чтобы регистр не ждал данных)
    digitalWrite(LATCH, HIGH);
  }
}
	void rpm_mahovik() { /* this code will be executed every time the interrupt 0 (pin2) gets low.*/
  rpmmah_count++;
}
void rpm_shluz() { /* this code will be executed every time the interrupt 0 (pin2) gets low.*/
  rpmshl_count++;
}
	void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  attachInterrupt(0, rpm_mahovik, FALLING);
  attachInterrupt(1, rpm_shluz, FALLING);
	  pinMode(CLOCK, OUTPUT);
  pinMode(DATA, OUTPUT);
  pinMode(LATCH, OUTPUT);
  digitalWrite(LATCH, HIGH);
	  pinMode(19, INPUT_PULLUP);
  knopka_m.attach(19); // устанавливаем кнопку
  knopka_m.interval(5); // устанавливаем параметр stable interval = 5 мс
  pinMode(18, INPUT_PULLUP);
  knopka_mah_plus.attach(18); // устанавливаем кнопку
  knopka_mah_plus.interval(5); // устанавливаем параметр stable interval = 5 мс
  pinMode(17, INPUT_PULLUP);
  knopka_mah_minus.attach(17); // устанавливаем кнопку
  knopka_mah_minus.interval(5); // устанавливаем параметр stable interval = 5 мс
  pinMode(16, INPUT_PULLUP);
  knopka_shl_plus.attach(16); // устанавливаем кнопку
  knopka_shl_plus.interval(5); // устанавливаем параметр stable interval = 5 мс
  pinMode(15, INPUT_PULLUP);
  knopka_shl_minus.attach(15); // устанавливаем кнопку
  knopka_shl_minus.interval(5); // устанавливаем параметр stable interval = 5 мс
}
	void loop() {
  // put your main code here, to run repeatedly:
  if (EEPROM.read(0) == 0xFF) {
    ee_write ();
  }
	  if ((millis() <= 100) & (ee == 0)) {
    mh = EEPROM_int_read(0);
    hh = EEPROM_int_read(2);
    et_mah = EEPROM_int_read(4);
    et_shl = EEPROM_int_read(6);
    ot_mah = EEPROM_int_read(8);
    ot_shl = EEPROM_int_read(10);
    ee = 1;
  }
	  if (millis() - lastmillis_mah == 1000) {
    detachInterrupt(0);
    rpm_mah = rpmmah_count * 60;
    rpmmah_count = 0;
    lastmillis_mah = millis();
    attachInterrupt(0, rpm_mahovik, FALLING);
  }
	  if (millis() - lastmillis_shl == 5000) {
    detachInterrupt(1);
    rpm_shl = rpmshl_count * 12;
    rpmshl_count = 0;
    lastmillis_shl = millis();
    attachInterrupt(1, rpm_shluz, FALLING);
  }
	  if (millis() - lastmillis_show == 1000) {
    if (menu == 0) {
      numbers[0] = rpm_mah / 1000;
      numbers[1] = (rpm_mah % 1000) / 100;
      numbers[2] = ((rpm_mah % 1000) % 100) / 10;
      numbers[3] = ((rpm_mah % 1000) % 100) % 10;
      numbers[4] = rpm_shl / 10;
      numbers[5] = rpm_shl % 10;
    }
    if (menu == 1) {
      numbers[0] = mh / 1000;
      numbers[1] = (mh % 1000) / 100;
      numbers[2] = ((mh % 1000) % 100) / 10;
      numbers[3] = ((mh % 1000) % 100) % 10;
      numbers[4] = 11;
      numbers[5] = 11;
    }
    if (menu == 2) {
      numbers[0] = et_mah / 1000;
      numbers[1] = (et_mah % 1000) / 100;
      numbers[2] = ((et_mah % 1000) % 100) / 10;
      numbers[3] = ((et_mah % 1000) % 100) % 10;
      numbers[4] = et_shl / 10;
      numbers[5] = et_shl % 10;
    }
    if (menu == 3) {
      numbers[0] = ot_mah / 1000;
      numbers[1] = (ot_mah % 1000) / 100;
      numbers[2] = ((ot_mah % 1000) % 100) / 10;
      numbers[3] = ((ot_mah % 1000) % 100) % 10;
      numbers[4] = ot_shl / 10;
      numbers[5] = ot_shl % 10;
    }
    show();
    lastmillis_show = millis();
    Serial.println(lastmillis_show);
  }
  if (knopka_m.update() && knopka_m.read() == 0) {
    if (menu != 3) menu++;
    else {menu = 0; ee_write ();}
//  Serial.println ("Knopka");
  }
//////////////////////////////////////////////////////////////////
  if (knopka_mah_plus.update() && knopka_mah_plus.read() == 0) {
    if (menu == 2) {
      if (et_mah < 1000) et_mah = et_mah + 10;
    }
    if (menu == 3) {
      if (ot_mah < 100) ot_mah = ot_mah + 1;
    }
  }
  ////////////////////////////////////////////////////////////////////
  if (knopka_mah_minus.update() && knopka_mah_minus.read() == 0) {
    if (menu == 2) {
      if (et_mah > 800) et_mah = et_mah - 10;
    }
  }
  if (knopka_mah_minus.update() && knopka_mah_minus.read() == 0) {
    if (menu == 3) {
      if (ot_mah > 10) ot_mah = ot_mah - 1;
    }
  }
  /////////////////////////////////////////////////////////////////////
  //////////////////////////////////////////////////////////////////
  if (knopka_shl_plus.update() && knopka_shl_plus.read() == 0) {
    if (menu == 2) {
      if (et_shl < 70) et_shl = et_shl + 1;
    }
    if (menu == 3) {
      if (ot_shl < 20) ot_shl = ot_shl + 1;
    }
  }
  ////////////////////////////////////////////////////////////////////
  if (knopka_shl_minus.update() && knopka_shl_minus.read() == 0) {
    if (menu == 2) {
      if (et_shl > 30) et_shl = et_shl - 1;
    }
  }
  if (knopka_shl_minus.update() && knopka_shl_minus.read() == 0) {
    if (menu == 3) {
      if (ot_shl > 0) ot_shl = ot_shl - 1;
    }
}
}

123.png

Edited by LukaS_St
Link to comment
Share on other sites

20 минут назад, LukaS_St сказал:

if (millis() - lastmillis_mah == 1000) {     detachInterrupt(0);     rpm_mah = rpmmah_count * 60;

кто сказал что это условие будет выполнятся всегда?

Если бы мс инкрементировали в этом же цикле, такое условие допустимо

правильно писать

if (millis() - lastmillis_mah) >= 1000)

{

}

 

Edited by hasl
Link to comment
Share on other sites

Аккумуляторы INR21700 от EVE Energy со стандартной и увеличенной емкостью

В Компэл представлены аккумуляторы 21700 с емкостями 4000 мА⋅ч и 5000 мА⋅ч (INR21700-40P и INR21700-50E, соответственно). Аккумуляторы INR21700-50E характеризуются повышенной емкостью и предназначены для  устройств с длительным сроком службы. Для приложений, где требуется экстремальный ток разряда до 30 или 50 А, подойдет аккумулятор INR21700-40P. Аккумуляторы INR21700 предназначены для  электротранспорта, а также для промышленных и бытовых приложений. Подробнее>>

 

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

Пробовал и так писать. Из трех таких условий перестает только одно работать( Ликвидировал эту проблему объединив 2 части кода в одно условие, что привело к отсутствию  возможности регулировки частоты вывода информации на индикаторы.

Link to comment
Share on other sites

Широкий выбор электромеханических реле Hongfa на складе Компэл

КОМПЭЛ продолжает поддерживать и расширять список складских позиций Hongfa, представленных электромеханическими реле. Продукция компании активно применяется в таких областях, как промышленность, энергетика, бытовые приборы, автомобильная отрасль и специальная техника, требующая высокой надежности и на сегодняшний момент является первым претендентом для легкой замены электромеханических реле ушедших из РФ брендов.

Подробнее >>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

Join the conversation

You are posting as a guest. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...