Go Down

Topic: Code time inaccuracy (Read 411 times) previous topic - next topic

Dragonsired1

Oct 10, 2017, 06:18 pm Last Edit: Oct 10, 2017, 06:30 pm by Dragonsired1
Hi, while working on my project I noticed, that even when using millis function code inside it is skipped every 3-4 seconds. I tried to delete many things and nothing helped. There's pH monitoring, temperature, water flow, distance measuring... etc. I'm using Arduino Mega
Code: [Select]
#include <NewPing.h>
#include <Wire.h>
#include <SPI.h>
#include <TimerFreeTone.h>
#include "SdFat.h"
#include "Sodaq_DS3231.h"
#include "HX711.h"
#include <OneWire.h>
#include <Nextion.h>

#define Ka 0.0039083
#define Kb -5.775E-07
#define proud 1679.5
#define spodni 3346.0
#define horni 6016.0
#define privod 0.4

const int pinCidlaDS = 2;
OneWire oneWireDS(pinCidlaDS);
SdFat SD;
#define SD_CS_PIN SS
File Data;
HX711 scale;
NewPing sonar(12, 12, 200);
float spodni_a, horni_a;
int volt, hladinavody = 6;
byte sensorInterrupt = 0;
byte sensorPin       = 2;
float calibrationFactor = 4.5;
volatile byte pulseCount;
float flowRate;
unsigned int flowMilliLitres;
unsigned long totalMilliLitres;
float celkem_litru;
unsigned long oldTime,oldTime1;
char buffer[100] = {0};
uint32_t number2 = 0;
 
NexButton b3 = NexButton(2, 8, "b3"); 
NexButton b4 = NexButton(2, 10, "b4"); 
NexSlider h0 = NexSlider(5, 14, "h0");

NexTouch *nex_listen_list[] =
{
  &b3,
  &b4,
  &h0,
  NULL
};
void b3PushCallback(void *ptr) 
{ digitalWrite(23, HIGH);
  digitalWrite(22, LOW);  //
  delay(70000);
  digitalWrite(22, HIGH);
}
void b4PushCallback(void *ptr) 
{
  if(digitalRead(23)== HIGH)
  {
    digitalWrite(23,LOW);
    }else{digitalWrite(23,HIGH);}
}
void h0PopCallback(void *ptr)  // Release event for slider
{
   
}
void setup()
{
  Serial.begin(115200);
  pinMode(5,OUTPUT);
  pinMode(sensorPin, INPUT);
  digitalWrite(sensorPin, HIGH);
  attachInterrupt(sensorInterrupt, pulseCounter, FALLING);
  Wire.begin();
  rtc.begin();
  SD.begin();
  Data = SD.open("Data.txt", FILE_WRITE);
 
  scale.begin(A1, A2, 32);
  b3.attachPush(b3PushCallback);
  b4.attachPush(b4PushCallback);
  h0.attachPop(h0PopCallback);
}

void loop() {
  DateTime now = rtc.now();
    scale.set_gain(32);
    float proud_a = scale.read_average(1) / 1000.0;
    int prumer = int(proud_a);
    float zbytek = proud_a - float(prumer);
    if (zbytek < 0.5) {proud_a = float(prumer);}
    else {proud_a = float(prumer) + 0.5;}
    float podil = proud_a / proud;
    scale.set_gain(64);
    spodni_a = spodni * podil;
    horni_a = horni * podil;
    prumer = int(scale.read_average(1) / 1000.0);
    float x = float(prumer);
    float odpor = (x - spodni_a) * (180.0 - 100.0) / (horni_a - spodni_a) + 100.0 ;
    float teplota  = 1.7 + (( sqrt(Kb * odpor - 100.0 * Kb + 25.0 * pow(Ka, 2)) - 5.0 * Ka) / (10.0 * Kb)) - privod;

  if ((millis() - oldTime) > 1000)   /// Zobrazení a uložení dat na SD kartu každou vteřinu
  {
    oldTime = millis();
    detachInterrupt(sensorInterrupt);
    flowRate = ((1000.0 / (millis() - oldTime)) * pulseCount) / calibrationFactor;
    flowMilliLitres = (flowRate / 60) * 1000;
    totalMilliLitres += flowMilliLitres;
    celkem_litru = totalMilliLitres / 1000;
    pulseCount = 0;
    attachInterrupt(sensorInterrupt, pulseCounter, FALLING);
    ///pH
    volt = analogRead(0);
    int measure = analogRead(0);
    double voltage = 4.9 / 1024.0 * measure;
    float Po = 7 + ((593 - measure) / 35.67);
    ///pH
    ///Hladina vody
    hladinavody = sonar.ping_cm();
    ///Hladina vody
    Serial.print("monitoring.pH.txt=\"  " + String(Po) + "\"");
    NextionEndCommand();
    Serial.print("monitoring.teplota.txt=\" " + String(teplota) + " 0C\"");
    NextionEndCommand();
    if (hladinavody < 10) {
      Serial.print("monitoring.t6.txt=\"  " + String(hladinavody) + ".00 cm\"");
    }
    else {
      Serial.print("monitoring.t6.txt=\" " + String(hladinavody) + ".00 cm\"");
    }
    NextionEndCommand();
    Serial.print("monitoring.kondu.txt=\"---.-- uS.m-1\"");
    NextionEndCommand();

    if (celkem_litru < 10) {
      Serial.print("monitoring.c_l.txt=\"  " + String(celkem_litru) + "  l\"");
    }
    else if (celkem_litru < 100) {
      Serial.print("monitoring.c_l.txt=\" " + String(celkem_litru) + "  l\"");
    }
    else {
      Serial.print("monitoring.c_l.txt=\"" + String(celkem_litru) + "  l\"");
    }
    NextionEndCommand();
    Serial.print("monitoring.prutok.txt=\"" + String(flowMilliLitres) + ".00 ml.s-1\"");
     NextionEndCommand();
    if (now.second() < 10 && now.minute() < 10 ) {
      Serial.print("Time.txt=\"" + String(now.date()) + "/" + String(now.month()) + "/" + String(now.year()) + " " + String(now.hour()) + ":0" + String(now.minute()) + ":0" + String(now.second()) + "\"");
    } else if (now.second() < 10 && now.minute() > 10)
    {
      Serial.print("Time.txt=\"" + String(now.date()) + "/" + String(now.month()) + "/" + String(now.year()) + " " + String(now.hour()) + ":" + String(now.minute()) + ":0" + String(now.second()) + "\"");
    }
    else if (now.second() > 10 && now.minute() < 10)
    {
      Serial.print("Time.txt=\"" + String(now.date()) + "/" + String(now.month()) + "/" + String(now.year()) + " " + String(now.hour()) + ":0" + String(now.minute()) + ":" + String(now.second()) + "\"");
    }
    else {
      Serial.print("Time.txt=\"" + String(now.date()) + "/" + String(now.month()) + "/" + String(now.year()) + " " + String(now.hour()) + ":" + String(now.minute()) + ":" + String(now.second()) + "\"");
    }
    NextionEndCommand();


  }
  if ( hladinavody <= 4)
  {
    TimerFreeTone(5, 3830, 500);
    digitalWrite(22, LOW);
  } else {
    digitalWrite(22, HIGH);
  }
 
  if ((millis() - oldTime1) > 10) 
  {
    oldTime1 = millis();
   nexLoop(nex_listen_list);
  }
 
}

void pulseCounter()
{
  pulseCount++;
}
void NextionEndCommand()
{
  Serial.write(0xff);
  Serial.write(0xff);
  Serial.write(0xff);
}


It's really long code, is it problem with so much commands sent via Serial??? Sorry for not translating it, but it should give you basic idea.
Thank you for any suggestions.

Robin2

when using millis function code inside it is skipped every 3-4 seconds.
I don't know what you mean by that?

What is being skipped?

You are using a lot of libraries. Is it possible that some calls to a library take so long that the time for the next interval has passed?

The problem is often in the code that you do not post.

When did the problem emerge during your development of the program? Can you go back to a version that was working faultlessly and then know that it was some of the subsequent code that caused the problem or perhaps made a latent problem visible?

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

Dragonsired1

Quote
What is being skipped?
Measuring and writing to Serial is skipped. There's data log from sd card where I originally saved all data
Code: [Select]

10/10/2017/17-36-11;pH:6.19;...
10/10/2017/17-36-12;pH:6.18;...
10/10/2017/17-36-14;pH:6.19;... (13 is missing)
10/10/2017/17-36-16;pH:6.18;...
10/10/2017/17-36-17;pH:6.19;...
10/10/2017/17-36-19;pH:6.16;...(18 is missing)
10/10/2017/17-36-21;pH:6.19;


Quote
When did the problem emerge during your development of the program?
Noticed after couple changes.

Quote
Can you go back to a version that was working faultlessly
Unfortunately I deleted previous file day ago ... and don't have any backup. I tried to delete several things - including HX711 library because even though there's no 'delay' in code it measures only once in a second. I checked library but never found anything useful.

Robin2

How often is the data being written to the Serial port?

Sorry to hear you have accidentally deleted the earlier versions. IMHO the only practical step is to strip out enough stuff so you get back to a working version and start over. And make sure to keep back up copies this time.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

Dragonsired1

#4
Oct 10, 2017, 09:28 pm Last Edit: Oct 10, 2017, 09:34 pm by Dragonsired1
Quote
How often is the data being written to the Serial port?
Every 1 second. That includes writing data to Serial port for Nextion display, then saving all data to SD card (was deleted from code). I don't understand where the problem is. And I included just necessary things in code, everything there is for some purpose and can't be deleted. It's even weird, it sometimes skips printing/saving every 3-4 seconds sometimes every 15-20 seconds. I tried to give it more time so I rised from 1 s to 2s and nothing changed. It's very important to save and print all data each second and it makes me frustrated I don't know where can problem be.

Coding Badly


There is this...

Code: [Select]

void b3PushCallback(void *ptr)
{ digitalWrite(23, HIGH);
  digitalWrite(22, LOW);
  delay(70000);  // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  digitalWrite(22, HIGH);
}



allanhurst

#6
Oct 10, 2017, 10:05 pm Last Edit: Oct 10, 2017, 10:24 pm by allanhurst
I've had a look at and measured such things  on a scope on a nano AT328 at 16MHz

1/ The digitalWrite() takes about 6uS as against a direct port write of 62.5nS. 100 times slower.
And if you want to change lines simultaneously, no good.

2/the millis() function updates it's count every 1.024mS and takes about 7uS to do it. It doesn't matter whether you use it or not. Hence there is a skip.

3/ The loop() uses about 7uS every time round to perform backgrouind tasks - embed a while(1) if you want to avoid this.

I'm sure there are bits I've missed

Overall  a very nice and easy environment to use, but has significant overheads.

Allan

Robin2

I don't understand where the problem is
I know that - otherwise you would not be asking for help.

And because you don't know where the problem is you have to go back to an early development stage of the program to get a working version from which to start building the rest of the project. You can't expect to develop a complex program like that with all of the parts right from the start.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

Dragonsired1

There is this...

Code: [Select]

void b3PushCallback(void *ptr)
{ digitalWrite(23, HIGH);
  digitalWrite(22, LOW);
  delay(70000);  // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  digitalWrite(22, HIGH);
}



This function is called only when Button on display is pressed...

Quote
Overall  a very nice and easy environment to use, but has significant overheads.
From your suggestions I sum up, there's no way to make it precisely every second? It worked before...

Quote
you have to go back
Ok so I should make that same code from scratch adding more and more things and when that problem occurs find out what makes this problem... Ok

Coding Badly

Ok so I should make that same code from scratch adding more and more things and when that problem occurs find out what makes this problem...
Or, comment out sections until the problem disappears.  Your code has user interface parts (beep, button handling, display) and "functional" parts.  A great place to start would be to comment out the optional user interface parts (like the beep).


MorganS

...or strip thing out one at a time until you get to the shotest version of the program which demonstrates the error. Then post that complete code here.
"The problem is in the code you didn't post."

olf2012

This is part of the problem:
Code: [Select]
if ((millis() - oldTime) > 1000)   /// Zobrazení a uložení dat na SD kartu každou vteřinu
  {
    oldTime = millis();

This will get you out of sync with the real time. If last time you checked (millis() - oldTime) was 998, then next time you check it will be maybe 1050. The next successful check will be at 2051 (in real time) at least, but most probably it will be at about 2080. Then the next match is at 3100 etc. Sooner or later one full real time second will be skipped. I hope you understand what I mean :)
Change to:
Code: [Select]
if ((millis() - oldTime) > 1000)   /// Zobrazení a uložení dat na SD kartu každou vteřinu
  {
    oldTime += 1000;

Coding Badly

Code: [Select]

if ((millis() - oldTime) >= 1000)   /// Zobrazení a uložení dat na SD kartu každou vteřinu


 ;)

olf2012

#13
Oct 10, 2017, 11:35 pm Last Edit: Oct 10, 2017, 11:41 pm by olf2012
Code: [Select]

if ((millis() - oldTime) >= 1000)   /// Zobrazení a uložení dat na SD kartu každou vteřinu


 ;)
This will not make a difference to the problem I described, will it?
[EDIT] It will! Thanks for correcting me  :)

Dragonsired1

Quote
Change to:
Code: [Select]
if ((millis() - oldTime) >= 1000)   /// Zobrazení a uložení dat na SD kartu každou vteřinu
  {
    oldTime += 1000;
I changed the code, results are same:
https://youtu.be/PU2x_tzO8JI

Even some parts of code are ignored. There's code for changing numbers from 1-9 to 01-09 and it didn't worked.

Go Up