Programming Button Nextion Display issue

Hello everyone,

I am developing a project that consists of a copper and silver coupon microbalance, a T&H sensor, an SD module, an RTC module and a Nextion enhanced display all driven by a Atmega2650. Currently I have all the sensors and devices working properly with the values being updated on the display and the SD card recording all the information on a .CSV file for post processing. Right now I want to start adding functionalities like for example erasing the SD card with a button in the Nextion. However, I tried adding a simple code to just enable High a pin on the arduino while the rest of the code is running and it doesn't work. I think this might be because when I press the button the code is busy counting the frequency of the crystals. How can I solve this issue if this is the case? Is there some type of interrupt that I can programme? It doesn't allow me to post the code since it is too long so here is the .ino.

test1.ino (11.8 KB)

you are already using interruptions (overflowCount should be volatile by the way), I've not checked the setting, but do you know how much pressure does it put on your system? (how often do you call the ISRs?)

What are you getting on Serial1 ?

  if (Serial1.available() > 0)
  {
    String Received = Serial1.readString();
    if (int(Received[0]) == 1)

are you sure you want to compare against the number 1? should that be the character '1' instead?

readString() includes also a timeout possibly, so it's not a a great function to use

using delay() and willing to have a responsive/low latency to user actions code is not compatible

void tempAndHumRead()                                        //SHT T&H sensor reading
{
  delay(2000);

==> don't use any delay() use millis() to decide when it's time to update the T° reading.

This would be a non blocking way to update the T° and log every two seconds and listen to the Serial port for the number 0 or 1 (again did you mean '0' and '1' ?)

void tempAndHumRead()                                        //SHT T&H sensor reading
{
  sht.readSample();
  t = sht.getTemperature();
  h = sht.getHumidity();
}

void loop() {
  static uint32_t lastReadChrono = -30000; // long time ago so that first call would trigger a read

  int received = Serial1.read(); // returns -1 if nothing to read
  if (received == 1)  digitalWrite(Led, HIGH);
  else if (received == 0) digitalWrite(Led, LOW);

  if (millis() - lastReadChrono > 2000) {
    float  frq = counter();
    sendNex(frq);
    tempAndHumRead();
    logValue();
    writeSDCard(frq);
    lastReadChrono = millis();
  }
}

PS:why do you declare stuff you don't use (and why are they Strings when const char* would do)?

String daysOfTheWeek[7] = { "Domingo", "Lunes", "Martes", "Miercoles", "Jueves", "Viernes", "Sabado" };
String monthsNames[12] = { "Enero", "Febrero", "Marzo", "Abril", "Mayo",  "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre" };

There is also no need to build a String before writing in the SD file, just print along

void writeSDCard(float frq) {                                // Function for saving the Temperature humidity and frequency to SD
  DateTime now = rtc.now();
  logFile = SD.open("datalog.csv", FILE_WRITE);
  if (logFile) {
    logFile.print(now.year()); logFile.write(';');
    logFile.print(now.month()); logFile.write(';');
    logFile.print(now.day()); logFile.write(';');
    logFile.print(now.hour()); logFile.write(';');
    logFile.print(now.minute()); logFile.write(';');
    logFile.print(now.second()); logFile.write(';');
    logFile.print(h * 100, 0); logFile.write(';');
    logFile.print(t * 100, 0); logFile.write(';');
    logFile.print(freq, 0); logFile.write(';');
    logfile.println();
    logFile.close();
  } else {
    Serial1.print(F("d3.txt=\"Error openig the file\""));
    Serial1.write(0xff);
    Serial1.write(0xff);
    Serial1.write(0xff);
  }
}

and then you can get rid of all the global variables that are useless

float h = 0.0f;
float t = 0.0f;
int currentYear = 0;
int currentMonth = 0;
int currentDay = 0;
int currentHour = 0;
int currentMinute = 0;
int currentSecond = 0;
unsigned long currentCount = 0;

and the misnamed logValue() function that was just reading the time

Wow! Thank you very much for all the corrections and recommendations, I will apply them to the code. The frequency counter code that I am using is taken from nick gammon's timers (https://www.gammon.com.au/timers) and I think that the interrupt is being triggered every 1ms. Knowing this, would it be better to place one microcontroller (atmega 328) that does the frequency counting and then sends the value to another controller (atmega2560) that collects all the values ( temperature, humidity and frequency) and does the interfacing with the Nextion display?

Actually looking at your code a bit more, you use the ISR only when you need to measure the frequency the rest of the time the ISRs are not used but you block everything for 500ms which can be an issue with reading the serial ports. What's the range of frequency you are looking at?

the more stuff you add , the less frequently you'll go check the frequency - so as long as the frequency you measure does not change rapidly you should be fine

The frequency range is between 5MHz and 6 MHz. The frequency actually does not change very fast so I could even do a reading every 20 to 30 seconds. However, I have to read 2 cristals so it is a total of 1 second. I guess there will still be a possibility of pressing a button just on that 1 second interval.

OK so it's a pretty high frequency, you might not need 500ms to have a relevant number of ticks
have you tried counting for way less time, like 10msstartCounting(10); that's enough to collect 50,000 ticks at 5Mhz...

what resolution do you need? may be 1ms would be good enough (between 5000 and 6000 ticks collected)

That sounds even better, I haven't thought of getting the sampling time down. I am looking for a resolution of 1Hz. I have also swapped the resonator of the mega for a 0.1ppm TCXO to get better accuracy.

1Hz is ambitious when running at 16Mhz even with 0.1ppm

Basically with your approach you need to differentiate between 5,999,999 and 6,000,000 ticks during 1 second. If you measure for less time, say 0.1 second then you get in the rounding error...

You actually probably need to measure for 10 seconds or more to get more precise or get a much faster arduino

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.